@blips/ui 0.0.1 → 2.0.0

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 (60) hide show
  1. package/dist/index.cjs +4308 -2010
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.cts +435 -411
  4. package/dist/index.d.ts +435 -411
  5. package/dist/index.js +4244 -2008
  6. package/dist/index.js.map +1 -1
  7. package/package.json +18 -4
  8. package/src/components/accordion.tsx +58 -48
  9. package/src/components/alert-dialog.tsx +170 -112
  10. package/src/components/alert.tsx +49 -42
  11. package/src/components/aspect-ratio.tsx +9 -3
  12. package/src/components/avatar.tsx +109 -50
  13. package/src/components/badge.tsx +29 -17
  14. package/src/components/breadcrumb.tsx +81 -87
  15. package/src/components/button-group.tsx +83 -0
  16. package/src/components/button.tsx +40 -32
  17. package/src/components/calendar.tsx +49 -45
  18. package/src/components/card.tsx +77 -71
  19. package/src/components/carousel.tsx +150 -168
  20. package/src/components/chart.tsx +357 -0
  21. package/src/components/checkbox.tsx +28 -24
  22. package/src/components/collapsible.tsx +28 -6
  23. package/src/components/command.tsx +144 -110
  24. package/src/components/context-menu.tsx +220 -166
  25. package/src/components/dialog.tsx +131 -95
  26. package/src/components/drawer.tsx +105 -86
  27. package/src/components/dropdown-menu.tsx +234 -177
  28. package/src/components/form.tsx +167 -0
  29. package/src/components/hover-card.tsx +39 -22
  30. package/src/components/input-group.tsx +175 -0
  31. package/src/components/input-otp.tsx +56 -48
  32. package/src/components/input.tsx +18 -19
  33. package/src/components/kbd.tsx +28 -0
  34. package/src/components/label.tsx +20 -22
  35. package/src/components/menubar.tsx +221 -199
  36. package/src/components/navigation-menu.tsx +144 -102
  37. package/src/components/pagination.tsx +102 -91
  38. package/src/components/popover.tsx +86 -26
  39. package/src/components/progress.tsx +27 -24
  40. package/src/components/radio-group.tsx +28 -25
  41. package/src/components/resizable.tsx +42 -34
  42. package/src/components/scroll-area.tsx +54 -42
  43. package/src/components/select.tsx +165 -135
  44. package/src/components/separator.tsx +16 -17
  45. package/src/components/sheet.tsx +116 -113
  46. package/src/components/sidebar.tsx +726 -0
  47. package/src/components/skeleton.tsx +6 -8
  48. package/src/components/slider.tsx +60 -23
  49. package/src/components/sonner.tsx +25 -30
  50. package/src/components/spinner.tsx +16 -0
  51. package/src/components/switch.tsx +30 -22
  52. package/src/components/table.tsx +96 -97
  53. package/src/components/tabs.tsx +91 -53
  54. package/src/components/textarea.tsx +8 -12
  55. package/src/components/toggle-group.tsx +60 -37
  56. package/src/components/toggle.tsx +28 -24
  57. package/src/components/tooltip.tsx +50 -23
  58. package/src/globals.css +230 -68
  59. package/src/hooks/use-mobile.tsx +19 -0
  60. package/src/index.ts +105 -6
@@ -1,60 +1,83 @@
1
- "use client";
1
+ "use client"
2
2
 
3
- import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group";
4
- import type { VariantProps } from "class-variance-authority";
5
- import * as React from "react";
6
- import { toggleVariants } from "./toggle";
7
- import { cn } from "../lib/utils";
3
+ import * as React from "react"
4
+ import { type VariantProps } from "class-variance-authority"
5
+ import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group"
6
+
7
+ import { cn } from "../lib/utils"
8
+ import { toggleVariants } from "./toggle"
8
9
 
9
10
  const ToggleGroupContext = React.createContext<
10
- VariantProps<typeof toggleVariants>
11
+ VariantProps<typeof toggleVariants> & {
12
+ spacing?: number
13
+ }
11
14
  >({
12
15
  size: "default",
13
16
  variant: "default",
14
- });
15
-
16
- const ToggleGroup = React.forwardRef<
17
- React.ElementRef<typeof ToggleGroupPrimitive.Root>,
18
- React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Root> &
19
- VariantProps<typeof toggleVariants>
20
- >(({ className, variant, size, children, ...props }, ref) => (
21
- <ToggleGroupPrimitive.Root
22
- ref={ref}
23
- className={cn("flex items-center justify-center gap-1", className)}
24
- {...props}
25
- >
26
- <ToggleGroupContext.Provider value={{ variant, size }}>
27
- {children}
28
- </ToggleGroupContext.Provider>
29
- </ToggleGroupPrimitive.Root>
30
- ));
17
+ spacing: 0,
18
+ })
31
19
 
32
- ToggleGroup.displayName = ToggleGroupPrimitive.Root.displayName;
20
+ function ToggleGroup({
21
+ className,
22
+ variant,
23
+ size,
24
+ spacing = 0,
25
+ children,
26
+ ...props
27
+ }: React.ComponentProps<typeof ToggleGroupPrimitive.Root> &
28
+ VariantProps<typeof toggleVariants> & {
29
+ spacing?: number
30
+ }) {
31
+ return (
32
+ <ToggleGroupPrimitive.Root
33
+ data-slot="toggle-group"
34
+ data-variant={variant}
35
+ data-size={size}
36
+ data-spacing={spacing}
37
+ style={{ "--gap": spacing } as React.CSSProperties}
38
+ className={cn(
39
+ "group/toggle-group flex w-fit items-center gap-[--spacing(var(--gap))] rounded-md data-[spacing=default]:data-[variant=outline]:shadow-xs",
40
+ className
41
+ )}
42
+ {...props}
43
+ >
44
+ <ToggleGroupContext.Provider value={{ variant, size, spacing }}>
45
+ {children}
46
+ </ToggleGroupContext.Provider>
47
+ </ToggleGroupPrimitive.Root>
48
+ )
49
+ }
33
50
 
34
- const ToggleGroupItem = React.forwardRef<
35
- React.ElementRef<typeof ToggleGroupPrimitive.Item>,
36
- React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Item> &
37
- VariantProps<typeof toggleVariants>
38
- >(({ className, children, variant, size, ...props }, ref) => {
39
- const context = React.useContext(ToggleGroupContext);
51
+ function ToggleGroupItem({
52
+ className,
53
+ children,
54
+ variant,
55
+ size,
56
+ ...props
57
+ }: React.ComponentProps<typeof ToggleGroupPrimitive.Item> &
58
+ VariantProps<typeof toggleVariants>) {
59
+ const context = React.useContext(ToggleGroupContext)
40
60
 
41
61
  return (
42
62
  <ToggleGroupPrimitive.Item
43
- ref={ref}
63
+ data-slot="toggle-group-item"
64
+ data-variant={context.variant || variant}
65
+ data-size={context.size || size}
66
+ data-spacing={context.spacing}
44
67
  className={cn(
45
68
  toggleVariants({
46
69
  variant: context.variant || variant,
47
70
  size: context.size || size,
48
71
  }),
72
+ "w-auto min-w-0 shrink-0 px-3 focus:z-10 focus-visible:z-10",
73
+ "data-[spacing=0]:rounded-none data-[spacing=0]:shadow-none data-[spacing=0]:first:rounded-l-md data-[spacing=0]:last:rounded-r-md data-[spacing=0]:data-[variant=outline]:border-l-0 data-[spacing=0]:data-[variant=outline]:first:border-l",
49
74
  className
50
75
  )}
51
76
  {...props}
52
77
  >
53
78
  {children}
54
79
  </ToggleGroupPrimitive.Item>
55
- );
56
- });
57
-
58
- ToggleGroupItem.displayName = ToggleGroupPrimitive.Item.displayName;
80
+ )
81
+ }
59
82
 
60
- export { ToggleGroup, ToggleGroupItem };
83
+ export { ToggleGroup, ToggleGroupItem }
@@ -1,22 +1,24 @@
1
- import * as TogglePrimitive from "@radix-ui/react-toggle";
2
- import { cva, type VariantProps } from "class-variance-authority";
3
- import * as React from "react";
1
+ "use client"
4
2
 
5
- import { cn } from "../lib/utils";
3
+ import * as React from "react"
4
+ import { cva, type VariantProps } from "class-variance-authority"
5
+ import * as TogglePrimitive from "@radix-ui/react-toggle"
6
+
7
+ import { cn } from "../lib/utils"
6
8
 
7
9
  const toggleVariants = cva(
8
- "inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 gap-2",
10
+ "inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-[color,box-shadow] outline-none hover:bg-muted hover:text-muted-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
9
11
  {
10
12
  variants: {
11
13
  variant: {
12
14
  default: "bg-transparent",
13
15
  outline:
14
- "border border-input bg-transparent hover:bg-accent hover:text-accent-foreground",
16
+ "border border-input bg-transparent shadow-xs hover:bg-accent hover:text-accent-foreground",
15
17
  },
16
18
  size: {
17
- default: "h-10 px-3 min-w-10",
18
- sm: "h-9 px-2.5 min-w-9",
19
- lg: "h-11 px-5 min-w-11",
19
+ default: "h-9 min-w-9 px-2",
20
+ sm: "h-8 min-w-8 px-1.5",
21
+ lg: "h-10 min-w-10 px-2.5",
20
22
  },
21
23
  },
22
24
  defaultVariants: {
@@ -24,20 +26,22 @@ const toggleVariants = cva(
24
26
  size: "default",
25
27
  },
26
28
  }
27
- );
28
-
29
- const Toggle = React.forwardRef<
30
- React.ElementRef<typeof TogglePrimitive.Root>,
31
- React.ComponentPropsWithoutRef<typeof TogglePrimitive.Root> &
32
- VariantProps<typeof toggleVariants>
33
- >(({ className, variant, size, ...props }, ref) => (
34
- <TogglePrimitive.Root
35
- ref={ref}
36
- className={cn(toggleVariants({ variant, size, className }))}
37
- {...props}
38
- />
39
- ));
29
+ )
40
30
 
41
- Toggle.displayName = TogglePrimitive.Root.displayName;
31
+ function Toggle({
32
+ className,
33
+ variant,
34
+ size,
35
+ ...props
36
+ }: React.ComponentProps<typeof TogglePrimitive.Root> &
37
+ VariantProps<typeof toggleVariants>) {
38
+ return (
39
+ <TogglePrimitive.Root
40
+ data-slot="toggle"
41
+ className={cn(toggleVariants({ variant, size, className }))}
42
+ {...props}
43
+ />
44
+ )
45
+ }
42
46
 
43
- export { Toggle, toggleVariants };
47
+ export { Toggle, toggleVariants }
@@ -1,30 +1,57 @@
1
- "use client";
1
+ "use client"
2
2
 
3
- import * as TooltipPrimitive from "@radix-ui/react-tooltip";
4
- import * as React from "react";
3
+ import * as React from "react"
4
+ import * as TooltipPrimitive from "@radix-ui/react-tooltip"
5
5
 
6
- import { cn } from "../lib/utils";
6
+ import { cn } from "../lib/utils"
7
7
 
8
- const TooltipProvider = TooltipPrimitive.Provider;
8
+ function TooltipProvider({
9
+ delayDuration = 0,
10
+ ...props
11
+ }: React.ComponentProps<typeof TooltipPrimitive.Provider>) {
12
+ return (
13
+ <TooltipPrimitive.Provider
14
+ data-slot="tooltip-provider"
15
+ delayDuration={delayDuration}
16
+ {...props}
17
+ />
18
+ )
19
+ }
9
20
 
10
- const Tooltip = TooltipPrimitive.Root;
21
+ function Tooltip({
22
+ ...props
23
+ }: React.ComponentProps<typeof TooltipPrimitive.Root>) {
24
+ return <TooltipPrimitive.Root data-slot="tooltip" {...props} />
25
+ }
11
26
 
12
- const TooltipTrigger = TooltipPrimitive.Trigger;
27
+ function TooltipTrigger({
28
+ ...props
29
+ }: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {
30
+ return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />
31
+ }
13
32
 
14
- const TooltipContent = React.forwardRef<
15
- React.ElementRef<typeof TooltipPrimitive.Content>,
16
- React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>
17
- >(({ className, sideOffset = 4, ...props }, ref) => (
18
- <TooltipPrimitive.Content
19
- ref={ref}
20
- sideOffset={sideOffset}
21
- className={cn(
22
- "z-50 overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-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 origin-[--radix-tooltip-content-transform-origin]",
23
- className
24
- )}
25
- {...props}
26
- />
27
- ));
28
- TooltipContent.displayName = TooltipPrimitive.Content.displayName;
33
+ function TooltipContent({
34
+ className,
35
+ sideOffset = 0,
36
+ children,
37
+ ...props
38
+ }: React.ComponentProps<typeof TooltipPrimitive.Content>) {
39
+ return (
40
+ <TooltipPrimitive.Portal>
41
+ <TooltipPrimitive.Content
42
+ data-slot="tooltip-content"
43
+ sideOffset={sideOffset}
44
+ className={cn(
45
+ "z-50 w-fit origin-(--radix-tooltip-content-transform-origin) animate-in rounded-md bg-foreground px-3 py-1.5 text-xs text-balance text-background fade-in-0 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 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
46
+ className
47
+ )}
48
+ {...props}
49
+ >
50
+ {children}
51
+ <TooltipPrimitive.Arrow className="z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px] bg-foreground fill-foreground" />
52
+ </TooltipPrimitive.Content>
53
+ </TooltipPrimitive.Portal>
54
+ )
55
+ }
29
56
 
30
- export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };
57
+ export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }
package/src/globals.css CHANGED
@@ -1,77 +1,239 @@
1
+ @import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Quicksand:wght@500;600;700&family=JetBrains+Mono:wght@400;500&display=swap");
1
2
  @import "tailwindcss";
3
+ @import "tw-animate-css";
4
+
5
+ /* Content sources — scan this package's own files and every app that
6
+ consumes it (shadcn monorepo pattern). Paths are relative to this file
7
+ (packages/ui/src/globals.css). */
8
+ @source "../**/*.{ts,tsx}";
9
+ @source "../../../apps/**/*.{ts,tsx}";
10
+
11
+ @custom-variant dark (&:is(.dark *));
12
+
13
+ /* ============================================================
14
+ Blips UI tokens — shadcn/ui neutral palette, with the Blips
15
+ brand yellow (#FCBA28) kept as the single `primary` accent.
16
+ ============================================================ */
17
+
18
+ @theme inline {
19
+ --color-background: var(--background);
20
+ --color-foreground: var(--foreground);
21
+ --color-card: var(--card);
22
+ --color-card-foreground: var(--card-foreground);
23
+ --color-popover: var(--popover);
24
+ --color-popover-foreground: var(--popover-foreground);
25
+ --color-primary: var(--primary);
26
+ --color-primary-foreground: var(--primary-foreground);
27
+ --color-secondary: var(--secondary);
28
+ --color-secondary-foreground: var(--secondary-foreground);
29
+ --color-muted: var(--muted);
30
+ --color-muted-foreground: var(--muted-foreground);
31
+ --color-accent: var(--accent);
32
+ --color-accent-foreground: var(--accent-foreground);
33
+ --color-destructive: var(--destructive);
34
+ --color-destructive-foreground: var(--destructive-foreground);
35
+ --color-warning: var(--warning);
36
+ --color-warning-foreground: var(--warning-foreground);
37
+ --color-success: var(--success);
38
+ --color-success-foreground: var(--success-foreground);
39
+ --color-info: var(--info);
40
+ --color-info-foreground: var(--info-foreground);
41
+ --color-border: var(--border);
42
+ --color-input: var(--input);
43
+ --color-ring: var(--ring);
44
+
45
+ --color-chart-1: var(--chart-1);
46
+ --color-chart-2: var(--chart-2);
47
+ --color-chart-3: var(--chart-3);
48
+ --color-chart-4: var(--chart-4);
49
+ --color-chart-5: var(--chart-5);
50
+
51
+ --color-sidebar: var(--sidebar);
52
+ --color-sidebar-foreground: var(--sidebar-foreground);
53
+ --color-sidebar-primary: var(--sidebar-primary);
54
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
55
+ --color-sidebar-accent: var(--sidebar-accent);
56
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
57
+ --color-sidebar-border: var(--sidebar-border);
58
+ --color-sidebar-ring: var(--sidebar-ring);
59
+
60
+ --color-surface: var(--surface);
61
+ --color-surface-foreground: var(--surface-foreground);
62
+ --color-code: var(--code);
63
+ --color-code-foreground: var(--code-foreground);
64
+ --color-code-highlight: var(--code-highlight);
65
+ --color-code-number: var(--code-number);
66
+ --color-selection: var(--selection);
67
+ --color-selection-foreground: var(--selection-foreground);
68
+
69
+ /* Extended radius scale (shadcn). */
70
+ --radius-sm: calc(var(--radius) - 4px);
71
+ --radius-md: calc(var(--radius) - 2px);
72
+ --radius-lg: var(--radius);
73
+ --radius-xl: calc(var(--radius) + 4px);
74
+ --radius-2xl: calc(var(--radius) + 8px);
75
+
76
+ --breakpoint-3xl: 1600px;
77
+ --breakpoint-4xl: 2000px;
78
+
79
+ --font-sans: var(--font-sans);
80
+ --font-mono: var(--font-mono);
81
+ --font-heading: var(--font-heading);
82
+ --font-display: var(--font-display);
83
+
84
+ --animate-accordion-down: accordion-down 0.2s ease-out;
85
+ --animate-accordion-up: accordion-up 0.2s ease-out;
86
+
87
+ @keyframes accordion-down {
88
+ from {
89
+ height: 0;
90
+ }
91
+ to {
92
+ height: var(--radix-accordion-content-height);
93
+ }
94
+ }
2
95
 
3
- @theme {
4
- --color-background: hsl(0 0% 100%);
5
- --color-foreground: hsl(240 10% 3.9%);
6
-
7
- --color-card: hsl(0 0% 100%);
8
- --color-card-foreground: hsl(240 10% 3.9%);
9
-
10
- --color-popover: hsl(0 0% 100%);
11
- --color-popover-foreground: hsl(240 10% 3.9%);
12
-
13
- --color-primary: hsl(240 5.9% 10%);
14
- --color-primary-foreground: hsl(0 0% 98%);
15
-
16
- --color-secondary: hsl(240 4.8% 95.9%);
17
- --color-secondary-foreground: hsl(240 5.9% 10%);
18
-
19
- --color-muted: hsl(240 4.8% 95.9%);
20
- --color-muted-foreground: hsl(240 3.8% 46.1%);
21
-
22
- --color-accent: hsl(240 4.8% 95.9%);
23
- --color-accent-foreground: hsl(240 5.9% 10%);
24
-
25
- --color-destructive: hsl(0 84.2% 60.2%);
26
- --color-destructive-foreground: hsl(0 0% 98%);
27
-
28
- --color-border: hsl(240 5.9% 90%);
29
- --color-input: hsl(240 5.9% 90%);
30
- --color-ring: hsl(240 5.9% 10%);
31
-
32
- --radius-sm: 0.25rem;
33
- --radius-md: 0.375rem;
34
- --radius-lg: 0.5rem;
35
- --radius-xl: 0.75rem;
96
+ @keyframes accordion-up {
97
+ from {
98
+ height: var(--radix-accordion-content-height);
99
+ }
100
+ to {
101
+ height: 0;
102
+ }
103
+ }
36
104
  }
37
105
 
38
- @media (prefers-color-scheme: dark) {
39
- @theme {
40
- --color-background: hsl(240 10% 3.9%);
41
- --color-foreground: hsl(0 0% 98%);
42
-
43
- --color-card: hsl(240 10% 3.9%);
44
- --color-card-foreground: hsl(0 0% 98%);
45
-
46
- --color-popover: hsl(240 10% 3.9%);
47
- --color-popover-foreground: hsl(0 0% 98%);
48
-
49
- --color-primary: hsl(0 0% 98%);
50
- --color-primary-foreground: hsl(240 5.9% 10%);
51
-
52
- --color-secondary: hsl(240 3.7% 15.9%);
53
- --color-secondary-foreground: hsl(0 0% 98%);
54
-
55
- --color-muted: hsl(240 3.7% 15.9%);
56
- --color-muted-foreground: hsl(240 5% 64.9%);
57
-
58
- --color-accent: hsl(240 3.7% 15.9%);
59
- --color-accent-foreground: hsl(0 0% 98%);
60
-
61
- --color-destructive: hsl(0 62.8% 30.6%);
62
- --color-destructive-foreground: hsl(0 0% 98%);
63
-
64
- --color-border: hsl(240 3.7% 15.9%);
65
- --color-input: hsl(240 3.7% 15.9%);
66
- --color-ring: hsl(240 4.9% 83.9%);
67
- }
106
+ /* ----- Light theme (default) — shadcn neutral + Blips yellow primary ----- */
107
+ :root {
108
+ --radius: 0.625rem;
109
+
110
+ --background: oklch(1 0 0);
111
+ --foreground: oklch(0% 0 0);
112
+ --card: oklch(1 0 0);
113
+ --card-foreground: oklch(0% 0 0);
114
+ --popover: oklch(1 0 0);
115
+ --popover-foreground: oklch(0% 0 0);
116
+
117
+ --primary: #fcba28; /* Amarelo Blips — único token de marca */
118
+ --primary-foreground: #000000;
119
+
120
+ --secondary: oklch(0.97 0 0);
121
+ --secondary-foreground: oklch(0.205 0 0);
122
+ --muted: oklch(0.97 0 0);
123
+ --muted-foreground: oklch(0.556 0 0);
124
+ --accent: oklch(0.97 0 0);
125
+ --accent-foreground: oklch(0.205 0 0);
126
+
127
+ --destructive: oklch(0.577 0.245 27.325);
128
+ --destructive-foreground: oklch(0.97 0.01 17);
129
+
130
+ --warning: oklch(0.828 0.189 84.429);
131
+ --warning-foreground: oklch(0.205 0 0);
132
+ --success: oklch(0.62 0.13 155);
133
+ --success-foreground: oklch(0.985 0 0);
134
+ --info: oklch(0.546 0.215 262.881);
135
+ --info-foreground: oklch(0.985 0 0);
136
+
137
+ --border: oklch(0.922 0 0);
138
+ --input: oklch(0.922 0 0);
139
+ --ring: oklch(0.708 0 0);
140
+
141
+ --chart-1: oklch(0.646 0.222 41.116);
142
+ --chart-2: oklch(0.6 0.118 184.704);
143
+ --chart-3: oklch(0.398 0.07 227.392);
144
+ --chart-4: oklch(0.828 0.189 84.429);
145
+ --chart-5: oklch(0.769 0.188 70.08);
146
+
147
+ --sidebar: oklch(0.985 0 0);
148
+ --sidebar-foreground: oklch(0% 0 0);
149
+ --sidebar-primary: #fcba28;
150
+ --sidebar-primary-foreground: #000000;
151
+ --sidebar-accent: oklch(0.97 0 0);
152
+ --sidebar-accent-foreground: oklch(0.205 0 0);
153
+ --sidebar-border: oklch(0.922 0 0);
154
+ --sidebar-ring: oklch(0.708 0 0);
155
+
156
+ --surface: oklch(0.98 0 0);
157
+ --surface-foreground: var(--foreground);
158
+ --code: var(--surface);
159
+ --code-foreground: var(--surface-foreground);
160
+ --code-highlight: oklch(0.96 0 0);
161
+ --code-number: oklch(0.56 0 0);
162
+ --selection: oklch(0% 0 0);
163
+ --selection-foreground: oklch(1 0 0);
164
+
165
+ --font-sans:
166
+ "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto,
167
+ sans-serif;
168
+ --font-heading: var(--font-sans);
169
+ --font-display: "Quicksand", var(--font-sans);
170
+ --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
68
171
  }
69
172
 
70
- * {
71
- border-color: var(--color-border);
173
+ /* ----- Dark theme — shadcn neutral + Blips yellow primary ----- */
174
+ .dark {
175
+ --background: oklch(0.145 0 0);
176
+ --foreground: oklch(0.985 0 0);
177
+ --card: oklch(0.205 0 0);
178
+ --card-foreground: oklch(0.985 0 0);
179
+ --popover: oklch(0.205 0 0);
180
+ --popover-foreground: oklch(0.985 0 0);
181
+
182
+ --primary: #fcba28;
183
+ --primary-foreground: #000000;
184
+
185
+ --secondary: oklch(0.269 0 0);
186
+ --secondary-foreground: oklch(0.985 0 0);
187
+ --muted: oklch(0.269 0 0);
188
+ --muted-foreground: oklch(0.708 0 0);
189
+ --accent: oklch(0.371 0 0);
190
+ --accent-foreground: oklch(0.985 0 0);
191
+
192
+ --destructive: oklch(0.704 0.191 22.216);
193
+ --destructive-foreground: oklch(0.58 0.22 27);
194
+
195
+ --warning: oklch(0.828 0.189 84.429);
196
+ --warning-foreground: oklch(0.205 0 0);
197
+ --success: oklch(0.7 0.14 155);
198
+ --success-foreground: oklch(0.205 0 0);
199
+ --info: oklch(0.707 0.165 254.624);
200
+ --info-foreground: oklch(0.205 0 0);
201
+
202
+ --border: oklch(1 0 0 / 10%);
203
+ --input: oklch(1 0 0 / 15%);
204
+ --ring: oklch(0.556 0 0);
205
+
206
+ --chart-1: oklch(0.488 0.243 264.376);
207
+ --chart-2: oklch(0.696 0.17 162.48);
208
+ --chart-3: oklch(0.769 0.188 70.08);
209
+ --chart-4: oklch(0.627 0.265 303.9);
210
+ --chart-5: oklch(0.645 0.246 16.439);
211
+
212
+ --sidebar: oklch(0.205 0 0);
213
+ --sidebar-foreground: oklch(0.985 0 0);
214
+ --sidebar-primary: #fcba28;
215
+ --sidebar-primary-foreground: #000000;
216
+ --sidebar-accent: oklch(0.269 0 0);
217
+ --sidebar-accent-foreground: oklch(0.985 0 0);
218
+ --sidebar-border: oklch(1 0 0 / 10%);
219
+ --sidebar-ring: oklch(0.439 0 0);
220
+
221
+ --surface: oklch(0.2 0 0);
222
+ --surface-foreground: oklch(0.708 0 0);
223
+ --code: var(--surface);
224
+ --code-foreground: var(--surface-foreground);
225
+ --code-highlight: oklch(0.27 0 0);
226
+ --code-number: oklch(0.72 0 0);
227
+ --selection: oklch(0.922 0 0);
228
+ --selection-foreground: oklch(0.205 0 0);
72
229
  }
73
230
 
74
- body {
75
- background-color: var(--color-background);
76
- color: var(--color-foreground);
231
+ @layer base {
232
+ * {
233
+ @apply border-border outline-ring/50;
234
+ }
235
+ body {
236
+ @apply bg-background text-foreground;
237
+ font-family: var(--font-sans);
238
+ }
77
239
  }
@@ -0,0 +1,19 @@
1
+ import * as React from "react"
2
+
3
+ const MOBILE_BREAKPOINT = 768
4
+
5
+ export function useIsMobile() {
6
+ const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined)
7
+
8
+ React.useEffect(() => {
9
+ const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)
10
+ const onChange = () => {
11
+ setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
12
+ }
13
+ mql.addEventListener("change", onChange)
14
+ setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
15
+ return () => mql.removeEventListener("change", onChange)
16
+ }, [])
17
+
18
+ return !!isMobile
19
+ }