@particle-academy/react-fancy 1.7.0 → 1.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/README.md +76 -82
  2. package/docs/Accordion.md +78 -0
  3. package/docs/Action.md +76 -0
  4. package/docs/Autocomplete.md +74 -0
  5. package/docs/Avatar.md +40 -0
  6. package/docs/Badge.md +42 -0
  7. package/docs/Brand.md +44 -0
  8. package/docs/Breadcrumbs.md +51 -0
  9. package/docs/Calendar.md +72 -0
  10. package/docs/Callout.md +46 -0
  11. package/docs/Canvas.md +102 -0
  12. package/docs/Card.md +68 -0
  13. package/docs/Carousel.md +97 -0
  14. package/docs/Chart.md +126 -0
  15. package/docs/Checkbox.md +86 -0
  16. package/docs/ColorPicker.md +49 -0
  17. package/docs/Command.md +88 -0
  18. package/docs/Composer.md +60 -0
  19. package/docs/ContentRenderer.md +68 -0
  20. package/docs/ContextMenu.md +82 -0
  21. package/docs/DatePicker.md +64 -0
  22. package/docs/Diagram.md +119 -0
  23. package/docs/Dropdown.md +79 -0
  24. package/docs/Editor.md +84 -0
  25. package/docs/Emoji.md +40 -0
  26. package/docs/EmojiSelect.md +47 -0
  27. package/docs/Field.md +48 -0
  28. package/docs/FileUpload.md +81 -0
  29. package/docs/Heading.md +43 -0
  30. package/docs/Icon.md +75 -0
  31. package/docs/Input.md +73 -0
  32. package/docs/Kanban.md +79 -0
  33. package/docs/Menu.md +71 -0
  34. package/docs/MobileMenu.md +69 -0
  35. package/docs/Modal.md +74 -0
  36. package/docs/MultiSwitch.md +64 -0
  37. package/docs/Navbar.md +65 -0
  38. package/docs/OtpInput.md +48 -0
  39. package/docs/Pagination.md +48 -0
  40. package/docs/Pillbox.md +53 -0
  41. package/docs/Popover.md +82 -0
  42. package/docs/Portal.md +40 -0
  43. package/docs/Profile.md +52 -0
  44. package/docs/Progress.md +42 -0
  45. package/docs/RadioGroup.md +69 -0
  46. package/docs/Select.md +122 -0
  47. package/docs/Separator.md +41 -0
  48. package/docs/Sidebar.md +88 -0
  49. package/docs/Skeleton.md +44 -0
  50. package/docs/Slider.md +75 -0
  51. package/docs/Switch.md +55 -0
  52. package/docs/Table.md +133 -0
  53. package/docs/Tabs.md +85 -0
  54. package/docs/Text.md +44 -0
  55. package/docs/Textarea.md +62 -0
  56. package/docs/TimePicker.md +45 -0
  57. package/docs/Timeline.md +118 -0
  58. package/docs/Toast.md +79 -0
  59. package/docs/Tooltip.md +46 -0
  60. package/docs/hooks.md +180 -0
  61. package/docs/utilities.md +74 -0
  62. package/package.json +2 -1
@@ -0,0 +1,48 @@
1
+ # OtpInput
2
+
3
+ One-time password input with individual digit cells, auto-advance, and paste support.
4
+
5
+ ## Import
6
+
7
+ ```tsx
8
+ import { OtpInput } from "@particle-academy/react-fancy";
9
+ ```
10
+
11
+ ## Basic Usage
12
+
13
+ ```tsx
14
+ <OtpInput length={6} onChange={(code) => console.log(code)} />
15
+ ```
16
+
17
+ ## Props
18
+
19
+ | Prop | Type | Default | Description |
20
+ |------|------|---------|-------------|
21
+ | `length` | `number` | `6` | Number of digit cells |
22
+ | `value` | `string` | - | Controlled value |
23
+ | `onChange` | `(value: string) => void` | - | Callback with the full OTP string |
24
+ | `disabled` | `boolean` | `false` | Disables all inputs |
25
+ | `autoFocus` | `boolean` | `false` | Auto-focus the first cell on mount |
26
+ | `className` | `string` | - | Additional CSS classes on the container |
27
+
28
+ **Behavior:**
29
+ - Only numeric digits are accepted.
30
+ - Focus advances to the next cell after input.
31
+ - **Backspace** clears the current cell, or moves to the previous cell if already empty.
32
+ - **Arrow keys** move focus between cells.
33
+ - **Paste** fills cells from the clipboard (non-numeric characters are stripped).
34
+
35
+ ## Examples
36
+
37
+ ### 4-digit code with auto-focus
38
+
39
+ ```tsx
40
+ const [code, setCode] = useState("");
41
+
42
+ <OtpInput
43
+ length={4}
44
+ autoFocus
45
+ value={code}
46
+ onChange={setCode}
47
+ />
48
+ ```
@@ -0,0 +1,48 @@
1
+ # Pagination
2
+
3
+ A page navigation component with previous/next buttons, page numbers, and ellipsis for large ranges.
4
+
5
+ ## Import
6
+
7
+ ```tsx
8
+ import { Pagination } from "@particle-academy/react-fancy";
9
+ ```
10
+
11
+ ## Basic Usage
12
+
13
+ ```tsx
14
+ <Pagination page={1} totalPages={10} onPageChange={setPage} />
15
+ ```
16
+
17
+ ## Props
18
+
19
+ | Prop | Type | Default | Description |
20
+ |------|------|---------|-------------|
21
+ | page | `number` | **required** | Current active page (1-based) |
22
+ | onPageChange | `(page: number) => void` | **required** | Callback when a page is selected |
23
+ | totalPages | `number` | **required** | Total number of pages |
24
+ | siblingCount | `number` | `1` | Number of sibling pages shown around the current page |
25
+ | className | `string` | - | Additional CSS classes |
26
+
27
+ Renders `null` when `totalPages <= 1`. Automatically inserts ellipsis when the page count exceeds the visible slot count.
28
+
29
+ ## Examples
30
+
31
+ ### Basic pagination
32
+
33
+ ```tsx
34
+ const [page, setPage] = useState(1);
35
+
36
+ <Pagination page={page} totalPages={20} onPageChange={setPage} />
37
+ ```
38
+
39
+ ### More visible siblings
40
+
41
+ ```tsx
42
+ <Pagination
43
+ page={page}
44
+ totalPages={50}
45
+ onPageChange={setPage}
46
+ siblingCount={2}
47
+ />
48
+ ```
@@ -0,0 +1,53 @@
1
+ # Pillbox
2
+
3
+ Tag/pill input that lets users type free-text values and manage them as removable pills.
4
+
5
+ ## Import
6
+
7
+ ```tsx
8
+ import { Pillbox } from "@particle-academy/react-fancy";
9
+ ```
10
+
11
+ ## Basic Usage
12
+
13
+ ```tsx
14
+ <Pillbox placeholder="Add tags..." onChange={(tags) => console.log(tags)} />
15
+ ```
16
+
17
+ ## Props
18
+
19
+ | Prop | Type | Default | Description |
20
+ |------|------|---------|-------------|
21
+ | `value` | `string[]` | - | Controlled list of items |
22
+ | `defaultValue` | `string[]` | `[]` | Default items (uncontrolled) |
23
+ | `onChange` | `(values: string[]) => void` | - | Callback when items change |
24
+ | `placeholder` | `string` | `"Type and press Enter..."` | Placeholder (shown only when no items exist) |
25
+ | `maxItems` | `number` | - | Maximum number of items allowed |
26
+ | `disabled` | `boolean` | `false` | Disables input and removal |
27
+ | `className` | `string` | - | Additional CSS classes |
28
+
29
+ **Behavior:**
30
+ - Press **Enter** to add the current text as a pill. Duplicates and empty strings are ignored.
31
+ - Press **Backspace** on an empty input to remove the last pill.
32
+ - Click the **X** on any pill to remove it.
33
+
34
+ ## Examples
35
+
36
+ ### With max items
37
+
38
+ ```tsx
39
+ <Pillbox
40
+ placeholder="Add up to 5 skills..."
41
+ maxItems={5}
42
+ defaultValue={["React", "TypeScript"]}
43
+ onChange={setSkills}
44
+ />
45
+ ```
46
+
47
+ ### Controlled
48
+
49
+ ```tsx
50
+ const [emails, setEmails] = useState<string[]>([]);
51
+
52
+ <Pillbox value={emails} onChange={setEmails} placeholder="Add email addresses..." />
53
+ ```
@@ -0,0 +1,82 @@
1
+ # Popover
2
+
3
+ A floating content panel anchored to a trigger element. Supports click and hover activation with configurable placement.
4
+
5
+ ## Import
6
+
7
+ ```tsx
8
+ import { Popover } from "@particle-academy/react-fancy";
9
+ ```
10
+
11
+ ## Basic Usage
12
+
13
+ ```tsx
14
+ <Popover>
15
+ <Popover.Trigger>
16
+ <button>Open popover</button>
17
+ </Popover.Trigger>
18
+ <Popover.Content>
19
+ <p>Popover content here</p>
20
+ </Popover.Content>
21
+ </Popover>
22
+ ```
23
+
24
+ ## Props
25
+
26
+ ### Popover (root)
27
+
28
+ | Prop | Type | Default | Description |
29
+ |------|------|---------|-------------|
30
+ | open | `boolean` | - | Controlled open state |
31
+ | defaultOpen | `boolean` | `false` | Default open state (uncontrolled) |
32
+ | onOpenChange | `(open: boolean) => void` | - | Callback when open state changes |
33
+ | placement | `Placement` | `"bottom"` | Position relative to trigger. One of: `"top"`, `"bottom"`, `"left"`, `"right"`, `"top-start"`, `"top-end"`, `"bottom-start"`, `"bottom-end"` |
34
+ | offset | `number` | `8` | Pixel offset from the trigger |
35
+ | hover | `boolean` | `false` | Open on hover instead of click |
36
+ | hoverDelay | `number` | `200` | Delay in ms before opening on hover |
37
+ | hoverCloseDelay | `number` | `300` | Delay in ms before closing after hover leaves |
38
+
39
+ ### Popover.Trigger
40
+
41
+ | Prop | Type | Default | Description |
42
+ |------|------|---------|-------------|
43
+ | children | `ReactNode` | - | Trigger element |
44
+ | className | `string` | - | Additional CSS classes |
45
+
46
+ ### Popover.Content
47
+
48
+ | Prop | Type | Default | Description |
49
+ |------|------|---------|-------------|
50
+ | children | `ReactNode` | - | Content to display |
51
+ | className | `string` | - | Additional CSS classes |
52
+
53
+ ## Hover Mode
54
+
55
+ The `hover` prop switches from click-to-toggle to hover-to-open behavior. When enabled, the popover opens after `hoverDelay` ms and closes after `hoverCloseDelay` ms once the cursor leaves both the trigger and content. Moving from the trigger into the content keeps the popover open.
56
+
57
+ ```tsx
58
+ <Popover hover hoverDelay={100} hoverCloseDelay={400}>
59
+ <Popover.Trigger>
60
+ <button>Hover me</button>
61
+ </Popover.Trigger>
62
+ <Popover.Content>
63
+ <p>Tooltip-like popover</p>
64
+ </Popover.Content>
65
+ </Popover>
66
+ ```
67
+
68
+ ## Controlled Example
69
+
70
+ ```tsx
71
+ const [open, setOpen] = useState(false);
72
+
73
+ <Popover open={open} onOpenChange={setOpen} placement="right">
74
+ <Popover.Trigger>
75
+ <button>Info</button>
76
+ </Popover.Trigger>
77
+ <Popover.Content className="p-4 w-64">
78
+ <h3>Details</h3>
79
+ <p>Some additional information.</p>
80
+ </Popover.Content>
81
+ </Popover>
82
+ ```
package/docs/Portal.md ADDED
@@ -0,0 +1,40 @@
1
+ # Portal
2
+
3
+ Renders children into a DOM node outside the React component tree using `createPortal`, with automatic dark mode propagation.
4
+
5
+ ## Import
6
+
7
+ ```tsx
8
+ import { Portal } from "@particle-academy/react-fancy";
9
+ ```
10
+
11
+ ## Basic Usage
12
+
13
+ ```tsx
14
+ <Portal>
15
+ <div className="fixed inset-0 z-50 bg-black/50">Modal overlay</div>
16
+ </Portal>
17
+ ```
18
+
19
+ ## Props
20
+
21
+ | Prop | Type | Default | Description |
22
+ |------|------|---------|-------------|
23
+ | children | `ReactNode` | **required** | Content to render in the portal |
24
+ | container | `HTMLElement` | `document.body` | Target DOM element to portal into |
25
+
26
+ Portal wraps children in a `<div style="display: contents">` that automatically syncs the `dark` class from `<html>`, ensuring Tailwind `dark:` utilities work correctly inside portals.
27
+
28
+ Returns `null` during SSR (when `document` is undefined).
29
+
30
+ ## Examples
31
+
32
+ ### Custom container
33
+
34
+ ```tsx
35
+ const container = document.getElementById("modal-root")!;
36
+
37
+ <Portal container={container}>
38
+ <div>Rendered inside #modal-root</div>
39
+ </Portal>
40
+ ```
@@ -0,0 +1,52 @@
1
+ # Profile
2
+
3
+ A profile display component that combines an Avatar with a name and optional subtitle.
4
+
5
+ ## Import
6
+
7
+ ```tsx
8
+ import { Profile } from "@particle-academy/react-fancy";
9
+ ```
10
+
11
+ ## Basic Usage
12
+
13
+ ```tsx
14
+ <Profile name="Jane Doe" />
15
+ ```
16
+
17
+ ## Props
18
+
19
+ | Prop | Type | Default | Description |
20
+ |------|------|---------|-------------|
21
+ | src | `string` | - | Avatar image URL |
22
+ | alt | `string` | - | Avatar alt text (falls back to `name`) |
23
+ | fallback | `string` | - | Fallback initials for the avatar |
24
+ | name | `string` | **required** | Display name |
25
+ | subtitle | `string` | - | Secondary text (role, email, etc.) |
26
+ | size | `"sm" \| "md" \| "lg"` | `"md"` | Overall size |
27
+ | status | `"online" \| "offline" \| "busy" \| "away"` | - | Status indicator on the avatar |
28
+ | className | `string` | - | Additional CSS classes |
29
+
30
+ ## Examples
31
+
32
+ ### With avatar and status
33
+
34
+ ```tsx
35
+ <Profile
36
+ src="/photo.jpg"
37
+ name="Jane Doe"
38
+ subtitle="Product Designer"
39
+ status="online"
40
+ />
41
+ ```
42
+
43
+ ### Fallback initials
44
+
45
+ ```tsx
46
+ <Profile
47
+ fallback="AB"
48
+ name="Alice Brown"
49
+ subtitle="alice@example.com"
50
+ size="lg"
51
+ />
52
+ ```
@@ -0,0 +1,42 @@
1
+ # Progress
2
+
3
+ A progress indicator available as a horizontal bar or circular ring, with optional percentage display.
4
+
5
+ ## Import
6
+
7
+ ```tsx
8
+ import { Progress } from "@particle-academy/react-fancy";
9
+ ```
10
+
11
+ ## Basic Usage
12
+
13
+ ```tsx
14
+ <Progress value={60} />
15
+ ```
16
+
17
+ ## Props
18
+
19
+ | Prop | Type | Default | Description |
20
+ |------|------|---------|-------------|
21
+ | value | `number` | `0` | Current progress value |
22
+ | max | `number` | `100` | Maximum value |
23
+ | variant | `"bar" \| "circular"` | `"bar"` | Visual variant |
24
+ | size | `"sm" \| "md" \| "lg"` | `"md"` | Component size |
25
+ | color | `"blue" \| "green" \| "amber" \| "red" \| "violet" \| "zinc"` | `"blue"` | Progress color |
26
+ | indeterminate | `boolean` | `false` | Show indeterminate/loading animation |
27
+ | showValue | `boolean` | `false` | Display percentage text |
28
+ | className | `string` | - | Additional CSS classes |
29
+
30
+ ## Examples
31
+
32
+ ### Bar with percentage
33
+
34
+ ```tsx
35
+ <Progress value={75} showValue color="green" />
36
+ ```
37
+
38
+ ### Circular indeterminate
39
+
40
+ ```tsx
41
+ <Progress variant="circular" indeterminate size="lg" color="violet" />
42
+ ```
@@ -0,0 +1,69 @@
1
+ # RadioGroup
2
+
3
+ Radio button group for single-value selection from a list of options.
4
+
5
+ ## Import
6
+
7
+ ```tsx
8
+ import { RadioGroup } from "@particle-academy/react-fancy";
9
+ ```
10
+
11
+ ## Basic Usage
12
+
13
+ ```tsx
14
+ <RadioGroup
15
+ label="Plan"
16
+ list={["Free", "Pro", "Enterprise"]}
17
+ onValueChange={(plan) => console.log(plan)}
18
+ />
19
+ ```
20
+
21
+ ## Props
22
+
23
+ | Prop | Type | Default | Description |
24
+ |------|------|---------|-------------|
25
+ | `list` | `InputOption[]` | **required** | Options as strings or `{ value, label, disabled?, description? }` |
26
+ | `value` | `V` | - | Controlled selected value |
27
+ | `defaultValue` | `V` | - | Default selected value (uncontrolled) |
28
+ | `onValueChange` | `(value: V) => void` | - | Callback when selection changes |
29
+ | `orientation` | `"horizontal" \| "vertical"` | `"vertical"` | Layout direction |
30
+ | `label` | `string` | - | Group label (wraps in `Field`) |
31
+ | `description` | `string` | - | Helper text |
32
+ | `error` | `string` | - | Error message |
33
+ | `size` | `"xs" \| "sm" \| "md" \| "lg" \| "xl"` | `"md"` | Radio button size |
34
+ | `dirty` | `boolean` | `false` | Amber ring on all radios |
35
+ | `required` | `boolean` | `false` | Red asterisk on label |
36
+ | `disabled` | `boolean` | `false` | Disables all radios |
37
+ | `name` | `string` | auto-generated | HTML `name` attribute for the radio group |
38
+ | `className` | `string` | - | Additional CSS classes |
39
+
40
+ ## Examples
41
+
42
+ ### Horizontal layout with descriptions
43
+
44
+ ```tsx
45
+ <RadioGroup
46
+ label="Priority"
47
+ orientation="horizontal"
48
+ list={[
49
+ { value: "low", label: "Low", description: "No rush" },
50
+ { value: "medium", label: "Medium" },
51
+ { value: "high", label: "High", description: "Urgent" },
52
+ ]}
53
+ defaultValue="medium"
54
+ onValueChange={setPriority}
55
+ />
56
+ ```
57
+
58
+ ### Controlled
59
+
60
+ ```tsx
61
+ const [color, setColor] = useState("blue");
62
+
63
+ <RadioGroup
64
+ label="Theme color"
65
+ list={["red", "blue", "green"]}
66
+ value={color}
67
+ onValueChange={setColor}
68
+ />
69
+ ```
package/docs/Select.md ADDED
@@ -0,0 +1,122 @@
1
+ # Select
2
+
3
+ Dropdown select with two variants: a native `<select>` element and a custom listbox with search, multi-select, and indicator support.
4
+
5
+ ## Import
6
+
7
+ ```tsx
8
+ import { Select } from "@particle-academy/react-fancy";
9
+ ```
10
+
11
+ ## Basic Usage
12
+
13
+ ```tsx
14
+ <Select
15
+ label="Country"
16
+ list={["USA", "Canada", "Mexico"]}
17
+ placeholder="Choose a country"
18
+ />
19
+ ```
20
+
21
+ ## Variants
22
+
23
+ - **`"native"`** (default for single-select) -- Renders a standard `<select>` element. Best for simple use cases and mobile.
24
+ - **`"listbox"`** (default when `multiple` is set) -- Renders a custom dropdown with keyboard navigation, optional search, and selection indicators.
25
+
26
+ The variant is auto-selected based on the `multiple` prop, or set it explicitly with `variant`.
27
+
28
+ ## Props
29
+
30
+ Extends native `<select>` attributes (except `size`, `prefix`, `multiple`).
31
+
32
+ | Prop | Type | Default | Description |
33
+ |------|------|---------|-------------|
34
+ | `list` | `InputOption[] \| InputOptionGroup[]` | **required** | Options as strings or `{ value, label, disabled?, description? }`. Groups via `{ label, options }`. |
35
+ | `variant` | `"native" \| "listbox"` | `"native"` (auto `"listbox"` if `multiple`) | Rendering variant |
36
+ | `placeholder` | `string` | `"Select..."` (listbox) | Placeholder text |
37
+ | `size` | `"xs" \| "sm" \| "md" \| "lg" \| "xl"` | `"md"` | Controls sizing |
38
+ | `label` | `string` | - | Wraps in a `Field` with this label |
39
+ | `description` | `string` | - | Helper text below the select |
40
+ | `error` | `string` | - | Error message |
41
+ | `required` | `boolean` | `false` | Red asterisk on label |
42
+ | `dirty` | `boolean` | `false` | Amber ring |
43
+ | `disabled` | `boolean` | `false` | Disables the select |
44
+ | `onValueChange` | `(value: string) => void` | - | Callback for single-select value changes |
45
+ | **Listbox-only props** | | | |
46
+ | `multiple` | `boolean` | `false` | Enable multi-select (forces listbox variant) |
47
+ | `values` | `string[]` | - | Controlled multi-select values |
48
+ | `defaultValues` | `string[]` | - | Default multi-select values (uncontrolled) |
49
+ | `onValuesChange` | `(values: string[]) => void` | - | Callback for multi-select changes |
50
+ | `searchable` | `boolean` | `false` | Show search/filter input in the dropdown |
51
+ | `selectedSuffix` | `string` | `"selected"` | Suffix for the count display (e.g. "3 selected") |
52
+ | `indicator` | `"check" \| "checkbox"` | `"check"` | Selection indicator style |
53
+ | `prefix` | `ReactNode` | - | Affix before the select |
54
+ | `suffix` | `ReactNode` | - | Affix after the select |
55
+
56
+ ### InputOption type
57
+
58
+ ```ts
59
+ type InputOption = string | { value: string; label: string; disabled?: boolean; description?: string };
60
+ ```
61
+
62
+ ### InputOptionGroup type
63
+
64
+ ```ts
65
+ type InputOptionGroup = { label: string; options: InputOption[] };
66
+ ```
67
+
68
+ ## Examples
69
+
70
+ ### Native with option objects
71
+
72
+ ```tsx
73
+ <Select
74
+ label="Role"
75
+ list={[
76
+ { value: "admin", label: "Administrator" },
77
+ { value: "editor", label: "Editor" },
78
+ { value: "viewer", label: "Viewer", disabled: true },
79
+ ]}
80
+ onValueChange={(role) => console.log(role)}
81
+ />
82
+ ```
83
+
84
+ ### Listbox with search
85
+
86
+ ```tsx
87
+ <Select
88
+ variant="listbox"
89
+ label="Framework"
90
+ searchable
91
+ list={["React", "Vue", "Angular", "Svelte", "Solid"]}
92
+ onValueChange={setFramework}
93
+ />
94
+ ```
95
+
96
+ ### Multi-select with checkbox indicator
97
+
98
+ ```tsx
99
+ const [selected, setSelected] = useState<string[]>([]);
100
+
101
+ <Select
102
+ label="Toppings"
103
+ multiple
104
+ searchable
105
+ indicator="checkbox"
106
+ list={["Pepperoni", "Mushrooms", "Onions", "Olives", "Peppers"]}
107
+ values={selected}
108
+ onValuesChange={setSelected}
109
+ />
110
+ ```
111
+
112
+ ### Option groups (native)
113
+
114
+ ```tsx
115
+ <Select
116
+ label="Vehicle"
117
+ list={[
118
+ { label: "Cars", options: ["Sedan", "SUV", "Truck"] },
119
+ { label: "Bikes", options: ["Sport", "Cruiser"] },
120
+ ]}
121
+ />
122
+ ```
@@ -0,0 +1,41 @@
1
+ # Separator
2
+
3
+ A horizontal or vertical divider line with optional centered label text.
4
+
5
+ ## Import
6
+
7
+ ```tsx
8
+ import { Separator } from "@particle-academy/react-fancy";
9
+ ```
10
+
11
+ ## Basic Usage
12
+
13
+ ```tsx
14
+ <Separator />
15
+ ```
16
+
17
+ ## Props
18
+
19
+ | Prop | Type | Default | Description |
20
+ |------|------|---------|-------------|
21
+ | orientation | `"horizontal" \| "vertical"` | `"horizontal"` | Separator direction |
22
+ | label | `string` | - | Optional centered label text (horizontal only) |
23
+ | className | `string` | - | Additional CSS classes |
24
+
25
+ ## Examples
26
+
27
+ ### Horizontal with label
28
+
29
+ ```tsx
30
+ <Separator label="or" />
31
+ ```
32
+
33
+ ### Vertical separator
34
+
35
+ ```tsx
36
+ <div className="flex h-8 items-center gap-4">
37
+ <span>Left</span>
38
+ <Separator orientation="vertical" />
39
+ <span>Right</span>
40
+ </div>
41
+ ```
@@ -0,0 +1,88 @@
1
+ # Sidebar
2
+
3
+ A collapsible sidebar navigation with icon-only or letter-abbreviated collapsed mode, submenus, groups, and a toggle button.
4
+
5
+ ## Import
6
+
7
+ ```tsx
8
+ import { Sidebar } from "@particle-academy/react-fancy";
9
+ ```
10
+
11
+ ## Basic Usage
12
+
13
+ ```tsx
14
+ <Sidebar>
15
+ <Sidebar.Item href="/" icon={<HomeIcon />} active>Home</Sidebar.Item>
16
+ <Sidebar.Item href="/settings" icon={<GearIcon />}>Settings</Sidebar.Item>
17
+ <Sidebar.Group label="Projects">
18
+ <Sidebar.Item href="/project-a">Project A</Sidebar.Item>
19
+ <Sidebar.Item href="/project-b">Project B</Sidebar.Item>
20
+ </Sidebar.Group>
21
+ <Sidebar.Toggle />
22
+ </Sidebar>
23
+ ```
24
+
25
+ ## Props
26
+
27
+ ### Sidebar (root)
28
+
29
+ | Prop | Type | Default | Description |
30
+ |------|------|---------|-------------|
31
+ | collapsed | `boolean` | - | Controlled collapsed state |
32
+ | defaultCollapsed | `boolean` | `false` | Default collapsed state (uncontrolled) |
33
+ | onCollapsedChange | `(collapsed: boolean) => void` | - | Callback when collapsed state changes |
34
+ | collapseMode | `"icons" \| "letters"` | `"icons"` | How items display when collapsed: icons only, or first 3 letters |
35
+ | className | `string` | - | Additional CSS classes |
36
+
37
+ ### Sidebar.Item
38
+
39
+ | Prop | Type | Default | Description |
40
+ |------|------|---------|-------------|
41
+ | children | `ReactNode` | - | Item label |
42
+ | href | `string` | - | Link URL |
43
+ | icon | `ReactNode` | - | Leading icon |
44
+ | active | `boolean` | - | Active state highlight |
45
+ | disabled | `boolean` | - | Disable the item |
46
+ | badge | `ReactNode` | - | Trailing badge element |
47
+ | onClick | `() => void` | - | Click handler |
48
+ | className | `string` | - | Additional CSS classes |
49
+
50
+ ### Sidebar.Group
51
+
52
+ | Prop | Type | Default | Description |
53
+ |------|------|---------|-------------|
54
+ | children | `ReactNode` | - | Grouped items |
55
+ | label | `string` | - | Group heading |
56
+ | className | `string` | - | Additional CSS classes |
57
+
58
+ ### Sidebar.Submenu
59
+
60
+ | Prop | Type | Default | Description |
61
+ |------|------|---------|-------------|
62
+ | children | `ReactNode` | - | Submenu items |
63
+ | label | `string` | - | Submenu trigger label (required) |
64
+ | icon | `ReactNode` | - | Leading icon |
65
+ | defaultOpen | `boolean` | - | Whether the submenu starts open |
66
+ | className | `string` | - | Additional CSS classes |
67
+
68
+ ### Sidebar.Toggle
69
+
70
+ | Prop | Type | Default | Description |
71
+ |------|------|---------|-------------|
72
+ | className | `string` | - | Additional CSS classes |
73
+
74
+ ## Collapsible Sidebar
75
+
76
+ ```tsx
77
+ const [collapsed, setCollapsed] = useState(false);
78
+
79
+ <Sidebar collapsed={collapsed} onCollapsedChange={setCollapsed} collapseMode="icons">
80
+ <Sidebar.Item icon={<HomeIcon />}>Dashboard</Sidebar.Item>
81
+ <Sidebar.Item icon={<UsersIcon />}>Users</Sidebar.Item>
82
+ <Sidebar.Submenu label="Reports" icon={<ChartIcon />} defaultOpen>
83
+ <Sidebar.Item>Monthly</Sidebar.Item>
84
+ <Sidebar.Item>Yearly</Sidebar.Item>
85
+ </Sidebar.Submenu>
86
+ <Sidebar.Toggle />
87
+ </Sidebar>
88
+ ```