laif-ds 0.2.44 → 0.2.45

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 (98) hide show
  1. package/dist/_virtual/index4.js +5 -5
  2. package/dist/_virtual/index5.js +5 -5
  3. package/dist/_virtual/index6.js +2 -2
  4. package/dist/_virtual/index7.js +2 -2
  5. package/dist/agent-docs/components/Accordion.md +157 -0
  6. package/dist/agent-docs/components/Alert.md +95 -0
  7. package/dist/agent-docs/components/AlertDialog.md +126 -0
  8. package/dist/agent-docs/components/AppEditor.md +90 -0
  9. package/dist/agent-docs/components/AppForm.md +242 -0
  10. package/dist/agent-docs/components/AppMultipleSelectDropdown.md +38 -0
  11. package/dist/agent-docs/components/AppRadioGroup.md +223 -0
  12. package/dist/agent-docs/components/AppSelect.md +427 -0
  13. package/dist/agent-docs/components/AppSidebar.md +122 -0
  14. package/dist/agent-docs/components/AppStepper.md +77 -0
  15. package/dist/agent-docs/components/AspectRatio.md +87 -0
  16. package/dist/agent-docs/components/AsyncSelect.md +127 -0
  17. package/dist/agent-docs/components/AudioVisualizer.md +41 -0
  18. package/dist/agent-docs/components/Avatar.md +113 -0
  19. package/dist/agent-docs/components/Badge.md +118 -0
  20. package/dist/agent-docs/components/Breadcrumb.md +78 -0
  21. package/dist/agent-docs/components/Button.md +129 -0
  22. package/dist/agent-docs/components/Calendar.md +222 -0
  23. package/dist/agent-docs/components/Card.md +147 -0
  24. package/dist/agent-docs/components/Carousel.md +129 -0
  25. package/dist/agent-docs/components/Chart.md +75 -0
  26. package/dist/agent-docs/components/Chat.md +109 -0
  27. package/dist/agent-docs/components/ChatMessage.md +61 -0
  28. package/dist/agent-docs/components/Checkbox.md +135 -0
  29. package/dist/agent-docs/components/CircularProgress.md +49 -0
  30. package/dist/agent-docs/components/CodeHighlighter.md +31 -0
  31. package/dist/agent-docs/components/Collapsible.md +95 -0
  32. package/dist/agent-docs/components/Command.md +142 -0
  33. package/dist/agent-docs/components/Confirmer.md +175 -0
  34. package/dist/agent-docs/components/ContextMenu.md +191 -0
  35. package/dist/agent-docs/components/CopyButton.md +26 -0
  36. package/dist/agent-docs/components/DataCrossTable.md +94 -0
  37. package/dist/agent-docs/components/DataTable.md +254 -0
  38. package/dist/agent-docs/components/DatePicker.md +109 -0
  39. package/dist/agent-docs/components/Dialog.md +125 -0
  40. package/dist/agent-docs/components/Drawer.md +127 -0
  41. package/dist/agent-docs/components/DropdownMenu.md +57 -0
  42. package/dist/agent-docs/components/FilePreview.md +99 -0
  43. package/dist/agent-docs/components/FilePreviewer.md +139 -0
  44. package/dist/agent-docs/components/FileUploader.md +129 -0
  45. package/dist/agent-docs/components/Form.md +62 -0
  46. package/dist/agent-docs/components/FormComposer.md +137 -0
  47. package/dist/agent-docs/components/GanttChart.md +122 -0
  48. package/dist/agent-docs/components/HoverCard.md +37 -0
  49. package/dist/agent-docs/components/Icon.md +99 -0
  50. package/dist/agent-docs/components/Input.md +138 -0
  51. package/dist/agent-docs/components/InputOtp.md +40 -0
  52. package/dist/agent-docs/components/InputSelector.md +97 -0
  53. package/dist/agent-docs/components/InterruptPrompt.md +32 -0
  54. package/dist/agent-docs/components/Label.md +28 -0
  55. package/dist/agent-docs/components/MarkdownRenderer.md +36 -0
  56. package/dist/agent-docs/components/Menubar.md +164 -0
  57. package/dist/agent-docs/components/MessageInput.md +131 -0
  58. package/dist/agent-docs/components/MessageList.md +96 -0
  59. package/dist/agent-docs/components/MultipleSelector.md +146 -0
  60. package/dist/agent-docs/components/NavigationMenu.md +51 -0
  61. package/dist/agent-docs/components/Pagination.md +55 -0
  62. package/dist/agent-docs/components/Popover.md +103 -0
  63. package/dist/agent-docs/components/Progress.md +30 -0
  64. package/dist/agent-docs/components/PromptSuggestions.md +33 -0
  65. package/dist/agent-docs/components/RadioGroup.md +90 -0
  66. package/dist/agent-docs/components/Resizable.md +35 -0
  67. package/dist/agent-docs/components/ResizePrompt.md +13 -0
  68. package/dist/agent-docs/components/ScrollArea.md +49 -0
  69. package/dist/agent-docs/components/SecurePdfViewer.md +38 -0
  70. package/dist/agent-docs/components/Select.md +132 -0
  71. package/dist/agent-docs/components/Separator.md +32 -0
  72. package/dist/agent-docs/components/Sheet.md +40 -0
  73. package/dist/agent-docs/components/ShikiHighlighter.md +31 -0
  74. package/dist/agent-docs/components/Sidebar.md +85 -0
  75. package/dist/agent-docs/components/Skeleton.md +29 -0
  76. package/dist/agent-docs/components/Slider.md +58 -0
  77. package/dist/agent-docs/components/Sonner.md +21 -0
  78. package/dist/agent-docs/components/Spinner.md +139 -0
  79. package/dist/agent-docs/components/Stepper.md +67 -0
  80. package/dist/agent-docs/components/Switch.md +42 -0
  81. package/dist/agent-docs/components/Table.md +63 -0
  82. package/dist/agent-docs/components/TableSkeleton.md +46 -0
  83. package/dist/agent-docs/components/Tabs.md +86 -0
  84. package/dist/agent-docs/components/TextArea.md +52 -0
  85. package/dist/agent-docs/components/ThemeSwitcher.md +69 -0
  86. package/dist/agent-docs/components/Toaster.md +23 -0
  87. package/dist/agent-docs/components/Toggle.md +31 -0
  88. package/dist/agent-docs/components/ToggleGroup.md +30 -0
  89. package/dist/agent-docs/components/Tooltip.md +91 -0
  90. package/dist/agent-docs/components/TypingIndicator.md +21 -0
  91. package/dist/agent-docs/components/Typo.md +65 -0
  92. package/dist/agent-docs/components/WeeklyCalendar.md +64 -0
  93. package/dist/agent-docs/components-list.md +144 -0
  94. package/dist/node_modules/eventemitter3/index2.js +1 -1
  95. package/dist/node_modules/hast-util-to-jsx-runtime/lib/index.js +1 -1
  96. package/dist/node_modules/style-to-object/cjs/index.js +1 -1
  97. package/dist/node_modules/unified/lib/index.js +1 -1
  98. package/package.json +3 -2
@@ -0,0 +1,87 @@
1
+ # AspectRatio
2
+
3
+ ## Overview
4
+
5
+ A container that maintains a consistent aspect ratio for its content. Useful for images, videos, and any media that requires a fixed ratio.
6
+
7
+ ---
8
+
9
+ ## Props
10
+
11
+ ### AspectRatio (Root)
12
+
13
+ | Prop | Type | Default | Description |
14
+ | ----------- | ------------------- | ----------- | ----------------------------------------------- |
15
+ | `ratio` | `number` | `undefined` | Aspect ratio expressed as a number (e.g., 16/9).|
16
+ | `className` | `string` | `""` | Additional classes applied to the container. |
17
+ | `children` | `React.ReactNode` | **required**| Content inside the ratio-constrained container. |
18
+
19
+ ---
20
+
21
+ ## Behavior
22
+
23
+ - **Responsive**: The container scales while preserving the specified ratio.
24
+ - **Content fill**: Child content should handle its own layout (e.g., `object-cover`).
25
+ - **Styling**: Apply width/height and styling via `className`.
26
+
27
+ ---
28
+
29
+ ## Examples
30
+
31
+ ### 16:9 Ratio
32
+
33
+ ```tsx
34
+ import { AspectRatio } from "laif-ds";
35
+
36
+ export function Ratio16x9() {
37
+ return (
38
+ <AspectRatio ratio={16 / 9} className="bg-d-secondary/10 w-[400px] rounded-md overflow-hidden">
39
+ <div className="flex h-full items-center justify-center">
40
+ <p className="text-sm text-d-secondary-foreground">16:9 Aspect Ratio</p>
41
+ </div>
42
+ </AspectRatio>
43
+ );
44
+ }
45
+ ```
46
+
47
+ ### Square (1:1)
48
+
49
+ ```tsx
50
+ import { AspectRatio } from "laif-ds";
51
+
52
+ export function Square() {
53
+ return (
54
+ <AspectRatio ratio={1 / 1} className="bg-d-secondary/10 w-[400px] rounded-md overflow-hidden">
55
+ <div className="flex h-full items-center justify-center">
56
+ <p className="text-sm text-d-secondary-foreground">1:1 Aspect Ratio</p>
57
+ </div>
58
+ </AspectRatio>
59
+ );
60
+ }
61
+ ```
62
+
63
+ ### With Image
64
+
65
+ ```tsx
66
+ import { AspectRatio } from "laif-ds";
67
+
68
+ export function ImageRatio() {
69
+ return (
70
+ <AspectRatio ratio={16 / 9} className="w-[400px] rounded-md overflow-hidden">
71
+ <img
72
+ src="https://images.unsplash.com/photo-1588345921523-c2dcdb7f1dcd?w=800&dpr=2&q=80"
73
+ alt="Image"
74
+ className="h-full w-full object-cover"
75
+ />
76
+ </AspectRatio>
77
+ );
78
+ }
79
+ ```
80
+
81
+ ---
82
+
83
+ ## Notes
84
+
85
+ - **Children**: Place any content inside; use `object-cover` for images to avoid distortion.
86
+ - **Width**: Control width via `className`; height is computed from the ratio.
87
+
@@ -0,0 +1,127 @@
1
+ # AsyncSelect
2
+
3
+ ## Overview
4
+
5
+ Generic async select with search input, popover list, optional preload and multiple selection. Fully render-prop driven for option content and value extraction.
6
+
7
+ ---
8
+
9
+ ## Props
10
+
11
+ | Prop | Type | Default | Description |
12
+ | ----------------- | -------------------------------------------- | ----------- | ----------- |
13
+ | `fetcher` | `(query?: string) => Promise<T[]>` | **required**| Async loader for options. Called on open and on search. |
14
+ | `preload` | `boolean` | `false` | Preload all data once; then client-filter using `filterFn`. |
15
+ | `filterFn` | `(option: T, query: string) => boolean` | `undefined` | Custom client-side filter when `preload=true`. |
16
+ | `renderOption` | `(option: T) => React.ReactNode` | **required**| How to render each option row. |
17
+ | `getOptionValue` | `(option: T) => string` | **required**| Extract option id. |
18
+ | `getDisplayValue` | `(option: T) => React.ReactNode` | **required**| Display value for trigger. |
19
+ | `multiple` | `boolean` | `false` | Enable multi-selection. Controls `value` type. |
20
+ | `value` | `string | string[]` | `undefined` | Controlled value. |
21
+ | `onChange` | `(value: string | string[]) => void` | `undefined` | Change callback. |
22
+ | `label` | `string | React.ReactNode` | `undefined` | Optional label above. |
23
+ | `labelClassName` | `string` | `undefined` | Label classes. |
24
+ | `placeholder` | `string` | `"Select..."` | Placeholder when empty. |
25
+ | `disabled` | `boolean` | `false` | Disable trigger and input. |
26
+ | `width` | `string | number | "auto"` | `200px` | Popover width; `auto` matches trigger width. |
27
+ | `triggerClassName`| `string` | `undefined` | Extra classes for trigger button. |
28
+ | `noResultsMessage`| `string` | `undefined` | Message when list is empty. |
29
+ | `clearable` | `boolean` | `true` | Show clear icon when a value is set. |
30
+ | `size` | `"sm" | "default" | "lg"` | `"default"` | Trigger size. |
31
+ | `loadingSkeleton` | `React.ReactNode` | `undefined` | Custom loading skeleton list. |
32
+ | `notFound` | `React.ReactNode` | `undefined` | Custom empty content. |
33
+
34
+ ---
35
+
36
+ ## Behavior
37
+
38
+ - **Search**: Debounced input (0ms when `preload=true`, 300ms otherwise).
39
+ - **Caching**: Results cached by query; reused when re-typing.
40
+ - **Multiple**: Renders selected count or first label; supports checkbox UI per item.
41
+ - **Clear**: Built-in clear icon (uses DS `Icon`), respects `clearable`.
42
+ - **A11y**: Trigger focus ring and keyboard navigation via `cmdk`.
43
+
44
+ ---
45
+
46
+ ## Examples
47
+
48
+ ### Preloaded
49
+
50
+ ```tsx
51
+ import * as React from "react";
52
+ import { AsyncSelect } from "laif-ds";
53
+
54
+ type User = { id: number; name: string; email: string };
55
+
56
+ async function fetchUsers(query?: string): Promise<User[]> {
57
+ const res = await fetch("https://jsonplaceholder.typicode.com/users");
58
+ const data: User[] = await res.json();
59
+ if (!query) return data;
60
+ const q = query.toLowerCase();
61
+ return data.filter((u) => u.name.toLowerCase().includes(q));
62
+ }
63
+
64
+ export function PreloadedUsers() {
65
+ const [value, setValue] = React.useState("");
66
+ return (
67
+ <AsyncSelect<User>
68
+ preload
69
+ fetcher={fetchUsers}
70
+ value={value}
71
+ onChange={setValue}
72
+ renderOption={(u) => (
73
+ <div className="truncate">
74
+ <div className="font-medium">{u.name}</div>
75
+ <div className="text-d-muted-foreground text-xs">{u.email}</div>
76
+ </div>
77
+ )}
78
+ getOptionValue={(u) => String(u.id)}
79
+ getDisplayValue={(u) => u.name}
80
+ placeholder="Select a user..."
81
+ width="300px"
82
+ />
83
+ );
84
+ }
85
+ ```
86
+
87
+ ### Multiple with Steps
88
+
89
+ ```tsx
90
+ import * as React from "react";
91
+ import { AsyncSelect } from "laif-ds";
92
+
93
+ type Tag = { id: string; label: string };
94
+ const tags: Tag[] = [
95
+ { id: "react", label: "React" },
96
+ { id: "nextjs", label: "Next.js" },
97
+ { id: "tailwind", label: "Tailwind" },
98
+ ];
99
+
100
+ export function MultipleTags() {
101
+ const [value, setValue] = React.useState<string[]>([]);
102
+ const fetcher = async (q?: string) =>
103
+ !q ? tags : tags.filter((t) => t.label.toLowerCase().includes(q!.toLowerCase()));
104
+ return (
105
+ <AsyncSelect<Tag>
106
+ multiple
107
+ fetcher={fetcher}
108
+ value={value}
109
+ onChange={setValue}
110
+ renderOption={(t) => t.label}
111
+ getOptionValue={(t) => t.id}
112
+ getDisplayValue={(t) => t.label}
113
+ placeholder="Select tags..."
114
+ width="auto"
115
+ />
116
+ );
117
+ }
118
+ ```
119
+
120
+ ---
121
+
122
+ ## Notes
123
+
124
+ - **Trigger width**: Use `width="auto"` to match trigger width; or a fixed `number|string`.
125
+ - **Filtering**: For big datasets prefer server search (no `preload`); for small datasets prefer `preload` + `filterFn`.
126
+ - **Theming**: Uses DS token classes across trigger, list, and states.
127
+
@@ -0,0 +1,41 @@
1
+ # AudioVisualizer
2
+
3
+ ## Overview
4
+
5
+ Canvas-based audio waveform visualizer for a MediaStream. Starts/stops with `isRecording` and resizes responsively.
6
+
7
+ ---
8
+
9
+ ## Props
10
+
11
+ | Prop | Type | Description |
12
+ | --- | --- | --- |
13
+ | `stream` | `MediaStream | null` | Input audio stream |
14
+ | `isRecording` | `boolean` | Whether to render visualization |
15
+ | `onClick` | `() => void` | Click handler (e.g., to toggle state) |
16
+
17
+ ---
18
+
19
+ ## Example
20
+
21
+ ```tsx
22
+ import { useEffect, useState } from "react";
23
+ import { AudioVisualizer } from "laif-ds";
24
+
25
+ export function MicVisualizer() {
26
+ const [stream, setStream] = useState<MediaStream | null>(null);
27
+ const [isRecording, setIsRecording] = useState(false);
28
+
29
+ useEffect(() => {
30
+ navigator.mediaDevices.getUserMedia({ audio: true }).then(setStream);
31
+ }, []);
32
+
33
+ return (
34
+ <AudioVisualizer
35
+ stream={stream}
36
+ isRecording={isRecording}
37
+ onClick={() => setIsRecording((v) => !v)}
38
+ />
39
+ );
40
+ }
41
+ ```
@@ -0,0 +1,113 @@
1
+ # Avatar
2
+
3
+ ## Overview
4
+
5
+ Circular user/avatar component with image and fallback. Accessible and easily styled.
6
+
7
+ ---
8
+
9
+ ## Props
10
+
11
+ ### Avatar (Root)
12
+
13
+ | Prop | Type | Default | Description |
14
+ | ----------- | ----------------- | ----------- | ------------------------------------------------ |
15
+ | `className` | `string` | `""` | Additional classes for size/border/layout. |
16
+ | `children` | `React.ReactNode` | **required**| Typically `AvatarImage` and `AvatarFallback`. |
17
+
18
+ ### Subcomponents
19
+
20
+ - `AvatarImage`: The image element.
21
+ - Props: `src`, `alt`, `className`.
22
+ - `AvatarFallback`: Fallback content shown when the image fails or loads slowly.
23
+ - Props: `children` (e.g., initials), `className`.
24
+
25
+ ---
26
+
27
+ ## Behavior
28
+
29
+ - **Shape**: Circular by default (`rounded-full`).
30
+ - **Sizing**: Control via `className` (e.g., `h-16 w-16`).
31
+ - **Fallback**: Displays initials or an icon when the image is unavailable.
32
+
33
+ ---
34
+
35
+ ## Examples
36
+
37
+ ### With Image
38
+
39
+ ```tsx
40
+ import { Avatar, AvatarImage, AvatarFallback } from "laif-ds";
41
+
42
+ export function WithImage() {
43
+ return (
44
+ <Avatar>
45
+ <AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
46
+ <AvatarFallback>CN</AvatarFallback>
47
+ </Avatar>
48
+ );
49
+ }
50
+ ```
51
+
52
+ ### With Fallback
53
+
54
+ ```tsx
55
+ import { Avatar, AvatarImage, AvatarFallback } from "laif-ds";
56
+
57
+ export function WithFallback() {
58
+ return (
59
+ <Avatar>
60
+ <AvatarImage src="" alt="User" />
61
+ <AvatarFallback>JD</AvatarFallback>
62
+ </Avatar>
63
+ );
64
+ }
65
+ ```
66
+
67
+ ### Custom Size
68
+
69
+ ```tsx
70
+ import { Avatar, AvatarImage, AvatarFallback } from "laif-ds";
71
+
72
+ export function CustomSize() {
73
+ return (
74
+ <Avatar className="h-16 w-16">
75
+ <AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
76
+ <AvatarFallback>CN</AvatarFallback>
77
+ </Avatar>
78
+ );
79
+ }
80
+ ```
81
+
82
+ ### Avatar Group
83
+
84
+ ```tsx
85
+ import { Avatar, AvatarImage, AvatarFallback } from "laif-ds";
86
+
87
+ export function AvatarGroup() {
88
+ return (
89
+ <div className="flex -space-x-2">
90
+ <Avatar className="border-background border-2">
91
+ <AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
92
+ <AvatarFallback>CN</AvatarFallback>
93
+ </Avatar>
94
+ <Avatar className="border-background border-2">
95
+ <AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
96
+ <AvatarFallback>JD</AvatarFallback>
97
+ </Avatar>
98
+ <Avatar className="border-background border-2">
99
+ <AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
100
+ <AvatarFallback>MK</AvatarFallback>
101
+ </Avatar>
102
+ </div>
103
+ );
104
+ }
105
+ ```
106
+
107
+ ---
108
+
109
+ ## Notes
110
+
111
+ - **Accessibility**: Provide `alt` text for `AvatarImage`.
112
+ - **Styling**: Combine with borders/shadows via `className`.
113
+
@@ -0,0 +1,118 @@
1
+ # Badge
2
+
3
+ ## Overview
4
+
5
+ Small, inline label for status and metadata. Supports many visual variants, optional icons, link mode, and disabled state.
6
+
7
+ ---
8
+
9
+ ## Props
10
+
11
+ ### Badge (Root)
12
+
13
+ | Prop | Type | Default | Description |
14
+ | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | ------------------------------------------- |
15
+ | `variant` | `"default" \| "destructive" \| "warning" \| "success" \| "outline" \| "outline-primary" \| "outline-destructive" \| "outline-warning" \| "outline-success" \| "secondary" \| "ghost" \| "ghost-destructive" \| "ghost-accent" \| "ghost-warning" \| "ghost-success" \| "link"` | `"default"` | Visual style of the badge. |
16
+ | `asChild` | `boolean` | `false` | Renders the badge as its child element. |
17
+ | `disabled` | `boolean` | `false` | Disables interactions and dims the badge. |
18
+ | `iconLeft` | `IconName` | `undefined` | Optional left icon (uses `Icon` component). |
19
+ | `iconRight` | `IconName` | `undefined` | Optional right icon (uses `Icon` component).|
20
+ | `className` | `string` | `""` | Additional classes on the root element. |
21
+ | `children` | `React.ReactNode` | **required** | Text or content inside the badge. |
22
+
23
+ ---
24
+
25
+ ## Behavior
26
+
27
+ - **Variants**: Outline, ghost, and semantic variants available for flexible UIs.
28
+ - **As child**: Use `asChild` to render as an anchor or any custom element.
29
+ - **Icons**: `iconLeft`/`iconRight` render `Icon` with appropriate sizes.
30
+ - **Disabled**: Applies `cursor-not-allowed` and reduces opacity.
31
+
32
+ ---
33
+
34
+ ## Examples
35
+
36
+ ### Default
37
+
38
+ ```tsx
39
+ import { Badge } from "laif-ds";
40
+
41
+ export function DefaultBadge() {
42
+ return <Badge>Badge</Badge>;
43
+ }
44
+ ```
45
+
46
+ ### Variants Grid
47
+
48
+ ```tsx
49
+ import { Badge, type BadgeProps } from "laif-ds";
50
+
51
+ const variants: BadgeProps["variant"][] = [
52
+ "default",
53
+ "destructive",
54
+ "warning",
55
+ "success",
56
+ "outline",
57
+ "outline-primary",
58
+ "outline-destructive",
59
+ "outline-warning",
60
+ "outline-success",
61
+ "secondary",
62
+ "ghost",
63
+ "ghost-accent",
64
+ "ghost-destructive",
65
+ "ghost-warning",
66
+ "ghost-success",
67
+ "link",
68
+ ];
69
+
70
+ export function VariantsShowcase() {
71
+ return (
72
+ <div className="flex flex-wrap gap-2">
73
+ {variants.map((v) => (
74
+ <Badge key={v} variant={v}>
75
+ {v}
76
+ </Badge>
77
+ ))}
78
+ </div>
79
+ );
80
+ }
81
+ ```
82
+
83
+ ### With Icons
84
+
85
+ ```tsx
86
+ import { Badge } from "laif-ds";
87
+
88
+ export function WithIcons() {
89
+ return (
90
+ <div className="flex gap-2">
91
+ <Badge iconLeft="Check" iconRight="X">Approved</Badge>
92
+ <Badge variant="outline-primary" iconLeft="Pencil">Edit</Badge>
93
+ </div>
94
+ );
95
+ }
96
+ ```
97
+
98
+ ### As Link (asChild)
99
+
100
+ ```tsx
101
+ import { Badge } from "laif-ds";
102
+
103
+ export function LinkBadge() {
104
+ return (
105
+ <Badge asChild>
106
+ <a href="#" className="cursor-pointer">Clickable Badge</a>
107
+ </Badge>
108
+ );
109
+ }
110
+ ```
111
+
112
+ ---
113
+
114
+ ## Notes
115
+
116
+ - **Icons**: Use `IconName` values supported by the design system.
117
+ - **AsChild**: Useful to keep semantics (e.g., anchors) while styling as badges.
118
+
@@ -0,0 +1,78 @@
1
+ # Breadcrumb
2
+
3
+ ## Overview
4
+
5
+ Composable breadcrumb navigation components. Includes list, items, links, separators, current page, and ellipsis. Lightweight wrappers around semantic HTML with sensible styles.
6
+
7
+ ---
8
+
9
+ ## Subcomponents
10
+
11
+ - `Breadcrumb`
12
+ - `BreadcrumbList`
13
+ - `BreadcrumbItem`
14
+ - `BreadcrumbLink` (supports `asChild`)
15
+ - `BreadcrumbPage`
16
+ - `BreadcrumbSeparator` (defaults to chevron icon)
17
+ - `BreadcrumbEllipsis` (three-dot ellipsis)
18
+
19
+ All subcomponents extend their respective native element props.
20
+
21
+ ---
22
+
23
+ ## Examples
24
+
25
+ ### Basic
26
+
27
+ ```tsx
28
+ import {
29
+ Breadcrumb,
30
+ BreadcrumbList,
31
+ BreadcrumbItem,
32
+ BreadcrumbLink,
33
+ BreadcrumbPage,
34
+ BreadcrumbSeparator,
35
+ } from "laif-ds";
36
+
37
+ export function BasicBreadcrumb() {
38
+ return (
39
+ <Breadcrumb>
40
+ <BreadcrumbList>
41
+ <BreadcrumbItem>
42
+ <BreadcrumbLink href="/">Home</BreadcrumbLink>
43
+ </BreadcrumbItem>
44
+ <BreadcrumbSeparator />
45
+ <BreadcrumbItem>
46
+ <BreadcrumbLink href="/docs">Docs</BreadcrumbLink>
47
+ </BreadcrumbItem>
48
+ <BreadcrumbSeparator />
49
+ <BreadcrumbItem>
50
+ <BreadcrumbPage>Components</BreadcrumbPage>
51
+ </BreadcrumbItem>
52
+ </BreadcrumbList>
53
+ </Breadcrumb>
54
+ );
55
+ }
56
+ ```
57
+
58
+ ### Custom Separator
59
+
60
+ ```tsx
61
+ import { Breadcrumb, BreadcrumbList, BreadcrumbItem, BreadcrumbLink, BreadcrumbSeparator, BreadcrumbPage } from "laif-ds";
62
+
63
+ export function CustomSeparator() {
64
+ return (
65
+ <Breadcrumb>
66
+ <BreadcrumbList>
67
+ <BreadcrumbItem>
68
+ <BreadcrumbLink href="/">Home</BreadcrumbLink>
69
+ </BreadcrumbItem>
70
+ <BreadcrumbSeparator>/</BreadcrumbSeparator>
71
+ <BreadcrumbItem>
72
+ <BreadcrumbPage>Current</BreadcrumbPage>
73
+ </BreadcrumbItem>
74
+ </BreadcrumbList>
75
+ </Breadcrumb>
76
+ );
77
+ }
78
+ ```
@@ -0,0 +1,129 @@
1
+ # Button
2
+
3
+ ## Overview
4
+
5
+ Versatile button with multiple variants and sizes, optional leading/trailing icons, loading state, and support for rendering as a child element.
6
+
7
+ ---
8
+
9
+ ## Props
10
+
11
+ ### Button (Root)
12
+
13
+ | Prop | Type | Default | Description |
14
+ | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------ | ------------- | -------------------------------------------------------- |
15
+ | `variant` | `"default" | "destructive" | "outline" | "outline-primary" | "outline-destructive" | "secondary" | "ghost" | "ghost-destructive" | "ghost-accent" | "link"` | `"default"` | Visual style of the button. |
16
+ | `size` | `"default" | "sm" | "lg" | "icon"` | `"default"` | Size of the button. |
17
+ | `asChild` | `boolean` | `false` | Render as child (e.g., anchor) while preserving styles. |
18
+ | `iconLeft` | `IconName` | `undefined` | Optional left icon name. |
19
+ | `iconRight` | `IconName` | `undefined` | Optional right icon name. |
20
+ | `isLoading` | `boolean` | `false` | Shows a loading spinner; overrides `iconLeft`. |
21
+ | `className` | `string` | `""` | Additional classes for layout/width. |
22
+ | `disabled` | `boolean` | `false` | Disables the button. |
23
+ | `onClick` | `(e: React.MouseEvent<HTMLButtonElement>) => void` | `undefined` | Click handler. |
24
+ | `children` | `React.ReactNode` | **required** | Button label or content. |
25
+
26
+ ---
27
+
28
+ ## Behavior
29
+
30
+ - **Loading**: When `isLoading` is `true`, a spinner is shown and `iconLeft` is hidden.
31
+ - **Icons**: Icon sizes adapt to the button size (`sm`, `default`, `lg`, `icon`).
32
+ - **As Child**: Use `asChild` to render the button as a link or custom element while keeping button styles.
33
+ - **Accessibility**: Keyboard-focus ring and proper semantics are included.
34
+
35
+ ---
36
+
37
+ ## Examples
38
+
39
+ ### Default
40
+
41
+ ```tsx
42
+ import { Button } from "laif-ds";
43
+
44
+ export function DefaultButton() {
45
+ return <Button>Button</Button>;
46
+ }
47
+ ```
48
+
49
+ ### Showcase (Variants × Sizes)
50
+
51
+ ```tsx
52
+ import { Button, type ButtonProps } from "laif-ds";
53
+
54
+ const variants: ButtonProps["variant"][] = [
55
+ "default",
56
+ "destructive",
57
+ "outline",
58
+ "outline-primary",
59
+ "outline-destructive",
60
+ "secondary",
61
+ "ghost",
62
+ "ghost-accent",
63
+ "ghost-destructive",
64
+ "link",
65
+ ];
66
+
67
+ const sizes: ButtonProps["size"][] = ["lg", "default", "sm", "icon"];
68
+
69
+ export function ButtonsGrid() {
70
+ return (
71
+ <div className="flex flex-col gap-4">
72
+ {variants.map((variant) => (
73
+ <div key={variant} className="flex items-center gap-2 flex-wrap">
74
+ {sizes.map((size) => (
75
+ size === "icon" ? (
76
+ <Button key={`${variant}-${size}`} variant={variant} size={size} iconLeft="BadgeInfo" />
77
+ ) : (
78
+ <Button key={`${variant}-${size}`} variant={variant} size={size}>
79
+ {variant} - {size}
80
+ </Button>
81
+ )
82
+ ))}
83
+ </div>
84
+ ))}
85
+ </div>
86
+ );
87
+ }
88
+ ```
89
+
90
+ ### Full Width
91
+
92
+ ```tsx
93
+ import { Button } from "laif-ds";
94
+
95
+ export function FullWidthButton() {
96
+ return (
97
+ <Button className="w-full">Full Width Button</Button>
98
+ );
99
+ }
100
+ ```
101
+
102
+ ### With Icon
103
+
104
+ ```tsx
105
+ import { Button } from "laif-ds";
106
+
107
+ export function WithIcon() {
108
+ return <Button iconLeft="Check">Button with Icon</Button>;
109
+ }
110
+ ```
111
+
112
+ ### Loading
113
+
114
+ ```tsx
115
+ import { Button } from "laif-ds";
116
+
117
+ export function LoadingButton() {
118
+ return <Button isLoading>Loading Button</Button>;
119
+ }
120
+ ```
121
+
122
+ ---
123
+
124
+ ## Notes
125
+
126
+ - **Disabled**: Applies reduced opacity and prevents interactions.
127
+ - **Icon-only**: Use `size="icon"` for square icon buttons.
128
+ - **Theming**: Use variants to match semantic meaning (primary, destructive, etc.).
129
+