aural-ui 4.0.1 → 4.1.0
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.
- package/dist/components/aspect-ratio/AspectRatio.stories.tsx +290 -1228
- package/dist/components/avatar/Avatar.stories.tsx +219 -235
- package/dist/components/badge/Badge.stories.tsx +379 -116
- package/dist/components/banner/Banner.stories.tsx +445 -391
- package/dist/components/breadcrumb/Breadcrumb.stories.tsx +453 -199
- package/dist/components/button/Button.stories.tsx +585 -230
- package/dist/components/card/Card.stories.tsx +619 -301
- package/dist/components/char-count/CharCount.stories.tsx +350 -248
- package/dist/components/checkbox/Checkbox.stories.tsx +309 -167
- package/dist/components/chip/Chip.stories.tsx +362 -168
- package/dist/components/circular-loader/CircularLoader.stories.tsx +221 -636
- package/dist/components/clamp-lines/ClampLines.stories.tsx +246 -117
- package/dist/components/collapsible/Collapsible.stories.tsx +391 -252
- package/dist/components/command/Command.stories.tsx +530 -867
- package/dist/components/dialog/Dialog.stories.tsx +501 -950
- package/dist/components/divider/Divider.stories.tsx +264 -527
- package/dist/components/dot-loader/DotLoader.stories.tsx +256 -257
- package/dist/components/drawer/Drawer.stories.tsx +659 -1023
- package/dist/components/dropdown/Dropdown.stories.tsx +643 -1028
- package/dist/components/form/Form.stories.tsx +560 -274
- package/dist/components/helper-text/HelperText.stories.tsx +199 -200
- package/dist/components/hover-card/HoverCard.stories.tsx +318 -1254
- package/dist/components/icon-button/IconButton.stories.tsx +837 -194
- package/dist/components/if-else/if-else.stories.tsx +370 -83
- package/dist/components/input/Input.stories.tsx +436 -368
- package/dist/components/label/Label.stories.tsx +156 -154
- package/dist/components/list/List.stories.tsx +484 -835
- package/dist/components/marquee/Marquee.stories.tsx +356 -712
- package/dist/components/otp-inputs/OtpInputs.stories.tsx +352 -422
- package/dist/components/overlay/Overlay.stories.tsx +452 -824
- package/dist/components/pagination/Pagination.stories.tsx +721 -210
- package/dist/components/popover/Popover.stories.tsx +481 -896
- package/dist/components/radio/Radio.stories.tsx +432 -124
- package/dist/components/resizable/Resizable.stories.tsx +495 -799
- package/dist/components/scroll-area/ScrollArea.stories.tsx +383 -1059
- package/dist/components/search/Search.stories.tsx +312 -595
- package/dist/components/select/Select.stories.tsx +684 -789
- package/dist/components/sheet/Sheet.stories.tsx +671 -950
- package/dist/components/skelton/Skelton.stories.tsx +230 -764
- package/dist/components/slider/Slider.stories.tsx +383 -760
- package/dist/components/stepper/Stepper.stories.tsx +371 -514
- package/dist/components/switch/Switch.stories.tsx +461 -208
- package/dist/components/switch-case/SwitchCase.stories.tsx +367 -188
- package/dist/components/table/Table.stories.tsx +770 -916
- package/dist/components/tabs/Tabs.stories.tsx +458 -1455
- package/dist/components/tag/Tag.stories.tsx +714 -542
- package/dist/components/textarea/TextArea.stories.tsx +621 -562
- package/dist/components/thumbnail-tags/ThumbnailTags.stories.tsx +228 -154
- package/dist/components/toast/Toast.stories.tsx +452 -1339
- package/dist/components/toggle/Toggle.stories.tsx +488 -931
- package/dist/components/tooltip/Tooltip.stories.tsx +344 -1388
- package/dist/components/typography/Typography.stories.tsx +406 -89
- package/dist/hooks/use-change-state/UseChangeState.stories.tsx +309 -606
- package/dist/hooks/use-previous/UsePrevious.stories.tsx +367 -917
- package/dist/hooks/use-standalone-pagination/UseStandalonePagination.stories.tsx +639 -867
- package/dist/icons/Icons.stories.tsx +0 -12
- package/dist/icons/ai-avatar-icon/AiAvatarIcon.stories.tsx +223 -1060
- package/dist/icons/alert-icon/AlertIcon.stories.tsx +106 -968
- package/dist/icons/all-icons.tsx +37 -16
- package/dist/icons/angle-down-icon/AngleDownIcon.stories.tsx +137 -1010
- package/dist/icons/apple-logo-icon/AppleLogoIcon.stories.tsx +145 -935
- package/dist/icons/arrow-box-left-icon/ArrowBoxLeftIcon.stories.tsx +132 -1046
- package/dist/icons/arrow-corner-up-left-icon/ArrowCornerUpLeftIcon.stories.tsx +134 -986
- package/dist/icons/arrow-corner-up-right-icon/ArrowCornerUpRightIcon.stories.tsx +135 -1028
- package/dist/icons/arrow-left-icon/ArrowLeftIcon.stories.tsx +133 -971
- package/dist/icons/arrow-right-icon/ArrowRightIcon.stories.tsx +145 -1123
- package/dist/icons/arrow-right-up-icon/ArrowRightUpIcon.stories.tsx +143 -1252
- package/dist/icons/art-board-icon/ArtBoardIcon.stories.tsx +123 -632
- package/dist/icons/audio-bar-icon/AudioBarIcon.stories.tsx +141 -1223
- package/dist/icons/backward-ten-seconds-icon/BackwardTenSecondsIcon.stories.tsx +164 -1018
- package/dist/icons/bubble-check-icon/BubbleCheckIcon.stories.tsx +121 -1236
- package/dist/icons/bubble-crossed-icon/BubbleCrossedIcon.stories.tsx +121 -1213
- package/dist/icons/bubble-sparkle-icon/BubbleSparkleIcon.stories.tsx +116 -893
- package/dist/icons/camera-icon/CameraIcon.stories.tsx +109 -1254
- package/dist/icons/capital-a-letter-icon/CapitalALetterIcon.stories.tsx +114 -975
- package/dist/icons/chevron-double-left-icon/ChevronDoubleLeftIcon.stories.tsx +157 -994
- package/dist/icons/chevron-double-right-icon/ChevronDoubleRightIcon.stories.tsx +160 -992
- package/dist/icons/chevron-down-icon/ChevronDownIcon.stories.tsx +140 -970
- package/dist/icons/chevron-left-icon/ChevronLeftIcon.stories.tsx +126 -993
- package/dist/icons/chevron-right-icon/ChevronRightIcon.stories.tsx +144 -987
- package/dist/icons/chevron-up-icon/ChevronUpIcon.stories.tsx +141 -1007
- package/dist/icons/circle-tick-icon/CircleTickIcon.stories.tsx +147 -1187
- package/dist/icons/circular-play-icon/CircularPlayIcon.stories.tsx +110 -476
- package/dist/icons/coin-icon/CoinIcon.stories.tsx +120 -1364
- package/dist/icons/coin-toons-icon/CoinToonsIcon.stories.tsx +113 -1360
- package/dist/icons/column-wide-add-icon/ColumnWideAddIcon.stories.tsx +111 -942
- package/dist/icons/command-icon/CommandIcon.stories.tsx +124 -1087
- package/dist/icons/copy-icon/CopyIcon.stories.tsx +119 -996
- package/dist/icons/cross-circle-icon/CrossCircleIcon.stories.tsx +144 -1046
- package/dist/icons/cross-icon/CrossIcon.stories.tsx +136 -999
- package/dist/icons/download-icon/DownloadIcon.stories.tsx +123 -857
- package/dist/icons/edit-big-icon/EditBigIcon.stories.tsx +121 -1080
- package/dist/icons/email-icon/EmailIcon.stories.tsx +112 -979
- package/dist/icons/expand-icon/ExpandIcon.stories.tsx +109 -1146
- package/dist/icons/eye-close-icon/EyeCloseIcon.stories.tsx +141 -1068
- package/dist/icons/eye-open-icon/EyeOpenIcon.stories.tsx +140 -1081
- package/dist/icons/feature-shine-icon/FeatureShineIcon.stories.tsx +124 -1050
- package/dist/icons/file-chart-icon/FileChartIcon.stories.tsx +123 -1091
- package/dist/icons/file-text-icon/FileTextIcon.stories.tsx +122 -633
- package/dist/icons/filter-bar-row-icon/FilterBarRowIcon.stories.tsx +116 -1087
- package/dist/icons/forward-ten-seconds-icon/ForwardTenSecondsIcon.stories.tsx +166 -1020
- package/dist/icons/git-branch-icon/GitBranchIcon.stories.tsx +112 -1182
- package/dist/icons/git-fork-icon/GitForkIcon.stories.tsx +112 -1155
- package/dist/icons/globe-icon/GlobeIcon.stories.tsx +127 -325
- package/dist/icons/google-logo-icon/GoogleLogoIcon.stories.tsx +142 -985
- package/dist/icons/grip-vertical-icon/GripVerticalIcon.stories.tsx +116 -1217
- package/dist/icons/head-icon/HeadIcon.stories.tsx +108 -953
- package/dist/icons/heart-icon/HeartIcon.stories.tsx +117 -1060
- package/dist/icons/image-avatar-sparkle-icon/ImageAvatarSparkleIcon.stories.tsx +116 -716
- package/dist/icons/image-icon/ImageIcon.stories.tsx +102 -1164
- package/dist/icons/import-folder-icon/ImportFolderIcon.stories.tsx +108 -1233
- package/dist/icons/import-left-arrow-folder-icon/ImportLeftArrowFolderIcon.stories.tsx +133 -1289
- package/dist/icons/indian-flag-icon/IndianFlagIcon.stories.tsx +155 -1012
- package/dist/icons/instagram-icon/InstagramIcon.stories.tsx +158 -1438
- package/dist/icons/layout-column-icon/LayoutColumnIcon.stories.tsx +121 -1011
- package/dist/icons/layout-left-icon/LayoutLeftIcon.stories.tsx +116 -981
- package/dist/icons/layout-right-icon/LayoutRightIcon.stories.tsx +116 -979
- package/dist/icons/light-bulb-simple-icon/LightBulbSimpleIcon.stories.tsx +105 -1252
- package/dist/icons/linked-in-icon/LinkedInIcon.stories.tsx +151 -1554
- package/dist/icons/magic-book-icon/MagicBookIcon.stories.tsx +107 -1227
- package/dist/icons/magic-edit-icon/MagicEditIcon.stories.tsx +116 -707
- package/dist/icons/maintenance-icon/MaintenanceIcon.stories.tsx +119 -1226
- package/dist/icons/message-icon/MessageIcon.stories.tsx +111 -557
- package/dist/icons/minimize-icon/MinimizeIcon.stories.tsx +112 -1198
- package/dist/icons/moon-icon/MoonIcon.stories.tsx +117 -557
- package/dist/icons/move-horizontal-icon/MoveHorizontalIcon.stories.tsx +106 -1235
- package/dist/icons/move-vertical-icon/MoveVerticalIcon.stories.tsx +112 -1185
- package/dist/icons/musical-note-icon/MusicalNoteIcon.stories.tsx +116 -1012
- package/dist/icons/notepad-icon/NotepadIcon.stories.tsx +108 -1137
- package/dist/icons/notes-icon/NotesIcon.stories.tsx +116 -1138
- package/dist/icons/page-search-icon/PageSearchIcon.stories.tsx +106 -1146
- package/dist/icons/page-text-icon/PageTextIcon.stories.tsx +119 -719
- package/dist/icons/paint-roll-icon/PaintRollIcon.stories.tsx +110 -999
- package/dist/icons/paper-plane-icon/PaperPlaneIcon.stories.tsx +109 -912
- package/dist/icons/pause-icon/PauseIcon.stories.tsx +110 -1041
- package/dist/icons/pencil-icon/PencilIcon.stories.tsx +112 -1109
- package/dist/icons/phone-icon/PhoneIcon.stories.tsx +112 -1023
- package/dist/icons/plus-icon/PlusIcon.stories.tsx +103 -1132
- package/dist/icons/pocket-studio-icon/PocketStudioIcon.stories.tsx +104 -870
- package/dist/icons/scroll-down-icon/ScrollDownIcon.stories.tsx +99 -476
- package/dist/icons/search-icon/SearchIcon.stories.tsx +108 -1161
- package/dist/icons/setting-icon/SettingIcon.stories.tsx +104 -1009
- package/dist/icons/share-icon/ShareIcon.stories.tsx +117 -1064
- package/dist/icons/shield-icon/ShieldIcon.stories.tsx +114 -974
- package/dist/icons/site-logo-icon/SiteLogoIcon.stories.tsx +134 -1160
- package/dist/icons/skip-backward-icon/SkipBackwardIcon.stories.tsx +169 -1017
- package/dist/icons/skip-forward-icon/SkipForwardIcon.stories.tsx +161 -1016
- package/dist/icons/sparkles-soft-icon/SparklesSoftIcon.stories.tsx +102 -1001
- package/dist/icons/spinner-gradient-icon/SpinnerGradientIcon.stories.tsx +155 -593
- package/dist/icons/spinner-solid-icon/SpinnerSolidIcon.stories.tsx +155 -608
- package/dist/icons/spinner-solid-neutral-icon/SpinnerSolidINeutralcon.stories.tsx +142 -712
- package/dist/icons/star-icon/StarIcon.stories.tsx +120 -946
- package/dist/icons/store-coin-icon/StoreCoinIcon.stories.tsx +109 -1013
- package/dist/icons/suggestion-icon/SuggestionIcon.stories.tsx +113 -891
- package/dist/icons/sun-icon/SunIcon.stories.tsx +117 -864
- package/dist/icons/text-color-icon/TextColorIcon.stories.tsx +113 -989
- package/dist/icons/text-indicator-icon/TextIndicatorIcon.stories.tsx +120 -1027
- package/dist/icons/threads-icon/ThreadsIcon.stories.tsx +153 -1476
- package/dist/icons/tick-circle-icon/TickCircleIcon.stories.tsx +143 -1187
- package/dist/icons/tick-icon/TickIcon.stories.tsx +142 -1322
- package/dist/icons/trash-icon/TrashIcon.stories.tsx +105 -970
- package/dist/icons/twitter-x-icon/TwitterXIcon.stories.tsx +154 -1457
- package/dist/icons/upload-icon/UploadIcon.stories.tsx +112 -930
- package/dist/icons/vertical-menu-icon/VerticalMenuIcon.stories.tsx +115 -1019
- package/dist/icons/video-play-list-icon/VideoPlaylistIcon.stories.tsx +122 -1092
- package/dist/icons/voice-playing-icon/VoicePlayingIcon.stories.tsx +120 -1401
- package/dist/icons/volume-full-icon/VolumeFullIcon.stories.tsx +107 -1212
- package/dist/icons/volume-half-icon/VolumeHalfIcon.stories.tsx +109 -1122
- package/dist/icons/volume-off-icon/VolumeOffIcon.stories.tsx +112 -1124
- package/dist/icons/warning-icon/WarningIcon.stories.tsx +119 -1083
- package/dist/icons/youtube-icon/YoutubeIcon.stories.tsx +158 -983
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
|
@@ -1,21 +1,42 @@
|
|
|
1
1
|
import React from "react"
|
|
2
|
-
import
|
|
2
|
+
import { EmailIcon } from "@icons/email-icon"
|
|
3
3
|
import { AlertIcon, CrossIcon, TickIcon } from "@icons/index"
|
|
4
4
|
import type { Meta, StoryObj } from "@storybook/react-vite"
|
|
5
5
|
|
|
6
|
+
import { AuralComponentDocsPage } from "src/ui/story-spec/components/component-story-docs-page"
|
|
7
|
+
|
|
6
8
|
import Input from "."
|
|
7
9
|
|
|
10
|
+
// ─── Meta ─────────────────────────────────────────────────────────────────────
|
|
11
|
+
|
|
8
12
|
const meta: Meta<typeof Input> = {
|
|
9
13
|
title: "Components/UI/Input",
|
|
10
14
|
component: Input,
|
|
11
15
|
parameters: {
|
|
12
16
|
layout: "centered",
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
docs: {
|
|
18
|
+
description: {
|
|
19
|
+
component:
|
|
20
|
+
"A flexible text input built with atomic design principles. Supports four validation variants (default, error, warning, success), three decoration styles (underline, outline, filled), start/end icon slots, password toggle, character counting, and full accessibility via ARIA attributes.",
|
|
21
|
+
},
|
|
22
|
+
page: () => (
|
|
23
|
+
<AuralComponentDocsPage
|
|
24
|
+
features={[
|
|
25
|
+
{
|
|
26
|
+
title: "4 Validation States",
|
|
27
|
+
description: "Default to success",
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
title: "3 Decoration Styles",
|
|
31
|
+
description: "Underline, outline, filled",
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
title: "Icon Slots",
|
|
35
|
+
description: "Start and end icons",
|
|
36
|
+
},
|
|
37
|
+
]}
|
|
38
|
+
/>
|
|
39
|
+
),
|
|
19
40
|
},
|
|
20
41
|
},
|
|
21
42
|
tags: ["autodocs"],
|
|
@@ -23,419 +44,466 @@ const meta: Meta<typeof Input> = {
|
|
|
23
44
|
variant: {
|
|
24
45
|
control: { type: "select" },
|
|
25
46
|
options: ["default", "error", "warning", "success"],
|
|
47
|
+
description: "Visual validation state",
|
|
48
|
+
},
|
|
49
|
+
decoration: {
|
|
50
|
+
control: { type: "select" },
|
|
51
|
+
options: ["underline", "outline", "filled"],
|
|
52
|
+
description: "Border and background style",
|
|
26
53
|
},
|
|
27
54
|
type: {
|
|
28
55
|
control: { type: "select" },
|
|
29
56
|
options: ["text", "email", "password", "number", "tel", "url"],
|
|
57
|
+
description: "HTML input type",
|
|
30
58
|
},
|
|
31
|
-
disabled: {
|
|
32
|
-
|
|
33
|
-
},
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
},
|
|
37
|
-
fullWidth: {
|
|
38
|
-
control: { type: "boolean" },
|
|
39
|
-
},
|
|
40
|
-
transparentOnAutofill: {
|
|
41
|
-
control: { type: "boolean" },
|
|
42
|
-
},
|
|
59
|
+
disabled: { control: { type: "boolean" } },
|
|
60
|
+
required: { control: { type: "boolean" } },
|
|
61
|
+
fullWidth: { control: { type: "boolean" } },
|
|
62
|
+
label: { control: { type: "text" } },
|
|
63
|
+
placeholder: { control: { type: "text" } },
|
|
64
|
+
helperText: { control: { type: "text" } },
|
|
43
65
|
},
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export default meta
|
|
47
|
-
type Story = StoryObj<typeof Input>
|
|
48
|
-
|
|
49
|
-
// Basic variants
|
|
50
|
-
export const Default: Story = {
|
|
51
|
-
args: {
|
|
52
|
-
label: "Default Input",
|
|
53
|
-
placeholder: "Enter text here...",
|
|
54
|
-
variant: "default",
|
|
55
|
-
},
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export const WithValue: Story = {
|
|
59
66
|
args: {
|
|
60
|
-
label: "Input with Value",
|
|
61
|
-
value: "Pre-filled value",
|
|
62
67
|
variant: "default",
|
|
68
|
+
decoration: "underline",
|
|
69
|
+
type: "text",
|
|
70
|
+
disabled: false,
|
|
71
|
+
required: false,
|
|
72
|
+
fullWidth: false,
|
|
73
|
+
label: "Label",
|
|
74
|
+
placeholder: "Placeholder…",
|
|
63
75
|
},
|
|
64
76
|
}
|
|
65
77
|
|
|
66
|
-
export
|
|
67
|
-
|
|
68
|
-
label: "Required Field",
|
|
69
|
-
placeholder: "This field is required",
|
|
70
|
-
required: true,
|
|
71
|
-
variant: "default",
|
|
72
|
-
},
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// Variants
|
|
76
|
-
export const Error: Story = {
|
|
77
|
-
args: {
|
|
78
|
-
label: "Error Input",
|
|
79
|
-
placeholder: "Enter valid email",
|
|
80
|
-
variant: "error",
|
|
81
|
-
helperText: "This field contains an error",
|
|
82
|
-
value: "invalid-email",
|
|
83
|
-
},
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
export const Warning: Story = {
|
|
87
|
-
args: {
|
|
88
|
-
label: "Warning Input",
|
|
89
|
-
placeholder: "Enter password",
|
|
90
|
-
variant: "warning",
|
|
91
|
-
helperText: "Password strength is weak",
|
|
92
|
-
value: "123",
|
|
93
|
-
},
|
|
94
|
-
}
|
|
78
|
+
export default meta
|
|
79
|
+
type Story = StoryObj<typeof Input>
|
|
95
80
|
|
|
96
|
-
|
|
97
|
-
args: {
|
|
98
|
-
label: "Success Input",
|
|
99
|
-
placeholder: "Enter email",
|
|
100
|
-
variant: "success",
|
|
101
|
-
helperText: "Email is valid",
|
|
102
|
-
value: "user@example.com",
|
|
103
|
-
},
|
|
104
|
-
}
|
|
81
|
+
// ─── 1. Playground ────────────────────────────────────────────────────────────
|
|
105
82
|
|
|
106
|
-
|
|
107
|
-
export const Disabled: Story = {
|
|
108
|
-
args: {
|
|
109
|
-
label: "Disabled Input",
|
|
110
|
-
placeholder: "Cannot type here",
|
|
111
|
-
disabled: true,
|
|
112
|
-
value: "Disabled value",
|
|
113
|
-
},
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
export const FullWidth: Story = {
|
|
117
|
-
args: {
|
|
118
|
-
label: "Full Width Input",
|
|
119
|
-
placeholder: "This input takes full width",
|
|
120
|
-
fullWidth: true,
|
|
121
|
-
},
|
|
83
|
+
export const Playground: Story = {
|
|
122
84
|
parameters: {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
args: {
|
|
130
|
-
label: "Email",
|
|
131
|
-
type: "email",
|
|
132
|
-
placeholder: "Enter your email",
|
|
133
|
-
helperText: "We'll never share your email",
|
|
85
|
+
docs: {
|
|
86
|
+
description: {
|
|
87
|
+
story:
|
|
88
|
+
"Use the Storybook controls panel to configure every prop. The input below reflects your selections live.",
|
|
89
|
+
},
|
|
90
|
+
},
|
|
134
91
|
},
|
|
92
|
+
render: (args) => (
|
|
93
|
+
<div className="w-full max-w-sm space-y-4">
|
|
94
|
+
<Input {...args} fullWidth />
|
|
95
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border px-4 py-3">
|
|
96
|
+
<code className="text-fm-secondary text-fm-md leading-fm-md font-(--font-fm-mono)">
|
|
97
|
+
{`<Input variant="${args.variant}" decoration="${args.decoration}" type="${args.type}"${args.disabled ? " disabled" : ""}${args.required ? " required" : ""} />`}
|
|
98
|
+
</code>
|
|
99
|
+
</div>
|
|
100
|
+
</div>
|
|
101
|
+
),
|
|
135
102
|
}
|
|
136
103
|
|
|
137
|
-
|
|
138
|
-
args: {
|
|
139
|
-
label: "Password",
|
|
140
|
-
type: "password",
|
|
141
|
-
placeholder: "Enter your password",
|
|
142
|
-
helperText: "Password must be at least 8 characters",
|
|
143
|
-
},
|
|
144
|
-
}
|
|
104
|
+
// ─── 2. AllVariants ───────────────────────────────────────────────────────────
|
|
145
105
|
|
|
146
|
-
export const
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
106
|
+
export const AllVariants: Story = {
|
|
107
|
+
parameters: {
|
|
108
|
+
docs: {
|
|
109
|
+
description: {
|
|
110
|
+
story:
|
|
111
|
+
"Full matrix of all four validation variants (default, error, warning, success) across all three decoration styles (underline, outline, filled).",
|
|
112
|
+
},
|
|
113
|
+
},
|
|
151
114
|
},
|
|
152
|
-
|
|
115
|
+
render: () => {
|
|
116
|
+
const variants = [
|
|
117
|
+
{ variant: "default" as const, label: "Default" },
|
|
118
|
+
{ variant: "error" as const, label: "Error" },
|
|
119
|
+
{ variant: "warning" as const, label: "Warning" },
|
|
120
|
+
{ variant: "success" as const, label: "Success" },
|
|
121
|
+
]
|
|
122
|
+
const decorations = [
|
|
123
|
+
{ decoration: "underline" as const, label: "Underline" },
|
|
124
|
+
{ decoration: "outline" as const, label: "Outline" },
|
|
125
|
+
{ decoration: "filled" as const, label: "Filled" },
|
|
126
|
+
]
|
|
153
127
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
128
|
+
return (
|
|
129
|
+
<div className="space-y-8">
|
|
130
|
+
{decorations.map(({ decoration, label: decLabel }) => (
|
|
131
|
+
<div key={decoration}>
|
|
132
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md mb-4 font-medium">
|
|
133
|
+
{decLabel}
|
|
134
|
+
</h4>
|
|
135
|
+
<div className="flex flex-wrap gap-6">
|
|
136
|
+
{variants.map(({ variant, label }) => (
|
|
137
|
+
<div key={variant} className="w-48 space-y-2 text-center">
|
|
138
|
+
<Input
|
|
139
|
+
label={label}
|
|
140
|
+
placeholder={`${label}…`}
|
|
141
|
+
variant={variant}
|
|
142
|
+
decoration={decoration}
|
|
143
|
+
helperText={
|
|
144
|
+
variant === "error"
|
|
145
|
+
? "Something went wrong"
|
|
146
|
+
: variant === "warning"
|
|
147
|
+
? "Double-check this value"
|
|
148
|
+
: variant === "success"
|
|
149
|
+
? "Looks great!"
|
|
150
|
+
: "Helper text"
|
|
151
|
+
}
|
|
152
|
+
fullWidth
|
|
153
|
+
/>
|
|
154
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
155
|
+
{label}
|
|
156
|
+
</p>
|
|
157
|
+
</div>
|
|
158
|
+
))}
|
|
159
|
+
</div>
|
|
160
|
+
</div>
|
|
161
|
+
))}
|
|
162
|
+
</div>
|
|
163
|
+
)
|
|
159
164
|
},
|
|
160
165
|
}
|
|
161
166
|
|
|
162
|
-
|
|
163
|
-
args: {
|
|
164
|
-
label: "Website",
|
|
165
|
-
type: "url",
|
|
166
|
-
placeholder: "https://example.com",
|
|
167
|
-
},
|
|
168
|
-
}
|
|
167
|
+
// ─── 3. Configurations ────────────────────────────────────────────────────────
|
|
169
168
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
169
|
+
export const Configurations: Story = {
|
|
170
|
+
parameters: {
|
|
171
|
+
docs: {
|
|
172
|
+
description: {
|
|
173
|
+
story:
|
|
174
|
+
"Non-variant configuration axes: start icon, end icon, both icons together, and different input types (email, password with toggle, number).",
|
|
175
|
+
},
|
|
176
|
+
},
|
|
176
177
|
},
|
|
177
|
-
|
|
178
|
+
render: () => (
|
|
179
|
+
<div className="w-full max-w-sm space-y-8">
|
|
180
|
+
{/* Start icon */}
|
|
181
|
+
<div>
|
|
182
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md mb-4 font-medium">
|
|
183
|
+
Start Icon
|
|
184
|
+
</h4>
|
|
185
|
+
<div className="flex flex-wrap gap-4">
|
|
186
|
+
<div className="w-full space-y-2 text-center">
|
|
187
|
+
<Input
|
|
188
|
+
label="Search"
|
|
189
|
+
placeholder="Search…"
|
|
190
|
+
decoration="outline"
|
|
191
|
+
startIcon={<AlertIcon className="text-fm-secondary h-4 w-4" />}
|
|
192
|
+
fullWidth
|
|
193
|
+
/>
|
|
194
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
195
|
+
startIcon
|
|
196
|
+
</p>
|
|
197
|
+
</div>
|
|
198
|
+
</div>
|
|
199
|
+
</div>
|
|
178
200
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
201
|
+
{/* End icon */}
|
|
202
|
+
<div>
|
|
203
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md mb-4 font-medium">
|
|
204
|
+
End Icon
|
|
205
|
+
</h4>
|
|
206
|
+
<div className="w-full space-y-2 text-center">
|
|
207
|
+
<Input
|
|
208
|
+
label="Verified email"
|
|
209
|
+
placeholder="you@example.com"
|
|
210
|
+
decoration="outline"
|
|
211
|
+
variant="success"
|
|
212
|
+
endIcon={<TickIcon className="text-fm-positive h-4 w-4" />}
|
|
213
|
+
helperText="Email is valid"
|
|
214
|
+
fullWidth
|
|
215
|
+
/>
|
|
216
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
217
|
+
endIcon
|
|
218
|
+
</p>
|
|
219
|
+
</div>
|
|
220
|
+
</div>
|
|
187
221
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
222
|
+
{/* Both icons */}
|
|
223
|
+
<div>
|
|
224
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md mb-4 font-medium">
|
|
225
|
+
Both Icons
|
|
226
|
+
</h4>
|
|
227
|
+
<div className="w-full space-y-2 text-center">
|
|
228
|
+
<Input
|
|
229
|
+
label="Username"
|
|
230
|
+
placeholder="your_handle"
|
|
231
|
+
decoration="outline"
|
|
232
|
+
variant="error"
|
|
233
|
+
startIcon={<AlertIcon className="text-fm-negative h-4 w-4" />}
|
|
234
|
+
endIcon={<CrossIcon className="text-fm-negative h-4 w-4" />}
|
|
235
|
+
helperText="Username already taken"
|
|
236
|
+
fullWidth
|
|
237
|
+
/>
|
|
238
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
239
|
+
startIcon + endIcon
|
|
240
|
+
</p>
|
|
241
|
+
</div>
|
|
242
|
+
</div>
|
|
198
243
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
244
|
+
{/* Input types */}
|
|
245
|
+
<div>
|
|
246
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md mb-4 font-medium">
|
|
247
|
+
Input Types
|
|
248
|
+
</h4>
|
|
249
|
+
<div className="space-y-4">
|
|
250
|
+
<div className="space-y-2 text-center">
|
|
251
|
+
<Input
|
|
252
|
+
label="Email"
|
|
253
|
+
type="email"
|
|
254
|
+
placeholder="you@example.com"
|
|
255
|
+
decoration="outline"
|
|
256
|
+
startIcon={<EmailIcon className="text-fm-secondary h-4 w-4" />}
|
|
257
|
+
helperText="We'll never share your email"
|
|
258
|
+
fullWidth
|
|
259
|
+
/>
|
|
260
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
261
|
+
type="email"
|
|
262
|
+
</p>
|
|
263
|
+
</div>
|
|
264
|
+
<div className="space-y-2 text-center">
|
|
265
|
+
<Input
|
|
266
|
+
label="Password"
|
|
267
|
+
type="password"
|
|
268
|
+
placeholder="Min 8 characters"
|
|
269
|
+
decoration="outline"
|
|
270
|
+
helperText="Password toggle appears automatically"
|
|
271
|
+
fullWidth
|
|
272
|
+
/>
|
|
273
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
274
|
+
type="password" (toggle built-in)
|
|
275
|
+
</p>
|
|
276
|
+
</div>
|
|
277
|
+
<div className="space-y-2 text-center">
|
|
278
|
+
<Input
|
|
279
|
+
label="Age"
|
|
280
|
+
type="number"
|
|
281
|
+
placeholder="25"
|
|
282
|
+
decoration="outline"
|
|
283
|
+
fullWidth
|
|
284
|
+
/>
|
|
285
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
286
|
+
type="number"
|
|
287
|
+
</p>
|
|
288
|
+
</div>
|
|
289
|
+
</div>
|
|
290
|
+
</div>
|
|
217
291
|
</div>
|
|
218
292
|
),
|
|
219
|
-
parameters: {
|
|
220
|
-
layout: "centered",
|
|
221
|
-
},
|
|
222
293
|
}
|
|
223
294
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
<Input
|
|
228
|
-
label="Valid Email"
|
|
229
|
-
type="email"
|
|
230
|
-
value="user@example.com"
|
|
231
|
-
variant="success"
|
|
232
|
-
helperText="Email is valid"
|
|
233
|
-
endIcon={<TickIcon className="h-4 w-4 text-green-500" />}
|
|
234
|
-
fullWidth
|
|
235
|
-
/>
|
|
236
|
-
<Input
|
|
237
|
-
label="Invalid Email"
|
|
238
|
-
type="email"
|
|
239
|
-
value="invalid-email"
|
|
240
|
-
variant="error"
|
|
241
|
-
helperText="Please enter a valid email address"
|
|
242
|
-
endIcon={<CrossIcon className="h-4 w-4 text-red-500" />}
|
|
243
|
-
fullWidth
|
|
244
|
-
/>
|
|
245
|
-
<Input
|
|
246
|
-
label="Weak Password"
|
|
247
|
-
type="password"
|
|
248
|
-
value="123"
|
|
249
|
-
variant="warning"
|
|
250
|
-
helperText="Password is too weak. Use at least 8 characters"
|
|
251
|
-
fullWidth
|
|
252
|
-
/>
|
|
253
|
-
</div>
|
|
254
|
-
),
|
|
295
|
+
// ─── 4. States ────────────────────────────────────────────────────────────────
|
|
296
|
+
|
|
297
|
+
export const States: Story = {
|
|
255
298
|
parameters: {
|
|
256
|
-
|
|
299
|
+
docs: {
|
|
300
|
+
description: {
|
|
301
|
+
story:
|
|
302
|
+
"All five input states side by side: default (idle), disabled (non-interactive), error, warning, and success.",
|
|
303
|
+
},
|
|
304
|
+
},
|
|
257
305
|
},
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
export const DifferentSizes: Story = {
|
|
261
306
|
render: () => (
|
|
262
|
-
<div className="space-y-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
307
|
+
<div className="w-full max-w-sm space-y-8">
|
|
308
|
+
{[
|
|
309
|
+
{
|
|
310
|
+
label: "Default",
|
|
311
|
+
props: {
|
|
312
|
+
label: "Default",
|
|
313
|
+
placeholder: "Enter a value…",
|
|
314
|
+
variant: "default" as const,
|
|
315
|
+
},
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
label: "Disabled",
|
|
319
|
+
props: {
|
|
320
|
+
label: "Disabled",
|
|
321
|
+
value: "Cannot edit this",
|
|
322
|
+
disabled: true,
|
|
323
|
+
variant: "default" as const,
|
|
324
|
+
},
|
|
325
|
+
},
|
|
326
|
+
{
|
|
327
|
+
label: "Error",
|
|
328
|
+
props: {
|
|
329
|
+
label: "Error",
|
|
330
|
+
value: "invalid-email",
|
|
331
|
+
variant: "error" as const,
|
|
332
|
+
helperText: "Please enter a valid email address.",
|
|
333
|
+
},
|
|
334
|
+
},
|
|
335
|
+
{
|
|
336
|
+
label: "Warning",
|
|
337
|
+
props: {
|
|
338
|
+
label: "Warning",
|
|
339
|
+
value: "abc",
|
|
340
|
+
variant: "warning" as const,
|
|
341
|
+
helperText: "Password is too short (min 8 characters).",
|
|
342
|
+
},
|
|
343
|
+
},
|
|
344
|
+
{
|
|
345
|
+
label: "Success",
|
|
346
|
+
props: {
|
|
347
|
+
label: "Success",
|
|
348
|
+
value: "user@example.com",
|
|
349
|
+
variant: "success" as const,
|
|
350
|
+
helperText: "Email is valid.",
|
|
351
|
+
},
|
|
352
|
+
},
|
|
353
|
+
].map(({ label, props }) => (
|
|
354
|
+
<div key={label}>
|
|
355
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md mb-3 font-medium">
|
|
356
|
+
{label}
|
|
357
|
+
</h4>
|
|
358
|
+
<Input decoration="outline" fullWidth {...props} />
|
|
359
|
+
</div>
|
|
360
|
+
))}
|
|
279
361
|
</div>
|
|
280
362
|
),
|
|
281
|
-
parameters: {
|
|
282
|
-
layout: "padded",
|
|
283
|
-
},
|
|
284
363
|
}
|
|
285
364
|
|
|
286
|
-
//
|
|
287
|
-
export const AtomicComponents: Story = {
|
|
288
|
-
render: () => (
|
|
289
|
-
<div className="space-y-6">
|
|
290
|
-
<div>
|
|
291
|
-
<h3 className="text-fm-primary mb-3 text-lg font-semibold">
|
|
292
|
-
Using Atomic Components
|
|
293
|
-
</h3>
|
|
294
|
-
|
|
295
|
-
<Input.Root className="w-80">
|
|
296
|
-
<Input.Label htmlFor="custom-input" required>
|
|
297
|
-
Custom Composed Input
|
|
298
|
-
</Input.Label>
|
|
299
|
-
|
|
300
|
-
<Input.Wrapper>
|
|
301
|
-
<Input.StartIcon>
|
|
302
|
-
<AlertIcon className="text-fm-secondary h-4 w-4" />
|
|
303
|
-
</Input.StartIcon>
|
|
304
|
-
|
|
305
|
-
<Input.Base
|
|
306
|
-
id="custom-input"
|
|
307
|
-
className="block w-full rounded-md border border-gray-300 py-2 pr-10 pl-10 transition-all duration-200 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 focus:outline-none"
|
|
308
|
-
placeholder="Custom composition"
|
|
309
|
-
/>
|
|
310
|
-
|
|
311
|
-
<Input.EndIcon>
|
|
312
|
-
<TickIcon className="h-4 w-4 text-green-500" />
|
|
313
|
-
</Input.EndIcon>
|
|
314
|
-
</Input.Wrapper>
|
|
365
|
+
// ─── 5. Interactive ───────────────────────────────────────────────────────────
|
|
315
366
|
|
|
316
|
-
|
|
317
|
-
Built using atomic components
|
|
318
|
-
</HelperText>
|
|
319
|
-
</Input.Root>
|
|
320
|
-
</div>
|
|
321
|
-
</div>
|
|
322
|
-
),
|
|
367
|
+
export const Interactive: Story = {
|
|
323
368
|
parameters: {
|
|
324
|
-
|
|
369
|
+
docs: {
|
|
370
|
+
description: {
|
|
371
|
+
story:
|
|
372
|
+
"Live validation demo. The email and password inputs update their variant and helper text in real time as you type. Preset buttons let you jump to predefined states.",
|
|
373
|
+
},
|
|
374
|
+
},
|
|
325
375
|
},
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
// Interactive example
|
|
329
|
-
export const InteractiveExample: Story = {
|
|
330
376
|
render: () => {
|
|
331
377
|
const [email, setEmail] = React.useState("")
|
|
332
378
|
const [password, setPassword] = React.useState("")
|
|
379
|
+
const [decoration, setDecoration] = React.useState<
|
|
380
|
+
"underline" | "outline" | "filled"
|
|
381
|
+
>("outline")
|
|
333
382
|
|
|
334
383
|
const emailVariant =
|
|
335
|
-
email.
|
|
336
|
-
? "
|
|
337
|
-
: email.
|
|
338
|
-
? "
|
|
339
|
-
: "
|
|
384
|
+
email.length === 0
|
|
385
|
+
? "default"
|
|
386
|
+
: email.includes("@") && email.includes(".")
|
|
387
|
+
? "success"
|
|
388
|
+
: "error"
|
|
389
|
+
|
|
340
390
|
const passwordVariant =
|
|
341
|
-
password.length
|
|
342
|
-
? "
|
|
343
|
-
: password.length
|
|
344
|
-
? "
|
|
345
|
-
:
|
|
391
|
+
password.length === 0
|
|
392
|
+
? "default"
|
|
393
|
+
: password.length >= 8
|
|
394
|
+
? "success"
|
|
395
|
+
: password.length >= 4
|
|
396
|
+
? "warning"
|
|
397
|
+
: "error"
|
|
398
|
+
|
|
399
|
+
const presets: Array<{ label: string; email: string; password: string }> = [
|
|
400
|
+
{
|
|
401
|
+
label: "Valid credentials",
|
|
402
|
+
email: "user@example.com",
|
|
403
|
+
password: "securepass1",
|
|
404
|
+
},
|
|
405
|
+
{
|
|
406
|
+
label: "Invalid email",
|
|
407
|
+
email: "not-an-email",
|
|
408
|
+
password: "securepass1",
|
|
409
|
+
},
|
|
410
|
+
{ label: "Weak password", email: "user@example.com", password: "abc" },
|
|
411
|
+
{ label: "Clear", email: "", password: "" },
|
|
412
|
+
]
|
|
346
413
|
|
|
347
414
|
return (
|
|
348
|
-
<div className="w-
|
|
349
|
-
<
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
415
|
+
<div className="w-full p-8">
|
|
416
|
+
<div className="mx-auto max-w-3xl space-y-6">
|
|
417
|
+
<div className="grid grid-cols-1 gap-6 lg:grid-cols-3">
|
|
418
|
+
{/* Controls panel */}
|
|
419
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary space-y-5 rounded-xl border p-5">
|
|
420
|
+
<p className="text-fm-primary font-fm-brand text-fm-sm leading-fm-sm font-semibold tracking-widest uppercase">
|
|
421
|
+
Presets
|
|
422
|
+
</p>
|
|
423
|
+
<div className="space-y-2">
|
|
424
|
+
{presets.map(({ label, email: e, password: p }) => (
|
|
425
|
+
<button
|
|
426
|
+
key={label}
|
|
427
|
+
onClick={() => {
|
|
428
|
+
setEmail(e)
|
|
429
|
+
setPassword(p)
|
|
430
|
+
}}
|
|
431
|
+
className="border-fm-divider-secondary text-fm-primary font-fm-text text-fm-sm leading-fm-sm hover:bg-fm-surface-primary w-full rounded-lg border px-3 py-2 text-left transition-colors"
|
|
432
|
+
>
|
|
433
|
+
{label}
|
|
434
|
+
</button>
|
|
435
|
+
))}
|
|
436
|
+
</div>
|
|
437
|
+
<div className="border-fm-divider-secondary border-t pt-4" />
|
|
438
|
+
<p className="text-fm-primary font-fm-brand text-fm-sm leading-fm-sm font-semibold tracking-widest uppercase">
|
|
439
|
+
Decoration
|
|
440
|
+
</p>
|
|
441
|
+
<div className="space-y-2">
|
|
442
|
+
{(["underline", "outline", "filled"] as const).map((d) => (
|
|
443
|
+
<button
|
|
444
|
+
key={d}
|
|
445
|
+
onClick={() => setDecoration(d)}
|
|
446
|
+
className={`border-fm-divider-secondary text-fm-primary font-fm-text text-fm-sm leading-fm-sm w-full rounded-lg border px-3 py-2 text-left capitalize transition-colors ${decoration === d ? "bg-fm-surface-primary" : "hover:bg-fm-surface-primary"}`}
|
|
447
|
+
>
|
|
448
|
+
{d}
|
|
449
|
+
</button>
|
|
450
|
+
))}
|
|
451
|
+
</div>
|
|
452
|
+
</div>
|
|
453
|
+
|
|
454
|
+
{/* Preview stage */}
|
|
455
|
+
<div className="flex flex-col gap-4 lg:col-span-2">
|
|
456
|
+
<Input
|
|
457
|
+
label="Email"
|
|
458
|
+
type="email"
|
|
459
|
+
placeholder="you@example.com"
|
|
460
|
+
value={email}
|
|
461
|
+
onChange={(e) => setEmail(e.target.value)}
|
|
462
|
+
variant={emailVariant as "default" | "error" | "success"}
|
|
463
|
+
decoration={decoration}
|
|
464
|
+
helperText={
|
|
465
|
+
emailVariant === "success"
|
|
466
|
+
? "Email looks good!"
|
|
467
|
+
: emailVariant === "error"
|
|
468
|
+
? "Please enter a valid email address."
|
|
469
|
+
: "Enter your email address"
|
|
470
|
+
}
|
|
471
|
+
required
|
|
472
|
+
fullWidth
|
|
473
|
+
/>
|
|
474
|
+
|
|
475
|
+
<Input
|
|
476
|
+
label="Password"
|
|
477
|
+
type="password"
|
|
478
|
+
placeholder="Min 8 characters"
|
|
479
|
+
value={password}
|
|
480
|
+
onChange={(e) => setPassword(e.target.value)}
|
|
481
|
+
variant={
|
|
482
|
+
passwordVariant as "default" | "error" | "warning" | "success"
|
|
483
|
+
}
|
|
484
|
+
decoration={decoration}
|
|
485
|
+
helperText={
|
|
486
|
+
passwordVariant === "success"
|
|
487
|
+
? "Password strength is strong."
|
|
488
|
+
: passwordVariant === "warning"
|
|
489
|
+
? "Password is too short — use at least 8 characters."
|
|
490
|
+
: passwordVariant === "error"
|
|
491
|
+
? "Password is far too short."
|
|
492
|
+
: "Enter your password"
|
|
493
|
+
}
|
|
494
|
+
required
|
|
495
|
+
fullWidth
|
|
496
|
+
/>
|
|
497
|
+
|
|
498
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border px-4 py-3">
|
|
499
|
+
<code className="text-fm-secondary text-fm-md leading-fm-md font-(--font-fm-mono)">
|
|
500
|
+
{`email variant="${emailVariant}" | password variant="${passwordVariant}"`}
|
|
501
|
+
</code>
|
|
502
|
+
</div>
|
|
503
|
+
</div>
|
|
504
|
+
</div>
|
|
394
505
|
</div>
|
|
395
506
|
</div>
|
|
396
507
|
)
|
|
397
508
|
},
|
|
398
|
-
parameters: {
|
|
399
|
-
layout: "centered",
|
|
400
|
-
},
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
// Edge cases
|
|
404
|
-
export const EdgeCases: Story = {
|
|
405
|
-
render: () => (
|
|
406
|
-
<div className="w-80 space-y-4">
|
|
407
|
-
<Input
|
|
408
|
-
label="Very Long Label That Might Wrap to Multiple Lines in Some Cases"
|
|
409
|
-
placeholder="Long label test"
|
|
410
|
-
helperText="This demonstrates how the component handles very long labels and helper text that might wrap to multiple lines in constrained spaces"
|
|
411
|
-
variant="default"
|
|
412
|
-
fullWidth
|
|
413
|
-
/>
|
|
414
|
-
|
|
415
|
-
<Input
|
|
416
|
-
label=""
|
|
417
|
-
placeholder="No label provided"
|
|
418
|
-
helperText="Input without label"
|
|
419
|
-
fullWidth
|
|
420
|
-
/>
|
|
421
|
-
|
|
422
|
-
<Input label="No Helper Text" placeholder="Clean input" fullWidth />
|
|
423
|
-
|
|
424
|
-
<Input placeholder="No label, no helper text" fullWidth />
|
|
425
|
-
|
|
426
|
-
<Input
|
|
427
|
-
label="All Features"
|
|
428
|
-
placeholder="Everything enabled"
|
|
429
|
-
startIcon={<AlertIcon className="h-4 w-4 text-blue-500" />}
|
|
430
|
-
endIcon={<TickIcon className="h-4 w-4 text-green-500" />}
|
|
431
|
-
helperText="This input has all features enabled"
|
|
432
|
-
variant="success"
|
|
433
|
-
required
|
|
434
|
-
fullWidth
|
|
435
|
-
/>
|
|
436
|
-
</div>
|
|
437
|
-
),
|
|
438
|
-
parameters: {
|
|
439
|
-
layout: "centered",
|
|
440
|
-
},
|
|
441
509
|
}
|