├── src ├── vite-env.d.ts ├── pages │ ├── settings │ │ ├── error-example │ │ │ └── index.tsx │ │ ├── profile │ │ │ ├── index.tsx │ │ │ └── profile-form.tsx │ │ ├── display │ │ │ ├── index.tsx │ │ │ └── display-form.tsx │ │ ├── notifications │ │ │ └── index.tsx │ │ ├── account │ │ │ └── index.tsx │ │ ├── appearance │ │ │ ├── index.tsx │ │ │ └── appearance-form.tsx │ │ ├── components │ │ │ ├── content-section.tsx │ │ │ └── sidebar-nav.tsx │ │ └── index.tsx │ ├── tasks │ │ ├── data │ │ │ ├── schema.ts │ │ │ └── data.tsx │ │ ├── index.tsx │ │ └── components │ │ │ ├── data-table-view-options.tsx │ │ │ ├── data-table-toolbar.tsx │ │ │ ├── data-table-row-actions.tsx │ │ │ ├── data-table-column-header.tsx │ │ │ ├── data-table-pagination.tsx │ │ │ ├── columns.tsx │ │ │ ├── data-table.tsx │ │ │ └── data-table-faceted-filter.tsx │ ├── errors │ │ ├── maintenance-error.tsx │ │ ├── not-found-error.tsx │ │ └── general-error.tsx │ ├── dashboard │ │ └── components │ │ │ ├── overview.tsx │ │ │ └── recent-sales.tsx │ ├── auth │ │ ├── forgot-password.tsx │ │ ├── otp.tsx │ │ ├── components │ │ │ ├── forgot-form.tsx │ │ │ ├── otp-form.tsx │ │ │ ├── user-auth-form.tsx │ │ │ └── sign-up-form.tsx │ │ ├── sign-in-2.tsx │ │ ├── sign-up.tsx │ │ └── sign-in.tsx │ ├── apps │ │ ├── data.tsx │ │ └── index.tsx │ └── extra-components │ │ └── index.tsx ├── lib │ └── utils.ts ├── components │ ├── search.tsx │ ├── loader.tsx │ ├── ui │ │ ├── collapsible.tsx │ │ ├── label.tsx │ │ ├── textarea.tsx │ │ ├── separator.tsx │ │ ├── input.tsx │ │ ├── toaster.tsx │ │ ├── checkbox.tsx │ │ ├── tooltip.tsx │ │ ├── switch.tsx │ │ ├── badge.tsx │ │ ├── popover.tsx │ │ ├── radio-group.tsx │ │ ├── avatar.tsx │ │ ├── tabs.tsx │ │ ├── card.tsx │ │ ├── calendar.tsx │ │ ├── table.tsx │ │ ├── dialog.tsx │ │ ├── use-toast.ts │ │ ├── form.tsx │ │ ├── toast.tsx │ │ ├── command.tsx │ │ └── select.tsx │ ├── coming-soon.tsx │ ├── app-shell.tsx │ ├── theme-switch.tsx │ ├── custom │ │ ├── password-input.tsx │ │ ├── breadcrumb.tsx │ │ ├── button.tsx │ │ └── layout.tsx │ ├── theme-provider.tsx │ ├── top-nav.tsx │ ├── user-nav.tsx │ └── sidebar.tsx ├── hooks │ ├── use-check-active-nav.tsx │ ├── use-local-storage.tsx │ └── use-is-collapsed.tsx ├── main.tsx ├── assets │ └── vite.svg ├── index.css ├── data │ └── sidelinks.tsx └── router.tsx ├── .gitattributes ├── netlify.toml ├── public └── images │ ├── favicon.png │ ├── shadcn-admin.png │ └── favicon.svg ├── postcss.config.js ├── tsconfig.node.json ├── .prettierignore ├── .prettierrc ├── vite.config.ts ├── .gitignore ├── components.json ├── .eslintrc.cjs ├── tsconfig.json ├── LICENSE ├── index.html ├── README.md ├── tailwind.config.js └── package.json /src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /netlify.toml: -------------------------------------------------------------------------------- 1 | [[redirects]] 2 | from = "/*" 3 | to = "/index.html" 4 | status = 200 -------------------------------------------------------------------------------- /public/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edwin1113/AdminDashboard-Shadcn/HEAD/public/images/favicon.png -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /public/images/shadcn-admin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edwin1113/AdminDashboard-Shadcn/HEAD/public/images/shadcn-admin.png -------------------------------------------------------------------------------- /src/pages/settings/error-example/index.tsx: -------------------------------------------------------------------------------- 1 | export default function ErrorExample() { 2 | throw Error('an error occurs while loading this component') 3 | return

Error Example

4 | } 5 | -------------------------------------------------------------------------------- /src/lib/utils.ts: -------------------------------------------------------------------------------- 1 | import { type ClassValue, clsx } from "clsx" 2 | import { twMerge } from "tailwind-merge" 3 | 4 | export function cn(...inputs: ClassValue[]) { 5 | return twMerge(clsx(inputs)) 6 | } 7 | -------------------------------------------------------------------------------- /tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "skipLibCheck": true, 5 | "module": "ESNext", 6 | "moduleResolution": "bundler", 7 | "allowSyntheticDefaultImports": true 8 | }, 9 | "include": ["vite.config.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # Ignore everything 2 | /* 3 | 4 | # Except these files & folders 5 | !/src 6 | !index.html 7 | !package.json 8 | !tsconfig.json 9 | !tsconfig.node.json 10 | !vite.config.ts 11 | !.prettierrc 12 | !README.md 13 | !CHANGELOG.md 14 | !.eslintrc.cjs 15 | !postcss.config.js -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "always", 3 | "semi": false, 4 | "tabWidth": 2, 5 | "printWidth": 80, 6 | "singleQuote": true, 7 | "jsxSingleQuote": true, 8 | "trailingComma": "es5", 9 | "bracketSpacing": true, 10 | "endOfLine": "lf", 11 | "plugins": ["prettier-plugin-tailwindcss"] 12 | } 13 | -------------------------------------------------------------------------------- /src/components/search.tsx: -------------------------------------------------------------------------------- 1 | import { Input } from '@/components/ui/input' 2 | 3 | export function Search() { 4 | return ( 5 |
6 | 11 |
12 | ) 13 | } 14 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import path from 'path' 2 | import { defineConfig } from 'vite' 3 | import react from '@vitejs/plugin-react-swc' 4 | 5 | // https://vitejs.dev/config/ 6 | export default defineConfig({ 7 | plugins: [react()], 8 | resolve: { 9 | alias: { 10 | '@': path.resolve(__dirname, './src'), 11 | }, 12 | }, 13 | }) 14 | -------------------------------------------------------------------------------- /src/components/loader.tsx: -------------------------------------------------------------------------------- 1 | import { IconLoader } from '@tabler/icons-react' 2 | 3 | export default function Loader() { 4 | return ( 5 |
6 | 7 | loading 8 |
9 | ) 10 | } 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /src/components/ui/collapsible.tsx: -------------------------------------------------------------------------------- 1 | import * as CollapsiblePrimitive from "@radix-ui/react-collapsible" 2 | 3 | const Collapsible = CollapsiblePrimitive.Root 4 | 5 | const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger 6 | 7 | const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent 8 | 9 | export { Collapsible, CollapsibleTrigger, CollapsibleContent } 10 | -------------------------------------------------------------------------------- /src/pages/settings/profile/index.tsx: -------------------------------------------------------------------------------- 1 | import ProfileForm from './profile-form' 2 | import ContentSection from '../components/content-section' 3 | 4 | export default function SettingsProfile() { 5 | return ( 6 | 10 | 11 | 12 | ) 13 | } 14 | -------------------------------------------------------------------------------- /src/pages/tasks/data/schema.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod' 2 | 3 | // We're keeping a simple non-relational schema here. 4 | // IRL, you will have a schema for your data models. 5 | export const taskSchema = z.object({ 6 | id: z.string(), 7 | title: z.string(), 8 | status: z.string(), 9 | label: z.string(), 10 | priority: z.string(), 11 | }) 12 | 13 | export type Task = z.infer 14 | -------------------------------------------------------------------------------- /components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "new-york", 4 | "rsc": false, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "tailwind.config.js", 8 | "css": "src/index.css", 9 | "baseColor": "slate", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils" 16 | } 17 | } -------------------------------------------------------------------------------- /src/pages/settings/display/index.tsx: -------------------------------------------------------------------------------- 1 | import { DisplayForm } from './display-form' 2 | import ContentSection from '../components/content-section' 3 | 4 | export default function SettingsDisplay() { 5 | return ( 6 | 10 | 11 | 12 | ) 13 | } 14 | -------------------------------------------------------------------------------- /src/pages/settings/notifications/index.tsx: -------------------------------------------------------------------------------- 1 | import { NotificationsForm } from './notifications-form' 2 | import ContentSection from '../components/content-section' 3 | 4 | export default function SettingsNotifications() { 5 | return ( 6 | 10 | 11 | 12 | ) 13 | } 14 | -------------------------------------------------------------------------------- /src/pages/settings/account/index.tsx: -------------------------------------------------------------------------------- 1 | import { AccountForm } from './account-form' 2 | import ContentSection from '../components/content-section' 3 | 4 | export default function SettingsAccount() { 5 | return ( 6 | 11 | 12 | 13 | ) 14 | } 15 | -------------------------------------------------------------------------------- /src/pages/settings/appearance/index.tsx: -------------------------------------------------------------------------------- 1 | import { AppearanceForm } from './appearance-form' 2 | import ContentSection from '../components/content-section' 3 | 4 | export default function SettingsAppearance() { 5 | return ( 6 | 11 | 12 | 13 | ) 14 | } 15 | -------------------------------------------------------------------------------- /src/hooks/use-check-active-nav.tsx: -------------------------------------------------------------------------------- 1 | import { useLocation } from 'react-router-dom' 2 | 3 | export default function useCheckActiveNav() { 4 | const { pathname } = useLocation() 5 | 6 | const checkActiveNav = (nav: string) => { 7 | const pathArray = pathname.split('/').filter((item) => item !== '') 8 | 9 | if (nav === '/' && pathArray.length < 1) return true 10 | 11 | return pathArray.includes(nav.replace(/^\//, '')) 12 | } 13 | 14 | return { checkActiveNav } 15 | } 16 | -------------------------------------------------------------------------------- /public/images/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { browser: true, es2020: true }, 4 | extends: [ 5 | 'eslint:recommended', 6 | 'plugin:@typescript-eslint/recommended', 7 | 'plugin:react-hooks/recommended', 8 | ], 9 | ignorePatterns: ['dist', '.eslintrc.cjs', 'src/components/ui'], 10 | parser: '@typescript-eslint/parser', 11 | plugins: ['react-refresh'], 12 | rules: { 13 | 'react-refresh/only-export-components': [ 14 | 'warn', 15 | { allowConstantExport: true }, 16 | ], 17 | }, 18 | } 19 | -------------------------------------------------------------------------------- /src/components/coming-soon.tsx: -------------------------------------------------------------------------------- 1 | import { IconPlanet } from '@tabler/icons-react' 2 | 3 | export default function ComingSoon() { 4 | return ( 5 |
6 |
7 | 8 |

Coming Soon 👀

9 |

10 | This page has not been created yet.
11 | Stay tuned though! 12 |

13 |
14 |
15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /src/main.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom/client' 3 | import { RouterProvider } from 'react-router-dom' 4 | import { Toaster } from '@/components/ui/toaster' 5 | import { ThemeProvider } from '@/components/theme-provider' 6 | import router from '@/router' 7 | import '@/index.css' 8 | 9 | ReactDOM.createRoot(document.getElementById('root')!).render( 10 | 11 | 12 | 13 | 14 | 15 | 16 | ) 17 | -------------------------------------------------------------------------------- /src/hooks/use-local-storage.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from 'react' 2 | 3 | interface LocalStorageProps { 4 | key: string 5 | defaultValue: T 6 | } 7 | 8 | export default function useLocalStorage({ 9 | key, 10 | defaultValue, 11 | }: LocalStorageProps) { 12 | const [value, setValue] = useState(() => { 13 | const storedValue = localStorage.getItem(key) 14 | return storedValue !== null ? (JSON.parse(storedValue) as T) : defaultValue 15 | }) 16 | 17 | useEffect(() => { 18 | localStorage.setItem(key, JSON.stringify(value)) 19 | }, [value, key]) 20 | 21 | return [value, setValue] as const 22 | } 23 | -------------------------------------------------------------------------------- /src/components/app-shell.tsx: -------------------------------------------------------------------------------- 1 | import { Outlet } from 'react-router-dom' 2 | import Sidebar from './sidebar' 3 | import useIsCollapsed from '@/hooks/use-is-collapsed' 4 | 5 | export default function AppShell() { 6 | const [isCollapsed, setIsCollapsed] = useIsCollapsed() 7 | return ( 8 |
9 | 10 |
14 | 15 |
16 |
17 | ) 18 | } 19 | -------------------------------------------------------------------------------- /src/pages/errors/maintenance-error.tsx: -------------------------------------------------------------------------------- 1 | import { Button } from '@/components/custom/button' 2 | 3 | export default function MaintenanceError() { 4 | return ( 5 |
6 |
7 |

503

8 | Website is under maintenance! 9 |

10 | The site is not available at the moment.
11 | We'll be back online shortly. 12 |

13 |
14 | 15 |
16 |
17 |
18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /src/components/ui/label.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | import * as LabelPrimitive from "@radix-ui/react-label" 3 | import { cva, type VariantProps } from "class-variance-authority" 4 | 5 | import { cn } from "@/lib/utils" 6 | 7 | const labelVariants = cva( 8 | "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" 9 | ) 10 | 11 | const Label = React.forwardRef< 12 | React.ElementRef, 13 | React.ComponentPropsWithoutRef & 14 | VariantProps 15 | >(({ className, ...props }, ref) => ( 16 | 21 | )) 22 | Label.displayName = LabelPrimitive.Root.displayName 23 | 24 | export { Label } 25 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "useDefineForClassFields": true, 5 | "lib": ["ES2020", "DOM", "DOM.Iterable"], 6 | "module": "ESNext", 7 | "skipLibCheck": true, 8 | 9 | /* Bundler mode */ 10 | "moduleResolution": "bundler", 11 | "allowImportingTsExtensions": true, 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "noEmit": true, 15 | "jsx": "react-jsx", 16 | 17 | /* Alias */ 18 | "baseUrl": ".", 19 | "paths": { 20 | "@/*": ["./src/*"], 21 | }, 22 | 23 | /* Linting */ 24 | "strict": true, 25 | "noUnusedLocals": true, 26 | "noUnusedParameters": true, 27 | "noFallthroughCasesInSwitch": true, 28 | }, 29 | "include": ["src"], 30 | "references": [{ "path": "./tsconfig.node.json" }], 31 | } 32 | -------------------------------------------------------------------------------- /src/pages/settings/components/content-section.tsx: -------------------------------------------------------------------------------- 1 | import { Separator } from '@/components/ui/separator' 2 | 3 | interface ContentSectionProps { 4 | title: string 5 | desc: string 6 | children: JSX.Element 7 | } 8 | 9 | export default function ContentSection({ 10 | title, 11 | desc, 12 | children, 13 | }: ContentSectionProps) { 14 | return ( 15 |
16 |
17 |

{title}

18 |

{desc}

19 |
20 | 21 |
22 |
{children}
23 |
24 |
25 | ) 26 | } 27 | -------------------------------------------------------------------------------- /src/components/ui/textarea.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | 3 | import { cn } from "@/lib/utils" 4 | 5 | export interface TextareaProps 6 | extends React.TextareaHTMLAttributes {} 7 | 8 | const Textarea = React.forwardRef( 9 | ({ className, ...props }, ref) => { 10 | return ( 11 |