@neynar/ui 0.1.1 → 0.1.2
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.
- package/dist/components/ui/accordion.d.ts +1 -25
- package/dist/components/ui/accordion.d.ts.map +1 -1
- package/dist/components/ui/alert-dialog.d.ts +240 -46
- package/dist/components/ui/alert-dialog.d.ts.map +1 -1
- package/dist/components/ui/alert.d.ts +73 -11
- package/dist/components/ui/alert.d.ts.map +1 -1
- package/dist/components/ui/aspect-ratio.d.ts +44 -10
- package/dist/components/ui/aspect-ratio.d.ts.map +1 -1
- package/dist/components/ui/avatar.d.ts +117 -33
- package/dist/components/ui/avatar.d.ts.map +1 -1
- package/dist/components/ui/badge.d.ts +50 -71
- package/dist/components/ui/badge.d.ts.map +1 -1
- package/dist/components/ui/breadcrumb.d.ts +231 -49
- package/dist/components/ui/breadcrumb.d.ts.map +1 -1
- package/dist/components/ui/button.d.ts +189 -71
- package/dist/components/ui/button.d.ts.map +1 -1
- package/dist/components/ui/calendar.d.ts +197 -40
- package/dist/components/ui/calendar.d.ts.map +1 -1
- package/dist/components/ui/card.d.ts +7 -22
- package/dist/components/ui/card.d.ts.map +1 -1
- package/dist/components/ui/carousel.d.ts +369 -99
- package/dist/components/ui/carousel.d.ts.map +1 -1
- package/dist/components/ui/chart.d.ts.map +1 -1
- package/dist/components/ui/checkbox.d.ts +110 -38
- package/dist/components/ui/checkbox.d.ts.map +1 -1
- package/dist/components/ui/collapsible.d.ts +246 -61
- package/dist/components/ui/collapsible.d.ts.map +1 -1
- package/dist/components/ui/combobox.d.ts +207 -159
- package/dist/components/ui/combobox.d.ts.map +1 -1
- package/dist/components/ui/command.d.ts +336 -67
- package/dist/components/ui/command.d.ts.map +1 -1
- package/dist/components/ui/container.d.ts +159 -64
- package/dist/components/ui/container.d.ts.map +1 -1
- package/dist/components/ui/context-menu.d.ts +321 -39
- package/dist/components/ui/context-menu.d.ts.map +1 -1
- package/dist/components/ui/date-picker.d.ts +113 -86
- package/dist/components/ui/date-picker.d.ts.map +1 -1
- package/dist/components/ui/dialog.d.ts +106 -25
- package/dist/components/ui/dialog.d.ts.map +1 -1
- package/dist/components/ui/drawer.d.ts +388 -59
- package/dist/components/ui/drawer.d.ts.map +1 -1
- package/dist/components/ui/dropdown-menu.d.ts +521 -74
- package/dist/components/ui/dropdown-menu.d.ts.map +1 -1
- package/dist/components/ui/empty-state.d.ts +148 -76
- package/dist/components/ui/empty-state.d.ts.map +1 -1
- package/dist/components/ui/hover-card.d.ts +253 -34
- package/dist/components/ui/hover-card.d.ts.map +1 -1
- package/dist/components/ui/input.d.ts +143 -44
- package/dist/components/ui/input.d.ts.map +1 -1
- package/dist/components/ui/label.d.ts +0 -8
- package/dist/components/ui/label.d.ts.map +1 -1
- package/dist/components/ui/menubar.d.ts +288 -46
- package/dist/components/ui/menubar.d.ts.map +1 -1
- package/dist/components/ui/navigation-menu.d.ts +444 -127
- package/dist/components/ui/navigation-menu.d.ts.map +1 -1
- package/dist/components/ui/pagination.d.ts +342 -66
- package/dist/components/ui/pagination.d.ts.map +1 -1
- package/dist/components/ui/popover.d.ts +0 -8
- package/dist/components/ui/popover.d.ts.map +1 -1
- package/dist/components/ui/progress.d.ts +88 -30
- package/dist/components/ui/progress.d.ts.map +1 -1
- package/dist/components/ui/radio-group.d.ts +189 -45
- package/dist/components/ui/radio-group.d.ts.map +1 -1
- package/dist/components/ui/resizable.d.ts +178 -62
- package/dist/components/ui/resizable.d.ts.map +1 -1
- package/dist/components/ui/scroll-area.d.ts +180 -21
- package/dist/components/ui/scroll-area.d.ts.map +1 -1
- package/dist/components/ui/select.d.ts +382 -60
- package/dist/components/ui/select.d.ts.map +1 -1
- package/dist/components/ui/separator.d.ts +52 -39
- package/dist/components/ui/separator.d.ts.map +1 -1
- package/dist/components/ui/sheet.d.ts +144 -27
- package/dist/components/ui/sheet.d.ts.map +1 -1
- package/dist/components/ui/sidebar.d.ts +81 -31
- package/dist/components/ui/sidebar.d.ts.map +1 -1
- package/dist/components/ui/skeleton.d.ts +94 -32
- package/dist/components/ui/skeleton.d.ts.map +1 -1
- package/dist/components/ui/slider.d.ts +37 -31
- package/dist/components/ui/slider.d.ts.map +1 -1
- package/dist/components/ui/sonner.d.ts +280 -46
- package/dist/components/ui/sonner.d.ts.map +1 -1
- package/dist/components/ui/stack.d.ts +289 -148
- package/dist/components/ui/stack.d.ts.map +1 -1
- package/dist/components/ui/stories/aspect-ratio.stories.d.ts +1 -2
- package/dist/components/ui/stories/aspect-ratio.stories.d.ts.map +1 -1
- package/dist/components/ui/stories/container.stories.d.ts +2 -3
- package/dist/components/ui/stories/container.stories.d.ts.map +1 -1
- package/dist/components/ui/stories/empty-state.stories.d.ts +2 -2
- package/dist/components/ui/stories/scroll-area.stories.d.ts +1 -2
- package/dist/components/ui/stories/scroll-area.stories.d.ts.map +1 -1
- package/dist/components/ui/stories/stack.stories.d.ts +1 -1
- package/dist/components/ui/stories/text-field.stories.d.ts +7 -1
- package/dist/components/ui/stories/text-field.stories.d.ts.map +1 -1
- package/dist/components/ui/switch.d.ts +44 -38
- package/dist/components/ui/switch.d.ts.map +1 -1
- package/dist/components/ui/table.d.ts +33 -0
- package/dist/components/ui/table.d.ts.map +1 -1
- package/dist/components/ui/tabs.d.ts +4 -22
- package/dist/components/ui/tabs.d.ts.map +1 -1
- package/dist/components/ui/text-field.d.ts +170 -84
- package/dist/components/ui/text-field.d.ts.map +1 -1
- package/dist/components/ui/textarea.d.ts +106 -29
- package/dist/components/ui/textarea.d.ts.map +1 -1
- package/dist/components/ui/theme-toggle.d.ts +190 -65
- package/dist/components/ui/theme-toggle.d.ts.map +1 -1
- package/dist/components/ui/theme.d.ts +107 -23
- package/dist/components/ui/theme.d.ts.map +1 -1
- package/dist/components/ui/toggle-group.d.ts +143 -67
- package/dist/components/ui/toggle-group.d.ts.map +1 -1
- package/dist/components/ui/toggle.d.ts +118 -30
- package/dist/components/ui/toggle.d.ts.map +1 -1
- package/dist/components/ui/tooltip.d.ts +152 -28
- package/dist/components/ui/tooltip.d.ts.map +1 -1
- package/dist/components/ui/typography.d.ts +452 -134
- package/dist/components/ui/typography.d.ts.map +1 -1
- package/dist/index.js +9388 -8281
- package/dist/index.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/llms.txt +173 -3
- package/package.json +5 -2
- package/src/components/ui/accordion.tsx +112 -27
- package/src/components/ui/alert-dialog.tsx +401 -46
- package/src/components/ui/alert.tsx +114 -11
- package/src/components/ui/aspect-ratio.tsx +69 -14
- package/src/components/ui/avatar.tsx +179 -33
- package/src/components/ui/badge.tsx +74 -75
- package/src/components/ui/breadcrumb.tsx +335 -50
- package/src/components/ui/button.tsx +198 -90
- package/src/components/ui/calendar.tsx +867 -43
- package/src/components/ui/card.tsx +140 -33
- package/src/components/ui/carousel.tsx +529 -98
- package/src/components/ui/chart.tsx +222 -1
- package/src/components/ui/checkbox.tsx +176 -38
- package/src/components/ui/collapsible.tsx +321 -67
- package/src/components/ui/combobox.tsx +284 -83
- package/src/components/ui/command.tsx +527 -67
- package/src/components/ui/container.tsx +217 -65
- package/src/components/ui/context-menu.tsx +716 -51
- package/src/components/ui/date-picker.tsx +228 -38
- package/src/components/ui/dialog.tsx +270 -33
- package/src/components/ui/drawer.tsx +546 -67
- package/src/components/ui/dropdown-menu.tsx +657 -74
- package/src/components/ui/empty-state.tsx +241 -82
- package/src/components/ui/hover-card.tsx +328 -39
- package/src/components/ui/input.tsx +207 -44
- package/src/components/ui/label.tsx +98 -8
- package/src/components/ui/menubar.tsx +587 -54
- package/src/components/ui/navigation-menu.tsx +557 -128
- package/src/components/ui/pagination.tsx +561 -79
- package/src/components/ui/popover.tsx +119 -8
- package/src/components/ui/progress.tsx +131 -29
- package/src/components/ui/radio-group.tsx +260 -51
- package/src/components/ui/resizable.tsx +289 -63
- package/src/components/ui/scroll-area.tsx +377 -66
- package/src/components/ui/select.tsx +545 -60
- package/src/components/ui/separator.tsx +146 -40
- package/src/components/ui/sheet.tsx +348 -31
- package/src/components/ui/sidebar.tsx +471 -29
- package/src/components/ui/skeleton.tsx +114 -32
- package/src/components/ui/slider.tsx +77 -31
- package/src/components/ui/sonner.tsx +574 -46
- package/src/components/ui/stack.tsx +423 -101
- package/src/components/ui/switch.tsx +78 -39
- package/src/components/ui/table.tsx +170 -4
- package/src/components/ui/tabs.tsx +108 -22
- package/src/components/ui/text-field.tsx +226 -81
- package/src/components/ui/textarea.tsx +180 -29
- package/src/components/ui/theme-toggle.tsx +313 -65
- package/src/components/ui/theme.tsx +117 -23
- package/src/components/ui/toggle-group.tsx +280 -69
- package/src/components/ui/toggle.tsx +124 -35
- package/src/components/ui/tooltip.tsx +239 -29
- package/src/components/ui/typography.tsx +1115 -165
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* Textarea - Multi-line text input control for extended content entry
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
* of text that span multiple lines, such as comments, descriptions,
|
|
7
|
-
*
|
|
8
|
-
* by the browser.
|
|
5
|
+
* A styled textarea component built on the native HTML textarea element for entering
|
|
6
|
+
* longer pieces of text that span multiple lines, such as comments, descriptions,
|
|
7
|
+
* messages, or any content that requires multiple lines of input. Features automatic
|
|
8
|
+
* content-based resizing using CSS field-sizing when supported by the browser.
|
|
9
9
|
*
|
|
10
10
|
* Built following shadcn/ui design patterns with consistent styling and behavior
|
|
11
|
-
* across form elements.
|
|
11
|
+
* across form elements. Inherits all native HTML textarea functionality while
|
|
12
|
+
* providing enhanced visual design and better accessibility patterns.
|
|
12
13
|
*
|
|
13
14
|
* @example
|
|
14
15
|
* ```tsx
|
|
15
16
|
* // Basic usage
|
|
16
|
-
* <Textarea placeholder="Type your message here
|
|
17
|
+
* <Textarea placeholder="Type your message here..." />
|
|
17
18
|
* ```
|
|
18
19
|
*
|
|
19
20
|
* @example
|
|
@@ -25,14 +26,16 @@ import * as React from "react";
|
|
|
25
26
|
* id="description"
|
|
26
27
|
* placeholder="Enter a description..."
|
|
27
28
|
* rows={4}
|
|
29
|
+
* required
|
|
28
30
|
* />
|
|
29
31
|
* </div>
|
|
30
32
|
* ```
|
|
31
33
|
*
|
|
32
34
|
* @example
|
|
33
35
|
* ```tsx
|
|
34
|
-
* // Controlled with character limit
|
|
36
|
+
* // Controlled with character limit and validation
|
|
35
37
|
* const [bio, setBio] = useState("");
|
|
38
|
+
* const [error, setError] = useState("");
|
|
36
39
|
* const maxLength = 160;
|
|
37
40
|
*
|
|
38
41
|
* <div className="space-y-2">
|
|
@@ -40,43 +43,117 @@ import * as React from "react";
|
|
|
40
43
|
* <Textarea
|
|
41
44
|
* id="bio"
|
|
42
45
|
* value={bio}
|
|
43
|
-
* onChange={(e) =>
|
|
46
|
+
* onChange={(e) => {
|
|
47
|
+
* setBio(e.target.value);
|
|
48
|
+
* if (e.target.value.length > maxLength) {
|
|
49
|
+
* setError("Bio is too long");
|
|
50
|
+
* } else {
|
|
51
|
+
* setError("");
|
|
52
|
+
* }
|
|
53
|
+
* }}
|
|
44
54
|
* placeholder="Tell us about yourself..."
|
|
45
55
|
* maxLength={maxLength}
|
|
56
|
+
* aria-invalid={!!error}
|
|
57
|
+
* aria-describedby={error ? "bio-error" : "bio-count"}
|
|
46
58
|
* />
|
|
47
|
-
* <
|
|
48
|
-
*
|
|
49
|
-
*
|
|
59
|
+
* <div className="flex justify-between items-center">
|
|
60
|
+
* <p id="bio-count" className="text-sm text-muted-foreground">
|
|
61
|
+
* {bio.length}/{maxLength} characters
|
|
62
|
+
* </p>
|
|
63
|
+
* {error && (
|
|
64
|
+
* <p id="bio-error" className="text-sm text-destructive">
|
|
65
|
+
* {error}
|
|
66
|
+
* </p>
|
|
67
|
+
* )}
|
|
68
|
+
* </div>
|
|
50
69
|
* </div>
|
|
51
70
|
* ```
|
|
52
71
|
*
|
|
53
72
|
* @example
|
|
54
73
|
* ```tsx
|
|
55
|
-
* //
|
|
74
|
+
* // Auto-resizing with minimum height
|
|
56
75
|
* <Textarea
|
|
57
|
-
* placeholder="
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
* className="border-destructive"
|
|
76
|
+
* placeholder="This textarea grows with content"
|
|
77
|
+
* className="min-h-[100px] max-h-[300px]"
|
|
78
|
+
* style={{ resize: "vertical" }}
|
|
61
79
|
* />
|
|
62
|
-
* <p id="feedback-error" className="text-sm text-destructive">
|
|
63
|
-
* This field is required
|
|
64
|
-
* </p>
|
|
65
80
|
* ```
|
|
66
81
|
*
|
|
67
|
-
* @
|
|
68
|
-
*
|
|
82
|
+
* @example
|
|
83
|
+
* ```tsx
|
|
84
|
+
* // Form integration with validation
|
|
85
|
+
* <form onSubmit={handleSubmit}>
|
|
86
|
+
* <div className="space-y-2">
|
|
87
|
+
* <Label htmlFor="feedback">Feedback</Label>
|
|
88
|
+
* <Textarea
|
|
89
|
+
* id="feedback"
|
|
90
|
+
* name="feedback"
|
|
91
|
+
* placeholder="Share your thoughts..."
|
|
92
|
+
* required
|
|
93
|
+
* minLength={10}
|
|
94
|
+
* maxLength={500}
|
|
95
|
+
* rows={3}
|
|
96
|
+
* />
|
|
97
|
+
* </div>
|
|
98
|
+
* <Button type="submit">Submit Feedback</Button>
|
|
99
|
+
* </form>
|
|
100
|
+
* ```
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```tsx
|
|
104
|
+
* // Different wrap behaviors for code/text
|
|
105
|
+
* <div className="space-y-4">
|
|
106
|
+
* <div>
|
|
107
|
+
* <Label>Code (no wrapping)</Label>
|
|
108
|
+
* <Textarea
|
|
109
|
+
* wrap="off"
|
|
110
|
+
* placeholder="Enter code here..."
|
|
111
|
+
* className="font-mono text-sm"
|
|
112
|
+
* style={{ resize: "both" }}
|
|
113
|
+
* />
|
|
114
|
+
* </div>
|
|
115
|
+
* <div>
|
|
116
|
+
* <Label>Text (soft wrapping)</Label>
|
|
117
|
+
* <Textarea
|
|
118
|
+
* wrap="soft"
|
|
119
|
+
* placeholder="Enter text content..."
|
|
120
|
+
* />
|
|
121
|
+
* </div>
|
|
122
|
+
* </div>
|
|
123
|
+
* ```
|
|
69
124
|
*
|
|
70
125
|
* @accessibility
|
|
71
|
-
* -
|
|
72
|
-
* -
|
|
73
|
-
* -
|
|
74
|
-
* -
|
|
75
|
-
* -
|
|
76
|
-
* - Respects disabled and
|
|
77
|
-
* -
|
|
126
|
+
* - Full keyboard navigation with Tab to focus and Shift+Tab to unfocus
|
|
127
|
+
* - Screen reader compatible with proper labeling support
|
|
128
|
+
* - ARIA state management for validation (aria-invalid, aria-describedby)
|
|
129
|
+
* - Supports assistive technology form field recognition
|
|
130
|
+
* - Visible focus indicators with ring outline for keyboard users
|
|
131
|
+
* - Respects disabled and read-only states for interaction prevention
|
|
132
|
+
* - Automatic association with Label components via htmlFor/id pattern
|
|
133
|
+
* - Auto-resizing maintains proper focus and scroll position
|
|
134
|
+
* - Character limits announced to screen readers when using aria-describedby
|
|
135
|
+
* - Spell checking integration with assistive technologies
|
|
136
|
+
*
|
|
137
|
+
* @behavior
|
|
138
|
+
* - Auto-resizing based on content using CSS field-sizing property
|
|
139
|
+
* - Smooth transitions for focus states and validation changes
|
|
140
|
+
* - Native browser resize handle (unless overridden with CSS resize property)
|
|
141
|
+
* - Form validation integration with HTML5 constraint validation API
|
|
142
|
+
* - Clipboard operations (cut, copy, paste) work as expected
|
|
143
|
+
* - Text selection and manipulation using standard keyboard shortcuts
|
|
144
|
+
*
|
|
145
|
+
* @styling
|
|
146
|
+
* - Base styles provide consistent appearance across form elements
|
|
147
|
+
* - Focus-visible styles with ring and border color changes
|
|
148
|
+
* - Error state styling via aria-invalid attribute with destructive colors
|
|
149
|
+
* - Dark mode support with appropriate background and text colors
|
|
150
|
+
* - Shadow and border transitions for interactive feedback
|
|
151
|
+
* - Disabled state with reduced opacity and pointer-events disabled
|
|
78
152
|
*
|
|
153
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea} MDN textarea documentation
|
|
79
154
|
* @see {@link https://ui.shadcn.com/docs/components/textarea} shadcn/ui Textarea documentation
|
|
155
|
+
* @see {@link Label} For proper labeling and accessibility association
|
|
156
|
+
* @see {@link Input} Single-line text input alternative
|
|
80
157
|
* @since 1.0.0
|
|
81
158
|
*/
|
|
82
159
|
declare function Textarea({ className, ...props }: React.ComponentProps<"textarea">): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"textarea.d.ts","sourceRoot":"","sources":["../../../src/components/ui/textarea.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"textarea.d.ts","sourceRoot":"","sources":["../../../src/components/ui/textarea.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AA8E/B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4JG;AACH,iBAAS,QAAQ,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,UAAU,CAAC,2CAW1E;AAED,OAAO,EAAE,QAAQ,EAAE,CAAC"}
|
|
@@ -1,105 +1,230 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
size?: "default" | "sm" | "lg" | "icon";
|
|
9
|
-
/** Additional CSS classes */
|
|
10
|
-
className?: string;
|
|
11
|
-
/** Whether to show text labels (only applies when size is not "icon") */
|
|
1
|
+
import { Button, buttonVariants } from "@/components/ui/button";
|
|
2
|
+
import { type VariantProps } from "class-variance-authority";
|
|
3
|
+
type ThemeToggleProps = {
|
|
4
|
+
/**
|
|
5
|
+
* Whether to show the current theme name as text next to the icon
|
|
6
|
+
* @default `size !== "icon"`
|
|
7
|
+
*/
|
|
12
8
|
showLabel?: boolean;
|
|
13
|
-
/**
|
|
9
|
+
/**
|
|
10
|
+
* Alignment of the dropdown menu relative to the trigger button
|
|
11
|
+
* @default "end"
|
|
12
|
+
*/
|
|
14
13
|
align?: "start" | "center" | "end";
|
|
15
|
-
}
|
|
14
|
+
} & React.ComponentProps<typeof Button> & VariantProps<typeof buttonVariants>;
|
|
16
15
|
/**
|
|
17
|
-
* ThemeToggle - A zero-
|
|
16
|
+
* ThemeToggle - A zero-configuration theme switcher with system, light, and dark modes
|
|
17
|
+
*
|
|
18
|
+
* A completely self-contained theme toggle component that provides an intuitive dropdown
|
|
19
|
+
* interface for switching between system preference, light mode, and dark mode. Works
|
|
20
|
+
* immediately without any provider setup, context configuration, or additional dependencies.
|
|
18
21
|
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* for SSR compatibility and automatically detects system theme changes.
|
|
22
|
+
* Built on top of shadcn/ui components (Button + DropdownMenu) with the Neynar useTheme
|
|
23
|
+
* hook for state management. Handles theme persistence via cookies, system preference
|
|
24
|
+
* detection, real-time system changes, and synchronization across multiple instances.
|
|
23
25
|
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
+
* **Zero Configuration Design:**
|
|
27
|
+
* Just import and use - no providers, no setup, no configuration required. The component
|
|
28
|
+
* handles all theme management internally and provides a complete solution out of the box.
|
|
26
29
|
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
30
|
+
* **Perfect for:**
|
|
31
|
+
* - Application headers and navigation bars
|
|
32
|
+
* - Settings panels and preference screens
|
|
33
|
+
* - Toolbars and floating action areas
|
|
34
|
+
* - Any location where users need quick theme access
|
|
35
|
+
*
|
|
36
|
+
* @example Basic usage (most common - icon button)
|
|
29
37
|
* ```tsx
|
|
30
|
-
* //
|
|
31
|
-
*
|
|
38
|
+
* // Just drop it in! Works immediately with zero setup
|
|
39
|
+
* function Header() {
|
|
40
|
+
* return (
|
|
41
|
+
* <header className="flex items-center justify-between p-4">
|
|
42
|
+
* <Logo />
|
|
43
|
+
* <ThemeToggle /> // That's it!
|
|
44
|
+
* </header>
|
|
45
|
+
* );
|
|
46
|
+
* }
|
|
32
47
|
* ```
|
|
33
48
|
*
|
|
34
|
-
* @example With text labels
|
|
49
|
+
* @example With text labels for better UX
|
|
35
50
|
* ```tsx
|
|
36
51
|
* // Show current theme name next to icon
|
|
37
52
|
* <ThemeToggle size="default" showLabel />
|
|
53
|
+
*
|
|
54
|
+
* // In a settings panel
|
|
55
|
+
* <div className="space-y-4">
|
|
56
|
+
* <h3>Appearance</h3>
|
|
57
|
+
* <div className="flex items-center justify-between">
|
|
58
|
+
* <span>Theme</span>
|
|
59
|
+
* <ThemeToggle size="sm" showLabel />
|
|
60
|
+
* </div>
|
|
61
|
+
* </div>
|
|
38
62
|
* ```
|
|
39
63
|
*
|
|
40
|
-
* @example
|
|
64
|
+
* @example Different visual variants
|
|
41
65
|
* ```tsx
|
|
42
|
-
* // Ghost button for minimalist
|
|
66
|
+
* // Ghost button for minimalist toolbars
|
|
43
67
|
* <ThemeToggle variant="ghost" />
|
|
44
68
|
*
|
|
45
|
-
* // Secondary style for
|
|
69
|
+
* // Secondary style for subtle integration
|
|
46
70
|
* <ThemeToggle variant="secondary" size="sm" />
|
|
47
71
|
*
|
|
48
|
-
* //
|
|
49
|
-
* <ThemeToggle
|
|
72
|
+
* // Outline style (default) for clear boundaries
|
|
73
|
+
* <ThemeToggle variant="outline" size="lg" />
|
|
74
|
+
* ```
|
|
75
|
+
*
|
|
76
|
+
* @example Custom positioning and styling
|
|
77
|
+
* ```tsx
|
|
78
|
+
* // Custom alignment and styling
|
|
79
|
+
* <ThemeToggle
|
|
80
|
+
* align="start"
|
|
81
|
+
* className="border-2 border-primary shadow-lg"
|
|
82
|
+
* />
|
|
83
|
+
*
|
|
84
|
+
* // Multiple synchronized instances
|
|
85
|
+
* function App() {
|
|
86
|
+
* return (
|
|
87
|
+
* <>
|
|
88
|
+
* <Header>
|
|
89
|
+
* <ThemeToggle /> // Changes sync automatically
|
|
90
|
+
* </Header>
|
|
91
|
+
* <Sidebar>
|
|
92
|
+
* <ThemeToggle variant="ghost" size="sm" /> // Stays in sync
|
|
93
|
+
* </Sidebar>
|
|
94
|
+
* </>
|
|
95
|
+
* );
|
|
96
|
+
* }
|
|
50
97
|
* ```
|
|
51
98
|
*
|
|
52
|
-
* @example
|
|
99
|
+
* @example Integration with navigation patterns
|
|
53
100
|
* ```tsx
|
|
54
|
-
* // Header navigation
|
|
55
|
-
* <header className="
|
|
56
|
-
* <
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
101
|
+
* // Header navigation with multiple controls
|
|
102
|
+
* <header className="border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
|
|
103
|
+
* <div className="container flex h-14 items-center">
|
|
104
|
+
* <div className="flex items-center space-x-2">
|
|
105
|
+
* <Logo />
|
|
106
|
+
* <nav className="hidden md:flex items-center space-x-6">
|
|
107
|
+
* <Link href="/docs">Documentation</Link>
|
|
108
|
+
* <Link href="/examples">Examples</Link>
|
|
109
|
+
* </nav>
|
|
110
|
+
* </div>
|
|
111
|
+
* <div className="flex items-center space-x-2 ml-auto">
|
|
112
|
+
* <Button variant="ghost" size="sm">Settings</Button>
|
|
113
|
+
* <ThemeToggle />
|
|
114
|
+
* <UserMenu />
|
|
115
|
+
* </div>
|
|
60
116
|
* </div>
|
|
61
117
|
* </header>
|
|
62
118
|
*
|
|
63
|
-
* // Sidebar footer
|
|
64
|
-
* <
|
|
65
|
-
* <
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
119
|
+
* // Sidebar with theme control in footer
|
|
120
|
+
* <aside className="w-64 border-r bg-muted/40">
|
|
121
|
+
* <nav className="flex-1 p-4">
|
|
122
|
+
* // Navigation items
|
|
123
|
+
* </nav>
|
|
124
|
+
* <footer className="p-4 border-t">
|
|
125
|
+
* <div className="flex items-center justify-between">
|
|
126
|
+
* <UserProfile compact />
|
|
127
|
+
* <ThemeToggle variant="ghost" size="sm" />
|
|
128
|
+
* </div>
|
|
129
|
+
* </footer>
|
|
130
|
+
* </aside>
|
|
131
|
+
* ```
|
|
132
|
+
*
|
|
133
|
+
* @example Advanced usage patterns
|
|
134
|
+
* ```tsx
|
|
135
|
+
* // Responsive behavior with different sizes
|
|
136
|
+
* <div className="flex items-center gap-2">
|
|
137
|
+
* <span className="hidden sm:inline-block text-sm">Theme:</span>
|
|
138
|
+
* <ThemeToggle
|
|
139
|
+
* size={{ base: "sm", md: "default" }}
|
|
140
|
+
* showLabel={{ base: false, sm: true }}
|
|
141
|
+
* />
|
|
142
|
+
* </div>
|
|
143
|
+
*
|
|
144
|
+
* // Conditional rendering based on user preferences
|
|
145
|
+
* function CustomThemeControl({ userPrefersAdvanced }: { userPrefersAdvanced: boolean }) {
|
|
146
|
+
* if (userPrefersAdvanced) {
|
|
147
|
+
* return <AdvancedThemePanel />;
|
|
148
|
+
* }
|
|
149
|
+
* return <ThemeToggle showLabel />;
|
|
150
|
+
* }
|
|
70
151
|
* ```
|
|
71
152
|
*
|
|
72
|
-
* @param variant -
|
|
73
|
-
* @param size - Button
|
|
153
|
+
* @param variant - Visual style variant inherited from Button component (default: "outline")
|
|
154
|
+
* @param size - Size variant inherited from Button component (default: "icon")
|
|
74
155
|
* @param className - Additional CSS classes for custom styling
|
|
75
156
|
* @param showLabel - Whether to show theme name text (auto-enabled for non-icon sizes)
|
|
76
|
-
* @param align - Dropdown menu alignment relative to trigger button
|
|
157
|
+
* @param align - Dropdown menu alignment relative to trigger button (default: "end")
|
|
77
158
|
*
|
|
78
159
|
* @features
|
|
79
|
-
* - **Zero Configuration**:
|
|
80
|
-
* - **System Detection**: Automatically follows OS dark/light preference
|
|
81
|
-
* - **
|
|
82
|
-
* - **
|
|
83
|
-
* - **
|
|
84
|
-
* - **
|
|
160
|
+
* - **Zero Configuration**: Import and use immediately - no setup required
|
|
161
|
+
* - **System Detection**: Automatically follows OS dark/light preference changes
|
|
162
|
+
* - **Perfect Persistence**: Theme choice saved via cookies for SSR compatibility
|
|
163
|
+
* - **Multi-Instance Sync**: Multiple toggles stay perfectly synchronized
|
|
164
|
+
* - **Real-Time Updates**: Responds to system theme changes while app is running
|
|
165
|
+
* - **Smooth Transitions**: CSS-based theme switching with no flash of wrong content
|
|
166
|
+
* - **Accessibility First**: Full keyboard navigation and screen reader support
|
|
167
|
+
* - **Touch Optimized**: Works perfectly on mobile and tablet devices
|
|
168
|
+
* - **Framework Agnostic**: Works with Next.js, Vite, Create React App, etc.
|
|
85
169
|
*
|
|
86
170
|
* @accessibility
|
|
87
|
-
* -
|
|
88
|
-
* -
|
|
89
|
-
* -
|
|
90
|
-
* -
|
|
91
|
-
* -
|
|
171
|
+
* - **Keyboard Navigation**: Full support for Enter, Space, and Arrow keys
|
|
172
|
+
* - **Screen Reader Support**: Proper ARIA labels and role announcements
|
|
173
|
+
* - **Focus Management**: Visible focus indicators meeting WCAG 2.1 AA standards
|
|
174
|
+
* - **State Communication**: Current selection clearly indicated with checkmarks
|
|
175
|
+
* - **High Contrast**: Works with system high contrast modes
|
|
176
|
+
* - **Reduced Motion**: Respects user's motion preferences
|
|
177
|
+
* - **Semantic HTML**: Uses proper button and menu semantics
|
|
178
|
+
* - **Live Regions**: Theme changes announced to assistive technology
|
|
179
|
+
*
|
|
180
|
+
* @technical
|
|
181
|
+
* **Component Architecture:**
|
|
182
|
+
* - Built with Radix UI primitives for robust accessibility
|
|
183
|
+
* - Uses Tailwind CSS with CSS custom properties for theming
|
|
184
|
+
* - State managed by custom `useTheme` hook with event-driven synchronization
|
|
185
|
+
* - Cookie-based persistence with 1-year expiration
|
|
186
|
+
* - Client-side hydration safe with SSR support
|
|
187
|
+
*
|
|
188
|
+
* **Performance Characteristics:**
|
|
189
|
+
* - Minimal bundle size impact (only imports what's needed)
|
|
190
|
+
* - No context overhead (direct hook usage)
|
|
191
|
+
* - Efficient event-driven updates (single state change per theme switch)
|
|
192
|
+
* - Lazy loading compatible (works in code-split components)
|
|
193
|
+
* - No memory leaks (automatic cleanup of event listeners)
|
|
194
|
+
*
|
|
195
|
+
* **Browser Support:**
|
|
196
|
+
* - Modern browsers with CSS custom properties support
|
|
197
|
+
* - IE11+ with polyfills for CustomEvent and matchMedia
|
|
198
|
+
* - Graceful degradation for older browsers
|
|
199
|
+
* - Progressive enhancement for advanced features
|
|
92
200
|
*
|
|
93
201
|
* @remarks
|
|
202
|
+
* **State Management:**
|
|
94
203
|
* This component uses the {@link useTheme} hook internally to manage theme state.
|
|
95
|
-
* Theme changes are persisted automatically and synchronized across
|
|
96
|
-
*
|
|
97
|
-
*
|
|
204
|
+
* Theme changes are persisted automatically via cookies and synchronized across
|
|
205
|
+
* all browser tabs and multiple component instances using custom events.
|
|
206
|
+
*
|
|
207
|
+
* **Styling Integration:**
|
|
208
|
+
* The component integrates with your existing design system through Tailwind CSS
|
|
209
|
+
* and shadcn/ui patterns. Themes are applied via CSS custom properties and dark
|
|
210
|
+
* mode class toggles, ensuring compatibility with most styling approaches.
|
|
211
|
+
*
|
|
212
|
+
* **Server-Side Rendering:**
|
|
213
|
+
* Fully compatible with SSR frameworks like Next.js. Theme preference is stored
|
|
214
|
+
* in cookies to prevent hydration mismatches, and the component gracefully handles
|
|
215
|
+
* server/client differences.
|
|
98
216
|
*
|
|
99
|
-
* @see {@link useTheme} - The underlying theme management hook
|
|
100
|
-
* @see {@link Button} - Base button component
|
|
101
|
-
* @see {@link DropdownMenu} - Menu component
|
|
217
|
+
* @see {@link useTheme} - The underlying theme management hook with event-driven architecture
|
|
218
|
+
* @see {@link Button} - Base button component providing variant and size styling
|
|
219
|
+
* @see {@link DropdownMenu} - Menu component providing accessible dropdown interaction
|
|
220
|
+
* @see {@link DropdownMenuContent} - Content container with positioning and collision detection
|
|
221
|
+
* @see {@link DropdownMenuItem} - Individual menu items with proper focus management
|
|
222
|
+
* @see {@link ThemePreference} - Type definition for available theme options
|
|
102
223
|
* @since 1.0.0
|
|
103
224
|
*/
|
|
104
|
-
|
|
225
|
+
declare function ThemeToggle({ variant, size, className, showLabel, align, ...props }: ThemeToggleProps): import("react/jsx-runtime").JSX.Element;
|
|
226
|
+
declare namespace ThemeToggle {
|
|
227
|
+
var displayName: string;
|
|
228
|
+
}
|
|
229
|
+
export { ThemeToggle };
|
|
105
230
|
//# sourceMappingURL=theme-toggle.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"theme-toggle.d.ts","sourceRoot":"","sources":["../../../src/components/ui/theme-toggle.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"theme-toggle.d.ts","sourceRoot":"","sources":["../../../src/components/ui/theme-toggle.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAShE,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AA4H7D,KAAK,gBAAgB,GAAG;IACtB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;CACpC,GAAG,KAAK,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,GACrC,YAAY,CAAC,OAAO,cAAc,CAAC,CAAC;AAEtC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiNG;AACH,iBAAS,WAAW,CAAC,EACnB,OAAmB,EACnB,IAAa,EACb,SAAS,EACT,SAAS,EACT,KAAa,EACb,GAAG,KAAK,EACT,EAAE,gBAAgB,2CA6DlB;kBApEQ,WAAW;;;AAwEpB,OAAO,EAAE,WAAW,EAAE,CAAC"}
|
|
@@ -12,6 +12,10 @@
|
|
|
12
12
|
* 3. Applies the appropriate theme class and color scheme immediately
|
|
13
13
|
* 4. Executes synchronously before first paint to prevent FOUC
|
|
14
14
|
*
|
|
15
|
+
* Built as a zero-configuration component that requires no props or setup. Simply
|
|
16
|
+
* drop it into your application's root layout and it will handle theme initialization
|
|
17
|
+
* automatically.
|
|
18
|
+
*
|
|
15
19
|
* @component
|
|
16
20
|
* @example Basic usage in Next.js App Router
|
|
17
21
|
* ```tsx
|
|
@@ -67,43 +71,123 @@
|
|
|
67
71
|
* }
|
|
68
72
|
* ```
|
|
69
73
|
*
|
|
74
|
+
* @example Usage with Gatsby
|
|
75
|
+
* ```tsx
|
|
76
|
+
* import { Theme } from "@neynar/ui";
|
|
77
|
+
*
|
|
78
|
+
* export function wrapRootElement({ element }) {
|
|
79
|
+
* return (
|
|
80
|
+
* <>
|
|
81
|
+
* <Theme />
|
|
82
|
+
* {element}
|
|
83
|
+
* </>
|
|
84
|
+
* );
|
|
85
|
+
* }
|
|
86
|
+
* ```
|
|
87
|
+
*
|
|
88
|
+
* @example Usage in plain React
|
|
89
|
+
* ```tsx
|
|
90
|
+
* import { Theme } from "@neynar/ui";
|
|
91
|
+
* import { createRoot } from "react-dom/client";
|
|
92
|
+
*
|
|
93
|
+
* const root = createRoot(document.getElementById('root'));
|
|
94
|
+
* root.render(
|
|
95
|
+
* <>
|
|
96
|
+
* <Theme />
|
|
97
|
+
* <App />
|
|
98
|
+
* </>
|
|
99
|
+
* );
|
|
100
|
+
* ```
|
|
101
|
+
*
|
|
70
102
|
* @features
|
|
71
|
-
* - **FOUC Prevention**: Applies theme before first paint
|
|
72
|
-
* - **Framework Agnostic**: Works with Next.js, Vite, Remix, and other React frameworks
|
|
73
|
-
* - **SSR Compatible**: Handles server-side rendering correctly
|
|
74
|
-
* - **System Detection**: Automatically follows OS dark/light preference
|
|
75
|
-
* - **Cookie Persistence**: Maintains theme across browser sessions
|
|
76
|
-
* - **Minimal Overhead**: Tiny inline script with no external dependencies
|
|
103
|
+
* - **FOUC Prevention**: Applies theme before first paint to eliminate flash
|
|
104
|
+
* - **Framework Agnostic**: Works with Next.js, Vite, Remix, Gatsby, and other React frameworks
|
|
105
|
+
* - **SSR Compatible**: Handles server-side rendering correctly without hydration issues
|
|
106
|
+
* - **System Detection**: Automatically follows OS dark/light preference when set to "system"
|
|
107
|
+
* - **Cookie Persistence**: Maintains theme preference across browser sessions and tabs
|
|
108
|
+
* - **Minimal Overhead**: Tiny inline script (~0.5KB minified) with no external dependencies
|
|
109
|
+
* - **Zero Configuration**: Works immediately without any setup or props
|
|
110
|
+
* - **Error Resilient**: Graceful fallback to light theme on any execution errors
|
|
77
111
|
*
|
|
78
112
|
* @accessibility
|
|
79
|
-
* - Respects
|
|
80
|
-
* - Maintains proper color contrast ratios
|
|
81
|
-
* -
|
|
82
|
-
* - Follows WCAG guidelines for
|
|
113
|
+
* - Respects `prefers-color-scheme` media query for system theme preference
|
|
114
|
+
* - Maintains proper color contrast ratios in both light and dark themes
|
|
115
|
+
* - Compatible with screen readers and assistive technology
|
|
116
|
+
* - Follows WCAG 2.1 guidelines for color and contrast accessibility
|
|
117
|
+
* - Supports high contrast mode when available in the operating system
|
|
118
|
+
* - No accessibility barriers introduced by the theme switching mechanism
|
|
83
119
|
*
|
|
84
120
|
* @performance
|
|
85
|
-
* - Executes before React hydration
|
|
86
|
-
* - No
|
|
87
|
-
* -
|
|
88
|
-
* -
|
|
121
|
+
* - **Critical Path Optimization**: Executes before React hydration to prevent FOUC
|
|
122
|
+
* - **Zero Dependencies**: No external libraries or network requests required
|
|
123
|
+
* - **Inline Execution**: Script runs immediately without additional round trips
|
|
124
|
+
* - **Minimal Size**: Compressed script adds negligible overhead to page load
|
|
125
|
+
* - **No Runtime Cost**: Zero ongoing performance impact after initial execution
|
|
126
|
+
* - **Memory Efficient**: No persistent JavaScript objects or event listeners
|
|
89
127
|
*
|
|
90
128
|
* @security
|
|
91
|
-
* - Uses dangerouslySetInnerHTML with
|
|
92
|
-
* - No
|
|
93
|
-
* -
|
|
94
|
-
* -
|
|
129
|
+
* - **Safe HTML Injection**: Uses `dangerouslySetInnerHTML` with verified safe content
|
|
130
|
+
* - **No External Sources**: All code is inline with no external script references
|
|
131
|
+
* - **No Dynamic Evaluation**: No use of `eval()`, `Function()`, or similar dynamic execution
|
|
132
|
+
* - **Error Boundaries**: Comprehensive try-catch blocks prevent script failures
|
|
133
|
+
* - **Cookie Safety**: Proper parsing and validation of cookie data
|
|
134
|
+
* - **XSS Protection**: No user input or dynamic content injection
|
|
135
|
+
*
|
|
136
|
+
* @browser-support
|
|
137
|
+
* - **Modern Browsers**: Full support in all modern browsers (Chrome 60+, Firefox 55+, Safari 12+)
|
|
138
|
+
* - **Legacy Browsers**: Graceful degradation in older browsers (defaults to light theme)
|
|
139
|
+
* - **Mobile Browsers**: Full support on iOS Safari, Chrome Mobile, Samsung Internet
|
|
140
|
+
* - **Media Query Support**: Requires `matchMedia` API for system theme detection
|
|
141
|
+
* - **Cookie Support**: Requires cookies for theme persistence (standard in all browsers)
|
|
142
|
+
* - **JavaScript Required**: Non-functional with JavaScript disabled (graceful degradation)
|
|
143
|
+
*
|
|
144
|
+
* @implementation-details
|
|
145
|
+
* **Script Execution Flow:**
|
|
146
|
+
* 1. Parse theme cookie using safe JSON parsing with error handling
|
|
147
|
+
* 2. Extract user preference (system/light/dark) from stored data
|
|
148
|
+
* 3. If "system", query `prefers-color-scheme` media query for OS preference
|
|
149
|
+
* 4. Apply corresponding CSS class ('dark') and color-scheme property
|
|
150
|
+
* 5. Handle any errors by defaulting to light theme
|
|
151
|
+
*
|
|
152
|
+
* **Cookie Structure:**
|
|
153
|
+
* ```json
|
|
154
|
+
* {
|
|
155
|
+
* "preference": "system" | "light" | "dark",
|
|
156
|
+
* "mode": "light" | "dark"
|
|
157
|
+
* }
|
|
158
|
+
* ```
|
|
159
|
+
*
|
|
160
|
+
* **DOM Modifications:**
|
|
161
|
+
* - Adds or removes 'dark' class on `document.documentElement`
|
|
162
|
+
* - Sets `color-scheme` CSS property for native element theming
|
|
163
|
+
* - Changes are applied synchronously before first paint
|
|
95
164
|
*
|
|
96
165
|
* @remarks
|
|
97
166
|
* This component must be used alongside the {@link useTheme} hook and
|
|
98
|
-
* {@link ThemeToggle} component for a complete theming solution. The
|
|
99
|
-
* handles initial theme application, while the
|
|
167
|
+
* {@link ThemeToggle} component for a complete theming solution. The Theme
|
|
168
|
+
* component handles initial theme application (FOUC prevention), while the
|
|
169
|
+
* hook manages runtime theme changes and the toggle provides user interface.
|
|
170
|
+
*
|
|
171
|
+
* **Architecture Overview:**
|
|
172
|
+
* - **Theme Component**: Prevents FOUC by applying initial theme
|
|
173
|
+
* - **useTheme Hook**: Manages theme state and preference changes at runtime
|
|
174
|
+
* - **ThemeToggle Component**: Provides user interface for theme selection
|
|
175
|
+
* - **Cookie Persistence**: Shared storage mechanism between all components
|
|
100
176
|
*
|
|
101
177
|
* The component is designed to work with Tailwind CSS's dark mode strategy,
|
|
102
178
|
* specifically the 'dark' class approach. It applies the 'dark' class to the
|
|
103
|
-
* document root and sets the appropriate color-scheme CSS property
|
|
179
|
+
* document root and sets the appropriate color-scheme CSS property for native
|
|
180
|
+
* element theming.
|
|
181
|
+
*
|
|
182
|
+
* **Integration Requirements:**
|
|
183
|
+
* - Tailwind CSS configured with `darkMode: 'class'` strategy
|
|
184
|
+
* - CSS custom properties for theme-aware color definitions
|
|
185
|
+
* - Proper color contrast ratios defined for both light and dark themes
|
|
186
|
+
* - Optional: CSS transitions for smooth theme switching
|
|
104
187
|
*
|
|
105
|
-
* @see {@link useTheme} - Hook for managing theme state and preferences
|
|
106
|
-
* @see {@link ThemeToggle} - UI component for theme switching
|
|
188
|
+
* @see {@link useTheme} - Hook for managing theme state and preferences at runtime
|
|
189
|
+
* @see {@link ThemeToggle} - UI component for user-initiated theme switching
|
|
190
|
+
* @see {@link https://tailwindcss.com/docs/dark-mode} - Tailwind CSS dark mode documentation
|
|
107
191
|
* @since 1.0.0
|
|
108
192
|
*/
|
|
109
193
|
export declare function Theme(): import("react/jsx-runtime").JSX.Element;
|