mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-08-04 14:57:42 +00:00
👐 a11y: Bump @ariakit/react, Improve a11y of Token Usage, Archived Chats, Reduce Table Layout Shifts (#13874)
Some checks are pending
Docker Dev Branch Images Build / build (Dockerfile, lc-dev, node) (push) Waiting to run
Docker Dev Branch Images Build / build (Dockerfile.multi, lc-dev-api, api-build) (push) Waiting to run
GitNexus Index / index (push) Waiting to run
GitNexus Index / post-index (push) Blocked by required conditions
Publish `@librechat/client` to NPM / pack (push) Waiting to run
Publish `@librechat/client` to NPM / publish-npm (push) Blocked by required conditions
Docker Dev Images Build / build (Dockerfile, librechat-dev, node) (push) Waiting to run
Docker Dev Images Build / build (Dockerfile.multi, librechat-dev-api, api-build) (push) Waiting to run
Sync Locize Translations & Create Translation PR / Sync Translation Keys with Locize (push) Waiting to run
Sync Locize Translations & Create Translation PR / Create Translation PR on Version Published (push) Blocked by required conditions
Sync Helm Chart Tags / Ignore non-main push (push) Waiting to run
Sync Helm Chart Tags / Sync chart tags (push) Waiting to run
Some checks are pending
Docker Dev Branch Images Build / build (Dockerfile, lc-dev, node) (push) Waiting to run
Docker Dev Branch Images Build / build (Dockerfile.multi, lc-dev-api, api-build) (push) Waiting to run
GitNexus Index / index (push) Waiting to run
GitNexus Index / post-index (push) Blocked by required conditions
Publish `@librechat/client` to NPM / pack (push) Waiting to run
Publish `@librechat/client` to NPM / publish-npm (push) Blocked by required conditions
Docker Dev Images Build / build (Dockerfile, librechat-dev, node) (push) Waiting to run
Docker Dev Images Build / build (Dockerfile.multi, librechat-dev-api, api-build) (push) Waiting to run
Sync Locize Translations & Create Translation PR / Sync Translation Keys with Locize (push) Waiting to run
Sync Locize Translations & Create Translation PR / Create Translation PR on Version Published (push) Blocked by required conditions
Sync Helm Chart Tags / Ignore non-main push (push) Waiting to run
Sync Helm Chart Tags / Sync chart tags (push) Waiting to run
* chore: Update `@ariakit/react` and `@ariakit/react-core` dependencies to v0.4.29 and v0.4.26 respectively, and add new `@ariakit/components`, `@ariakit/react-components`, `@ariakit/react-store`, and `@ariakit/react-utils` packages to package-lock.json and package.json files. * fix: restore keyboard navigation for Tools dropdown submenus Compose the Artifacts and MCP submenu triggers as a `MenuButton` that receives the parent `MenuItem`'s props/ref directly, instead of nesting a `MenuItem` inside the submenu's own provider and placing the ref on a wrapper div. This registers the focusable trigger with the parent menu store so arrow-key navigation reaches the items, which fully broke under Ariakit 0.4.29. * fix: Improve keyboard navigation for TokenUsageIndicator popover Refactor the TokenUsageIndicator component to enhance keyboard accessibility. The popover now maintains focus on the gauge trigger, ensuring that the Escape key closes the popover without shifting focus to the non-interactive panel. Additionally, the autoFocusOnShow property is set to false to prevent unwanted focus behavior when the popover is displayed. * fix: Stabilize focus and layout shift in Archived Chats dialog Anchor dialog focus to the content element so rapid tabbing during the virtualized table's loading state no longer escapes to the page's top focus guard, and stabilize the columns memo to keep the focus trap intact. Reserve a fixed height and stable scrollbar gutter, and drop the redundant nested scroll wrapper in the shared DataTable to eliminate load-time layout shift. * fix: Add stable scrollbar gutter to SharedLinks DataTable Enhance the layout stability of the SharedLinks component by adding a "scrollbar-gutter-stable" class to the DataTable. This change aims to prevent layout shifts during loading, improving the overall user experience. * fix: Enhance keyboard accessibility and focus management in TokenUsageIndicator Refactor the TokenUsageIndicator component to improve keyboard navigation and focus behavior. Introduced a useRef hook for the disclosure button to ensure focus remains on the gauge trigger when the popover is opened. Updated the popover's finalFocus property to return focus to the trigger on close, enhancing the overall user experience for keyboard users.
This commit is contained in:
parent
1505fd5262
commit
465cb6e394
10 changed files with 184 additions and 86 deletions
|
|
@ -29,8 +29,8 @@
|
|||
},
|
||||
"homepage": "https://librechat.ai",
|
||||
"dependencies": {
|
||||
"@ariakit/react": "^0.4.15",
|
||||
"@ariakit/react-core": "^0.4.17",
|
||||
"@ariakit/react": "^0.4.29",
|
||||
"@ariakit/react-core": "^0.4.26",
|
||||
"@codesandbox/sandpack-react": "^2.19.10",
|
||||
"@dicebear/collection": "^9.4.1",
|
||||
"@dicebear/core": "^9.4.1",
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
import React from 'react';
|
||||
import * as Ariakit from '@ariakit/react';
|
||||
import { PinIcon } from '@librechat/client';
|
||||
import { ChevronRight, WandSparkles } from 'lucide-react';
|
||||
import { ArtifactModes } from 'librechat-data-provider';
|
||||
import { ChevronRight, WandSparkles } from 'lucide-react';
|
||||
import { useLocalize } from '~/hooks';
|
||||
import { cn } from '~/utils';
|
||||
|
||||
interface ArtifactsSubMenuProps {
|
||||
interface ArtifactsSubMenuProps extends React.HTMLAttributes<HTMLButtonElement> {
|
||||
isArtifactsPinned: boolean;
|
||||
setIsArtifactsPinned: (value: boolean) => void;
|
||||
artifactsMode: string;
|
||||
|
|
@ -15,7 +15,7 @@ interface ArtifactsSubMenuProps {
|
|||
handleCustomToggle: () => void;
|
||||
}
|
||||
|
||||
const ArtifactsSubMenu = React.forwardRef<HTMLDivElement, ArtifactsSubMenuProps>(
|
||||
const ArtifactsSubMenu = React.forwardRef<HTMLButtonElement, ArtifactsSubMenuProps>(
|
||||
(
|
||||
{
|
||||
isArtifactsPinned,
|
||||
|
|
@ -24,6 +24,7 @@ const ArtifactsSubMenu = React.forwardRef<HTMLDivElement, ArtifactsSubMenuProps>
|
|||
handleArtifactsToggle,
|
||||
handleShadcnToggle,
|
||||
handleCustomToggle,
|
||||
className,
|
||||
...props
|
||||
},
|
||||
ref,
|
||||
|
|
@ -41,25 +42,24 @@ const ArtifactsSubMenu = React.forwardRef<HTMLDivElement, ArtifactsSubMenuProps>
|
|||
const isCustomEnabled = artifactsMode === ArtifactModes.CUSTOM;
|
||||
|
||||
return (
|
||||
<div ref={ref}>
|
||||
<>
|
||||
<Ariakit.MenuProvider store={menuStore}>
|
||||
<Ariakit.MenuItem
|
||||
<Ariakit.MenuButton
|
||||
ref={ref}
|
||||
{...props}
|
||||
hideOnClick={false}
|
||||
render={
|
||||
<Ariakit.MenuButton
|
||||
onClick={(e: React.MouseEvent<HTMLButtonElement>) => {
|
||||
e.stopPropagation();
|
||||
handleArtifactsToggle();
|
||||
}}
|
||||
onMouseEnter={() => {
|
||||
if (isEnabled) {
|
||||
menuStore.show();
|
||||
}
|
||||
}}
|
||||
className="flex w-full cursor-pointer items-center justify-between rounded-lg p-2 hover:bg-surface-hover"
|
||||
/>
|
||||
}
|
||||
onClick={(e: React.MouseEvent<HTMLButtonElement>) => {
|
||||
e.stopPropagation();
|
||||
handleArtifactsToggle();
|
||||
}}
|
||||
onMouseEnter={() => {
|
||||
if (isEnabled) {
|
||||
menuStore.show();
|
||||
}
|
||||
}}
|
||||
className={cn(
|
||||
'flex w-full cursor-pointer items-center justify-between rounded-lg p-2 hover:bg-surface-hover',
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
<WandSparkles className="icon-md" aria-hidden="true" />
|
||||
|
|
@ -83,7 +83,7 @@ const ArtifactsSubMenu = React.forwardRef<HTMLDivElement, ArtifactsSubMenuProps>
|
|||
<PinIcon unpin={isArtifactsPinned} />
|
||||
</div>
|
||||
</button>
|
||||
</Ariakit.MenuItem>
|
||||
</Ariakit.MenuButton>
|
||||
|
||||
{isEnabled && (
|
||||
<Ariakit.Menu
|
||||
|
|
@ -144,7 +144,7 @@ const ArtifactsSubMenu = React.forwardRef<HTMLDivElement, ArtifactsSubMenuProps>
|
|||
</Ariakit.Menu>
|
||||
)}
|
||||
</Ariakit.MenuProvider>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -8,12 +8,12 @@ import { useBadgeRowContext } from '~/Providers';
|
|||
import { useLocalize } from '~/hooks';
|
||||
import { cn } from '~/utils';
|
||||
|
||||
interface MCPSubMenuProps {
|
||||
interface MCPSubMenuProps extends React.HTMLAttributes<HTMLButtonElement> {
|
||||
placeholder?: string;
|
||||
}
|
||||
|
||||
const MCPSubMenu = React.forwardRef<HTMLDivElement, MCPSubMenuProps>(
|
||||
({ placeholder, ...props }, ref) => {
|
||||
const MCPSubMenu = React.forwardRef<HTMLButtonElement, MCPSubMenuProps>(
|
||||
({ placeholder, className, ...props }, ref) => {
|
||||
const localize = useLocalize();
|
||||
const context = useBadgeRowContext();
|
||||
const { storageContextKey, mcpServerManager } = context ?? {};
|
||||
|
|
@ -48,20 +48,19 @@ const MCPSubMenu = React.forwardRef<HTMLDivElement, MCPSubMenuProps>(
|
|||
const configDialogProps = getConfigDialogProps();
|
||||
|
||||
return (
|
||||
<div ref={ref}>
|
||||
<>
|
||||
<Ariakit.MenuProvider store={menuStore}>
|
||||
<Ariakit.MenuItem
|
||||
<Ariakit.MenuButton
|
||||
ref={ref}
|
||||
{...props}
|
||||
hideOnClick={false}
|
||||
render={
|
||||
<Ariakit.MenuButton
|
||||
onClick={(e: React.MouseEvent<HTMLButtonElement>) => {
|
||||
e.stopPropagation();
|
||||
menuStore.toggle();
|
||||
}}
|
||||
className="flex w-full cursor-pointer items-center justify-between rounded-lg p-2 hover:bg-surface-hover"
|
||||
/>
|
||||
}
|
||||
onClick={(e: React.MouseEvent<HTMLButtonElement>) => {
|
||||
e.stopPropagation();
|
||||
menuStore.toggle();
|
||||
}}
|
||||
className={cn(
|
||||
'flex w-full cursor-pointer items-center justify-between rounded-lg p-2 hover:bg-surface-hover',
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
<MCPIcon className="h-5 w-5 flex-shrink-0 text-text-primary" aria-hidden="true" />
|
||||
|
|
@ -85,7 +84,7 @@ const MCPSubMenu = React.forwardRef<HTMLDivElement, MCPSubMenuProps>(
|
|||
<PinIcon unpin={isPinned} />
|
||||
</div>
|
||||
</button>
|
||||
</Ariakit.MenuItem>
|
||||
</Ariakit.MenuButton>
|
||||
|
||||
<Ariakit.Menu
|
||||
portal={true}
|
||||
|
|
@ -114,7 +113,7 @@ const MCPSubMenu = React.forwardRef<HTMLDivElement, MCPSubMenuProps>(
|
|||
{configDialogProps && (
|
||||
<MCPConfigDialog {...configDialogProps} storageContextKey={storageContextKey} />
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { memo } from 'react';
|
||||
import { memo, useRef } from 'react';
|
||||
import * as Ariakit from '@ariakit/react';
|
||||
import { TooltipAnchor } from '@librechat/client';
|
||||
import type { TConversation } from 'librechat-data-provider';
|
||||
|
|
@ -29,6 +29,7 @@ function TokenUsageIndicator({
|
|||
const localize = useLocalize();
|
||||
const view = useTokenUsage({ index, conversation, isSubmitting });
|
||||
const popover = Ariakit.usePopoverStore({ placement: 'top' });
|
||||
const disclosureRef = useRef<HTMLButtonElement>(null);
|
||||
|
||||
/** Hide until the branch has data — keeps a fresh, message-less chat clean and
|
||||
* lets the indicator animate into view once the first tokens land. */
|
||||
|
|
@ -64,6 +65,7 @@ function TokenUsageIndicator({
|
|||
side="top"
|
||||
render={
|
||||
<Ariakit.PopoverDisclosure
|
||||
ref={disclosureRef}
|
||||
store={popover}
|
||||
type="button"
|
||||
data-testid="token-usage"
|
||||
|
|
@ -88,11 +90,17 @@ function TokenUsageIndicator({
|
|||
</Ariakit.PopoverDisclosure>
|
||||
}
|
||||
/>
|
||||
{/* Focus the labelled dialog on open so screen readers enter and announce
|
||||
the breakdown, and so focus stays contained instead of falling back to
|
||||
the body (which the composer's global focus logic would steal). The
|
||||
visible ring is suppressed via focus:outline-none, and finalFocus
|
||||
returns focus to the gauge trigger on close. */}
|
||||
<Ariakit.Popover
|
||||
store={popover}
|
||||
gutter={8}
|
||||
portal
|
||||
unmountOnHide
|
||||
finalFocus={disclosureRef}
|
||||
aria-label={localize('com_ui_context_usage')}
|
||||
className="z-[200] rounded-xl border border-border-medium bg-surface-secondary p-3 shadow-lg focus:outline-none"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -332,6 +332,7 @@ export default function SharedLinks() {
|
|||
<DataTable
|
||||
columns={columns}
|
||||
data={allLinks}
|
||||
className="scrollbar-gutter-stable"
|
||||
onDelete={handleDelete}
|
||||
filterColumn="title"
|
||||
hasNextPage={hasNextPage}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { useRef } from 'react';
|
||||
import { OGDialog, OGDialogContent, OGDialogHeader, OGDialogTitle } from '@librechat/client';
|
||||
import type { RefObject } from 'react';
|
||||
import ArchivedChatsTable from './ArchivedChatsTable';
|
||||
|
|
@ -13,12 +14,24 @@ export function ArchivedChatsModal({
|
|||
triggerRef?: RefObject<HTMLButtonElement | HTMLDivElement | null>;
|
||||
}) {
|
||||
const localize = useLocalize();
|
||||
const contentRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
/** The virtualized table has no stable focusable on mount, so Radix's default
|
||||
* autofocus lands on a row that the virtualizer tears out, dropping focus to
|
||||
* the page's top focus guard; anchor focus to the dialog content instead. */
|
||||
const handleOpenAutoFocus = (event: Event) => {
|
||||
event.preventDefault();
|
||||
contentRef.current?.focus();
|
||||
};
|
||||
|
||||
return (
|
||||
<OGDialog open={open} onOpenChange={onOpenChange} triggerRef={triggerRef}>
|
||||
<OGDialogContent
|
||||
ref={contentRef}
|
||||
tabIndex={-1}
|
||||
onOpenAutoFocus={handleOpenAutoFocus}
|
||||
title={localize('com_nav_archived_chats')}
|
||||
className="w-11/12 max-w-[1000px] bg-background text-text-primary shadow-2xl"
|
||||
className="w-11/12 max-w-[1000px] bg-background text-text-primary shadow-2xl focus:outline-none"
|
||||
>
|
||||
<OGDialogHeader>
|
||||
<OGDialogTitle>{localize('com_nav_archived_chats')}</OGDialogTitle>
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ export default function ArchivedChatsTable({
|
|||
},
|
||||
});
|
||||
|
||||
const unarchiveMutation = useArchiveConvoMutation({
|
||||
const { mutate: unarchiveConversation, isLoading: isUnarchiving } = useArchiveConvoMutation({
|
||||
onSuccess: async () => {
|
||||
await refetch();
|
||||
},
|
||||
|
|
@ -253,20 +253,16 @@ export default function ArchivedChatsTable({
|
|||
variant="ghost"
|
||||
className="h-8 w-8 p-0 hover:bg-surface-hover"
|
||||
onClick={() =>
|
||||
unarchiveMutation.mutate({
|
||||
unarchiveConversation({
|
||||
conversationId: conversation.conversationId,
|
||||
isArchived: false,
|
||||
})
|
||||
}
|
||||
title={localize('com_ui_unarchive_conversation')}
|
||||
aria-label={localize('com_ui_unarchive_conversation')}
|
||||
disabled={unarchiveMutation.isLoading}
|
||||
disabled={isUnarchiving}
|
||||
>
|
||||
{unarchiveMutation.isLoading ? (
|
||||
<Spinner />
|
||||
) : (
|
||||
<ArchiveRestore className="size-4" />
|
||||
)}
|
||||
{isUnarchiving ? <Spinner /> : <ArchiveRestore className="size-4" />}
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
|
|
@ -296,24 +292,29 @@ export default function ArchivedChatsTable({
|
|||
},
|
||||
},
|
||||
],
|
||||
[isSmallScreen, localize, unarchiveMutation],
|
||||
[isSmallScreen, localize, unarchiveConversation, isUnarchiving],
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<DataTable
|
||||
columns={columns}
|
||||
data={allConversations}
|
||||
filterColumn="title"
|
||||
onFilterChange={debouncedFilterChange}
|
||||
filterValue={queryParams.search}
|
||||
fetchNextPage={handleFetchNextPage}
|
||||
hasNextPage={hasNextPage}
|
||||
isFetchingNextPage={isFetchingNextPage}
|
||||
isLoading={isLoading}
|
||||
showCheckboxes={false}
|
||||
enableSearch={searchState.enabled === true}
|
||||
/>
|
||||
{/* Fixed height keeps the loading (skeleton) and loaded states the same
|
||||
size, so the virtualized table can't reflow the dialog on load. */}
|
||||
<div className="h-[60vh]">
|
||||
<DataTable
|
||||
columns={columns}
|
||||
data={allConversations}
|
||||
className="scrollbar-gutter-stable"
|
||||
filterColumn="title"
|
||||
onFilterChange={debouncedFilterChange}
|
||||
filterValue={queryParams.search}
|
||||
fetchNextPage={handleFetchNextPage}
|
||||
hasNextPage={hasNextPage}
|
||||
isFetchingNextPage={isFetchingNextPage}
|
||||
isLoading={isLoading}
|
||||
showCheckboxes={false}
|
||||
enableSearch={searchState.enabled === true}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<OGDialog open={isDeleteOpen} onOpenChange={onOpenChange}>
|
||||
<OGDialogContent
|
||||
|
|
|
|||
109
package-lock.json
generated
109
package-lock.json
generated
|
|
@ -413,8 +413,8 @@
|
|||
"version": "v0.8.7-rc1",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@ariakit/react": "^0.4.15",
|
||||
"@ariakit/react-core": "^0.4.17",
|
||||
"@ariakit/react": "^0.4.29",
|
||||
"@ariakit/react-core": "^0.4.26",
|
||||
"@codesandbox/sandpack-react": "^2.19.10",
|
||||
"@dicebear/collection": "^9.4.1",
|
||||
"@dicebear/core": "^9.4.1",
|
||||
|
|
@ -762,19 +762,30 @@
|
|||
"ajv": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@ariakit/components": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@ariakit/components/-/components-0.1.2.tgz",
|
||||
"integrity": "sha512-tvh2P0x1cJnoPXnmDEJwdRk3z7x6cTB8ArctcZdAUXlRg9tuwW/rJoBFJMzD5qMI9CDDlQ3Zctx58HvENw4BYw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@ariakit/store": "0.1.2",
|
||||
"@ariakit/utils": "0.1.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@ariakit/core": {
|
||||
"version": "0.4.15",
|
||||
"resolved": "https://registry.npmjs.org/@ariakit/core/-/core-0.4.15.tgz",
|
||||
"integrity": "sha512-vvxmZvkNhiisKM+Y1TbGMUfVVchV/sWu9F0xw0RYADXcimWPK31dd9JnIZs/OQ5pwAryAHmERHwuGQVESkSjwQ==",
|
||||
"version": "0.4.20",
|
||||
"resolved": "https://registry.npmjs.org/@ariakit/core/-/core-0.4.20.tgz",
|
||||
"integrity": "sha512-DJbUnui0fM+2ZgiWLOMuFOmlWSJDNV3f6tqghIYRTWEm51TN/LoU6uM8og6/g7Nrwl4Uo5l8AoQT9Kkr/i/uRg==",
|
||||
"deprecated": "This package has been split into smaller packages. Use @ariakit/components, @ariakit/store, or @ariakit/utils depending on the APIs you need.",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@ariakit/react": {
|
||||
"version": "0.4.17",
|
||||
"resolved": "https://registry.npmjs.org/@ariakit/react/-/react-0.4.17.tgz",
|
||||
"integrity": "sha512-HQaIboE2axtlncJz1hRTaiQfJ1GGjhdtNcAnPwdjvl2RybfmlHowIB+HTVBp36LzroKPs/M4hPCxk7XTaqRZGg==",
|
||||
"version": "0.4.29",
|
||||
"resolved": "https://registry.npmjs.org/@ariakit/react/-/react-0.4.29.tgz",
|
||||
"integrity": "sha512-SLXlsddWHSwfUol4Yi0zULlalNWjzWjpS3zg7B7aaPd64saONQ5ktWf9KMxqBklcpjMLeF2dB9BAHAvpPVdCIQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@ariakit/react-core": "0.4.17"
|
||||
"@ariakit/react-components": "0.1.2"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
|
|
@ -785,21 +796,83 @@
|
|||
"react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@ariakit/react-core": {
|
||||
"version": "0.4.17",
|
||||
"resolved": "https://registry.npmjs.org/@ariakit/react-core/-/react-core-0.4.17.tgz",
|
||||
"integrity": "sha512-kFF6n+gC/5CRQIyaMTFoBPio2xUe0k9rZhMNdUobWRmc/twfeLVkODx+8UVYaNyKilTge8G0JFqwvFKku/jKEw==",
|
||||
"node_modules/@ariakit/react-components": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@ariakit/react-components/-/react-components-0.1.2.tgz",
|
||||
"integrity": "sha512-SM+SPMAVlOZmGAfWNBza+0k9y4mkA5/dJhDoOyhE96cbNARy665uLdwowSJl1JGuFfcZzuzAwGon7f/rYeyfkQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@ariakit/core": "0.4.15",
|
||||
"@floating-ui/dom": "^1.0.0",
|
||||
"use-sync-external-store": "^1.2.0"
|
||||
"@ariakit/components": "0.1.2",
|
||||
"@ariakit/react-store": "0.1.2",
|
||||
"@ariakit/react-utils": "0.1.2",
|
||||
"@ariakit/store": "0.1.2",
|
||||
"@ariakit/utils": "0.1.2",
|
||||
"@floating-ui/dom": "^1.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^17.0.0 || ^18.0.0 || ^19.0.0",
|
||||
"react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@ariakit/react-core": {
|
||||
"version": "0.4.26",
|
||||
"resolved": "https://registry.npmjs.org/@ariakit/react-core/-/react-core-0.4.26.tgz",
|
||||
"integrity": "sha512-/Peh1KiVpjj79nCJIa6lEdzSTT9P9FZoy+CxByIFKL3YKdlXmDIIhS1E/tAqKbDq4ODVdynnqmrIDxE5wCoZYw==",
|
||||
"deprecated": "This package has been split into smaller packages. Use @ariakit/react-components or @ariakit/react-utils depending on the APIs you need.",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@ariakit/core": "0.4.20",
|
||||
"@floating-ui/dom": "^1.0.0",
|
||||
"use-sync-external-store": "^1.6.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^17.0.0 || ^18.0.0 || ^19.0.0",
|
||||
"react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@ariakit/react-store": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@ariakit/react-store/-/react-store-0.1.2.tgz",
|
||||
"integrity": "sha512-1r1Gn0tqhnOS0LFvHNGzn5/8C5aOANO5vb0Gxh94oR/be4zwCSE2zfQjOjRfpL+BBDhOcProME2+G6UslEJxbg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@ariakit/react-utils": "0.1.2",
|
||||
"@ariakit/store": "0.1.2",
|
||||
"@ariakit/utils": "0.1.2",
|
||||
"use-sync-external-store": "^1.6.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@ariakit/react-utils": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@ariakit/react-utils/-/react-utils-0.1.2.tgz",
|
||||
"integrity": "sha512-Rnl6D1542Mqu80xK++oUv1JXS0PtNmKXd9nkdud5nyvySiBDTrmPqRW44/D+5GbuZrboreQuY3tPYwKL7a7onQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@ariakit/store": "0.1.2",
|
||||
"@ariakit/utils": "0.1.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@ariakit/store": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@ariakit/store/-/store-0.1.2.tgz",
|
||||
"integrity": "sha512-SS7bV4+a+1q9M9i0WV6DD4P/ypRKlCvII8soo2UMe1yuaxZA/Fc0htHe+EZwjJ6TMLjHfHh2TDSnXyrjC7QImA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@ariakit/utils": "0.1.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@ariakit/utils": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@ariakit/utils/-/utils-0.1.2.tgz",
|
||||
"integrity": "sha512-lBJhtBWpKjIck/9i7G8cahvaUgLsyGklI/Pjv+VtY9KTzyuzX5GpRbbLKMS/e1qLnFPS4C3CybYB70b1bVcAkw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@asamuzakjp/css-color": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-3.2.0.tgz",
|
||||
|
|
@ -43076,8 +43149,8 @@
|
|||
"typescript": "^5.9.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ariakit/react": "^0.4.16",
|
||||
"@ariakit/react-core": "^0.4.17",
|
||||
"@ariakit/react": "^0.4.29",
|
||||
"@ariakit/react-core": "^0.4.26",
|
||||
"@dicebear/collection": "^9.4.1",
|
||||
"@dicebear/core": "^9.4.1",
|
||||
"@headlessui/react": "^2.1.2",
|
||||
|
|
|
|||
|
|
@ -36,8 +36,8 @@
|
|||
"dev": "tsdown --watch"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ariakit/react": "^0.4.16",
|
||||
"@ariakit/react-core": "^0.4.17",
|
||||
"@ariakit/react": "^0.4.29",
|
||||
"@ariakit/react-core": "^0.4.26",
|
||||
"@dicebear/collection": "^9.4.1",
|
||||
"@dicebear/core": "^9.4.1",
|
||||
"@headlessui/react": "^2.1.2",
|
||||
|
|
|
|||
|
|
@ -435,7 +435,10 @@ export default function DataTable<TData, TValue>({
|
|||
className,
|
||||
)}
|
||||
>
|
||||
<Table className="w-full min-w-[300px] table-fixed border-separate border-spacing-0">
|
||||
<Table
|
||||
unwrapped
|
||||
className="w-full min-w-[300px] table-fixed border-separate border-spacing-0"
|
||||
>
|
||||
<TableHeader className="sticky top-0 z-50 bg-surface-secondary">
|
||||
{table.getHeaderGroups().map((headerGroup) => (
|
||||
<TableRow key={headerGroup.id} className="border-b border-border-light">
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue