├── .eslintrc ├── .gitignore ├── .prettierrc ├── README.md ├── app ├── (guest) │ ├── layout.tsx │ ├── login │ │ └── page.tsx │ ├── pages │ │ └── error │ │ │ ├── 404 │ │ │ └── page.tsx │ │ │ └── 500 │ │ │ └── page.tsx │ └── register │ │ └── page.tsx ├── dashboard │ ├── default │ │ ├── cards │ │ │ ├── chat.tsx │ │ │ ├── metric.tsx │ │ │ ├── payment-method.tsx │ │ │ ├── payment.tsx │ │ │ ├── subscriptions.tsx │ │ │ ├── theme-members.tsx │ │ │ └── total-revenue.tsx │ │ └── page.tsx │ ├── error.tsx │ ├── layout.tsx │ └── pages │ │ ├── settings │ │ ├── layout.tsx │ │ ├── page.tsx │ │ ├── profile-form.tsx │ │ └── sidebar-nav.tsx │ │ └── users │ │ ├── data-table.tsx │ │ ├── data.json │ │ └── page.tsx ├── favicon.ico ├── globals.scss └── layout.tsx ├── components.json ├── components ├── anchor.tsx ├── card-action-menus.tsx ├── date-range-picker.tsx ├── icon.tsx ├── icons.tsx ├── layout │ ├── header.tsx │ ├── logo.tsx │ ├── search.tsx │ └── sidebar.tsx ├── main-layout.tsx ├── providers.tsx ├── theme-provider.tsx ├── ui │ ├── accordion.tsx │ ├── avatar.tsx │ ├── badge.tsx │ ├── breadcrumb.tsx │ ├── button.tsx │ ├── calendar.tsx │ ├── card.tsx │ ├── chart.tsx │ ├── checkbox.tsx │ ├── collapsible.tsx │ ├── command.tsx │ ├── dialog.tsx │ ├── dropdown-menu.tsx │ ├── form.tsx │ ├── input.tsx │ ├── label.tsx │ ├── pagination.tsx │ ├── popover.tsx │ ├── progress.tsx │ ├── radio-group.tsx │ ├── scroll-area.tsx │ ├── select.tsx │ ├── separator.tsx │ ├── sheet.tsx │ ├── switch.tsx │ ├── table.tsx │ ├── tabs.tsx │ ├── textarea.tsx │ └── tooltip.tsx └── user-avatar.tsx ├── lib ├── routes-config.tsx └── utils.ts ├── middleware.ts ├── next.config.mjs ├── package-lock.json ├── package.json ├── postcss.config.mjs ├── public ├── github.png ├── images │ ├── 404.svg │ ├── 500.svg │ ├── avatars │ │ ├── 1.png │ │ ├── 10.png │ │ ├── 11.png │ │ ├── 12.png │ │ ├── 2.png │ │ ├── 3.png │ │ ├── 4.png │ │ ├── 5.png │ │ ├── 6.png │ │ ├── 7.png │ │ ├── 8.png │ │ └── 9.png │ └── cover.png ├── logo.png ├── preview.png └── seo.jpg ├── tailwind.config.ts └── tsconfig.json /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals", 3 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | .yarn/install-state.gz 8 | 9 | # testing 10 | /coverage 11 | 12 | # next.js 13 | /.next/ 14 | /out/ 15 | 16 | # production 17 | /build 18 | 19 | # misc 20 | .DS_Store 21 | *.pem 22 | 23 | # debug 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | 28 | # local env files 29 | .env*.local 30 | 31 | # vercel 32 | .vercel 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | next-env.d.ts 37 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": true, 3 | "tabWidth": 2, 4 | "printWidth": 100, 5 | "singleQuote": false, 6 | "trailingComma": "none", 7 | "jsxBracketSameLine": true, 8 | "plugins": ["prettier-plugin-tailwindcss"] 9 | } 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
5 | 6 | Logo 7 | 8 | 9 |

Shadcn UI Kit

10 | 11 |

12 | Shadcn UI Kit is a comprehensive collection of ready-to-use admin dashboards, website templates, and customizable components. 13 |
14 |
15 | Home Page 16 |  •  17 | Dashboards 18 |  •  19 | Templates 20 |  •  21 | Free 22 |

23 |
24 |
25 | 26 | ## 💎 About Shadcn UI Kit 27 | 28 | **Shadcn UI Kit** is a comprehensive and versatile collection of ready-to-use admin dashboards, website templates, and fully customizable components designed for modern web applications. It goes beyond standard UI libraries by offering enhanced functionality, greater design flexibility, and a seamless user experience. Whether you're building complex admin panels or sleek landing pages, Shadcn UI Kit provides the tools you need to create visually appealing and highly functional interfaces with ease. 29 | 30 | Logo 31 | 32 | ## 🪄 Get Lifetime Access (PRO) 33 | 34 | Get lifetime use of the premium version of Shadcn UI Kit with hundreds of UI components, dashboards, website templates and pre-built pages. Free updates, newly added components and templates are also included. 35 | 36 | | Free Version | [Shadcn UI Kit PRO](https://shadcnuikit.com/pricing) | 37 | | -------------- | ---------------------------------------------------- | 38 | | 1 Dashboard | ✔ 10 Dashboards | 39 | | 5+ Pages | ✔ 50+ Pages | 40 | | 1 Color Scheme | ✔ 10+ Web Apps | 41 | | | ✔ 100+ Premium Components | 42 | | | ✔ Premium Templates | 43 | | | ✔ 5+ Color Schemes | 44 | | | ✔ Theme Customization | 45 | | | ✔ Dark/Light Mode 🌙 | 46 | | | ✔ LTR/RTL Support | 47 | | | ✔ New Sidebar | 48 | | | ✔ Multiple Layouts | 49 | | | ✔ and more.. | 50 | 51 | ✅ [Click here](https://shadcnuikit.com/pricing) to get the Shadcn UI Kit and review it in detail 52 | 53 | ## ✉️ Contact 54 | 55 | Toby Belhome - [@TobyBelhome](https://x.com/TobyBelhome) 56 | 57 |

(back to top)

58 | -------------------------------------------------------------------------------- /app/(guest)/layout.tsx: -------------------------------------------------------------------------------- 1 | import Providers from "@/components/providers"; 2 | 3 | export default function GuestLayout({ 4 | children 5 | }: Readonly<{ 6 | children: React.ReactNode; 7 | }>) { 8 | return {children}; 9 | } 10 | -------------------------------------------------------------------------------- /app/(guest)/login/page.tsx: -------------------------------------------------------------------------------- 1 | import { Button } from "@/components/ui/button"; 2 | import { Input } from "@/components/ui/input"; 3 | import { Label } from "@/components/ui/label"; 4 | import { generateMeta } from "@/lib/utils"; 5 | import { GithubIcon } from "lucide-react"; 6 | import Link from "next/link"; 7 | 8 | export async function generateMetadata() { 9 | return generateMeta({ 10 | title: "Login Page - Shadcn UI Kit Free", 11 | description: 12 | "A login form with email and password. There's an option to login with Google and a link to sign up if you don't have an account.", 13 | canonical: "/login" 14 | }); 15 | } 16 | 17 | export default function LoginPageV1() { 18 | return ( 19 |
20 |
21 | Login visual 22 |
23 | 24 |
25 |
26 |
27 |

Welcome back

28 |

Please sign in to your account

29 |
30 | 31 |
32 |
33 |
34 | 37 | 46 |
47 |
48 | 51 | 60 |
61 |
62 | 63 | Forgot your password? 64 | 65 |
66 |
67 | 68 |
69 | 72 |
73 |
74 | 75 |
76 |
77 |
78 |
79 |
80 |
81 | or continue with 82 |
83 |
84 | 85 |
86 | 107 | 111 |
112 | 113 |
114 | Don't have an account?{" "} 115 | 116 | Sign up 117 | 118 |
119 |
120 |
121 |
122 |
123 | ); 124 | } 125 | -------------------------------------------------------------------------------- /app/(guest)/pages/error/404/page.tsx: -------------------------------------------------------------------------------- 1 | import { Button } from "@/components/ui/button"; 2 | import { generateMeta } from "@/lib/utils"; 3 | import { ArrowRight } from "lucide-react"; 4 | 5 | export async function generateMetadata() { 6 | return generateMeta({ 7 | title: "404 Page - Shadcn UI Kit Free", 8 | description: 9 | "This is an example of a template for 404 error pages. Built with technologies like Tailwind CSS, Next.js, React and Shadcn.", 10 | canonical: "/pages/error/404" 11 | }); 12 | } 13 | 14 | export default function Error404() { 15 | return ( 16 |
17 |
18 |

404

19 |

20 | Page not found 21 |

22 |

23 | Sorry, we couldn’t find the page you’re looking for. 24 |

25 |
26 | 27 | 30 |
31 |
32 | 33 |
34 | Login visual 39 |
40 |
41 | ); 42 | } 43 | -------------------------------------------------------------------------------- /app/(guest)/pages/error/500/page.tsx: -------------------------------------------------------------------------------- 1 | import { generateMeta } from "@/lib/utils"; 2 | 3 | export async function generateMetadata() { 4 | return generateMeta({ 5 | title: "500 Page - Shadcn UI Kit Free", 6 | description: 7 | "This is an example of a template for 500 error pages. Built with technologies like Tailwind CSS, Next.js, React and Shadcn.", 8 | canonical: "/pages/error/404" 9 | }); 10 | } 11 | 12 | export default function Error404() { 13 | return ( 14 |
15 |
16 |

500

17 |

18 | Server Error 19 |

20 |

21 | There seems to be a connection problem between the server and the website. 22 |

23 |
24 | 25 |
26 | Login visual 31 |
32 |
33 | ); 34 | } 35 | -------------------------------------------------------------------------------- /app/(guest)/register/page.tsx: -------------------------------------------------------------------------------- 1 | import { Button } from "@/components/ui/button"; 2 | import { Input } from "@/components/ui/input"; 3 | import { Label } from "@/components/ui/label"; 4 | import { generateMeta } from "@/lib/utils"; 5 | import { GithubIcon } from "lucide-react"; 6 | 7 | export async function generateMetadata() { 8 | return generateMeta({ 9 | title: "Register Page - Shadcn UI Kit Free", 10 | description: 11 | "A login form with email and password. There's an option to login with Google and a link to sign up if you don't have an account.", 12 | canonical: "/register" 13 | }); 14 | } 15 | 16 | export default function LoginPageV1() { 17 | return ( 18 |
19 |
20 | Login visual 21 |
22 | 23 |
24 |
25 |
26 |

Register

27 |

28 | Create a new account to access the dashboard. 29 |

30 |
31 | 32 |
33 |
34 |
35 | 38 | 46 |
47 |
48 | 51 | 60 |
61 |
62 | 65 | 74 |
75 |
76 | 77 |
78 | 81 |
82 |
83 | 84 |
85 |
86 |
87 |
88 |
89 |
90 | or continue with 91 |
92 |
93 | 94 |
95 | 116 | 120 |
121 | 122 |

123 | Already have an account?{" "} 124 | 125 | Log in 126 | 127 |

128 |
129 |
130 |
131 |
132 | ); 133 | } 134 | -------------------------------------------------------------------------------- /app/dashboard/default/cards/chat.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import * as React from "react"; 4 | import { Check, Plus, Send } from "lucide-react"; 5 | 6 | import { cn } from "@/lib/utils"; 7 | import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; 8 | import { Button } from "@/components/ui/button"; 9 | import { 10 | Card, 11 | CardContent, 12 | CardFooter, 13 | CardHeader, 14 | } from "@/components/ui/card"; 15 | import { 16 | Command, 17 | CommandEmpty, 18 | CommandGroup, 19 | CommandInput, 20 | CommandItem, 21 | CommandList, 22 | } from "@/components/ui/command"; 23 | import { 24 | Dialog, 25 | DialogContent, 26 | DialogDescription, 27 | DialogFooter, 28 | DialogHeader, 29 | DialogTitle, 30 | } from "@/components/ui/dialog"; 31 | import { Input } from "@/components/ui/input"; 32 | import { 33 | Tooltip, 34 | TooltipContent, 35 | TooltipProvider, 36 | TooltipTrigger, 37 | } from "@/components/ui/tooltip"; 38 | 39 | const users = [ 40 | { 41 | name: "Olivia Martin", 42 | email: "m@example.com", 43 | avatar: "/avatars/01.png", 44 | }, 45 | { 46 | name: "Isabella Nguyen", 47 | email: "isabella.nguyen@email.com", 48 | avatar: "/avatars/03.png", 49 | }, 50 | { 51 | name: "Emma Wilson", 52 | email: "emma@example.com", 53 | avatar: "/avatars/05.png", 54 | }, 55 | { 56 | name: "Jackson Lee", 57 | email: "lee@example.com", 58 | avatar: "/avatars/02.png", 59 | }, 60 | { 61 | name: "William Kim", 62 | email: "will@email.com", 63 | avatar: "/avatars/04.png", 64 | }, 65 | ] as const; 66 | 67 | type User = (typeof users)[number]; 68 | 69 | export function ChatCard() { 70 | const [open, setOpen] = React.useState(false); 71 | const [selectedUsers, setSelectedUsers] = React.useState([]); 72 | 73 | const [messages, setMessages] = React.useState([ 74 | { 75 | role: "agent", 76 | content: "Hi, how can I help you today?", 77 | }, 78 | { 79 | role: "user", 80 | content: "Hey, I'm having trouble with my account.", 81 | }, 82 | { 83 | role: "agent", 84 | content: "What seems to be the problem?", 85 | }, 86 | { 87 | role: "user", 88 | content: "I can't log in.", 89 | }, 90 | ]); 91 | const [input, setInput] = React.useState(""); 92 | const inputLength = input.trim().length; 93 | 94 | return ( 95 | <> 96 | 97 | 98 |
99 | 100 | 101 | OM 102 | 103 |
104 |

Sofia Davis

105 |

m@example.com

106 |
107 |
108 | 109 | 110 | 111 | 120 | 121 | New message 122 | 123 | 124 |
125 | 126 |
127 | {messages.map((message, index) => ( 128 |
137 | {message.content} 138 |
139 | ))} 140 |
141 |
142 | 143 |
{ 145 | event.preventDefault(); 146 | if (inputLength === 0) return; 147 | setMessages([ 148 | ...messages, 149 | { 150 | role: "user", 151 | content: input, 152 | }, 153 | ]); 154 | setInput(""); 155 | }} 156 | className="flex w-full items-center space-x-2" 157 | > 158 | setInput(event.target.value)} 165 | /> 166 | 170 |
171 |
172 |
173 | 174 | 175 | 176 | New message 177 | 178 | Invite a user to this thread. This will create a new group 179 | message. 180 | 181 | 182 | 183 | 184 | 185 | No users found. 186 | 187 | {users.map((user) => ( 188 | { 192 | if (selectedUsers.includes(user)) { 193 | return setSelectedUsers( 194 | selectedUsers.filter( 195 | (selectedUser) => selectedUser !== user, 196 | ), 197 | ); 198 | } 199 | 200 | return setSelectedUsers( 201 | [...users].filter((u) => 202 | [...selectedUsers, user].includes(u), 203 | ), 204 | ); 205 | }} 206 | > 207 | 208 | 209 | {user.name[0]} 210 | 211 |
212 |

213 | {user.name} 214 |

215 |

216 | {user.email} 217 |

218 |
219 | {selectedUsers.includes(user) ? ( 220 | 221 | ) : null} 222 |
223 | ))} 224 |
225 |
226 |
227 | 228 | {selectedUsers.length > 0 ? ( 229 |
230 | {selectedUsers.map((user) => ( 231 | 235 | 236 | {user.name[0]} 237 | 238 | ))} 239 |
240 | ) : ( 241 |

242 | Select users to add to this thread. 243 |

244 | )} 245 | 253 |
254 |
255 |
256 | 257 | ); 258 | } 259 | -------------------------------------------------------------------------------- /app/dashboard/default/cards/metric.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { Line, LineChart, ResponsiveContainer, Tooltip } from "recharts"; 4 | 5 | import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; 6 | import { ExportButton } from "@/components/card-action-menus"; 7 | 8 | const data = [ 9 | { 10 | average: 400, 11 | today: 240 12 | }, 13 | { 14 | average: 300, 15 | today: 139 16 | }, 17 | { 18 | average: 200, 19 | today: 980 20 | }, 21 | { 22 | average: 278, 23 | today: 390 24 | }, 25 | { 26 | average: 189, 27 | today: 480 28 | }, 29 | { 30 | average: 239, 31 | today: 380 32 | }, 33 | { 34 | average: 349, 35 | today: 430 36 | } 37 | ]; 38 | 39 | export default function MetricCard({ className }: { className?: string }) { 40 | return ( 41 | 42 | 43 |
44 |
45 | Exercise Minutes 46 | 47 | Your exercise minutes are ahead of where you normally are. 48 | 49 |
50 | 51 |
52 |
53 | 54 |
55 | 56 | 64 | { 66 | if (active && payload && payload.length) { 67 | return ( 68 |
69 |
70 |
71 | 72 | Average 73 | 74 | 75 | {payload[0].value} 76 | 77 |
78 |
79 | 80 | Today 81 | 82 | {payload[1].value} 83 |
84 |
85 |
86 | ); 87 | } 88 | 89 | return null; 90 | }} 91 | /> 92 | 108 | 123 |
124 |
125 |
126 |
127 |
128 | ); 129 | } 130 | -------------------------------------------------------------------------------- /app/dashboard/default/cards/payment-method.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { Icons } from "@/components/icons"; 4 | import { Button } from "@/components/ui/button"; 5 | import { 6 | Card, 7 | CardContent, 8 | CardDescription, 9 | CardFooter, 10 | CardHeader, 11 | CardTitle, 12 | } from "@/components/ui/card"; 13 | import { Input } from "@/components/ui/input"; 14 | import { Label } from "@/components/ui/label"; 15 | import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; 16 | import { 17 | Select, 18 | SelectContent, 19 | SelectItem, 20 | SelectTrigger, 21 | SelectValue, 22 | } from "@/components/ui/select"; 23 | 24 | export function PaymentMethodCard() { 25 | return ( 26 | 27 | 28 | Payment Method 29 | 30 | Add a new payment method to your account. 31 | 32 | 33 | 34 | 35 |
36 | 42 | 61 |
62 | 63 |
64 | 70 | 77 |
78 | 79 |
80 | 86 | 93 |
94 |
95 |
96 | 97 | 98 |
99 |
100 | 101 | 102 |
103 |
104 | 105 | 106 |
107 |
108 |
109 | 110 | 129 |
130 |
131 | 132 | 144 |
145 |
146 | 147 | 148 |
149 |
150 |
151 | 152 | 153 | 154 |
155 | ); 156 | } 157 | -------------------------------------------------------------------------------- /app/dashboard/default/cards/payment.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import * as React from "react"; 4 | 5 | import { 6 | ColumnDef, 7 | ColumnFiltersState, 8 | SortingState, 9 | VisibilityState, 10 | flexRender, 11 | getCoreRowModel, 12 | getFilteredRowModel, 13 | getPaginationRowModel, 14 | getSortedRowModel, 15 | useReactTable 16 | } from "@tanstack/react-table"; 17 | 18 | import { Button } from "@/components/ui/button"; 19 | import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; 20 | import { Checkbox } from "@/components/ui/checkbox"; 21 | import { 22 | DropdownMenu, 23 | DropdownMenuCheckboxItem, 24 | DropdownMenuContent, 25 | DropdownMenuItem, 26 | DropdownMenuLabel, 27 | DropdownMenuSeparator, 28 | DropdownMenuTrigger 29 | } from "@/components/ui/dropdown-menu"; 30 | import { Input } from "@/components/ui/input"; 31 | import { 32 | Table, 33 | TableBody, 34 | TableCell, 35 | TableHead, 36 | TableHeader, 37 | TableRow 38 | } from "@/components/ui/table"; 39 | import { ChevronDownIcon, ChevronsUpDown, Ellipsis } from "lucide-react"; 40 | import { CardOptionsMenu } from "@/components/card-action-menus"; 41 | 42 | const data: Payment[] = [ 43 | { 44 | id: "m5gr84i9", 45 | amount: 316, 46 | status: "success", 47 | email: "ken99@yahoo.com" 48 | }, 49 | { 50 | id: "3u1reuv4", 51 | amount: 242, 52 | status: "success", 53 | email: "Abe45@gmail.com" 54 | }, 55 | { 56 | id: "derv1ws0", 57 | amount: 837, 58 | status: "processing", 59 | email: "Monserrat44@gmail.com" 60 | }, 61 | { 62 | id: "5kma53ae", 63 | amount: 874, 64 | status: "success", 65 | email: "Silas22@gmail.com" 66 | }, 67 | { 68 | id: "bhqecj4p", 69 | amount: 721, 70 | status: "failed", 71 | email: "carmella@hotmail.com" 72 | } 73 | ]; 74 | 75 | export type Payment = { 76 | id: string; 77 | amount: number; 78 | status: "pending" | "processing" | "success" | "failed"; 79 | email: string; 80 | }; 81 | 82 | export const columns: ColumnDef[] = [ 83 | { 84 | id: "select", 85 | header: ({ table }) => ( 86 | table.toggleAllPageRowsSelected(!!value)} 91 | aria-label="Select all" 92 | /> 93 | ), 94 | cell: ({ row }) => ( 95 | row.toggleSelected(!!value)} 98 | aria-label="Select row" 99 | /> 100 | ), 101 | enableSorting: false, 102 | enableHiding: false 103 | }, 104 | { 105 | accessorKey: "status", 106 | header: "Status", 107 | cell: ({ row }) =>
{row.getValue("status")}
108 | }, 109 | { 110 | accessorKey: "email", 111 | header: ({ column }) => { 112 | return ( 113 | 119 | ); 120 | }, 121 | cell: ({ row }) =>
{row.getValue("email")}
122 | }, 123 | { 124 | accessorKey: "amount", 125 | header: () =>
Amount
, 126 | cell: ({ row }) => { 127 | const amount = parseFloat(row.getValue("amount")); 128 | 129 | // Format the amount as a dollar amount 130 | const formatted = new Intl.NumberFormat("en-US", { 131 | style: "currency", 132 | currency: "USD" 133 | }).format(amount); 134 | 135 | return
{formatted}
; 136 | } 137 | }, 138 | { 139 | id: "actions", 140 | enableHiding: false, 141 | cell: ({ row }) => { 142 | const payment = row.original; 143 | 144 | return ( 145 | 146 | 147 | 151 | 152 | 153 | Actions 154 | navigator.clipboard.writeText(payment.id)}> 155 | Copy payment ID 156 | 157 | 158 | View customer 159 | View payment details 160 | 161 | 162 | ); 163 | } 164 | } 165 | ]; 166 | 167 | export function PaymentsCard({ className }: { className?: string }) { 168 | const [sorting, setSorting] = React.useState([]); 169 | const [columnFilters, setColumnFilters] = React.useState([]); 170 | const [columnVisibility, setColumnVisibility] = React.useState({}); 171 | const [rowSelection, setRowSelection] = React.useState({}); 172 | 173 | const table = useReactTable({ 174 | data, 175 | columns, 176 | onSortingChange: setSorting, 177 | onColumnFiltersChange: setColumnFilters, 178 | getCoreRowModel: getCoreRowModel(), 179 | getPaginationRowModel: getPaginationRowModel(), 180 | getSortedRowModel: getSortedRowModel(), 181 | getFilteredRowModel: getFilteredRowModel(), 182 | onColumnVisibilityChange: setColumnVisibility, 183 | onRowSelectionChange: setRowSelection, 184 | state: { 185 | sorting, 186 | columnFilters, 187 | columnVisibility, 188 | rowSelection 189 | } 190 | }); 191 | 192 | return ( 193 | 194 | 195 |
196 | Payments 197 | Manage your payments. 198 |
199 | 200 |
201 | 202 |
203 | table.getColumn("email")?.setFilterValue(event.target.value)} 207 | className="max-w-sm" 208 | /> 209 | 210 | 211 | 214 | 215 | 216 | {table 217 | .getAllColumns() 218 | .filter((column) => column.getCanHide()) 219 | .map((column) => { 220 | return ( 221 | column.toggleVisibility(!!value)}> 226 | {column.id} 227 | 228 | ); 229 | })} 230 | 231 | 232 |
233 |
234 | 235 | 236 | {table.getHeaderGroups().map((headerGroup) => ( 237 | 238 | {headerGroup.headers.map((header) => { 239 | return ( 240 | 241 | {header.isPlaceholder 242 | ? null 243 | : flexRender(header.column.columnDef.header, header.getContext())} 244 | 245 | ); 246 | })} 247 | 248 | ))} 249 | 250 | 251 | {table.getRowModel().rows?.length ? ( 252 | table.getRowModel().rows.map((row) => ( 253 | 254 | {row.getVisibleCells().map((cell) => ( 255 | 256 | {flexRender(cell.column.columnDef.cell, cell.getContext())} 257 | 258 | ))} 259 | 260 | )) 261 | ) : ( 262 | 263 | 264 | No results. 265 | 266 | 267 | )} 268 | 269 |
270 |
271 |
272 |
273 | {table.getFilteredSelectedRowModel().rows.length} of{" "} 274 | {table.getFilteredRowModel().rows.length} row(s) selected. 275 |
276 |
277 | 284 | 291 |
292 |
293 |
294 |
295 | ); 296 | } 297 | -------------------------------------------------------------------------------- /app/dashboard/default/cards/subscriptions.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { Bar, BarChart, Line, LineChart, ResponsiveContainer } from "recharts"; 4 | 5 | import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; 6 | 7 | const data = [ 8 | { 9 | revenue: 10400, 10 | subscription: 240, 11 | }, 12 | { 13 | revenue: 14405, 14 | subscription: 300, 15 | }, 16 | { 17 | revenue: 9400, 18 | subscription: 200, 19 | }, 20 | { 21 | revenue: 8200, 22 | subscription: 278, 23 | }, 24 | { 25 | revenue: 7000, 26 | subscription: 189, 27 | }, 28 | { 29 | revenue: 9600, 30 | subscription: 239, 31 | }, 32 | { 33 | revenue: 11244, 34 | subscription: 278, 35 | }, 36 | { 37 | revenue: 26475, 38 | subscription: 189, 39 | }, 40 | ]; 41 | 42 | export default function SubscriptionsCard() { 43 | return ( 44 | 45 | 46 | Subscriptions 47 | 48 | 49 |
+2350
50 |

+180.1% from last month

51 |
52 | 53 | 54 | 64 | 65 | 66 |
67 |
68 |
69 | ); 70 | } 71 | -------------------------------------------------------------------------------- /app/dashboard/default/cards/theme-members.tsx: -------------------------------------------------------------------------------- 1 | import { ChevronDownIcon, ChevronsDownIcon } from "lucide-react"; 2 | 3 | import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; 4 | import { Button } from "@/components/ui/button"; 5 | import { 6 | Card, 7 | CardContent, 8 | CardDescription, 9 | CardHeader, 10 | CardTitle, 11 | } from "@/components/ui/card"; 12 | import { 13 | Command, 14 | CommandEmpty, 15 | CommandGroup, 16 | CommandInput, 17 | CommandItem, 18 | CommandList, 19 | } from "@/components/ui/command"; 20 | import { 21 | Popover, 22 | PopoverContent, 23 | PopoverTrigger, 24 | } from "@/components/ui/popover"; 25 | 26 | export default function TeamMembersCard() { 27 | return ( 28 | 29 | 30 | Team Members 31 | 32 | Invite your team members to collaborate. 33 | 34 | 35 | 36 |
37 |
38 | 39 | 40 | OM 41 | 42 |
43 |

Sofia Davis

44 |

m@example.com

45 |
46 |
47 | 48 | 49 | 53 | 54 | 55 | 56 | 57 | 58 | No roles found. 59 | 60 | 61 |

Viewer

62 |

63 | Can view and comment. 64 |

65 |
66 | 67 |

Developer

68 |

69 | Can view, comment and edit. 70 |

71 |
72 | 73 |

Billing

74 |

75 | Can view, comment and manage billing. 76 |

77 |
78 | 79 |

Owner

80 |

81 | Admin-level access to all resources. 82 |

83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 | 93 | 94 | JL 95 | 96 |
97 |

Jackson Lee

98 |

p@example.com

99 |
100 |
101 | 102 | 103 | 107 | 108 | 109 | 110 | 111 | 112 | No roles found. 113 | 114 | 115 |

Viewer

116 |

117 | Can view and comment. 118 |

119 |
120 | 121 |

Developer

122 |

123 | Can view, comment and edit. 124 |

125 |
126 | 127 |

Billing

128 |

129 | Can view, comment and manage billing. 130 |

131 |
132 | 133 |

Owner

134 |

135 | Admin-level access to all resources. 136 |

137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 | ); 147 | } 148 | -------------------------------------------------------------------------------- /app/dashboard/default/cards/total-revenue.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { Bar, BarChart, Line, LineChart, ResponsiveContainer } from "recharts"; 4 | 5 | import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; 6 | 7 | const data = [ 8 | { 9 | revenue: 10400, 10 | subscription: 240, 11 | }, 12 | { 13 | revenue: 14405, 14 | subscription: 300, 15 | }, 16 | { 17 | revenue: 9400, 18 | subscription: 200, 19 | }, 20 | { 21 | revenue: 8200, 22 | subscription: 278, 23 | }, 24 | { 25 | revenue: 7000, 26 | subscription: 189, 27 | }, 28 | { 29 | revenue: 9600, 30 | subscription: 239, 31 | }, 32 | { 33 | revenue: 11244, 34 | subscription: 278, 35 | }, 36 | { 37 | revenue: 26475, 38 | subscription: 189, 39 | }, 40 | ]; 41 | 42 | export default function TotalRevenueCard() { 43 | return ( 44 | 45 | 46 | Total Revenue 47 | 48 | 49 |
$15,231.89
50 |

+20.1% from last month

51 |
52 | 53 | 62 | 77 | 78 | 79 |
80 |
81 |
82 | ); 83 | } 84 | -------------------------------------------------------------------------------- /app/dashboard/default/page.tsx: -------------------------------------------------------------------------------- 1 | import CalendarDateRangePicker from "@/components/date-range-picker"; 2 | import TeamMembersCard from "./cards/theme-members"; 3 | import SubscriptionsCard from "./cards/subscriptions"; 4 | import TotalRevenueCard from "./cards/total-revenue"; 5 | import { ChatCard } from "./cards/chat"; 6 | import { Button } from "@/components/ui/button"; 7 | import MetricCard from "./cards/metric"; 8 | import { PaymentsCard } from "./cards/payment"; 9 | import { PaymentMethodCard } from "./cards/payment-method"; 10 | import { generateMeta } from "@/lib/utils"; 11 | 12 | export async function generateMetadata() { 13 | return generateMeta({ 14 | title: "Dashboard - Shadcn UI Kit Free", 15 | description: 16 | "The default dashboard template, built with React and Tailwind CSS, offers a sleek and efficient interface for monitoring key data and user interactions.", 17 | canonical: "/default" 18 | }); 19 | } 20 | 21 | export default function Page() { 22 | return ( 23 | <> 24 |
25 |

Dashboard

26 |
27 | 28 | 29 |
30 |
31 |
32 | 33 | 34 | 35 | 36 |
37 | 38 |
39 |
40 | 41 |
42 | 43 |
44 | 45 | ); 46 | } 47 | -------------------------------------------------------------------------------- /app/dashboard/error.tsx: -------------------------------------------------------------------------------- 1 | "use client"; // Error components must be Client Components 2 | 3 | import { Button } from "@/components/ui/button"; 4 | import { useEffect } from "react"; 5 | 6 | export default function Error({ 7 | error, 8 | reset 9 | }: { 10 | error: Error & { digest?: string }; 11 | reset: () => void; 12 | }) { 13 | useEffect(() => { 14 | // Log the error to an error reporting service 15 | console.error("-->", error); 16 | }, [error]); 17 | 18 | return ( 19 |
20 |
21 |

Oops!

22 |

Something went wrong!

23 |
24 | 25 |
26 | ); 27 | } 28 | -------------------------------------------------------------------------------- /app/dashboard/layout.tsx: -------------------------------------------------------------------------------- 1 | import MainLayout from "@/components/main-layout"; 2 | 3 | export default function AuthLayout({ 4 | children 5 | }: Readonly<{ 6 | children: React.ReactNode; 7 | }>) { 8 | return {children}; 9 | } 10 | -------------------------------------------------------------------------------- /app/dashboard/pages/settings/layout.tsx: -------------------------------------------------------------------------------- 1 | import { Separator } from "@/components/ui/separator"; 2 | import { SidebarNav } from "./sidebar-nav"; 3 | import { generateMeta } from "@/lib/utils"; 4 | 5 | export async function generateMetadata() { 6 | return generateMeta({ 7 | title: "Settings Page", 8 | description: 9 | "Example of settings page and form created using react-hook-form and Zod validator. Built with Tailwind CSS and React.", 10 | canonical: "/pages/settings" 11 | }); 12 | } 13 | 14 | const sidebarNavItems = [ 15 | { 16 | title: "Profile", 17 | href: "/dashboard/pages/settings" 18 | }, 19 | { 20 | title: "Account", 21 | href: "#" 22 | }, 23 | { 24 | title: "Appearance", 25 | href: "#" 26 | }, 27 | { 28 | title: "Notifications", 29 | href: "#" 30 | }, 31 | { 32 | title: "Display", 33 | href: "#" 34 | } 35 | ]; 36 | 37 | export default function SettingsLayout({ children }: { children: React.ReactNode }) { 38 | return ( 39 | <> 40 |
41 |

Settings

42 |

43 | Manage your account settings and set e-mail preferences. 44 |

45 |
46 | 47 |
48 | 51 |
{children}
52 |
53 | 54 | ); 55 | } 56 | -------------------------------------------------------------------------------- /app/dashboard/pages/settings/page.tsx: -------------------------------------------------------------------------------- 1 | import { Separator } from "@/components/ui/separator"; 2 | import { ProfileForm } from "./profile-form"; 3 | 4 | export default function SettingsProfilePage() { 5 | return ( 6 |
7 |
8 |

Profile

9 |

10 | This is how others will see you on the site. 11 |

12 |
13 | 14 | 15 |
16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /app/dashboard/pages/settings/profile-form.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import Link from "next/link"; 4 | import { zodResolver } from "@hookform/resolvers/zod"; 5 | import { useFieldArray, useForm } from "react-hook-form"; 6 | import { z } from "zod"; 7 | 8 | import { cn } from "@/lib/utils"; 9 | import { Button } from "@/components/ui/button"; 10 | import { 11 | Form, 12 | FormControl, 13 | FormDescription, 14 | FormField, 15 | FormItem, 16 | FormLabel, 17 | FormMessage 18 | } from "@/components/ui/form"; 19 | import { Input } from "@/components/ui/input"; 20 | import { 21 | Select, 22 | SelectContent, 23 | SelectItem, 24 | SelectTrigger, 25 | SelectValue 26 | } from "@/components/ui/select"; 27 | import { Textarea } from "@/components/ui/textarea"; 28 | 29 | const profileFormSchema = z.object({ 30 | username: z 31 | .string() 32 | .min(2, { 33 | message: "Username must be at least 2 characters." 34 | }) 35 | .max(30, { 36 | message: "Username must not be longer than 30 characters." 37 | }), 38 | email: z 39 | .string({ 40 | required_error: "Please select an email to display." 41 | }) 42 | .email(), 43 | bio: z.string().max(160).min(4), 44 | urls: z 45 | .array( 46 | z.object({ 47 | value: z.string().url({ message: "Please enter a valid URL." }) 48 | }) 49 | ) 50 | .optional() 51 | }); 52 | 53 | type ProfileFormValues = z.infer; 54 | 55 | // This can come from your database or API. 56 | const defaultValues: Partial = { 57 | bio: "I own a computer.", 58 | urls: [{ value: "https://shadcn.com" }, { value: "http://twitter.com/shadcn" }] 59 | }; 60 | 61 | export function ProfileForm() { 62 | const form = useForm({ 63 | resolver: zodResolver(profileFormSchema), 64 | defaultValues, 65 | mode: "onChange" 66 | }); 67 | 68 | const { fields, append } = useFieldArray({ 69 | name: "urls", 70 | control: form.control 71 | }); 72 | 73 | function onSubmit(data: ProfileFormValues) {} 74 | 75 | return ( 76 |
77 | 78 | ( 82 | 83 | Username 84 | 85 | 86 | 87 | 88 | This is your public display name. It can be your real name or a pseudonym. You can 89 | only change this once every 30 days. 90 | 91 | 92 | 93 | )} 94 | /> 95 | ( 99 | 100 | Email 101 | 113 | 114 | You can manage verified email addresses in your{" "} 115 | email settings. 116 | 117 | 118 | 119 | )} 120 | /> 121 | ( 125 | 126 | Bio 127 | 128 |