flikkui 0.2.0-beta.10 → 0.2.0-beta.12

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 (80) hide show
  1. package/README.md +2 -213
  2. package/dist/components/ai/CodeBlock/CodeBlock.theme.js +5 -5
  3. package/dist/components/ai/PromptInput/PromptInput.js +0 -3
  4. package/dist/components/ai/PromptInput/PromptInput.theme.js +1 -1
  5. package/dist/components/ai/index.d.ts +0 -4
  6. package/dist/components/ai/index.js +0 -6
  7. package/dist/components/core/Accordion/Accordion.theme.js +1 -1
  8. package/dist/components/core/Alert/Alert.js +21 -8
  9. package/dist/components/core/Alert/Alert.theme.d.ts +4 -0
  10. package/dist/components/core/Alert/Alert.theme.js +18 -10
  11. package/dist/components/core/Alert/Alert.types.d.ts +31 -14
  12. package/dist/components/core/Alert/index.d.ts +1 -1
  13. package/dist/components/core/AvatarGroup/AvatarGroup.animations.js +10 -36
  14. package/dist/components/core/AvatarGroup/AvatarGroup.js +3 -15
  15. package/dist/components/core/AvatarGroup/AvatarGroup.theme.d.ts +0 -1
  16. package/dist/components/core/AvatarGroup/AvatarGroup.theme.js +0 -6
  17. package/dist/components/core/Badge/Badge.theme.js +13 -14
  18. package/dist/components/core/Button/Button.ripple.js +4 -0
  19. package/dist/components/core/Metric/Metric.js +1 -5
  20. package/dist/components/core/Metric/Metric.theme.js +1 -1
  21. package/dist/components/core/Metric/index.d.ts +1 -1
  22. package/dist/components/core/Tag/Tag.js +2 -1
  23. package/dist/components/core/Tag/Tag.theme.js +3 -3
  24. package/dist/components/core/Toast/Toast.animations.d.ts +1 -1
  25. package/dist/components/core/Toast/Toast.animations.js +4 -7
  26. package/dist/components/core/Toast/Toast.js +26 -7
  27. package/dist/components/core/Toast/Toast.theme.js +4 -1
  28. package/dist/components/core/Toast/Toast.types.d.ts +10 -0
  29. package/dist/components/core/Toast/ToastProvider.js +31 -1
  30. package/dist/components/core/index.d.ts +0 -1
  31. package/dist/components/core/index.js +0 -2
  32. package/dist/components/effects/Animated/Animated.animations.d.ts +7 -0
  33. package/dist/components/effects/Animated/Animated.animations.js +49 -0
  34. package/dist/components/effects/Animated/Animated.d.ts +6 -0
  35. package/dist/components/effects/Animated/Animated.js +35 -0
  36. package/dist/components/effects/Animated/Animated.types.d.ts +23 -0
  37. package/dist/components/effects/Animated/AnimatedItem.d.ts +2 -0
  38. package/dist/components/effects/Animated/AnimatedItem.js +40 -0
  39. package/dist/components/effects/Animated/index.d.ts +2 -0
  40. package/dist/components/effects/SpotlightBorder/SpotlightBorder.js +9 -5
  41. package/dist/components/effects/index.d.ts +2 -0
  42. package/dist/components/effects/index.js +1 -0
  43. package/dist/components/forms/FileUpload/FileUpload.js +0 -1
  44. package/dist/components/forms/TimePicker/TimePickerContent.js +0 -1
  45. package/dist/components/forms/index.d.ts +0 -1
  46. package/dist/components/forms/index.js +0 -4
  47. package/dist/index.js +1 -5
  48. package/dist/styles.css +1 -1
  49. package/package.json +1 -2
  50. package/dist/components/ai/ArtifactContainer/ArtifactContainer.animations.d.ts +0 -21
  51. package/dist/components/ai/ArtifactContainer/ArtifactContainer.animations.js +0 -123
  52. package/dist/components/ai/ArtifactContainer/ArtifactContainer.d.ts +0 -7
  53. package/dist/components/ai/ArtifactContainer/ArtifactContainer.js +0 -342
  54. package/dist/components/ai/ArtifactContainer/ArtifactContainer.theme.d.ts +0 -2
  55. package/dist/components/ai/ArtifactContainer/ArtifactContainer.theme.js +0 -25
  56. package/dist/components/ai/ArtifactContainer/ArtifactContainer.types.d.ts +0 -77
  57. package/dist/components/ai/ArtifactContainer/index.d.ts +0 -4
  58. package/dist/components/ai/ChatInterface/ChatInterface.d.ts +0 -26
  59. package/dist/components/ai/ChatInterface/ChatInterface.js +0 -65
  60. package/dist/components/ai/ChatInterface/ChatInterface.theme.d.ts +0 -2
  61. package/dist/components/ai/ChatInterface/ChatInterface.theme.js +0 -8
  62. package/dist/components/ai/ChatInterface/ChatInterface.types.d.ts +0 -68
  63. package/dist/components/ai/ChatInterface/ChatInterface.types.js +0 -19
  64. package/dist/components/ai/ChatInterface/index.d.ts +0 -4
  65. package/dist/components/core/Notification/Notification.d.ts +0 -3
  66. package/dist/components/core/Notification/Notification.js +0 -115
  67. package/dist/components/core/Notification/Notification.theme.d.ts +0 -16
  68. package/dist/components/core/Notification/Notification.theme.js +0 -57
  69. package/dist/components/core/Notification/Notification.types.d.ts +0 -46
  70. package/dist/components/core/Notification/index.d.ts +0 -3
  71. package/dist/components/forms/StepperForm/StepperForm.d.ts +0 -7
  72. package/dist/components/forms/StepperForm/StepperForm.js +0 -86
  73. package/dist/components/forms/StepperForm/StepperForm.theme.d.ts +0 -2
  74. package/dist/components/forms/StepperForm/StepperForm.theme.js +0 -19
  75. package/dist/components/forms/StepperForm/StepperForm.types.d.ts +0 -65
  76. package/dist/components/forms/StepperForm/StepperForm.types.js +0 -12
  77. package/dist/components/forms/StepperForm/index.d.ts +0 -3
  78. package/dist/hooks/useFormStateMachine.js +0 -70
  79. package/dist/utils/formValidation.js +0 -21
  80. package/dist/utils/stateMachine.js +0 -45
package/README.md CHANGED
@@ -1,224 +1,13 @@
1
1
  # Flikkui
2
2
 
3
- A modern React component library built with TypeScript, Tailwind CSS v4, and Framer Motion. Follows the shadcn philosophy with complete `className` override support.
3
+ A modern React component library built with TypeScript, Tailwind CSS v4, and Framer Motion.
4
4
 
5
5
  ## Installation
6
6
 
7
7
  ```bash
8
8
  npm install flikkui
9
- # or
10
- yarn add flikkui
11
9
  ```
12
10
 
13
- ## Setup
14
-
15
- The quickest way to get started is with the CLI init command. It auto-detects your project type (Next.js, Vite, Remix, CRA), installs peer dependencies, and injects the CSS import into your entry file:
16
-
17
- ```bash
18
- npx flikkui init
19
- ```
20
-
21
- Options:
22
-
23
- | Flag | Description |
24
- |------|-------------|
25
- | `--tailwind`, `-t` | Set up Tailwind CSS integration (adds preset and content paths) |
26
- | `--yes`, `-y` | Skip prompts and use defaults |
27
- | `--skip-install` | Skip installing dependencies (prints manual command instead) |
28
-
29
- ### Manual Setup
30
-
31
- If you prefer to set things up yourself:
32
-
33
- 1. Install peer dependencies:
34
-
35
- ```bash
36
- npm install react react-dom tailwindcss motion clsx tailwind-merge @heroicons/react
37
- # or
38
- yarn add react react-dom tailwindcss motion clsx tailwind-merge @heroicons/react
39
- ```
40
-
41
- 2. Import styles in your main app file:
42
-
43
- ```tsx
44
- import 'flikkui/styles.css'
45
- ```
46
-
47
- ## Basic Usage
48
-
49
- ```tsx
50
- import { Button } from 'flikkui'
51
-
52
- function App() {
53
- return <Button variant="filled" color="primary">Click me</Button>
54
- }
55
- ```
56
-
57
- ### Subpath Imports
58
-
59
- Import from specific categories to optimize bundle size:
60
-
61
- ```tsx
62
- import { Button, Badge, Accordion } from 'flikkui/core'
63
- import { Input, Select, Checkbox } from 'flikkui/forms'
64
- import { AreaChart, BarChart } from 'flikkui/charts'
65
- import { GlassEffect } from 'flikkui/effects'
66
- ```
67
-
68
- ## Customizing the Theme
69
-
70
- Flikkui uses CSS variables for all theming. Override any variable in your own CSS to customize colors, spacing, border radius, and more.
71
-
72
- ### Colors
73
-
74
- Override semantic color palettes by redefining the CSS variables after importing the library styles:
75
-
76
- ```css
77
- :root {
78
- /* Change the primary color to green */
79
- --color-primary-50: oklch(0.982 0.018 155.826);
80
- --color-primary-100: oklch(0.962 0.044 156.743);
81
- --color-primary-200: oklch(0.925 0.084 155.995);
82
- --color-primary-300: oklch(0.871 0.15 154.449);
83
- --color-primary-400: oklch(0.792 0.209 151.711);
84
- --color-primary-500: oklch(0.723 0.219 149.579);
85
- --color-primary-600: oklch(0.627 0.194 149.214);
86
- --color-primary-700: oklch(0.527 0.154 150.069);
87
- --color-primary-800: oklch(0.448 0.119 151.328);
88
- --color-primary-900: oklch(0.393 0.095 152.535);
89
- --color-primary-950: oklch(0.266 0.065 152.934);
90
-
91
- --color-primary: var(--color-primary-600);
92
- }
93
- ```
94
-
95
- Available color palettes: `primary`, `danger`, `success`, `warning`. Each has shades from `50` to `950`.
96
-
97
- ### Text Colors
98
-
99
- ```css
100
- :root {
101
- --color-text-primary: var(--color-neutral-950);
102
- --color-text-secondary: var(--color-neutral-800);
103
- --color-text-placeholder: var(--color-neutral-600);
104
- --color-text-muted: var(--color-neutral-500);
105
- --color-text-disabled: var(--color-neutral-400);
106
- --color-text-inverse: var(--color-neutral-50);
107
- }
108
- ```
109
-
110
- ### Backgrounds & Borders
111
-
112
- ```css
113
- :root {
114
- --color-background: oklch(98.5% 0.002 247.839);
115
- --color-background-secondary: oklch(95% 0.002 247.839);
116
- --color-background-tertiary: oklch(90% 0.002 247.839);
117
- --color-background-quaternary: oklch(85% 0.002 247.839);
118
- --color-background-quinary: oklch(80% 0.002 247.839);
119
- --color-background-disabled: var(--color-neutral-100);
120
- --color-border: oklch(92.2% 0 0);
121
- }
122
- ```
123
-
124
- ### Border Radius System
125
-
126
- All border radii derive from a single `--radius-base` token. Change it once to update the entire UI:
127
-
128
- ```css
129
- :root {
130
- --radius-base: 0.5rem; /* 8px - change this to update all radii */
131
-
132
- /* Forms & Controls (1x base) */
133
- --form-radius: var(--radius-base);
134
- --button-radius: var(--form-radius);
135
- --badge-radius: var(--form-radius);
136
- --nav-item-radius: var(--radius-base);
137
-
138
- /* Overlays (1.5x base) */
139
- --dropdown-radius: calc(var(--radius-base) * 1.5);
140
- --tooltip-radius: var(--radius-base);
141
- --popover-radius: calc(var(--radius-base) * 1.5);
142
-
143
- /* Feedback surfaces */
144
- --alert-radius: calc(var(--radius-base) * 1.5);
145
- --toast-radius: calc(var(--radius-base) * 2);
146
- --drawer-radius: calc(var(--radius-base) * 2);
147
-
148
- /* Surfaces (3x base) */
149
- --card-radius: calc(var(--radius-base) * 3);
150
- --modal-radius: calc(var(--radius-base) * 3);
151
-
152
- /* Special shapes */
153
- --segmented-radius: 99px;
154
- --avatar-radius: 50%;
155
- }
156
- ```
157
-
158
- ### Form Elements
159
-
160
- Control sizing, padding, and border radius for all form components:
161
-
162
- ```css
163
- :root {
164
- /* Heights */
165
- --form-min-h-sm: 2rem;
166
- --form-min-h-md: 2.5rem;
167
- --form-min-h-lg: 3rem;
168
-
169
- /* Horizontal padding */
170
- --form-px-sm: 0.75rem;
171
- --form-px-md: 0.875rem;
172
- --form-px-lg: 1rem;
173
-
174
- /* Vertical padding */
175
- --form-py-sm: 0.5rem;
176
- --form-py-md: 0.625rem;
177
- --form-py-lg: 0.75rem;
178
-
179
- /* Font sizes */
180
- --form-text-sm: 0.75rem;
181
- --form-text-md: 0.875rem;
182
- --form-text-lg: 1rem;
183
- }
184
- ```
185
-
186
- Button, badge, segmented, and other component variables inherit from these form defaults but can be overridden individually (e.g. `--button-radius`, `--badge-radius`, `--button-px-*`).
187
-
188
- ### Dark Mode
189
-
190
- Add the `dark` class to your `<html>` or any parent container. All components adapt automatically:
191
-
192
- ```html
193
- <html class="dark">
194
- <!-- dark mode active -->
195
- </html>
196
- ```
197
-
198
- The library ships with sensible dark mode defaults. To customize dark mode colors, override variables inside `.dark`:
199
-
200
- ```css
201
- .dark {
202
- --color-background: oklch(14.5% 0 0);
203
- --color-border: oklch(30% 0 0);
204
- --color-primary: var(--color-primary-400);
205
- --color-text-primary: var(--color-neutral-50);
206
- --color-text-secondary: var(--color-neutral-400);
207
- }
208
- ```
209
-
210
- ### Full Variable Reference
211
-
212
- See [`src/styles/theme.css`](src/styles/theme.css) for the complete list of available CSS variables.
213
-
214
- ## Documentation
215
-
216
- This package is currently in beta. Full documentation coming soon.
217
-
218
11
  ## License
219
12
 
220
- MIT License - see LICENSE file for details.
221
-
222
- ---
223
-
224
- Built by Espranza Innovations
13
+ MIT
@@ -1,15 +1,15 @@
1
1
  const codeBlockTheme = {
2
2
  baseStyle: "relative rounded-[var(--codeblock-radius)] border border-[var(--color-border)] overflow-hidden bg-[var(--color-background)]",
3
3
  header: "flex items-center justify-between px-3 py-1.5 bg-[var(--color-background-secondary)] border-b border-[var(--color-border)]",
4
- headerLeft: "flex items-center gap-2 min-w-0 flex-1",
4
+ headerLeft: "flex items-center gap-2 min-w-0 flex-1 ",
5
5
  headerRight: "flex items-center gap-2 flex-shrink-0",
6
- filename: "text-sm font-medium text-[var(--color-text-primary)] font-mono truncate",
6
+ filename: "text-sm font-medium text-[var(--color-text-secondary)] truncate",
7
7
  languageLabel: "text-xs uppercase tracking-wider font-semibold text-[var(--color-text-muted)]",
8
8
  codeWrapper: "overflow-x-auto",
9
9
  lineNumber: "text-[var(--color-text-muted)] select-none text-right tabular-nums min-w-[2.5rem] pr-4 opacity-50",
10
- highlightedLine: "bg-[var(--color-primary-50)] border-l-2 border-l-[var(--color-primary)] -mx-4 px-4",
11
- diffAddition: "bg-[var(--color-success-50)] border-l-4 border-l-[var(--color-success)] -mx-4 px-4",
12
- diffDeletion: "bg-[var(--color-danger-50)] border-l-4 border-l-[var(--color-danger)] -mx-4 px-4",
10
+ highlightedLine: " -mx-4 px-4 bg-[var(--color-primary-50)] border-l-2 border-l-[var(--color-primary)] dark:bg-neutral-400/5 dark:border-l-neutral-200",
11
+ diffAddition: "-mx-4 px-4 bg-[var(--color-success-50)] border-l-4 border-l-[var(--color-success)] dark:bg-[var(--color-success-600)]/20 dark:border-l-[var(--color-success-700)]",
12
+ diffDeletion: "-mx-4 px-4 bg-[var(--color-danger-50)] border-l-4 border-l-[var(--color-danger)] dark:bg-[var(--color-danger-600)]/20 dark:border-l-[var(--color-danger-700)]",
13
13
  copyButton: "p-1.5 rounded-[calc(var(--radius-base)*0.75)] text-[var(--color-text-muted)] hover:text-[var(--color-text-primary)] hover:bg-[var(--color-background-tertiary)] transition-colors cursor-pointer focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-primary)]",
14
14
  copySuccess: "text-[var(--color-success)]",
15
15
  };
@@ -77,7 +77,6 @@ import '../../core/Alert/Alert.js';
77
77
  import '../../core/Toast/Toast.js';
78
78
  import '../../core/Toast/ToastProvider.js';
79
79
  import '@heroicons/react/24/solid';
80
- import '../../core/Notification/Notification.js';
81
80
  import '../../core/Spinner/Spinner.js';
82
81
  import '../../core/Message/Message.js';
83
82
  import '../../core/Message/TypeWriter.js';
@@ -117,8 +116,6 @@ import '../../forms/InputAddress/InputAddress.js';
117
116
  import '../../forms/InputAddress/InputAddress.theme.js';
118
117
  import '../../forms/InputDate/InputDate.js';
119
118
  import '../../forms/InputCounter/InputCounter.js';
120
- import '../../forms/StepperForm/StepperForm.js';
121
- import '../../forms/StepperForm/StepperForm.types.js';
122
119
  import '../../forms/InputTag/InputTag.js';
123
120
  import '../../forms/InputTag/InputTag.theme.js';
124
121
  import '../../forms/Combobox/Combobox.js';
@@ -1,5 +1,5 @@
1
1
  const promptInputTheme = {
2
- baseStyle: "rounded-[var(--card-radius)] border-[1px] border-[var(--color-border)] flex flex-col gap-2 shadow-real-md p-4 outline-2 outline-[var(--color-border)]/30 bg-[var(--color-background-secondary)] ",
2
+ baseStyle: "rounded-[var(--card-radius)] border-[1px] border-[var(--color-border)] flex flex-col gap-2 shadow-real-md p-4 outline-2 outline-[var(--color-border)]/30 bg-white dark:bg-[var(--color-background-secondary)] ",
3
3
  textareaStyle: "w-full bg-transparent text-sm text-[var(--color-text-primary)] placeholder:text-[var(--color-text-placeholder)] focus:outline-none resize-none overflow-y-auto transition-[height] duration-200 ease-in-out",
4
4
  footerStyle: "flex justify-between items-end",
5
5
  actionsStyle: "flex gap-1",
@@ -1,5 +1,3 @@
1
- export { ChatInterface, chatInterfaceTheme, useChatInterfaceContext, } from "./ChatInterface";
2
- export type { ChatInterfaceProps, ChatInterfaceContextValue, ChatInterfaceTheme, ChatInterfaceThemeOverrides, } from "./ChatInterface";
3
1
  export { Message, messageTheme } from "../core/Message";
4
2
  export type { MessageProps, MessageRole, MessageVariant, MessageAvatarProps, MessageTheme, MessageThemeOverrides, } from "../core/Message";
5
3
  export { MessageHistory, messageHistoryTheme } from "./MessageHistory";
@@ -19,5 +17,3 @@ export type { CodeBlockProps, CodeBlockLanguage, CodeBlockTheme, CodeBlockThemeO
19
17
  export { ApprovalCard } from "./ApprovalCard";
20
18
  export type { ApprovalCardProps, ApprovalRiskLevel, ApprovalMode, } from "./ApprovalCard";
21
19
  export { approvalCardTheme } from "./ApprovalCard/ApprovalCard.theme";
22
- export { ArtifactContainer, artifactContainerTheme, getHandlePillVariants, getPaneCollapseTransition, getCanvasTabContentVariants, getBorderGlowVariants, getTabUnderlineTransition, } from "./ArtifactContainer";
23
- export type { ArtifactContainerProps, ArtifactContainerChatProps, ArtifactContainerCanvasProps, ArtifactContainerCanvasTabProps, ArtifactContainerTheme, SplitDirection, CollapsedPane, } from "./ArtifactContainer";
@@ -1,6 +1,3 @@
1
- export { ChatInterface } from './ChatInterface/ChatInterface.js';
2
- export { chatInterfaceTheme } from './ChatInterface/ChatInterface.theme.js';
3
- export { useChatInterfaceContext } from './ChatInterface/ChatInterface.types.js';
4
1
  export { Message } from '../core/Message/Message.js';
5
2
  export { messageTheme } from '../core/Message/Message.theme.js';
6
3
  import '../core/Message/TypeWriter.js';
@@ -26,6 +23,3 @@ export { CodeBlock } from './CodeBlock/CodeBlock.js';
26
23
  export { codeBlockTheme } from './CodeBlock/CodeBlock.theme.js';
27
24
  export { ApprovalCard } from './ApprovalCard/ApprovalCard.js';
28
25
  export { approvalCardTheme } from './ApprovalCard/ApprovalCard.theme.js';
29
- export { ArtifactContainer } from './ArtifactContainer/ArtifactContainer.js';
30
- export { artifactContainerTheme } from './ArtifactContainer/ArtifactContainer.theme.js';
31
- export { getBorderGlowVariants, getCanvasTabContentVariants, getHandlePillVariants, getPaneCollapseTransition, getTabUnderlineTransition } from './ArtifactContainer/ArtifactContainer.animations.js';
@@ -4,7 +4,7 @@ const accordionTheme = {
4
4
  // Base container styles for stacked variant (unified card)
5
5
  baseStyleStacked: "w-full max-w-xl border border-[var(--color-border)] rounded-[var(--form-radius)] overflow-hidden",
6
6
  // Item styles for separated variant (individual cards with spacing)
7
- itemStyle: "border border-[var(--color-border)] rounded-[var(--form-radius)] bg-[var(--color-background)] overflow-hidden mb-2 last-of-type:mb-0 data-[state=open]:shadow-xs",
7
+ itemStyle: "border border-[var(--color-border)] rounded-[var(--form-radius)] bg-white dark:bg-[var(--color-background-secondary)] overflow-hidden mb-2 last-of-type:mb-0 data-[state=open]:shadow-xs",
8
8
  // Item styles for stacked variant (shared borders, no spacing)
9
9
  itemStyleStacked: "bg-white border-t border-[var(--color-border)] first-of-type:border-t-0",
10
10
  // Trigger styles (shared across variants)
@@ -2,24 +2,37 @@ import { jsxs, jsx } from 'react/jsx-runtime';
2
2
  import React__default from 'react';
3
3
  import { cn } from '../../../utils/cn.js';
4
4
  import { alertTheme } from './Alert.theme.js';
5
- import { XCircleIcon, ExclamationTriangleIcon, CheckCircleIcon, InformationCircleIcon, XMarkIcon } from '@heroicons/react/24/solid';
5
+ import { XMarkIcon, XCircleIcon, ExclamationTriangleIcon, CheckCircleIcon, InformationCircleIcon, BellIcon } from '@heroicons/react/24/solid';
6
6
  import { Button } from '../Button/Button.js';
7
7
 
8
- const colorIcons = {
9
- neutral: InformationCircleIcon,
8
+ const defaultIcons = {
9
+ neutral: BellIcon,
10
10
  primary: InformationCircleIcon,
11
11
  success: CheckCircleIcon,
12
12
  warning: ExclamationTriangleIcon,
13
13
  danger: XCircleIcon,
14
14
  };
15
- const Alert = React__default.forwardRef(({ variant = "default", color = "primary", title, description, dismissible = false, icon, showIcon = true, onDismiss, className, theme: customTheme = {}, children, darkMode = false, ...props }, ref) => {
16
- var _a, _b, _c, _d;
17
- const IconComponent = colorIcons[color];
15
+ const Alert = React__default.forwardRef(({ variant = "default", color = "primary", title, description, dismissible, icon, showIcon = true, avatar, actions, onDismiss, className, children, darkMode = false, ...props }, ref) => {
16
+ var _a;
17
+ const iconColor = (_a = alertTheme.iconColors[color]) !== null && _a !== void 0 ? _a : alertTheme.iconColors.primary;
18
+ const showDismiss = dismissible === true || (dismissible !== false && !!onDismiss);
18
19
  const handleDismiss = () => {
19
20
  onDismiss === null || onDismiss === void 0 ? void 0 : onDismiss();
20
21
  };
21
- const hasContent = title || description || children;
22
- const alertNode = (jsxs("div", { ref: ref, className: cn(alertTheme.baseStyle, (_a = alertTheme.variants) === null || _a === void 0 ? void 0 : _a[variant], ((_b = alertTheme.colors) === null || _b === void 0 ? void 0 : _b[color]) || "", customTheme.baseStyle, (_c = customTheme.variants) === null || _c === void 0 ? void 0 : _c[variant], (_d = customTheme.colors) === null || _d === void 0 ? void 0 : _d[color], className), role: "alert", ...props, children: [showIcon && (jsx("div", { className: "flex-shrink-0 size-5 mt-0.5", children: icon || jsx(IconComponent, { className: "size-5" }) })), hasContent && (jsxs("div", { className: "flex-1 min-w-0", children: [title && jsx("div", { className: "font-semibold text-sm", children: title }), description && (jsx("div", { className: "text-sm mt-0.5 text-[var(--color-text-secondary)]", children: description })), children && jsx("div", { className: "mt-1", children: children })] })), dismissible && (jsx(Button, { variant: "link", color: "primary", size: "sm", iconOnly: true, onClick: handleDismiss, className: "absolute top-2 right-2 flex-shrink-0 opacity-70 hover:opacity-100 transition-opacity cursor-pointer", children: jsx(XMarkIcon, { className: "size-4" }) }))] }));
22
+ const renderIconOrAvatar = () => {
23
+ if (avatar) {
24
+ return (jsx("div", { className: "flex-shrink-0 w-10 h-10 rounded-full", "aria-hidden": "true", children: avatar }));
25
+ }
26
+ if (icon === null || !showIcon) {
27
+ return null;
28
+ }
29
+ if (React__default.isValidElement(icon)) {
30
+ return (jsx("div", { className: "flex-shrink-0 w-6 h-6 mt-1", "aria-hidden": "true", children: icon }));
31
+ }
32
+ const IconComponent = defaultIcons[color];
33
+ return (jsx("div", { className: "flex-shrink-0 w-6 h-6 mt-1", "aria-hidden": "true", children: jsx(IconComponent, { className: cn("w-6 h-6", iconColor) }) }));
34
+ };
35
+ const alertNode = (jsxs("div", { ref: ref, className: cn(alertTheme.baseStyle, alertTheme.variants[variant], className), role: "alert", "aria-live": "assertive", "aria-atomic": "true", ...props, children: [renderIconOrAvatar(), jsxs("div", { className: `flex-1 min-w-0 ${showDismiss ? "mr-5" : ""}`, children: [title && (jsx("div", { className: cn("font-semibold text-[var(--color-text-primary)]"), children: title })), description && (jsx("div", { className: "text-[var(--color-text-secondary)]/90 mt-1", children: description })), children && jsx("div", { className: "mt-2", children: children }), actions && (jsx("div", { className: "flex items-center gap-2 mt-6", children: actions }))] }), showDismiss && (jsx(Button, { variant: "link", color: "neutral", size: "sm", iconOnly: true, onClick: handleDismiss, "aria-label": "Dismiss alert", className: "rounded-full absolute top-2 right-2 flex-shrink-0", children: jsx(XMarkIcon, { className: "size-4", strokeWidth: 2 }) }))] }));
23
36
  if (darkMode) {
24
37
  return jsx("div", { className: "dark", children: alertNode });
25
38
  }
@@ -1,2 +1,6 @@
1
1
  import { AlertTheme } from "./Alert.types";
2
+ /**
3
+ * Default theme configuration for Alert component
4
+ * Uses flat color organization matching Badge pattern
5
+ */
2
6
  export declare const alertTheme: AlertTheme;
@@ -1,18 +1,26 @@
1
+ /**
2
+ * Default theme configuration for Alert component
3
+ * Uses flat color organization matching Badge pattern
4
+ */
1
5
  const alertTheme = {
2
- baseStyle: "relative flex items-start gap-3 rounded-[var(--alert-radius)] p-4 text-sm bg-white border border-[var(--color-border)] dark:bg-[var(--color-background-secondary)] shadow-lg",
6
+ // Base styles applied to all alerts
7
+ baseStyle: "relative flex items-start gap-3 rounded-[var(--alert-radius)] p-4 text-sm border border-[var(--color-border)] backdrop-blur-md bg-white dark:bg-[var(--color-background-secondary)]/80",
8
+ // Visual style variants (structure only, no colors)
3
9
  variants: {
4
- default: "border border-[var(--color-border)]",
10
+ default: "",
5
11
  glass: "glass-effect",
6
12
  },
7
- /**
8
- * Semantic colors with ring and background styling
9
- */
10
- colors: {
13
+ // Icon color styles per color
14
+ iconColors: {
11
15
  neutral: "text-[var(--color-text-primary)]",
12
- primary: "text-[var(--color-primary-700)] dark:text-[var(--color-primary-400)]",
13
- success: "text-[var(--color-success-700)] dark:text-[var(--color-success-400)]",
14
- warning: "text-[var(--color-warning-700)] dark:text-[var(--color-warning-400)]",
15
- danger: "text-[var(--color-danger-700)] dark:text-[var(--color-danger-400)]",
16
+ primary: "text-[var(--color-primary)]",
17
+ success: "text-[var(--color-success)]",
18
+ warning: "text-[var(--color-warning)]",
19
+ danger: "text-[var(--color-danger)]",
20
+ },
21
+ // State styles
22
+ states: {
23
+ dismissible: "pr-10",
16
24
  },
17
25
  };
18
26
 
@@ -7,20 +7,25 @@ export type AlertColor = "neutral" | "primary" | "success" | "warning" | "danger
7
7
  * Alert visual variant
8
8
  */
9
9
  export type AlertVariant = "default" | "glass";
10
+ /**
11
+ * Theme configuration for Alert component
12
+ */
10
13
  export interface AlertTheme {
14
+ /** Base styles applied to all alerts */
11
15
  baseStyle: string;
16
+ /** Visual style variants (structure only, no colors) */
12
17
  variants: Record<AlertVariant, string>;
13
- colors: Record<AlertColor, string>;
14
- }
15
- export interface AlertThemeOverrides {
16
- baseStyle?: string;
17
- variants?: Partial<Record<AlertVariant, string>>;
18
- colors?: Partial<Record<AlertColor, string>>;
18
+ /** Icon color styles per color */
19
+ iconColors: Record<AlertColor, string>;
20
+ /** State styles */
21
+ states: {
22
+ dismissible: string;
23
+ };
19
24
  }
20
25
  export interface AlertProps extends HTMLAttributes<HTMLDivElement> {
21
- /** Visual variant (default, glass) */
26
+ /** Visual variant */
22
27
  variant?: AlertVariant;
23
- /** Semantic color (neutral, primary, success, warning, danger) */
28
+ /** Semantic color */
24
29
  color?: AlertColor;
25
30
  /** The main title/message of the alert */
26
31
  title?: string;
@@ -28,21 +33,33 @@ export interface AlertProps extends HTMLAttributes<HTMLDivElement> {
28
33
  description?: string;
29
34
  /** Whether the alert can be dismissed */
30
35
  dismissible?: boolean;
31
- /** Custom icon for the alert */
32
- icon?: ReactNode;
36
+ /**
37
+ * Custom icon for the alert
38
+ * - Provide custom icon: overrides the default variant icon
39
+ * - Set to null: hides icon completely
40
+ * - Leave undefined: shows default variant icon
41
+ */
42
+ icon?: ReactNode | null;
33
43
  /** Whether to show the default icon for the variant */
34
44
  showIcon?: boolean;
45
+ /**
46
+ * Avatar to display (takes precedence over icons)
47
+ * Example: avatar={<Avatar src="..." alt="User name" size="md" />}
48
+ */
49
+ avatar?: ReactNode;
50
+ /**
51
+ * Action buttons as ReactNode
52
+ * Example: actions={<><Button>Cancel</Button><Button variant="filled">Save</Button></>}
53
+ */
54
+ actions?: ReactNode;
35
55
  /** Callback when the alert is dismissed */
36
56
  onDismiss?: () => void;
37
57
  /** Custom class name */
38
58
  className?: string;
39
- /** Theme overrides */
40
- theme?: AlertThemeOverrides;
41
59
  /** Children content */
42
60
  children?: ReactNode;
43
61
  /**
44
- * Enable dark mode styling. When true, applies the `dark` class so components
45
- * use light colors for visibility.
62
+ * Enable dark mode styling.
46
63
  * @default false
47
64
  */
48
65
  darkMode?: boolean;
@@ -1,3 +1,3 @@
1
1
  export { Alert } from './Alert';
2
- export type { AlertProps, AlertVariant, AlertTheme, AlertThemeOverrides } from './Alert.types';
2
+ export type { AlertProps, AlertVariant, AlertColor, AlertTheme } from './Alert.types';
3
3
  export { alertTheme } from './Alert.theme';
@@ -8,10 +8,10 @@
8
8
  const getAvatarGroupVariants = (shouldReduceMotion = false, enableAnimations = true) => {
9
9
  if (shouldReduceMotion || !enableAnimations) {
10
10
  return {
11
- initial: { scale: 1, opacity: 1, zIndex: 10, x: 0, y: 0, rotate: 0 },
12
- hover: { scale: 1, zIndex: 10, x: 0, y: 0, rotate: 0 },
13
- notHovered: { scale: 1, opacity: 1, zIndex: 10, x: 0, y: 0, rotate: 0 },
14
- default: { scale: 1, opacity: 1, zIndex: 10, x: 0, y: 0, rotate: 0 },
11
+ initial: { scale: 1, opacity: 1, x: 0, y: 0, rotate: 0 },
12
+ hover: { scale: 1, x: 0, y: 0, rotate: 0 },
13
+ notHovered: { scale: 1, opacity: 1, x: 0, y: 0, rotate: 0 },
14
+ default: { scale: 1, opacity: 1, x: 0, y: 0, rotate: 0 },
15
15
  };
16
16
  }
17
17
  return {
@@ -22,15 +22,13 @@ const getAvatarGroupVariants = (shouldReduceMotion = false, enableAnimations = t
22
22
  y: 0,
23
23
  rotate: 0,
24
24
  filter: "saturate(1)",
25
- zIndex: 10,
26
25
  },
27
26
  hover: {
28
- scale: 1.05,
29
- y: -2,
27
+ scale: 1.02,
28
+ y: -1,
30
29
  rotate: 0,
31
30
  opacity: 1,
32
31
  filter: "saturate(1)",
33
- zIndex: 50,
34
32
  transition: {
35
33
  type: "spring",
36
34
  stiffness: 400,
@@ -38,34 +36,11 @@ const getAvatarGroupVariants = (shouldReduceMotion = false, enableAnimations = t
38
36
  mass: 0.8,
39
37
  },
40
38
  },
41
- notHovered: (custom) => {
42
- const { index, hoveredIndex, direction } = custom;
43
- if (hoveredIndex === null)
44
- return {};
45
- // Calculate relative position
46
- const isBefore = index < hoveredIndex;
47
- const isRowReverse = direction === "row-reverse";
48
- // Fan rotation: tilt away from the focused item
49
- // If before: tilt left (-deg). If after: tilt right (+deg).
50
- const rotateAmount = 15;
51
- let rotation = 0;
52
- let xOffset = 0;
53
- if (!isRowReverse) {
54
- rotation = isBefore ? -rotateAmount : rotateAmount;
55
- // Slight nudge to separate just a tiny bit without claiming space
56
- xOffset = isBefore ? -2 : 2;
57
- }
58
- else {
59
- rotation = isBefore ? rotateAmount : -rotateAmount;
60
- xOffset = isBefore ? 2 : -2;
61
- }
39
+ notHovered: () => {
62
40
  return {
63
- scale: 0.85,
64
- y: 4, // Sink slightly
65
- x: xOffset,
66
- rotate: rotation,
67
- filter: "saturate(0)", // Black and white, no blur
68
- zIndex: 5, // Lower z-index for non-hovered items
41
+ scale: 0.95,
42
+ y: 2,
43
+ filter: "saturate(0)",
69
44
  transition: {
70
45
  type: "spring",
71
46
  stiffness: 300,
@@ -80,7 +55,6 @@ const getAvatarGroupVariants = (shouldReduceMotion = false, enableAnimations = t
80
55
  y: 0,
81
56
  rotate: 0,
82
57
  filter: "saturate(1)",
83
- zIndex: 10,
84
58
  transition: {
85
59
  type: "spring",
86
60
  stiffness: 300,
@@ -15,9 +15,6 @@ const AvatarGroup = React__default.forwardRef(({ avatars = [], max = 5, size = "
15
15
  const visibleAvatars = avatars.slice(0, max);
16
16
  const overflowCount = avatars.length > max ? avatars.length - max : 0;
17
17
  const spacingClass = avatarGroupTheme.spacingStyles[spacing];
18
- const spacingHoverClass = enableAnimations
19
- ? avatarGroupTheme.spacingHoverStyles[spacing]
20
- : "";
21
18
  const directionClass = direction === "row-reverse" ? "flex-row-reverse" : "flex-row";
22
19
  const totalPeople = avatars.length;
23
20
  const groupDescription = avatars
@@ -27,13 +24,12 @@ const AvatarGroup = React__default.forwardRef(({ avatars = [], max = 5, size = "
27
24
  visibleAvatars,
28
25
  overflowCount,
29
26
  spacingClass,
30
- spacingHoverClass,
31
27
  directionClass,
32
28
  totalPeople,
33
29
  groupDescription,
34
30
  };
35
- }, [avatars, max, spacing, direction, enableAnimations]);
36
- const { visibleAvatars, overflowCount, spacingClass, spacingHoverClass, directionClass, totalPeople, groupDescription, } = memoizedData;
31
+ }, [avatars, max, spacing, direction]);
32
+ const { visibleAvatars, overflowCount, spacingClass, directionClass, totalPeople, groupDescription, } = memoizedData;
37
33
  return (jsxs("div", { ref: ref, className: cn(avatarGroupTheme.baseStyle, directionClass, className), role: "group", "aria-label": ariaLabel, "aria-description": `Contains ${totalPeople} users: ${groupDescription}`, "data-size": size, "data-spacing": spacing, "data-direction": direction, "data-total": totalPeople, "data-visible": visibleAvatars.length, "data-overflow": overflowCount > 0 ? "true" : "false", onMouseLeave: () => enableAnimations && setHoveredIndex(null), ...props, children: [visibleAvatars.map((avatarProps, index) => {
38
34
  // Create contextual label for individual avatars in a group
39
35
  const position = index + 1;
@@ -41,12 +37,6 @@ const AvatarGroup = React__default.forwardRef(({ avatars = [], max = 5, size = "
41
37
  const MotionDiv = enableAnimations ? motion.div : "div";
42
38
  const motionProps = enableAnimations
43
39
  ? {
44
- custom: {
45
- index,
46
- hoveredIndex,
47
- direction,
48
- totalPeople: visibleAvatars.length,
49
- },
50
40
  variants: getAvatarGroupVariants(shouldReduceMotion, enableAnimations),
51
41
  animate: getAnimationState(index, hoveredIndex, enableAnimations),
52
42
  onHoverStart: () => setHoveredIndex(index),
@@ -55,9 +45,7 @@ const AvatarGroup = React__default.forwardRef(({ avatars = [], max = 5, size = "
55
45
  : {};
56
46
  return (jsx(MotionDiv, { className: cn(
57
47
  // First avatar doesn't need negative margin
58
- index > 0 ? spacingClass : "z-10",
59
- // Apply hover z-index only when animations enabled
60
- index > 0 && spacingHoverClass), "data-position": position, "data-index": index, ...motionProps, children: jsx(Avatar, { size: size, ...avatarProps, contextualLabel: contextLabel,
48
+ index > 0 ? spacingClass : "z-10"), "data-position": position, "data-index": index, ...motionProps, children: jsx(Avatar, { size: size, ...avatarProps, contextualLabel: contextLabel,
61
49
  // Ensure that groupPosition is not passed to avoid conflicts
62
50
  groupPosition: undefined }) }, index));
63
51
  }), overflowCount > 0 && (jsx("div", { className: cn(spacingClass, enableAnimations &&
@@ -5,7 +5,6 @@ import { AvatarGroupSpacing } from "./AvatarGroup.types";
5
5
  interface AvatarGroupTheme {
6
6
  baseStyle: string;
7
7
  spacingStyles: Record<AvatarGroupSpacing, string>;
8
- spacingHoverStyles: Record<AvatarGroupSpacing, string>;
9
8
  overflowAvatarStyle: string;
10
9
  }
11
10
  /**
@@ -10,12 +10,6 @@ const avatarGroupTheme = {
10
10
  normal: "-ml-3 z-10",
11
11
  loose: "-ml-2 z-10",
12
12
  },
13
- // Hover z-index effects - applied separately when animations enabled
14
- spacingHoverStyles: {
15
- tight: "hover:z-20",
16
- normal: "hover:z-20",
17
- loose: "hover:z-20",
18
- },
19
13
  // Overflow avatar styles
20
14
  overflowAvatarStyle: "bg-[var(--color-neutral-100)] text-[var(--color-text-primary)] font-semibold text-sm flex items-center justify-center hover:bg-neutral-200 transition-colors duration-200",
21
15
  };