solid-tom-ui 1.0.10 → 1.0.14

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 (120) hide show
  1. package/README.md +246 -246
  2. package/dist/README.md +246 -246
  3. package/dist/components/avatar/avatar.js.map +1 -1
  4. package/dist/components/badge/badge.js.map +1 -1
  5. package/dist/components/breadcrumb/breadcrumb.js.map +1 -1
  6. package/dist/components/button/button.js.map +1 -1
  7. package/dist/components/carousel/carousel.js.map +1 -1
  8. package/dist/components/chat-bubble/chatBubble.js.map +1 -1
  9. package/dist/components/checkbox/checkbox.js.map +1 -1
  10. package/dist/components/collapse/collapse.js.map +1 -1
  11. package/dist/components/context-menu/context-menu.js.map +1 -1
  12. package/dist/components/context-menu/context-menu.store.js.map +1 -1
  13. package/dist/components/divider/divider.js.map +1 -1
  14. package/dist/components/dropdown/dropdown.js.map +1 -1
  15. package/dist/components/dropdown/dropdown.store.js.map +1 -1
  16. package/dist/components/float-button/float-button.js.map +1 -1
  17. package/dist/components/hover-3d-image/hover-3d-image.js.map +1 -1
  18. package/dist/components/image-preview/image-preview.js.map +1 -1
  19. package/dist/components/input/input.js.map +1 -1
  20. package/dist/components/input/input.utils.js.map +1 -1
  21. package/dist/components/input/variants/input-color.js.map +1 -1
  22. package/dist/components/input/variants/input-date.js.map +1 -1
  23. package/dist/components/input/variants/input-number.d.ts.map +1 -1
  24. package/dist/components/input/variants/input-number.js +1 -1
  25. package/dist/components/input/variants/input-number.js.map +1 -1
  26. package/dist/components/input/variants/input-otp.js.map +1 -1
  27. package/dist/components/input/variants/input-password.js.map +1 -1
  28. package/dist/components/input/variants/input-radio.js.map +1 -1
  29. package/dist/components/input/variants/input-range.js.map +1 -1
  30. package/dist/components/input/variants/input-text.d.ts.map +1 -1
  31. package/dist/components/input/variants/input-text.js +1 -1
  32. package/dist/components/input/variants/input-text.js.map +1 -1
  33. package/dist/components/input/variants/input-textarea.js.map +1 -1
  34. package/dist/components/loading/loading.js.map +1 -1
  35. package/dist/components/mansory/mansory.js.map +1 -1
  36. package/dist/components/menu/menu.js.map +1 -1
  37. package/dist/components/menu/menu.types.d.ts +2 -3
  38. package/dist/components/menu/menu.types.d.ts.map +1 -1
  39. package/dist/components/modal/modal.js.map +1 -1
  40. package/dist/components/modal/modalContext.js.map +1 -1
  41. package/dist/components/pagination/pagination.js.map +1 -1
  42. package/dist/components/progress-bar/progress-bar.js.map +1 -1
  43. package/dist/components/qr-code/qr-code.js.map +1 -1
  44. package/dist/components/select/select.js.map +1 -1
  45. package/dist/components/select-zone/select-zone.js.map +1 -1
  46. package/dist/components/skeleton/skeleton.js.map +1 -1
  47. package/dist/components/slider/slider.js.map +1 -1
  48. package/dist/components/splitter/splitter.js.map +1 -1
  49. package/dist/components/steps/steps.js.map +1 -1
  50. package/dist/components/swap/swap.js.map +1 -1
  51. package/dist/components/switch/switch.js.map +1 -1
  52. package/dist/components/tab/tab.js.map +1 -1
  53. package/dist/components/table/table.js.map +1 -1
  54. package/dist/components/timeline/timeline.js.map +1 -1
  55. package/dist/components/toast/icons/ErrorIcon.js.map +1 -1
  56. package/dist/components/toast/icons/IconCircle.js.map +1 -1
  57. package/dist/components/toast/icons/InfoIcon.js.map +1 -1
  58. package/dist/components/toast/icons/LoaderIcon.js.map +1 -1
  59. package/dist/components/toast/icons/SuccessIcon.js.map +1 -1
  60. package/dist/components/toast/icons/WarningIcon.js.map +1 -1
  61. package/dist/components/toast/toast.js.map +1 -1
  62. package/dist/components/toast/toast.store.js.map +1 -1
  63. package/dist/components/tooltip/tooltip.js.map +1 -1
  64. package/dist/components/tour/tour.js.map +1 -1
  65. package/dist/components/upload/upload.js.map +1 -1
  66. package/dist/components/z-index/z-index.context.js.map +1 -1
  67. package/dist/components/z-index/z-index.js.map +1 -1
  68. package/dist/components/z-index/z-index.store.js.map +1 -1
  69. package/dist/components/z-index/z-index.types.js.map +1 -1
  70. package/dist/package.json +1 -1
  71. package/dist/skill/avatar.skill.md.txt +255 -255
  72. package/dist/skill/badge.skill.md.txt +223 -223
  73. package/dist/skill/breadcrumb.skill.md.txt +177 -177
  74. package/dist/skill/button.skill.md.txt +198 -198
  75. package/dist/skill/carousel.skill.md.txt +406 -406
  76. package/dist/skill/chat-bubble.skill.md.txt +342 -342
  77. package/dist/skill/checkbox.skill.md.txt +326 -326
  78. package/dist/skill/code-preview.skill.md.txt +240 -240
  79. package/dist/skill/collapse.skill.md.txt +329 -329
  80. package/dist/skill/context-menu.skill.md.txt +233 -233
  81. package/dist/skill/diff.skill.md.txt +244 -244
  82. package/dist/skill/divider.skill.md.txt +151 -151
  83. package/dist/skill/doc.skill.md.txt +191 -191
  84. package/dist/skill/drawer.skill.md.txt +157 -157
  85. package/dist/skill/dropdown.skill.md.txt +198 -198
  86. package/dist/skill/float-button.skill.md.txt +315 -315
  87. package/dist/skill/hover-3d-image.skill.md.txt +120 -120
  88. package/dist/skill/iframe.skill.md.txt +114 -114
  89. package/dist/skill/image-preview.skill.md.txt +162 -162
  90. package/dist/skill/indicator.skill.md.txt +60 -60
  91. package/dist/skill/input.skill.md.txt +489 -489
  92. package/dist/skill/loading.skill.md.txt +127 -127
  93. package/dist/skill/menu.skill.md.txt +476 -476
  94. package/dist/skill/modal.skill.md.txt +359 -359
  95. package/dist/skill/pagination.skill.md.txt +405 -405
  96. package/dist/skill/progress-bar.skill.md.txt +207 -207
  97. package/dist/skill/qr-code.skill.md.txt +136 -136
  98. package/dist/skill/rating.skill.md.txt +167 -167
  99. package/dist/skill/select-zone.skill.md.txt +93 -93
  100. package/dist/skill/select.skill.md.txt +663 -663
  101. package/dist/skill/skeleton.skill.md.txt +192 -192
  102. package/dist/skill/slider.skill.md.txt +404 -404
  103. package/dist/skill/splitter.skill.md.txt +411 -411
  104. package/dist/skill/steps.skill.md.txt +264 -264
  105. package/dist/skill/swap.skill.md.txt +139 -139
  106. package/dist/skill/switch.skill.md.txt +191 -191
  107. package/dist/skill/tab.skill.md.txt +484 -484
  108. package/dist/skill/table.example.header.md.txt +666 -666
  109. package/dist/skill/table.skill.md.txt +1407 -1407
  110. package/dist/skill/text-rotate.skill.md.txt +186 -186
  111. package/dist/skill/timeline.skill.md.txt +247 -247
  112. package/dist/skill/toast.skill.md.txt +531 -531
  113. package/dist/skill/tooltip.skill.md.txt +222 -222
  114. package/dist/skill/tour.skill.md.txt +156 -156
  115. package/dist/skill/upload.skill.md.txt +358 -358
  116. package/dist/utils/cn.js.map +1 -1
  117. package/dist/utils/element-tracker.js.map +1 -1
  118. package/dist/utils/helper.js.map +1 -1
  119. package/dist/utils/hoc.js.map +1 -1
  120. package/package.json +132 -133
@@ -1,315 +1,315 @@
1
- ## COMPONENT IDENTITY
2
- - **Import**: `import { FloatButton } from 'solid-tom-ui';`
3
- - **Export**: `FloatButton` (named export)
4
- - **Framework**: SolidJS
5
- - **Purpose**: Fixed-position floating action button (FAB)
6
-
7
- ---
8
-
9
- ## TYPE SIGNATURE
10
-
11
- ```ts
12
- // ─── Shared base ────────────────────────────────────────────────
13
- type FloatButtonBaseProps = {
14
- color?: string; // any CSS color value or CSS variable; default: 'var(--color-warning)'
15
- size?: number; // button diameter in px; default: 24
16
- icon?: SolidComponent;
17
- animate?: 'ripple' | 'pulse' | 'bounce' | 'heartBeat' | 'headShake' | 'swing' | 'jello' | 'none';
18
- class?: string;
19
- onClickOpen?: (e: MouseEvent) => void;
20
- badge?: {
21
- count?: number;
22
- animate?: 'bounce' | 'heartBeat' | 'swing' | 'jello' | 'none';
23
- class?: string;
24
- };
25
- };
26
-
27
- type CloseIcon = {
28
- label: string;
29
- icon: SolidComponent;
30
- color?: string;
31
- onClickClose?: (e: MouseEvent) => void;
32
- };
33
-
34
- // ─── Discriminated union on `type` ──────────────────────────────
35
- type FloatButtonSingleProps = FloatButtonBaseProps & { type: 'single' };
36
- type FloatButtonDefaultProps = FloatButtonBaseProps & {
37
- type: 'default';
38
- actions?: SolidComponent[];
39
- closeIcon?: CloseIcon;
40
- };
41
- type FloatButtonFlowerProps = FloatButtonBaseProps & {
42
- type: 'flower';
43
- actions?: SolidComponent[];
44
- closeIcon?: CloseIcon;
45
- };
46
-
47
- export type FloatButtonProps =
48
- | FloatButtonSingleProps
49
- | FloatButtonDefaultProps
50
- | FloatButtonFlowerProps;
51
- ```
52
-
53
- ---
54
-
55
- ## DEFAULT VALUES (applied via `mergeProps`)
56
-
57
- | Prop | Default |
58
- | ----------------- | ------------------------ |
59
- | `type` | `'default'` |
60
- | `color` | `'var(--color-warning)'` |
61
- | `size` | `24` |
62
- | `animate` | `'none'` |
63
- | `closeIcon.label` | `'Close'` |
64
- | `closeIcon.icon` | `'X'` |
65
-
66
- ---
67
-
68
- ## PROP REFERENCE
69
-
70
- | Prop | Type | Required | Description |
71
- | ------------------------ | ----------------------------------------------------------------------------------------------- | ------------------------------- | --------------------------------------------------------------------------- |
72
- | `type` | `'single' \| 'default' \| 'flower'` | ✅ YES | Controls which FAB variant is rendered (see Type Variants below) |
73
- | `icon` | `SolidComponent` | ❌ NO | Icon rendered inside the main trigger button |
74
- | `color` | `string` | ❌ NO | Background color of the main button — any CSS color or CSS variable |
75
- | `size` | `number` | ❌ NO | Diameter of main button in px (applied to both `width` and `height`) |
76
- | `animate` | `'ripple' \| 'pulse' \| 'bounce' \| 'heartBeat' \| 'headShake' \| 'swing' \| 'jello' \| 'none'` | ❌ NO | Infinite animation applied to the main button |
77
- | `class` | `string` | ❌ NO | Extra Tailwind classes on the root wrapper div (use for position overrides) |
78
- | `onClickOpen` | `(e: MouseEvent) => void` | ❌ NO | Click handler on the main button |
79
- | `badge.count` | `number` | ❌ NO | Number shown in the red badge bubble on the main button |
80
- | `badge.animate` | `'bounce' \| 'heartBeat' \| 'swing' \| 'jello' \| 'none'` | ❌ NO | Animation applied to the badge bubble |
81
- | `badge.class` | `string` | ❌ NO | Extra classes on the badge div (e.g. override background color) |
82
- | `actions` | `SolidComponent[]` | ❌ NO (`default`/`flower` only) | Array of action items shown when FAB is opened |
83
- | `closeIcon.label` | `string` | ❌ NO (`default`/`flower` only) | Text label next to the close button (shown in `default` type) |
84
- | `closeIcon.icon` | `SolidComponent` | ❌ NO (`default`/`flower` only) | Icon inside the close button |
85
- | `closeIcon.color` | `string` | ❌ NO | Color override for the close button |
86
- | `closeIcon.onClickClose` | `(e: MouseEvent) => void` | ❌ NO | Click handler on the close button |
87
-
88
- ---
89
-
90
- ## TYPE VARIANTS — Detailed behavior per `type`
91
-
92
- ### `type="single"`
93
-
94
- - Renders **only** the main trigger button — no menu, no close button, no actions
95
- - `actions` and `closeIcon` props are **unavailable** (TypeScript enforces this)
96
- - Clicking is handled entirely by `onClickOpen`
97
- - Best for: back-to-top, open chat, single-action triggers
98
-
99
- ```tsx
100
- <FloatButton
101
- type="single"
102
- size={40}
103
- icon={<ArrowUp color="white" size={20} />}
104
- color="var(--color-primary)"
105
- animate="heartBeat"
106
- onClickOpen={() => window.scrollTo({ top: 0, behavior: 'smooth' })}
107
- badge={{ count: 3, animate: 'bounce' }}
108
- />
109
- ```
110
-
111
- ---
112
-
113
- ### `type="default"`
114
-
115
- - Renders main button + **vertical list menu** of action items
116
- - Menu opens on hover/focus (`tabIndex={0}` on inner div)
117
- - `actions` array: each item renders as `<div class="flex gap-2">{item}</div>` — items can be any JSX (Button, custom div, etc.)
118
- - `closeIcon.label` is shown as text **next to** the close button (unique to this type)
119
- - No hard limit on `actions` length
120
-
121
- ```tsx
122
- <FloatButton
123
- type="default"
124
- size={40}
125
- icon={<Plus color="white" size={20} />}
126
- color="red"
127
- closeIcon={{
128
- label: 'Close',
129
- icon: 'X',
130
- onClickClose: () => console.log('closed'),
131
- }}
132
- actions={[
133
- <Button variant="solid" color="neutral" icon={<Activity color="white" size={20} />}>
134
- Activity
135
- </Button>,
136
- <div class="flex items-center gap-2">
137
- <span>With Label</span>
138
- <Button variant="solid" color="error" icon="C" shape="square" />
139
- </div>,
140
- ]}
141
- badge={{ count: 500, class: 'bg-primary' }}
142
- />
143
- ```
144
-
145
- ---
146
-
147
- ### `type="flower"`
148
-
149
- - Renders main button + **radial/flower menu** of action items spreading outward
150
- - Root div gets additional class `fab-flower`
151
- - `actions` array: items rendered **directly** without a wrapping flex div
152
- - **HARD LIMIT: maximum 4 items in `actions`** — items beyond index 3 are silently dropped with a `console.warn`
153
- - Use `shape="circle"` Buttons inside `actions` to preserve the circular flower layout
154
-
155
- ```tsx
156
- <FloatButton
157
- type="flower"
158
- size={40}
159
- icon={<Plus color="white" size={20} />}
160
- color="orange"
161
- closeIcon={{ label: 'Close', icon: 'X', onClickClose: () => {} }}
162
- actions={[
163
- <Button variant="solid" color="neutral" shape="circle" icon="A" />,
164
- <Button variant="solid" color="primary" shape="circle" icon="B" />,
165
- <Button variant="solid" color="error" shape="circle" icon="C" />,
166
- <Button variant="solid" color="accent" shape="circle" icon="D" />,
167
- // ⛔ 5th item would be dropped — console.warn fired
168
- ]}
169
- />
170
- ```
171
-
172
- ---
173
-
174
- ## ANIMATION REFERENCE
175
-
176
- ### Main button (`animate` prop)
177
-
178
- | Value | CSS class applied |
179
- | ------------- | ------------------- |
180
- | `'ripple'` | `animate-ripple` |
181
- | `'pulse'` | `animate-pulse` |
182
- | `'bounce'` | `animate-bounce` |
183
- | `'heartBeat'` | `animate-heartBeat` |
184
- | `'headShake'` | `animate-headShake` |
185
- | `'swing'` | `animate-swing` |
186
- | `'jello'` | `animate-jello` |
187
- | `'none'` | _(no class)_ |
188
-
189
- ### Badge (`badge.animate` prop)
190
-
191
- Applies `animate-{value}` class directly to the badge div. Supports: `bounce`, `heartBeat`, `swing`, `jello`, `none`.
192
-
193
- ---
194
-
195
- ## BADGE SIZING — Automatic width adjustment
196
-
197
- The badge width adapts to `badge.count` automatically:
198
- | Count range | Applied classes |
199
- |-----------------|--------------------------------------|
200
- | `< 100` | `w-5` (fixed circle) |
201
- | `100 – 999` | `px-1` (pill shape) |
202
- | `1000 – 9999` | `px-1 translate-x-1 -translate-y-1` |
203
- | `≥ 10000` | `px-1 translate-x-2` |
204
-
205
- Agents do NOT need to handle badge sizing — it is automatic.
206
-
207
- ---
208
-
209
- ## POSITIONING
210
-
211
- - The component renders with class `fab` by default. CSS for `.fab` is defined in `mockup.style.css` / project global styles.
212
- - Default position is typically `bottom-right` (defined by `.fab` global CSS).
213
- - To override position, use the `class` prop with Tailwind positioning utilities:
214
-
215
- ```tsx
216
- // Move to bottom-left
217
- <FloatButton type="single" class="bottom-10 left-10" ... />
218
-
219
- // Move to top-right
220
- <FloatButton type="single" class="top-10 right-10" ... />
221
- ```
222
-
223
- ---
224
-
225
- ## BEHAVIOR NOTES FOR AGENTS
226
-
227
- 1. **`type` is a discriminated union** — TypeScript will error if `actions` or `closeIcon` are passed to `type="single"`. Only pass those props to `type="default"` or `type="flower"`.
228
-
229
- 2. **Menu open/close is CSS-driven** — the `.fab` class uses CSS (`:focus-within`, `:hover`) to toggle the menu visibility. There is no JS open/close state. `onClickOpen` is only an additional callback, not the toggle mechanism.
230
-
231
- 3. **`color` sets both `background-color` and CSS custom properties** — internally it sets `--innner-color` and `--btn-color` on the button's inline style. Any value valid in CSS works: named colors, hex, rgb, hsl, `var(--css-variable)`.
232
-
233
- 4. **`size` is in pixels as a `number`** — internally converted to `"${size}px"` string. Do NOT pass a string like `"40px"`.
234
-
235
- 5. **`flower` type silently drops items beyond index 3** — a `console.warn` is fired but no error is thrown. Always cap `actions` at 4 items for `type="flower"`.
236
-
237
- 6. **`actions` in `default` type wrap each item in `<div class="flex gap-2">`** — items can be any JSX shape (Button, span+Button, div, etc.). Items in `flower` type are rendered without any wrapper.
238
-
239
- 7. **Badge only renders when `badge.count` is truthy** — passing `badge={{ count: 0 }}` will NOT render a badge (0 is falsy).
240
-
241
- 8. **Main button always has `shape="circle"`** — this cannot be changed via props.
242
-
243
- ---
244
-
245
- ## COMMON MISTAKES TO AVOID
246
-
247
- | Mistake | Correct approach |
248
- | --------------------------------------------------- | --------------------------------------------------------------------- |
249
- | Passing `actions` to `type="single"` | `single` has no menu — use `type="default"` or `type="flower"` |
250
- | Passing `size="40px"` (string) | `size` is a `number` — pass `size={40}` |
251
- | Adding more than 4 items to `type="flower"` actions | Cap at 4 — excess items are silently dropped |
252
- | Using non-circle Buttons in `type="flower"` actions | Always use `shape="circle"` for flower layout integrity |
253
- | Expecting `onClickOpen` to toggle the menu | Menu toggle is CSS-only; `onClickOpen` is a side-effect callback only |
254
- | Setting `badge={{ count: 0 }}` expecting a badge | `0` is falsy — badge will not render; use a positive number |
255
- | Passing CSS string to `size` | `size` expects `number` (px unit is appended internally) |
256
-
257
- ---
258
-
259
- ## FULL EXAMPLE — All three variants
260
-
261
- ```tsx
262
- import { FloatButton, Button } from 'solid-tom-ui';
263
- import { Plus, ArrowUp, Activity } from 'lucide-solid';
264
-
265
- // 1. Single — one-action FAB
266
- <FloatButton
267
- type="single"
268
- size={40}
269
- icon={<ArrowUp color="white" size={20} />}
270
- color="var(--color-primary)"
271
- animate="bounce"
272
- onClickOpen={() => window.scrollTo({ top: 0, behavior: 'smooth' })}
273
- />
274
-
275
- // 2. Default — vertical menu
276
- <FloatButton
277
- type="default"
278
- size={44}
279
- icon={<Plus color="white" size={22} />}
280
- color="#e74c3c"
281
- animate="ripple"
282
- closeIcon={{ label: 'Close', icon: 'X', onClickClose: () => {} }}
283
- actions={[
284
- <Button variant="solid" color="neutral" icon={<Activity color="white" size={18} />}>
285
- Analytics
286
- </Button>,
287
- <Button variant="solid" color="primary">
288
- Settings
289
- </Button>,
290
- ]}
291
- badge={{ count: 12, animate: 'heartBeat', class: 'bg-error' }}
292
- />
293
-
294
- // 3. Flower — radial menu (max 4 actions, circle buttons)
295
- <FloatButton
296
- type="flower"
297
- size={44}
298
- icon={<Plus color="white" size={22} />}
299
- color="orange"
300
- closeIcon={{ label: 'Close', icon: 'X', onClickClose: () => {} }}
301
- actions={[
302
- <Button variant="solid" color="neutral" shape="circle" icon="A" />,
303
- <Button variant="solid" color="primary" shape="circle" icon="B" />,
304
- <Button variant="solid" color="error" shape="circle" icon="C" />,
305
- <Button variant="solid" color="accent" shape="circle" icon="D" />,
306
- ]}
307
- />
308
- ```
309
- ---
310
-
311
- ## Component Conventions
312
-
313
- > **CSS encoding**: internal CSS classes use short encoded names (e.g. `fb01`, `fb02`) per project convention.
314
-
315
- > **Unique IDs**: if this component needs to generate HTML `id` attributes, always use `createUniqueId()` from `solid-js` — never `Math.random()` or `Date.now()`.
1
+ ## COMPONENT IDENTITY
2
+ - **Import**: `import { FloatButton } from 'solid-tom-ui';`
3
+ - **Export**: `FloatButton` (named export)
4
+ - **Framework**: SolidJS
5
+ - **Purpose**: Fixed-position floating action button (FAB)
6
+
7
+ ---
8
+
9
+ ## TYPE SIGNATURE
10
+
11
+ ```ts
12
+ // ─── Shared base ────────────────────────────────────────────────
13
+ type FloatButtonBaseProps = {
14
+ color?: string; // any CSS color value or CSS variable; default: 'var(--color-warning)'
15
+ size?: number; // button diameter in px; default: 24
16
+ icon?: SolidComponent;
17
+ animate?: 'ripple' | 'pulse' | 'bounce' | 'heartBeat' | 'headShake' | 'swing' | 'jello' | 'none';
18
+ class?: string;
19
+ onClickOpen?: (e: MouseEvent) => void;
20
+ badge?: {
21
+ count?: number;
22
+ animate?: 'bounce' | 'heartBeat' | 'swing' | 'jello' | 'none';
23
+ class?: string;
24
+ };
25
+ };
26
+
27
+ type CloseIcon = {
28
+ label: string;
29
+ icon: SolidComponent;
30
+ color?: string;
31
+ onClickClose?: (e: MouseEvent) => void;
32
+ };
33
+
34
+ // ─── Discriminated union on `type` ──────────────────────────────
35
+ type FloatButtonSingleProps = FloatButtonBaseProps & { type: 'single' };
36
+ type FloatButtonDefaultProps = FloatButtonBaseProps & {
37
+ type: 'default';
38
+ actions?: SolidComponent[];
39
+ closeIcon?: CloseIcon;
40
+ };
41
+ type FloatButtonFlowerProps = FloatButtonBaseProps & {
42
+ type: 'flower';
43
+ actions?: SolidComponent[];
44
+ closeIcon?: CloseIcon;
45
+ };
46
+
47
+ export type FloatButtonProps =
48
+ | FloatButtonSingleProps
49
+ | FloatButtonDefaultProps
50
+ | FloatButtonFlowerProps;
51
+ ```
52
+
53
+ ---
54
+
55
+ ## DEFAULT VALUES (applied via `mergeProps`)
56
+
57
+ | Prop | Default |
58
+ | ----------------- | ------------------------ |
59
+ | `type` | `'default'` |
60
+ | `color` | `'var(--color-warning)'` |
61
+ | `size` | `24` |
62
+ | `animate` | `'none'` |
63
+ | `closeIcon.label` | `'Close'` |
64
+ | `closeIcon.icon` | `'X'` |
65
+
66
+ ---
67
+
68
+ ## PROP REFERENCE
69
+
70
+ | Prop | Type | Required | Description |
71
+ | ------------------------ | ----------------------------------------------------------------------------------------------- | ------------------------------- | --------------------------------------------------------------------------- |
72
+ | `type` | `'single' \| 'default' \| 'flower'` | ✅ YES | Controls which FAB variant is rendered (see Type Variants below) |
73
+ | `icon` | `SolidComponent` | ❌ NO | Icon rendered inside the main trigger button |
74
+ | `color` | `string` | ❌ NO | Background color of the main button — any CSS color or CSS variable |
75
+ | `size` | `number` | ❌ NO | Diameter of main button in px (applied to both `width` and `height`) |
76
+ | `animate` | `'ripple' \| 'pulse' \| 'bounce' \| 'heartBeat' \| 'headShake' \| 'swing' \| 'jello' \| 'none'` | ❌ NO | Infinite animation applied to the main button |
77
+ | `class` | `string` | ❌ NO | Extra Tailwind classes on the root wrapper div (use for position overrides) |
78
+ | `onClickOpen` | `(e: MouseEvent) => void` | ❌ NO | Click handler on the main button |
79
+ | `badge.count` | `number` | ❌ NO | Number shown in the red badge bubble on the main button |
80
+ | `badge.animate` | `'bounce' \| 'heartBeat' \| 'swing' \| 'jello' \| 'none'` | ❌ NO | Animation applied to the badge bubble |
81
+ | `badge.class` | `string` | ❌ NO | Extra classes on the badge div (e.g. override background color) |
82
+ | `actions` | `SolidComponent[]` | ❌ NO (`default`/`flower` only) | Array of action items shown when FAB is opened |
83
+ | `closeIcon.label` | `string` | ❌ NO (`default`/`flower` only) | Text label next to the close button (shown in `default` type) |
84
+ | `closeIcon.icon` | `SolidComponent` | ❌ NO (`default`/`flower` only) | Icon inside the close button |
85
+ | `closeIcon.color` | `string` | ❌ NO | Color override for the close button |
86
+ | `closeIcon.onClickClose` | `(e: MouseEvent) => void` | ❌ NO | Click handler on the close button |
87
+
88
+ ---
89
+
90
+ ## TYPE VARIANTS — Detailed behavior per `type`
91
+
92
+ ### `type="single"`
93
+
94
+ - Renders **only** the main trigger button — no menu, no close button, no actions
95
+ - `actions` and `closeIcon` props are **unavailable** (TypeScript enforces this)
96
+ - Clicking is handled entirely by `onClickOpen`
97
+ - Best for: back-to-top, open chat, single-action triggers
98
+
99
+ ```tsx
100
+ <FloatButton
101
+ type="single"
102
+ size={40}
103
+ icon={<ArrowUp color="white" size={20} />}
104
+ color="var(--color-primary)"
105
+ animate="heartBeat"
106
+ onClickOpen={() => window.scrollTo({ top: 0, behavior: 'smooth' })}
107
+ badge={{ count: 3, animate: 'bounce' }}
108
+ />
109
+ ```
110
+
111
+ ---
112
+
113
+ ### `type="default"`
114
+
115
+ - Renders main button + **vertical list menu** of action items
116
+ - Menu opens on hover/focus (`tabIndex={0}` on inner div)
117
+ - `actions` array: each item renders as `<div class="flex gap-2">{item}</div>` — items can be any JSX (Button, custom div, etc.)
118
+ - `closeIcon.label` is shown as text **next to** the close button (unique to this type)
119
+ - No hard limit on `actions` length
120
+
121
+ ```tsx
122
+ <FloatButton
123
+ type="default"
124
+ size={40}
125
+ icon={<Plus color="white" size={20} />}
126
+ color="red"
127
+ closeIcon={{
128
+ label: 'Close',
129
+ icon: 'X',
130
+ onClickClose: () => console.log('closed'),
131
+ }}
132
+ actions={[
133
+ <Button variant="solid" color="neutral" icon={<Activity color="white" size={20} />}>
134
+ Activity
135
+ </Button>,
136
+ <div class="flex items-center gap-2">
137
+ <span>With Label</span>
138
+ <Button variant="solid" color="error" icon="C" shape="square" />
139
+ </div>,
140
+ ]}
141
+ badge={{ count: 500, class: 'bg-primary' }}
142
+ />
143
+ ```
144
+
145
+ ---
146
+
147
+ ### `type="flower"`
148
+
149
+ - Renders main button + **radial/flower menu** of action items spreading outward
150
+ - Root div gets additional class `fab-flower`
151
+ - `actions` array: items rendered **directly** without a wrapping flex div
152
+ - **HARD LIMIT: maximum 4 items in `actions`** — items beyond index 3 are silently dropped with a `console.warn`
153
+ - Use `shape="circle"` Buttons inside `actions` to preserve the circular flower layout
154
+
155
+ ```tsx
156
+ <FloatButton
157
+ type="flower"
158
+ size={40}
159
+ icon={<Plus color="white" size={20} />}
160
+ color="orange"
161
+ closeIcon={{ label: 'Close', icon: 'X', onClickClose: () => {} }}
162
+ actions={[
163
+ <Button variant="solid" color="neutral" shape="circle" icon="A" />,
164
+ <Button variant="solid" color="primary" shape="circle" icon="B" />,
165
+ <Button variant="solid" color="error" shape="circle" icon="C" />,
166
+ <Button variant="solid" color="accent" shape="circle" icon="D" />,
167
+ // ⛔ 5th item would be dropped — console.warn fired
168
+ ]}
169
+ />
170
+ ```
171
+
172
+ ---
173
+
174
+ ## ANIMATION REFERENCE
175
+
176
+ ### Main button (`animate` prop)
177
+
178
+ | Value | CSS class applied |
179
+ | ------------- | ------------------- |
180
+ | `'ripple'` | `animate-ripple` |
181
+ | `'pulse'` | `animate-pulse` |
182
+ | `'bounce'` | `animate-bounce` |
183
+ | `'heartBeat'` | `animate-heartBeat` |
184
+ | `'headShake'` | `animate-headShake` |
185
+ | `'swing'` | `animate-swing` |
186
+ | `'jello'` | `animate-jello` |
187
+ | `'none'` | _(no class)_ |
188
+
189
+ ### Badge (`badge.animate` prop)
190
+
191
+ Applies `animate-{value}` class directly to the badge div. Supports: `bounce`, `heartBeat`, `swing`, `jello`, `none`.
192
+
193
+ ---
194
+
195
+ ## BADGE SIZING — Automatic width adjustment
196
+
197
+ The badge width adapts to `badge.count` automatically:
198
+ | Count range | Applied classes |
199
+ |-----------------|--------------------------------------|
200
+ | `< 100` | `w-5` (fixed circle) |
201
+ | `100 – 999` | `px-1` (pill shape) |
202
+ | `1000 – 9999` | `px-1 translate-x-1 -translate-y-1` |
203
+ | `≥ 10000` | `px-1 translate-x-2` |
204
+
205
+ Agents do NOT need to handle badge sizing — it is automatic.
206
+
207
+ ---
208
+
209
+ ## POSITIONING
210
+
211
+ - The component renders with class `fab` by default. CSS for `.fab` is defined in `mockup.style.css` / project global styles.
212
+ - Default position is typically `bottom-right` (defined by `.fab` global CSS).
213
+ - To override position, use the `class` prop with Tailwind positioning utilities:
214
+
215
+ ```tsx
216
+ // Move to bottom-left
217
+ <FloatButton type="single" class="bottom-10 left-10" ... />
218
+
219
+ // Move to top-right
220
+ <FloatButton type="single" class="top-10 right-10" ... />
221
+ ```
222
+
223
+ ---
224
+
225
+ ## BEHAVIOR NOTES FOR AGENTS
226
+
227
+ 1. **`type` is a discriminated union** — TypeScript will error if `actions` or `closeIcon` are passed to `type="single"`. Only pass those props to `type="default"` or `type="flower"`.
228
+
229
+ 2. **Menu open/close is CSS-driven** — the `.fab` class uses CSS (`:focus-within`, `:hover`) to toggle the menu visibility. There is no JS open/close state. `onClickOpen` is only an additional callback, not the toggle mechanism.
230
+
231
+ 3. **`color` sets both `background-color` and CSS custom properties** — internally it sets `--innner-color` and `--btn-color` on the button's inline style. Any value valid in CSS works: named colors, hex, rgb, hsl, `var(--css-variable)`.
232
+
233
+ 4. **`size` is in pixels as a `number`** — internally converted to `"${size}px"` string. Do NOT pass a string like `"40px"`.
234
+
235
+ 5. **`flower` type silently drops items beyond index 3** — a `console.warn` is fired but no error is thrown. Always cap `actions` at 4 items for `type="flower"`.
236
+
237
+ 6. **`actions` in `default` type wrap each item in `<div class="flex gap-2">`** — items can be any JSX shape (Button, span+Button, div, etc.). Items in `flower` type are rendered without any wrapper.
238
+
239
+ 7. **Badge only renders when `badge.count` is truthy** — passing `badge={{ count: 0 }}` will NOT render a badge (0 is falsy).
240
+
241
+ 8. **Main button always has `shape="circle"`** — this cannot be changed via props.
242
+
243
+ ---
244
+
245
+ ## COMMON MISTAKES TO AVOID
246
+
247
+ | Mistake | Correct approach |
248
+ | --------------------------------------------------- | --------------------------------------------------------------------- |
249
+ | Passing `actions` to `type="single"` | `single` has no menu — use `type="default"` or `type="flower"` |
250
+ | Passing `size="40px"` (string) | `size` is a `number` — pass `size={40}` |
251
+ | Adding more than 4 items to `type="flower"` actions | Cap at 4 — excess items are silently dropped |
252
+ | Using non-circle Buttons in `type="flower"` actions | Always use `shape="circle"` for flower layout integrity |
253
+ | Expecting `onClickOpen` to toggle the menu | Menu toggle is CSS-only; `onClickOpen` is a side-effect callback only |
254
+ | Setting `badge={{ count: 0 }}` expecting a badge | `0` is falsy — badge will not render; use a positive number |
255
+ | Passing CSS string to `size` | `size` expects `number` (px unit is appended internally) |
256
+
257
+ ---
258
+
259
+ ## FULL EXAMPLE — All three variants
260
+
261
+ ```tsx
262
+ import { FloatButton, Button } from 'solid-tom-ui';
263
+ import { Plus, ArrowUp, Activity } from 'lucide-solid';
264
+
265
+ // 1. Single — one-action FAB
266
+ <FloatButton
267
+ type="single"
268
+ size={40}
269
+ icon={<ArrowUp color="white" size={20} />}
270
+ color="var(--color-primary)"
271
+ animate="bounce"
272
+ onClickOpen={() => window.scrollTo({ top: 0, behavior: 'smooth' })}
273
+ />
274
+
275
+ // 2. Default — vertical menu
276
+ <FloatButton
277
+ type="default"
278
+ size={44}
279
+ icon={<Plus color="white" size={22} />}
280
+ color="#e74c3c"
281
+ animate="ripple"
282
+ closeIcon={{ label: 'Close', icon: 'X', onClickClose: () => {} }}
283
+ actions={[
284
+ <Button variant="solid" color="neutral" icon={<Activity color="white" size={18} />}>
285
+ Analytics
286
+ </Button>,
287
+ <Button variant="solid" color="primary">
288
+ Settings
289
+ </Button>,
290
+ ]}
291
+ badge={{ count: 12, animate: 'heartBeat', class: 'bg-error' }}
292
+ />
293
+
294
+ // 3. Flower — radial menu (max 4 actions, circle buttons)
295
+ <FloatButton
296
+ type="flower"
297
+ size={44}
298
+ icon={<Plus color="white" size={22} />}
299
+ color="orange"
300
+ closeIcon={{ label: 'Close', icon: 'X', onClickClose: () => {} }}
301
+ actions={[
302
+ <Button variant="solid" color="neutral" shape="circle" icon="A" />,
303
+ <Button variant="solid" color="primary" shape="circle" icon="B" />,
304
+ <Button variant="solid" color="error" shape="circle" icon="C" />,
305
+ <Button variant="solid" color="accent" shape="circle" icon="D" />,
306
+ ]}
307
+ />
308
+ ```
309
+ ---
310
+
311
+ ## Component Conventions
312
+
313
+ > **CSS encoding**: internal CSS classes use short encoded names (e.g. `fb01`, `fb02`) per project convention.
314
+
315
+ > **Unique IDs**: if this component needs to generate HTML `id` attributes, always use `createUniqueId()` from `solid-js` — never `Math.random()` or `Date.now()`.