Alpha 35 [v3] (#5830)
* fix(component): support compound pattern in server component * fix(component): keep accordion and chip in sync with compound pattern * fix(component): type of forward refs * fix(calendar): temporary workaround for ref error * fix(storybook): imports * refactor: migration from dot notation to separted components to support RSC * refactor: migrate to React 19 ref pattern - remove forwardRef wrappers and explicit ref declarations from all components * refactor: provider context removed as it is not longer needed on react 19 * feat: made the migration smoother by still supporting the "dot" exports but adjusting the main compound component * fix: compound patter, radio group api, ref on react 19 * refactor(switch): split switch and switch-group into separate components following radio/radio-group pattern * chore(changelog): update v3.0.0-alpha.35 release notes and date * fix(page): update version label to reflect RSC support * chore(changelog): update examples to use new component names CardRoot and TabsRoot * fix(changelog): update release notes for v3.0.0-alpha.35, refactor Switch component to align with Radio/RadioGroup pattern, and clarify migration steps * fix: broken storybook (#5836) * fix(disclosure-group): broken api * chore(radio): remove storybook * chore: alpha 35 released --------- Co-authored-by: Tianen Pang <32772271+tianenpang@users.noreply.github.com> Co-authored-by: WK <wingkwong.code@gmail.com>
This commit is contained in:
+2
-2
@@ -2,8 +2,8 @@
|
||||
"mode": "pre",
|
||||
"tag": "alpha",
|
||||
"initialVersions": {
|
||||
"@heroui/react": "3.0.0-alpha.34",
|
||||
"@heroui/styles": "3.0.0-alpha.34"
|
||||
"@heroui/react": "3.0.0-alpha.35",
|
||||
"@heroui/styles": "3.0.0-alpha.35"
|
||||
},
|
||||
"changesets": ["pink-monkeys-notice"]
|
||||
}
|
||||
|
||||
@@ -12,6 +12,35 @@ icon: clock-arrow-rotate-left
|
||||
## Latest Release
|
||||
|
||||
|
||||
### v3.0.0-alpha.35
|
||||
|
||||
**October 21, 2025**
|
||||
|
||||
#### React Server Components Support
|
||||
- Fixed critical issue where compound components didn't work in React Server Components (RSC)
|
||||
- Moved compound pattern logic from components to index files, resolving `"use client"` conflicts
|
||||
- **(⚠️ Breaking change)**: Main component now requires `.Root` suffix (e.g., `<Avatar>` → `<Avatar.Root>`)
|
||||
- Named exports remain unchanged and fully supported
|
||||
|
||||
#### React 19 Improvements
|
||||
- Removed `forwardRef` (now native in [React 19](https://react.dev/blog/2024/12/05/react-19#ref-as-a-prop))
|
||||
- Simplified Context usage (`Context.Provider` → [React 19](https://react.dev/blog/2024/12/05/react-19#context-as-a-provider))
|
||||
|
||||
#### Switch Component Refactoring
|
||||
- **(⚠️ Breaking change)**: Split Switch and SwitchGroup into separate components
|
||||
- Cleaner API: `<SwitchGroup>` replaces `<Switch.Group>` and `<Switch.GroupItems>`
|
||||
- Matches Radio/RadioGroup pattern for consistency
|
||||
- Separate styles, types, and implementations
|
||||
|
||||
#### Affected Components
|
||||
All compound components now require `.Root` suffix: `Accordion`, `Avatar`, `Card`, `Disclosure`, `Fieldset`, `Kbd`, `Link`, `Popover`, `Radio`, `Switch`, `Tabs`, `Tooltip`
|
||||
|
||||
[Read full release notes →](/docs/changelog/v3-0-0-alpha-35)
|
||||
|
||||
---
|
||||
|
||||
## Previous Releases
|
||||
|
||||
### v3.0.0-alpha.34
|
||||
|
||||
**October 15, 2025**
|
||||
@@ -26,10 +55,6 @@ icon: clock-arrow-rotate-left
|
||||
|
||||
[Read full release notes →](/docs/changelog/v3-0-0-alpha-34)
|
||||
|
||||
---
|
||||
|
||||
## Previous Releases
|
||||
|
||||
### v3.0.0-alpha.33
|
||||
|
||||
**October 5, 2025**
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
"title": "Changelog",
|
||||
"description": "HeroUI v3 Release Notes",
|
||||
"root": false,
|
||||
"pages": ["changelog", "v3-0-0-alpha-34"]
|
||||
"pages": ["changelog", "v3-0-0-alpha-35"]
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ description: Card component redesign, CloseButton, MCP Server for AI assistants
|
||||
---
|
||||
|
||||
<div className="flex items-center gap-3 mb-6">
|
||||
<span className="text-sm text-neutral-500 dark:text-neutral-400">October 1, 2025</span>
|
||||
<span className="text-sm text-muted">October 1, 2025</span>
|
||||
</div>
|
||||
|
||||
This release adds AI development tools, updates the [Card component](/docs/components/card) API, and improves the developer experience.
|
||||
|
||||
@@ -4,7 +4,7 @@ description: RAC upgrade, Tabs indicator redesign, Switch size variant, Related
|
||||
---
|
||||
|
||||
<div className="flex items-center gap-3 mb-6">
|
||||
<span className="text-sm text-neutral-500 dark:text-neutral-400">October 5, 2025</span>
|
||||
<span className="text-sm text-muted">October 5, 2025</span>
|
||||
</div>
|
||||
|
||||
This release upgrades React Aria Components, redesigns the Tabs indicator, adds Switch sizes, and includes component showcases.
|
||||
|
||||
@@ -4,7 +4,7 @@ description: Essentials for building forms with a clean API Form, TextField, Rad
|
||||
---
|
||||
|
||||
<div className="flex items-center gap-3 mb-6">
|
||||
<span className="text-sm text-neutral-500 dark:text-neutral-400">October 15, 2025</span>
|
||||
<span className="text-sm text-muted">October 15, 2025</span>
|
||||
</div>
|
||||
|
||||
This release introduces Form-based components, form field tokens, reorganizes Storybook, and aligns data-slot markers across components.
|
||||
|
||||
@@ -0,0 +1,401 @@
|
||||
---
|
||||
title: v3.0.0-alpha.35
|
||||
description: React Server Components support for compound components, React 19 improvements, and critical bug fixes.
|
||||
---
|
||||
|
||||
<div className="flex items-center gap-3 mb-6">
|
||||
<span className="text-sm text-muted">October 21, 2025</span>
|
||||
</div>
|
||||
|
||||
This release fixes a critical issue where **compound components didn't work correctly in React Server Components (RSC)**. Additionally, this release adopts React 19 best practices by removing `forwardRef` and simplifying context usage. The Switch component has been refactored to match the Radio/RadioGroup pattern, providing a cleaner and more consistent API.
|
||||
|
||||
## Installation
|
||||
|
||||
Update to the latest version:
|
||||
|
||||
<Tabs items={["npm", "pnpm", "yarn", "bun"]}>
|
||||
<Tab value="npm">
|
||||
```bash
|
||||
npm i @heroui/styles@alpha @heroui/react@alpha
|
||||
```
|
||||
</Tab>
|
||||
<Tab value="pnpm">
|
||||
```bash
|
||||
pnpm add @heroui/styles@alpha @heroui/react@alpha
|
||||
```
|
||||
</Tab>
|
||||
<Tab value="yarn">
|
||||
```bash
|
||||
yarn add @heroui/styles@alpha @heroui/react@alpha
|
||||
```
|
||||
</Tab>
|
||||
<Tab value="bun">
|
||||
```bash
|
||||
bun add @heroui/styles@alpha @heroui/react@alpha
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
<Callout type="info">
|
||||
**Using AI assistants?** Simply prompt "Hey Cursor, update HeroUI to the latest version" and your AI assistant will automatically compare versions and apply the necessary changes. Learn more about the [HeroUI MCP Server](/docs/ui-for-agents/mcp-server).
|
||||
</Callout>
|
||||
|
||||
## What's New
|
||||
|
||||
### React Server Components Support
|
||||
|
||||
Compound components now work correctly in React Server Components. The previous implementation had the compound pattern logic inside components, which conflicted with the `"use client"` directive. This has been fixed by moving the pattern logic to component index files.
|
||||
|
||||
### React 19 Improvements
|
||||
|
||||
This release adopts React 19 best practices:
|
||||
|
||||
1. **Removed `forwardRef`**: No longer needed in React 19, where `ref` is now a prop ([React 19 docs](https://react.dev/blog/2024/12/05/react-19#ref-as-a-prop))
|
||||
2. **Simplified Context**: `Context.Provider` replaced with just `Context` ([React 19 docs](https://react.dev/blog/2024/12/05/react-19#context-as-a-provider))
|
||||
|
||||
### Switch Component Architecture Improvement
|
||||
|
||||
The Switch component has been refactored to follow the same clean separation pattern as Radio/RadioGroup:
|
||||
|
||||
- **Separate Components**: Switch and SwitchGroup are now independent components (previously combined)
|
||||
- **Cleaner API**: `<SwitchGroup>` replaces the nested `<Switch.Group>` and `<Switch.GroupItems>` pattern
|
||||
- **Better Organization**: Separate styles, types, and implementations for each component
|
||||
- **Consistent Pattern**: Matches the Radio/RadioGroup architecture for a more predictable API
|
||||
|
||||
**Before:**
|
||||
```tsx
|
||||
<Switch.Group>
|
||||
<Switch.GroupItems>
|
||||
<Switch.Root>...</Switch.Root>
|
||||
</Switch.GroupItems>
|
||||
</Switch.Group>
|
||||
```
|
||||
|
||||
**After:**
|
||||
```tsx
|
||||
<SwitchGroup>
|
||||
<Switch.Root>...</Switch.Root>
|
||||
<Switch.Root>...</Switch.Root>
|
||||
</SwitchGroup>
|
||||
```
|
||||
|
||||
## ⚠️ Breaking Changes
|
||||
|
||||
### Main Component Requires `.Root` Suffix
|
||||
|
||||
To support React Server Components, the compound component pattern has been restructured. The main component now requires the `.Root` suffix when using the compound pattern.
|
||||
|
||||
**Before:**
|
||||
```tsx
|
||||
import { Avatar } from "@heroui/react"
|
||||
|
||||
<Avatar>
|
||||
<Avatar.Image src="/images/avatar.jpeg" alt="Junior Garcia" />
|
||||
<Avatar.Fallback>JR</Avatar.Fallback>
|
||||
</Avatar>
|
||||
```
|
||||
|
||||
**After:**
|
||||
```tsx
|
||||
import { Avatar } from "@heroui/react"
|
||||
|
||||
<Avatar.Root>
|
||||
<Avatar.Image src="/images/avatar.jpeg" alt="Junior Garcia" />
|
||||
<Avatar.Fallback>JR</Avatar.Fallback>
|
||||
</Avatar.Root>
|
||||
```
|
||||
|
||||
**Note:** Named exports (e.g., `<Avatar>`, `<AvatarImage>`, `<AvatarFallback>`) remain unchanged and fully supported.
|
||||
|
||||
### Switch Component API Changes
|
||||
|
||||
The Switch component grouping API has been restructured to match the Radio/RadioGroup pattern:
|
||||
|
||||
**Before:**
|
||||
```tsx
|
||||
import { Switch } from "@heroui/react"
|
||||
|
||||
<Switch.Group orientation="horizontal">
|
||||
<Switch.GroupItems>
|
||||
<Switch.Root name="notifications">
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Label>Notifications</Label>
|
||||
</Switch.Root>
|
||||
<Switch.Root name="marketing">
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Label>Marketing</Label>
|
||||
</Switch.Root>
|
||||
</Switch.GroupItems>
|
||||
</Switch.Group>
|
||||
```
|
||||
|
||||
**After:**
|
||||
```tsx
|
||||
import { Switch, SwitchGroup } from "@heroui/react"
|
||||
|
||||
<SwitchGroup orientation="horizontal">
|
||||
<Switch.Root name="notifications">
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Label>Notifications</Label>
|
||||
</Switch.Root>
|
||||
<Switch.Root name="marketing">
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Label>Marketing</Label>
|
||||
</Switch.Root>
|
||||
</SwitchGroup>
|
||||
```
|
||||
|
||||
This change helps to:
|
||||
|
||||
- **Separate Components**: Switch and SwitchGroup are now independent components (previously combined)
|
||||
- **Cleaner API**: `<SwitchGroup>` replaces the nested `<Switch.Group>` and `<Switch.GroupItems>` pattern
|
||||
- **Better Organization**: Separate styles, types, and implementations for each component
|
||||
- **Consistent Pattern**: Matches the Radio/RadioGroup architecture for a more predictable API
|
||||
|
||||
|
||||
**Migration Steps:**
|
||||
1. Import `SwitchGroup` separately: `import { Switch, SwitchGroup } from "@heroui/react"`
|
||||
2. Replace `<Switch.Group>` with `<SwitchGroup>`
|
||||
3. Remove the nested `<Switch.GroupItems>` wrapper
|
||||
4. Individual `Switch.Root` components remain unchanged
|
||||
|
||||
#### Affected Components
|
||||
|
||||
All compound components are affected:
|
||||
|
||||
- `Accordion` → `Accordion.Root`
|
||||
- `Avatar` → `Avatar.Root`
|
||||
- `Card` → `Card.Root`
|
||||
- `Disclosure` → `Disclosure.Root`
|
||||
- `Fieldset` → `Fieldset.Root`
|
||||
- `Kbd` → `Kbd.Root`
|
||||
- `Link` → `Link.Root`
|
||||
- `Popover` → `Popover.Root`
|
||||
- `RadioGroup` → `RadioGroup.Root`
|
||||
- `Switch` → `Switch.Root`
|
||||
- `Tabs` → `Tabs.Root`
|
||||
- `Tooltip` → `Tooltip.Root`
|
||||
|
||||
## Migration Guide
|
||||
|
||||
You have two options for using HeroUI compound components:
|
||||
|
||||
### Option 1: Update to Use `.Root` (Compound Pattern)
|
||||
|
||||
If you're using the compound pattern (dot notation), update your code to use `.Root` for the main component:
|
||||
|
||||
**Card Example:**
|
||||
```tsx
|
||||
import { Card } from "@heroui/react"
|
||||
|
||||
<Card.Root>
|
||||
<Card.Header>
|
||||
<Card.Title>Card Title</Card.Title>
|
||||
<Card.Description>Card description</Card.Description>
|
||||
</Card.Header>
|
||||
<Card.Content>
|
||||
Card content
|
||||
</Card.Content>
|
||||
<Card.Footer>
|
||||
Card footer
|
||||
</Card.Footer>
|
||||
</Card.Root>
|
||||
```
|
||||
|
||||
**Tabs Example:**
|
||||
```tsx
|
||||
import { Tabs } from "@heroui/react"
|
||||
|
||||
<Tabs.Root>
|
||||
<Tabs.ListWrapper>
|
||||
<Tabs.List>
|
||||
<Tabs.Tab id="tab1">Tab 1<Tabs.Indicator /></Tabs.Tab>
|
||||
<Tabs.Tab id="tab2">Tab 2<Tabs.Indicator /></Tabs.Tab>
|
||||
</Tabs.List>
|
||||
</Tabs.ListWrapper>
|
||||
<Tabs.Panel id="tab1">Panel 1</Tabs.Panel>
|
||||
<Tabs.Panel id="tab2">Panel 2</Tabs.Panel>
|
||||
</Tabs.Root>
|
||||
```
|
||||
|
||||
[See more examples in the documentation](/docs/components/card)
|
||||
|
||||
**Avatar Example:**
|
||||
```tsx
|
||||
import { Avatar } from "@heroui/react"
|
||||
|
||||
<Avatar.Root>
|
||||
<Avatar.Image alt="John Doe" src="..." />
|
||||
<Avatar.Fallback>JD</Avatar.Fallback>
|
||||
</Avatar.Root>
|
||||
```
|
||||
|
||||
[See more examples in the documentation](/docs/components/avatar)
|
||||
|
||||
### Option 2: Use Named Exports
|
||||
|
||||
We added support for named exports for all compound components. You can use them like this:
|
||||
|
||||
**Card Example:**
|
||||
```tsx
|
||||
import {
|
||||
CardRoot,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
CardDescription,
|
||||
CardContent,
|
||||
CardFooter,
|
||||
} from "@heroui/react"
|
||||
|
||||
<CardRoot>
|
||||
<CardHeader>
|
||||
<CardTitle>Card Title</CardTitle>
|
||||
<CardDescription>Card description</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
Card content
|
||||
</CardContent>
|
||||
<CardFooter>
|
||||
Card footer
|
||||
</CardFooter>
|
||||
</CardRoot>
|
||||
```
|
||||
|
||||
**Tabs Example:**
|
||||
```tsx
|
||||
import { TabsRoot, TabListWrapper, TabList, Tab, TabIndicator, TabPanel } from "@heroui/react"
|
||||
|
||||
<TabsRoot>
|
||||
<TabListWrapper>
|
||||
<TabList>
|
||||
<Tab id="tab1">Tab 1<TabIndicator /></Tab>
|
||||
<Tab id="tab2">Tab 2<TabIndicator /></Tab>
|
||||
</TabList>
|
||||
</TabListWrapper>
|
||||
<TabPanel id="tab1">Panel 1</TabPanel>
|
||||
<TabPanel id="tab2">Panel 2</TabPanel>
|
||||
</TabsRoot>
|
||||
```
|
||||
|
||||
**Avatar Example:**
|
||||
```tsx
|
||||
import { Avatar, AvatarImage, AvatarFallback } from "@heroui/react"
|
||||
|
||||
<Avatar>
|
||||
<AvatarImage alt="John Doe" src="..." />
|
||||
<AvatarFallback>JD</AvatarFallback>
|
||||
</Avatar>
|
||||
```
|
||||
|
||||
### Migration Steps
|
||||
|
||||
If you're using the compound pattern, you only need to update the main component to use `.Root`:
|
||||
|
||||
1. **Find all instances of compound components** (e.g., `<Avatar>` with `<Avatar.Image>` inside)
|
||||
|
||||
2. **Add `.Root` to the main component**:
|
||||
```tsx
|
||||
// Before
|
||||
<Avatar>
|
||||
<Avatar.Image ... />
|
||||
</Avatar>
|
||||
|
||||
// After
|
||||
<Avatar.Root>
|
||||
<Avatar.Image ... />
|
||||
</Avatar.Root>
|
||||
```
|
||||
|
||||
3. **That's it!** All child components (e.g., `Avatar.Image`, `Avatar.Fallback`) remain unchanged.
|
||||
|
||||
### Complete Migration Reference
|
||||
|
||||
| Component | Named Export Pattern | Compound Pattern (with `.Root`) | Additional Changes |
|
||||
|-----------|---------------------|---------------------|---------------------|
|
||||
| **Accordion** | `<Accordion>` | `<Accordion.Root>` | - |
|
||||
| **Avatar** | `<Avatar>` | `<Avatar.Root>` | - |
|
||||
| **Card** | `<Card>` | `<Card.Root>` | - |
|
||||
| **Disclosure** | `<Disclosure>` | `<Disclosure.Root>` | - |
|
||||
| **Fieldset** | `<Fieldset>` | `<Fieldset.Root>` | - |
|
||||
| **Kbd** | `<Kbd>` | `<Kbd.Root>` | - |
|
||||
| **Link** | `<Link>` | `<Link.Root>` | - |
|
||||
| **Popover** | `<Popover>` | `<Popover.Root>` | - |
|
||||
| **Radio** | `<Radio>` | `<Radio.Root>` | - |
|
||||
| **Switch** | `<Switch>`, `<SwitchControl>` | `<Switch.Root>`, `<Switch.Control>` | `<Switch.Group>` → `<SwitchGroup>` (separate component) |
|
||||
| **Tabs** | `<Tabs>`, `<TabList>` | `<Tabs.Root>`, `<Tabs.List>` | - |
|
||||
| **Tooltip** | `<Tooltip>`, `<TooltipTrigger>` | `<Tooltip.Root>`, `<Tooltip.Trigger>` | - |
|
||||
|
||||
### Automated Migration
|
||||
|
||||
For large codebases using the compound pattern, you can use find-and-replace:
|
||||
|
||||
```bash
|
||||
# Example for Avatar component
|
||||
# Update the main component to use .Root
|
||||
sed -i 's/<Avatar>/<Avatar.Root>/g' **/*.tsx
|
||||
sed -i 's/<\/Avatar>/<\/Avatar.Root>/g' **/*.tsx
|
||||
|
||||
# Switch component requires additional steps
|
||||
# First, ensure SwitchGroup is imported
|
||||
# Then replace Switch.Group with SwitchGroup
|
||||
sed -i 's/<Switch\.Group/<SwitchGroup/g' **/*.tsx
|
||||
sed -i 's/<\/Switch\.Group>/<\/SwitchGroup>/g' **/*.tsx
|
||||
|
||||
# Remove Switch.GroupItems wrapper
|
||||
sed -i 's/<Switch\.GroupItems>//g' **/*.tsx
|
||||
sed -i 's/<\/Switch\.GroupItems>//g' **/*.tsx
|
||||
|
||||
# Repeat for other compound components (Card, Tabs, etc.)
|
||||
# Note: This only affects files using the compound pattern
|
||||
```
|
||||
|
||||
**Important:**
|
||||
- Be careful with automated replacements. Make sure you're only replacing compound pattern usage, not named exports.
|
||||
- For Switch migrations, verify that `SwitchGroup` is imported: `import { Switch, SwitchGroup } from "@heroui/react"`
|
||||
- Test your code after running automated migrations to ensure all changes are correct.
|
||||
|
||||
## Why This Change?
|
||||
|
||||
This change was necessary to fix React Server Components compatibility. The previous implementation had architectural limitations:
|
||||
|
||||
1. **RSC Compatibility**: Compound pattern logic conflicted with `"use client"` directives
|
||||
2. **React 19 Readiness**: Removes deprecated patterns like `forwardRef` and `Context.Provider`
|
||||
3. **Cleaner Architecture**: Pattern logic is now in index files, not component files
|
||||
4. **Better Separation**: Server and client components can now work together seamlessly
|
||||
|
||||
## Documentation Updates
|
||||
|
||||
Component documentation will be updated to reflect the new patterns:
|
||||
|
||||
- Examples will show the compound pattern with `.Root`
|
||||
- Named export examples remain valid and supported
|
||||
- Migration guides will help you transition smoothly
|
||||
- Both patterns are fully supported and work identically
|
||||
|
||||
## Need Help?
|
||||
|
||||
If you encounter any issues during migration:
|
||||
|
||||
1. **Compound pattern users**: Update the main component to use `.Root` (e.g., `<Avatar>` → `<Avatar.Root>`)
|
||||
2. **Named export users**: No changes needed - your code continues to work as-is
|
||||
3. Check the component documentation for examples
|
||||
4. Report issues at: [GitHub Issues](https://github.com/heroui-inc/heroui/issues)
|
||||
|
||||
## Links
|
||||
|
||||
- [Component Documentation](https://heroui.com/docs/components)
|
||||
- [React Server Components](https://react.dev/reference/rsc/server-components)
|
||||
- [React 19 Release](https://react.dev/blog/2024/12/05/react-19)
|
||||
- [GitHub Repository](https://github.com/heroui-inc/heroui)
|
||||
|
||||
## Contributors
|
||||
|
||||
Thanks to everyone who contributed to this release, improving React Server Components support and React 19 compatibility!
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
title: Accordion
|
||||
description: A collapsible content panel for organizing information in a compact space
|
||||
icon: updated
|
||||
links:
|
||||
rac: Disclosure
|
||||
source: accordion/accordion.tsx
|
||||
@@ -24,13 +25,13 @@ import { Accordion } from '@heroui/react';
|
||||
|
||||
### Anatomy
|
||||
|
||||
Import all parts and piece them together.
|
||||
Import the Accordion component and access all parts using dot notation.
|
||||
|
||||
```tsx
|
||||
import { Accordion } from '@heroui/react';
|
||||
|
||||
export default () => (
|
||||
<Accordion>
|
||||
<Accordion.Root>
|
||||
<Accordion.Item>
|
||||
<Accordion.Heading>
|
||||
<Accordion.Trigger>
|
||||
@@ -41,7 +42,7 @@ export default () => (
|
||||
<Accordion.Body/>
|
||||
</Accordion.Panel>
|
||||
</Accordion.Item>
|
||||
</Accordion>
|
||||
</Accordion.Root>
|
||||
)
|
||||
```
|
||||
|
||||
@@ -89,7 +90,7 @@ export default () => (
|
||||
|
||||
<CollapsibleCode lang="tsx" code={`"use client";
|
||||
|
||||
import {Accordion, cn} from "@heroui/react";
|
||||
import { Accordion, cn } from "@heroui/react";
|
||||
import {Icon} from "@iconify/react";
|
||||
|
||||
const items = [
|
||||
@@ -119,7 +120,7 @@ const items = [
|
||||
|
||||
export function CustomStyles() {
|
||||
return (
|
||||
<Accordion className="bg-surface-1 w-full max-w-md rounded-2xl" variant="outline">
|
||||
<Accordion.Root className="bg-surface-1 w-full max-w-md rounded-2xl" variant="outline">
|
||||
{items.map((item, index) => (
|
||||
<Accordion.Item
|
||||
key={index}
|
||||
@@ -152,7 +153,7 @@ export function CustomStyles() {
|
||||
</Accordion.Panel>
|
||||
</Accordion.Item>
|
||||
))}
|
||||
</Accordion>
|
||||
</Accordion.Root>
|
||||
);
|
||||
}`} />
|
||||
|
||||
@@ -210,7 +211,7 @@ The component supports both CSS pseudo-classes and data attributes for flexibili
|
||||
|
||||
## API Reference
|
||||
|
||||
### Accordion Props
|
||||
### Accordion.Root Props
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
|------|------|---------|-------------|
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
title: Avatar
|
||||
description: Display user profile images with customizable fallback content
|
||||
icon: updated
|
||||
links:
|
||||
radix: avatar
|
||||
source: avatar/avatar.tsx
|
||||
@@ -21,16 +22,16 @@ import { Avatar } from '@heroui/react';
|
||||
|
||||
### Anatomy
|
||||
|
||||
Import all parts and piece them together.
|
||||
Import the Avatar component and access all parts using dot notation.
|
||||
|
||||
```tsx
|
||||
import { Avatar } from '@heroui/react';
|
||||
|
||||
export default () => (
|
||||
<Avatar>
|
||||
<Avatar.Root>
|
||||
<Avatar.Image/>
|
||||
<Avatar.Fallback/>
|
||||
</Avatar>
|
||||
</Avatar.Root>
|
||||
)
|
||||
```
|
||||
|
||||
@@ -63,10 +64,10 @@ import { Avatar } from '@heroui/react';
|
||||
|
||||
function CustomAvatar() {
|
||||
return (
|
||||
<Avatar className="size-20">
|
||||
<Avatar.Root className="size-20">
|
||||
<Avatar.Image src="..." alt="..." />
|
||||
<Avatar.Fallback>XL</Avatar.Fallback>
|
||||
</Avatar>
|
||||
</Avatar.Root>
|
||||
);
|
||||
}
|
||||
```
|
||||
@@ -113,7 +114,7 @@ The Avatar component uses these CSS classes ([View source styles](https://github
|
||||
|
||||
## API Reference
|
||||
|
||||
### Avatar Props
|
||||
### Avatar.Root Props
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
|------|------|---------|-------------|
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
title: Card
|
||||
description: Flexible container component for grouping related content and actions
|
||||
icon: updated
|
||||
links:
|
||||
source: card/card.tsx
|
||||
styles: card.css
|
||||
@@ -10,7 +11,7 @@ links:
|
||||
## Import
|
||||
|
||||
```tsx
|
||||
import {Card} from "@heroui/react";
|
||||
import { Card } from "@heroui/react";
|
||||
```
|
||||
|
||||
### Usage
|
||||
@@ -21,20 +22,20 @@ import {Card} from "@heroui/react";
|
||||
|
||||
### Anatomy
|
||||
|
||||
Import all parts and piece them together.
|
||||
Import the Card component and access all parts using dot notation.
|
||||
|
||||
```tsx
|
||||
import {Card} from "@heroui/react";
|
||||
import { Card } from "@heroui/react";
|
||||
|
||||
export default () => (
|
||||
<Card>
|
||||
<Card.Root>
|
||||
<Card.Header>
|
||||
<Card.Title />
|
||||
<Card.Description />
|
||||
</Card.Header>
|
||||
<Card.Content />
|
||||
<Card.Footer />
|
||||
</Card>
|
||||
</Card.Root>
|
||||
);
|
||||
```
|
||||
|
||||
@@ -78,18 +79,18 @@ export default () => (
|
||||
|
||||
```tsx
|
||||
// Semantic markup
|
||||
<Card role="article" aria-labelledby="card-title">
|
||||
<Card.Root role="article" aria-labelledby="card-title">
|
||||
<Card.Header>
|
||||
<Card.Title id="card-title">Article Title</Card.Title>
|
||||
</Card.Header>
|
||||
</Card>
|
||||
</Card.Root>
|
||||
|
||||
// Interactive cards
|
||||
<Card asChild>
|
||||
<Card.Root asChild>
|
||||
<a href="/details" aria-label="View product details">
|
||||
<Card.Title>Product Name</Card.Title>
|
||||
</a>
|
||||
</Card>
|
||||
</Card.Root>
|
||||
```
|
||||
|
||||
## Styling
|
||||
@@ -97,7 +98,7 @@ export default () => (
|
||||
### Component Customization
|
||||
|
||||
```tsx
|
||||
<Card className="border-2 border-blue-500 bg-gradient-to-r from-blue-50 to-purple-50">
|
||||
<Card.Root className="border-2 border-blue-500 bg-gradient-to-r from-blue-50 to-purple-50">
|
||||
<Card.Header>
|
||||
<Card.Title className="text-blue-900">Custom Styled Card</Card.Title>
|
||||
<Card.Description className="text-blue-700">Custom colors applied</Card.Description>
|
||||
@@ -105,7 +106,7 @@ export default () => (
|
||||
<Card.Content>
|
||||
<p className="text-blue-800">Content with custom styling</p>
|
||||
</Card.Content>
|
||||
</Card>
|
||||
</Card.Root>
|
||||
```
|
||||
|
||||
### CSS Variable Overrides
|
||||
@@ -145,7 +146,7 @@ Card uses BEM naming for predictable styling, ([View source styles](https://gith
|
||||
|
||||
## API Reference
|
||||
|
||||
### Card
|
||||
### Card.Root
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
| ----------- | --------------------------------------------------------- | ------------ | -------------------------- |
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
---
|
||||
title: Description
|
||||
description: Provides supplementary text for form fields and other components
|
||||
icon: new
|
||||
links:
|
||||
rac: TextField
|
||||
source: description/description.tsx
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
title: DisclosureGroup
|
||||
description: Container that manages multiple Disclosure items with coordinated expanded states
|
||||
icon: updated
|
||||
links:
|
||||
rac: DisclosureGroup
|
||||
source: disclosure-group/disclosure-group.tsx
|
||||
@@ -30,14 +31,14 @@ import {DisclosureGroup, Disclosure} from '@heroui/react';
|
||||
|
||||
export default () => (
|
||||
<DisclosureGroup>
|
||||
<Disclosure id="item1">
|
||||
<Disclosure.Root id="item1">
|
||||
<Disclosure.Heading>
|
||||
<Disclosure.Trigger>
|
||||
<Disclosure.Indicator />
|
||||
</Disclosure.Trigger>
|
||||
</Disclosure.Heading>
|
||||
<Disclosure.Content />
|
||||
</Disclosure>
|
||||
</Disclosure.Root>
|
||||
</DisclosureGroup>
|
||||
)
|
||||
```
|
||||
@@ -59,18 +60,23 @@ You can control which disclosures are expanded with external navigation controls
|
||||
### Passing Tailwind CSS classes
|
||||
|
||||
```tsx
|
||||
import {DisclosureGroup, Disclosure} from '@heroui/react';
|
||||
import {
|
||||
DisclosureGroup,
|
||||
Disclosure,
|
||||
DisclosureTrigger,
|
||||
DisclosurePanel
|
||||
} from '@heroui/react';
|
||||
|
||||
function CustomDisclosureGroup() {
|
||||
return (
|
||||
<DisclosureGroup className="border rounded-lg p-4 space-y-2">
|
||||
<Disclosure id="first" className="border-b pb-2">
|
||||
<Disclosure.Trigger>Item 1</Disclosure.Trigger>
|
||||
<Disclosure.Content>Content 1</Disclosure.Content>
|
||||
<DisclosureTrigger>Item 1</DisclosureTrigger>
|
||||
<DisclosurePanel>Content 1</DisclosurePanel>
|
||||
</Disclosure>
|
||||
<Disclosure id="second">
|
||||
<Disclosure.Trigger>Item 2</Disclosure.Trigger>
|
||||
<Disclosure.Content>Content 2</Disclosure.Content>
|
||||
<DisclosureTrigger>Item 2</DisclosureTrigger>
|
||||
<DisclosurePanel>Content 2</DisclosurePanel>
|
||||
</Disclosure>
|
||||
</DisclosureGroup>
|
||||
);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
title: Disclosure
|
||||
description: A disclosure is a collapsible section with a header containing a heading and a trigger button, and a panel that wraps the content.
|
||||
icon: updated
|
||||
links:
|
||||
rac: Disclosure
|
||||
source: disclosure/disclosure.tsx
|
||||
@@ -12,7 +13,7 @@ links:
|
||||
## Import
|
||||
|
||||
```tsx
|
||||
import {Disclosure} from '@heroui/react';
|
||||
import { Disclosure } from '@heroui/react';
|
||||
```
|
||||
|
||||
### Usage
|
||||
@@ -23,20 +24,20 @@ import {Disclosure} from '@heroui/react';
|
||||
|
||||
### Anatomy
|
||||
|
||||
Import all parts and piece them together.
|
||||
Import the Disclosure component and access all parts using dot notation.
|
||||
|
||||
```tsx
|
||||
import { Disclosure } from '@heroui/react';
|
||||
|
||||
export default () => (
|
||||
<Disclosure>
|
||||
<Disclosure.Root>
|
||||
<Disclosure.Heading>
|
||||
<Disclosure.Trigger>
|
||||
<Disclosure.Indicator />
|
||||
</Disclosure.Trigger>
|
||||
</Disclosure.Heading>
|
||||
<Disclosure.Content/>
|
||||
</Disclosure>
|
||||
</Disclosure.Root>
|
||||
)
|
||||
```
|
||||
|
||||
@@ -51,15 +52,19 @@ import { Disclosure } from '@heroui/react';
|
||||
|
||||
function CustomDisclosure() {
|
||||
return (
|
||||
<Disclosure className="border rounded-lg p-4">
|
||||
<Disclosure.Trigger className="text-lg font-semibold">
|
||||
Click to expand
|
||||
<Disclosure.Indicator className="ml-2" />
|
||||
</Disclosure.Trigger>
|
||||
<Disclosure.Content className="mt-4 text-gray-600">
|
||||
Hidden content
|
||||
<Disclosure.Root className="border rounded-lg p-4">
|
||||
<Disclosure.Heading>
|
||||
<Disclosure.Trigger className="text-lg font-semibold">
|
||||
Click to expand
|
||||
<Disclosure.Indicator />
|
||||
</Disclosure.Trigger>
|
||||
</Disclosure.Heading>
|
||||
<Disclosure.Content>
|
||||
<Disclosure.Body className="mt-4 text-gray-600">
|
||||
Hidden content
|
||||
</Disclosure.Body>
|
||||
</Disclosure.Content>
|
||||
</Disclosure>
|
||||
</Disclosure.Root>
|
||||
);
|
||||
}
|
||||
```
|
||||
@@ -114,7 +119,7 @@ The component supports both CSS pseudo-classes and data attributes for flexibili
|
||||
|
||||
## API Reference
|
||||
|
||||
### Disclosure Props
|
||||
### Disclosure.Root Props
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
|------|------|---------|-------------|
|
||||
@@ -124,28 +129,20 @@ The component supports both CSS pseudo-classes and data attributes for flexibili
|
||||
| `children` | `ReactNode \| RenderFunction` | - | Content to render |
|
||||
| `className` | `string` | - | Additional CSS classes |
|
||||
|
||||
### Disclosure.Trigger Props
|
||||
### DisclosureTrigger Props
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
|------|------|---------|-------------|
|
||||
| `children` | `ReactNode \| RenderFunction` | - | Trigger content |
|
||||
| `className` | `string` | - | Additional CSS classes |
|
||||
| `slot` | `string` | `"trigger"` | Slot name for React Aria |
|
||||
|
||||
### Disclosure.Content Props
|
||||
### DisclosurePanel Props
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
|------|------|---------|-------------|
|
||||
| `children` | `ReactNode` | - | Content to show/hide |
|
||||
| `className` | `string` | - | Additional CSS classes |
|
||||
|
||||
### Disclosure.Indicator Props
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
|------|------|---------|-------------|
|
||||
| `children` | `ReactElement` | `<IconChevronDown />` | Custom indicator element |
|
||||
| `className` | `string` | - | Additional CSS classes |
|
||||
|
||||
### RenderProps
|
||||
|
||||
When using the render prop pattern, these values are provided:
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
---
|
||||
title: FieldError
|
||||
description: Displays validation error messages for form fields
|
||||
icon: new
|
||||
links:
|
||||
rac: FieldError
|
||||
source: field-error/field-error.tsx
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Fieldset
|
||||
description: Group related form controls with legends, descriptions, and actions
|
||||
icon: new
|
||||
icon: updated
|
||||
links:
|
||||
source: fieldset/fieldset.tsx
|
||||
styles: fieldset.css
|
||||
@@ -20,13 +20,13 @@ import { Fieldset } from '@heroui/react';
|
||||
|
||||
### Anatomy
|
||||
|
||||
Import all parts and piece them together.
|
||||
Import the Fieldset component and access all parts using dot notation.
|
||||
|
||||
```tsx
|
||||
import {Fieldset} from '@heroui/react';
|
||||
import { Fieldset } from '@heroui/react';
|
||||
|
||||
export default () => (
|
||||
<Fieldset>
|
||||
<Fieldset.Root>
|
||||
<Fieldset.Legend />
|
||||
<Fieldset.Group>
|
||||
{/* form fields go here */}
|
||||
@@ -34,7 +34,7 @@ export default () => (
|
||||
<Fieldset.Actions>
|
||||
{/* action buttons go here */}
|
||||
</Fieldset.Actions>
|
||||
</Fieldset>
|
||||
</Fieldset.Root>
|
||||
)
|
||||
```
|
||||
|
||||
@@ -47,11 +47,11 @@ export default () => (
|
||||
### Passing Tailwind CSS classes
|
||||
|
||||
```tsx
|
||||
import {Fieldset, TextField} from '@heroui/react';
|
||||
import { Fieldset, TextField, Label, Input } from '@heroui/react';
|
||||
|
||||
function CustomFieldset() {
|
||||
return (
|
||||
<Fieldset className="rounded-xl border border-border bg-surface-2 p-6 shadow-sm">
|
||||
<Fieldset.Root className="rounded-xl border border-border bg-surface-2 p-6 shadow-sm">
|
||||
<Fieldset.Legend className="text-lg font-semibold">Team members</Fieldset.Legend>
|
||||
<Fieldset.Group className="grid gap-4 md:grid-cols-2">
|
||||
<TextField>
|
||||
@@ -66,7 +66,7 @@ function CustomFieldset() {
|
||||
<Fieldset.Actions className="justify-end gap-3">
|
||||
{/* Action buttons */}
|
||||
</Fieldset.Actions>
|
||||
</Fieldset>
|
||||
</Fieldset.Root>
|
||||
);
|
||||
}
|
||||
```
|
||||
@@ -106,14 +106,13 @@ The Fieldset compound component exposes these CSS selectors:
|
||||
|
||||
## API Reference
|
||||
|
||||
### Fieldset Props
|
||||
### Fieldset.Root Props
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
|------|------|---------|-------------|
|
||||
| `asChild` | `boolean` | `false` | Render the fieldset as a custom component via `Slot`. |
|
||||
| `className` | `string` | - | Tailwind CSS classes applied to the root element. |
|
||||
| `children` | `React.ReactNode` | - | Fieldset content (legend, groups, descriptions, actions). |
|
||||
| `ref` | `React.Ref<HTMLFieldSetElement>` | - | Ref forwarded to the fieldset element. |
|
||||
| `nativeProps` | `React.HTMLAttributes<HTMLFieldSetElement>` | Supports native fieldset attributes and events. |
|
||||
|
||||
### Fieldset.Legend Props
|
||||
@@ -123,7 +122,6 @@ The Fieldset compound component exposes these CSS selectors:
|
||||
| `asChild` | `boolean` | `false` | Render the legend as another component with `Slot`. |
|
||||
| `className` | `string` | - | Tailwind classes for the legend element. |
|
||||
| `children` | `React.ReactNode` | - | Legend content, usually plain text. |
|
||||
| `ref` | `React.Ref<HTMLLegendElement>` | - | Ref forwarded to the legend element. |
|
||||
| `nativeProps` | `React.HTMLAttributes<HTMLLegendElement>` | - | Native legend attributes. |
|
||||
|
||||
### Fieldset.Group Props
|
||||
@@ -133,7 +131,6 @@ The Fieldset compound component exposes these CSS selectors:
|
||||
| `asChild` | `boolean` | `false` | Render the group as a different component. |
|
||||
| `className` | `string` | - | Layout and spacing classes for grouped fields. |
|
||||
| `children` | `React.ReactNode` | - | Form controls to group inside the fieldset. |
|
||||
| `ref` | `React.Ref<HTMLDivElement>` | - | Ref forwarded to the group wrapper. |
|
||||
| `nativeProps` | `React.HTMLAttributes<HTMLDivElement>` | - | Native div attributes. |
|
||||
|
||||
### Fieldset.Actions Props
|
||||
@@ -143,5 +140,4 @@ The Fieldset compound component exposes these CSS selectors:
|
||||
| `asChild` | `boolean` | `false` | Render the actions container as a custom component. |
|
||||
| `className` | `string` | - | Tailwind classes to align action buttons or text. |
|
||||
| `children` | `React.ReactNode` | - | Action buttons or helper text. |
|
||||
| `ref` | `React.Ref<HTMLDivElement>` | - | Ref forwarded to the actions container. |
|
||||
| `nativeProps` | `React.HTMLAttributes<HTMLDivElement>` | - | Native div attributes. |
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
---
|
||||
title: Form
|
||||
description: Wrapper component for form validation and submission handling
|
||||
icon: new
|
||||
links:
|
||||
source: form/form.tsx
|
||||
rac: https://react-spectrum.adobe.com/react-aria/Form.html
|
||||
@@ -76,7 +75,6 @@ The Form component is a wrapper around React Aria's Form primitive that provides
|
||||
| `onInvalid` | `(event: FormEvent<HTMLFormElement>) => void` | - | Handler called when the form validation fails. By default, the first invalid field will be focused. Use `preventDefault()` to customize focus behavior. |
|
||||
| `onReset` | `(event: FormEvent<HTMLFormElement>) => void` | - | Handler called when the form is reset. |
|
||||
| `onSubmit` | `(event: FormEvent<HTMLFormElement>) => void` | - | Handler called when the form is submitted. |
|
||||
| `ref` | `React.Ref<HTMLFormElement>` | - | Ref forwarded to the form element. |
|
||||
| `target` | `'_self' \| '_blank' \| '_parent' \| '_top'` | - | Where to display the response after submitting the form. |
|
||||
| `validationBehavior` | `'native' \| 'aria'` | `'native'` | Whether to use native HTML validation or ARIA validation. 'native' blocks form submission, 'aria' displays errors in realtime. |
|
||||
| `validationErrors` | `ValidationErrors` | - | Server-side validation errors mapped by field name. Displayed immediately and cleared when user modifies the field. |
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
---
|
||||
title: Input
|
||||
description: Primitive single-line text input component that accepts standard HTML attributes
|
||||
icon: new
|
||||
links:
|
||||
rac: Input
|
||||
source: input/input.tsx
|
||||
@@ -117,6 +116,5 @@ Input accepts all standard HTML `<input>` attributes plus the following:
|
||||
| `min` | `number \| string` | - | Minimum value (for number/date inputs). |
|
||||
| `max` | `number \| string` | - | Maximum value (for number/date inputs). |
|
||||
| `step` | `number \| string` | - | Stepping interval (for number inputs). |
|
||||
| `ref` | `React.Ref<HTMLInputElement>` | - | Ref forwarded to the input element. |
|
||||
|
||||
> For validation props like `isInvalid`, `isRequired`, and error handling, use **[TextField](/docs/components/text-field)** with Input as a child component.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
title: Kbd
|
||||
description: Display keyboard shortcuts and key combinations
|
||||
icon: updated
|
||||
links:
|
||||
source: kbd/kbd.tsx
|
||||
styles: kbd.css
|
||||
@@ -11,7 +12,7 @@ links:
|
||||
## Import
|
||||
|
||||
```tsx
|
||||
import {Kbd} from "@heroui/react";
|
||||
import { Kbd } from "@heroui/react";
|
||||
```
|
||||
|
||||
### Usage
|
||||
@@ -22,16 +23,16 @@ import {Kbd} from "@heroui/react";
|
||||
|
||||
### Anatomy
|
||||
|
||||
Import all parts and piece them together.
|
||||
Import the Kbd component and access all parts using dot notation.
|
||||
|
||||
```tsx
|
||||
import {Kbd} from "@heroui/react";
|
||||
import { Kbd } from "@heroui/react";
|
||||
|
||||
export default () => (
|
||||
<Kbd>
|
||||
<Kbd.Abbr keyValue="command" />
|
||||
<Kbd.Root>
|
||||
<Kbd.Abbr title="Command">⌘</Kbd.Abbr>
|
||||
<Kbd.Content>K</Kbd.Content>
|
||||
</Kbd>
|
||||
</Kbd.Root>
|
||||
);
|
||||
```
|
||||
|
||||
@@ -64,13 +65,13 @@ export default () => (
|
||||
### Passing Tailwind CSS classes
|
||||
|
||||
```tsx
|
||||
import {Kbd} from "@heroui/react";
|
||||
import { Kbd } from "@heroui/react";
|
||||
|
||||
function CustomKbd() {
|
||||
return (
|
||||
<Kbd className="bg-gray-100 dark:bg-gray-800">
|
||||
<Kbd.Root className="bg-gray-100 dark:bg-gray-800">
|
||||
<Kbd.Content>K</Kbd.Content>
|
||||
</Kbd>
|
||||
</Kbd.Root>
|
||||
);
|
||||
}
|
||||
```
|
||||
@@ -110,7 +111,7 @@ The Kbd component uses these CSS classes ([View source styles](https://github.co
|
||||
|
||||
## API Reference
|
||||
|
||||
### Kbd Props
|
||||
### Kbd.Root Props
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
| ----------- | ----------------- | ------- | ---------------------- |
|
||||
@@ -121,17 +122,18 @@ The Kbd component uses these CSS classes ([View source styles](https://github.co
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
| ----------- | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `keyValue` | `KbdKey` | - | The keyboard key to display. Available values include modifier keys and special keys |
|
||||
| `title` | `string` | - | Title attribute for accessibility (e.g., "Command" for ⌘) |
|
||||
| `children` | `React.ReactNode` | - | The symbol or text to display (e.g., ⌘, ⌥, ⇧) |
|
||||
| `className` | `string` | - | Custom CSS classes |
|
||||
|
||||
### Kbd.Content Props
|
||||
### Kbd.Key Props
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
| ----------- | ----------------- | ------- | ---------------------------------- |
|
||||
| `children` | `React.ReactNode` | - | Text content of the key |
|
||||
| `className` | `string` | - | Custom CSS classes |
|
||||
|
||||
### KbdKey Type
|
||||
### Kbd.Content Type
|
||||
|
||||
Available key values for the `keyValue` prop:
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
---
|
||||
title: Label
|
||||
description: Renders an accessible label associated with form controls
|
||||
icon: new
|
||||
links:
|
||||
rac: TextField
|
||||
source: label/label.tsx
|
||||
|
||||
@@ -24,16 +24,16 @@ import { Link } from '@heroui/react';
|
||||
|
||||
### Anatomy
|
||||
|
||||
Import all parts and piece them together.
|
||||
Import the Link component and access all parts using dot notation.
|
||||
|
||||
```tsx
|
||||
import {Link} from '@heroui/react';
|
||||
import { Link } from '@heroui/react';
|
||||
|
||||
export default () => (
|
||||
<Link href="#">
|
||||
<Link.Root href="#">
|
||||
Call to action
|
||||
<Link.Icon />
|
||||
</Link>
|
||||
</Link.Root>
|
||||
);
|
||||
```
|
||||
|
||||
@@ -54,16 +54,16 @@ export default () => (
|
||||
### Passing Tailwind CSS classes
|
||||
|
||||
```tsx
|
||||
import {Link} from '@heroui/react';
|
||||
import { Link } from '@heroui/react';
|
||||
|
||||
function CustomLink() {
|
||||
return (
|
||||
<Link
|
||||
<Link.Root
|
||||
href="#"
|
||||
className="text-lg font-bold text-accent hover:text-accent/80"
|
||||
>
|
||||
Custom styled link
|
||||
</Link>
|
||||
</Link.Root>
|
||||
);
|
||||
}
|
||||
```
|
||||
@@ -99,7 +99,7 @@ The component supports both CSS pseudo-classes and data attributes for flexibili
|
||||
|
||||
## API Reference
|
||||
|
||||
### Link Props
|
||||
### Link.Root Props
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
|------|------|---------|-------------|
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
title: Popover
|
||||
description: Displays rich content in a portal triggered by a button or any custom element
|
||||
icon: updated
|
||||
links:
|
||||
rac: Popover
|
||||
source: popover/popover.tsx
|
||||
@@ -22,13 +23,13 @@ import { Popover } from '@heroui/react';
|
||||
|
||||
### Anatomy
|
||||
|
||||
Import all parts and piece them together.
|
||||
Import the Popover component and access all parts using dot notation.
|
||||
|
||||
```tsx
|
||||
import { Popover } from '@heroui/react';
|
||||
|
||||
export default () => (
|
||||
<Popover>
|
||||
<Popover.Root>
|
||||
<Popover.Trigger/>
|
||||
<Popover.Content>
|
||||
<Popover.Arrow />
|
||||
@@ -37,7 +38,7 @@ export default () => (
|
||||
{/* content goes here */}
|
||||
</Popover.Dialog>
|
||||
</Popover.Content>
|
||||
</Popover>
|
||||
</Popover.Root>
|
||||
)
|
||||
```
|
||||
|
||||
@@ -64,19 +65,21 @@ export default () => (
|
||||
### Passing Tailwind CSS classes
|
||||
|
||||
```tsx
|
||||
import {Popover, Button} from '@heroui/react';
|
||||
import { Popover, Button } from '@heroui/react';
|
||||
|
||||
function CustomPopover() {
|
||||
return (
|
||||
<Popover>
|
||||
<Button>Open</Button>
|
||||
<Popover.Root>
|
||||
<Popover.Trigger>
|
||||
<Button>Open</Button>
|
||||
</Popover.Trigger>
|
||||
<Popover.Content className="bg-accent text-accent-foreground">
|
||||
<Popover.Dialog>
|
||||
<Popover.Heading>Custom Styled</Popover.Heading>
|
||||
<h3>Custom Styled</h3>
|
||||
<p>This popover has custom styling</p>
|
||||
</Popover.Dialog>
|
||||
</Popover.Content>
|
||||
</Popover>
|
||||
</Popover.Root>
|
||||
);
|
||||
}
|
||||
```
|
||||
@@ -125,7 +128,7 @@ The component supports animation states:
|
||||
|
||||
## API Reference
|
||||
|
||||
### Popover Props
|
||||
### Popover.Root Props
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
|------|------|---------|-------------|
|
||||
@@ -158,13 +161,6 @@ The component supports animation states:
|
||||
| `children` | `React.ReactNode` | - | Element that triggers the popover |
|
||||
| `className` | `string` | - | Additional CSS classes |
|
||||
|
||||
### Popover.Heading Props
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
|------|------|---------|-------------|
|
||||
| `children` | `React.ReactNode` | - | Heading text content |
|
||||
| `className` | `string` | - | Additional CSS classes |
|
||||
|
||||
### Popover.Arrow Props
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: RadioGroup
|
||||
description: Radio group for selecting a single option from a list
|
||||
icon: new
|
||||
icon: updated
|
||||
links:
|
||||
rac: RadioGroup
|
||||
source: radio-group/radio-group.tsx
|
||||
@@ -24,7 +24,7 @@ import { RadioGroup, Radio } from '@heroui/react';
|
||||
|
||||
### Anatomy
|
||||
|
||||
Import all parts and piece them together.
|
||||
Import the RadioGroup component and access all parts using dot notation.
|
||||
|
||||
```tsx
|
||||
import {RadioGroup, Radio, Label, Description, FieldError} from '@heroui/react';
|
||||
@@ -33,7 +33,7 @@ export default () => (
|
||||
<RadioGroup>
|
||||
<Label />
|
||||
<Description />
|
||||
<Radio value="option1">
|
||||
<Radio.Root value="option1">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator>
|
||||
<span>✓</span> {/* Custom indicator (optional) */}
|
||||
@@ -43,7 +43,7 @@ export default () => (
|
||||
<Label />
|
||||
<Description />
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
</Radio.Root>
|
||||
<FieldError />
|
||||
</RadioGroup>
|
||||
)
|
||||
@@ -103,52 +103,31 @@ Combine `defaultValue` with `onChange` when you only need to react to updates.
|
||||
### Passing Tailwind CSS classes
|
||||
|
||||
```tsx
|
||||
import {RadioGroup, Radio, Label, Description} from '@heroui/react';
|
||||
import { RadioGroup, Radio } from '@heroui/react';
|
||||
|
||||
export default () => (
|
||||
<RadioGroup defaultValue="premium" name="plan">
|
||||
<Label>Plan selection</Label>
|
||||
<Description>Choose the plan that best suits your needs</Description>
|
||||
<Radio
|
||||
<Radio.Root
|
||||
className="border-border group cursor-pointer rounded-xl border-2 p-4 hover:border-blue-300 data-[selected=true]:border-blue-500 data-[selected=true]:bg-blue-500/10"
|
||||
value="basic"
|
||||
>
|
||||
<Radio.Control className="border-border border-2 group-hover:border-blue-400 group-data-[selected=true]:border-blue-500 group-data-[selected=true]:bg-blue-500">
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label className="cursor-pointer font-semibold">Basic Plan</Label>
|
||||
<Description className="text-sm">
|
||||
Includes 100 messages per month and up to 3 themes to set up
|
||||
</Description>
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
<Radio
|
||||
<Radio.Indicator className="border-border border-2 group-hover:border-blue-400 group-data-[selected=true]:border-blue-500 group-data-[selected=true]:bg-blue-500" />
|
||||
Basic Plan
|
||||
</Radio.Root>
|
||||
<Radio.Root
|
||||
className="border-border group cursor-pointer rounded-xl border-2 p-4 hover:border-purple-300 data-[selected=true]:border-purple-500 data-[selected=true]:bg-purple-500/10"
|
||||
value="premium"
|
||||
>
|
||||
<Radio.Control className="border-border border-2 group-hover:border-purple-400 group-data-[selected=true]:border-purple-500 group-data-[selected=true]:bg-purple-500">
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label className="cursor-pointer font-semibold">Premium Plan</Label>
|
||||
<Description className="text-sm">
|
||||
Includes 200 messages per month and up to 6 themes to set up
|
||||
</Description>
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
<Radio
|
||||
<Radio.Indicator className="border-border border-2 group-hover:border-purple-400 group-data-[selected=true]:border-purple-500 group-data-[selected=true]:bg-purple-500" />
|
||||
Premium Plan
|
||||
</Radio.Root>
|
||||
<Radio.Root
|
||||
className="border-border group cursor-pointer rounded-xl border-2 p-4 hover:border-emerald-300 data-[selected=true]:border-emerald-500 data-[selected=true]:bg-emerald-500/10"
|
||||
value="business"
|
||||
>
|
||||
<Radio.Control className="border-border border-2 group-hover:border-emerald-400 group-data-[selected=true]:border-emerald-500 group-data-[selected=true]:bg-emerald-500">
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
<Radio.Content>
|
||||
<Label className="cursor-pointer font-semibold">Business Plan</Label>
|
||||
<Description className="text-sm">Unlimited messages and themes</Description>
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
<Radio.Indicator className="border-border border-2 group-hover:border-emerald-400 group-data-[selected=true]:border-emerald-500 group-data-[selected=true]:bg-emerald-500" />
|
||||
Business Plan
|
||||
</Radio.Root>
|
||||
</RadioGroup>
|
||||
);
|
||||
```
|
||||
@@ -226,7 +205,7 @@ The radio supports both CSS pseudo-classes and data attributes for flexibility:
|
||||
| `orientation` | `'horizontal' \| 'vertical'` | `'vertical'` | The orientation of the radio group |
|
||||
| `children` | `React.ReactNode \| (values: RadioGroupRenderProps) => React.ReactNode` | - | Radio group content or render prop |
|
||||
|
||||
### Radio Props
|
||||
### Radio.Root Props
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
|------|------|---------|-------------|
|
||||
@@ -241,7 +220,7 @@ Extends `React.HTMLAttributes<HTMLSpanElement>`.
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
|------|------|---------|-------------|
|
||||
| `children` | `React.ReactNode` | - | Content to render inside the control, typically `Radio.Indicator`. |
|
||||
| `children` | `React.ReactNode` | - | The content to render inside the control wrapper (typically Radio.Indicator) |
|
||||
|
||||
### Radio.Indicator Props
|
||||
|
||||
@@ -257,7 +236,7 @@ Extends `React.HTMLAttributes<HTMLDivElement>`.
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
|------|------|---------|-------------|
|
||||
| `children` | `React.ReactNode` | - | Content displayed next to the control, usually `Label` and `Description`. |
|
||||
| `children` | `React.ReactNode` | - | The content to render inside the content wrapper (typically Label and Description) |
|
||||
|
||||
### RadioRenderProps
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
title: Switch
|
||||
description: A toggle switch component for boolean states
|
||||
icon: updated
|
||||
links:
|
||||
rac: Switch
|
||||
source: switch/switch.tsx
|
||||
@@ -12,7 +13,7 @@ links:
|
||||
## Import
|
||||
|
||||
```tsx
|
||||
import { Switch, SwitchGroup } from '@heroui/react';
|
||||
import { Switch, SwitchGroup, Label } from '@heroui/react';
|
||||
```
|
||||
|
||||
### Usage
|
||||
@@ -23,19 +24,43 @@ import { Switch, SwitchGroup } from '@heroui/react';
|
||||
|
||||
### Anatomy
|
||||
|
||||
Import all parts and piece them together.
|
||||
Import the Switch component and access all parts using dot notation.
|
||||
|
||||
```tsx
|
||||
import {Switch} from '@heroui/react';
|
||||
import { Switch, Label } from '@heroui/react';
|
||||
|
||||
export default () => (
|
||||
<Switch>
|
||||
<Switch.Root>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb>
|
||||
<Switch.Icon /> {/* Optional */}
|
||||
<Switch.Icon/> {/* Optional */}
|
||||
</Switch.Thumb>
|
||||
</Switch.Control>
|
||||
</Switch>
|
||||
<Label/> {/* Optional */}
|
||||
</Switch.Root>
|
||||
);
|
||||
```
|
||||
|
||||
For grouping multiple switches, use the `SwitchGroup` component:
|
||||
|
||||
```tsx
|
||||
import { Switch, SwitchGroup, Label } from '@heroui/react';
|
||||
|
||||
export default () => (
|
||||
<SwitchGroup>
|
||||
<Switch.Root>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Label>Option 1</Label>
|
||||
</Switch.Root>
|
||||
<Switch.Root>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Label>Option 2</Label>
|
||||
</Switch.Root>
|
||||
</SwitchGroup>
|
||||
);
|
||||
```
|
||||
|
||||
@@ -121,12 +146,14 @@ export default () => (
|
||||
|
||||
### Passing Tailwind CSS classes
|
||||
|
||||
You can customize individual Switch components:
|
||||
|
||||
```tsx
|
||||
import { Switch, Label } from '@heroui/react';
|
||||
|
||||
function CustomSwitch() {
|
||||
return (
|
||||
<Switch>
|
||||
<Switch.Root>
|
||||
{({isSelected}) => (
|
||||
<>
|
||||
<Switch.Control
|
||||
@@ -134,18 +161,37 @@ function CustomSwitch() {
|
||||
>
|
||||
<Switch.Thumb
|
||||
className={`size-[27px] bg-white shadow-sm ${isSelected ? "translate-x-5 shadow-lg" : ""}`}
|
||||
>
|
||||
<Switch.Icon>
|
||||
<Icon
|
||||
className={`size-4 ${isSelected ? "text-cyan-600" : "text-blue-600"}`}
|
||||
icon={isSelected ? "gravity-ui:check" : "gravity-ui:power"}
|
||||
/>
|
||||
</Switch.Icon>
|
||||
</Switch.Thumb>
|
||||
/>
|
||||
</Switch.Control>
|
||||
<Label>Custom Switch</Label>
|
||||
</>
|
||||
)}
|
||||
</Switch>
|
||||
</Switch.Root>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
Or customize the SwitchGroup layout:
|
||||
|
||||
```tsx
|
||||
import { Switch, SwitchGroup, Label } from '@heroui/react';
|
||||
|
||||
function CustomSwitchGroup() {
|
||||
return (
|
||||
<SwitchGroup className="gap-8" orientation="horizontal">
|
||||
<Switch.Root>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Label>Option 1</Label>
|
||||
</Switch.Root>
|
||||
<Switch.Root>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Label>Option 2</Label>
|
||||
</Switch.Root>
|
||||
</SwitchGroup>
|
||||
);
|
||||
}
|
||||
```
|
||||
@@ -179,19 +225,26 @@ HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component va
|
||||
|
||||
### CSS Classes
|
||||
|
||||
#### Switch Classes
|
||||
|
||||
The Switch component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/switch.css)):
|
||||
|
||||
#### Base Classes
|
||||
- `.switch` - Base switch container
|
||||
- `.switch__control` - Switch control track
|
||||
- `.switch__thumb` - Switch thumb that moves
|
||||
- `.switch__icon` - Optional icon inside the thumb
|
||||
- `.switch--sm` - Small size variant
|
||||
- `.switch--md` - Medium size variant (default)
|
||||
- `.switch--lg` - Large size variant
|
||||
|
||||
#### SwitchGroup Classes
|
||||
|
||||
The SwitchGroup component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/switch-group.css)):
|
||||
|
||||
#### Group Classes
|
||||
- `.switch-group` - Switch group container
|
||||
- `.switch-group__items` - Container for switch items
|
||||
- `.switch-group--horizontal` - Horizontal layout
|
||||
- `.switch-group--vertical` - Vertical layout
|
||||
- `.switch-group--vertical` - Vertical layout (default)
|
||||
|
||||
### Interactive States
|
||||
|
||||
@@ -205,7 +258,7 @@ The switch supports both CSS pseudo-classes and data attributes for flexibility:
|
||||
|
||||
## API Reference
|
||||
|
||||
### Switch Props
|
||||
### Switch.Root Props
|
||||
|
||||
Inherits from [React Aria Switch](https://react-spectrum.adobe.com/react-aria/Switch.html).
|
||||
|
||||
@@ -242,3 +295,4 @@ When using the render prop pattern, these values are provided:
|
||||
|------|------|---------|-------------|
|
||||
| `orientation` | `'horizontal' \| 'vertical'` | `'vertical'` | The orientation of the switch group |
|
||||
| `children` | `React.ReactNode` | - | The switch items to render |
|
||||
| `className` | `string` | - | Additional CSS class names |
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
title: Tabs
|
||||
description: Tabs organize content into multiple sections and allow users to navigate between them.
|
||||
icon: updated
|
||||
links:
|
||||
rac: Tabs
|
||||
source: tabs/tabs.tsx
|
||||
@@ -24,13 +25,13 @@ import { Tabs } from '@heroui/react';
|
||||
|
||||
### Anatomy
|
||||
|
||||
Import all parts and piece them together.
|
||||
Import the Tabs component and access all parts using dot notation.
|
||||
|
||||
```tsx
|
||||
import { Tabs } from '@heroui/react';
|
||||
|
||||
export default () => (
|
||||
<Tabs>
|
||||
<Tabs.Root>
|
||||
<Tabs.ListWrapper>
|
||||
<Tabs.List aria-label="Options">
|
||||
<Tabs.Tab>
|
||||
@@ -39,7 +40,7 @@ export default () => (
|
||||
</Tabs.List>
|
||||
</Tabs.ListWrapper>
|
||||
<Tabs.Panel/>
|
||||
</Tabs>
|
||||
</Tabs.Root>
|
||||
)
|
||||
```
|
||||
|
||||
@@ -75,16 +76,16 @@ import { Tabs } from '@heroui/react';
|
||||
|
||||
function CustomTabs() {
|
||||
return (
|
||||
<Tabs className="w-full max-w-lg text-center">
|
||||
<Tabs.Root className="w-full max-w-lg text-center">
|
||||
<Tabs.ListWrapper>
|
||||
<Tabs.List
|
||||
aria-label="Options"
|
||||
className="*:data-[selected=true]:text-accent-foreground w-fit *:h-6 *:w-fit *:px-3 *:text-sm *:font-normal"
|
||||
>
|
||||
<Tabs.Tab id="daily">Daily</Tabs.Tab>
|
||||
<Tabs.Tab id="weekly">Weekly</Tabs.Tab>
|
||||
<Tabs.Tab id="bi-weekly">Bi-Weekly</Tabs.Tab>
|
||||
<Tabs.Tab id="monthly">Monthly</Tabs.Tab>
|
||||
<Tabs.Tab id="daily">Daily<Tabs.Indicator /></Tabs.Tab>
|
||||
<Tabs.Tab id="weekly">Weekly<Tabs.Indicator /></Tabs.Tab>
|
||||
<Tabs.Tab id="bi-weekly">Bi-Weekly<Tabs.Indicator /></Tabs.Tab>
|
||||
<Tabs.Tab id="monthly">Monthly<Tabs.Indicator /></Tabs.Tab>
|
||||
</Tabs.List>
|
||||
</Tabs.ListWrapper>
|
||||
<Tabs.Panel className="px-4" id="daily">
|
||||
@@ -103,7 +104,7 @@ function CustomTabs() {
|
||||
<h3 className="mb-2 font-semibold">Monthly</h3>
|
||||
<p className="text-sm text-gray-600">Manage your monthly tasks and goals.</p>
|
||||
</Tabs.Panel>
|
||||
</Tabs>
|
||||
</Tabs.Root>
|
||||
);
|
||||
}
|
||||
`} />
|
||||
@@ -137,7 +138,7 @@ The component supports both CSS pseudo-classes and data attributes:
|
||||
|
||||
## API Reference
|
||||
|
||||
### Tabs Props
|
||||
### Tabs.Root Props
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
|------|------|---------|-------------|
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
---
|
||||
title: TextField
|
||||
description: Composition-friendly text fields with labels, descriptions, and inline validation
|
||||
icon: new
|
||||
links:
|
||||
rac: TextField
|
||||
source: text-field/text-field.tsx
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
---
|
||||
title: TextArea
|
||||
description: Primitive multiline text input component that accepts standard HTML attributes
|
||||
icon: new
|
||||
links:
|
||||
rac: TextArea
|
||||
source: textarea/textarea.tsx
|
||||
@@ -118,6 +117,5 @@ TextArea accepts all standard HTML `<textarea>` attributes plus the following:
|
||||
| `maxLength` | `number` | - | Maximum number of characters. |
|
||||
| `minLength` | `number` | - | Minimum number of characters. |
|
||||
| `wrap` | `'soft' \| 'hard'` | - | How text wraps when submitted. |
|
||||
| `ref` | `React.Ref<HTMLTextAreaElement>` | - | Ref forwarded to the textarea element. |
|
||||
|
||||
> For validation props like `isInvalid`, `isRequired`, and error handling, use **[TextField](/docs/components/text-field)** with TextArea as a child component.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
title: Tooltip
|
||||
description: Displays informative text when users hover over or focus on an element
|
||||
icon: updated
|
||||
links:
|
||||
rac: Tooltip
|
||||
source: tooltip/tooltip.tsx
|
||||
@@ -23,13 +24,13 @@ import { Tooltip } from '@heroui/react';
|
||||
|
||||
### Anatomy
|
||||
|
||||
Import all parts and piece them together.
|
||||
Import the Tooltip component and access all parts using dot notation.
|
||||
|
||||
```tsx
|
||||
import { Tooltip } from '@heroui/react';
|
||||
|
||||
export default () => (
|
||||
<Tooltip>
|
||||
<Tooltip.Root>
|
||||
<Tooltip.Trigger>
|
||||
<button>Hover for tooltip</button>
|
||||
</Tooltip.Trigger>
|
||||
@@ -37,7 +38,7 @@ export default () => (
|
||||
<Tooltip.Arrow />
|
||||
Helpful information about this element
|
||||
</Tooltip.Content>
|
||||
</Tooltip>
|
||||
</Tooltip.Root>
|
||||
)
|
||||
```
|
||||
|
||||
@@ -64,16 +65,18 @@ export default () => (
|
||||
### Passing Tailwind CSS classes
|
||||
|
||||
```tsx
|
||||
import {Tooltip, Button} from '@heroui/react';
|
||||
import { Tooltip, Button } from '@heroui/react';
|
||||
|
||||
function CustomTooltip() {
|
||||
return (
|
||||
<Tooltip>
|
||||
<Button>Hover me</Button>
|
||||
<Tooltip.Root>
|
||||
<Tooltip.Trigger>
|
||||
<Button>Hover me</Button>
|
||||
</Tooltip.Trigger>
|
||||
<Tooltip.Content className="bg-accent text-accent-foreground">
|
||||
<p>Custom styled tooltip</p>
|
||||
</Tooltip.Content>
|
||||
</Tooltip>
|
||||
</Tooltip.Root>
|
||||
);
|
||||
}
|
||||
```
|
||||
@@ -115,7 +118,7 @@ The component supports animation states:
|
||||
|
||||
## API Reference
|
||||
|
||||
### Tooltip Props
|
||||
### Tooltip.Root Props
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
|------|------|---------|-------------|
|
||||
|
||||
@@ -43,13 +43,15 @@ Built on [React Aria Components](https://react-spectrum.adobe.com/react-aria/) f
|
||||
|
||||
```tsx
|
||||
// Automatic ARIA attributes, keyboard navigation, and focus management
|
||||
import { Tabs, TabList, Tab, TabPanel } from '@heroui/react';
|
||||
|
||||
<Tabs defaultSelectedKey="profile">
|
||||
<Tabs.List aria-label="Settings">
|
||||
<Tabs.Tab id="profile">Profile</Tabs.Tab>
|
||||
<Tabs.Tab id="security">Security</Tabs.Tab>
|
||||
</Tabs.List>
|
||||
<Tabs.Panel id="profile">Content</Tabs.Panel>
|
||||
<Tabs.Panel id="security">Content</Tabs.Panel>
|
||||
<TabList aria-label="Settings">
|
||||
<Tab id="profile">Profile</Tab>
|
||||
<Tab id="security">Security</Tab>
|
||||
</TabList>
|
||||
<TabPanel id="profile">Content</TabPanel>
|
||||
<TabPanel id="security">Content</TabPanel>
|
||||
</Tabs>
|
||||
```
|
||||
|
||||
@@ -59,18 +61,28 @@ Compound components let you rearrange, customize, or omit parts as needed.
|
||||
|
||||
```tsx
|
||||
// Compose parts to build exactly what you need
|
||||
import {
|
||||
Accordion,
|
||||
AccordionItem,
|
||||
AccordionHeading,
|
||||
AccordionTrigger,
|
||||
AccordionIndicator,
|
||||
AccordionPanel,
|
||||
AccordionBody
|
||||
} from '@heroui/react';
|
||||
|
||||
<Accordion>
|
||||
<Accordion.Item id="1">
|
||||
<Accordion.Heading>
|
||||
<Accordion.Trigger>
|
||||
<AccordionItem id="1">
|
||||
<AccordionHeading>
|
||||
<AccordionTrigger>
|
||||
Question Text
|
||||
<Accordion.Indicator />
|
||||
</Accordion.Trigger>
|
||||
</Accordion.Heading>
|
||||
<Accordion.Panel>
|
||||
<Accordion.Body>Answer content</Accordion.Body>
|
||||
</Accordion.Panel>
|
||||
</Accordion.Item>
|
||||
<AccordionIndicator />
|
||||
</AccordionTrigger>
|
||||
</AccordionHeading>
|
||||
<AccordionPanel>
|
||||
<AccordionBody>Answer content</AccordionBody>
|
||||
</AccordionPanel>
|
||||
</AccordionItem>
|
||||
</Accordion>
|
||||
```
|
||||
|
||||
@@ -104,10 +116,18 @@ Consistent patterns across all components: sizes (`sm`, `md`, `lg`), variants, c
|
||||
<Chip size="lg" variant="success" className="custom" />
|
||||
<Avatar size="lg" className="custom" />
|
||||
|
||||
// Compound components use dot notation
|
||||
<Alert.Icon />
|
||||
<Card.Header />
|
||||
<Accordion.Trigger />
|
||||
// Compound components support both named exports and dot notation
|
||||
import { Alert, AlertIcon, CardHeader, AccordionTrigger } from '@heroui/react';
|
||||
|
||||
// Named exports
|
||||
<Alert>
|
||||
<AlertIcon />
|
||||
</Alert>
|
||||
|
||||
// Dot notation (requires .Root)
|
||||
<Alert.Root>
|
||||
<Alert.Icon />
|
||||
</Alert.Root>
|
||||
```
|
||||
|
||||
### 6. Type Safety First
|
||||
|
||||
@@ -38,28 +38,60 @@ import Link from 'next/link';
|
||||
These components support `asChild`:
|
||||
|
||||
- `Button` - Change button element
|
||||
- `Alert` parts - Root, Icon, Content, Title, Description, Action, Close
|
||||
- `Avatar` - Change root element
|
||||
- `Alert` and its parts - `Alert`, `AlertIcon`, `AlertContent`, `AlertTitle`, `AlertDescription`, `AlertAction`, `AlertClose`
|
||||
- `Avatar` and its parts - `Avatar`, `AvatarImage`, `AvatarFallback`
|
||||
- More components coming soon
|
||||
|
||||
## Compound Components
|
||||
|
||||
HeroUI components are built as compound components - they export multiple parts that work together:
|
||||
HeroUI components are built as compound components - they export multiple parts that work together. You can use them in two ways:
|
||||
|
||||
### Option 1: Named Exports (Recommended)
|
||||
|
||||
Import each part separately:
|
||||
|
||||
```tsx
|
||||
import {
|
||||
Alert,
|
||||
AlertIcon,
|
||||
AlertContent,
|
||||
AlertTitle,
|
||||
AlertDescription,
|
||||
AlertClose
|
||||
} from '@heroui/react';
|
||||
|
||||
<Alert>
|
||||
<AlertIcon />
|
||||
<AlertContent>
|
||||
<AlertTitle>Success</AlertTitle>
|
||||
<AlertDescription>Your changes have been saved.</AlertDescription>
|
||||
</AlertContent>
|
||||
<AlertClose />
|
||||
</Alert>
|
||||
```
|
||||
|
||||
### Option 2: Dot Notation (Compound Pattern)
|
||||
|
||||
Import the main component and access parts via dot notation:
|
||||
|
||||
```tsx
|
||||
import { Alert } from '@heroui/react';
|
||||
|
||||
<Alert>
|
||||
<Alert.Root>
|
||||
<Alert.Icon />
|
||||
<Alert.Content>
|
||||
<Alert.Title>Success</Alert.Title>
|
||||
<Alert.Description>Your changes have been saved.</Alert.Description>
|
||||
</Alert.Content>
|
||||
<Alert.Close />
|
||||
</Alert>
|
||||
</Alert.Root>
|
||||
```
|
||||
|
||||
This pattern provides:
|
||||
**Note:** When using dot notation, the main component requires `.Root` suffix (e.g., `<Alert.Root>` instead of `<Alert>`).
|
||||
|
||||
### Benefits of Compound Components
|
||||
|
||||
Both patterns provide:
|
||||
|
||||
- **Flexibility** - Arrange parts as needed
|
||||
- **Customization** - Style each part independently
|
||||
@@ -74,7 +106,7 @@ HeroUI exports variant functions that can be applied to any component. This allo
|
||||
Apply button styles to any component:
|
||||
|
||||
```tsx
|
||||
import { Link, buttonVariants } from '@heroui/react';
|
||||
import { Link, LinkIcon, buttonVariants } from '@heroui/react';
|
||||
|
||||
// Link styled as a tertiary button
|
||||
<Link
|
||||
@@ -87,7 +119,7 @@ import { Link, buttonVariants } from '@heroui/react';
|
||||
target="_blank"
|
||||
>
|
||||
HeroUI
|
||||
<Link.Icon className="h-2 w-2" />
|
||||
<LinkIcon className="h-2 w-2" />
|
||||
</Link>
|
||||
|
||||
// Native anchor styled as primary button
|
||||
@@ -128,11 +160,14 @@ function LinkButton({ href, children, ...props }) {
|
||||
// Icon button with tooltip
|
||||
function IconButton({ icon, label, ...props }) {
|
||||
return (
|
||||
<Tooltip content={label}>
|
||||
<Button isIconOnly {...props}>
|
||||
<Icon icon={icon} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Tooltip.Root>
|
||||
<Tooltip.Trigger>
|
||||
<Button isIconOnly {...props}>
|
||||
<Icon icon={icon} />
|
||||
</Button>
|
||||
</Tooltip.Trigger>
|
||||
<Tooltip.Content>{label}</Tooltip.Content>
|
||||
</Tooltip.Root>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import {buttonVariants} from "@heroui/react";
|
||||
import Link from "fumadocs-core/link";
|
||||
import LinkRoot from "fumadocs-core/link";
|
||||
|
||||
// TODO:
|
||||
import {Iconify} from "@/components/iconify";
|
||||
@@ -9,14 +9,14 @@ import {currentVersion} from "@/utils/version";
|
||||
|
||||
const VersionChip = () => {
|
||||
return (
|
||||
<Link
|
||||
<LinkRoot
|
||||
className="chip bg-pink-400/8 hover:bg-default/40 rounded-full border-pink-400/20 dark:border-pink-400/10 dark:bg-white/10 dark:hover:bg-pink-400/20"
|
||||
href="/docs/changelog"
|
||||
>
|
||||
<Iconify className="text-pink-400/90" icon="sparkles" />
|
||||
{/* <span className="bg-gradient-to-r from-[#CA8501] to-[#BD3232] bg-clip-text text-transparent"> */}
|
||||
<span className="text-pink-400/90">v{currentVersion}: Form Components</span>
|
||||
</Link>
|
||||
<span className="text-pink-400/90">v{currentVersion}: RSC Support</span>
|
||||
</LinkRoot>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -35,15 +35,18 @@ export default function HomePage() {
|
||||
skip the copy-paste and focus on building.
|
||||
</p>
|
||||
<div className="mt-2 flex gap-3">
|
||||
<Link className={buttonVariants({class: "shadow-lg", variant: "primary"})} href="/docs">
|
||||
<LinkRoot
|
||||
className={buttonVariants({class: "shadow-lg", variant: "primary"})}
|
||||
href="/docs"
|
||||
>
|
||||
Explore Docs
|
||||
</Link>
|
||||
<Link
|
||||
</LinkRoot>
|
||||
<LinkRoot
|
||||
className={buttonVariants({class: "bg-default/50", variant: "tertiary"})}
|
||||
href="/docs/components/accordion"
|
||||
>
|
||||
View Components
|
||||
</Link>
|
||||
</LinkRoot>
|
||||
</div>
|
||||
</div>
|
||||
{/* <HomeThemeCustomizer /> */}
|
||||
|
||||
@@ -17,7 +17,7 @@ interface GenerateProps {
|
||||
site?: ReactNode;
|
||||
}
|
||||
|
||||
export function generateOGImage(options: GenerateProps & ImageResponseOptions): ImageResponse {
|
||||
function generateOGImage(options: GenerateProps & ImageResponseOptions): ImageResponse {
|
||||
const {description, icon, site, title, ...rest} = options;
|
||||
|
||||
return new ImageResponse(generate({description, icon, site, title}), {
|
||||
@@ -27,7 +27,7 @@ export function generateOGImage(options: GenerateProps & ImageResponseOptions):
|
||||
});
|
||||
}
|
||||
|
||||
export function generate({...props}: GenerateProps): ReactElement {
|
||||
function generate({...props}: GenerateProps): ReactElement {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
@@ -85,7 +85,7 @@ const [interRegular, interBold] = await Promise.all([
|
||||
promises.readFile(path.join(process.cwd(), "public/fonts/Inter-Bold.ttf")),
|
||||
]);
|
||||
|
||||
export const GET = async (_req: Request, {params}: RouteContext<"/og/[...slug]">) => {
|
||||
export const GET = async (_req: Request, {params}: {params: Promise<{slug: string[]}>}) => {
|
||||
const {slug} = await params;
|
||||
const page = source.getPage(slug.slice(0, -1));
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import type {ShowcaseItem as ShowcaseItemType} from "@/showcases";
|
||||
|
||||
import {chipVariants} from "@heroui/react";
|
||||
import Link from "next/link";
|
||||
import LinkRoot from "next/link";
|
||||
import {useSearchParams} from "next/navigation";
|
||||
import {Suspense} from "react";
|
||||
import {tv} from "tailwind-variants";
|
||||
@@ -108,7 +108,7 @@ export function ShowcaseDetailClient({codePanel, showcase, showcaseId}: Showcase
|
||||
{/* Center - Show used components */}
|
||||
<div className="order-1 my-2 flex flex-1 items-center justify-center gap-2 md:order-2 md:my-0">
|
||||
{showcase.components.map((component) => (
|
||||
<Link
|
||||
<LinkRoot
|
||||
key={component}
|
||||
href={`/docs/components/${component.toLowerCase().replace(/group$/, "-group")}`}
|
||||
className={chipVariants({
|
||||
@@ -117,7 +117,7 @@ export function ShowcaseDetailClient({codePanel, showcase, showcaseId}: Showcase
|
||||
})}
|
||||
>
|
||||
{component}
|
||||
</Link>
|
||||
</LinkRoot>
|
||||
))}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
"use client";
|
||||
|
||||
import {Button, Kbd, Tooltip} from "@heroui/react";
|
||||
import {
|
||||
Button,
|
||||
KbdContent,
|
||||
KbdRoot,
|
||||
TooltipArrow,
|
||||
TooltipContent,
|
||||
TooltipRoot,
|
||||
TooltipTrigger,
|
||||
} from "@heroui/react";
|
||||
import {useRouter, useSearchParams} from "next/navigation";
|
||||
import {useEffect} from "react";
|
||||
|
||||
@@ -19,7 +27,7 @@ export function ShowcaseHeader() {
|
||||
const returnUrl = searchParams.get("returnUrl") || "/showcase";
|
||||
|
||||
const onClose = () => {
|
||||
router.push(returnUrl);
|
||||
router.push(returnUrl as any);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
@@ -39,39 +47,43 @@ export function ShowcaseHeader() {
|
||||
return (
|
||||
<header className="border-border/50 bg-background/50 z-[1] flex items-center justify-between border-b p-4 backdrop-blur-sm">
|
||||
<div className="flex flex-1 justify-start">
|
||||
<Tooltip delay={0}>
|
||||
<Button isIconOnly aria-label="Close" variant="secondary" onPress={onClose}>
|
||||
<Iconify className="text-foreground/70" icon="xmark" />
|
||||
</Button>
|
||||
<Tooltip.Content className="text-muted px-2 py-0.5 text-xs" offset={7} placement="bottom">
|
||||
<Tooltip.Arrow />
|
||||
<TooltipRoot delay={0}>
|
||||
<TooltipTrigger>
|
||||
<Button isIconOnly aria-label="Close" variant="secondary" onPress={onClose}>
|
||||
<Iconify className="text-foreground/70" icon="xmark" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent className="text-muted px-2 py-0.5 text-xs" offset={7} placement="bottom">
|
||||
<TooltipArrow />
|
||||
Press{" "}
|
||||
<Kbd>
|
||||
<Kbd.Content className="text-xs">Esc</Kbd.Content>
|
||||
</Kbd>{" "}
|
||||
<KbdRoot>
|
||||
<KbdContent className="text-xs">Esc</KbdContent>
|
||||
</KbdRoot>{" "}
|
||||
to close
|
||||
</Tooltip.Content>
|
||||
</Tooltip>
|
||||
</TooltipContent>
|
||||
</TooltipRoot>
|
||||
</div>
|
||||
<div className="flex flex-1 items-center justify-center">
|
||||
<HeroUILogo className="text-foreground/20" />
|
||||
</div>
|
||||
<div className="flex flex-1 items-center justify-end gap-2">
|
||||
<ShowcaseThemeSwitch />
|
||||
<Tooltip delay={1500}>
|
||||
<Button
|
||||
isIconOnly
|
||||
aria-label="Toggle showcase code"
|
||||
variant={isCodeVisible ? "primary" : "secondary"}
|
||||
onPress={toggleCode}
|
||||
>
|
||||
<Iconify className={isCodeVisible ? "" : "text-foreground/70"} icon="code" />
|
||||
</Button>
|
||||
<Tooltip.Content offset={7}>
|
||||
<Tooltip.Arrow />
|
||||
<TooltipRoot delay={1500}>
|
||||
<TooltipTrigger>
|
||||
<Button
|
||||
isIconOnly
|
||||
aria-label="Toggle showcase code"
|
||||
variant={isCodeVisible ? "primary" : "secondary"}
|
||||
onPress={toggleCode}
|
||||
>
|
||||
<Iconify className={isCodeVisible ? "" : "text-foreground/70"} icon="code" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent offset={7}>
|
||||
<TooltipArrow />
|
||||
<p className="text-muted text-xs">{isCodeVisible ? "Hide code" : "Show code"}</p>
|
||||
</Tooltip.Content>
|
||||
</Tooltip>
|
||||
</TooltipContent>
|
||||
</TooltipRoot>
|
||||
{/* TODO: Add this later */}
|
||||
{/* <Button isIconOnly aria-label="Open showcase in new tab" variant="secondary">
|
||||
<Iconify className="text-foreground/70" icon="arrow-up-right-from-square" />
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import {Button, Tooltip} from "@heroui/react";
|
||||
import {Button, TooltipArrow, TooltipContent, TooltipRoot, TooltipTrigger} from "@heroui/react";
|
||||
import React from "react";
|
||||
|
||||
import {Iconify} from "@/components/iconify";
|
||||
@@ -44,21 +44,23 @@ export function ShowcaseThemeSwitch() {
|
||||
: "Toggle theme";
|
||||
|
||||
return (
|
||||
<Tooltip delay={1500}>
|
||||
<Button
|
||||
isIconOnly
|
||||
aria-label="Toggle showcase theme"
|
||||
className={cn("border-none", isDisabled && "cursor-not-allowed opacity-50")}
|
||||
isDisabled={isDisabled}
|
||||
variant="secondary"
|
||||
onPress={onPress}
|
||||
>
|
||||
<Iconify className="text-foreground/70 m-0" icon={isDark ? "moon" : "sun"} />
|
||||
</Button>
|
||||
<Tooltip.Content offset={7}>
|
||||
<Tooltip.Arrow />
|
||||
<TooltipRoot delay={1500}>
|
||||
<TooltipTrigger>
|
||||
<Button
|
||||
isIconOnly
|
||||
aria-label="Toggle showcase theme"
|
||||
className={cn("border-none", isDisabled && "cursor-not-allowed opacity-50")}
|
||||
isDisabled={isDisabled}
|
||||
variant="secondary"
|
||||
onPress={onPress}
|
||||
>
|
||||
<Iconify className="text-foreground/70 m-0" icon={isDark ? "moon" : "sun"} />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent offset={7}>
|
||||
<TooltipArrow />
|
||||
<p className="text-muted text-xs">{tooltipContent}</p>
|
||||
</Tooltip.Content>
|
||||
</Tooltip>
|
||||
</TooltipContent>
|
||||
</TooltipRoot>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,13 +6,12 @@ import React from "react";
|
||||
import {
|
||||
ColorSwatchPicker as AriaColorSwatchPicker,
|
||||
ColorSwatchPickerItem as AriaColorSwatchPickerItem,
|
||||
ColorSwatch,
|
||||
} from "react-aria-components";
|
||||
import {tv} from "tailwind-variants";
|
||||
|
||||
import {composeTailwindRenderProps, focusRing} from "@/utils/compose-tw-render";
|
||||
|
||||
import {ColorSwatch} from "./color-swatch";
|
||||
|
||||
const itemStyles = tv({
|
||||
base: "rounded-xs relative",
|
||||
extend: focusRing,
|
||||
|
||||
@@ -43,7 +43,7 @@ const items = [
|
||||
|
||||
export function Basic() {
|
||||
return (
|
||||
<Accordion className="w-full max-w-md">
|
||||
<Accordion.Root className="w-full max-w-md">
|
||||
{items.map((item, index) => (
|
||||
<Accordion.Item key={index}>
|
||||
<Accordion.Heading>
|
||||
@@ -62,6 +62,6 @@ export function Basic() {
|
||||
</Accordion.Panel>
|
||||
</Accordion.Item>
|
||||
))}
|
||||
</Accordion>
|
||||
</Accordion.Root>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ export function CustomIndicator() {
|
||||
const [expandedKeys, setExpandedKeys] = React.useState<Set<Key>>(new Set([""]));
|
||||
|
||||
return (
|
||||
<Accordion
|
||||
<Accordion.Root
|
||||
className="w-full max-w-md"
|
||||
expandedKeys={expandedKeys}
|
||||
variant="outline"
|
||||
@@ -70,6 +70,6 @@ export function CustomIndicator() {
|
||||
</Accordion.Body>
|
||||
</Accordion.Panel>
|
||||
</Accordion.Item>
|
||||
</Accordion>
|
||||
</Accordion.Root>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ const items = [
|
||||
|
||||
export function CustomStyles() {
|
||||
return (
|
||||
<Accordion className="bg-surface-1/10 w-full max-w-md rounded-2xl" variant="outline">
|
||||
<Accordion.Root className="bg-surface-1/10 w-full max-w-md rounded-2xl" variant="outline">
|
||||
{items.map((item, index) => (
|
||||
<Accordion.Item
|
||||
key={index}
|
||||
@@ -61,6 +61,6 @@ export function CustomStyles() {
|
||||
</Accordion.Panel>
|
||||
</Accordion.Item>
|
||||
))}
|
||||
</Accordion>
|
||||
</Accordion.Root>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ export function Disabled() {
|
||||
<div className="flex w-full flex-col items-center gap-8">
|
||||
<div className="w-full max-w-md space-y-2">
|
||||
<h3 className="text-muted text-sm font-medium">Entire accordion disabled</h3>
|
||||
<Accordion isDisabled className="w-full max-w-md">
|
||||
<Accordion.Root isDisabled className="w-full max-w-md">
|
||||
<Accordion.Item>
|
||||
<Accordion.Heading>
|
||||
<Accordion.Trigger>
|
||||
@@ -35,12 +35,12 @@ export function Disabled() {
|
||||
</Accordion.Body>
|
||||
</Accordion.Panel>
|
||||
</Accordion.Item>
|
||||
</Accordion>
|
||||
</Accordion.Root>
|
||||
</div>
|
||||
|
||||
<div className="w-full max-w-md space-y-2">
|
||||
<h3 className="text-muted text-sm font-medium">Individual items disabled</h3>
|
||||
<Accordion className="w-full max-w-md">
|
||||
<Accordion.Root className="w-full max-w-md">
|
||||
<Accordion.Item>
|
||||
<Accordion.Heading>
|
||||
<Accordion.Trigger>
|
||||
@@ -78,7 +78,7 @@ export function Disabled() {
|
||||
<Accordion.Body>This item is also active and can be toggled.</Accordion.Body>
|
||||
</Accordion.Panel>
|
||||
</Accordion.Item>
|
||||
</Accordion>
|
||||
</Accordion.Root>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -58,7 +58,7 @@ export function FAQ() {
|
||||
{categories.map((category) => (
|
||||
<div key={category.title}>
|
||||
<p className="text-muted text-md mb-2 font-medium">{category.title}</p>
|
||||
<Accordion className="w-full" variant="outline">
|
||||
<Accordion.Root className="w-full" variant="outline">
|
||||
{category.items.map((item, index) => (
|
||||
<Accordion.Item key={index}>
|
||||
<Accordion.Heading>
|
||||
@@ -74,7 +74,7 @@ export function FAQ() {
|
||||
</Accordion.Panel>
|
||||
</Accordion.Item>
|
||||
))}
|
||||
</Accordion>
|
||||
</Accordion.Root>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -4,7 +4,7 @@ import {Accordion} from "@heroui/react";
|
||||
|
||||
export function Multiple() {
|
||||
return (
|
||||
<Accordion allowsMultipleExpanded className="w-full max-w-md">
|
||||
<Accordion.Root allowsMultipleExpanded className="w-full max-w-md">
|
||||
<Accordion.Item>
|
||||
<Accordion.Heading>
|
||||
<Accordion.Trigger>
|
||||
@@ -64,6 +64,6 @@ export function Multiple() {
|
||||
</Accordion.Body>
|
||||
</Accordion.Panel>
|
||||
</Accordion.Item>
|
||||
</Accordion>
|
||||
</Accordion.Root>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ const items = [
|
||||
|
||||
export function Oultine() {
|
||||
return (
|
||||
<Accordion className="w-full max-w-md" variant="outline">
|
||||
<Accordion.Root className="w-full max-w-md" variant="outline">
|
||||
{items.map((item, index) => (
|
||||
<Accordion.Item key={index}>
|
||||
<Accordion.Heading>
|
||||
@@ -62,6 +62,6 @@ export function Oultine() {
|
||||
</Accordion.Panel>
|
||||
</Accordion.Item>
|
||||
))}
|
||||
</Accordion>
|
||||
</Accordion.Root>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4,12 +4,12 @@ import {Alert} from "@heroui/react";
|
||||
|
||||
export function Basic() {
|
||||
return (
|
||||
<Alert className="max-w-lg">
|
||||
<Alert.Root className="max-w-lg">
|
||||
<Alert.Icon />
|
||||
<Alert.Content>
|
||||
<Alert.Title>Heads up!</Alert.Title>
|
||||
<Alert.Description>You can add components to your app using the cli.</Alert.Description>
|
||||
</Alert.Content>
|
||||
</Alert>
|
||||
</Alert.Root>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import {Icon} from "@iconify/react";
|
||||
export function CustomIcon() {
|
||||
return (
|
||||
<div className="flex flex-col gap-4">
|
||||
<Alert className="max-w-lg" variant="success">
|
||||
<Alert.Root className="max-w-lg" variant="success">
|
||||
<Alert.Icon>
|
||||
<Icon className="size-5" icon="gravity-ui:circle-check-fill" />
|
||||
</Alert.Icon>
|
||||
@@ -14,9 +14,9 @@ export function CustomIcon() {
|
||||
<Alert.Title>Payment received</Alert.Title>
|
||||
<Alert.Description>Your payment has been successfully processed.</Alert.Description>
|
||||
</Alert.Content>
|
||||
</Alert>
|
||||
</Alert.Root>
|
||||
|
||||
<Alert className="max-w-lg" variant="danger">
|
||||
<Alert.Root className="max-w-lg" variant="danger">
|
||||
<Alert.Icon>
|
||||
<Icon className="size-5" icon="gravity-ui:triangle-exclamation-fill" />
|
||||
</Alert.Icon>
|
||||
@@ -24,7 +24,7 @@ export function CustomIcon() {
|
||||
<Alert.Title>Security alert</Alert.Title>
|
||||
<Alert.Description>Unusual activity detected in your account.</Alert.Description>
|
||||
</Alert.Content>
|
||||
</Alert>
|
||||
</Alert.Root>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ export function Dismissible() {
|
||||
}
|
||||
|
||||
return (
|
||||
<Alert className="max-w-lg">
|
||||
<Alert.Root className="max-w-lg">
|
||||
<Alert.Icon />
|
||||
<Alert.Content>
|
||||
<Alert.Title>Dismissible Alert</Alert.Title>
|
||||
@@ -27,6 +27,6 @@ export function Dismissible() {
|
||||
</Alert.Description>
|
||||
</Alert.Content>
|
||||
<Alert.Close onClick={() => setIsVisible(false)} />
|
||||
</Alert>
|
||||
</Alert.Root>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import {Alert} from "@heroui/react";
|
||||
export function Variants() {
|
||||
return (
|
||||
<div className="flex flex-col gap-4">
|
||||
<Alert className="max-w-lg">
|
||||
<Alert.Root className="max-w-lg">
|
||||
<Alert.Icon />
|
||||
<Alert.Content>
|
||||
<Alert.Title>Default Alert</Alert.Title>
|
||||
@@ -13,31 +13,31 @@ export function Variants() {
|
||||
This is the default alert variant with neutral styling.
|
||||
</Alert.Description>
|
||||
</Alert.Content>
|
||||
</Alert>
|
||||
</Alert.Root>
|
||||
|
||||
<Alert className="max-w-lg" variant="success">
|
||||
<Alert.Root className="max-w-lg" variant="success">
|
||||
<Alert.Icon />
|
||||
<Alert.Content>
|
||||
<Alert.Title>Success!</Alert.Title>
|
||||
<Alert.Description>Your operation completed successfully.</Alert.Description>
|
||||
</Alert.Content>
|
||||
</Alert>
|
||||
</Alert.Root>
|
||||
|
||||
<Alert className="max-w-lg" variant="warning">
|
||||
<Alert.Root className="max-w-lg" variant="warning">
|
||||
<Alert.Icon />
|
||||
<Alert.Content>
|
||||
<Alert.Title>Warning</Alert.Title>
|
||||
<Alert.Description>Please review the information before proceeding.</Alert.Description>
|
||||
</Alert.Content>
|
||||
</Alert>
|
||||
</Alert.Root>
|
||||
|
||||
<Alert className="max-w-lg" variant="danger">
|
||||
<Alert.Root className="max-w-lg" variant="danger">
|
||||
<Alert.Icon />
|
||||
<Alert.Content>
|
||||
<Alert.Title>Error</Alert.Title>
|
||||
<Alert.Description>An error occurred while processing your request.</Alert.Description>
|
||||
</Alert.Content>
|
||||
</Alert>
|
||||
</Alert.Root>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import {Alert} from "@heroui/react";
|
||||
|
||||
export function WithAction() {
|
||||
return (
|
||||
<Alert className="max-w-lg">
|
||||
<Alert.Root className="max-w-lg">
|
||||
<Alert.Icon />
|
||||
<Alert.Content>
|
||||
<Alert.Title>Update available</Alert.Title>
|
||||
@@ -13,6 +13,6 @@ export function WithAction() {
|
||||
</Alert.Description>
|
||||
</Alert.Content>
|
||||
<Alert.Action onClick={() => console.log("Update clicked")}>Update</Alert.Action>
|
||||
</Alert>
|
||||
</Alert.Root>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,20 +5,20 @@ import {Avatar} from "@heroui/react";
|
||||
export function Basic() {
|
||||
return (
|
||||
<div className="flex items-center gap-4">
|
||||
<Avatar>
|
||||
<Avatar.Root>
|
||||
<Avatar.Image alt="John Doe" src="https://img.heroui.chat/image/avatar?w=400&h=400&u=3" />
|
||||
<Avatar.Fallback>JD</Avatar.Fallback>
|
||||
</Avatar>
|
||||
<Avatar>
|
||||
</Avatar.Root>
|
||||
<Avatar.Root>
|
||||
<Avatar.Image
|
||||
alt="Blue"
|
||||
src="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/avatars/blue.jpg"
|
||||
/>
|
||||
<Avatar.Fallback>B</Avatar.Fallback>
|
||||
</Avatar>
|
||||
<Avatar>
|
||||
</Avatar.Root>
|
||||
<Avatar.Root>
|
||||
<Avatar.Fallback>JR</Avatar.Fallback>
|
||||
</Avatar>
|
||||
</Avatar.Root>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,21 +5,21 @@ import {Avatar} from "@heroui/react";
|
||||
export function Colors() {
|
||||
return (
|
||||
<div className="flex items-center gap-4">
|
||||
<Avatar color="default">
|
||||
<Avatar.Root color="default">
|
||||
<Avatar.Fallback>DF</Avatar.Fallback>
|
||||
</Avatar>
|
||||
<Avatar color="accent">
|
||||
</Avatar.Root>
|
||||
<Avatar.Root color="accent">
|
||||
<Avatar.Fallback>AC</Avatar.Fallback>
|
||||
</Avatar>
|
||||
<Avatar color="success">
|
||||
</Avatar.Root>
|
||||
<Avatar.Root color="success">
|
||||
<Avatar.Fallback>SC</Avatar.Fallback>
|
||||
</Avatar>
|
||||
<Avatar color="warning">
|
||||
</Avatar.Root>
|
||||
<Avatar.Root color="warning">
|
||||
<Avatar.Fallback>WR</Avatar.Fallback>
|
||||
</Avatar>
|
||||
<Avatar color="danger">
|
||||
</Avatar.Root>
|
||||
<Avatar.Root color="danger">
|
||||
<Avatar.Fallback>DG</Avatar.Fallback>
|
||||
</Avatar>
|
||||
</Avatar.Root>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,25 +6,25 @@ export function CustomStyles() {
|
||||
return (
|
||||
<div className="flex items-center gap-4">
|
||||
{/* Custom size with Tailwind classes */}
|
||||
<Avatar className="size-16">
|
||||
<Avatar.Root className="size-16">
|
||||
<Avatar.Image
|
||||
alt="Extra Large"
|
||||
src="https://img.heroui.chat/image/avatar?w=400&h=400&u=3"
|
||||
/>
|
||||
<Avatar.Fallback>XL</Avatar.Fallback>
|
||||
</Avatar>
|
||||
</Avatar.Root>
|
||||
|
||||
{/* Square avatar */}
|
||||
<Avatar className="rounded-lg">
|
||||
<Avatar.Root className="rounded-lg">
|
||||
<Avatar.Image
|
||||
alt="Square Avatar"
|
||||
src="https://img.heroui.chat/image/avatar?w=400&h=400&u=4"
|
||||
/>
|
||||
<Avatar.Fallback className="rounded-lg">SQ</Avatar.Fallback>
|
||||
</Avatar>
|
||||
</Avatar.Root>
|
||||
|
||||
{/* Gradient border */}
|
||||
<Avatar className="bg-gradient-to-tr from-pink-500 to-yellow-500 p-0.5">
|
||||
<Avatar.Root className="bg-gradient-to-tr from-pink-500 to-yellow-500 p-0.5">
|
||||
<div className="bg-background size-full rounded-full p-0.5">
|
||||
<Avatar.Image
|
||||
alt="Gradient Border"
|
||||
@@ -33,17 +33,17 @@ export function CustomStyles() {
|
||||
/>
|
||||
<Avatar.Fallback className="border-none">GB</Avatar.Fallback>
|
||||
</div>
|
||||
</Avatar>
|
||||
</Avatar.Root>
|
||||
|
||||
{/* Status indicator */}
|
||||
<div className="relative">
|
||||
<Avatar>
|
||||
<Avatar.Root>
|
||||
<Avatar.Image
|
||||
alt="Online User"
|
||||
src="https://img.heroui.chat/image/avatar?w=400&h=400&u=8"
|
||||
/>
|
||||
<Avatar.Fallback>ON</Avatar.Fallback>
|
||||
</Avatar>
|
||||
</Avatar.Root>
|
||||
<span className="ring-background absolute bottom-0 right-0 size-3 rounded-full bg-green-500 ring-2" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -7,32 +7,32 @@ export function Fallback() {
|
||||
return (
|
||||
<div className="flex items-center gap-4">
|
||||
{/* Text fallback */}
|
||||
<Avatar>
|
||||
<Avatar.Root>
|
||||
<Avatar.Fallback>JD</Avatar.Fallback>
|
||||
</Avatar>
|
||||
</Avatar.Root>
|
||||
|
||||
{/* Icon fallback */}
|
||||
<Avatar>
|
||||
<Avatar.Root>
|
||||
<Avatar.Fallback>
|
||||
<Icon icon="gravity-ui:person" />
|
||||
</Avatar.Fallback>
|
||||
</Avatar>
|
||||
</Avatar.Root>
|
||||
|
||||
{/* Fallback with delay */}
|
||||
<Avatar>
|
||||
<Avatar.Root>
|
||||
<Avatar.Image
|
||||
alt="Delayed Avatar"
|
||||
src="https://invalid-url-to-show-fallback.com/image.jpg"
|
||||
/>
|
||||
<Avatar.Fallback delayMs={600}>NA</Avatar.Fallback>
|
||||
</Avatar>
|
||||
</Avatar.Root>
|
||||
|
||||
{/* Custom styled fallback */}
|
||||
<Avatar>
|
||||
<Avatar.Root>
|
||||
<Avatar.Fallback className="border-none bg-gradient-to-br from-pink-500 to-purple-500 text-white">
|
||||
GB
|
||||
</Avatar.Fallback>
|
||||
</Avatar>
|
||||
</Avatar.Root>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ export function Group() {
|
||||
{/* Basic avatar group */}
|
||||
<div className="flex -space-x-2">
|
||||
{users.slice(0, 4).map((user) => (
|
||||
<Avatar key={user.id} className="ring-background ring-2">
|
||||
<Avatar.Root key={user.id} className="ring-background ring-2">
|
||||
<Avatar.Image alt={user.name} src={user.image} />
|
||||
<Avatar.Fallback>
|
||||
{user.name
|
||||
@@ -44,14 +44,14 @@ export function Group() {
|
||||
.map((n) => n[0])
|
||||
.join("")}
|
||||
</Avatar.Fallback>
|
||||
</Avatar>
|
||||
</Avatar.Root>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Avatar group with counter */}
|
||||
<div className="flex -space-x-2">
|
||||
{users.slice(0, 3).map((user) => (
|
||||
<Avatar key={user.id} className="ring-background ring-2">
|
||||
<Avatar.Root key={user.id} className="ring-background ring-2">
|
||||
<Avatar.Image alt={user.name} src={user.image} />
|
||||
<Avatar.Fallback>
|
||||
{user.name
|
||||
@@ -59,11 +59,11 @@ export function Group() {
|
||||
.map((n) => n[0])
|
||||
.join("")}
|
||||
</Avatar.Fallback>
|
||||
</Avatar>
|
||||
</Avatar.Root>
|
||||
))}
|
||||
<Avatar className="ring-background ring-2">
|
||||
<Avatar.Root className="ring-background ring-2">
|
||||
<Avatar.Fallback className="text-xs">+{users.length - 3}</Avatar.Fallback>
|
||||
</Avatar>
|
||||
</Avatar.Root>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -5,27 +5,27 @@ import {Avatar} from "@heroui/react";
|
||||
export function Sizes() {
|
||||
return (
|
||||
<div className="flex items-center gap-4">
|
||||
<Avatar size="sm">
|
||||
<Avatar.Root size="sm">
|
||||
<Avatar.Image
|
||||
alt="Small Avatar"
|
||||
src="https://img.heroui.chat/image/avatar?w=400&h=400&u=3"
|
||||
/>
|
||||
<Avatar.Fallback>SM</Avatar.Fallback>
|
||||
</Avatar>
|
||||
<Avatar size="md">
|
||||
</Avatar.Root>
|
||||
<Avatar.Root size="md">
|
||||
<Avatar.Image
|
||||
alt="Medium Avatar"
|
||||
src="https://img.heroui.chat/image/avatar?w=400&h=400&u=4"
|
||||
/>
|
||||
<Avatar.Fallback>MD</Avatar.Fallback>
|
||||
</Avatar>
|
||||
<Avatar size="lg">
|
||||
</Avatar.Root>
|
||||
<Avatar.Root size="lg">
|
||||
<Avatar.Image
|
||||
alt="Large Avatar"
|
||||
src="https://img.heroui.chat/image/avatar?w=400&h=400&u=5"
|
||||
/>
|
||||
<Avatar.Fallback>LG</Avatar.Fallback>
|
||||
</Avatar>
|
||||
</Avatar.Root>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import {Icon} from "@iconify/react";
|
||||
|
||||
export function Default() {
|
||||
return (
|
||||
<Card className="w-[400px]">
|
||||
<Card.Root className="w-[400px]">
|
||||
<Icon
|
||||
aria-label="Dollar sign icon"
|
||||
className="text-primary size-6"
|
||||
@@ -20,7 +20,7 @@ export function Default() {
|
||||
<p>Add your wallet in settings to withdraw</p>
|
||||
</Card.Content>
|
||||
<Card.Footer>
|
||||
<Link
|
||||
<Link.Root
|
||||
aria-label="Go to settings (opens in new tab)"
|
||||
href="https://heroui.com"
|
||||
rel="noopener noreferrer"
|
||||
@@ -28,8 +28,8 @@ export function Default() {
|
||||
>
|
||||
Go to settings
|
||||
<Link.Icon aria-hidden="true" />
|
||||
</Link>
|
||||
</Link.Root>
|
||||
</Card.Footer>
|
||||
</Card>
|
||||
</Card.Root>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import {Button, Card} from "@heroui/react";
|
||||
|
||||
export function Horizontal() {
|
||||
return (
|
||||
<Card className="w-full items-stretch md:flex-row">
|
||||
<Card.Root className="w-full items-stretch md:flex-row">
|
||||
<img
|
||||
alt="Porsche 911 Golden Edition"
|
||||
className="rounded-panel pointer-events-none aspect-square w-full select-none object-cover md:max-w-[136px]"
|
||||
@@ -34,6 +34,6 @@ export function Horizontal() {
|
||||
<Button>Buy Now</Button>
|
||||
</Card.Footer>
|
||||
</div>
|
||||
</Card>
|
||||
</Card.Root>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import {Card} from "@heroui/react";
|
||||
export function Variants() {
|
||||
return (
|
||||
<div className="flex flex-col gap-4">
|
||||
<Card className="w-[320px]" variant="flat">
|
||||
<Card.Root className="w-[320px]" variant="flat">
|
||||
<Card.Header>
|
||||
<Card.Title>Variant Flat</Card.Title>
|
||||
<Card.Description>Transparent background with no border</Card.Description>
|
||||
@@ -13,9 +13,9 @@ export function Variants() {
|
||||
<Card.Content>
|
||||
<p>Content with no variant styling</p>
|
||||
</Card.Content>
|
||||
</Card>
|
||||
</Card.Root>
|
||||
|
||||
<Card className="w-[320px]" variant="outlined">
|
||||
<Card.Root className="w-[320px]" variant="outlined">
|
||||
<Card.Header>
|
||||
<Card.Title>Variant Outlined</Card.Title>
|
||||
<Card.Description>This card uses outlined variant (default)</Card.Description>
|
||||
@@ -23,9 +23,9 @@ export function Variants() {
|
||||
<Card.Content>
|
||||
<p>Content with subtle elevation</p>
|
||||
</Card.Content>
|
||||
</Card>
|
||||
</Card.Root>
|
||||
|
||||
<Card className="w-[320px]" variant="elevated">
|
||||
<Card.Root className="w-[320px]" variant="elevated">
|
||||
<Card.Header>
|
||||
<Card.Title>Variant Elevated</Card.Title>
|
||||
<Card.Description>This card uses elevated variant</Card.Description>
|
||||
@@ -33,9 +33,9 @@ export function Variants() {
|
||||
<Card.Content>
|
||||
<p>Content with medium elevation</p>
|
||||
</Card.Content>
|
||||
</Card>
|
||||
</Card.Root>
|
||||
|
||||
<Card className="w-[320px]" variant="filled">
|
||||
<Card.Root className="w-[320px]" variant="filled">
|
||||
<Card.Header>
|
||||
<Card.Title>Variant Filled</Card.Title>
|
||||
<Card.Description>This card uses filled variant</Card.Description>
|
||||
@@ -43,7 +43,7 @@ export function Variants() {
|
||||
<Card.Content>
|
||||
<p>Content with higher elevation</p>
|
||||
</Card.Content>
|
||||
</Card>
|
||||
</Card.Root>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import {Avatar, Card} from "@heroui/react";
|
||||
export function WithAvatar() {
|
||||
return (
|
||||
<div className="flex flex-col gap-4 md:flex-row">
|
||||
<Card className="w-[200px] gap-2">
|
||||
<Card.Root className="w-[200px] gap-2">
|
||||
<img
|
||||
alt="Indie Hackers community"
|
||||
className="rounded-panel pointer-events-none aspect-square w-14 select-none object-cover"
|
||||
@@ -17,18 +17,18 @@ export function WithAvatar() {
|
||||
<Card.Description>148 members</Card.Description>
|
||||
</Card.Header>
|
||||
<Card.Footer className="flex gap-2">
|
||||
<Avatar aria-label="Martha's profile picture" className="size-5" role="img">
|
||||
<Avatar.Root aria-label="Martha's profile picture" className="size-5" role="img">
|
||||
<Avatar.Image
|
||||
alt="Martha's avatar"
|
||||
src="https://img.heroui.chat/image/avatar?w=160&h=160"
|
||||
/>
|
||||
<Avatar.Fallback className="text-xs">IH</Avatar.Fallback>
|
||||
</Avatar>
|
||||
</Avatar.Root>
|
||||
<span className="text-xs">By Martha</span>
|
||||
</Card.Footer>
|
||||
</Card>
|
||||
</Card.Root>
|
||||
|
||||
<Card className="w-[200px] gap-2">
|
||||
<Card.Root className="w-[200px] gap-2">
|
||||
<img
|
||||
alt="AI Builders community"
|
||||
className="rounded-panel pointer-events-none aspect-square w-14 select-none object-cover"
|
||||
@@ -40,16 +40,16 @@ export function WithAvatar() {
|
||||
<Card.Description>362 members</Card.Description>
|
||||
</Card.Header>
|
||||
<Card.Footer className="flex gap-2">
|
||||
<Avatar aria-label="John's profile picture" className="size-5" role="img">
|
||||
<Avatar.Root aria-label="John's profile picture" className="size-5" role="img">
|
||||
<Avatar.Image
|
||||
alt="John's avatar - blue themed"
|
||||
src="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/avatars/blue.jpg"
|
||||
/>
|
||||
<Avatar.Fallback className="text-xs">B</Avatar.Fallback>
|
||||
</Avatar>
|
||||
</Avatar.Root>
|
||||
<span className="text-xs">By John</span>
|
||||
</Card.Footer>
|
||||
</Card>
|
||||
</Card.Root>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import {Icon} from "@iconify/react";
|
||||
export function WithBackgroundImage() {
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center gap-6 md:flex-row">
|
||||
<Card className="aspect-[280/337] w-full max-w-[280px]">
|
||||
<Card.Root className="aspect-[280/337] w-full max-w-[280px]">
|
||||
{/* Background image */}
|
||||
<img
|
||||
alt="Happy pet"
|
||||
@@ -67,9 +67,9 @@ export function WithBackgroundImage() {
|
||||
Notify me
|
||||
</Button>
|
||||
</Card.Footer>
|
||||
</Card>
|
||||
</Card.Root>
|
||||
|
||||
<Card className="aspect-[65/56] w-full md:w-[390px]">
|
||||
<Card.Root className="aspect-[65/56] w-full md:w-[390px]">
|
||||
{/* Background image */}
|
||||
<img
|
||||
alt="Beautiful aerial view of Buenos Aires cityscape"
|
||||
@@ -105,7 +105,7 @@ export function WithBackgroundImage() {
|
||||
Map
|
||||
</Button>
|
||||
</Card.Footer>
|
||||
</Card>
|
||||
</Card.Root>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,46 +1,32 @@
|
||||
"use client";
|
||||
|
||||
import {Button, Card, Link} from "@heroui/react";
|
||||
import {Button, Card, Input, Label, Link, TextField} from "@heroui/react";
|
||||
|
||||
export function WithForm() {
|
||||
return (
|
||||
<Card className="w-full max-w-md">
|
||||
<Card.Root className="w-full max-w-md">
|
||||
<Card.Header>
|
||||
<Card.Title>Login</Card.Title>
|
||||
<Card.Description>Enter your credentials to access your account</Card.Description>
|
||||
</Card.Header>
|
||||
<Card.Content>
|
||||
<form className="flex flex-col gap-4">
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-sm font-medium" htmlFor="email">
|
||||
Email
|
||||
</label>
|
||||
<input
|
||||
className="border-border bg-background focus:ring-focus rounded-md border px-3 py-2 text-sm focus:outline-none focus:ring-2"
|
||||
id="email"
|
||||
placeholder="email@example.com"
|
||||
type="email"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-sm font-medium" htmlFor="password">
|
||||
Password
|
||||
</label>
|
||||
<input
|
||||
className="border-border bg-background focus:ring-focus rounded-md border px-3 py-2 text-sm focus:outline-none focus:ring-2"
|
||||
id="password"
|
||||
placeholder="••••••••"
|
||||
type="password"
|
||||
/>
|
||||
</div>
|
||||
<TextField name="email" type="email">
|
||||
<Label>Email</Label>
|
||||
<Input placeholder="email@example.com" />
|
||||
</TextField>
|
||||
<TextField name="password" type="password">
|
||||
<Label>Password</Label>
|
||||
<Input placeholder="••••••••" />
|
||||
</TextField>
|
||||
</form>
|
||||
</Card.Content>
|
||||
<Card.Footer className="flex flex-col gap-2">
|
||||
<Button className="w-full">Sign In</Button>
|
||||
<Link className="text-center text-sm" href="#">
|
||||
<Link.Root className="text-center text-sm" href="#">
|
||||
Forgot password?
|
||||
</Link>
|
||||
</Link.Root>
|
||||
</Card.Footer>
|
||||
</Card>
|
||||
</Card.Root>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import {Card} from "@heroui/react";
|
||||
export function WithImage() {
|
||||
return (
|
||||
<div className="flex flex-col gap-4 md:flex-row">
|
||||
<Card className="w-[220px] gap-2 p-1">
|
||||
<Card.Root className="w-[220px] gap-2 p-1">
|
||||
<img
|
||||
alt="Luxury cars collection"
|
||||
className="block aspect-square w-full shrink-0 select-none rounded-[calc(theme(--radius-panel)-theme(spacing.1))] object-cover align-middle"
|
||||
@@ -18,9 +18,9 @@ export function WithImage() {
|
||||
18 pictures
|
||||
</span>
|
||||
</Card.Footer>
|
||||
</Card>
|
||||
</Card.Root>
|
||||
|
||||
<Card className="w-[220px] gap-2 p-1">
|
||||
<Card.Root className="w-[220px] gap-2 p-1">
|
||||
<img
|
||||
alt="Modern office workspace"
|
||||
className="block aspect-square w-full shrink-0 select-none rounded-[calc(theme(--radius-panel)-theme(spacing.1))] object-cover align-middle"
|
||||
@@ -33,7 +33,7 @@ export function WithImage() {
|
||||
56 pictures
|
||||
</span>
|
||||
</Card.Footer>
|
||||
</Card>
|
||||
</Card.Root>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ export function Basic() {
|
||||
<div className="w-full max-w-md">
|
||||
<div className="flex flex-col gap-4 bg-transparent p-4">
|
||||
<DisclosureGroup expandedKeys={expandedKeys} onExpandedChange={setExpandedKeys}>
|
||||
<Disclosure aria-label="Preview HeroUI Native" id="preview">
|
||||
<Disclosure.Root aria-label="Preview HeroUI Native" id="preview">
|
||||
<Disclosure.Heading>
|
||||
<Button
|
||||
slot="trigger"
|
||||
@@ -45,9 +45,9 @@ export function Basic() {
|
||||
</Button>
|
||||
</Disclosure.Body>
|
||||
</Disclosure.Content>
|
||||
</Disclosure>
|
||||
</Disclosure.Root>
|
||||
<Separator className="my-2" />
|
||||
<Disclosure id="download">
|
||||
<Disclosure.Root id="download">
|
||||
<Disclosure.Heading aria-label="Download HeroUI Native">
|
||||
<Button
|
||||
slot="trigger"
|
||||
@@ -81,7 +81,7 @@ export function Basic() {
|
||||
</Button>
|
||||
</Disclosure.Body>
|
||||
</Disclosure.Content>
|
||||
</Disclosure>
|
||||
</Disclosure.Root>
|
||||
</DisclosureGroup>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -48,7 +48,7 @@ export function Controlled() {
|
||||
</div>
|
||||
</div>
|
||||
<DisclosureGroup expandedKeys={expandedKeys} onExpandedChange={setExpandedKeys}>
|
||||
<Disclosure aria-label="Preview HeroUI Native" id="preview">
|
||||
<Disclosure.Root aria-label="Preview HeroUI Native" id="preview">
|
||||
<Disclosure.Heading>
|
||||
<Button
|
||||
slot="trigger"
|
||||
@@ -81,9 +81,9 @@ export function Controlled() {
|
||||
</Button>
|
||||
</Disclosure.Body>
|
||||
</Disclosure.Content>
|
||||
</Disclosure>
|
||||
</Disclosure.Root>
|
||||
<Separator className="my-2" />
|
||||
<Disclosure id="download">
|
||||
<Disclosure.Root id="download">
|
||||
<Disclosure.Heading aria-label="Download HeroUI Native">
|
||||
<Button
|
||||
slot="trigger"
|
||||
@@ -116,7 +116,7 @@ export function Controlled() {
|
||||
</Button>
|
||||
</Disclosure.Body>
|
||||
</Disclosure.Content>
|
||||
</Disclosure>
|
||||
</Disclosure.Root>
|
||||
</DisclosureGroup>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -9,7 +9,7 @@ export function Basic() {
|
||||
|
||||
return (
|
||||
<div className="w-full max-w-md text-center">
|
||||
<Disclosure isExpanded={isExpanded} onExpandedChange={setIsExpanded}>
|
||||
<Disclosure.Root isExpanded={isExpanded} onExpandedChange={setIsExpanded}>
|
||||
<Disclosure.Heading>
|
||||
<Button slot="trigger" variant="secondary">
|
||||
<Icon icon="gravity-ui:qr-code" />
|
||||
@@ -34,7 +34,7 @@ export function Basic() {
|
||||
</Button>
|
||||
</Disclosure.Body>
|
||||
</Disclosure.Content>
|
||||
</Disclosure>
|
||||
</Disclosure.Root>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
Button,
|
||||
Description,
|
||||
FieldError,
|
||||
FieldGroup,
|
||||
Fieldset,
|
||||
Form,
|
||||
Input,
|
||||
@@ -29,10 +30,10 @@ export function Basic() {
|
||||
|
||||
return (
|
||||
<Form className="w-full max-w-96" onSubmit={onSubmit}>
|
||||
<Fieldset>
|
||||
<Fieldset.Root>
|
||||
<Fieldset.Legend>Profile Settings</Fieldset.Legend>
|
||||
<Description>Update your profile information.</Description>
|
||||
<Fieldset.Group>
|
||||
<FieldGroup>
|
||||
<TextField
|
||||
isRequired
|
||||
name="name"
|
||||
@@ -69,7 +70,7 @@ export function Basic() {
|
||||
<Description>Minimum 10 characters</Description>
|
||||
<FieldError />
|
||||
</TextField>
|
||||
</Fieldset.Group>
|
||||
</FieldGroup>
|
||||
<Fieldset.Actions>
|
||||
<Button type="submit">
|
||||
<Icon icon="gravity-ui:floppy-disk" />
|
||||
@@ -79,7 +80,7 @@ export function Basic() {
|
||||
Cancel
|
||||
</Button>
|
||||
</Fieldset.Actions>
|
||||
</Fieldset>
|
||||
</Fieldset.Root>
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,22 +5,22 @@ import {Kbd} from "@heroui/react";
|
||||
export function Basic() {
|
||||
return (
|
||||
<div className="flex items-center gap-4">
|
||||
<Kbd>
|
||||
<Kbd.Root>
|
||||
<Kbd.Abbr keyValue="command" />
|
||||
<Kbd.Content>K</Kbd.Content>
|
||||
</Kbd>
|
||||
<Kbd>
|
||||
</Kbd.Root>
|
||||
<Kbd.Root>
|
||||
<Kbd.Abbr keyValue="shift" />
|
||||
<Kbd.Content>P</Kbd.Content>
|
||||
</Kbd>
|
||||
<Kbd>
|
||||
</Kbd.Root>
|
||||
<Kbd.Root>
|
||||
<Kbd.Abbr keyValue="ctrl" />
|
||||
<Kbd.Content>C</Kbd.Content>
|
||||
</Kbd>
|
||||
<Kbd>
|
||||
</Kbd.Root>
|
||||
<Kbd.Root>
|
||||
<Kbd.Abbr keyValue="option" />
|
||||
<Kbd.Content>D</Kbd.Content>
|
||||
</Kbd>
|
||||
</Kbd.Root>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -7,36 +7,36 @@ export function InlineUsage() {
|
||||
<div className="space-y-4">
|
||||
<p className="text-sm">
|
||||
Press{" "}
|
||||
<Kbd>
|
||||
<Kbd.Root>
|
||||
<Kbd.Content>Esc</Kbd.Content>
|
||||
</Kbd>{" "}
|
||||
</Kbd.Root>{" "}
|
||||
to close the dialog.
|
||||
</p>
|
||||
<p className="text-sm">
|
||||
Use{" "}
|
||||
<Kbd>
|
||||
<Kbd.Root>
|
||||
<Kbd.Abbr keyValue="command" />
|
||||
<Kbd.Content>K</Kbd.Content>
|
||||
</Kbd>{" "}
|
||||
</Kbd.Root>{" "}
|
||||
to open the command palette.
|
||||
</p>
|
||||
<p className="text-sm">
|
||||
Navigate with{" "}
|
||||
<Kbd>
|
||||
<Kbd.Root>
|
||||
<Kbd.Abbr keyValue="up" />
|
||||
</Kbd>{" "}
|
||||
</Kbd.Root>{" "}
|
||||
and{" "}
|
||||
<Kbd>
|
||||
<Kbd.Root>
|
||||
<Kbd.Abbr keyValue="down" />
|
||||
</Kbd>{" "}
|
||||
</Kbd.Root>{" "}
|
||||
arrow keys.
|
||||
</p>
|
||||
<p className="text-sm">
|
||||
Save your work with{" "}
|
||||
<Kbd>
|
||||
<Kbd.Root>
|
||||
<Kbd.Abbr keyValue="command" />
|
||||
<Kbd.Content>S</Kbd.Content>
|
||||
</Kbd>{" "}
|
||||
</Kbd.Root>{" "}
|
||||
regularly.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -10,31 +10,31 @@ export function InstructionalText() {
|
||||
<ul className="space-y-2 text-sm">
|
||||
<li>
|
||||
• Open search:{" "}
|
||||
<Kbd>
|
||||
<Kbd.Root>
|
||||
<Kbd.Abbr keyValue="command" />
|
||||
<Kbd.Content>K</Kbd.Content>
|
||||
</Kbd>
|
||||
</Kbd.Root>
|
||||
</li>
|
||||
<li>
|
||||
• Toggle sidebar:{" "}
|
||||
<Kbd>
|
||||
<Kbd.Root>
|
||||
<Kbd.Abbr keyValue="command" />
|
||||
<Kbd.Content>B</Kbd.Content>
|
||||
</Kbd>
|
||||
</Kbd.Root>
|
||||
</li>
|
||||
<li>
|
||||
• New file:{" "}
|
||||
<Kbd>
|
||||
<Kbd.Root>
|
||||
<Kbd.Abbr keyValue="command" />
|
||||
<Kbd.Content>N</Kbd.Content>
|
||||
</Kbd>
|
||||
</Kbd.Root>
|
||||
</li>
|
||||
<li>
|
||||
• Quick save:{" "}
|
||||
<Kbd>
|
||||
<Kbd.Root>
|
||||
<Kbd.Abbr keyValue="command" />
|
||||
<Kbd.Content>S</Kbd.Content>
|
||||
</Kbd>
|
||||
</Kbd.Root>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -8,35 +8,35 @@ export function NavigationKeys() {
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-muted text-sm">Arrow Keys:</span>
|
||||
<div className="flex items-center gap-2">
|
||||
<Kbd>
|
||||
<Kbd.Root>
|
||||
<Kbd.Abbr keyValue="up" />
|
||||
</Kbd>
|
||||
<Kbd>
|
||||
</Kbd.Root>
|
||||
<Kbd.Root>
|
||||
<Kbd.Abbr keyValue="down" />
|
||||
</Kbd>
|
||||
<Kbd>
|
||||
</Kbd.Root>
|
||||
<Kbd.Root>
|
||||
<Kbd.Abbr keyValue="left" />
|
||||
</Kbd>
|
||||
<Kbd>
|
||||
</Kbd.Root>
|
||||
<Kbd.Root>
|
||||
<Kbd.Abbr keyValue="right" />
|
||||
</Kbd>
|
||||
</Kbd.Root>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-muted text-sm">Page Navigation:</span>
|
||||
<div className="flex items-center gap-2">
|
||||
<Kbd>
|
||||
<Kbd.Root>
|
||||
<Kbd.Abbr keyValue="pageup" />
|
||||
</Kbd>
|
||||
<Kbd>
|
||||
</Kbd.Root>
|
||||
<Kbd.Root>
|
||||
<Kbd.Abbr keyValue="pagedown" />
|
||||
</Kbd>
|
||||
<Kbd>
|
||||
</Kbd.Root>
|
||||
<Kbd.Root>
|
||||
<Kbd.Abbr keyValue="home" />
|
||||
</Kbd>
|
||||
<Kbd>
|
||||
</Kbd.Root>
|
||||
<Kbd.Root>
|
||||
<Kbd.Abbr keyValue="end" />
|
||||
</Kbd>
|
||||
</Kbd.Root>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -7,32 +7,32 @@ export function SpecialKeys() {
|
||||
<div className="space-y-3">
|
||||
<p className="text-sm">
|
||||
Press{" "}
|
||||
<Kbd>
|
||||
<Kbd.Root>
|
||||
<Kbd.Abbr keyValue="enter" />
|
||||
</Kbd>{" "}
|
||||
</Kbd.Root>{" "}
|
||||
to confirm or{" "}
|
||||
<Kbd>
|
||||
<Kbd.Root>
|
||||
<Kbd.Abbr keyValue="escape" />
|
||||
</Kbd>{" "}
|
||||
</Kbd.Root>{" "}
|
||||
to cancel.
|
||||
</p>
|
||||
<p className="text-sm">
|
||||
Use{" "}
|
||||
<Kbd>
|
||||
<Kbd.Root>
|
||||
<Kbd.Abbr keyValue="tab" />
|
||||
</Kbd>{" "}
|
||||
</Kbd.Root>{" "}
|
||||
to navigate between form fields and{" "}
|
||||
<Kbd>
|
||||
<Kbd.Root>
|
||||
<Kbd.Abbr keyValue="shift" />
|
||||
<Kbd.Abbr keyValue="tab" />
|
||||
</Kbd>{" "}
|
||||
</Kbd.Root>{" "}
|
||||
to go back.
|
||||
</p>
|
||||
<p className="text-sm">
|
||||
Hold{" "}
|
||||
<Kbd>
|
||||
<Kbd.Root>
|
||||
<Kbd.Abbr keyValue="space" />
|
||||
</Kbd>{" "}
|
||||
</Kbd.Root>{" "}
|
||||
to temporarily enable panning mode.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -5,15 +5,15 @@ import {Link} from "@heroui/react";
|
||||
export function LinkBasic() {
|
||||
return (
|
||||
<div className="flex flex-wrap items-center gap-4">
|
||||
<Link href="#">
|
||||
<Link.Root href="#">
|
||||
Call to action
|
||||
<Link.Icon />
|
||||
</Link>
|
||||
<Link isDisabled href="#">
|
||||
</Link.Root>
|
||||
<Link.Root isDisabled href="#">
|
||||
Call to action
|
||||
<Link.Icon />
|
||||
</Link>
|
||||
<Link
|
||||
</Link.Root>
|
||||
<Link.Root
|
||||
className="border-default bg-default-100 text-foreground hover:bg-default-200 inline-flex items-center gap-2 rounded-full border px-3 py-1 text-sm font-medium transition"
|
||||
href="https://heroui.com"
|
||||
rel="noopener noreferrer"
|
||||
@@ -21,7 +21,7 @@ export function LinkBasic() {
|
||||
>
|
||||
HeroUI
|
||||
<Link.Icon className="h-3 w-3" />
|
||||
</Link>
|
||||
</Link.Root>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -7,20 +7,20 @@ import {LinkIcon} from "@/icons/link";
|
||||
export function LinkCustomIcon() {
|
||||
return (
|
||||
<div className="flex flex-col gap-3">
|
||||
<Link href="#">
|
||||
<Link.Root href="#">
|
||||
External link
|
||||
<Link.Icon>
|
||||
<LinkIcon className="h-3.5 w-3.5" />
|
||||
</Link.Icon>
|
||||
</Link>
|
||||
<Link className="gap-1" href="#">
|
||||
</Link.Root>
|
||||
<Link.Root className="gap-1" href="#">
|
||||
<Link.Icon>
|
||||
<svg aria-hidden="true" className="h-4 w-4" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path d="M10 2a8 8 0 1 1-8 8 8.01 8.01 0 0 1 8-8Zm.75 4.75a.75.75 0 1 0-1.5 0v4.5a.75.75 0 0 0 1.5 0Zm0 6a.75.75 0 1 0-1.5 0 .75.75 0 0 0 1.5 0Z" />
|
||||
</svg>
|
||||
</Link.Icon>
|
||||
Inline SVG icon
|
||||
</Link>
|
||||
</Link.Root>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,14 +5,14 @@ import {Link} from "@heroui/react";
|
||||
export function LinkIconPlacement() {
|
||||
return (
|
||||
<div className="flex flex-col gap-3">
|
||||
<Link href="#">
|
||||
<Link.Root href="#">
|
||||
Icon at end (default)
|
||||
<Link.Icon />
|
||||
</Link>
|
||||
<Link className="gap-1" href="#">
|
||||
</Link.Root>
|
||||
<Link.Root className="gap-1" href="#">
|
||||
<Link.Icon />
|
||||
Icon at start
|
||||
</Link>
|
||||
</Link.Root>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import {Button, Popover} from "@heroui/react";
|
||||
export function PopoverBasic() {
|
||||
return (
|
||||
<div className="flex items-center gap-4">
|
||||
<Popover>
|
||||
<Popover.Root>
|
||||
<Button>Click me</Button>
|
||||
<Popover.Content>
|
||||
<Popover.Dialog>
|
||||
@@ -15,7 +15,7 @@ export function PopoverBasic() {
|
||||
</p>
|
||||
</Popover.Dialog>
|
||||
</Popover.Content>
|
||||
</Popover>
|
||||
</Popover.Root>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -8,16 +8,16 @@ export function PopoverInteractive() {
|
||||
|
||||
return (
|
||||
<div className="flex items-center gap-6">
|
||||
<Popover>
|
||||
<Popover.Root>
|
||||
<Popover.Trigger aria-label="User profile">
|
||||
<div className="flex items-center gap-2">
|
||||
<Avatar size="sm">
|
||||
<Avatar.Root size="sm">
|
||||
<Avatar.Image
|
||||
alt="Sarah Johnson"
|
||||
src="https://img.heroui.chat/image/avatar?w=400&h=400&u=3"
|
||||
/>
|
||||
<Avatar.Fallback>SJ</Avatar.Fallback>
|
||||
</Avatar>
|
||||
</Avatar.Root>
|
||||
<div className="flex flex-col">
|
||||
<p className="text-sm font-medium">Sarah Johnson</p>
|
||||
<p className="text-muted text-xs">@sarahj</p>
|
||||
@@ -29,13 +29,13 @@ export function PopoverInteractive() {
|
||||
<Popover.Heading>
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-3">
|
||||
<Avatar size="md">
|
||||
<Avatar.Root size="md">
|
||||
<Avatar.Image
|
||||
alt="Sarah Johnson"
|
||||
src="https://img.heroui.chat/image/avatar?w=400&h=400&u=3"
|
||||
/>
|
||||
<Avatar.Fallback>SJ</Avatar.Fallback>
|
||||
</Avatar>
|
||||
</Avatar.Root>
|
||||
<div>
|
||||
<p className="font-semibold">Sarah Johnson</p>
|
||||
<p className="text-muted text-sm">@sarahj</p>
|
||||
@@ -66,7 +66,7 @@ export function PopoverInteractive() {
|
||||
</div>
|
||||
</Popover.Dialog>
|
||||
</Popover.Content>
|
||||
</Popover>
|
||||
</Popover.Root>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ export function PopoverPlacement() {
|
||||
return (
|
||||
<div className="grid grid-cols-3 gap-4">
|
||||
<div />
|
||||
<Popover>
|
||||
<Popover.Root>
|
||||
<Button className="w-full" variant="tertiary">
|
||||
Top
|
||||
</Button>
|
||||
@@ -16,10 +16,10 @@ export function PopoverPlacement() {
|
||||
<p className="text-sm">Top placement</p>
|
||||
</Popover.Dialog>
|
||||
</Popover.Content>
|
||||
</Popover>
|
||||
</Popover.Root>
|
||||
<div />
|
||||
|
||||
<Popover>
|
||||
<Popover.Root>
|
||||
<Button className="w-full" variant="tertiary">
|
||||
Left
|
||||
</Button>
|
||||
@@ -29,13 +29,13 @@ export function PopoverPlacement() {
|
||||
<p className="text-sm">Left placement</p>
|
||||
</Popover.Dialog>
|
||||
</Popover.Content>
|
||||
</Popover>
|
||||
</Popover.Root>
|
||||
|
||||
<div className="flex items-center justify-center">
|
||||
<span className="text-muted text-sm">Click buttons</span>
|
||||
</div>
|
||||
|
||||
<Popover>
|
||||
<Popover.Root>
|
||||
<Button className="w-full" variant="tertiary">
|
||||
Right
|
||||
</Button>
|
||||
@@ -45,10 +45,10 @@ export function PopoverPlacement() {
|
||||
<p className="text-sm">Right placement</p>
|
||||
</Popover.Dialog>
|
||||
</Popover.Content>
|
||||
</Popover>
|
||||
</Popover.Root>
|
||||
|
||||
<div />
|
||||
<Popover>
|
||||
<Popover.Root>
|
||||
<Button className="w-full" variant="tertiary">
|
||||
Bottom
|
||||
</Button>
|
||||
@@ -58,7 +58,7 @@ export function PopoverPlacement() {
|
||||
<p className="text-sm">Bottom placement</p>
|
||||
</Popover.Dialog>
|
||||
</Popover.Content>
|
||||
</Popover>
|
||||
</Popover.Root>
|
||||
<div />
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -6,7 +6,7 @@ import {Icon} from "@iconify/react";
|
||||
export function PopoverWithArrow() {
|
||||
return (
|
||||
<div className="flex items-center gap-4">
|
||||
<Popover>
|
||||
<Popover.Root>
|
||||
<Button variant="secondary">With Arrow</Button>
|
||||
<Popover.Content>
|
||||
<Popover.Dialog>
|
||||
@@ -17,9 +17,9 @@ export function PopoverWithArrow() {
|
||||
</p>
|
||||
</Popover.Dialog>
|
||||
</Popover.Content>
|
||||
</Popover>
|
||||
</Popover.Root>
|
||||
|
||||
<Popover>
|
||||
<Popover.Root>
|
||||
<Button isIconOnly variant="tertiary">
|
||||
<Icon icon="gravity-ui:ellipsis" />
|
||||
</Button>
|
||||
@@ -32,7 +32,7 @@ export function PopoverWithArrow() {
|
||||
</p>
|
||||
</Popover.Dialog>
|
||||
</Popover.Content>
|
||||
</Popover>
|
||||
</Popover.Root>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ export function Basic() {
|
||||
<RadioGroup defaultValue="premium" name="plan">
|
||||
<Label>Plan selection</Label>
|
||||
<Description>Choose the plan that suits you best</Description>
|
||||
<Radio value="basic">
|
||||
<Radio.Root value="basic">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
@@ -15,8 +15,8 @@ export function Basic() {
|
||||
<Label>Basic Plan</Label>
|
||||
<Description>Includes 100 messages per month</Description>
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
<Radio value="premium">
|
||||
</Radio.Root>
|
||||
<Radio.Root value="premium">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
@@ -24,8 +24,8 @@ export function Basic() {
|
||||
<Label>Premium Plan</Label>
|
||||
<Description>Includes 200 messages per month</Description>
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
<Radio value="business">
|
||||
</Radio.Root>
|
||||
<Radio.Root value="business">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
@@ -33,7 +33,7 @@ export function Basic() {
|
||||
<Label>Business Plan</Label>
|
||||
<Description>Unlimited messages</Description>
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
</Radio.Root>
|
||||
</RadioGroup>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ export function Controlled() {
|
||||
<div className="flex flex-col gap-4">
|
||||
<RadioGroup name="plan-controlled" value={value} onChange={setValue}>
|
||||
<Label>Subscription plan</Label>
|
||||
<Radio value="starter">
|
||||
<Radio.Root value="starter">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
@@ -18,8 +18,8 @@ export function Controlled() {
|
||||
<Label>Starter</Label>
|
||||
<Description>For side projects and small teams</Description>
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
<Radio value="pro">
|
||||
</Radio.Root>
|
||||
<Radio.Root value="pro">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
@@ -27,8 +27,8 @@ export function Controlled() {
|
||||
<Label>Pro</Label>
|
||||
<Description>Advanced reporting and analytics</Description>
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
<Radio value="teams">
|
||||
</Radio.Root>
|
||||
<Radio.Root value="teams">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
@@ -36,7 +36,7 @@ export function Controlled() {
|
||||
<Label>Teams</Label>
|
||||
<Description>Share access with up to 10 teammates</Description>
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
</Radio.Root>
|
||||
</RadioGroup>
|
||||
<p className="text-muted text-sm">
|
||||
Selected plan: <span className="font-medium">{value}</span>
|
||||
|
||||
@@ -7,7 +7,7 @@ export function CustomIndicator() {
|
||||
<RadioGroup defaultValue="premium" name="plan-custom-indicator">
|
||||
<Label>Plan selection</Label>
|
||||
<Description>Choose the plan that suits you best</Description>
|
||||
<Radio value="basic">
|
||||
<Radio.Root value="basic">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator>
|
||||
{({isSelected}) =>
|
||||
@@ -19,8 +19,8 @@ export function CustomIndicator() {
|
||||
<Label>Basic Plan</Label>
|
||||
<Description>Includes 100 messages per month</Description>
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
<Radio value="premium">
|
||||
</Radio.Root>
|
||||
<Radio.Root value="premium">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator>
|
||||
{({isSelected}) =>
|
||||
@@ -32,8 +32,8 @@ export function CustomIndicator() {
|
||||
<Label>Premium Plan</Label>
|
||||
<Description>Includes 200 messages per month</Description>
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
<Radio value="business">
|
||||
</Radio.Root>
|
||||
<Radio.Root value="business">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator>
|
||||
{({isSelected}) =>
|
||||
@@ -45,7 +45,7 @@ export function CustomIndicator() {
|
||||
<Label>Business Plan</Label>
|
||||
<Description>Unlimited messages</Description>
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
</Radio.Root>
|
||||
</RadioGroup>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ export function DeliveryAndPayment() {
|
||||
<Label>Delivery method</Label>
|
||||
<div className="grid gap-x-4 md:grid-cols-3">
|
||||
{deliveryOptions.map((option) => (
|
||||
<Radio
|
||||
<Radio.Root
|
||||
key={option.value}
|
||||
value={option.value}
|
||||
className={clsx(
|
||||
@@ -83,7 +83,7 @@ export function DeliveryAndPayment() {
|
||||
</div>
|
||||
<span className="text-sm font-semibold">{option.price}</span>
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
</Radio.Root>
|
||||
))}
|
||||
</div>
|
||||
</RadioGroup>
|
||||
@@ -95,7 +95,7 @@ export function DeliveryAndPayment() {
|
||||
</div>
|
||||
<div className="grid gap-x-4 md:grid-cols-2">
|
||||
{paymentOptions.map((option) => (
|
||||
<Radio
|
||||
<Radio.Root
|
||||
key={option.value}
|
||||
value={option.value}
|
||||
className={clsx(
|
||||
@@ -113,7 +113,7 @@ export function DeliveryAndPayment() {
|
||||
<Description>{option.description}</Description>
|
||||
</div>
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
</Radio.Root>
|
||||
))}
|
||||
</div>
|
||||
</RadioGroup>
|
||||
|
||||
@@ -7,7 +7,7 @@ export function Disabled() {
|
||||
<RadioGroup isDisabled defaultValue="pro" name="plan-disabled">
|
||||
<Label>Subscription plan</Label>
|
||||
<Description>Plan changes are temporarily paused while we roll out updates.</Description>
|
||||
<Radio value="starter">
|
||||
<Radio.Root value="starter">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
@@ -15,8 +15,8 @@ export function Disabled() {
|
||||
<Label>Starter</Label>
|
||||
<Description>For side projects and small teams</Description>
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
<Radio value="pro">
|
||||
</Radio.Root>
|
||||
<Radio.Root value="pro">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
@@ -24,8 +24,8 @@ export function Disabled() {
|
||||
<Label>Pro</Label>
|
||||
<Description>Advanced reporting and analytics</Description>
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
<Radio value="teams">
|
||||
</Radio.Root>
|
||||
<Radio.Root value="teams">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
@@ -33,7 +33,7 @@ export function Disabled() {
|
||||
<Label>Teams</Label>
|
||||
<Description>Share access with up to 10 teammates</Description>
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
</Radio.Root>
|
||||
</RadioGroup>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ export function Horizontal() {
|
||||
<div className="flex flex-col gap-4">
|
||||
<Label>Subscription plan</Label>
|
||||
<RadioGroup defaultValue="pro" name="plan-orientation" orientation="horizontal">
|
||||
<Radio value="starter">
|
||||
<Radio.Root value="starter">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
@@ -15,8 +15,8 @@ export function Horizontal() {
|
||||
<Label>Starter</Label>
|
||||
<Description>For side projects</Description>
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
<Radio value="pro">
|
||||
</Radio.Root>
|
||||
<Radio.Root value="pro">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
@@ -24,8 +24,8 @@ export function Horizontal() {
|
||||
<Label>Pro</Label>
|
||||
<Description>Advanced reporting</Description>
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
<Radio value="teams">
|
||||
</Radio.Root>
|
||||
<Radio.Root value="teams">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
@@ -33,7 +33,7 @@ export function Horizontal() {
|
||||
<Label>Teams</Label>
|
||||
<Description>Up to 10 teammates</Description>
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
</Radio.Root>
|
||||
</RadioGroup>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -14,7 +14,7 @@ export function Uncontrolled() {
|
||||
onChange={(nextValue) => setSelection(nextValue)}
|
||||
>
|
||||
<Label>Subscription plan</Label>
|
||||
<Radio value="starter">
|
||||
<Radio.Root value="starter">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
@@ -22,8 +22,8 @@ export function Uncontrolled() {
|
||||
<Label>Starter</Label>
|
||||
<Description>For side projects and small teams</Description>
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
<Radio value="pro">
|
||||
</Radio.Root>
|
||||
<Radio.Root value="pro">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
@@ -31,8 +31,8 @@ export function Uncontrolled() {
|
||||
<Label>Pro</Label>
|
||||
<Description>Advanced reporting and analytics</Description>
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
<Radio value="teams">
|
||||
</Radio.Root>
|
||||
<Radio.Root value="teams">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
@@ -40,7 +40,7 @@ export function Uncontrolled() {
|
||||
<Label>Teams</Label>
|
||||
<Description>Share access with up to 10 teammates</Description>
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
</Radio.Root>
|
||||
</RadioGroup>
|
||||
<p className="text-muted text-sm">
|
||||
Last chosen plan: <span className="font-medium">{selection}</span>
|
||||
|
||||
@@ -20,7 +20,7 @@ export function Validation() {
|
||||
>
|
||||
<RadioGroup isRequired name="plan-validation">
|
||||
<Label>Subscription plan</Label>
|
||||
<Radio value="starter">
|
||||
<Radio.Root value="starter">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
@@ -28,8 +28,8 @@ export function Validation() {
|
||||
<Label>Starter</Label>
|
||||
<Description>For side projects and small teams</Description>
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
<Radio value="pro">
|
||||
</Radio.Root>
|
||||
<Radio.Root value="pro">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
@@ -37,8 +37,8 @@ export function Validation() {
|
||||
<Label>Pro</Label>
|
||||
<Description>Advanced reporting and analytics</Description>
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
<Radio value="teams">
|
||||
</Radio.Root>
|
||||
<Radio.Root value="teams">
|
||||
<Radio.Control>
|
||||
<Radio.Indicator />
|
||||
</Radio.Control>
|
||||
@@ -46,7 +46,7 @@ export function Validation() {
|
||||
<Label>Teams</Label>
|
||||
<Description>Share access with up to 10 teammates</Description>
|
||||
</Radio.Content>
|
||||
</Radio>
|
||||
</Radio.Root>
|
||||
<FieldError>Choose a subscription before continuing.</FieldError>
|
||||
</RadioGroup>
|
||||
<Button className="mt-2 w-fit" type="submit">
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
"use client";
|
||||
|
||||
import {Label, Switch} from "@heroui/react";
|
||||
import {Label, SwitchControl, SwitchRoot, SwitchThumb} from "@heroui/react";
|
||||
|
||||
export function Basic() {
|
||||
return (
|
||||
<Switch>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<SwitchRoot>
|
||||
<SwitchControl>
|
||||
<SwitchThumb />
|
||||
</SwitchControl>
|
||||
<Label className="text-sm">Enable notifications</Label>
|
||||
</Switch>
|
||||
</SwitchRoot>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import {Label, Switch} from "@heroui/react";
|
||||
import {Label, SwitchControl, SwitchRoot, SwitchThumb} from "@heroui/react";
|
||||
import React from "react";
|
||||
|
||||
export function Controlled() {
|
||||
@@ -8,13 +8,13 @@ export function Controlled() {
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-4">
|
||||
<Switch isSelected={isSelected} onChange={setIsSelected}>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<SwitchRoot isSelected={isSelected} onChange={setIsSelected}>
|
||||
<SwitchControl>
|
||||
<SwitchThumb />
|
||||
</SwitchControl>
|
||||
<Label className="text-sm">Enable notifications</Label>
|
||||
</Switch>
|
||||
<p className="text-muted text-sm">Switch is {isSelected ? "on" : "off"}</p>
|
||||
</SwitchRoot>
|
||||
<p className="text-muted text-sm">SwitchRoot is {isSelected ? "on" : "off"}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
"use client";
|
||||
|
||||
import {Switch} from "@heroui/react";
|
||||
import {SwitchControl, SwitchIcon, SwitchRoot, SwitchThumb} from "@heroui/react";
|
||||
import {Icon} from "@iconify/react";
|
||||
|
||||
export function CustomStyles() {
|
||||
return (
|
||||
<Switch>
|
||||
<SwitchRoot>
|
||||
{({isSelected}) => (
|
||||
<>
|
||||
<Switch.Control
|
||||
<SwitchControl
|
||||
className={`h-[31px] w-[51px] bg-blue-500 ${isSelected ? "bg-cyan-500 shadow-[0_0_12px_rgba(6,182,212,0.5)]" : ""}`}
|
||||
>
|
||||
<Switch.Thumb
|
||||
<SwitchThumb
|
||||
className={`size-[27px] bg-white shadow-sm ${isSelected ? "ms-[22px] shadow-lg" : ""}`}
|
||||
>
|
||||
<Switch.Icon>
|
||||
<SwitchIcon>
|
||||
<Icon
|
||||
className={`size-4 ${isSelected ? "text-cyan-600" : "text-blue-600"}`}
|
||||
icon={isSelected ? "gravity-ui:check" : "gravity-ui:power"}
|
||||
/>
|
||||
</Switch.Icon>
|
||||
</Switch.Thumb>
|
||||
</Switch.Control>
|
||||
</SwitchIcon>
|
||||
</SwitchThumb>
|
||||
</SwitchControl>
|
||||
</>
|
||||
)}
|
||||
</Switch>
|
||||
</SwitchRoot>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
"use client";
|
||||
|
||||
import {Label, Switch} from "@heroui/react";
|
||||
import {Label, SwitchControl, SwitchRoot, SwitchThumb} from "@heroui/react";
|
||||
|
||||
export function DefaultSelected() {
|
||||
return (
|
||||
<Switch defaultSelected>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<SwitchRoot defaultSelected>
|
||||
<SwitchControl>
|
||||
<SwitchThumb />
|
||||
</SwitchControl>
|
||||
<Label className="text-sm">Enable notifications</Label>
|
||||
</Switch>
|
||||
</SwitchRoot>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
"use client";
|
||||
|
||||
import {Label, Switch} from "@heroui/react";
|
||||
import {Label, SwitchControl, SwitchRoot, SwitchThumb} from "@heroui/react";
|
||||
|
||||
export function Disabled() {
|
||||
return (
|
||||
<Switch isDisabled>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<SwitchRoot isDisabled>
|
||||
<SwitchControl>
|
||||
<SwitchThumb />
|
||||
</SwitchControl>
|
||||
<Label className="text-sm">Enable notifications</Label>
|
||||
</Switch>
|
||||
</SwitchRoot>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -18,26 +18,24 @@ export function Form() {
|
||||
return (
|
||||
<form className="flex flex-col gap-4" onSubmit={handleSubmit}>
|
||||
<SwitchGroup>
|
||||
<SwitchGroup.Items>
|
||||
<Switch name="notifications" value="on">
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Label className="text-sm">Enable notifications</Label>
|
||||
</Switch>
|
||||
<Switch defaultSelected name="newsletter" value="on">
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Label className="text-sm">Subscribe to newsletter</Label>
|
||||
</Switch>
|
||||
<Switch name="marketing" value="on">
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Label className="text-sm">Receive marketing updates</Label>
|
||||
</Switch>
|
||||
</SwitchGroup.Items>
|
||||
<Switch.Root name="notifications" value="on">
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Label className="text-sm">Enable notifications</Label>
|
||||
</Switch.Root>
|
||||
<Switch.Root defaultSelected name="newsletter" value="on">
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Label className="text-sm">Subscribe to newsletter</Label>
|
||||
</Switch.Root>
|
||||
<Switch.Root name="marketing" value="on">
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Label className="text-sm">Receive marketing updates</Label>
|
||||
</Switch.Root>
|
||||
</SwitchGroup>
|
||||
<Button className="mt-4" size="sm" type="submit" variant="primary">
|
||||
Submit
|
||||
|
||||
@@ -5,26 +5,24 @@ import {Label, Switch, SwitchGroup} from "@heroui/react";
|
||||
export function GroupHorizontal() {
|
||||
return (
|
||||
<SwitchGroup className="overflow-x-auto" orientation="horizontal">
|
||||
<SwitchGroup.Items>
|
||||
<Switch name="notifications">
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Label className="text-sm">Notifications</Label>
|
||||
</Switch>
|
||||
<Switch name="marketing">
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Label className="text-sm">Marketing</Label>
|
||||
</Switch>
|
||||
<Switch name="social">
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Label className="text-sm">Social</Label>
|
||||
</Switch>
|
||||
</SwitchGroup.Items>
|
||||
<Switch.Root name="notifications">
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Label className="text-sm">Notifications</Label>
|
||||
</Switch.Root>
|
||||
<Switch.Root name="marketing">
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Label className="text-sm">Marketing</Label>
|
||||
</Switch.Root>
|
||||
<Switch.Root name="social">
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Label className="text-sm">Social</Label>
|
||||
</Switch.Root>
|
||||
</SwitchGroup>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,26 +5,24 @@ import {Label, Switch, SwitchGroup} from "@heroui/react";
|
||||
export function Group() {
|
||||
return (
|
||||
<SwitchGroup>
|
||||
<SwitchGroup.Items>
|
||||
<Switch name="notifications">
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Label className="text-sm">Allow Notifications</Label>
|
||||
</Switch>
|
||||
<Switch name="marketing">
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Label className="text-sm">Marketing emails</Label>
|
||||
</Switch>
|
||||
<Switch name="social">
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Label className="text-sm">Social media updates</Label>
|
||||
</Switch>
|
||||
</SwitchGroup.Items>
|
||||
<Switch.Root name="notifications">
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Label className="text-sm">Allow Notifications</Label>
|
||||
</Switch.Root>
|
||||
<Switch.Root name="marketing">
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Label className="text-sm">Marketing emails</Label>
|
||||
</Switch.Root>
|
||||
<Switch.Root name="social">
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Label className="text-sm">Social media updates</Label>
|
||||
</Switch.Root>
|
||||
</SwitchGroup>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
"use client";
|
||||
|
||||
import {Label, Switch} from "@heroui/react";
|
||||
import {Label, SwitchControl, SwitchRoot, SwitchThumb} from "@heroui/react";
|
||||
|
||||
export function LabelPosition() {
|
||||
return (
|
||||
<div className="flex flex-col gap-4">
|
||||
<Switch>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<SwitchRoot>
|
||||
<SwitchControl>
|
||||
<SwitchThumb />
|
||||
</SwitchControl>
|
||||
<Label className="text-sm">Label after</Label>
|
||||
</Switch>
|
||||
<Switch>
|
||||
</SwitchRoot>
|
||||
<SwitchRoot>
|
||||
<Label className="text-sm">Label before</Label>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
</Switch>
|
||||
<SwitchControl>
|
||||
<SwitchThumb />
|
||||
</SwitchControl>
|
||||
</SwitchRoot>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
"use client";
|
||||
|
||||
import {Label, Switch} from "@heroui/react";
|
||||
import {Label, SwitchControl, SwitchRoot, SwitchThumb} from "@heroui/react";
|
||||
|
||||
export function RenderProps() {
|
||||
return (
|
||||
<Switch>
|
||||
<SwitchRoot>
|
||||
{({isSelected}) => (
|
||||
<>
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<SwitchControl>
|
||||
<SwitchThumb />
|
||||
</SwitchControl>
|
||||
<Label className="text-sm">{isSelected ? "Enabled" : "Disabled"}</Label>
|
||||
</>
|
||||
)}
|
||||
</Switch>
|
||||
</SwitchRoot>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
"use client";
|
||||
|
||||
import {Label, Switch} from "@heroui/react";
|
||||
import {Label, SwitchControl, SwitchRoot, SwitchThumb} from "@heroui/react";
|
||||
|
||||
export function Sizes() {
|
||||
return (
|
||||
<div className="flex gap-6">
|
||||
<Switch size="sm">
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<SwitchRoot size="sm">
|
||||
<SwitchControl>
|
||||
<SwitchThumb />
|
||||
</SwitchControl>
|
||||
<Label className="text-xs">Small</Label>
|
||||
</Switch>
|
||||
<Switch size="md">
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
</SwitchRoot>
|
||||
<SwitchRoot size="md">
|
||||
<SwitchControl>
|
||||
<SwitchThumb />
|
||||
</SwitchControl>
|
||||
<Label className="text-sm">Medium</Label>
|
||||
</Switch>
|
||||
<Switch size="lg">
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
</SwitchRoot>
|
||||
<SwitchRoot size="lg">
|
||||
<SwitchControl>
|
||||
<SwitchThumb />
|
||||
</SwitchControl>
|
||||
<Label className="text-base">Large</Label>
|
||||
</Switch>
|
||||
</SwitchRoot>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
"use client";
|
||||
|
||||
import {Description, Label, Switch} from "@heroui/react";
|
||||
import {Description, Label, SwitchControl, SwitchRoot, SwitchThumb} from "@heroui/react";
|
||||
|
||||
export function WithDescription() {
|
||||
return (
|
||||
<div className="max-w-sm">
|
||||
<Switch>
|
||||
<SwitchRoot>
|
||||
<div className="flex gap-3">
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<SwitchControl>
|
||||
<SwitchThumb />
|
||||
</SwitchControl>
|
||||
<div className="flex flex-col gap-1">
|
||||
<Label className="text-sm">Public profile</Label>
|
||||
<Description>Allow others to see your profile information</Description>
|
||||
</div>
|
||||
</div>
|
||||
</Switch>
|
||||
</SwitchRoot>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import {Switch} from "@heroui/react";
|
||||
import {SwitchControl, SwitchIcon, SwitchRoot, SwitchThumb} from "@heroui/react";
|
||||
import {Icon} from "@iconify/react";
|
||||
|
||||
export function WithIcons() {
|
||||
@@ -35,22 +35,22 @@ export function WithIcons() {
|
||||
return (
|
||||
<div className="flex gap-3">
|
||||
{Object.entries(icons).map(([key, value]) => (
|
||||
<Switch key={key} defaultSelected size="lg">
|
||||
<SwitchRoot key={key} defaultSelected size="lg">
|
||||
{({isSelected}) => (
|
||||
<>
|
||||
<Switch.Control className={isSelected ? value.selectedControlClass : ""}>
|
||||
<Switch.Thumb>
|
||||
<Switch.Icon>
|
||||
<SwitchControl className={isSelected ? value.selectedControlClass : ""}>
|
||||
<SwitchThumb>
|
||||
<SwitchIcon>
|
||||
<Icon
|
||||
className={`${isSelected ? "opacity-100" : "opacity-70"} size-3 text-inherit`}
|
||||
icon={isSelected ? value.on : value.off}
|
||||
/>
|
||||
</Switch.Icon>
|
||||
</Switch.Thumb>
|
||||
</Switch.Control>
|
||||
</SwitchIcon>
|
||||
</SwitchThumb>
|
||||
</SwitchControl>
|
||||
</>
|
||||
)}
|
||||
</Switch>
|
||||
</SwitchRoot>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
"use client";
|
||||
|
||||
import {Switch} from "@heroui/react";
|
||||
import {SwitchControl, SwitchRoot, SwitchThumb} from "@heroui/react";
|
||||
|
||||
export function WithoutLabel() {
|
||||
return (
|
||||
<Switch aria-label="Enable notifications">
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
</Switch>
|
||||
<SwitchRoot aria-label="Enable notifications">
|
||||
<SwitchControl>
|
||||
<SwitchThumb />
|
||||
</SwitchControl>
|
||||
</SwitchRoot>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,35 +1,35 @@
|
||||
"use client";
|
||||
|
||||
import {Tabs} from "@heroui/react";
|
||||
import {Tab, TabIndicator, TabList, TabListWrapper, TabPanel, TabsRoot} from "@heroui/react";
|
||||
|
||||
export function Basic() {
|
||||
return (
|
||||
<Tabs className="w-full max-w-md">
|
||||
<Tabs.ListWrapper>
|
||||
<Tabs.List aria-label="Options">
|
||||
<Tabs.Tab id="overview">
|
||||
<TabsRoot className="w-full max-w-md">
|
||||
<TabListWrapper>
|
||||
<TabList aria-label="Options">
|
||||
<Tab id="overview">
|
||||
Overview
|
||||
<Tabs.Indicator />
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab id="analytics">
|
||||
<TabIndicator />
|
||||
</Tab>
|
||||
<Tab id="analytics">
|
||||
Analytics
|
||||
<Tabs.Indicator />
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab id="reports">
|
||||
<TabIndicator />
|
||||
</Tab>
|
||||
<Tab id="reports">
|
||||
Reports
|
||||
<Tabs.Indicator />
|
||||
</Tabs.Tab>
|
||||
</Tabs.List>
|
||||
</Tabs.ListWrapper>
|
||||
<Tabs.Panel className="pt-4" id="overview">
|
||||
<TabIndicator />
|
||||
</Tab>
|
||||
</TabList>
|
||||
</TabListWrapper>
|
||||
<TabPanel className="pt-4" id="overview">
|
||||
<p>View your project overview and recent activity.</p>
|
||||
</Tabs.Panel>
|
||||
<Tabs.Panel className="pt-4" id="analytics">
|
||||
</TabPanel>
|
||||
<TabPanel className="pt-4" id="analytics">
|
||||
<p>Track your metrics and analyze performance data.</p>
|
||||
</Tabs.Panel>
|
||||
<Tabs.Panel className="pt-4" id="reports">
|
||||
</TabPanel>
|
||||
<TabPanel className="pt-4" id="reports">
|
||||
<p>Generate and download detailed reports.</p>
|
||||
</Tabs.Panel>
|
||||
</Tabs>
|
||||
</TabPanel>
|
||||
</TabsRoot>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,33 +1,33 @@
|
||||
"use client";
|
||||
|
||||
import {Tabs} from "@heroui/react";
|
||||
import {Tab, TabIndicator, TabList, TabListWrapper, TabsRoot} from "@heroui/react";
|
||||
|
||||
export function CustomStyles() {
|
||||
return (
|
||||
<Tabs className="w-full max-w-lg text-center">
|
||||
<Tabs.ListWrapper>
|
||||
<Tabs.List
|
||||
<TabsRoot className="w-full max-w-lg text-center">
|
||||
<TabListWrapper>
|
||||
<TabList
|
||||
aria-label="Options"
|
||||
className="*:data-[selected=true]:text-accent-foreground w-fit *:h-6 *:w-fit *:px-3 *:text-sm *:font-normal"
|
||||
>
|
||||
<Tabs.Tab id="daily">
|
||||
<Tab id="daily">
|
||||
Daily
|
||||
<Tabs.Indicator className="bg-accent" />
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab id="weekly">
|
||||
<TabIndicator className="bg-accent" />
|
||||
</Tab>
|
||||
<Tab id="weekly">
|
||||
Weekly
|
||||
<Tabs.Indicator className="bg-accent" />
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab id="bi-weekly">
|
||||
<TabIndicator className="bg-accent" />
|
||||
</Tab>
|
||||
<Tab id="bi-weekly">
|
||||
Bi-Weekly
|
||||
<Tabs.Indicator className="bg-accent" />
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab id="monthly">
|
||||
<TabIndicator className="bg-accent" />
|
||||
</Tab>
|
||||
<Tab id="monthly">
|
||||
Monthly
|
||||
<Tabs.Indicator className="bg-accent" />
|
||||
</Tabs.Tab>
|
||||
</Tabs.List>
|
||||
</Tabs.ListWrapper>
|
||||
</Tabs>
|
||||
<TabIndicator className="bg-accent" />
|
||||
</Tab>
|
||||
</TabList>
|
||||
</TabListWrapper>
|
||||
</TabsRoot>
|
||||
);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user