@7onic-ui/react 0.3.5 → 0.3.7

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 (3) hide show
  1. package/README.md +73 -17
  2. package/llms.txt +544 -512
  3. package/package.json +4 -2
package/llms.txt CHANGED
@@ -8,6 +8,7 @@ Single source of truth — design tokens to code. Use this to build any React se
8
8
  - Documentation: https://7onic.design
9
9
  - npm: `@7onic-ui/react` (components) + `@7onic-ui/tokens` (design tokens)
10
10
  - For tokens-only guide, see: https://7onic.design/llms.txt
11
+ - MCP server (token search / component catalog / validate_code): https://7onic.design/components/mcp — on Claude Code: `claude plugin marketplace add itonys/7onic && claude plugin install 7onic-design@7onic`
11
12
 
12
13
  ---
13
14
 
@@ -27,92 +28,29 @@ Before writing any code, present this checklist and wait for answers:
27
28
 
28
29
  **If the user answers in natural language** (e.g., "Make me a dashboard with dark mode, English only"), extract the answers from their message. **If any item is missing, ask a follow-up question for the missing items only.** Do not proceed until all 5 items are answered.
29
30
 
30
- ### Step 2: Execute full setup (all at once, do not skip any)
31
+ ### Step 2: Install / Setup
31
32
 
32
- After receiving answers, execute ALL of the following in order. Every step is mandatory.
33
+ ⚠️ **DO NOT GUESS** — install procedures evolve with each Tailwind / Next / Vite version. Before writing any code, AI **MUST** fetch the live pages below and follow their instructions verbatim:
33
34
 
34
- **2-1. Install packages (skip if already installed):**
35
- ```bash
36
- npm install @7onic-ui/react @7onic-ui/tokens lucide-react
37
- ```
38
- > Check package.json first. If packages are already listed in dependencies, skip this step.
39
-
40
- **2-2. Create or update globals.css with token imports:**
41
-
42
- **How to detect Tailwind version:**
43
- - `tailwind.config.js` (or `.ts`) exists → **v3**
44
- - No config file → **v4** (uses CSS-based configuration)
45
-
46
- **New project (Tailwind v4):**
47
- ```css
48
- /* globals.css (Next.js) or src/index.css (Vite) — ALL imports are required, do not skip any */
49
- @import "tailwindcss";
50
- @import "@7onic-ui/tokens/css/variables.css";
51
- @import "@7onic-ui/tokens/css/themes/light.css";
52
- @import "@7onic-ui/tokens/css/themes/dark.css"; /* omit ONLY if dark mode = no */
53
- @import "@7onic-ui/tokens/tailwind/v4-theme.css";
54
- ```
55
-
56
- **Existing project with Tailwind v3** (detect from tailwind.config.js):
57
- ```css
58
- /* globals.css */
59
- @import '@7onic-ui/tokens/css/variables.css';
60
- @import '@7onic-ui/tokens/css/themes/light.css';
61
- @import '@7onic-ui/tokens/css/themes/dark.css'; /* omit ONLY if dark mode = no */
62
- @tailwind base;
63
- @tailwind components;
64
- @tailwind utilities;
65
- ```
66
- ```js
67
- // tailwind.config.js — add preset
68
- const preset = require('@7onic-ui/tokens/tailwind/v3-preset')
69
- module.exports = {
70
- presets: [preset],
71
- content: [
72
- './src/**/*.{js,ts,jsx,tsx}',
73
- './node_modules/@7onic-ui/react/dist/**/*.{js,mjs}',
74
- ],
75
- }
76
- ```
77
-
78
- **2-3. Vite users only — clean up `src/index.css`:**
35
+ - **Official install page (SSOT)**: https://7onic.design/components/installation
36
+ - **Tailwind CSS official**: https://tailwindcss.com/docs/installation
79
37
 
80
- Vite's default template generates CSS that overrides 7onic token styles. Two paths:
38
+ The install instructions are intentionally **not duplicated in this file**. Setup details (packages, `tailwind.config.js`, `vite.config.ts`, `postcss.config.mjs`, `globals.css` patterns, framework default cleanup, layer wrap tips, etc.) are version-sensitive and change frequently — always defer to the live documentation above.
81
39
 
82
- - **CLI path (`npx 7onic init`) — recommended**: auto-handles all cleanup below, plus injects `@import "tailwindcss"` (v4), configures `@/` path alias (patches `tsconfig.app.json` + `vite.config.ts`, installs `@types/node`), and `npx 7onic add` auto-injects `@source "./components/ui"`. Prompts user, creates `.bak` backup.
83
- - **npm-only path (manual)**: delete the following blocks from `src/index.css`:
84
- - `:root { font-family: system-ui, ... }` block
85
- - `body { display: flex; place-items: center; ... }` block
86
- - `button { background-color: #1a1a1a; ... }` block and all other element-level rules (`a { color: #646cff }`, etc.)
87
- - `@media (prefers-color-scheme: light) { ... }` block
40
+ Apply user's answers from Step 1 after the install page steps are complete:
41
+ - Dark mode = yes → implement dark mode toggle (see below in this file)
42
+ - Custom font → load via `next/font/google` (Next.js) or Fontsource / CDN (Vite)
43
+ - Japanese / Korean locale → load Noto Sans JP / KR
88
44
 
89
- After deletion, `src/index.css` should contain only the token imports added in step 2-2. For v4 also add `@import "tailwindcss"` at the top, and configure `@/` alias manually.
45
+ ⛔ **Do NOT proceed to Step 3 until install page setup is verified.**
90
46
 
91
- **2-4. Apply user's answers:**
92
-
93
- - Dark mode = yes → implement dark mode toggle (see below)
94
- - Custom font → load font:
95
- - **Next.js**: use `next/font/google`
96
- - **Vite / Remix**: use Fontsource (`npm install @fontsource/inter`, then `import '@fontsource/inter/400.css'` in `src/main.tsx`) or Google Fonts CDN
97
- - Then set `--font-family-sans` in CSS
98
- - Locale includes Japanese → load Noto Sans JP font
99
- - Fontsource: `npm install @fontsource/noto-sans-jp` → import in `src/main.tsx` (Vite) or `app/layout.tsx` (Next.js)
100
- - CDN: Google Fonts link tag in `index.html`
101
- - Locale includes Korean → load Noto Sans KR font
102
- - Fontsource: `npm install @fontsource/noto-sans-kr` → import in `src/main.tsx` (Vite) or `app/layout.tsx` (Next.js)
103
- - CDN: Google Fonts link tag in `index.html`
104
-
105
- **2-5. Verify setup is complete before writing any UI code:**
106
- - [ ] Packages installed (@7onic-ui/react, @7onic-ui/tokens, lucide-react)
107
- - [ ] globals.css / src/index.css has ALL required imports in correct order
108
- - [ ] (Vite only) Vite template CSS blocks deleted from src/index.css
109
- - [ ] Dark mode toggle (if selected)
110
- - [ ] Font loaded (if custom)
111
- - [ ] CJK fonts loaded (if applicable)
47
+ ### Icon Import Pattern (lucide-react)
112
48
 
113
- ⛔ **Do NOT proceed to Step 3 until all checks pass.**
49
+ ⚠️ **`lucide-react` is NOT a 7onic dependency.** 7onic components themselves use inline SVG. Install separately if you want to use lucide icons in your app code:
114
50
 
115
- ### Icon Import Pattern (lucide-react)
51
+ ```bash
52
+ npm install lucide-react
53
+ ```
116
54
 
117
55
  ```tsx
118
56
  // ✅ Official pattern — no suffix
@@ -131,7 +69,9 @@ import { Badge as BadgeIcon } from 'lucide-react'
131
69
  Place `<Toaster />` once in your root layout file. Without this, `toast()` calls will not render.
132
70
 
133
71
  ```tsx
134
- import { Toaster } from '@7onic-ui/react'// In your root layout (e.g., app/layout.tsx)
72
+ import { Toaster } from '@7onic-ui/react'
73
+
74
+ // In your root layout (e.g., app/layout.tsx)
135
75
  <body>
136
76
  {children}
137
77
  <Toaster position="bottom-right" />
@@ -248,7 +188,9 @@ style={{ color: '#333', padding: '20px' }}
248
188
  w-4 h-4, w-5 h-5 → icon-sm, icon-md
249
189
 
250
190
  // ❌ Radix direct import
251
- import * as Dialog from '@radix-ui/react-dialog' → import { Badge, Button, Card, Input, Table } from '@7onic-ui/react'// ❌ Unnecessary component wrappers
191
+ import * as Dialog from '@radix-ui/react-dialog' → import { Badge, Button, Card, Input, Table } from '@7onic-ui/react'
192
+
193
+ // ❌ Unnecessary component wrappers
252
194
  function MyButton(props) { return <Button {...props} /> } → Use Button directly
253
195
  ```
254
196
 
@@ -402,7 +344,9 @@ import { Button, Card, Input, toast } from '@7onic-ui/react'
402
344
  All components use Named imports. Works in every environment (Next.js App Router RSC, Client Components, Pages Router, Vite, CRA, CJS).
403
345
 
404
346
  ```tsx
405
- import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@7onic-ui/react'<Card>
347
+ import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@7onic-ui/react'
348
+
349
+ <Card>
406
350
  <CardHeader>
407
351
  <CardTitle>Title</CardTitle>
408
352
  <CardDescription>Description</CardDescription>
@@ -426,7 +370,7 @@ Badge, Button, ButtonGroup, Checkbox, Divider, IconButton, Input, Progress, Skel
426
370
 
427
371
  ---
428
372
 
429
- # ═══ SECTION 3: ALL COMPONENTS (42) ═══
373
+ # ═══ SECTION 3: ALL COMPONENTS (41) ═══
430
374
 
431
375
  ---
432
376
 
@@ -435,7 +379,9 @@ Badge, Button, ButtonGroup, Checkbox, Divider, IconButton, Input, Progress, Skel
435
379
  ### Button
436
380
 
437
381
  ```tsx
438
- import { Button } from '@7onic-ui/react'<Button variant="solid" color="primary" size="default">Submit</Button>
382
+ import { Button } from '@7onic-ui/react'
383
+
384
+ <Button variant="solid" color="primary" size="default">Submit</Button>
439
385
  <Button variant="outline" color="default" leftIcon={<Icon />}>Cancel</Button>
440
386
  <Button loading>Processing...</Button>
441
387
  <Button variant="link" color="primary">Learn more</Button>
@@ -464,7 +410,9 @@ import { Button } from '@7onic-ui/react'<Button variant="solid" color="primary"
464
410
  ### IconButton
465
411
 
466
412
  ```tsx
467
- import { IconButton } from '@7onic-ui/react'<IconButton variant="ghost" size="default" aria-label="Settings">
413
+ import { IconButton } from '@7onic-ui/react'
414
+
415
+ <IconButton variant="ghost" size="default" aria-label="Settings">
468
416
  <SettingsIcon />
469
417
  </IconButton>
470
418
  ```
@@ -487,7 +435,9 @@ import { IconButton } from '@7onic-ui/react'<IconButton variant="ghost" size="de
487
435
  ### ButtonGroup
488
436
 
489
437
  ```tsx
490
- import { Button, ButtonGroup } from '@7onic-ui/react'<ButtonGroup variant="outline" size="default" attached>
438
+ import { Button, ButtonGroup } from '@7onic-ui/react'
439
+
440
+ <ButtonGroup variant="outline" size="default" attached>
491
441
  <Button>Left</Button>
492
442
  <Button>Center</Button>
493
443
  <Button>Right</Button>
@@ -511,7 +461,9 @@ Provides context — child Buttons inherit variant/size/radius automatically.
511
461
  ### Input
512
462
 
513
463
  ```tsx
514
- import { Input } from '@7onic-ui/react'<Input placeholder="Email" size="default" />
464
+ import { Input } from '@7onic-ui/react'
465
+
466
+ <Input placeholder="Email" size="default" />
515
467
  <Input variant="filled" leftIcon={<SearchIcon />} />
516
468
  <Input error rightIcon={<AlertIcon />} />
517
469
  ```
@@ -533,7 +485,9 @@ import { Input } from '@7onic-ui/react'<Input placeholder="Email" size="default"
533
485
  ### Textarea
534
486
 
535
487
  ```tsx
536
- import { Textarea } from '@7onic-ui/react'<Textarea placeholder="Message" rows={4} resize="vertical" />
488
+ import { Textarea } from '@7onic-ui/react'
489
+
490
+ <Textarea placeholder="Message" rows={4} resize="vertical" />
537
491
  ```
538
492
 
539
493
  | Prop | Type | Default | Description |
@@ -551,7 +505,9 @@ import { Textarea } from '@7onic-ui/react'<Textarea placeholder="Message" rows={
551
505
  ### Select
552
506
 
553
507
  ```tsx
554
- import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue } from '@7onic-ui/react'<Select>
508
+ import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue } from '@7onic-ui/react'
509
+
510
+ <Select>
555
511
  <SelectTrigger>
556
512
  <SelectValue placeholder="Choose option" />
557
513
  </SelectTrigger>
@@ -581,7 +537,9 @@ import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrig
581
537
  ### DropdownMenu
582
538
 
583
539
  ```tsx
584
- import { Button, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger } from '@7onic-ui/react'<DropdownMenu>
540
+ import { Button, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger } from '@7onic-ui/react'
541
+
542
+ <DropdownMenu>
585
543
  <DropdownMenuTrigger asChild>
586
544
  <Button variant="outline">Options</Button>
587
545
  </DropdownMenuTrigger>
@@ -601,14 +559,16 @@ import { Button, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMe
601
559
  | flush | `boolean` | `false` | Full-width items (no padding) |
602
560
  | sideOffset | `number` | `4` | Gap from trigger |
603
561
 
604
- **Sub-components:** DropdownMenu.Trigger, DropdownMenu.Content, DropdownMenu.Item, DropdownMenu.CheckboxItem, DropdownMenu.RadioItem, DropdownMenu.Label, DropdownMenu.Separator, DropdownMenu.Group, DropdownMenu.Sub, DropdownMenu.SubTrigger, DropdownMenu.SubContent, DropdownMenu.Shortcut
562
+ **Sub-components:** DropdownMenu.Trigger, DropdownMenu.Content, DropdownMenu.Item, DropdownMenu.CheckboxItem, DropdownMenu.RadioGroup, DropdownMenu.RadioItem, DropdownMenu.Label, DropdownMenu.Separator, DropdownMenu.Group, DropdownMenu.Sub, DropdownMenu.SubTrigger, DropdownMenu.SubContent, DropdownMenu.Shortcut
605
563
 
606
564
  ---
607
565
 
608
566
  ### Checkbox
609
567
 
610
568
  ```tsx
611
- import { Checkbox } from '@7onic-ui/react'<Checkbox label="Accept terms" />
569
+ import { Checkbox } from '@7onic-ui/react'
570
+
571
+ <Checkbox label="Accept terms" />
612
572
  <Checkbox size="lg" color="primary" checked />
613
573
  <Checkbox checked="indeterminate" />
614
574
  ```
@@ -630,7 +590,9 @@ import { Checkbox } from '@7onic-ui/react'<Checkbox label="Accept terms" />
630
590
  ### RadioGroup
631
591
 
632
592
  ```tsx
633
- import { RadioGroup, RadioGroupItem } from '@7onic-ui/react'<RadioGroup defaultValue="a">
593
+ import { RadioGroup, RadioGroupItem } from '@7onic-ui/react'
594
+
595
+ <RadioGroup defaultValue="a">
634
596
  <RadioGroupItem value="a" label="Option A" />
635
597
  <RadioGroupItem value="b" label="Option B" />
636
598
  <RadioGroupItem value="c" label="Option C" disabled />
@@ -654,7 +616,9 @@ import { RadioGroup, RadioGroupItem } from '@7onic-ui/react'<RadioGroup defaultV
654
616
  ### Switch
655
617
 
656
618
  ```tsx
657
- import { Switch } from '@7onic-ui/react'<Switch label="Notifications" />
619
+ import { Switch } from '@7onic-ui/react'
620
+
621
+ <Switch label="Notifications" />
658
622
  <Switch size="lg" color="primary" defaultChecked />
659
623
  <Switch startLabel="Off" endLabel="On" />
660
624
  ```
@@ -679,7 +643,9 @@ import { Switch } from '@7onic-ui/react'<Switch label="Notifications" />
679
643
  ### Toggle
680
644
 
681
645
  ```tsx
682
- import { Toggle } from '@7onic-ui/react'<Toggle variant="default" aria-label="Bold">
646
+ import { Toggle } from '@7onic-ui/react'
647
+
648
+ <Toggle variant="default" aria-label="Bold">
683
649
  <BoldIcon />
684
650
  </Toggle>
685
651
  <Toggle variant="outline" pressed>Active</Toggle>
@@ -702,7 +668,9 @@ import { Toggle } from '@7onic-ui/react'<Toggle variant="default" aria-label="Bo
702
668
  ### ToggleGroup
703
669
 
704
670
  ```tsx
705
- import { ToggleGroup, ToggleGroupItem } from '@7onic-ui/react'<ToggleGroup type="single" defaultValue="center">
671
+ import { ToggleGroup, ToggleGroupItem } from '@7onic-ui/react'
672
+
673
+ <ToggleGroup type="single" defaultValue="center">
706
674
  <ToggleGroupItem value="left"><AlignLeftIcon /></ToggleGroupItem>
707
675
  <ToggleGroupItem value="center"><AlignCenterIcon /></ToggleGroupItem>
708
676
  <ToggleGroupItem value="right"><AlignRightIcon /></ToggleGroupItem>
@@ -728,7 +696,9 @@ import { ToggleGroup, ToggleGroupItem } from '@7onic-ui/react'<ToggleGroup type=
728
696
  ### Segmented
729
697
 
730
698
  ```tsx
731
- import { Segmented, SegmentedItem } from '@7onic-ui/react'<Segmented defaultValue="all">
699
+ import { Segmented, SegmentedItem } from '@7onic-ui/react'
700
+
701
+ <Segmented defaultValue="all">
732
702
  <SegmentedItem value="all">All</SegmentedItem>
733
703
  <SegmentedItem value="active">Active</SegmentedItem>
734
704
  <SegmentedItem value="inactive">Inactive</SegmentedItem>
@@ -753,7 +723,9 @@ import { Segmented, SegmentedItem } from '@7onic-ui/react'<Segmented defaultValu
753
723
  ### Slider
754
724
 
755
725
  ```tsx
756
- import { Slider } from '@7onic-ui/react'<Slider defaultValue={[50]} showTooltip="auto" />
726
+ import { Slider } from '@7onic-ui/react'
727
+
728
+ <Slider defaultValue={[50]} showTooltip="auto" />
757
729
  <Slider defaultValue={[20, 80]} color="primary" />
758
730
  ```
759
731
 
@@ -778,7 +750,9 @@ import { Slider } from '@7onic-ui/react'<Slider defaultValue={[50]} showTooltip=
778
750
  ### Field (Form Wrapper)
779
751
 
780
752
  ```tsx
781
- import { Field, FieldCharCount, FieldError, FieldLabel, Input, Textarea } from '@7onic-ui/react'<Field error="Invalid email">
753
+ import { Field, FieldCharCount, FieldError, FieldLabel, Input, Textarea } from '@7onic-ui/react'
754
+
755
+ <Field error="Invalid email">
782
756
  <FieldLabel required>Email</FieldLabel>
783
757
  <Input placeholder="you@example.com" />
784
758
  <FieldError />
@@ -807,7 +781,9 @@ import { Field, FieldCharCount, FieldError, FieldLabel, Input, Textarea } from '
807
781
  ### Avatar
808
782
 
809
783
  ```tsx
810
- import { Avatar, AvatarFallback, AvatarGroup, AvatarImage } from '@7onic-ui/react'<Avatar size="default">
784
+ import { Avatar, AvatarFallback, AvatarGroup, AvatarImage } from '@7onic-ui/react'
785
+
786
+ <Avatar size="default">
811
787
  <AvatarImage src="/photo.jpg" alt="User" />
812
788
  <AvatarFallback name="John Doe" colorized />
813
789
  </Avatar>
@@ -845,7 +821,9 @@ import { Avatar, AvatarFallback, AvatarGroup, AvatarImage } from '@7onic-ui/reac
845
821
  ### Badge
846
822
 
847
823
  ```tsx
848
- import { Badge } from '@7onic-ui/react'<Badge variant="solid" color="primary">New</Badge>
824
+ import { Badge } from '@7onic-ui/react'
825
+
826
+ <Badge variant="solid" color="primary">New</Badge>
849
827
  <Badge variant="subtle" color="success" dot>Active</Badge>
850
828
  <Badge variant="outline" removable onRemove={() => {}}>Tag</Badge>
851
829
  ```
@@ -855,7 +833,7 @@ import { Badge } from '@7onic-ui/react'<Badge variant="solid" color="primary">Ne
855
833
  | variant | `'solid' \| 'subtle' \| 'outline'` | `'subtle'` | Visual style |
856
834
  | color | `'default' \| 'primary' \| 'success' \| 'warning' \| 'error' \| 'info'` | `'default'` | Color scheme |
857
835
  | size | `'sm' \| 'default' \| 'lg'` | `'default'` | Badge size |
858
- | radius | `'sm' \| 'md' \| 'lg' \| 'xl' \| 'full'` | `'full'` | Border radius |
836
+ | radius | `'sm' \| 'base' \| 'md' \| 'lg' \| 'full'` | `'full'` | Border radius |
859
837
  | icon | `ReactNode` | — | Leading icon |
860
838
  | dot | `boolean` | `false` | Status dot indicator |
861
839
  | removable | `boolean` | `false` | Shows remove button |
@@ -867,7 +845,9 @@ import { Badge } from '@7onic-ui/react'<Badge variant="solid" color="primary">Ne
867
845
  ### Card
868
846
 
869
847
  ```tsx
870
- import { Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardImage, CardTitle, IconButton } from '@7onic-ui/react'<Card variant="default" interactive>
848
+ import { Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardImage, CardTitle, IconButton } from '@7onic-ui/react'
849
+
850
+ <Card variant="default" interactive>
871
851
  <CardImage src="/cover.jpg" overlay overlayOpacity={40} />
872
852
  <CardHeader>
873
853
  <CardTitle icon={<StarIcon />}>Featured</CardTitle>
@@ -900,7 +880,9 @@ import { Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader,
900
880
  ### Table
901
881
 
902
882
  ```tsx
903
- import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@7onic-ui/react'<Table variant="default" stickyHeader>
883
+ import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@7onic-ui/react'
884
+
885
+ <Table variant="default" stickyHeader>
904
886
  <TableHeader>
905
887
  <TableRow>
906
888
  <TableHead sortable sortDirection="asc" onSort={() => {}}>Name</TableHead>
@@ -947,7 +929,9 @@ import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@
947
929
  ### Tabs
948
930
 
949
931
  ```tsx
950
- import { Tabs, TabsContent, TabsList, TabsTrigger } from '@7onic-ui/react'<Tabs defaultValue="tab1">
932
+ import { Tabs, TabsContent, TabsList, TabsTrigger } from '@7onic-ui/react'
933
+
934
+ <Tabs defaultValue="tab1">
951
935
  <TabsList variant="line" size="default">
952
936
  <TabsTrigger value="tab1">Tab 1</TabsTrigger>
953
937
  <TabsTrigger value="tab2">Tab 2</TabsTrigger>
@@ -972,7 +956,9 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from '@7onic-ui/react'<Tabs
972
956
  ### Accordion
973
957
 
974
958
  ```tsx
975
- import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@7onic-ui/react'<Accordion type="single" collapsible defaultValue="item-1">
959
+ import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@7onic-ui/react'
960
+
961
+ <Accordion type="single" collapsible defaultValue="item-1">
976
962
  <AccordionItem value="item-1">
977
963
  <AccordionTrigger>Section 1</AccordionTrigger>
978
964
  <AccordionContent>Content 1</AccordionContent>
@@ -999,7 +985,9 @@ import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@7
999
985
  ### Divider
1000
986
 
1001
987
  ```tsx
1002
- import { Divider } from '@7onic-ui/react'<Divider />
988
+ import { Divider } from '@7onic-ui/react'
989
+
990
+ <Divider />
1003
991
  <Divider variant="dashed" color="muted" />
1004
992
  <Divider label="OR" labelPosition="center" />
1005
993
  <Divider orientation="vertical" />
@@ -1021,7 +1009,9 @@ import { Divider } from '@7onic-ui/react'<Divider />
1021
1009
  ### Modal
1022
1010
 
1023
1011
  ```tsx
1024
- import { Button, Modal, ModalBody, ModalClose, ModalContent, ModalDescription, ModalFooter, ModalHeader, ModalOverlay, ModalPortal, ModalTitle, ModalTrigger } from '@7onic-ui/react'<Modal>
1012
+ import { Button, Modal, ModalBody, ModalClose, ModalContent, ModalDescription, ModalFooter, ModalHeader, ModalOverlay, ModalPortal, ModalTitle, ModalTrigger } from '@7onic-ui/react'
1013
+
1014
+ <Modal>
1025
1015
  <ModalTrigger asChild>
1026
1016
  <Button>Open Modal</Button>
1027
1017
  </ModalTrigger>
@@ -1057,7 +1047,9 @@ import { Button, Modal, ModalBody, ModalClose, ModalContent, ModalDescription, M
1057
1047
  ### AlertModal
1058
1048
 
1059
1049
  ```tsx
1060
- import { AlertModal, AlertModalAction, AlertModalBody, AlertModalCancel, AlertModalContent, AlertModalDescription, AlertModalFooter, AlertModalHeader, AlertModalOverlay, AlertModalPortal, AlertModalTitle, AlertModalTrigger, Button } from '@7onic-ui/react'<AlertModal>
1050
+ import { AlertModal, AlertModalAction, AlertModalBody, AlertModalCancel, AlertModalContent, AlertModalDescription, AlertModalFooter, AlertModalHeader, AlertModalOverlay, AlertModalPortal, AlertModalTitle, AlertModalTrigger, Button } from '@7onic-ui/react'
1051
+
1052
+ <AlertModal>
1061
1053
  <AlertModalTrigger asChild>
1062
1054
  <Button color="destructive">Delete</Button>
1063
1055
  </AlertModalTrigger>
@@ -1091,7 +1083,9 @@ import { AlertModal, AlertModalAction, AlertModalBody, AlertModalCancel, AlertMo
1091
1083
  ### Drawer
1092
1084
 
1093
1085
  ```tsx
1094
- import { Button, Drawer, DrawerBody, DrawerClose, DrawerContent, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger } from '@7onic-ui/react'<Drawer>
1086
+ import { Button, Drawer, DrawerBody, DrawerClose, DrawerContent, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger } from '@7onic-ui/react'
1087
+
1088
+ <Drawer>
1095
1089
  <DrawerTrigger asChild>
1096
1090
  <Button>Open Drawer</Button>
1097
1091
  </DrawerTrigger>
@@ -1123,7 +1117,9 @@ import { Button, Drawer, DrawerBody, DrawerClose, DrawerContent, DrawerFooter, D
1123
1117
  ### Tooltip
1124
1118
 
1125
1119
  ```tsx
1126
- import { Button, Tooltip, TooltipArrow, TooltipContent, TooltipPortal, TooltipProvider, TooltipTrigger } from '@7onic-ui/react'<TooltipProvider>
1120
+ import { Button, Tooltip, TooltipArrow, TooltipContent, TooltipPortal, TooltipProvider, TooltipTrigger } from '@7onic-ui/react'
1121
+
1122
+ <TooltipProvider>
1127
1123
  <Tooltip>
1128
1124
  <TooltipTrigger asChild>
1129
1125
  <Button>Hover me</Button>
@@ -1158,7 +1154,9 @@ import { Button, Tooltip, TooltipArrow, TooltipContent, TooltipPortal, TooltipPr
1158
1154
  ### Popover
1159
1155
 
1160
1156
  ```tsx
1161
- import { Button, Popover, PopoverArrow, PopoverContent, PopoverPortal, PopoverTrigger } from '@7onic-ui/react'<Popover>
1157
+ import { Button, Popover, PopoverArrow, PopoverContent, PopoverPortal, PopoverTrigger } from '@7onic-ui/react'
1158
+
1159
+ <Popover>
1162
1160
  <PopoverTrigger asChild>
1163
1161
  <Button variant="outline">Open</Button>
1164
1162
  </PopoverTrigger>
@@ -1188,7 +1186,9 @@ import { Button, Popover, PopoverArrow, PopoverContent, PopoverPortal, PopoverTr
1188
1186
  ### Alert
1189
1187
 
1190
1188
  ```tsx
1191
- import { Alert, AlertDescription, AlertTitle } from '@7onic-ui/react'<Alert color="success" closable onClose={() => {}}>
1189
+ import { Alert, AlertDescription, AlertTitle } from '@7onic-ui/react'
1190
+
1191
+ <Alert color="success" closable onClose={() => {}}>
1192
1192
  <AlertTitle>Success</AlertTitle>
1193
1193
  <AlertDescription>Operation completed.</AlertDescription>
1194
1194
  </Alert>
@@ -1216,7 +1216,9 @@ import { Alert, AlertDescription, AlertTitle } from '@7onic-ui/react'<Alert colo
1216
1216
  ### Toast (Imperative API)
1217
1217
 
1218
1218
  ```tsx
1219
- import { Toaster, toast } from '@7onic-ui/react'// 1. Add Toaster provider to your app layout (once)
1219
+ import { Toaster, toast } from '@7onic-ui/react'
1220
+
1221
+ // 1. Add Toaster provider to your app layout (once)
1220
1222
  <Toaster position="bottom-right" />
1221
1223
 
1222
1224
  // 2. Call toast() anywhere
@@ -1264,7 +1266,9 @@ toast.dismiss() // Dismiss all
1264
1266
  ### Progress
1265
1267
 
1266
1268
  ```tsx
1267
- import { Progress } from '@7onic-ui/react'<Progress value={65} showValue />
1269
+ import { Progress } from '@7onic-ui/react'
1270
+
1271
+ <Progress value={65} showValue />
1268
1272
  <Progress type="circular" value={75} color="primary" />
1269
1273
  <Progress variant="striped" animated value={50} />
1270
1274
  ```
@@ -1286,7 +1290,9 @@ import { Progress } from '@7onic-ui/react'<Progress value={65} showValue />
1286
1290
  ### Spinner
1287
1291
 
1288
1292
  ```tsx
1289
- import { Spinner } from '@7onic-ui/react'<Spinner />
1293
+ import { Spinner } from '@7onic-ui/react'
1294
+
1295
+ <Spinner />
1290
1296
  <Spinner variant="dots" size="lg" color="primary" />
1291
1297
  <Spinner variant="bars" speed="slow" />
1292
1298
  <Spinner variant="orbit" orbitStyle="morph" />
@@ -1306,7 +1312,9 @@ import { Spinner } from '@7onic-ui/react'<Spinner />
1306
1312
  ### Skeleton
1307
1313
 
1308
1314
  ```tsx
1309
- import { Skeleton } from '@7onic-ui/react'<Skeleton variant="text" count={3} />
1315
+ import { Skeleton } from '@7onic-ui/react'
1316
+
1317
+ <Skeleton variant="text" count={3} />
1310
1318
  <Skeleton variant="circular" width={48} height={48} />
1311
1319
  <Skeleton variant="rectangular" width="100%" height={200} />
1312
1320
 
@@ -1334,7 +1342,9 @@ import { Skeleton } from '@7onic-ui/react'<Skeleton variant="text" count={3} />
1334
1342
  ### Breadcrumb
1335
1343
 
1336
1344
  ```tsx
1337
- import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator } from '@7onic-ui/react'<Breadcrumb>
1345
+ import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator } from '@7onic-ui/react'
1346
+
1347
+ <Breadcrumb>
1338
1348
  <BreadcrumbList>
1339
1349
  <BreadcrumbItem>
1340
1350
  <BreadcrumbLink href="/">Home</BreadcrumbLink>
@@ -1366,7 +1376,9 @@ import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbP
1366
1376
  ### Pagination
1367
1377
 
1368
1378
  ```tsx
1369
- import { Pagination, PaginationContent, PaginationItems, PaginationNext, PaginationPrevious } from '@7onic-ui/react'{/* Quick mode — withControls (default: true), withEdges (default: false) */}
1379
+ import { Pagination, PaginationContent, PaginationItems, PaginationNext, PaginationPrevious } from '@7onic-ui/react'
1380
+
1381
+ {/* Quick mode — withControls (default: true), withEdges (default: false) */}
1370
1382
  <Pagination total={10} defaultValue={1} />
1371
1383
  <Pagination total={10} defaultValue={1} withEdges />
1372
1384
  <Pagination total={10} defaultValue={1} withControls={false} />
@@ -1405,7 +1417,9 @@ import { Pagination, PaginationContent, PaginationItems, PaginationNext, Paginat
1405
1417
  ### NavigationMenu
1406
1418
 
1407
1419
  ```tsx
1408
- import { NavigationMenu, NavigationMenuContent, NavigationMenuGroup, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport } from '@7onic-ui/react'{/* Horizontal (header) */}
1420
+ import { NavigationMenu, NavigationMenuContent, NavigationMenuGroup, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport } from '@7onic-ui/react'
1421
+
1422
+ {/* Horizontal (header) */}
1409
1423
  <NavigationMenu orientation="horizontal">
1410
1424
  <NavigationMenuList>
1411
1425
  <NavigationMenuItem>
@@ -1470,7 +1484,9 @@ import { NavigationMenu, NavigationMenuContent, NavigationMenuGroup, NavigationM
1470
1484
  All chart types use the Chart namespace:
1471
1485
 
1472
1486
  ```tsx
1473
- import { ChartArea, ChartBar, ChartLegend, ChartLegendContent, ChartLine, ChartPie, ChartTooltip, ChartTooltipContent, ChartXAxis, ChartYAxis } from '@7onic-ui/react/chart'const chartConfig = {
1487
+ import { Chart, ChartArea, ChartBar, ChartLegend, ChartLegendContent, ChartLine, ChartPie, ChartTooltip, ChartTooltipContent, ChartXAxis, ChartYAxis } from '@7onic-ui/react/chart'
1488
+
1489
+ const chartConfig = {
1474
1490
  revenue: { label: 'Revenue', color: 'var(--color-chart-1)' },
1475
1491
  profit: { label: 'Profit', color: 'var(--color-chart-2)' },
1476
1492
  }
@@ -1570,7 +1586,9 @@ type ChartConfig = {
1570
1586
  ### MetricCard
1571
1587
 
1572
1588
  ```tsx
1573
- import { MetricCard, MetricCardDescription, MetricCardHeader, MetricCardSymbol, MetricCardTitle, MetricCardTrend, MetricCardValue } from '@7onic-ui/react'<MetricCard>
1589
+ import { MetricCard, MetricCardDescription, MetricCardHeader, MetricCardSymbol, MetricCardTitle, MetricCardTrend, MetricCardValue } from '@7onic-ui/react'
1590
+
1591
+ <MetricCard>
1574
1592
  <MetricCardHeader>
1575
1593
  <MetricCardTitle>Revenue</MetricCardTitle>
1576
1594
  <MetricCardSymbol><DollarIcon /></MetricCardSymbol>
@@ -1599,176 +1617,439 @@ import { MetricCard, MetricCardDescription, MetricCardHeader, MetricCardSymbol,
1599
1617
 
1600
1618
  ---
1601
1619
 
1602
- # ═══ SECTION 4: COMPONENT USAGE GUIDE ═══
1603
-
1604
- ## Component Selection
1605
-
1606
- Before creating custom UI, check if 7onic already has it:
1607
-
1608
- | Need | Use This Component |
1609
- |---|---|
1610
- | Action trigger | Button, IconButton |
1611
- | Text input | Input (single line), Textarea (multi line) |
1612
- | Selection (one) | RadioGroup, Select, Segmented |
1613
- | Selection (many) | Checkbox, ToggleGroup |
1614
- | Boolean toggle | Switch, Toggle, Checkbox |
1615
- | Container | Card |
1616
- | Data table | Table |
1617
- | Tabs | Tabs |
1618
- | Collapsible | Accordion |
1619
- | Dialog | Modal |
1620
- | Side panel | Drawer |
1621
- | Hint text | Tooltip |
1622
- | Rich hint | Popover |
1623
- | Notification | Toast (imperative), Alert (inline) |
1624
- | Loading | Spinner (indeterminate), Progress (determinate), Skeleton (placeholder) |
1625
- | Navigation | Breadcrumb, Pagination, NavigationMenu |
1626
- | Data visualization | Chart (Line/Area/Bar/Pie), MetricCard |
1627
- | Metric display | MetricCard |
1628
- | Tag / chip | Badge (with `removable`) |
1629
- | Avatar | Avatar |
1630
- | Separator | Divider |
1631
-
1632
- **If the component exists, use it.** Don't build custom versions with HTML + classes.
1633
-
1634
- ---
1620
+ ## AI Components
1635
1621
 
1636
- ## Import Pattern
1622
+ ### TypingIndicator
1637
1623
 
1638
1624
  ```tsx
1639
- // ✅ Single import path
1640
- import { Button, Card, Input, toast } from '@7onic-ui/react'
1641
-
1642
- // ✅ Chart components use a separate entry point (recharts is optional)
1643
- import { ChartBar } from '@7onic-ui/react/chart'
1644
-
1645
- // ❌ Never import from internal paths
1646
- import { Button } from '@7onic-ui/react/components/button' // WRONG
1625
+ import { TypingIndicator } from '@7onic-ui/react'
1647
1626
 
1648
- // ❌ Never import Radix directly
1649
- import * as Dialog from '@radix-ui/react-dialog' // WRONG → use Modal
1650
- ```
1651
-
1652
- ---
1653
-
1654
- ## Compound Component Structure
1627
+ {/* Default — dots, muted, default size */}
1628
+ <TypingIndicator />
1655
1629
 
1656
- Compound components have **required sub-components**. Missing them causes errors or broken UI.
1630
+ {/* Cursor variant */}
1631
+ <TypingIndicator variant="cursor" />
1657
1632
 
1658
- **Modal — required structure:**
1659
- ```tsx
1660
- <Modal>
1661
- <ModalTrigger>...</ModalTrigger>
1662
- <ModalPortal> {/* ← Required for correct z-index */}
1663
- <ModalOverlay /> {/* ← Required for backdrop */}
1664
- <ModalContent>
1665
- <ModalHeader>
1666
- <ModalTitle>...</ModalTitle>
1667
- </ModalHeader>
1668
- <ModalBody>...</ModalBody>
1669
- </ModalContent>
1670
- </ModalPortal>
1671
- </Modal>
1672
- ```
1633
+ {/* Chat bubble */}
1634
+ <TypingIndicator variant="dots" color="muted" />
1673
1635
 
1674
- **Drawer — same pattern as Modal** (Portal + Overlay + Content required)
1636
+ {/* AI response — fast with label */}
1637
+ <TypingIndicator
1638
+ variant="dots"
1639
+ color="primary"
1640
+ speed="fast"
1641
+ showLabel
1642
+ label="AI is typing..."
1643
+ />
1675
1644
 
1676
- **Tooltip — Provider required:**
1677
- ```tsx
1678
- <TooltipProvider> {/* ← Required, wrap app once */}
1679
- <Tooltip>
1680
- <TooltipTrigger>...</TooltipTrigger>
1681
- <TooltipPortal>
1682
- <TooltipContent>...</TooltipContent>
1683
- </TooltipPortal>
1684
- </Tooltip>
1685
- </TooltipProvider>
1645
+ {/* Large cursor, primary color */}
1646
+ <TypingIndicator variant="cursor" size="lg" color="primary" />
1686
1647
  ```
1687
1648
 
1688
- **Toast — imperative API, no compound structure:**
1689
- ```tsx
1690
- // Place Toaster once in layout
1691
- <Toaster />
1692
- // Call toast() anywhere
1693
- toast.success('Done')
1694
- ```
1649
+ | Prop | Type | Default | Description |
1650
+ |---|---|---|---|
1651
+ | variant | `'dots' \| 'cursor'` | `'dots'` | Animation style |
1652
+ | size | `'sm' \| 'default' \| 'lg'` | `'default'` | Size |
1653
+ | color | `'default' \| 'primary' \| 'muted'` | `'muted'` | Color |
1654
+ | speed | `'slow' \| 'default' \| 'fast'` | `'default'` | Speed (dots only) |
1655
+ | label | `string` | `'Typing'` | aria-label and showLabel text |
1656
+ | showLabel | `boolean` | `false` | Show text label alongside indicator |
1695
1657
 
1696
1658
  ---
1697
1659
 
1698
- ## asChild Pattern (Slot)
1699
-
1700
- `asChild` replaces the component's DOM element with its child, keeping styles and behavior:
1660
+ ### QuickReply
1701
1661
 
1702
1662
  ```tsx
1703
- // ❌ Double <a> — broken HTML
1704
- <Link href="/about">
1705
- <Button>About</Button>
1706
- </Link>
1707
-
1708
- // ✅ Button renders as <a> with Button styles
1709
- <Button asChild>
1710
- <Link href="/about">About</Link>
1711
- </Button>
1712
-
1713
- // ✅ DropdownMenu item as link
1714
- <DropdownMenuItem asChild>
1715
- <Link href="/settings">Settings</Link>
1716
- </DropdownMenuItem>
1717
-
1718
- // ✅ Breadcrumb as Next.js Link
1719
- <BreadcrumbLink asChild>
1720
- <Link href="/">Home</Link>
1721
- </BreadcrumbLink>
1722
- ```
1663
+ import { QuickReply, QuickReplyItem } from '@7onic-ui/react'
1723
1664
 
1724
- **Use `asChild` when combining 7onic components with routing `<Link>`.**
1725
- Components that support `asChild`: Button, IconButton, Badge, Card, Modal.Trigger, Modal.Close, Drawer.Trigger, Drawer.Close, DropdownMenu.Item, Breadcrumb.Link, NavigationMenu.Link, Tooltip.Trigger, Popover.Trigger
1726
-
1727
- ---
1728
-
1729
- ## Props Usage
1665
+ {/* Basic suggested replies */}
1666
+ <QuickReply aria-label="Suggested replies">
1667
+ <QuickReplyItem>About payment</QuickReplyItem>
1668
+ <QuickReplyItem>Shipping info</QuickReplyItem>
1669
+ <QuickReplyItem>Return policy</QuickReplyItem>
1670
+ </QuickReply>
1730
1671
 
1731
- **Always use allowed values.** Don't pass arbitrary strings to variant/size/color props.
1672
+ {/* Primary color, filled variant */}
1673
+ <QuickReply color="primary" variant="filled" aria-label="Quick replies">
1674
+ <QuickReplyItem>Payment</QuickReplyItem>
1675
+ <QuickReplyItem>Shipping</QuickReplyItem>
1676
+ </QuickReply>
1732
1677
 
1733
- ```tsx
1734
- // ✅ Correct
1735
- <Button variant="solid" size="default" color="primary" />
1678
+ {/* Wrap layout for FAQ */}
1679
+ <QuickReply layout="wrap" aria-label="FAQ topics">
1680
+ <QuickReplyItem>Payments</QuickReplyItem>
1681
+ <QuickReplyItem>Shipping</QuickReplyItem>
1682
+ <QuickReplyItem>Returns</QuickReplyItem>
1683
+ <QuickReplyItem>Account</QuickReplyItem>
1684
+ </QuickReply>
1736
1685
 
1737
- // ❌ Wrong — invalid values
1738
- <Button variant="primary" /> // 'primary' is a color, not a variant
1739
- <Button size="medium" /> // Use 'md' or 'default', not 'medium'
1740
- <Button color="blue" /> // Use 'primary', not raw color names
1686
+ {/* With icon */}
1687
+ <QuickReply aria-label="Actions">
1688
+ <QuickReplyItem icon={<MessageCircle />}>Contact us</QuickReplyItem>
1689
+ <QuickReplyItem icon={<Package />}>Track order</QuickReplyItem>
1690
+ </QuickReply>
1741
1691
  ```
1742
1692
 
1743
- **`className` on components = layout ONLY** (margin, width, flex positioning). All visual styling (color, size, radius, variant) must use Props.
1744
-
1745
- **Style via Props, not className:**
1746
- ```tsx
1747
- // ✅ Use Props
1748
- <Button color="primary" size="lg" />
1749
- <Badge color="error" variant="subtle" />
1693
+ | Prop (QuickReply) | Type | Default | Description |
1694
+ |---|---|---|---|
1695
+ | layout | `'scroll' \| 'wrap'` | `'scroll'` | Chip layout mode |
1696
+ | variant | `'outline' \| 'filled' \| 'ghost'` | `'outline'` | Visual style |
1697
+ | color | `'default' \| 'primary'` | `'default'` | Color theme |
1698
+ | size | `'sm' \| 'default' \| 'lg'` | `'default'` | Chip size |
1699
+ | radius | `'md' \| 'lg' \| 'full'` | `'full'` | Border radius |
1700
+ | gap | `'sm' \| 'default' \| 'lg'` | `'default'` | Gap between chips |
1750
1701
 
1751
- // ❌ Don't override with className
1752
- <Button className="bg-blue-500 text-white" />
1753
- <Badge className="bg-red-100" />
1754
- ```
1702
+ | Prop (QuickReply.Item) | Type | Default | Description |
1703
+ |---|---|---|---|
1704
+ | icon | `ReactNode` | — | Leading icon |
1705
+ | asChild | `boolean` | `false` | Compose with custom element (Radix Slot) |
1706
+ | disabled | `boolean` | `false` | Disable the chip |
1707
+ | onClick | `() => void` | — | Click callback |
1755
1708
 
1756
1709
  ---
1757
1710
 
1758
- ## Form Patterns
1759
-
1760
- **Use Field wrapper** for labeled form elements with validation:
1711
+ ### ChatInput
1761
1712
 
1762
1713
  ```tsx
1763
- import { Field, FieldCharCount, FieldError, FieldLabel, Input, Textarea } from '@7onic-ui/react'{/* Text input with label + error */}
1764
- <Field error={errors.email}>
1765
- <FieldLabel required>Email</FieldLabel>
1766
- <Input placeholder="you@example.com" />
1767
- <FieldError />
1768
- </Field>
1714
+ import { ChatInput, ChatInputField, ChatInputSubmit } from '@7onic-ui/react'
1769
1715
 
1770
- {/* Textarea with character count */}
1771
- <Field>
1716
+ {/* Basic uncontrolled */}
1717
+ <ChatInput onSubmit={(value) => console.log(value)}>
1718
+ <ChatInputField placeholder="Ask me anything..." />
1719
+ <ChatInputSubmit />
1720
+ </ChatInput>
1721
+
1722
+ {/* Controlled mode */}
1723
+ const [value, setValue] = useState('')
1724
+ <ChatInput onSubmit={(v) => { handleSend(v); setValue('') }}>
1725
+ <ChatInputField
1726
+ value={value}
1727
+ onChange={(e) => setValue(e.target.value)}
1728
+ placeholder="Ask me anything..."
1729
+ />
1730
+ <ChatInputSubmit />
1731
+ </ChatInput>
1732
+
1733
+ {/* With loading state + stop */}
1734
+ <ChatInput onSubmit={handleSubmit}>
1735
+ <ChatInputField placeholder="Ask me anything..." />
1736
+ <ChatInputSubmit
1737
+ loading={isLoading}
1738
+ onStop={() => abortController.abort()}
1739
+ />
1740
+ </ChatInput>
1741
+
1742
+ {/* Character count */}
1743
+ <ChatInput onSubmit={(value) => console.log(value)}>
1744
+ <ChatInputField placeholder="Ask me anything..." showCount maxLength={500} />
1745
+ <ChatInputSubmit />
1746
+ </ChatInput>
1747
+
1748
+ {/* Filled variant, large, custom radius */}
1749
+ <ChatInput variant="filled" size="lg" radius="2xl" onSubmit={(v) => console.log(v)}>
1750
+ <ChatInputField placeholder="Ask me anything..." maxRows={6} />
1751
+ <ChatInputSubmit />
1752
+ </ChatInput>
1753
+
1754
+ {/* Inline layout (single-line field + button side by side) */}
1755
+ <ChatInput layout="inline" radius="full" onSubmit={(value) => console.log(value)}>
1756
+ <ChatInputField placeholder="Message..." />
1757
+ <ChatInputSubmit />
1758
+ </ChatInput>
1759
+
1760
+ {/* Inline with custom button radius */}
1761
+ <ChatInput layout="inline" radius="xl" onSubmit={handleSubmit}>
1762
+ <ChatInputField placeholder="Message..." />
1763
+ <ChatInputSubmit buttonRadius="full" loading={isLoading} onStop={handleStop} />
1764
+ </ChatInput>
1765
+ ```
1766
+
1767
+ | Prop (ChatInput) | Type | Default | Description |
1768
+ |---|---|---|---|
1769
+ | variant | `'outline' \| 'filled'` | `'outline'` | Visual style |
1770
+ | size | `'sm' \| 'default' \| 'lg'` | `'default'` | Size scale |
1771
+ | radius | `'sm' \| 'md' \| 'lg' \| 'xl' \| '2xl' \| 'full'` | `'xl'` | Corner radius (`'full'` available in inline layout) |
1772
+ | color | `'default' \| 'primary'` | `'default'` | Submit button color |
1773
+ | layout | `'default' \| 'inline'` | `'default'` | `'inline'` renders field and button side by side |
1774
+ | disabled | `boolean` | `false` | Disable input and submit |
1775
+ | onSubmit | `(value: string) => void` | — | Submit callback |
1776
+
1777
+ | Prop (ChatInput.Field) | Type | Default | Description |
1778
+ |---|---|---|---|
1779
+ | maxRows | `number` | `8` | Max rows before scrolling |
1780
+ | showCount | `boolean` | `false` | Show character counter (default layout only) |
1781
+ | maxLength | `number` | — | Max characters |
1782
+ | placeholder | `string` | — | Placeholder text |
1783
+
1784
+ | Prop (ChatInput.Submit) | Type | Default | Description |
1785
+ |---|---|---|---|
1786
+ | loading | `boolean` | `false` | Switch to stop icon — button stays enabled |
1787
+ | onStop | `() => void` | — | Called on click when loading |
1788
+ | buttonRadius | `'sm' \| 'md' \| 'lg' \| 'xl' \| '2xl' \| 'full'` | — | Override button radius (default: auto from container radius) |
1789
+ | children | `ReactNode` | — | Custom icon (default: send arrow) |
1790
+
1791
+ ### ChatMessage
1792
+
1793
+ ```tsx
1794
+ import { ChatMessage, ChatMessageAvatar, ChatMessageContent, ChatMessageFooter } from '@7onic-ui/react'
1795
+
1796
+ {/* Assistant message */}
1797
+ <ChatMessage role="assistant">
1798
+ <ChatMessageAvatar />
1799
+ <div className="flex flex-col gap-1">
1800
+ <ChatMessageContent>How can I help you today?</ChatMessageContent>
1801
+ <ChatMessageFooter timestamp="12:34" />
1802
+ </div>
1803
+ </ChatMessage>
1804
+
1805
+ {/* User message with status */}
1806
+ <ChatMessage role="user">
1807
+ <div className="flex flex-col gap-1 items-end">
1808
+ <ChatMessageContent>Thank you for your help!</ChatMessageContent>
1809
+ <ChatMessageFooter timestamp="12:34" status="read" />
1810
+ </div>
1811
+ </ChatMessage>
1812
+
1813
+ {/* Typing animation */}
1814
+ <ChatMessage role="assistant" typing>
1815
+ <ChatMessageAvatar />
1816
+ <ChatMessageContent />
1817
+ </ChatMessage>
1818
+
1819
+ {/* Custom avatar + hover actions */}
1820
+ <ChatMessage
1821
+ role="assistant"
1822
+ actions={<button aria-label="Copy">...</button>}
1823
+ >
1824
+ <ChatMessageAvatar initials="AI" />
1825
+ <div className="flex flex-col gap-1">
1826
+ <ChatMessageContent>Response text here.</ChatMessageContent>
1827
+ <ChatMessageFooter timestamp="12:34" />
1828
+ </div>
1829
+ </ChatMessage>
1830
+
1831
+ {/* User bubble with muted color (common pattern) */}
1832
+ <ChatMessage role="user" color="muted">
1833
+ <div className="flex flex-col gap-1 items-end">
1834
+ <ChatMessageContent>Message text</ChatMessageContent>
1835
+ <ChatMessageFooter timestamp="12:34" status="read" />
1836
+ </div>
1837
+ </ChatMessage>
1838
+
1839
+ {/* History (flat) layout — full-width, no footer */}
1840
+ <div className="flex flex-col gap-3">
1841
+ <ChatMessage role="assistant" variant="flat">
1842
+ <ChatMessageAvatar />
1843
+ <ChatMessageContent className="w-full">Here is the answer.</ChatMessageContent>
1844
+ </ChatMessage>
1845
+ <ChatMessage role="user" variant="flat" color="muted">
1846
+ <ChatMessageContent className="w-full">Thanks!</ChatMessageContent>
1847
+ </ChatMessage>
1848
+ </div>
1849
+ ```
1850
+
1851
+ | Prop (ChatMessage) | Type | Default | Description |
1852
+ |---|---|---|---|
1853
+ | role | `'assistant' \| 'user'` | `'assistant'` | Aligns left (assistant) or right (user) |
1854
+ | variant | `'bubble' \| 'flat'` | `'bubble'` | Bubble style with background/border, or flat with no fill |
1855
+ | color | `'default' \| 'muted' \| 'primary' \| 'dark'` | `'default'` | Bubble background color |
1856
+ | size | `'sm' \| 'default' \| 'lg'` | `'default'` | Size scale affecting padding and font |
1857
+ | radius | `'md' \| 'lg' \| 'xl' \| '2xl'` | `'2xl'` | Bubble corner radius |
1858
+ | tail | `boolean` | `true` | Asymmetric tail corner (sharp on avatar side) — bubble only |
1859
+ | avatarSize | `'sm' \| 'md' \| 'lg'` | — | Avatar size — also adjusts gap between avatar and bubble |
1860
+ | typing | `boolean` | `false` | Show animated typing dots inside Content |
1861
+ | actions | `ReactNode` | — | Hover-reveal action buttons (copy, react, etc.) |
1862
+
1863
+ | Prop (ChatMessage.Avatar) | Type | Default | Description |
1864
+ |---|---|---|---|
1865
+ | size | `'sm' \| 'md' \| 'lg'` | `'md'` | Avatar size: 24/28/32px |
1866
+ | src | `string` | — | Avatar image URL |
1867
+ | alt | `string` | `'Avatar'` | Alt text |
1868
+ | initials | `string` | — | 1–2 character initials (fallback) |
1869
+ | icon | `ReactNode` | — | Custom icon (fallback) |
1870
+
1871
+ | Prop (ChatMessage.Footer) | Type | Default | Description |
1872
+ |---|---|---|---|
1873
+ | timestamp | `string` | — | Pre-formatted time string |
1874
+ | status | `'sending' \| 'sent' \| 'read' \| 'error' \| ReactNode` | — | Delivery status (built-in presets or custom node) |
1875
+ | size | `'sm' \| 'default' \| 'lg'` | — | Size override (defaults to context value from root) |
1876
+
1877
+ ---
1878
+
1879
+ ---
1880
+
1881
+ # ═══ SECTION 4: COMPONENT USAGE GUIDE ═══
1882
+
1883
+ ## Component Selection
1884
+
1885
+ Before creating custom UI, check if 7onic already has it:
1886
+
1887
+ | Need | Use This Component |
1888
+ |---|---|
1889
+ | Action trigger | Button, IconButton |
1890
+ | Text input | Input (single line), Textarea (multi line) |
1891
+ | Selection (one) | RadioGroup, Select, Segmented |
1892
+ | Selection (many) | Checkbox, ToggleGroup |
1893
+ | Boolean toggle | Switch, Toggle, Checkbox |
1894
+ | Container | Card |
1895
+ | Data table | Table |
1896
+ | Tabs | Tabs |
1897
+ | Collapsible | Accordion |
1898
+ | Dialog | Modal |
1899
+ | Side panel | Drawer |
1900
+ | Hint text | Tooltip |
1901
+ | Rich hint | Popover |
1902
+ | Notification | Toast (imperative), Alert (inline) |
1903
+ | Loading | Spinner (indeterminate), Progress (determinate), Skeleton (placeholder) |
1904
+ | Navigation | Breadcrumb, Pagination, NavigationMenu |
1905
+ | Data visualization | Chart (Line/Area/Bar/Pie), MetricCard |
1906
+ | Metric display | MetricCard |
1907
+ | Tag / chip | Badge (with `removable`) |
1908
+ | Avatar | Avatar |
1909
+ | Separator | Divider |
1910
+
1911
+ **If the component exists, use it.** Don't build custom versions with HTML + classes.
1912
+
1913
+ ---
1914
+
1915
+ ## Import Pattern
1916
+
1917
+ ```tsx
1918
+ // ✅ Single import path
1919
+ import { Button, Card, Input, toast } from '@7onic-ui/react'
1920
+
1921
+ // ✅ Chart components use a separate entry point (recharts is optional)
1922
+ import { ChartBar } from '@7onic-ui/react/chart'
1923
+
1924
+ // ❌ Never import from internal paths
1925
+ import { Button } from '@7onic-ui/react/components/button' // WRONG
1926
+
1927
+ // ❌ Never import Radix directly
1928
+ import * as Dialog from '@radix-ui/react-dialog' // WRONG → use Modal
1929
+ ```
1930
+
1931
+ ---
1932
+
1933
+ ## Compound Component Structure
1934
+
1935
+ Compound components have **required sub-components**. Missing them causes errors or broken UI.
1936
+
1937
+ **Modal — required structure:**
1938
+ ```tsx
1939
+ <Modal>
1940
+ <ModalTrigger>...</ModalTrigger>
1941
+ <ModalPortal> {/* ← Required for correct z-index */}
1942
+ <ModalOverlay /> {/* ← Required for backdrop */}
1943
+ <ModalContent>
1944
+ <ModalHeader>
1945
+ <ModalTitle>...</ModalTitle>
1946
+ </ModalHeader>
1947
+ <ModalBody>...</ModalBody>
1948
+ </ModalContent>
1949
+ </ModalPortal>
1950
+ </Modal>
1951
+ ```
1952
+
1953
+ **Drawer — same pattern as Modal** (Portal + Overlay + Content required)
1954
+
1955
+ **Tooltip — Provider required:**
1956
+ ```tsx
1957
+ <TooltipProvider> {/* ← Required, wrap app once */}
1958
+ <Tooltip>
1959
+ <TooltipTrigger>...</TooltipTrigger>
1960
+ <TooltipPortal>
1961
+ <TooltipContent>...</TooltipContent>
1962
+ </TooltipPortal>
1963
+ </Tooltip>
1964
+ </TooltipProvider>
1965
+ ```
1966
+
1967
+ **Toast — imperative API, no compound structure:**
1968
+ ```tsx
1969
+ // Place Toaster once in layout
1970
+ <Toaster />
1971
+ // Call toast() anywhere
1972
+ toast.success('Done')
1973
+ ```
1974
+
1975
+ ---
1976
+
1977
+ ## asChild Pattern (Slot)
1978
+
1979
+ `asChild` replaces the component's DOM element with its child, keeping styles and behavior:
1980
+
1981
+ ```tsx
1982
+ // ❌ Double <a> — broken HTML
1983
+ <Link href="/about">
1984
+ <Button>About</Button>
1985
+ </Link>
1986
+
1987
+ // ✅ Button renders as <a> with Button styles
1988
+ <Button asChild>
1989
+ <Link href="/about">About</Link>
1990
+ </Button>
1991
+
1992
+ // ✅ DropdownMenu item as link
1993
+ <DropdownMenuItem asChild>
1994
+ <Link href="/settings">Settings</Link>
1995
+ </DropdownMenuItem>
1996
+
1997
+ // ✅ Breadcrumb as Next.js Link
1998
+ <BreadcrumbLink asChild>
1999
+ <Link href="/">Home</Link>
2000
+ </BreadcrumbLink>
2001
+ ```
2002
+
2003
+ **Use `asChild` when combining 7onic components with routing `<Link>`.**
2004
+ Components that support `asChild`: Button, IconButton, Badge, Card, Modal.Trigger, Modal.Close, Drawer.Trigger, Drawer.Close, DropdownMenu.Item, Breadcrumb.Link, NavigationMenu.Link, Tooltip.Trigger, Popover.Trigger
2005
+
2006
+ ---
2007
+
2008
+ ## Props Usage
2009
+
2010
+ **Always use allowed values.** Don't pass arbitrary strings to variant/size/color props.
2011
+
2012
+ ```tsx
2013
+ // ✅ Correct
2014
+ <Button variant="solid" size="default" color="primary" />
2015
+
2016
+ // ❌ Wrong — invalid values
2017
+ <Button variant="primary" /> // 'primary' is a color, not a variant
2018
+ <Button size="medium" /> // Use 'md' or 'default', not 'medium'
2019
+ <Button color="blue" /> // Use 'primary', not raw color names
2020
+ ```
2021
+
2022
+ **`className` on components = layout ONLY** (margin, width, flex positioning). All visual styling (color, size, radius, variant) must use Props.
2023
+
2024
+ **Style via Props, not className:**
2025
+ ```tsx
2026
+ // ✅ Use Props
2027
+ <Button color="primary" size="lg" />
2028
+ <Badge color="error" variant="subtle" />
2029
+
2030
+ // ❌ Don't override with className
2031
+ <Button className="bg-blue-500 text-white" />
2032
+ <Badge className="bg-red-100" />
2033
+ ```
2034
+
2035
+ ---
2036
+
2037
+ ## Form Patterns
2038
+
2039
+ **Use Field wrapper** for labeled form elements with validation:
2040
+
2041
+ ```tsx
2042
+ import { Field, FieldCharCount, FieldError, FieldLabel, Input, Textarea } from '@7onic-ui/react'
2043
+
2044
+ {/* Text input with label + error */}
2045
+ <Field error={errors.email}>
2046
+ <FieldLabel required>Email</FieldLabel>
2047
+ <Input placeholder="you@example.com" />
2048
+ <FieldError />
2049
+ </Field>
2050
+
2051
+ {/* Textarea with character count */}
2052
+ <Field>
1772
2053
  <FieldLabel>Bio</FieldLabel>
1773
2054
  <Textarea maxLength={200} />
1774
2055
  <FieldCharCount />
@@ -1948,255 +2229,6 @@ But if YOUR code uses React hooks (`useState`, `useEffect`) or event handlers (`
1948
2229
  | ChatMessage | Compound | bubble/flat | sm/default/lg | default/muted/primary/dark | role (assistant/user), tail, avatarSize, radius (md/lg/xl/2xl), typing, actions, Avatar/Content/Footer sub-components |
1949
2230
  ---
1950
2231
 
1951
- ### TypingIndicator
1952
-
1953
- ```tsx
1954
- import { TypingIndicator } from '@7onic-ui/react'{/* Default — dots, muted, default size */}
1955
- <TypingIndicator />
1956
-
1957
- {/* Cursor variant */}
1958
- <TypingIndicator variant="cursor" />
1959
-
1960
- {/* Chat bubble */}
1961
- <TypingIndicator variant="dots" color="muted" />
1962
-
1963
- {/* AI response — fast with label */}
1964
- <TypingIndicator
1965
- variant="dots"
1966
- color="primary"
1967
- speed="fast"
1968
- showLabel
1969
- label="AI is typing..."
1970
- />
1971
-
1972
- {/* Large cursor, primary color */}
1973
- <TypingIndicator variant="cursor" size="lg" color="primary" />
1974
- ```
1975
-
1976
- | Prop | Type | Default | Description |
1977
- |---|---|---|---|
1978
- | variant | `'dots' \| 'cursor'` | `'dots'` | Animation style |
1979
- | size | `'sm' \| 'default' \| 'lg'` | `'default'` | Size |
1980
- | color | `'default' \| 'primary' \| 'muted'` | `'muted'` | Color |
1981
- | speed | `'slow' \| 'default' \| 'fast'` | `'default'` | Speed (dots only) |
1982
- | label | `string` | `'Typing'` | aria-label and showLabel text |
1983
- | showLabel | `boolean` | `false` | Show text label alongside indicator |
1984
-
1985
- ---
1986
-
1987
- ### QuickReply
1988
-
1989
- ```tsx
1990
- import { QuickReply, QuickReplyItem } from '@7onic-ui/react'{/* Basic suggested replies */}
1991
- <QuickReply aria-label="Suggested replies">
1992
- <QuickReplyItem>About payment</QuickReplyItem>
1993
- <QuickReplyItem>Shipping info</QuickReplyItem>
1994
- <QuickReplyItem>Return policy</QuickReplyItem>
1995
- </QuickReply>
1996
-
1997
- {/* Primary color, filled variant */}
1998
- <QuickReply color="primary" variant="filled" aria-label="Quick replies">
1999
- <QuickReplyItem>Payment</QuickReplyItem>
2000
- <QuickReplyItem>Shipping</QuickReplyItem>
2001
- </QuickReply>
2002
-
2003
- {/* Wrap layout for FAQ */}
2004
- <QuickReply layout="wrap" aria-label="FAQ topics">
2005
- <QuickReplyItem>Payments</QuickReplyItem>
2006
- <QuickReplyItem>Shipping</QuickReplyItem>
2007
- <QuickReplyItem>Returns</QuickReplyItem>
2008
- <QuickReplyItem>Account</QuickReplyItem>
2009
- </QuickReply>
2010
-
2011
- {/* With icon */}
2012
- <QuickReply aria-label="Actions">
2013
- <QuickReplyItem icon={<MessageCircle />}>Contact us</QuickReplyItem>
2014
- <QuickReplyItem icon={<Package />}>Track order</QuickReplyItem>
2015
- </QuickReply>
2016
- ```
2017
-
2018
- | Prop (QuickReply) | Type | Default | Description |
2019
- |---|---|---|---|
2020
- | layout | `'scroll' \| 'wrap'` | `'scroll'` | Chip layout mode |
2021
- | variant | `'outline' \| 'filled' \| 'ghost'` | `'outline'` | Visual style |
2022
- | color | `'default' \| 'primary'` | `'default'` | Color theme |
2023
- | size | `'sm' \| 'default' \| 'lg'` | `'default'` | Chip size |
2024
- | radius | `'md' \| 'lg' \| 'full'` | `'full'` | Border radius |
2025
- | gap | `'sm' \| 'default' \| 'lg'` | `'default'` | Gap between chips |
2026
-
2027
- | Prop (QuickReply.Item) | Type | Default | Description |
2028
- |---|---|---|---|
2029
- | icon | `ReactNode` | — | Leading icon |
2030
- | asChild | `boolean` | `false` | Compose with custom element (Radix Slot) |
2031
- | disabled | `boolean` | `false` | Disable the chip |
2032
- | onClick | `() => void` | — | Click callback |
2033
-
2034
- ---
2035
-
2036
- ### ChatInput
2037
-
2038
- ```tsx
2039
- import { ChatInput, ChatInputField, ChatInputSubmit } from '@7onic-ui/react'{/* Basic uncontrolled */}
2040
- <ChatInput onSubmit={(value) => console.log(value)}>
2041
- <ChatInputField placeholder="Ask me anything..." />
2042
- <ChatInputSubmit />
2043
- </ChatInput>
2044
-
2045
- {/* Controlled mode */}
2046
- const [value, setValue] = useState('')
2047
- <ChatInput onSubmit={(v) => { handleSend(v); setValue('') }}>
2048
- <ChatInputField
2049
- value={value}
2050
- onChange={(e) => setValue(e.target.value)}
2051
- placeholder="Ask me anything..."
2052
- />
2053
- <ChatInputSubmit />
2054
- </ChatInput>
2055
-
2056
- {/* With loading state + stop */}
2057
- <ChatInput onSubmit={handleSubmit}>
2058
- <ChatInputField placeholder="Ask me anything..." />
2059
- <ChatInputSubmit
2060
- loading={isLoading}
2061
- onStop={() => abortController.abort()}
2062
- />
2063
- </ChatInput>
2064
-
2065
- {/* Character count */}
2066
- <ChatInput onSubmit={(value) => console.log(value)}>
2067
- <ChatInputField placeholder="Ask me anything..." showCount maxLength={500} />
2068
- <ChatInputSubmit />
2069
- </ChatInput>
2070
-
2071
- {/* Filled variant, large, custom radius */}
2072
- <ChatInput variant="filled" size="lg" radius="2xl" onSubmit={(v) => console.log(v)}>
2073
- <ChatInputField placeholder="Ask me anything..." maxRows={6} />
2074
- <ChatInputSubmit />
2075
- </ChatInput>
2076
-
2077
- {/* Inline layout (single-line field + button side by side) */}
2078
- <ChatInput layout="inline" radius="full" onSubmit={(value) => console.log(value)}>
2079
- <ChatInputField placeholder="Message..." />
2080
- <ChatInputSubmit />
2081
- </ChatInput>
2082
-
2083
- {/* Inline with custom button radius */}
2084
- <ChatInput layout="inline" radius="xl" onSubmit={handleSubmit}>
2085
- <ChatInputField placeholder="Message..." />
2086
- <ChatInputSubmit buttonRadius="full" loading={isLoading} onStop={handleStop} />
2087
- </ChatInput>
2088
- ```
2089
-
2090
- | Prop (ChatInput) | Type | Default | Description |
2091
- |---|---|---|---|
2092
- | variant | `'outline' \| 'filled'` | `'outline'` | Visual style |
2093
- | size | `'sm' \| 'default' \| 'lg'` | `'default'` | Size scale |
2094
- | radius | `'sm' \| 'md' \| 'lg' \| 'xl' \| '2xl' \| 'full'` | `'xl'` | Corner radius (`'full'` available in inline layout) |
2095
- | color | `'default' \| 'primary'` | `'default'` | Submit button color |
2096
- | layout | `'default' \| 'inline'` | `'default'` | `'inline'` renders field and button side by side |
2097
- | disabled | `boolean` | `false` | Disable input and submit |
2098
- | onSubmit | `(value: string) => void` | — | Submit callback |
2099
-
2100
- | Prop (ChatInput.Field) | Type | Default | Description |
2101
- |---|---|---|---|
2102
- | maxRows | `number` | `8` | Max rows before scrolling |
2103
- | showCount | `boolean` | `false` | Show character counter (default layout only) |
2104
- | maxLength | `number` | — | Max characters |
2105
- | placeholder | `string` | — | Placeholder text |
2106
-
2107
- | Prop (ChatInput.Submit) | Type | Default | Description |
2108
- |---|---|---|---|
2109
- | loading | `boolean` | `false` | Switch to stop icon — button stays enabled |
2110
- | onStop | `() => void` | — | Called on click when loading |
2111
- | buttonRadius | `'sm' \| 'md' \| 'lg' \| 'xl' \| '2xl' \| 'full'` | — | Override button radius (default: auto from container radius) |
2112
- | children | `ReactNode` | — | Custom icon (default: send arrow) |
2113
-
2114
- ### ChatMessage
2115
-
2116
- ```tsx
2117
- import { ChatMessage, ChatMessageAvatar, ChatMessageContent, ChatMessageFooter } from '@7onic-ui/react'{/* Assistant message */}
2118
- <ChatMessage role="assistant">
2119
- <ChatMessageAvatar />
2120
- <div className="flex flex-col gap-1">
2121
- <ChatMessageContent>How can I help you today?</ChatMessageContent>
2122
- <ChatMessageFooter timestamp="12:34" />
2123
- </div>
2124
- </ChatMessage>
2125
-
2126
- {/* User message with status */}
2127
- <ChatMessage role="user">
2128
- <div className="flex flex-col gap-1 items-end">
2129
- <ChatMessageContent>Thank you for your help!</ChatMessageContent>
2130
- <ChatMessageFooter timestamp="12:34" status="read" />
2131
- </div>
2132
- </ChatMessage>
2133
-
2134
- {/* Typing animation */}
2135
- <ChatMessage role="assistant" typing>
2136
- <ChatMessageAvatar />
2137
- <ChatMessageContent />
2138
- </ChatMessage>
2139
-
2140
- {/* Custom avatar + hover actions */}
2141
- <ChatMessage
2142
- role="assistant"
2143
- actions={<button aria-label="Copy">...</button>}
2144
- >
2145
- <ChatMessageAvatar initials="AI" />
2146
- <div className="flex flex-col gap-1">
2147
- <ChatMessageContent>Response text here.</ChatMessageContent>
2148
- <ChatMessageFooter timestamp="12:34" />
2149
- </div>
2150
- </ChatMessage>
2151
-
2152
- {/* User bubble with muted color (common pattern) */}
2153
- <ChatMessage role="user" color="muted">
2154
- <div className="flex flex-col gap-1 items-end">
2155
- <ChatMessageContent>Message text</ChatMessageContent>
2156
- <ChatMessageFooter timestamp="12:34" status="read" />
2157
- </div>
2158
- </ChatMessage>
2159
-
2160
- {/* History (flat) layout — full-width, no footer */}
2161
- <div className="flex flex-col gap-3">
2162
- <ChatMessage role="assistant" variant="flat">
2163
- <ChatMessageAvatar />
2164
- <ChatMessageContent className="w-full">Here is the answer.</ChatMessageContent>
2165
- </ChatMessage>
2166
- <ChatMessage role="user" variant="flat" color="muted">
2167
- <ChatMessageContent className="w-full">Thanks!</ChatMessageContent>
2168
- </ChatMessage>
2169
- </div>
2170
- ```
2171
-
2172
- | Prop (ChatMessage) | Type | Default | Description |
2173
- |---|---|---|---|
2174
- | role | `'assistant' \| 'user'` | `'assistant'` | Aligns left (assistant) or right (user) |
2175
- | variant | `'bubble' \| 'flat'` | `'bubble'` | Bubble style with background/border, or flat with no fill |
2176
- | color | `'default' \| 'muted' \| 'primary' \| 'dark'` | `'default'` | Bubble background color |
2177
- | size | `'sm' \| 'default' \| 'lg'` | `'default'` | Size scale affecting padding and font |
2178
- | radius | `'md' \| 'lg' \| 'xl' \| '2xl'` | `'2xl'` | Bubble corner radius |
2179
- | tail | `boolean` | `true` | Asymmetric tail corner (sharp on avatar side) — bubble only |
2180
- | avatarSize | `'sm' \| 'md' \| 'lg'` | — | Avatar size — also adjusts gap between avatar and bubble |
2181
- | typing | `boolean` | `false` | Show animated typing dots inside Content |
2182
- | actions | `ReactNode` | — | Hover-reveal action buttons (copy, react, etc.) |
2183
-
2184
- | Prop (ChatMessage.Avatar) | Type | Default | Description |
2185
- |---|---|---|---|
2186
- | size | `'sm' \| 'md' \| 'lg'` | `'md'` | Avatar size: 24/28/32px |
2187
- | src | `string` | — | Avatar image URL |
2188
- | alt | `string` | `'Avatar'` | Alt text |
2189
- | initials | `string` | — | 1–2 character initials (fallback) |
2190
- | icon | `ReactNode` | — | Custom icon (fallback) |
2191
-
2192
- | Prop (ChatMessage.Footer) | Type | Default | Description |
2193
- |---|---|---|---|
2194
- | timestamp | `string` | — | Pre-formatted time string |
2195
- | status | `'sending' \| 'sent' \| 'read' \| 'error' \| ReactNode` | — | Delivery status (built-in presets or custom node) |
2196
- | size | `'sm' \| 'default' \| 'lg'` | — | Size override (defaults to context value from root) |
2197
-
2198
- ---
2199
-
2200
2232
  ## Compound Recipe (opt-in self-wrapper)
2201
2233
 
2202
2234
  v0.3.0+ library exports Named only (`<CardHeader>`). To restore dot-notation (`<Card.Header>`) in your project, add a wrapper file. File location is flexible (`src/lib/card.tsx`, `lib/card.tsx`, `src/components/compound/card.tsx`, etc.) — pick one. Adjust the import source to match your install method: