@betterstart/cli 0.1.81 → 0.1.83

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/dist/cli.js +176 -305
  2. package/dist/cli.js.map +1 -1
  3. package/package.json +1 -1
  4. package/templates/init/components/data-table/data-table.tsx +1 -1
  5. package/templates/init/components/layout/cms-search.tsx +6 -5
  6. package/templates/init/components/layout/cms-sidebar.tsx +3 -7
  7. package/templates/init/components/shared/page-header.tsx +5 -5
  8. package/templates/init/data/navigation.ts +6 -6
  9. package/templates/init/lib/actions/profile.ts +4 -0
  10. package/templates/init/lib/auth/auth.ts +17 -0
  11. package/templates/init/pages/dashboard-page.tsx +1 -1
  12. package/templates/init/pages/forgot-password-form.tsx +130 -0
  13. package/templates/init/pages/forgot-password-page.tsx +20 -0
  14. package/templates/init/pages/login-form.tsx +17 -1
  15. package/templates/init/pages/login-page.tsx +12 -2
  16. package/templates/init/pages/profile/profile-form.tsx +65 -137
  17. package/templates/init/pages/reset-password-form.tsx +159 -0
  18. package/templates/init/pages/reset-password-page.tsx +20 -0
  19. package/templates/init/pages/users/columns.tsx +13 -10
  20. package/templates/init/pages/users/users-page-content.tsx +9 -2
  21. package/templates/init/pages/users/users-page.tsx +1 -1
  22. package/templates/init/pages/users/users-table.tsx +2 -2
  23. package/templates/ui/badge.tsx +2 -2
  24. package/templates/ui/button.tsx +2 -2
  25. package/templates/ui/card.tsx +2 -2
  26. package/templates/ui/curriculum-editor.tsx +2 -2
  27. package/templates/ui/image-upload-field.tsx +2 -2
  28. package/templates/ui/input.tsx +5 -4
  29. package/templates/ui/media-upload-field.tsx +2 -2
  30. package/templates/ui/placeholder.tsx +1 -1
  31. package/templates/ui/sidebar.tsx +3 -3
  32. package/templates/ui/table.tsx +10 -4
  33. package/templates/ui/video-upload-field.tsx +2 -2
@@ -0,0 +1,159 @@
1
+ 'use client'
2
+
3
+ import { authClient } from '@cms/auth/client'
4
+ import { Button } from '@cms/components/ui/button'
5
+ import { Card, CardContent } from '@cms/components/ui/card'
6
+ import { Field, FieldGroup, FieldLabel } from '@cms/components/ui/field'
7
+ import { Input } from '@cms/components/ui/input'
8
+ import { cn } from '@cms/utils/cn'
9
+ import { LoaderCircle } from 'lucide-react'
10
+ import Link from 'next/link'
11
+ import { useRouter, useSearchParams } from 'next/navigation'
12
+ import * as React from 'react'
13
+
14
+ export function ResetPasswordForm({
15
+ className,
16
+ ...props
17
+ }: React.ComponentProps<'div'>) {
18
+ const router = useRouter()
19
+ const searchParams = useSearchParams()
20
+ const token = searchParams.get('token')
21
+
22
+ const [newPassword, setNewPassword] = React.useState('')
23
+ const [confirmPassword, setConfirmPassword] = React.useState('')
24
+ const [error, setError] = React.useState<string | null>(null)
25
+ const [isPending, startTransition] = React.useTransition()
26
+
27
+ if (!token) {
28
+ return (
29
+ <div className={cn('flex flex-col gap-6', className)} {...props}>
30
+ <Card className="overflow-hidden p-0">
31
+ <CardContent className="grid p-0 md:grid-cols-[5fr_7fr]">
32
+ <div className="relative hidden bg-muted md:block">
33
+ <img
34
+ src="https://assets.betterstart.dev/assets/placeholder.png"
35
+ alt="Image"
36
+ className="absolute inset-0 h-full w-full object-cover dark:brightness-[0.2] dark:grayscale"
37
+ />
38
+ </div>
39
+ <div className="p-6 md:p-20">
40
+ <FieldGroup className="pb-12 gap-10">
41
+ <div className="flex flex-col items-start">
42
+ <h1 className="text-xl font-medium">Invalid reset link</h1>
43
+ <p className="text-balance text-muted-foreground">
44
+ This password reset link is invalid or has expired. Please
45
+ request a new one.
46
+ </p>
47
+ </div>
48
+ <Link
49
+ href="/cms/forgot-password"
50
+ className="text-sm underline-offset-4 hover:underline"
51
+ >
52
+ Request a new reset link
53
+ </Link>
54
+ </FieldGroup>
55
+ </div>
56
+ </CardContent>
57
+ </Card>
58
+ </div>
59
+ )
60
+ }
61
+
62
+ const handleSubmit = (e: React.FormEvent) => {
63
+ e.preventDefault()
64
+ setError(null)
65
+
66
+ if (newPassword !== confirmPassword) {
67
+ setError('Passwords do not match')
68
+ return
69
+ }
70
+
71
+ if (newPassword.length < 8) {
72
+ setError('Password must be at least 8 characters')
73
+ return
74
+ }
75
+
76
+ startTransition(async () => {
77
+ try {
78
+ const { error } = await authClient.resetPassword({
79
+ newPassword,
80
+ token,
81
+ })
82
+ if (error) {
83
+ setError(error.message || 'Failed to reset password')
84
+ return
85
+ }
86
+ router.push('/cms/login?reset=success')
87
+ } catch {
88
+ setError('An error occurred. Please try again.')
89
+ }
90
+ })
91
+ }
92
+
93
+ return (
94
+ <div className={cn('flex flex-col gap-6', className)} {...props}>
95
+ <Card className="overflow-hidden p-0">
96
+ <CardContent className="grid p-0 md:grid-cols-[5fr_7fr]">
97
+ <div className="relative hidden bg-muted md:block">
98
+ <img
99
+ src="https://assets.betterstart.dev/assets/placeholder.png"
100
+ alt="Image"
101
+ className="absolute inset-0 h-full w-full object-cover dark:brightness-[0.2] dark:grayscale"
102
+ />
103
+ </div>
104
+ <form onSubmit={handleSubmit} className="p-6 md:p-20">
105
+ <FieldGroup className="pb-12 gap-10">
106
+ <div className="flex flex-col items-start">
107
+ <h1 className="text-xl font-medium">Reset password</h1>
108
+ <p className="text-balance text-muted-foreground">
109
+ Enter your new password below
110
+ </p>
111
+ </div>
112
+ {error ? (
113
+ <div className="bg-destructive/10 text-destructive text-sm p-3 rounded-md">
114
+ {error}
115
+ </div>
116
+ ) : null}
117
+ <div className="flex flex-col gap-4">
118
+ <Field>
119
+ <FieldLabel htmlFor="newPassword">New Password</FieldLabel>
120
+ <Input
121
+ id="newPassword"
122
+ type="password"
123
+ autoComplete="new-password"
124
+ placeholder="Enter new password"
125
+ value={newPassword}
126
+ onChange={(e) => setNewPassword(e.target.value)}
127
+ required
128
+ disabled={isPending}
129
+ />
130
+ </Field>
131
+ <Field>
132
+ <FieldLabel htmlFor="confirmPassword">
133
+ Confirm Password
134
+ </FieldLabel>
135
+ <Input
136
+ id="confirmPassword"
137
+ type="password"
138
+ autoComplete="new-password"
139
+ placeholder="Confirm new password"
140
+ value={confirmPassword}
141
+ onChange={(e) => setConfirmPassword(e.target.value)}
142
+ required
143
+ disabled={isPending}
144
+ />
145
+ </Field>
146
+ <Field className="pt-4">
147
+ <Button type="submit" disabled={isPending}>
148
+ {isPending && <LoaderCircle className="animate-spin" />}
149
+ {isPending ? 'Resetting...' : 'Reset Password'}
150
+ </Button>
151
+ </Field>
152
+ </div>
153
+ </FieldGroup>
154
+ </form>
155
+ </CardContent>
156
+ </Card>
157
+ </div>
158
+ )
159
+ }
@@ -0,0 +1,20 @@
1
+ import type { Metadata } from 'next'
2
+ import { Suspense } from 'react'
3
+ import { ResetPasswordForm } from './reset-password-form'
4
+
5
+ export const metadata: Metadata = {
6
+ title: 'Reset Password',
7
+ robots: { index: false, follow: false },
8
+ }
9
+
10
+ export default function ResetPasswordPage() {
11
+ return (
12
+ <div className="flex min-h-svh flex-col items-center justify-center bg-background p-6 md:p-10">
13
+ <div className="w-full max-w-sm md:max-w-4xl">
14
+ <Suspense>
15
+ <ResetPasswordForm />
16
+ </Suspense>
17
+ </div>
18
+ </div>
19
+ )
20
+ }
@@ -12,7 +12,7 @@ import {
12
12
  AlertDialogTitle,
13
13
  AlertDialogTrigger,
14
14
  } from '@cms/components/ui/alert-dialog'
15
- import { Avatar, AvatarFallback } from '@cms/components/ui/avatar'
15
+ import { Avatar, AvatarFallback, AvatarImage } from '@cms/components/ui/avatar'
16
16
  import { Badge } from '@cms/components/ui/badge'
17
17
  import { Button } from '@cms/components/ui/button'
18
18
  import {
@@ -26,7 +26,7 @@ import {
26
26
  import type { UserData } from '@cms/types/auth'
27
27
  import { useQueryClient } from '@tanstack/react-query'
28
28
  import type { ColumnDef } from '@tanstack/react-table'
29
- import { ArrowUpDown, Edit, MoreHorizontal, Trash } from 'lucide-react'
29
+ import { ArrowUpDown, Edit, MoreHorizontal, ShieldCheck, Trash } from 'lucide-react'
30
30
  import React from 'react'
31
31
  import { toast } from 'sonner'
32
32
  import { EditRoleDialog } from './edit-role-dialog'
@@ -117,10 +117,10 @@ export const columns: ColumnDef<UserData>[] = [
117
117
  <Button
118
118
  variant="ghost"
119
119
  onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
120
- className="hover:bg-muted/50 px-0!"
120
+ className="px-0 text-muted-foreground hover:text-foreground w-full hover:bg-transparent justify-start"
121
121
  >
122
122
  User
123
- <ArrowUpDown className="size-4" />
123
+ <ArrowUpDown className="size-3" />
124
124
  </Button>
125
125
  ),
126
126
  cell: ({ row }) => {
@@ -145,8 +145,9 @@ export const columns: ColumnDef<UserData>[] = [
145
145
  cell: ({ row }) => {
146
146
  const verified = row.getValue('emailVerified') as boolean
147
147
  return (
148
- <Badge variant={verified ? 'outline' : 'secondary'}>
149
- {verified ? 'Verified' : 'Unverified'}
148
+ <Badge variant="outline">
149
+
150
+ {verified ? <span className="flex items-center gap-1"><ShieldCheck className="size-3.5" />Verified</span> : <span className="flex items-center gap-1"><ShieldCheck className="size-3.5" />Unverified</span>}
150
151
  </Badge>
151
152
  )
152
153
  },
@@ -174,8 +175,10 @@ export const columns: ColumnDef<UserData>[] = [
174
175
  userName={row.original.name}
175
176
  >
176
177
  <Badge variant="outline" className="capitalize cursor-pointer">
177
- {role}
178
- <Edit className="size-3 ml-1" strokeWidth={2} />
178
+ <span className="flex items-center gap-1">
179
+ {role}
180
+ <Edit className="size-3" />
181
+ </span>
179
182
  </Badge>
180
183
  </EditRoleDialog>
181
184
  )
@@ -187,10 +190,10 @@ export const columns: ColumnDef<UserData>[] = [
187
190
  <Button
188
191
  variant="ghost"
189
192
  onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
190
- className="hover:bg-muted/50"
193
+ className="px-0 text-muted-foreground hover:text-foreground w-full hover:bg-transparent justify-start"
191
194
  >
192
195
  Joined
193
- <ArrowUpDown className="size-4" />
196
+ <ArrowUpDown className="size-3" />
194
197
  </Button>
195
198
  ),
196
199
  cell: ({ row }) => {
@@ -1,8 +1,12 @@
1
1
  'use client'
2
2
 
3
+ import React from 'react'
3
4
  import type { ColumnDef } from '@tanstack/react-table'
5
+ import { ChevronLeft } from 'lucide-react'
6
+ import { useRouter } from 'next/navigation'
4
7
  import { PageHeader } from '@cms/components/shared/page-header'
5
8
  import type { UserData } from '@cms/types/auth'
9
+ import { Button } from '@cms/components/ui/button'
6
10
  import { CreateUserDialog } from './create-user-dialog'
7
11
  import { UsersTable } from './users-table'
8
12
 
@@ -11,10 +15,13 @@ interface UsersPageContentProps<TValue> {
11
15
  }
12
16
 
13
17
  export function UsersPageContent<TValue>({ columns }: UsersPageContentProps<TValue>) {
18
+ const router = useRouter()
19
+
14
20
  return (
15
- <>
21
+ <React.Fragment>
16
22
  <PageHeader
17
23
  title="Users"
24
+ back={<Button variant="ghost" size="icon" onClick={() => router.back()}><ChevronLeft /></Button>}
18
25
  actions={
19
26
  <div className="flex items-center gap-2">
20
27
  <CreateUserDialog />
@@ -24,6 +31,6 @@ export function UsersPageContent<TValue>({ columns }: UsersPageContentProps<TVal
24
31
  <main className="space-y-6 p-6">
25
32
  <UsersTable columns={columns} />
26
33
  </main>
27
- </>
34
+ </React.Fragment>
28
35
  )
29
36
  }
@@ -11,7 +11,7 @@ export default function UsersPage() {
11
11
  </div>
12
12
  }
13
13
  >
14
- <div className="flex flex-col">
14
+ <div className="flex flex-col pt-14">
15
15
  <UsersPageContent columns={columns} />
16
16
  </div>
17
17
  </React.Suspense>
@@ -126,7 +126,7 @@ export function UsersTable<TValue>({ columns }: UsersTableProps<TValue>) {
126
126
  <div className="space-y-6">
127
127
  <div className="bg-card border overflow-hidden rounded-lg">
128
128
  <Table>
129
- <TableHeader className="bg-secondary">
129
+ <TableHeader>
130
130
  {table.getHeaderGroups().map((headerGroup) => (
131
131
  <TableRow key={headerGroup.id}>
132
132
  {headerGroup.headers.map((header) => (
@@ -180,7 +180,7 @@ export function UsersTable<TValue>({ columns }: UsersTableProps<TValue>) {
180
180
  value={pageSize === -1 ? 'all' : String(pageSize)}
181
181
  onValueChange={handlePageSizeChange}
182
182
  >
183
- <SelectTrigger className="w-[100px] h-8">
183
+ <SelectTrigger className="w-25 h-8">
184
184
  <SelectValue />
185
185
  </SelectTrigger>
186
186
  <SelectContent>
@@ -4,12 +4,12 @@ import { Slot } from 'radix-ui'
4
4
  import type * as React from 'react'
5
5
 
6
6
  const badgeVariants = cva(
7
- 'h-5 gap-1 rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium transition-all has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&>svg]:size-3! inline-flex items-center justify-center w-fit whitespace-nowrap shrink-0 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive overflow-hidden group/badge',
7
+ 'h-6 gap-1 rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium transition-all has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&>svg]:size-3! inline-flex items-center justify-center w-fit whitespace-nowrap shrink-0 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive overflow-hidden group/badge',
8
8
  {
9
9
  variants: {
10
10
  variant: {
11
11
  default: 'bg-primary text-primary-foreground [a]:hover:bg-primary/80',
12
- secondary: 'bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80',
12
+ secondary: 'bg-secondary border-border text-secondary-foreground [a]:hover:bg-secondary/80',
13
13
  destructive:
14
14
  'bg-destructive/10 [a]:hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 text-destructive dark:bg-destructive/20',
15
15
  outline: 'border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground',
@@ -11,7 +11,7 @@ const buttonVariants = cva(
11
11
  variant: {
12
12
  default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80",
13
13
  outline:
14
- "border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",
14
+ "border-border bg-white hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",
15
15
  secondary:
16
16
  "bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
17
17
  ghost:
@@ -22,7 +22,7 @@ const buttonVariants = cva(
22
22
  },
23
23
  size: {
24
24
  default:
25
- "h-10 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
25
+ "h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
26
26
  xs: "h-7 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",
27
27
  sm: "h-9 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5",
28
28
  lg: "h-12 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3",
@@ -12,7 +12,7 @@ function Card({
12
12
  data-slot="card"
13
13
  data-size={size}
14
14
  className={cn(
15
- "group/card flex flex-col gap-6 overflow-hidden rounded-xl bg-card py-6 text-sm text-card-foreground has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:gap-3 data-[size=sm]:py-3 data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl material-md",
15
+ "group/card flex flex-col gap-6 overflow-hidden rounded bg-card py-6 text-sm text-card-foreground has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:gap-3 data-[size=sm]:py-3 data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t *:[img:last-child]:rounded-b material-sm",
16
16
  className
17
17
  )}
18
18
  {...props}
@@ -84,7 +84,7 @@ function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
84
84
  <div
85
85
  data-slot="card-footer"
86
86
  className={cn(
87
- "flex items-center border-t bg-muted/50 px-6 pt-4 pb-4.5 group-data-[size=sm]/card:p-3",
87
+ "flex items-center border-t bg-background px-6 pt-4 pb-4.5 group-data-[size=sm]/card:p-3",
88
88
  className
89
89
  )}
90
90
  {...props}
@@ -296,7 +296,7 @@ const SequentialEditor = ({
296
296
  >
297
297
  {items.map((item, index) => (
298
298
  <AccordionItem key={index} value={`item-${index + 1}`} className="p-0 border-none">
299
- <div className="space-y-5 rounded-lg border p-4 bg-secondary/50 corner-squircle [&_h3]:m-0 w-full">
299
+ <div className="space-y-5 rounded-lg border p-4 bg-background corner-squircle [&_h3]:m-0 w-full">
300
300
  <AccordionTrigger className="flex items-center p-0 justify-between w-full">
301
301
  <div className="flex w-full items-center justify-between">
302
302
  <h4 className="text-sm font-medium w-full">
@@ -438,7 +438,7 @@ const WeeklyEditor = ({
438
438
  value={`week-${weekIndex + 1}`}
439
439
  className="p-0 border-none"
440
440
  >
441
- <div className="space-y-5 rounded-lg border p-4 bg-secondary/50 corner-squircle [&_h3]:m-0 w-full">
441
+ <div className="space-y-5 rounded-lg border p-4 bg-background corner-squircle [&_h3]:m-0 w-full">
442
442
  <AccordionTrigger className="flex items-center p-0 justify-between w-full">
443
443
  <div className="flex w-full items-center justify-between">
444
444
  <div className="flex flex-col items-start">
@@ -277,7 +277,7 @@ export function ImageUploadField({
277
277
 
278
278
  {/* Preview or Upload Area */}
279
279
  {displayPreview ? (
280
- <div className="relative w-full rounded-lg corner-squircle border border-dashed border-border bg-secondary h-50 flex items-center justify-center p-10 group">
280
+ <div className="relative w-full rounded-lg corner-squircle border border-dashed border-border bg-background h-50 flex items-center justify-center p-10 group">
281
281
  <img
282
282
  src={displayPreview}
283
283
  alt="Preview"
@@ -320,7 +320,7 @@ export function ImageUploadField({
320
320
  onClick={handleClick}
321
321
  disabled={disabled || isUploading}
322
322
  className={cn(
323
- 'w-full rounded-lg corner-squircle border border-dashed border-border bg-secondary h-50 flex items-center justify-center p-10 group',
323
+ 'w-full rounded-lg corner-squircle border border-dashed border-border bg-background h-50 flex items-center justify-center p-10 group',
324
324
  'hover:border-primary/50 transition-colors',
325
325
  'flex flex-col items-center justify-center gap-2 p-8',
326
326
  'disabled:opacity-50 disabled:cursor-not-allowed'
@@ -1,13 +1,14 @@
1
- import { cn } from '@cms/utils/cn'
2
- import type * as React from 'react'
1
+ import * as React from "react"
3
2
 
4
- function Input({ className, type, ...props }: React.ComponentProps<'input'>) {
3
+ import { cn } from "@cms/utils/cn"
4
+
5
+ function Input({ className, type, ...props }: React.ComponentProps<"input">) {
5
6
  return (
6
7
  <input
7
8
  type={type}
8
9
  data-slot="input"
9
10
  className={cn(
10
- 'dark:bg-input/30 border-input focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 disabled:bg-input/50 dark:disabled:bg-input/80 file:text-foreground placeholder:text-muted-foreground h-10 w-full min-w-0 rounded-lg border bg-transparent px-2.5 py-1 text-base transition-colors outline-none file:inline-flex file:h-6 file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:ring-3 disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:ring-3 md:text-sm',
11
+ "h-9 w-full min-w-0 rounded-lg border border-input bg-transparent px-2.5 py-1 text-base transition-colors outline-none file:inline-flex file:h-6 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-not-allowed disabled:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40",
11
12
  className
12
13
  )}
13
14
  {...props}
@@ -209,7 +209,7 @@ export function MediaUploadField({
209
209
 
210
210
  {/* Preview or Upload Area */}
211
211
  {previewUrl ? (
212
- <div className="relative w-full rounded-lg corner-squircle border border-dashed border-border bg-secondary/50 group">
212
+ <div className="relative w-full rounded-lg corner-squircle border border-dashed border-border bg-background group">
213
213
  {mediaType === 'video' ? (
214
214
  <video
215
215
  src={previewUrl}
@@ -265,7 +265,7 @@ export function MediaUploadField({
265
265
  onClick={handleClick}
266
266
  disabled={disabled || isUploading}
267
267
  className={cn(
268
- 'w-full rounded-lg corner-squircle border border-dashed border-border bg-secondary/50',
268
+ 'w-full rounded-lg corner-squircle border border-dashed border-border bg-background',
269
269
  'hover:border-primary/50 transition-colors',
270
270
  'flex flex-col items-center justify-center gap-2 p-8',
271
271
  'disabled:opacity-50 disabled:cursor-not-allowed'
@@ -12,7 +12,7 @@ export function Placeholder({ label, description, action, className, ...props }:
12
12
  return (
13
13
  <div
14
14
  className={cn(
15
- 'border flex items-center flex-col gap-2 border-dashed border-border rounded-lg corner-squircle p-8 bg-secondary/50',
15
+ 'border flex items-center flex-col gap-2 border-dashed border-border rounded-lg corner-squircle p-8 bg-background',
16
16
  className
17
17
  )}
18
18
  {...props}
@@ -160,7 +160,7 @@ function Sidebar({
160
160
  <div
161
161
  data-slot="sidebar"
162
162
  className={cn(
163
- 'bg-sidebar text-sidebar-foreground flex h-full w-(--sidebar-width) flex-col',
163
+ 'bg-sidebar text-sidebar-foreground flex h-full w-(--sidebar-width) flex-col relative z-11',
164
164
  className
165
165
  )}
166
166
  {...props}
@@ -198,7 +198,7 @@ function Sidebar({
198
198
 
199
199
  return (
200
200
  <div
201
- className="group peer text-sidebar-foreground hidden md:block"
201
+ className="group peer text-sidebar-foreground hidden md:block z-11 relative"
202
202
  data-state={state}
203
203
  data-collapsible={state === 'collapsed' ? collapsible : ''}
204
204
  data-variant={variant}
@@ -454,7 +454,7 @@ const sidebarMenuButtonVariants = cva(
454
454
  'bg-background hover:bg-sidebar-accent hover:text-sidebar-primary shadow-[0_0_0_1px_hsl(var(--sidebar-border))] hover:shadow-[0_0_0_1px_hsl(var(--sidebar-accent))]'
455
455
  },
456
456
  size: {
457
- default: 'h-9 text-sm',
457
+ default: 'h-8 text-sm',
458
458
  sm: 'h-7 text-xs',
459
459
  lg: 'h-12 text-sm group-data-[collapsible=icon]:p-0!'
460
460
  }
@@ -16,7 +16,13 @@ function Table({ className, ...props }: React.ComponentProps<'table'>) {
16
16
  }
17
17
 
18
18
  function TableHeader({ className, ...props }: React.ComponentProps<'thead'>) {
19
- return <thead data-slot="table-header" className={cn('[&_tr]:border-b', className)} {...props} />
19
+ return (
20
+ <thead
21
+ data-slot="table-header"
22
+ className={cn('[&_tr]:border-b [&_tr:hover]:bg-transparent! bg-background [&_th]:text-muted-foreground', className)}
23
+ {...props}
24
+ />
25
+ )
20
26
  }
21
27
 
22
28
  function TableBody({ className, ...props }: React.ComponentProps<'tbody'>) {
@@ -33,7 +39,7 @@ function TableFooter({ className, ...props }: React.ComponentProps<'tfoot'>) {
33
39
  return (
34
40
  <tfoot
35
41
  data-slot="table-footer"
36
- className={cn('bg-muted/50 border-t font-medium [&>tr]:last:border-b-0', className)}
42
+ className={cn('bg-background border-t font-medium [&>tr]:last:border-b-0', className)}
37
43
  {...props}
38
44
  />
39
45
  )
@@ -44,7 +50,7 @@ function TableRow({ className, ...props }: React.ComponentProps<'tr'>) {
44
50
  <tr
45
51
  data-slot="table-row"
46
52
  className={cn(
47
- 'hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors',
53
+ 'hover:bg-background data-[state=selected]:bg-background border-b transition-colors',
48
54
  className
49
55
  )}
50
56
  {...props}
@@ -69,7 +75,7 @@ function TableCell({ className, ...props }: React.ComponentProps<'td'>) {
69
75
  return (
70
76
  <td
71
77
  data-slot="table-cell"
72
- className={cn('px-4 py-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0', className)}
78
+ className={cn('px-4 py-3.5 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0', className)}
73
79
  {...props}
74
80
  />
75
81
  )
@@ -283,7 +283,7 @@ export function VideoUploadField({
283
283
 
284
284
  {/* Preview or Upload Area */}
285
285
  {displayPreview ? (
286
- <div className="relative w-full rounded-lg corner-squircle border border-dashed border-border bg-secondary h-50 flex items-center justify-center p-10 group overflow-hidden">
286
+ <div className="relative w-full rounded-lg corner-squircle border border-dashed border-border bg-background h-50 flex items-center justify-center p-10 group overflow-hidden">
287
287
  <video
288
288
  src={displayPreview}
289
289
  controls
@@ -328,7 +328,7 @@ export function VideoUploadField({
328
328
  onClick={handleClick}
329
329
  disabled={disabled || isUploading}
330
330
  className={cn(
331
- 'w-full rounded-lg corner-squircle border border-dashed border-border bg-secondary/50',
331
+ 'w-full rounded-lg corner-squircle border border-dashed border-border bg-background',
332
332
  'hover:border-primary/50 transition-colors',
333
333
  'flex flex-col items-center justify-center gap-2 p-8',
334
334
  'disabled:opacity-50 disabled:cursor-not-allowed'