@7onic-ui/react 0.3.6 โ†’ 0.3.8

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 +37 -7
  2. package/llms.txt +382 -377
  3. package/package.json +12 -8
package/README.md CHANGED
@@ -26,13 +26,13 @@
26
26
  | **๐ŸŽฏ** | **Zero design-code drift** | Design and code from a single vision. No handoff, no drift โ€” every component is pixel-verified against Figma. |
27
27
  | **๐Ÿ“ฆ** | **One JSON, every format** | `figma-tokens.json` auto-generates CSS, Tailwind v3, Tailwind v4, JS/TS, and JSON โ€” all in sync. |
28
28
  | **๐Ÿงฉ** | **shadcn freedom + MUI convenience** | shadcn's customization with none of its missing features. MUI's built-in power with none of its styling constraints. Both, by design. |
29
- | **โšก** | **npm or CLI โ€” your choice** | `npm install` for packages, `npx 7onic add` for local copy. Same components, two workflows. |
29
+ | **โšก** | **npm, CLI, or MCP โ€” three ways in** | `npm install` for packages, `npx 7onic add` for local copy, or `claude plugin install 7onic-design@7onic` so your AI agent can explore every token and component and run `validate_code` before a single file lands in your project. Same system, three workflows. |
30
30
  | **๐Ÿ”€** | **Only Tailwind v3+v4 dual support** | The ecosystem's only design system supporting both Tailwind versions. Same tokens, same DX. |
31
31
  | **๐Ÿช„** | **Framework-aware setup** | Detects Next.js / Vite, TypeScript, and Tailwind โ€” exits with a clear error if anything's missing. Auto-cleans Vite boilerplate (`.bak` backup), auto-wraps `*` reset in `@layer base` for Next.js + Tailwind v4. No Provider wrapper, no `globals.css` replacement. |
32
32
  | **๐ŸŽฎ** | **Built-in playground** | Interactive props editor + live code generation in docs. No Storybook setup needed. |
33
33
  | **๐ŸŒ—** | **Dark mode, zero config** | Light/dark themes built into tokens. System preference detection out of the box. |
34
34
  | **๐Ÿ”“** | **Framework-agnostic tokens** | Tokens ship as pure CSS variables. Use with Vue, Angular, Svelte, or vanilla CSS โ€” no React required. |
35
- | **๐Ÿค–** | **AI-ready** | Ships with `llms.txt` โ€” AI builds with design tokens, not hardcoded values. Zero config for Claude, Cursor, Copilot. |
35
+ | **๐Ÿค–** | **AI-ready** | `llms.txt` for any AI tool, plus an MCP server that installs as a Claude Code plugin in one command (no `npm install`, ~3 MB). AI builds with design tokens, not hardcoded values, and `validate_code` rejects what docs alone can't prevent. Claude Code, Cursor, Copilot. |
36
36
  | **๐ŸŒ** | **CJK-first typography** | Type scale tuned for Japanese kanji, Korean hangul, and Latin โ€” not an afterthought. |
37
37
  | **๐Ÿ”** | **Supply chain verified** | Cryptographically signed releases (npm provenance), automated vulnerability scanning in CI, reproducible builds. You can verify every package came from this exact GitHub commit โ€” not a hijacked account. |
38
38
  | **๐Ÿ”ฅ** | **Relentlessly updated** | Actively maintained with continuous research, refinement, and new features. Not abandoned โ€” ever. |
@@ -127,6 +127,8 @@ export default {
127
127
  ```
128
128
  </details>
129
129
 
130
+ <br>
131
+
130
132
  **Option B โ€” CLI (local file copy)**
131
133
 
132
134
  ```bash
@@ -134,7 +136,9 @@ npx 7onic init # detects framework, installs deps, configures CSS automaticall
134
136
  npx 7onic add button card input
135
137
  ```
136
138
 
137
- Use components:
139
+ <br>
140
+
141
+ **Use components:**
138
142
 
139
143
  ```tsx
140
144
  import { Button, Card, CardHeader, CardTitle, CardContent } from '@7onic-ui/react'
@@ -165,7 +169,7 @@ import { Chart, type ChartConfig } from '@7onic-ui/react/chart' // charts: sepa
165
169
  | **Navigation** | Breadcrumb, NavigationMenu, Pagination | 3 |
166
170
  | **AI** | TypingIndicator, QuickReply, ChatInput, ChatMessage | 4 |
167
171
 
168
- **42 components** โ€” all with CVA variants, controlled + uncontrolled modes, `forwardRef`, and **Named exports** (`CardHeader`, `ModalContent`, `TabsList`, ...). If you prefer dot-notation (`<Card.Header>`), drop in a [Compound Recipe wrapper](docs/decisions/NAMED-PRIMARY-MIGRATION.md) โ€” opt-in, Client Components only.
172
+ **42 components** โ€” all with CVA variants, controlled + uncontrolled modes, `forwardRef`, and **Named exports** (`CardHeader`, `ModalContent`, `TabsList`, ...). If you prefer dot-notation (`<Card.Header>`), drop in a Compound Recipe wrapper โ€” opt-in, Client Components only.
169
173
 
170
174
  ---
171
175
 
@@ -269,7 +273,31 @@ Once loaded, AI automatically uses `bg-primary` instead of `bg-blue-500`, spacin
269
273
 
270
274
  Works with Claude Code, Cursor, GitHub Copilot, ChatGPT, and any AI tool that reads text files.
271
275
 
272
- **Setup guides**: [Tokens](https://7onic.design/design-tokens/ai) ยท [Components](https://7onic.design/components/ai)
276
+ ### MCP Server
277
+
278
+ For agents that speak MCP, 7onic also ships a stdio server: token search, the full
279
+ component catalog, layout recipes, and `validate_code` rule checking โ€” with queries
280
+ and violation messages in English, Japanese, and Korean. On Claude Code it installs
281
+ as a plugin in one command (no `npm install`, ~3 MB):
282
+
283
+ ```bash
284
+ claude plugin marketplace add itonys/7onic && claude plugin install 7onic-design@7onic
285
+ ```
286
+
287
+ Other MCP clients: clone this repo and point your MCP config at `mcp/dist/index.js`
288
+ (the bundle is committed โ€” nothing to build).
289
+
290
+ ### AI Kit โ€” skills & agent
291
+
292
+ The plugin also ships two Claude Code skills and an agent on top of the MCP server:
293
+ `/7onic-setup` (project detection, token CSS wiring, idempotent health check),
294
+ `/7onic-design` (guided build workflow โ€” discovery โ†’ tokens โ†’ layout โ†’ a mandatory
295
+ `validate_code` loop), and `7onic-design-agent` for delegated page/component builds.
296
+ Not on the plugin? Get the same kit via `npx 7onic init --claude` (writes them into
297
+ your project's `.claude/`) or copy the files from
298
+ [7onic.design/components/mcp](https://7onic.design/components/mcp#ai-kit).
299
+
300
+ **Setup guides**: [Tokens](https://7onic.design/design-tokens/ai) ยท [Components](https://7onic.design/components/ai) ยท [MCP Server & AI Kit](https://7onic.design/components/mcp)
273
301
 
274
302
  ---
275
303
 
@@ -296,8 +324,10 @@ Works with Claude Code, Cursor, GitHub Copilot, ChatGPT, and any AI tool that re
296
324
  - [x] Automated doc verification (8 checks, AST-powered, blocks publish on error)
297
325
  - [x] Automated component verification (7 checks โ€” hardcoded colors, tokens, dark mode, dead code)
298
326
  - [x] Multilingual documentation โ€” English, Japanese, Korean (powered by next-intl)
299
- - [x] npm package distribution โ€” `@7onic-ui/react` + `@7onic-ui/tokens` v0.3.6
327
+ - [x] npm package distribution โ€” `@7onic-ui/react` + `@7onic-ui/tokens` v0.3.8
300
328
  - [x] AI integration โ€” `llms.txt` standard, setup guides for Claude Code / Cursor / Copilot / ChatGPT
329
+ - [x] MCP server โ€” token search, component catalog, layout recipes, `validate_code` rule checking (en/ja/ko), Claude Code plugin one-command install
330
+ - [x] AI Kit โ€” `/7onic-setup` + `/7onic-design` skills and a design agent (plugin, `npx 7onic init --claude`, or manual copy)
301
331
  - [x] `npx 7onic add` CLI (shadcn-style) โ€” source copy with dependency resolution
302
332
  - [x] `npx 7onic init` full workflow โ€” framework/TS/Tailwind detection (abort if missing), Vite `@/` alias auto-configure, base deps install, CSS token import, Vite boilerplate cleanup (`.bak` backup), Next.js+v4 `*` reset auto-wrap, `cn()` + `7onic.json` generation
303
333
  - [x] Technical blog โ€” [blog.7onic.design](https://blog.7onic.design) ("Design to Code" series)
@@ -325,5 +355,5 @@ MIT
325
355
  <p align="center">
326
356
  <strong>One JSON, every format โ€” from Figma to production.</strong><br>
327
357
  Independently built.<br>
328
- <sub>Last updated: 2026-04-29 (v0.3.6)</sub>
358
+ <sub>Last updated: 2026-10-22 (v0.3.8)</sub>
329
359
  </p>
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
 
@@ -369,7 +370,7 @@ Badge, Button, ButtonGroup, Checkbox, Divider, IconButton, Input, Progress, Skel
369
370
 
370
371
  ---
371
372
 
372
- # โ•โ•โ• SECTION 3: ALL COMPONENTS (42) โ•โ•โ•
373
+ # โ•โ•โ• SECTION 3: ALL COMPONENTS (41) โ•โ•โ•
373
374
 
374
375
  ---
375
376
 
@@ -558,7 +559,7 @@ import { Button, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMe
558
559
  | flush | `boolean` | `false` | Full-width items (no padding) |
559
560
  | sideOffset | `number` | `4` | Gap from trigger |
560
561
 
561
- **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
562
563
 
563
564
  ---
564
565
 
@@ -832,7 +833,7 @@ import { Badge } from '@7onic-ui/react'
832
833
  | variant | `'solid' \| 'subtle' \| 'outline'` | `'subtle'` | Visual style |
833
834
  | color | `'default' \| 'primary' \| 'success' \| 'warning' \| 'error' \| 'info'` | `'default'` | Color scheme |
834
835
  | size | `'sm' \| 'default' \| 'lg'` | `'default'` | Badge size |
835
- | radius | `'sm' \| 'md' \| 'lg' \| 'xl' \| 'full'` | `'full'` | Border radius |
836
+ | radius | `'sm' \| 'base' \| 'md' \| 'lg' \| 'full'` | `'full'` | Border radius |
836
837
  | icon | `ReactNode` | โ€” | Leading icon |
837
838
  | dot | `boolean` | `false` | Status dot indicator |
838
839
  | removable | `boolean` | `false` | Shows remove button |
@@ -1483,7 +1484,7 @@ import { NavigationMenu, NavigationMenuContent, NavigationMenuGroup, NavigationM
1483
1484
  All chart types use the Chart namespace:
1484
1485
 
1485
1486
  ```tsx
1486
- import { ChartArea, ChartBar, ChartLegend, ChartLegendContent, ChartLine, ChartPie, ChartTooltip, ChartTooltipContent, ChartXAxis, ChartYAxis } from '@7onic-ui/react/chart'
1487
+ import { Chart, ChartArea, ChartBar, ChartLegend, ChartLegendContent, ChartLine, ChartPie, ChartTooltip, ChartTooltipContent, ChartXAxis, ChartYAxis } from '@7onic-ui/react/chart'
1487
1488
 
1488
1489
  const chartConfig = {
1489
1490
  revenue: { label: 'Revenue', color: 'var(--color-chart-1)' },
@@ -1616,157 +1617,418 @@ import { MetricCard, MetricCardDescription, MetricCardHeader, MetricCardSymbol,
1616
1617
 
1617
1618
  ---
1618
1619
 
1619
- # โ•โ•โ• SECTION 4: COMPONENT USAGE GUIDE โ•โ•โ•
1620
-
1621
- ## Component Selection
1622
-
1623
- Before creating custom UI, check if 7onic already has it:
1624
-
1625
- | Need | Use This Component |
1626
- |---|---|
1627
- | Action trigger | Button, IconButton |
1628
- | Text input | Input (single line), Textarea (multi line) |
1629
- | Selection (one) | RadioGroup, Select, Segmented |
1630
- | Selection (many) | Checkbox, ToggleGroup |
1631
- | Boolean toggle | Switch, Toggle, Checkbox |
1632
- | Container | Card |
1633
- | Data table | Table |
1634
- | Tabs | Tabs |
1635
- | Collapsible | Accordion |
1636
- | Dialog | Modal |
1637
- | Side panel | Drawer |
1638
- | Hint text | Tooltip |
1639
- | Rich hint | Popover |
1640
- | Notification | Toast (imperative), Alert (inline) |
1641
- | Loading | Spinner (indeterminate), Progress (determinate), Skeleton (placeholder) |
1642
- | Navigation | Breadcrumb, Pagination, NavigationMenu |
1643
- | Data visualization | Chart (Line/Area/Bar/Pie), MetricCard |
1644
- | Metric display | MetricCard |
1645
- | Tag / chip | Badge (with `removable`) |
1646
- | Avatar | Avatar |
1647
- | Separator | Divider |
1620
+ ## AI Components
1648
1621
 
1649
- **If the component exists, use it.** Don't build custom versions with HTML + classes.
1622
+ ### TypingIndicator
1650
1623
 
1651
- ---
1624
+ ```tsx
1625
+ import { TypingIndicator } from '@7onic-ui/react'
1652
1626
 
1653
- ## Import Pattern
1627
+ {/* Default โ€” dots, muted, default size */}
1628
+ <TypingIndicator />
1654
1629
 
1655
- ```tsx
1656
- // โœ… Single import path
1657
- import { Button, Card, Input, toast } from '@7onic-ui/react'
1630
+ {/* Cursor variant */}
1631
+ <TypingIndicator variant="cursor" />
1658
1632
 
1659
- // โœ… Chart components use a separate entry point (recharts is optional)
1660
- import { ChartBar } from '@7onic-ui/react/chart'
1633
+ {/* Chat bubble */}
1634
+ <TypingIndicator variant="dots" color="muted" />
1661
1635
 
1662
- // โŒ Never import from internal paths
1663
- import { Button } from '@7onic-ui/react/components/button' // WRONG
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
+ />
1664
1644
 
1665
- // โŒ Never import Radix directly
1666
- import * as Dialog from '@radix-ui/react-dialog' // WRONG โ†’ use Modal
1645
+ {/* Large cursor, primary color */}
1646
+ <TypingIndicator variant="cursor" size="lg" color="primary" />
1667
1647
  ```
1668
1648
 
1669
- ---
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 |
1670
1657
 
1671
- ## Compound Component Structure
1658
+ ---
1672
1659
 
1673
- Compound components have **required sub-components**. Missing them causes errors or broken UI.
1660
+ ### QuickReply
1674
1661
 
1675
- **Modal โ€” required structure:**
1676
1662
  ```tsx
1677
- <Modal>
1678
- <ModalTrigger>...</ModalTrigger>
1679
- <ModalPortal> {/* โ† Required for correct z-index */}
1680
- <ModalOverlay /> {/* โ† Required for backdrop */}
1681
- <ModalContent>
1682
- <ModalHeader>
1683
- <ModalTitle>...</ModalTitle>
1684
- </ModalHeader>
1685
- <ModalBody>...</ModalBody>
1686
- </ModalContent>
1687
- </ModalPortal>
1688
- </Modal>
1689
- ```
1663
+ import { QuickReply, QuickReplyItem } from '@7onic-ui/react'
1690
1664
 
1691
- **Drawer โ€” same pattern as Modal** (Portal + Overlay + Content required)
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>
1692
1671
 
1693
- **Tooltip โ€” Provider required:**
1694
- ```tsx
1695
- <TooltipProvider> {/* โ† Required, wrap app once */}
1696
- <Tooltip>
1697
- <TooltipTrigger>...</TooltipTrigger>
1698
- <TooltipPortal>
1699
- <TooltipContent>...</TooltipContent>
1700
- </TooltipPortal>
1701
- </Tooltip>
1702
- </TooltipProvider>
1703
- ```
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>
1704
1677
 
1705
- **Toast โ€” imperative API, no compound structure:**
1706
- ```tsx
1707
- // Place Toaster once in layout
1708
- <Toaster />
1709
- // Call toast() anywhere
1710
- toast.success('Done')
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>
1685
+
1686
+ {/* With icon */}
1687
+ <QuickReply aria-label="Actions">
1688
+ <QuickReplyItem icon={<MessageCircle />}>Contact us</QuickReplyItem>
1689
+ <QuickReplyItem icon={<Package />}>Track order</QuickReplyItem>
1690
+ </QuickReply>
1711
1691
  ```
1712
1692
 
1713
- ---
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 |
1714
1701
 
1715
- ## asChild Pattern (Slot)
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 |
1716
1708
 
1717
- `asChild` replaces the component's DOM element with its child, keeping styles and behavior:
1709
+ ---
1710
+
1711
+ ### ChatInput
1718
1712
 
1719
1713
  ```tsx
1720
- // โŒ Double <a> โ€” broken HTML
1721
- <Link href="/about">
1722
- <Button>About</Button>
1723
- </Link>
1714
+ import { ChatInput, ChatInputField, ChatInputSubmit } from '@7onic-ui/react'
1724
1715
 
1725
- // โœ… Button renders as <a> with Button styles
1726
- <Button asChild>
1727
- <Link href="/about">About</Link>
1728
- </Button>
1716
+ {/* Basic uncontrolled */}
1717
+ <ChatInput onSubmit={(value) => console.log(value)}>
1718
+ <ChatInputField placeholder="Ask me anything..." />
1719
+ <ChatInputSubmit />
1720
+ </ChatInput>
1729
1721
 
1730
- // โœ… DropdownMenu item as link
1731
- <DropdownMenuItem asChild>
1732
- <Link href="/settings">Settings</Link>
1733
- </DropdownMenuItem>
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>
1734
1732
 
1735
- // โœ… Breadcrumb as Next.js Link
1736
- <BreadcrumbLink asChild>
1737
- <Link href="/">Home</Link>
1738
- </BreadcrumbLink>
1739
- ```
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>
1740
1741
 
1741
- **Use `asChild` when combining 7onic components with routing `<Link>`.**
1742
- 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
1742
+ {/* Character count */}
1743
+ <ChatInput onSubmit={(value) => console.log(value)}>
1744
+ <ChatInputField placeholder="Ask me anything..." showCount maxLength={500} />
1745
+ <ChatInputSubmit />
1746
+ </ChatInput>
1743
1747
 
1744
- ---
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>
1745
1753
 
1746
- ## Props Usage
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>
1747
1759
 
1748
- **Always use allowed values.** Don't pass arbitrary strings to variant/size/color props.
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
+ ```
1749
1766
 
1750
- ```tsx
1751
- // โœ… Correct
1752
- <Button variant="solid" size="default" color="primary" />
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 |
1753
1776
 
1754
- // โŒ Wrong โ€” invalid values
1755
- <Button variant="primary" /> // 'primary' is a color, not a variant
1756
- <Button size="medium" /> // Use 'md' or 'default', not 'medium'
1757
- <Button color="blue" /> // Use 'primary', not raw color names
1758
- ```
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 |
1759
1783
 
1760
- **`className` on components = layout ONLY** (margin, width, flex positioning). All visual styling (color, size, radius, variant) must use Props.
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
1761
1792
 
1762
- **Style via Props, not className:**
1763
1793
  ```tsx
1764
- // โœ… Use Props
1765
- <Button color="primary" size="lg" />
1766
- <Badge color="error" variant="subtle" />
1794
+ import { ChatMessage, ChatMessageAvatar, ChatMessageContent, ChatMessageFooter } from '@7onic-ui/react'
1767
1795
 
1768
- // โŒ Don't override with className
1769
- <Button className="bg-blue-500 text-white" />
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" />
1770
2032
  <Badge className="bg-red-100" />
1771
2033
  ```
1772
2034
 
@@ -1967,263 +2229,6 @@ But if YOUR code uses React hooks (`useState`, `useEffect`) or event handlers (`
1967
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 |
1968
2230
  ---
1969
2231
 
1970
- ### TypingIndicator
1971
-
1972
- ```tsx
1973
- import { TypingIndicator } from '@7onic-ui/react'
1974
-
1975
- {/* Default โ€” dots, muted, default size */}
1976
- <TypingIndicator />
1977
-
1978
- {/* Cursor variant */}
1979
- <TypingIndicator variant="cursor" />
1980
-
1981
- {/* Chat bubble */}
1982
- <TypingIndicator variant="dots" color="muted" />
1983
-
1984
- {/* AI response โ€” fast with label */}
1985
- <TypingIndicator
1986
- variant="dots"
1987
- color="primary"
1988
- speed="fast"
1989
- showLabel
1990
- label="AI is typing..."
1991
- />
1992
-
1993
- {/* Large cursor, primary color */}
1994
- <TypingIndicator variant="cursor" size="lg" color="primary" />
1995
- ```
1996
-
1997
- | Prop | Type | Default | Description |
1998
- |---|---|---|---|
1999
- | variant | `'dots' \| 'cursor'` | `'dots'` | Animation style |
2000
- | size | `'sm' \| 'default' \| 'lg'` | `'default'` | Size |
2001
- | color | `'default' \| 'primary' \| 'muted'` | `'muted'` | Color |
2002
- | speed | `'slow' \| 'default' \| 'fast'` | `'default'` | Speed (dots only) |
2003
- | label | `string` | `'Typing'` | aria-label and showLabel text |
2004
- | showLabel | `boolean` | `false` | Show text label alongside indicator |
2005
-
2006
- ---
2007
-
2008
- ### QuickReply
2009
-
2010
- ```tsx
2011
- import { QuickReply, QuickReplyItem } from '@7onic-ui/react'
2012
-
2013
- {/* Basic suggested replies */}
2014
- <QuickReply aria-label="Suggested replies">
2015
- <QuickReplyItem>About payment</QuickReplyItem>
2016
- <QuickReplyItem>Shipping info</QuickReplyItem>
2017
- <QuickReplyItem>Return policy</QuickReplyItem>
2018
- </QuickReply>
2019
-
2020
- {/* Primary color, filled variant */}
2021
- <QuickReply color="primary" variant="filled" aria-label="Quick replies">
2022
- <QuickReplyItem>Payment</QuickReplyItem>
2023
- <QuickReplyItem>Shipping</QuickReplyItem>
2024
- </QuickReply>
2025
-
2026
- {/* Wrap layout for FAQ */}
2027
- <QuickReply layout="wrap" aria-label="FAQ topics">
2028
- <QuickReplyItem>Payments</QuickReplyItem>
2029
- <QuickReplyItem>Shipping</QuickReplyItem>
2030
- <QuickReplyItem>Returns</QuickReplyItem>
2031
- <QuickReplyItem>Account</QuickReplyItem>
2032
- </QuickReply>
2033
-
2034
- {/* With icon */}
2035
- <QuickReply aria-label="Actions">
2036
- <QuickReplyItem icon={<MessageCircle />}>Contact us</QuickReplyItem>
2037
- <QuickReplyItem icon={<Package />}>Track order</QuickReplyItem>
2038
- </QuickReply>
2039
- ```
2040
-
2041
- | Prop (QuickReply) | Type | Default | Description |
2042
- |---|---|---|---|
2043
- | layout | `'scroll' \| 'wrap'` | `'scroll'` | Chip layout mode |
2044
- | variant | `'outline' \| 'filled' \| 'ghost'` | `'outline'` | Visual style |
2045
- | color | `'default' \| 'primary'` | `'default'` | Color theme |
2046
- | size | `'sm' \| 'default' \| 'lg'` | `'default'` | Chip size |
2047
- | radius | `'md' \| 'lg' \| 'full'` | `'full'` | Border radius |
2048
- | gap | `'sm' \| 'default' \| 'lg'` | `'default'` | Gap between chips |
2049
-
2050
- | Prop (QuickReply.Item) | Type | Default | Description |
2051
- |---|---|---|---|
2052
- | icon | `ReactNode` | โ€” | Leading icon |
2053
- | asChild | `boolean` | `false` | Compose with custom element (Radix Slot) |
2054
- | disabled | `boolean` | `false` | Disable the chip |
2055
- | onClick | `() => void` | โ€” | Click callback |
2056
-
2057
- ---
2058
-
2059
- ### ChatInput
2060
-
2061
- ```tsx
2062
- import { ChatInput, ChatInputField, ChatInputSubmit } from '@7onic-ui/react'
2063
-
2064
- {/* Basic uncontrolled */}
2065
- <ChatInput onSubmit={(value) => console.log(value)}>
2066
- <ChatInputField placeholder="Ask me anything..." />
2067
- <ChatInputSubmit />
2068
- </ChatInput>
2069
-
2070
- {/* Controlled mode */}
2071
- const [value, setValue] = useState('')
2072
- <ChatInput onSubmit={(v) => { handleSend(v); setValue('') }}>
2073
- <ChatInputField
2074
- value={value}
2075
- onChange={(e) => setValue(e.target.value)}
2076
- placeholder="Ask me anything..."
2077
- />
2078
- <ChatInputSubmit />
2079
- </ChatInput>
2080
-
2081
- {/* With loading state + stop */}
2082
- <ChatInput onSubmit={handleSubmit}>
2083
- <ChatInputField placeholder="Ask me anything..." />
2084
- <ChatInputSubmit
2085
- loading={isLoading}
2086
- onStop={() => abortController.abort()}
2087
- />
2088
- </ChatInput>
2089
-
2090
- {/* Character count */}
2091
- <ChatInput onSubmit={(value) => console.log(value)}>
2092
- <ChatInputField placeholder="Ask me anything..." showCount maxLength={500} />
2093
- <ChatInputSubmit />
2094
- </ChatInput>
2095
-
2096
- {/* Filled variant, large, custom radius */}
2097
- <ChatInput variant="filled" size="lg" radius="2xl" onSubmit={(v) => console.log(v)}>
2098
- <ChatInputField placeholder="Ask me anything..." maxRows={6} />
2099
- <ChatInputSubmit />
2100
- </ChatInput>
2101
-
2102
- {/* Inline layout (single-line field + button side by side) */}
2103
- <ChatInput layout="inline" radius="full" onSubmit={(value) => console.log(value)}>
2104
- <ChatInputField placeholder="Message..." />
2105
- <ChatInputSubmit />
2106
- </ChatInput>
2107
-
2108
- {/* Inline with custom button radius */}
2109
- <ChatInput layout="inline" radius="xl" onSubmit={handleSubmit}>
2110
- <ChatInputField placeholder="Message..." />
2111
- <ChatInputSubmit buttonRadius="full" loading={isLoading} onStop={handleStop} />
2112
- </ChatInput>
2113
- ```
2114
-
2115
- | Prop (ChatInput) | Type | Default | Description |
2116
- |---|---|---|---|
2117
- | variant | `'outline' \| 'filled'` | `'outline'` | Visual style |
2118
- | size | `'sm' \| 'default' \| 'lg'` | `'default'` | Size scale |
2119
- | radius | `'sm' \| 'md' \| 'lg' \| 'xl' \| '2xl' \| 'full'` | `'xl'` | Corner radius (`'full'` available in inline layout) |
2120
- | color | `'default' \| 'primary'` | `'default'` | Submit button color |
2121
- | layout | `'default' \| 'inline'` | `'default'` | `'inline'` renders field and button side by side |
2122
- | disabled | `boolean` | `false` | Disable input and submit |
2123
- | onSubmit | `(value: string) => void` | โ€” | Submit callback |
2124
-
2125
- | Prop (ChatInput.Field) | Type | Default | Description |
2126
- |---|---|---|---|
2127
- | maxRows | `number` | `8` | Max rows before scrolling |
2128
- | showCount | `boolean` | `false` | Show character counter (default layout only) |
2129
- | maxLength | `number` | โ€” | Max characters |
2130
- | placeholder | `string` | โ€” | Placeholder text |
2131
-
2132
- | Prop (ChatInput.Submit) | Type | Default | Description |
2133
- |---|---|---|---|
2134
- | loading | `boolean` | `false` | Switch to stop icon โ€” button stays enabled |
2135
- | onStop | `() => void` | โ€” | Called on click when loading |
2136
- | buttonRadius | `'sm' \| 'md' \| 'lg' \| 'xl' \| '2xl' \| 'full'` | โ€” | Override button radius (default: auto from container radius) |
2137
- | children | `ReactNode` | โ€” | Custom icon (default: send arrow) |
2138
-
2139
- ### ChatMessage
2140
-
2141
- ```tsx
2142
- import { ChatMessage, ChatMessageAvatar, ChatMessageContent, ChatMessageFooter } from '@7onic-ui/react'
2143
-
2144
- {/* Assistant message */}
2145
- <ChatMessage role="assistant">
2146
- <ChatMessageAvatar />
2147
- <div className="flex flex-col gap-1">
2148
- <ChatMessageContent>How can I help you today?</ChatMessageContent>
2149
- <ChatMessageFooter timestamp="12:34" />
2150
- </div>
2151
- </ChatMessage>
2152
-
2153
- {/* User message with status */}
2154
- <ChatMessage role="user">
2155
- <div className="flex flex-col gap-1 items-end">
2156
- <ChatMessageContent>Thank you for your help!</ChatMessageContent>
2157
- <ChatMessageFooter timestamp="12:34" status="read" />
2158
- </div>
2159
- </ChatMessage>
2160
-
2161
- {/* Typing animation */}
2162
- <ChatMessage role="assistant" typing>
2163
- <ChatMessageAvatar />
2164
- <ChatMessageContent />
2165
- </ChatMessage>
2166
-
2167
- {/* Custom avatar + hover actions */}
2168
- <ChatMessage
2169
- role="assistant"
2170
- actions={<button aria-label="Copy">...</button>}
2171
- >
2172
- <ChatMessageAvatar initials="AI" />
2173
- <div className="flex flex-col gap-1">
2174
- <ChatMessageContent>Response text here.</ChatMessageContent>
2175
- <ChatMessageFooter timestamp="12:34" />
2176
- </div>
2177
- </ChatMessage>
2178
-
2179
- {/* User bubble with muted color (common pattern) */}
2180
- <ChatMessage role="user" color="muted">
2181
- <div className="flex flex-col gap-1 items-end">
2182
- <ChatMessageContent>Message text</ChatMessageContent>
2183
- <ChatMessageFooter timestamp="12:34" status="read" />
2184
- </div>
2185
- </ChatMessage>
2186
-
2187
- {/* History (flat) layout โ€” full-width, no footer */}
2188
- <div className="flex flex-col gap-3">
2189
- <ChatMessage role="assistant" variant="flat">
2190
- <ChatMessageAvatar />
2191
- <ChatMessageContent className="w-full">Here is the answer.</ChatMessageContent>
2192
- </ChatMessage>
2193
- <ChatMessage role="user" variant="flat" color="muted">
2194
- <ChatMessageContent className="w-full">Thanks!</ChatMessageContent>
2195
- </ChatMessage>
2196
- </div>
2197
- ```
2198
-
2199
- | Prop (ChatMessage) | Type | Default | Description |
2200
- |---|---|---|---|
2201
- | role | `'assistant' \| 'user'` | `'assistant'` | Aligns left (assistant) or right (user) |
2202
- | variant | `'bubble' \| 'flat'` | `'bubble'` | Bubble style with background/border, or flat with no fill |
2203
- | color | `'default' \| 'muted' \| 'primary' \| 'dark'` | `'default'` | Bubble background color |
2204
- | size | `'sm' \| 'default' \| 'lg'` | `'default'` | Size scale affecting padding and font |
2205
- | radius | `'md' \| 'lg' \| 'xl' \| '2xl'` | `'2xl'` | Bubble corner radius |
2206
- | tail | `boolean` | `true` | Asymmetric tail corner (sharp on avatar side) โ€” bubble only |
2207
- | avatarSize | `'sm' \| 'md' \| 'lg'` | โ€” | Avatar size โ€” also adjusts gap between avatar and bubble |
2208
- | typing | `boolean` | `false` | Show animated typing dots inside Content |
2209
- | actions | `ReactNode` | โ€” | Hover-reveal action buttons (copy, react, etc.) |
2210
-
2211
- | Prop (ChatMessage.Avatar) | Type | Default | Description |
2212
- |---|---|---|---|
2213
- | size | `'sm' \| 'md' \| 'lg'` | `'md'` | Avatar size: 24/28/32px |
2214
- | src | `string` | โ€” | Avatar image URL |
2215
- | alt | `string` | `'Avatar'` | Alt text |
2216
- | initials | `string` | โ€” | 1โ€“2 character initials (fallback) |
2217
- | icon | `ReactNode` | โ€” | Custom icon (fallback) |
2218
-
2219
- | Prop (ChatMessage.Footer) | Type | Default | Description |
2220
- |---|---|---|---|
2221
- | timestamp | `string` | โ€” | Pre-formatted time string |
2222
- | status | `'sending' \| 'sent' \| 'read' \| 'error' \| ReactNode` | โ€” | Delivery status (built-in presets or custom node) |
2223
- | size | `'sm' \| 'default' \| 'lg'` | โ€” | Size override (defaults to context value from root) |
2224
-
2225
- ---
2226
-
2227
2232
  ## Compound Recipe (opt-in self-wrapper)
2228
2233
 
2229
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:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@7onic-ui/react",
3
- "version": "0.3.6",
3
+ "version": "0.3.8",
4
4
  "private": false,
5
5
  "sideEffects": [
6
6
  "*.css"
@@ -51,9 +51,10 @@
51
51
  "verify:components": "tsx scripts/verify-components.ts",
52
52
  "verify:framework-compat": "tsx scripts/verify-framework-compat.ts",
53
53
  "verify:llms-examples": "tsx scripts/verify-llms-examples.ts",
54
+ "verify:mcp": "cd mcp && npm run verify-drift && npm run verify-validate",
54
55
  "verify:publish": "tsx scripts/verify-publish.ts",
55
56
  "smoke": "bash scripts/smoke-test.sh",
56
- "prepublishOnly": "npm run verify:framework-compat && npm run verify:llms-examples && npm run build:lib && npm run verify:publish && npm run smoke"
57
+ "prepublishOnly": "npm run verify:framework-compat && npm run verify:llms-examples && npm run verify:mcp && npm run build:lib && npm run verify:publish && npm run smoke"
57
58
  },
58
59
  "dependencies": {
59
60
  "@radix-ui/react-accordion": "^1.2.0",
@@ -79,8 +80,6 @@
79
80
  "@radix-ui/react-tooltip": "^1.1.0",
80
81
  "class-variance-authority": "^0.7.0",
81
82
  "clsx": "^2.1.0",
82
- "jsonc-parser": "^3.3.1",
83
- "next-intl": "^4.9.1",
84
83
  "tailwind-merge": "^2.3.0"
85
84
  },
86
85
  "peerDependencies": {
@@ -106,14 +105,16 @@
106
105
  "autoprefixer": "^10.4.19",
107
106
  "cmdk": "^1.1.1",
108
107
  "eslint": "^8.57.0",
109
- "eslint-config-next": "^15.0.0",
108
+ "eslint-config-next": "^15.5.28",
110
109
  "eslint-config-prettier": "^9.1.0",
111
110
  "eslint-plugin-react": "^7.34.0",
112
111
  "eslint-plugin-react-hooks": "^4.6.0",
112
+ "jsonc-parser": "^3.3.1",
113
113
  "lucide-react": "^0.400.0",
114
- "next": "^15.5.15",
114
+ "next": "^15.5.28",
115
+ "next-intl": "^4.14.9",
115
116
  "picocolors": "^1.1.1",
116
- "postcss": "^8.4.38",
117
+ "postcss": "^8.5.31",
117
118
  "prettier": "^3.3.0",
118
119
  "react": "^19.0.0",
119
120
  "react-dom": "^19.0.0",
@@ -149,5 +150,8 @@
149
150
  "engines": {
150
151
  "node": ">=18"
151
152
  },
152
- "packageManager": "npm@10.9.1+sha512.c89530d37c4baa38afd43e76a077a84b9aa63840b986426584fd5c5a54ab0a0b21bb1595c851042b733784b0b43706d36a494b4d8ae1a086a762cb8d3f95942a"
153
+ "packageManager": "npm@10.9.1+sha512.c89530d37c4baa38afd43e76a077a84b9aa63840b986426584fd5c5a54ab0a0b21bb1595c851042b733784b0b43706d36a494b4d8ae1a086a762cb8d3f95942a",
154
+ "overrides": {
155
+ "postcss": "$postcss"
156
+ }
153
157
  }