Skip to content

Commit 0bf2617

Browse files
committed
Add ColumnsButton
1 parent 2d823bf commit 0bf2617

File tree

10 files changed

+574
-4
lines changed

10 files changed

+574
-4
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
"cmdk": "^1.1.1",
4242
"data-generator-retail": "^5.10.0",
4343
"date-fns": "^4.1.0",
44+
"diacritic": "^0.0.2",
4445
"echarts": "^5.6.0",
4546
"inflection": "^3.0.2",
4647
"lodash": "^4.17.21",

pnpm-lock.yaml

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

registry.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
"@tanstack/react-query",
4141
"class-variance-authority",
4242
"clsx",
43+
"diacritic",
4344
"inflection",
4445
"lodash",
4546
"lucide-react",
@@ -116,6 +117,10 @@
116117
"path": "src/components/admin/create-button.tsx",
117118
"type": "registry:component"
118119
},
120+
{
121+
"path": "src/components/admin/columns-button.tsx",
122+
"type": "registry:component"
123+
},
119124
{
120125
"path": "src/components/admin/data-table.tsx",
121126
"type": "registry:component"
@@ -140,6 +145,10 @@
140145
"path": "src/components/admin/export-button.tsx",
141146
"type": "registry:component"
142147
},
148+
{
149+
"path": "src/components/admin/field-toggle.tsx",
150+
"type": "registry:component"
151+
},
143152
{
144153
"path": "src/components/admin/form.tsx",
145154
"type": "registry:component"
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import * as React from "react";
2+
import { useTranslate, useResourceContext } from "ra-core";
3+
import { Columns } from "lucide-react";
4+
import * as PopoverPrimitive from "@radix-ui/react-popover";
5+
import { useIsMobile } from "@/hooks/use-mobile";
6+
import { Button } from "@/components/ui/button";
7+
import {
8+
Tooltip,
9+
TooltipContent,
10+
TooltipTrigger,
11+
} from "@/components/ui/tooltip";
12+
import { Popover, PopoverTrigger } from "@/components/ui/popover";
13+
import { cn } from "@/lib/utils";
14+
15+
/**
16+
* Renders a button that lets users show / hide columns in a DataTable
17+
*
18+
* @example
19+
* import { ColumnsButton, DataTable } from 'shadcn-admin-kit';
20+
*
21+
* const PostListActions = () => (
22+
* <TopToolbar>
23+
<ColumnsButton />
24+
<FilterButton />
25+
* </TopToolbar>
26+
* );
27+
*
28+
* const PostList = () => (
29+
* <List actions={<PostListActions />}>
30+
* <DataTable>
31+
* <DataTable.Col source="title" />
32+
* <DataTable.Col source="author" />
33+
...
34+
* </DataTable>
35+
* </List>
36+
* );
37+
*/
38+
export const ColumnsButton = (props: ColumnsButtonProps) => {
39+
const { className, ...rest } = props;
40+
const resource = useResourceContext(props);
41+
const storeKey = props.storeKey || `${resource}.datatable`;
42+
43+
const [open, setOpen] = React.useState(false);
44+
const isMobile = useIsMobile();
45+
const translate = useTranslate();
46+
47+
const title = translate("ra.action.select_columns", { _: "Columns" });
48+
49+
return (
50+
<span className={cn("inline-flex", className)}>
51+
<Popover open={open} onOpenChange={setOpen}>
52+
<PopoverTrigger asChild>
53+
{isMobile ? (
54+
<Tooltip>
55+
<TooltipTrigger asChild>
56+
<Button
57+
variant="ghost"
58+
size="icon"
59+
aria-label={title}
60+
{...rest}
61+
>
62+
<Columns className="size-4" />
63+
</Button>
64+
</TooltipTrigger>
65+
<TooltipContent>{title}</TooltipContent>
66+
</Tooltip>
67+
) : (
68+
<Button variant="outline" className="cursor-pointer" {...rest}>
69+
<Columns />
70+
{title}
71+
</Button>
72+
)}
73+
</PopoverTrigger>
74+
<PopoverPrimitive.Portal forceMount>
75+
<div className={open ? "block" : "hidden"}>
76+
<PopoverPrimitive.Content
77+
data-slot="popover-content"
78+
sideOffset={4}
79+
align="start"
80+
className="bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-72 origin-(--radix-popover-content-transform-origin) rounded-md border shadow-md outline-hidden p-0 min-w-[200px]"
81+
>
82+
<div id={`${storeKey}-columnsSelector`} className="p-2" />
83+
</PopoverPrimitive.Content>
84+
</div>
85+
</PopoverPrimitive.Portal>
86+
</Popover>
87+
</span>
88+
);
89+
};
90+
91+
export interface ColumnsButtonProps
92+
extends React.ComponentProps<typeof Button> {
93+
resource?: string;
94+
storeKey?: string;
95+
}

0 commit comments

Comments
 (0)