aural-ui 4.0.1 → 4.2.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/README.md +8 -1
- 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 +90 -90
- package/dist/index.js +90 -90
- package/package.json +8 -3
|
@@ -1,15 +1,9 @@
|
|
|
1
1
|
import React from "react"
|
|
2
2
|
import { Button } from "@components/button"
|
|
3
|
-
import {
|
|
4
|
-
AlertIcon,
|
|
5
|
-
EditBigIcon,
|
|
6
|
-
FileChartIcon,
|
|
7
|
-
PlusIcon,
|
|
8
|
-
SearchIcon,
|
|
9
|
-
TickCircleIcon,
|
|
10
|
-
} from "@icons/index"
|
|
11
3
|
import type { Meta, StoryObj } from "@storybook/react-vite"
|
|
12
4
|
|
|
5
|
+
import { AuralComponentDocsPage } from "src/ui/story-spec/components/component-story-docs-page"
|
|
6
|
+
|
|
13
7
|
import { HoverCard, HoverCardContent, HoverCardTrigger } from "."
|
|
14
8
|
|
|
15
9
|
const meta: Meta<typeof HoverCard> = {
|
|
@@ -17,151 +11,40 @@ const meta: Meta<typeof HoverCard> = {
|
|
|
17
11
|
component: HoverCard,
|
|
18
12
|
parameters: {
|
|
19
13
|
layout: "centered",
|
|
20
|
-
backgrounds: {
|
|
21
|
-
default: "dark",
|
|
22
|
-
values: [
|
|
23
|
-
{ name: "dark", value: "#0a0a0a" },
|
|
24
|
-
{ name: "light", value: "#ffffff" },
|
|
25
|
-
],
|
|
26
|
-
},
|
|
27
14
|
docs: {
|
|
28
15
|
description: {
|
|
29
|
-
component:
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
A rich contextual preview component built on top of Radix UI's HoverCard primitive, providing detailed information that appears on hover with a slight delay.
|
|
33
|
-
|
|
34
|
-
## Components
|
|
35
|
-
|
|
36
|
-
### Core Components
|
|
37
|
-
- **HoverCard**: Root component that manages the hover state and timing
|
|
38
|
-
- **HoverCardTrigger**: The element that triggers the hover card display
|
|
39
|
-
- **HoverCardContent**: The content container with positioning and styling
|
|
40
|
-
|
|
41
|
-
## Features
|
|
42
|
-
|
|
43
|
-
- **Smart Positioning**: Automatically positions to stay within viewport
|
|
44
|
-
- **Hover Delay**: Configurable delay before showing content
|
|
45
|
-
- **Rich Content**: Supports complex layouts with images, text, and actions
|
|
46
|
-
- **Keyboard Accessible**: Full keyboard navigation support
|
|
47
|
-
- **Portal Rendering**: Renders in a portal to avoid z-index issues
|
|
48
|
-
- **Responsive**: Adapts to different screen sizes
|
|
49
|
-
- **Design System**: Integrated with design tokens and themes
|
|
50
|
-
- **Animation**: Smooth enter/exit animations
|
|
51
|
-
|
|
52
|
-
## Usage Examples
|
|
53
|
-
|
|
54
|
-
### Basic HoverCard
|
|
55
|
-
\`\`\`tsx
|
|
56
|
-
<HoverCard>
|
|
57
|
-
<HoverCardTrigger>
|
|
58
|
-
<Button variant="link">Hover me</Button>
|
|
59
|
-
</HoverCardTrigger>
|
|
60
|
-
<HoverCardContent>
|
|
61
|
-
<div className="space-y-2">
|
|
62
|
-
<h4 className="text-sm font-semibold">Quick Info</h4>
|
|
63
|
-
<p className="text-sm text-muted-foreground">
|
|
64
|
-
This is a hover card with basic information.
|
|
65
|
-
</p>
|
|
66
|
-
</div>
|
|
67
|
-
</HoverCardContent>
|
|
68
|
-
</HoverCard>
|
|
69
|
-
\`\`\`
|
|
70
|
-
|
|
71
|
-
### User Profile Card
|
|
72
|
-
\`\`\`tsx
|
|
73
|
-
<HoverCard>
|
|
74
|
-
<HoverCardTrigger>
|
|
75
|
-
<Button variant="link">@username</Button>
|
|
76
|
-
</HoverCardTrigger>
|
|
77
|
-
<HoverCardContent className="w-80">
|
|
78
|
-
<div className="flex justify-between space-x-4">
|
|
79
|
-
<div className="space-y-1">
|
|
80
|
-
<h4 className="text-sm font-semibold">@username</h4>
|
|
81
|
-
<p className="text-sm">
|
|
82
|
-
Full Name - Software Developer
|
|
83
|
-
</p>
|
|
84
|
-
<div className="flex items-center pt-2">
|
|
85
|
-
<CalendarIcon className="mr-2 h-4 w-4" />
|
|
86
|
-
<span className="text-xs text-muted-foreground">
|
|
87
|
-
Joined December 2021
|
|
88
|
-
</span>
|
|
89
|
-
</div>
|
|
90
|
-
</div>
|
|
91
|
-
</div>
|
|
92
|
-
</HoverCardContent>
|
|
93
|
-
</HoverCard>
|
|
94
|
-
\`\`\`
|
|
95
|
-
|
|
96
|
-
### Product Preview
|
|
97
|
-
\`\`\`tsx
|
|
98
|
-
<HoverCard>
|
|
99
|
-
<HoverCardTrigger>
|
|
100
|
-
<img src="product.jpg" alt="Product" />
|
|
101
|
-
</HoverCardTrigger>
|
|
102
|
-
<HoverCardContent>
|
|
103
|
-
<div className="space-y-3">
|
|
104
|
-
<div>
|
|
105
|
-
<h4 className="font-semibold">Product Name</h4>
|
|
106
|
-
<p className="text-sm text-muted-foreground">
|
|
107
|
-
Product description with key features
|
|
108
|
-
</p>
|
|
109
|
-
</div>
|
|
110
|
-
<div className="flex items-center justify-between">
|
|
111
|
-
<span className="text-lg font-bold">$99.99</span>
|
|
112
|
-
<Button size="sm">Add to Cart</Button>
|
|
113
|
-
</div>
|
|
114
|
-
</div>
|
|
115
|
-
</HoverCardContent>
|
|
116
|
-
</HoverCard>
|
|
117
|
-
\`\`\`
|
|
118
|
-
|
|
119
|
-
## Positioning
|
|
120
|
-
|
|
121
|
-
The hover card automatically positions itself:
|
|
122
|
-
- **side**: "top" | "right" | "bottom" | "left"
|
|
123
|
-
- **align**: "start" | "center" | "end"
|
|
124
|
-
- **sideOffset**: Distance from the trigger (default: 4px)
|
|
125
|
-
- **alignOffset**: Offset along the alignment axis
|
|
126
|
-
|
|
127
|
-
## Accessibility
|
|
128
|
-
|
|
129
|
-
- **ARIA Support**: Proper ARIA attributes for screen readers
|
|
130
|
-
- **Keyboard Navigation**: Accessible via keyboard focus
|
|
131
|
-
- **Focus Management**: Proper focus handling
|
|
132
|
-
- **Delayed Appearance**: Prevents accidental triggers
|
|
133
|
-
- **Screen Reader**: Content is announced when card appears
|
|
134
|
-
|
|
135
|
-
## Design Tokens
|
|
136
|
-
|
|
137
|
-
- \`bg-fm-surface-frosted/20\`: Translucent background
|
|
138
|
-
- \`text-fm-primary\`: Primary text color
|
|
139
|
-
- \`rounded-md\`: Border radius
|
|
140
|
-
- \`border\`: Border styling
|
|
141
|
-
- \`shadow-md\`: Drop shadow
|
|
142
|
-
- \`p-4\`: Default padding
|
|
143
|
-
|
|
144
|
-
## Best Practices
|
|
145
|
-
|
|
146
|
-
- Use for supplementary information, not critical content
|
|
147
|
-
- Keep content concise and scannable
|
|
148
|
-
- Provide clear visual hierarchy
|
|
149
|
-
- Test with keyboard navigation
|
|
150
|
-
- Consider mobile users (hover cards don't work on touch)
|
|
151
|
-
- Don't nest interactive elements unnecessarily
|
|
152
|
-
`,
|
|
16
|
+
component:
|
|
17
|
+
"A rich contextual preview that appears on hover after a configurable delay. Composed of HoverCard (root state manager), HoverCardTrigger (the hovered element), and HoverCardContent (the floating panel). Supports align, sideOffset, openDelay, and closeDelay props.",
|
|
153
18
|
},
|
|
19
|
+
page: () => (
|
|
20
|
+
<AuralComponentDocsPage
|
|
21
|
+
features={[
|
|
22
|
+
{
|
|
23
|
+
title: "Hover Preview",
|
|
24
|
+
description: "Configurable open delay",
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
title: "Compound Parts",
|
|
28
|
+
description: "Trigger and content",
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
title: "Alignment Control",
|
|
32
|
+
description: "align and sideOffset",
|
|
33
|
+
},
|
|
34
|
+
]}
|
|
35
|
+
/>
|
|
36
|
+
),
|
|
154
37
|
},
|
|
155
38
|
},
|
|
156
39
|
tags: ["autodocs"],
|
|
157
40
|
argTypes: {
|
|
158
41
|
openDelay: {
|
|
159
42
|
control: { type: "number", min: 0, max: 2000, step: 100 },
|
|
160
|
-
description: "Delay before
|
|
43
|
+
description: "Delay in ms before the card opens",
|
|
161
44
|
},
|
|
162
45
|
closeDelay: {
|
|
163
46
|
control: { type: "number", min: 0, max: 2000, step: 100 },
|
|
164
|
-
description: "Delay before
|
|
47
|
+
description: "Delay in ms before the card closes",
|
|
165
48
|
},
|
|
166
49
|
},
|
|
167
50
|
}
|
|
@@ -169,1193 +52,374 @@ The hover card automatically positions itself:
|
|
|
169
52
|
export default meta
|
|
170
53
|
type Story = StoryObj<typeof HoverCard>
|
|
171
54
|
|
|
172
|
-
//
|
|
173
|
-
export const Basic: Story = {
|
|
174
|
-
render: () => (
|
|
175
|
-
<div className="p-8">
|
|
176
|
-
<HoverCard>
|
|
177
|
-
<HoverCardTrigger asChild>
|
|
178
|
-
<Button variant="text">Hover for more info</Button>
|
|
179
|
-
</HoverCardTrigger>
|
|
180
|
-
<HoverCardContent>
|
|
181
|
-
<div className="space-y-2">
|
|
182
|
-
<h4 className="text-fm-primary text-sm font-semibold">
|
|
183
|
-
Quick Information
|
|
184
|
-
</h4>
|
|
185
|
-
<p className="text-fm-secondary text-sm">
|
|
186
|
-
This is a basic hover card that provides additional context when
|
|
187
|
-
you hover over the trigger element.
|
|
188
|
-
</p>
|
|
189
|
-
</div>
|
|
190
|
-
</HoverCardContent>
|
|
191
|
-
</HoverCard>
|
|
192
|
-
</div>
|
|
193
|
-
),
|
|
194
|
-
parameters: {
|
|
195
|
-
docs: {
|
|
196
|
-
description: {
|
|
197
|
-
story:
|
|
198
|
-
"A simple hover card that appears when hovering over a trigger element.",
|
|
199
|
-
},
|
|
200
|
-
},
|
|
201
|
-
},
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// 2. User Profile Cards
|
|
205
|
-
export const UserProfiles: Story = {
|
|
206
|
-
render: () => (
|
|
207
|
-
<div className="space-y-8 p-8">
|
|
208
|
-
<h3 className="text-fm-primary text-center text-lg font-medium">
|
|
209
|
-
User Profile Cards
|
|
210
|
-
</h3>
|
|
211
|
-
|
|
212
|
-
<div className="grid grid-cols-1 gap-6 lg:grid-cols-2">
|
|
213
|
-
{/* Basic Profile */}
|
|
214
|
-
<div className="space-y-4">
|
|
215
|
-
<h4 className="text-fm-secondary text-sm font-medium">
|
|
216
|
-
Basic Profile
|
|
217
|
-
</h4>
|
|
218
|
-
<div className="text-center">
|
|
219
|
-
<HoverCard>
|
|
220
|
-
<HoverCardTrigger asChild>
|
|
221
|
-
<Button variant="text" className="text-fm-info">
|
|
222
|
-
@johndoe
|
|
223
|
-
</Button>
|
|
224
|
-
</HoverCardTrigger>
|
|
225
|
-
<HoverCardContent className="w-80">
|
|
226
|
-
<div className="flex space-x-4">
|
|
227
|
-
<div className="flex h-12 w-12 items-center justify-center rounded-full bg-gradient-to-br from-blue-500 to-purple-600">
|
|
228
|
-
<span className="text-fm-primary font-semibold">JD</span>
|
|
229
|
-
</div>
|
|
230
|
-
<div className="flex-1 space-y-1">
|
|
231
|
-
<h4 className="text-fm-primary text-sm font-semibold">
|
|
232
|
-
John Doe
|
|
233
|
-
</h4>
|
|
234
|
-
<p className="text-fm-secondary text-sm">
|
|
235
|
-
Senior Software Engineer
|
|
236
|
-
</p>
|
|
237
|
-
<p className="text-fm-tertiary text-xs">
|
|
238
|
-
Building amazing user experiences with React and
|
|
239
|
-
TypeScript
|
|
240
|
-
</p>
|
|
241
|
-
<div className="text-fm-secondary flex items-center gap-4 pt-2 text-xs">
|
|
242
|
-
<span>👥 1.2k followers</span>
|
|
243
|
-
<span>📍 San Francisco</span>
|
|
244
|
-
</div>
|
|
245
|
-
</div>
|
|
246
|
-
</div>
|
|
247
|
-
</HoverCardContent>
|
|
248
|
-
</HoverCard>
|
|
249
|
-
</div>
|
|
250
|
-
</div>
|
|
251
|
-
|
|
252
|
-
{/* Detailed Profile */}
|
|
253
|
-
<div className="space-y-4">
|
|
254
|
-
<h4 className="text-fm-secondary text-sm font-medium">
|
|
255
|
-
Detailed Profile
|
|
256
|
-
</h4>
|
|
257
|
-
<div className="text-center">
|
|
258
|
-
<HoverCard>
|
|
259
|
-
<HoverCardTrigger asChild>
|
|
260
|
-
<Button variant="text" className="text-fm-positive">
|
|
261
|
-
@sarahsmith
|
|
262
|
-
</Button>
|
|
263
|
-
</HoverCardTrigger>
|
|
264
|
-
<HoverCardContent className="w-96">
|
|
265
|
-
<div className="space-y-3">
|
|
266
|
-
<div className="flex space-x-4">
|
|
267
|
-
<div className="flex h-16 w-16 items-center justify-center rounded-full bg-gradient-to-br from-green-500 to-teal-600">
|
|
268
|
-
<span className="text-fm-primary text-lg font-semibold">
|
|
269
|
-
SS
|
|
270
|
-
</span>
|
|
271
|
-
</div>
|
|
272
|
-
<div className="flex-1 space-y-1">
|
|
273
|
-
<h4 className="text-fm-primary text-base font-semibold">
|
|
274
|
-
Sarah Smith
|
|
275
|
-
</h4>
|
|
276
|
-
<p className="text-fm-secondary text-sm">
|
|
277
|
-
UX Designer & Product Manager
|
|
278
|
-
</p>
|
|
279
|
-
<div className="text-fm-secondary flex items-center gap-2 text-xs">
|
|
280
|
-
<TickCircleIcon className="h-3 w-3" />
|
|
281
|
-
<span>Verified Account</span>
|
|
282
|
-
</div>
|
|
283
|
-
</div>
|
|
284
|
-
</div>
|
|
285
|
-
|
|
286
|
-
<p className="text-fm-secondary text-sm">
|
|
287
|
-
Passionate about creating intuitive digital experiences.
|
|
288
|
-
Currently working on design systems and user research.
|
|
289
|
-
</p>
|
|
290
|
-
|
|
291
|
-
<div className="grid grid-cols-3 gap-4 pt-2 text-center">
|
|
292
|
-
<div>
|
|
293
|
-
<div className="text-fm-primary text-lg font-semibold">
|
|
294
|
-
248
|
|
295
|
-
</div>
|
|
296
|
-
<div className="text-fm-secondary text-xs">Posts</div>
|
|
297
|
-
</div>
|
|
298
|
-
<div>
|
|
299
|
-
<div className="text-fm-primary text-lg font-semibold">
|
|
300
|
-
2.8k
|
|
301
|
-
</div>
|
|
302
|
-
<div className="text-fm-secondary text-xs">Followers</div>
|
|
303
|
-
</div>
|
|
304
|
-
<div>
|
|
305
|
-
<div className="text-fm-primary text-lg font-semibold">
|
|
306
|
-
892
|
|
307
|
-
</div>
|
|
308
|
-
<div className="text-fm-secondary text-xs">Following</div>
|
|
309
|
-
</div>
|
|
310
|
-
</div>
|
|
55
|
+
// ─── Parts ───────────────────────────────────────────────────────────────────
|
|
311
56
|
|
|
312
|
-
|
|
313
|
-
<Button size="sm" className="flex-1">
|
|
314
|
-
Follow
|
|
315
|
-
</Button>
|
|
316
|
-
<Button size="sm" variant="outline">
|
|
317
|
-
Message
|
|
318
|
-
</Button>
|
|
319
|
-
</div>
|
|
320
|
-
</div>
|
|
321
|
-
</HoverCardContent>
|
|
322
|
-
</HoverCard>
|
|
323
|
-
</div>
|
|
324
|
-
</div>
|
|
325
|
-
</div>
|
|
326
|
-
</div>
|
|
327
|
-
),
|
|
57
|
+
export const Parts: Story = {
|
|
328
58
|
parameters: {
|
|
329
59
|
docs: {
|
|
330
60
|
description: {
|
|
331
61
|
story:
|
|
332
|
-
"
|
|
62
|
+
"Each sub-component shown with its role. HoverCardTrigger wraps the hovered element; HoverCardContent hosts the floating preview panel.",
|
|
333
63
|
},
|
|
334
64
|
},
|
|
335
65
|
},
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
// 3. Product Previews
|
|
339
|
-
export const ProductPreviews: Story = {
|
|
340
66
|
render: () => (
|
|
341
|
-
<div className="space-y-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
Advanced analytics dashboard with real-time insights
|
|
370
|
-
</p>
|
|
371
|
-
</div>
|
|
372
|
-
<div className="flex items-center justify-between">
|
|
373
|
-
<span className="text-fm-primary text-lg font-bold">
|
|
374
|
-
$29/mo
|
|
375
|
-
</span>
|
|
376
|
-
<Button size="sm">
|
|
377
|
-
<PlusIcon className="mr-1 h-3 w-3" />
|
|
378
|
-
Add
|
|
379
|
-
</Button>
|
|
380
|
-
</div>
|
|
381
|
-
</div>
|
|
382
|
-
</HoverCardContent>
|
|
383
|
-
</HoverCard>
|
|
384
|
-
</div>
|
|
385
|
-
</div>
|
|
386
|
-
|
|
387
|
-
{/* Detailed Product */}
|
|
388
|
-
<div className="space-y-4">
|
|
389
|
-
<h4 className="text-fm-secondary text-sm font-medium">
|
|
390
|
-
Detailed Product
|
|
391
|
-
</h4>
|
|
392
|
-
<div className="text-center">
|
|
393
|
-
<HoverCard>
|
|
394
|
-
<HoverCardTrigger asChild>
|
|
395
|
-
<div className="border-fm-divider-secondary bg-fm-surface-secondary hover:bg-fm-surface-frosted/15 hover:border-fm-divider-contrast cursor-pointer rounded-lg border p-4 transition-colors">
|
|
396
|
-
<div className="mx-auto mb-2 flex h-20 w-20 items-center justify-center rounded-lg bg-gradient-to-br from-blue-500 to-cyan-600">
|
|
397
|
-
<SearchIcon className="text-fm-primary h-8 w-8" />
|
|
398
|
-
</div>
|
|
399
|
-
<p className="text-fm-primary text-sm">Search Engine</p>
|
|
400
|
-
</div>
|
|
401
|
-
</HoverCardTrigger>
|
|
402
|
-
<HoverCardContent className="w-80">
|
|
403
|
-
<div className="space-y-4">
|
|
404
|
-
<div className="flex space-x-3">
|
|
405
|
-
<div className="flex h-16 w-16 flex-shrink-0 items-center justify-center rounded-lg bg-gradient-to-br from-blue-500 to-cyan-600">
|
|
406
|
-
<SearchIcon className="text-fm-primary h-8 w-8" />
|
|
407
|
-
</div>
|
|
408
|
-
<div className="space-y-1">
|
|
409
|
-
<h4 className="text-fm-primary font-semibold">
|
|
410
|
-
Advanced Search Engine
|
|
411
|
-
</h4>
|
|
412
|
-
<p className="text-fm-secondary text-sm">
|
|
413
|
-
AI-powered search with natural language processing
|
|
414
|
-
</p>
|
|
415
|
-
<div className="flex items-center gap-2">
|
|
416
|
-
<div className="flex">
|
|
417
|
-
{[1, 2, 3, 4, 5].map((star) => (
|
|
418
|
-
<span
|
|
419
|
-
key={star}
|
|
420
|
-
className="text-fm-warning text-xs"
|
|
421
|
-
>
|
|
422
|
-
★
|
|
423
|
-
</span>
|
|
424
|
-
))}
|
|
425
|
-
</div>
|
|
426
|
-
<span className="text-fm-secondary text-xs">
|
|
427
|
-
(124 reviews)
|
|
428
|
-
</span>
|
|
429
|
-
</div>
|
|
430
|
-
</div>
|
|
431
|
-
</div>
|
|
432
|
-
|
|
433
|
-
<div className="space-y-2">
|
|
434
|
-
<div className="flex justify-between text-sm">
|
|
435
|
-
<span className="text-fm-secondary">Features:</span>
|
|
436
|
-
</div>
|
|
437
|
-
<ul className="text-fm-secondary space-y-1 text-xs">
|
|
438
|
-
<li>• Real-time search suggestions</li>
|
|
439
|
-
<li>• Advanced filtering options</li>
|
|
440
|
-
<li>• Analytics and insights</li>
|
|
441
|
-
<li>• API access included</li>
|
|
442
|
-
</ul>
|
|
443
|
-
</div>
|
|
444
|
-
|
|
445
|
-
<div className="border-fm-divider-secondary flex items-center justify-between border-t pt-2">
|
|
446
|
-
<div>
|
|
447
|
-
<span className="text-fm-secondary text-xs line-through">
|
|
448
|
-
$99/mo
|
|
449
|
-
</span>
|
|
450
|
-
<span className="text-fm-primary ml-2 text-lg font-bold">
|
|
451
|
-
$79/mo
|
|
452
|
-
</span>
|
|
453
|
-
</div>
|
|
454
|
-
<Button size="sm">Start Trial</Button>
|
|
455
|
-
</div>
|
|
456
|
-
</div>
|
|
457
|
-
</HoverCardContent>
|
|
458
|
-
</HoverCard>
|
|
459
|
-
</div>
|
|
460
|
-
</div>
|
|
461
|
-
|
|
462
|
-
{/* Feature Product */}
|
|
463
|
-
<div className="space-y-4">
|
|
464
|
-
<h4 className="text-fm-secondary text-sm font-medium">
|
|
465
|
-
Feature Product
|
|
466
|
-
</h4>
|
|
467
|
-
<div className="text-center">
|
|
468
|
-
<HoverCard>
|
|
469
|
-
<HoverCardTrigger asChild>
|
|
470
|
-
<div className="border-fm-divider-secondary bg-fm-surface-secondary hover:bg-fm-surface-frosted/15 hover:border-fm-divider-contrast cursor-pointer rounded-lg border p-4 transition-colors">
|
|
471
|
-
<div className="mx-auto mb-2 flex h-20 w-20 items-center justify-center rounded-lg bg-gradient-to-br from-orange-500 to-red-600">
|
|
472
|
-
<EditBigIcon className="text-fm-primary h-8 w-8" />
|
|
473
|
-
</div>
|
|
474
|
-
<p className="text-fm-primary text-sm">Editor Pro</p>
|
|
475
|
-
</div>
|
|
476
|
-
</HoverCardTrigger>
|
|
477
|
-
<HoverCardContent className="w-72">
|
|
478
|
-
<div className="space-y-3">
|
|
479
|
-
<div className="flex items-start space-x-3">
|
|
480
|
-
<div className="flex h-12 w-12 items-center justify-center rounded-lg bg-gradient-to-br from-orange-500 to-red-600">
|
|
481
|
-
<EditBigIcon className="text-fm-primary h-6 w-6" />
|
|
482
|
-
</div>
|
|
483
|
-
<div>
|
|
484
|
-
<h4 className="text-fm-primary font-semibold">
|
|
485
|
-
Editor Pro
|
|
486
|
-
</h4>
|
|
487
|
-
<p className="text-fm-secondary text-sm">
|
|
488
|
-
Professional code editor
|
|
489
|
-
</p>
|
|
490
|
-
<div className="mt-1 flex items-center gap-1">
|
|
491
|
-
<span className="rounded bg-orange-500/20 px-2 py-0.5 text-xs text-orange-300">
|
|
492
|
-
Popular
|
|
493
|
-
</span>
|
|
494
|
-
<span className="bg-fm-surface-positive/20 text-fm-positive rounded px-2 py-0.5 text-xs">
|
|
495
|
-
New
|
|
496
|
-
</span>
|
|
497
|
-
</div>
|
|
498
|
-
</div>
|
|
499
|
-
</div>
|
|
500
|
-
|
|
501
|
-
<div className="grid grid-cols-2 gap-3 text-xs">
|
|
502
|
-
<div className="space-y-1">
|
|
503
|
-
<div className="text-fm-secondary">Languages:</div>
|
|
504
|
-
<div className="text-fm-secondary">20+ supported</div>
|
|
505
|
-
</div>
|
|
506
|
-
<div className="space-y-1">
|
|
507
|
-
<div className="text-fm-secondary">Themes:</div>
|
|
508
|
-
<div className="text-fm-secondary">50+ themes</div>
|
|
509
|
-
</div>
|
|
510
|
-
</div>
|
|
511
|
-
|
|
512
|
-
<div className="flex items-center justify-between">
|
|
513
|
-
<span className="text-fm-primary text-lg font-bold">
|
|
514
|
-
Free
|
|
515
|
-
</span>
|
|
516
|
-
<Button size="sm" variant="outline">
|
|
517
|
-
Download
|
|
518
|
-
</Button>
|
|
519
|
-
</div>
|
|
520
|
-
</div>
|
|
521
|
-
</HoverCardContent>
|
|
522
|
-
</HoverCard>
|
|
523
|
-
</div>
|
|
67
|
+
<div className="w-full max-w-2xl space-y-10">
|
|
68
|
+
{/* HoverCardTrigger */}
|
|
69
|
+
<div className="space-y-3">
|
|
70
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
71
|
+
HoverCardTrigger
|
|
72
|
+
</h4>
|
|
73
|
+
<HoverCard>
|
|
74
|
+
<HoverCardTrigger asChild>
|
|
75
|
+
<Button variant="text">@aural_artist</Button>
|
|
76
|
+
</HoverCardTrigger>
|
|
77
|
+
<HoverCardContent>
|
|
78
|
+
<div className="space-y-1">
|
|
79
|
+
<p className="text-fm-primary font-fm-text text-fm-md leading-fm-md font-semibold">
|
|
80
|
+
Aural Artist
|
|
81
|
+
</p>
|
|
82
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
83
|
+
Hover the trigger above to see this card.
|
|
84
|
+
</p>
|
|
85
|
+
</div>
|
|
86
|
+
</HoverCardContent>
|
|
87
|
+
</HoverCard>
|
|
88
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-4">
|
|
89
|
+
<p className="text-fm-secondary font-fm-text text-fm-md leading-fm-xl">
|
|
90
|
+
Wraps any element and attaches hover event listeners. Pass{" "}
|
|
91
|
+
<code>asChild</code> to render the child element directly rather
|
|
92
|
+
than adding an extra DOM node. Must be a direct child of the{" "}
|
|
93
|
+
<code>HoverCard</code> root.
|
|
94
|
+
</p>
|
|
524
95
|
</div>
|
|
525
96
|
</div>
|
|
526
|
-
</div>
|
|
527
|
-
),
|
|
528
|
-
parameters: {
|
|
529
|
-
docs: {
|
|
530
|
-
description: {
|
|
531
|
-
story:
|
|
532
|
-
"Product preview cards showing different levels of detail and information architecture.",
|
|
533
|
-
},
|
|
534
|
-
},
|
|
535
|
-
},
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
// 4. Documentation Links
|
|
539
|
-
export const DocumentationLinks: Story = {
|
|
540
|
-
render: () => (
|
|
541
|
-
<div className="space-y-8 p-8">
|
|
542
|
-
<h3 className="text-fm-primary text-center text-lg font-medium">
|
|
543
|
-
Documentation Links
|
|
544
|
-
</h3>
|
|
545
|
-
|
|
546
|
-
<div className="space-y-6">
|
|
547
|
-
{/* API Documentation */}
|
|
548
|
-
<div className="space-y-4">
|
|
549
|
-
<h4 className="text-fm-secondary text-sm font-medium">
|
|
550
|
-
API Documentation
|
|
551
|
-
</h4>
|
|
552
|
-
<div className="space-y-2">
|
|
553
|
-
<p className="text-fm-secondary text-sm">
|
|
554
|
-
Learn more about our{" "}
|
|
555
|
-
<HoverCard>
|
|
556
|
-
<HoverCardTrigger asChild>
|
|
557
|
-
<Button
|
|
558
|
-
variant="text"
|
|
559
|
-
className="text-fm-info h-auto p-0 font-normal"
|
|
560
|
-
>
|
|
561
|
-
REST API
|
|
562
|
-
</Button>
|
|
563
|
-
</HoverCardTrigger>
|
|
564
|
-
<HoverCardContent>
|
|
565
|
-
<div className="space-y-2">
|
|
566
|
-
<h4 className="text-fm-primary text-sm font-semibold">
|
|
567
|
-
REST API
|
|
568
|
-
</h4>
|
|
569
|
-
<p className="text-fm-secondary text-sm">
|
|
570
|
-
Our REST API provides programmatic access to all platform
|
|
571
|
-
features.
|
|
572
|
-
</p>
|
|
573
|
-
<div className="text-fm-secondary space-y-1 text-xs">
|
|
574
|
-
<div>• Rate limit: 1000 requests/hour</div>
|
|
575
|
-
<div>• Authentication: API Key required</div>
|
|
576
|
-
<div>• Response format: JSON</div>
|
|
577
|
-
</div>
|
|
578
|
-
<Button size="sm" className="mt-2 w-full">
|
|
579
|
-
View Documentation
|
|
580
|
-
</Button>
|
|
581
|
-
</div>
|
|
582
|
-
</HoverCardContent>
|
|
583
|
-
</HoverCard>{" "}
|
|
584
|
-
and{" "}
|
|
585
|
-
<HoverCard>
|
|
586
|
-
<HoverCardTrigger asChild>
|
|
587
|
-
<Button
|
|
588
|
-
variant="text"
|
|
589
|
-
className="text-fm-info h-auto p-0 font-normal"
|
|
590
|
-
>
|
|
591
|
-
GraphQL endpoint
|
|
592
|
-
</Button>
|
|
593
|
-
</HoverCardTrigger>
|
|
594
|
-
<HoverCardContent>
|
|
595
|
-
<div className="space-y-2">
|
|
596
|
-
<h4 className="text-fm-primary text-sm font-semibold">
|
|
597
|
-
GraphQL API
|
|
598
|
-
</h4>
|
|
599
|
-
<p className="text-fm-secondary text-sm">
|
|
600
|
-
Query exactly the data you need with our GraphQL API.
|
|
601
|
-
</p>
|
|
602
|
-
<div className="text-fm-secondary space-y-1 text-xs">
|
|
603
|
-
<div>• Single endpoint for all queries</div>
|
|
604
|
-
<div>• Type-safe schema</div>
|
|
605
|
-
<div>• Real-time subscriptions</div>
|
|
606
|
-
</div>
|
|
607
|
-
<div className="mt-2 flex gap-2">
|
|
608
|
-
<Button size="sm" className="flex-1">
|
|
609
|
-
Playground
|
|
610
|
-
</Button>
|
|
611
|
-
<Button size="sm" variant="outline" className="flex-1">
|
|
612
|
-
Schema
|
|
613
|
-
</Button>
|
|
614
|
-
</div>
|
|
615
|
-
</div>
|
|
616
|
-
</HoverCardContent>
|
|
617
|
-
</HoverCard>
|
|
618
|
-
.
|
|
619
|
-
</p>
|
|
620
|
-
</div>
|
|
621
|
-
</div>
|
|
622
97
|
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
<p className="text-fm-secondary text-sm">
|
|
644
|
-
Control when and how you receive notifications from the
|
|
645
|
-
platform.
|
|
646
|
-
</p>
|
|
647
|
-
<div className="space-y-2">
|
|
648
|
-
<div className="text-fm-secondary text-xs">
|
|
649
|
-
Available notification types:
|
|
650
|
-
</div>
|
|
651
|
-
<ul className="text-fm-secondary ml-2 space-y-1 text-xs">
|
|
652
|
-
<li>• Email notifications</li>
|
|
653
|
-
<li>• Push notifications</li>
|
|
654
|
-
<li>• In-app notifications</li>
|
|
655
|
-
<li>• SMS alerts (premium)</li>
|
|
656
|
-
</ul>
|
|
657
|
-
</div>
|
|
658
|
-
</div>
|
|
659
|
-
</HoverCardContent>
|
|
660
|
-
</HoverCard>
|
|
661
|
-
</div>
|
|
662
|
-
|
|
663
|
-
<div className="flex items-center justify-between">
|
|
664
|
-
<span className="text-fm-primary">Auto-save frequency</span>
|
|
665
|
-
<HoverCard>
|
|
666
|
-
<HoverCardTrigger asChild>
|
|
667
|
-
<Button variant="outline" size="sm" className="h-6 w-6 p-0">
|
|
668
|
-
<TickCircleIcon className="h-4 w-4" />
|
|
669
|
-
</Button>
|
|
670
|
-
</HoverCardTrigger>
|
|
671
|
-
<HoverCardContent>
|
|
672
|
-
<div className="space-y-2">
|
|
673
|
-
<h4 className="text-fm-primary text-sm font-semibold">
|
|
674
|
-
Auto-save Settings
|
|
675
|
-
</h4>
|
|
676
|
-
<p className="text-fm-secondary text-sm">
|
|
677
|
-
Automatically save your work at regular intervals.
|
|
678
|
-
</p>
|
|
679
|
-
<div className="text-fm-secondary space-y-1 text-xs">
|
|
680
|
-
<div>• Every 30 seconds (recommended)</div>
|
|
681
|
-
<div>• Every 1 minute</div>
|
|
682
|
-
<div>• Every 5 minutes</div>
|
|
683
|
-
<div>• Disabled</div>
|
|
684
|
-
</div>
|
|
685
|
-
</div>
|
|
686
|
-
</HoverCardContent>
|
|
687
|
-
</HoverCard>
|
|
688
|
-
</div>
|
|
98
|
+
{/* HoverCardContent */}
|
|
99
|
+
<div className="space-y-3">
|
|
100
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
101
|
+
HoverCardContent
|
|
102
|
+
</h4>
|
|
103
|
+
<HoverCard defaultOpen>
|
|
104
|
+
<HoverCardTrigger asChild>
|
|
105
|
+
<Button variant="text">Hover card open</Button>
|
|
106
|
+
</HoverCardTrigger>
|
|
107
|
+
<HoverCardContent>
|
|
108
|
+
<div className="space-y-2">
|
|
109
|
+
<p className="text-fm-primary font-fm-text text-fm-md leading-fm-md font-semibold">
|
|
110
|
+
Frosted glass panel
|
|
111
|
+
</p>
|
|
112
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
113
|
+
Backdrop-blurred container with{" "}
|
|
114
|
+
<code>bg-fm-surface-frosted/20</code>. Accepts{" "}
|
|
115
|
+
<code>align</code>, <code>sideOffset</code>, and all Radix
|
|
116
|
+
Content props.
|
|
117
|
+
</p>
|
|
689
118
|
</div>
|
|
690
|
-
</
|
|
119
|
+
</HoverCardContent>
|
|
120
|
+
</HoverCard>
|
|
121
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-4">
|
|
122
|
+
<p className="text-fm-secondary font-fm-text text-fm-md leading-fm-xl">
|
|
123
|
+
The floating panel rendered in a portal. Uses a frosted-glass
|
|
124
|
+
backdrop with <code>text-fm-primary</code> text and{" "}
|
|
125
|
+
<code>w-64</code> default width. Positioning is controlled by{" "}
|
|
126
|
+
<code>align</code> and <code>sideOffset</code>.
|
|
127
|
+
</p>
|
|
691
128
|
</div>
|
|
692
129
|
</div>
|
|
693
130
|
</div>
|
|
694
131
|
),
|
|
695
|
-
parameters: {
|
|
696
|
-
docs: {
|
|
697
|
-
description: {
|
|
698
|
-
story:
|
|
699
|
-
"Documentation and help text hover cards for providing contextual information about features and settings.",
|
|
700
|
-
},
|
|
701
|
-
},
|
|
702
|
-
},
|
|
703
132
|
}
|
|
704
133
|
|
|
705
|
-
//
|
|
706
|
-
export const InteractiveElements: Story = {
|
|
707
|
-
render: () => {
|
|
708
|
-
const [selectedUser, setSelectedUser] = React.useState<string | null>(null)
|
|
709
|
-
const [hoveredProduct, setHoveredProduct] = React.useState<string | null>(
|
|
710
|
-
null
|
|
711
|
-
)
|
|
712
|
-
|
|
713
|
-
const users = [
|
|
714
|
-
{ id: "1", name: "Alice Johnson", role: "Designer", status: "online" },
|
|
715
|
-
{ id: "2", name: "Bob Smith", role: "Developer", status: "away" },
|
|
716
|
-
{ id: "3", name: "Carol Davis", role: "Manager", status: "offline" },
|
|
717
|
-
]
|
|
718
|
-
|
|
719
|
-
const products = [
|
|
720
|
-
{ id: "1", name: "Dashboard Pro", price: "$49", sales: 1234 },
|
|
721
|
-
{ id: "2", name: "Analytics Suite", price: "$79", sales: 856 },
|
|
722
|
-
{ id: "3", name: "Report Builder", price: "$29", sales: 2341 },
|
|
723
|
-
]
|
|
724
|
-
|
|
725
|
-
return (
|
|
726
|
-
<div className="space-y-8 p-8">
|
|
727
|
-
<h3 className="text-fm-primary text-center text-lg font-medium">
|
|
728
|
-
Interactive Elements
|
|
729
|
-
</h3>
|
|
730
|
-
|
|
731
|
-
<div className="grid grid-cols-1 gap-8 lg:grid-cols-2">
|
|
732
|
-
{/* Team Members */}
|
|
733
|
-
<div className="space-y-4">
|
|
734
|
-
<h4 className="text-fm-secondary text-sm font-medium">
|
|
735
|
-
Team Members
|
|
736
|
-
</h4>
|
|
737
|
-
<div className="space-y-2">
|
|
738
|
-
{users.map((user) => (
|
|
739
|
-
<HoverCard key={user.id}>
|
|
740
|
-
<HoverCardTrigger asChild>
|
|
741
|
-
<div
|
|
742
|
-
className={`flex cursor-pointer items-center space-x-3 rounded-lg border p-3 transition-colors ${
|
|
743
|
-
selectedUser === user.id
|
|
744
|
-
? "border-fm-divider-secondary bg-fm-surface-info-sec"
|
|
745
|
-
: "border-fm-divider-secondary bg-fm-surface-secondary hover:bg-fm-surface-frosted/15 hover:border-fm-divider-contrast"
|
|
746
|
-
}`}
|
|
747
|
-
onClick={() =>
|
|
748
|
-
setSelectedUser(
|
|
749
|
-
selectedUser === user.id ? null : user.id
|
|
750
|
-
)
|
|
751
|
-
}
|
|
752
|
-
>
|
|
753
|
-
<div
|
|
754
|
-
className={`flex h-8 w-8 items-center justify-center rounded-full ${
|
|
755
|
-
user.status === "online"
|
|
756
|
-
? "bg-fm-surface-positive"
|
|
757
|
-
: user.status === "away"
|
|
758
|
-
? "bg-fm-surface-warning"
|
|
759
|
-
: "bg-fm-surface-secondary"
|
|
760
|
-
}`}
|
|
761
|
-
>
|
|
762
|
-
<span className="text-fm-primary text-xs font-semibold">
|
|
763
|
-
{user.name
|
|
764
|
-
.split(" ")
|
|
765
|
-
.map((n) => n[0])
|
|
766
|
-
.join("")}
|
|
767
|
-
</span>
|
|
768
|
-
</div>
|
|
769
|
-
<div className="flex-1">
|
|
770
|
-
<div className="text-fm-primary text-sm font-medium">
|
|
771
|
-
{user.name}
|
|
772
|
-
</div>
|
|
773
|
-
<div className="text-fm-secondary text-xs">
|
|
774
|
-
{user.role}
|
|
775
|
-
</div>
|
|
776
|
-
</div>
|
|
777
|
-
<div
|
|
778
|
-
className={`h-2 w-2 rounded-full ${
|
|
779
|
-
user.status === "online"
|
|
780
|
-
? "bg-fm-surface-positive"
|
|
781
|
-
: user.status === "away"
|
|
782
|
-
? "bg-fm-surface-warning"
|
|
783
|
-
: "bg-fm-surface-secondary"
|
|
784
|
-
}`}
|
|
785
|
-
/>
|
|
786
|
-
</div>
|
|
787
|
-
</HoverCardTrigger>
|
|
788
|
-
<HoverCardContent className="w-80">
|
|
789
|
-
<div className="space-y-3">
|
|
790
|
-
<div className="flex space-x-4">
|
|
791
|
-
<div
|
|
792
|
-
className={`flex h-16 w-16 items-center justify-center rounded-full ${
|
|
793
|
-
user.status === "online"
|
|
794
|
-
? "bg-fm-surface-positive"
|
|
795
|
-
: user.status === "away"
|
|
796
|
-
? "bg-fm-surface-warning"
|
|
797
|
-
: "bg-fm-surface-secondary"
|
|
798
|
-
}`}
|
|
799
|
-
>
|
|
800
|
-
<span className="text-fm-primary font-semibold">
|
|
801
|
-
{user.name
|
|
802
|
-
.split(" ")
|
|
803
|
-
.map((n) => n[0])
|
|
804
|
-
.join("")}
|
|
805
|
-
</span>
|
|
806
|
-
</div>
|
|
807
|
-
<div className="space-y-1">
|
|
808
|
-
<h4 className="text-fm-primary text-sm font-semibold">
|
|
809
|
-
{user.name}
|
|
810
|
-
</h4>
|
|
811
|
-
<p className="text-fm-secondary text-sm">
|
|
812
|
-
{user.role}
|
|
813
|
-
</p>
|
|
814
|
-
<div className="flex items-center gap-2 text-xs">
|
|
815
|
-
<div
|
|
816
|
-
className={`h-2 w-2 rounded-full ${
|
|
817
|
-
user.status === "online"
|
|
818
|
-
? "bg-fm-surface-positive"
|
|
819
|
-
: user.status === "away"
|
|
820
|
-
? "bg-fm-surface-warning"
|
|
821
|
-
: "bg-fm-surface-secondary"
|
|
822
|
-
}`}
|
|
823
|
-
/>
|
|
824
|
-
<span className="text-fm-secondary capitalize">
|
|
825
|
-
{user.status}
|
|
826
|
-
</span>
|
|
827
|
-
</div>
|
|
828
|
-
</div>
|
|
829
|
-
</div>
|
|
830
|
-
|
|
831
|
-
<div className="text-fm-secondary text-sm">
|
|
832
|
-
{user.status === "online"
|
|
833
|
-
? "Available for collaboration"
|
|
834
|
-
: user.status === "away"
|
|
835
|
-
? "Away - will respond later"
|
|
836
|
-
: "Last seen 2 hours ago"}
|
|
837
|
-
</div>
|
|
838
|
-
|
|
839
|
-
<div className="flex gap-2">
|
|
840
|
-
<Button size="sm" className="flex-1">
|
|
841
|
-
Message
|
|
842
|
-
</Button>
|
|
843
|
-
<Button size="sm" variant="outline" className="flex-1">
|
|
844
|
-
Profile
|
|
845
|
-
</Button>
|
|
846
|
-
</div>
|
|
847
|
-
</div>
|
|
848
|
-
</HoverCardContent>
|
|
849
|
-
</HoverCard>
|
|
850
|
-
))}
|
|
851
|
-
</div>
|
|
852
|
-
</div>
|
|
853
|
-
|
|
854
|
-
{/* Product Analytics */}
|
|
855
|
-
<div className="space-y-4">
|
|
856
|
-
<h4 className="text-fm-secondary text-sm font-medium">
|
|
857
|
-
Product Analytics
|
|
858
|
-
</h4>
|
|
859
|
-
<div className="space-y-2">
|
|
860
|
-
{products.map((product) => (
|
|
861
|
-
<HoverCard key={product.id}>
|
|
862
|
-
<HoverCardTrigger asChild>
|
|
863
|
-
<div
|
|
864
|
-
className={`cursor-pointer rounded-lg border p-3 transition-colors ${
|
|
865
|
-
hoveredProduct === product.id
|
|
866
|
-
? "border-purple-500 bg-purple-500/10"
|
|
867
|
-
: "border-fm-divider-secondary bg-fm-surface-secondary hover:bg-fm-surface-frosted/15 hover:border-fm-divider-contrast"
|
|
868
|
-
}`}
|
|
869
|
-
onMouseEnter={() => setHoveredProduct(product.id)}
|
|
870
|
-
onMouseLeave={() => setHoveredProduct(null)}
|
|
871
|
-
>
|
|
872
|
-
<div className="flex items-center justify-between">
|
|
873
|
-
<div>
|
|
874
|
-
<div className="text-fm-primary text-sm font-medium">
|
|
875
|
-
{product.name}
|
|
876
|
-
</div>
|
|
877
|
-
<div className="text-fm-secondary text-xs">
|
|
878
|
-
{product.sales} sales
|
|
879
|
-
</div>
|
|
880
|
-
</div>
|
|
881
|
-
<div className="text-right">
|
|
882
|
-
<div className="text-fm-primary text-sm font-semibold">
|
|
883
|
-
{product.price}
|
|
884
|
-
</div>
|
|
885
|
-
<div className="text-fm-positive text-xs">↗ +12%</div>
|
|
886
|
-
</div>
|
|
887
|
-
</div>
|
|
888
|
-
</div>
|
|
889
|
-
</HoverCardTrigger>
|
|
890
|
-
<HoverCardContent className="w-96">
|
|
891
|
-
<div className="space-y-4">
|
|
892
|
-
<div className="flex items-start justify-between">
|
|
893
|
-
<div>
|
|
894
|
-
<h4 className="text-fm-primary font-semibold">
|
|
895
|
-
{product.name}
|
|
896
|
-
</h4>
|
|
897
|
-
<p className="text-fm-secondary text-sm">
|
|
898
|
-
Detailed product analytics
|
|
899
|
-
</p>
|
|
900
|
-
</div>
|
|
901
|
-
<span className="text-fm-primary text-lg font-bold">
|
|
902
|
-
{product.price}
|
|
903
|
-
</span>
|
|
904
|
-
</div>
|
|
905
|
-
|
|
906
|
-
<div className="grid grid-cols-2 gap-4">
|
|
907
|
-
<div className="space-y-1">
|
|
908
|
-
<div className="text-fm-secondary text-xs">
|
|
909
|
-
Total Sales
|
|
910
|
-
</div>
|
|
911
|
-
<div className="text-fm-primary text-lg font-semibold">
|
|
912
|
-
{product.sales}
|
|
913
|
-
</div>
|
|
914
|
-
<div className="text-fm-positive text-xs">
|
|
915
|
-
+12% vs last month
|
|
916
|
-
</div>
|
|
917
|
-
</div>
|
|
918
|
-
<div className="space-y-1">
|
|
919
|
-
<div className="text-fm-secondary text-xs">
|
|
920
|
-
Revenue
|
|
921
|
-
</div>
|
|
922
|
-
<div className="text-fm-primary text-lg font-semibold">
|
|
923
|
-
$
|
|
924
|
-
{(
|
|
925
|
-
parseInt(product.price.slice(1)) * product.sales
|
|
926
|
-
).toLocaleString()}
|
|
927
|
-
</div>
|
|
928
|
-
<div className="text-fm-positive text-xs">
|
|
929
|
-
+8% vs last month
|
|
930
|
-
</div>
|
|
931
|
-
</div>
|
|
932
|
-
</div>
|
|
134
|
+
// ─── Configurations ──────────────────────────────────────────────────────────
|
|
933
135
|
|
|
934
|
-
|
|
935
|
-
<div className="text-fm-secondary text-xs">
|
|
936
|
-
Top Markets
|
|
937
|
-
</div>
|
|
938
|
-
<div className="space-y-1">
|
|
939
|
-
<div className="flex justify-between text-xs">
|
|
940
|
-
<span className="text-fm-secondary">
|
|
941
|
-
North America
|
|
942
|
-
</span>
|
|
943
|
-
<span className="text-fm-primary">45%</span>
|
|
944
|
-
</div>
|
|
945
|
-
<div className="flex justify-between text-xs">
|
|
946
|
-
<span className="text-fm-secondary">Europe</span>
|
|
947
|
-
<span className="text-fm-primary">32%</span>
|
|
948
|
-
</div>
|
|
949
|
-
<div className="flex justify-between text-xs">
|
|
950
|
-
<span className="text-fm-secondary">
|
|
951
|
-
Asia Pacific
|
|
952
|
-
</span>
|
|
953
|
-
<span className="text-fm-primary">23%</span>
|
|
954
|
-
</div>
|
|
955
|
-
</div>
|
|
956
|
-
</div>
|
|
957
|
-
|
|
958
|
-
<Button size="sm" className="w-full">
|
|
959
|
-
<FileChartIcon className="mr-2 h-3 w-3" />
|
|
960
|
-
View Full Report
|
|
961
|
-
</Button>
|
|
962
|
-
</div>
|
|
963
|
-
</HoverCardContent>
|
|
964
|
-
</HoverCard>
|
|
965
|
-
))}
|
|
966
|
-
</div>
|
|
967
|
-
</div>
|
|
968
|
-
</div>
|
|
969
|
-
</div>
|
|
970
|
-
)
|
|
971
|
-
},
|
|
136
|
+
export const Configurations: Story = {
|
|
972
137
|
parameters: {
|
|
973
138
|
docs: {
|
|
974
139
|
description: {
|
|
975
140
|
story:
|
|
976
|
-
"
|
|
141
|
+
"Demonstrates align (start / center / end), sideOffset variations, and delay timing. Hover each trigger to see the positioning difference.",
|
|
977
142
|
},
|
|
978
143
|
},
|
|
979
144
|
},
|
|
980
|
-
}
|
|
981
|
-
|
|
982
|
-
// 6. Positioning & Timing
|
|
983
|
-
export const PositioningAndTiming: Story = {
|
|
984
145
|
render: () => (
|
|
985
|
-
<div className="space-y-8
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
Different Positions
|
|
995
|
-
</h4>
|
|
996
|
-
<div className="grid grid-cols-2 place-items-center gap-8 lg:grid-cols-4">
|
|
997
|
-
{/* Top */}
|
|
998
|
-
<div className="flex flex-col items-center gap-4">
|
|
999
|
-
<span className="text-fm-secondary text-sm">Top</span>
|
|
1000
|
-
<HoverCard>
|
|
1001
|
-
<HoverCardTrigger asChild>
|
|
1002
|
-
<Button variant="outline" size="sm">
|
|
1003
|
-
Top
|
|
1004
|
-
</Button>
|
|
1005
|
-
</HoverCardTrigger>
|
|
1006
|
-
<HoverCardContent side="top">
|
|
1007
|
-
<div className="space-y-2">
|
|
1008
|
-
<h4 className="text-fm-primary text-sm font-semibold">
|
|
1009
|
-
Top Position
|
|
1010
|
-
</h4>
|
|
1011
|
-
<p className="text-fm-secondary text-sm">
|
|
1012
|
-
Card positioned above the trigger
|
|
1013
|
-
</p>
|
|
1014
|
-
</div>
|
|
1015
|
-
</HoverCardContent>
|
|
1016
|
-
</HoverCard>
|
|
1017
|
-
</div>
|
|
1018
|
-
|
|
1019
|
-
{/* Right */}
|
|
1020
|
-
<div className="flex flex-col items-center gap-4">
|
|
1021
|
-
<span className="text-fm-secondary text-sm">Right</span>
|
|
146
|
+
<div className="w-full max-w-3xl space-y-8">
|
|
147
|
+
{/* Alignment */}
|
|
148
|
+
<div className="space-y-4">
|
|
149
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
150
|
+
Alignment — align prop
|
|
151
|
+
</h4>
|
|
152
|
+
<div className="flex flex-wrap justify-center gap-6">
|
|
153
|
+
{(["start", "center", "end"] as const).map((align) => (
|
|
154
|
+
<div key={align} className="space-y-2 text-center">
|
|
1022
155
|
<HoverCard>
|
|
1023
156
|
<HoverCardTrigger asChild>
|
|
1024
|
-
<Button variant="outline"
|
|
1025
|
-
Right
|
|
1026
|
-
</Button>
|
|
157
|
+
<Button variant="outline">align="{align}"</Button>
|
|
1027
158
|
</HoverCardTrigger>
|
|
1028
|
-
<HoverCardContent
|
|
1029
|
-
<
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
</h4>
|
|
1033
|
-
<p className="text-fm-secondary text-sm">
|
|
1034
|
-
Card positioned to the right
|
|
1035
|
-
</p>
|
|
1036
|
-
</div>
|
|
159
|
+
<HoverCardContent align={align}>
|
|
160
|
+
<p className="text-fm-primary font-fm-text text-fm-sm leading-fm-sm">
|
|
161
|
+
Content aligned to <strong>{align}</strong> of trigger.
|
|
162
|
+
</p>
|
|
1037
163
|
</HoverCardContent>
|
|
1038
164
|
</HoverCard>
|
|
165
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
166
|
+
{align}
|
|
167
|
+
</p>
|
|
1039
168
|
</div>
|
|
169
|
+
))}
|
|
170
|
+
</div>
|
|
171
|
+
</div>
|
|
1040
172
|
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
173
|
+
{/* sideOffset */}
|
|
174
|
+
<div className="space-y-4">
|
|
175
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
176
|
+
Side Offset — sideOffset prop
|
|
177
|
+
</h4>
|
|
178
|
+
<div className="flex flex-wrap justify-center gap-6">
|
|
179
|
+
{[0, 8, 16, 24].map((offset) => (
|
|
180
|
+
<div key={offset} className="space-y-2 text-center">
|
|
1044
181
|
<HoverCard>
|
|
1045
182
|
<HoverCardTrigger asChild>
|
|
1046
|
-
<Button variant="outline"
|
|
1047
|
-
Bottom
|
|
1048
|
-
</Button>
|
|
183
|
+
<Button variant="outline">offset {offset}px</Button>
|
|
1049
184
|
</HoverCardTrigger>
|
|
1050
|
-
<HoverCardContent
|
|
1051
|
-
<
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
</h4>
|
|
1055
|
-
<p className="text-fm-secondary text-sm">
|
|
1056
|
-
Card positioned below the trigger
|
|
1057
|
-
</p>
|
|
1058
|
-
</div>
|
|
185
|
+
<HoverCardContent sideOffset={offset}>
|
|
186
|
+
<p className="text-fm-primary font-fm-text text-fm-sm leading-fm-sm">
|
|
187
|
+
sideOffset={offset}
|
|
188
|
+
</p>
|
|
1059
189
|
</HoverCardContent>
|
|
1060
190
|
</HoverCard>
|
|
191
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
192
|
+
{offset}px gap
|
|
193
|
+
</p>
|
|
1061
194
|
</div>
|
|
195
|
+
))}
|
|
196
|
+
</div>
|
|
197
|
+
</div>
|
|
1062
198
|
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
199
|
+
{/* Delay timing */}
|
|
200
|
+
<div className="space-y-4">
|
|
201
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
202
|
+
Delay Timing — openDelay / closeDelay
|
|
203
|
+
</h4>
|
|
204
|
+
<div className="flex flex-wrap justify-center gap-6">
|
|
205
|
+
{[
|
|
206
|
+
{ label: "Instant", openDelay: 0, closeDelay: 0 },
|
|
207
|
+
{ label: "Default (700ms)", openDelay: 700, closeDelay: 300 },
|
|
208
|
+
{ label: "Slow (1200ms)", openDelay: 1200, closeDelay: 600 },
|
|
209
|
+
].map(({ label, openDelay, closeDelay }) => (
|
|
210
|
+
<div key={label} className="space-y-2 text-center">
|
|
211
|
+
<HoverCard openDelay={openDelay} closeDelay={closeDelay}>
|
|
1067
212
|
<HoverCardTrigger asChild>
|
|
1068
|
-
<Button variant="outline"
|
|
1069
|
-
Left
|
|
1070
|
-
</Button>
|
|
213
|
+
<Button variant="outline">{label}</Button>
|
|
1071
214
|
</HoverCardTrigger>
|
|
1072
|
-
<HoverCardContent
|
|
1073
|
-
<
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
</h4>
|
|
1077
|
-
<p className="text-fm-secondary text-sm">
|
|
1078
|
-
Card positioned to the left
|
|
1079
|
-
</p>
|
|
1080
|
-
</div>
|
|
215
|
+
<HoverCardContent>
|
|
216
|
+
<p className="text-fm-primary font-fm-text text-fm-sm leading-fm-sm">
|
|
217
|
+
Open: {openDelay}ms · Close: {closeDelay}ms
|
|
218
|
+
</p>
|
|
1081
219
|
</HoverCardContent>
|
|
1082
220
|
</HoverCard>
|
|
221
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
222
|
+
open {openDelay}ms
|
|
223
|
+
</p>
|
|
1083
224
|
</div>
|
|
1084
|
-
|
|
1085
|
-
</div>
|
|
1086
|
-
|
|
1087
|
-
{/* Timing */}
|
|
1088
|
-
<div className="space-y-4">
|
|
1089
|
-
<h4 className="text-fm-secondary text-center text-sm font-medium">
|
|
1090
|
-
Different Delays
|
|
1091
|
-
</h4>
|
|
1092
|
-
<div className="flex justify-center gap-4">
|
|
1093
|
-
<HoverCard openDelay={0}>
|
|
1094
|
-
<HoverCardTrigger asChild>
|
|
1095
|
-
<Button variant="outline" size="sm">
|
|
1096
|
-
Instant
|
|
1097
|
-
</Button>
|
|
1098
|
-
</HoverCardTrigger>
|
|
1099
|
-
<HoverCardContent>
|
|
1100
|
-
<div className="space-y-2">
|
|
1101
|
-
<h4 className="text-fm-primary text-sm font-semibold">
|
|
1102
|
-
No Delay
|
|
1103
|
-
</h4>
|
|
1104
|
-
<p className="text-fm-secondary text-sm">
|
|
1105
|
-
Appears immediately on hover
|
|
1106
|
-
</p>
|
|
1107
|
-
</div>
|
|
1108
|
-
</HoverCardContent>
|
|
1109
|
-
</HoverCard>
|
|
1110
|
-
|
|
1111
|
-
<HoverCard openDelay={500}>
|
|
1112
|
-
<HoverCardTrigger asChild>
|
|
1113
|
-
<Button variant="outline" size="sm">
|
|
1114
|
-
Medium
|
|
1115
|
-
</Button>
|
|
1116
|
-
</HoverCardTrigger>
|
|
1117
|
-
<HoverCardContent>
|
|
1118
|
-
<div className="space-y-2">
|
|
1119
|
-
<h4 className="text-fm-primary text-sm font-semibold">
|
|
1120
|
-
Medium Delay
|
|
1121
|
-
</h4>
|
|
1122
|
-
<p className="text-fm-secondary text-sm">
|
|
1123
|
-
500ms delay before appearing
|
|
1124
|
-
</p>
|
|
1125
|
-
</div>
|
|
1126
|
-
</HoverCardContent>
|
|
1127
|
-
</HoverCard>
|
|
1128
|
-
|
|
1129
|
-
<HoverCard openDelay={1000}>
|
|
1130
|
-
<HoverCardTrigger asChild>
|
|
1131
|
-
<Button variant="outline" size="sm">
|
|
1132
|
-
Slow
|
|
1133
|
-
</Button>
|
|
1134
|
-
</HoverCardTrigger>
|
|
1135
|
-
<HoverCardContent>
|
|
1136
|
-
<div className="space-y-2">
|
|
1137
|
-
<h4 className="text-fm-primary text-sm font-semibold">
|
|
1138
|
-
Long Delay
|
|
1139
|
-
</h4>
|
|
1140
|
-
<p className="text-fm-secondary text-sm">
|
|
1141
|
-
1000ms delay before appearing
|
|
1142
|
-
</p>
|
|
1143
|
-
</div>
|
|
1144
|
-
</HoverCardContent>
|
|
1145
|
-
</HoverCard>
|
|
1146
|
-
</div>
|
|
1147
|
-
</div>
|
|
1148
|
-
|
|
1149
|
-
{/* Size Variations */}
|
|
1150
|
-
<div className="space-y-4">
|
|
1151
|
-
<h4 className="text-fm-secondary text-center text-sm font-medium">
|
|
1152
|
-
Different Sizes
|
|
1153
|
-
</h4>
|
|
1154
|
-
<div className="flex justify-center gap-4">
|
|
1155
|
-
<HoverCard>
|
|
1156
|
-
<HoverCardTrigger asChild>
|
|
1157
|
-
<Button variant="outline" size="sm">
|
|
1158
|
-
Small
|
|
1159
|
-
</Button>
|
|
1160
|
-
</HoverCardTrigger>
|
|
1161
|
-
<HoverCardContent className="w-48">
|
|
1162
|
-
<div className="space-y-2">
|
|
1163
|
-
<h4 className="text-fm-primary text-sm font-semibold">
|
|
1164
|
-
Small Card
|
|
1165
|
-
</h4>
|
|
1166
|
-
<p className="text-fm-secondary text-sm">
|
|
1167
|
-
Compact information
|
|
1168
|
-
</p>
|
|
1169
|
-
</div>
|
|
1170
|
-
</HoverCardContent>
|
|
1171
|
-
</HoverCard>
|
|
1172
|
-
|
|
1173
|
-
<HoverCard>
|
|
1174
|
-
<HoverCardTrigger asChild>
|
|
1175
|
-
<Button variant="outline" size="sm">
|
|
1176
|
-
Medium
|
|
1177
|
-
</Button>
|
|
1178
|
-
</HoverCardTrigger>
|
|
1179
|
-
<HoverCardContent className="w-80">
|
|
1180
|
-
<div className="space-y-2">
|
|
1181
|
-
<h4 className="text-fm-primary text-sm font-semibold">
|
|
1182
|
-
Medium Card
|
|
1183
|
-
</h4>
|
|
1184
|
-
<p className="text-fm-secondary text-sm">
|
|
1185
|
-
Medium-sized card with more detailed information and
|
|
1186
|
-
multiple lines of text.
|
|
1187
|
-
</p>
|
|
1188
|
-
</div>
|
|
1189
|
-
</HoverCardContent>
|
|
1190
|
-
</HoverCard>
|
|
1191
|
-
|
|
1192
|
-
<HoverCard>
|
|
1193
|
-
<HoverCardTrigger asChild>
|
|
1194
|
-
<Button variant="outline" size="sm">
|
|
1195
|
-
Large
|
|
1196
|
-
</Button>
|
|
1197
|
-
</HoverCardTrigger>
|
|
1198
|
-
<HoverCardContent className="w-96">
|
|
1199
|
-
<div className="space-y-3">
|
|
1200
|
-
<h4 className="text-fm-primary text-sm font-semibold">
|
|
1201
|
-
Large Card
|
|
1202
|
-
</h4>
|
|
1203
|
-
<p className="text-fm-secondary text-sm">
|
|
1204
|
-
Large card with extensive information, multiple sections,
|
|
1205
|
-
and complex layouts. Perfect for detailed previews and
|
|
1206
|
-
comprehensive information displays.
|
|
1207
|
-
</p>
|
|
1208
|
-
<div className="border-fm-divider-secondary border-t pt-2">
|
|
1209
|
-
<Button size="sm" className="w-full">
|
|
1210
|
-
Learn More
|
|
1211
|
-
</Button>
|
|
1212
|
-
</div>
|
|
1213
|
-
</div>
|
|
1214
|
-
</HoverCardContent>
|
|
1215
|
-
</HoverCard>
|
|
1216
|
-
</div>
|
|
225
|
+
))}
|
|
1217
226
|
</div>
|
|
1218
227
|
</div>
|
|
1219
228
|
</div>
|
|
1220
229
|
),
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// ─── UseCases ────────────────────────────────────────────────────────────────
|
|
233
|
+
|
|
234
|
+
export const UseCases: Story = {
|
|
1221
235
|
parameters: {
|
|
1222
236
|
docs: {
|
|
1223
237
|
description: {
|
|
1224
238
|
story:
|
|
1225
|
-
"
|
|
239
|
+
"Real product-shaped examples: artist profile preview on hover, album info card, and user mention preview — all in an audio streaming context.",
|
|
1226
240
|
},
|
|
1227
241
|
},
|
|
1228
242
|
},
|
|
1229
|
-
}
|
|
1230
|
-
|
|
1231
|
-
// 7. Accessibility Demo
|
|
1232
|
-
export const AccessibilityDemo: Story = {
|
|
1233
243
|
render: () => (
|
|
1234
|
-
<div className="space-y-8 p-8">
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
<div className="border-fm-divider-secondary bg-fm-surface-
|
|
1241
|
-
<
|
|
1242
|
-
|
|
1243
|
-
</h4>
|
|
1244
|
-
<p className="text-fm-info-sec mb-2 text-xs">
|
|
1245
|
-
Try these keyboard interactions:
|
|
244
|
+
<div className="mx-auto max-w-3xl space-y-8 p-8">
|
|
245
|
+
{/* Artist profile preview */}
|
|
246
|
+
<div className="space-y-4">
|
|
247
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
248
|
+
Artist Profile Preview
|
|
249
|
+
</h4>
|
|
250
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary space-y-2 rounded-xl border p-5">
|
|
251
|
+
<p className="text-fm-tertiary font-fm-text text-fm-sm leading-fm-sm">
|
|
252
|
+
Now playing from
|
|
1246
253
|
</p>
|
|
1247
|
-
<
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
to focus hover card triggers
|
|
1251
|
-
</li>
|
|
1252
|
-
<li>• Hover card appears automatically on focus</li>
|
|
1253
|
-
<li>
|
|
1254
|
-
•{" "}
|
|
1255
|
-
<kbd className="bg-fm-surface-secondary rounded px-1">Escape</kbd>{" "}
|
|
1256
|
-
to dismiss hover card
|
|
1257
|
-
</li>
|
|
1258
|
-
<li>• Content is announced by screen readers</li>
|
|
1259
|
-
</ul>
|
|
1260
|
-
</div>
|
|
1261
|
-
|
|
1262
|
-
{/* Keyboard Accessible Examples */}
|
|
1263
|
-
<div className="space-y-4">
|
|
1264
|
-
<h4 className="text-fm-secondary text-sm font-medium">
|
|
1265
|
-
Keyboard Accessible Hover Cards
|
|
1266
|
-
</h4>
|
|
1267
|
-
<div className="flex flex-wrap gap-4">
|
|
1268
|
-
<HoverCard>
|
|
1269
|
-
<HoverCardTrigger asChild>
|
|
1270
|
-
<Button>Focusable Button</Button>
|
|
1271
|
-
</HoverCardTrigger>
|
|
1272
|
-
<HoverCardContent>
|
|
1273
|
-
<div className="space-y-2">
|
|
1274
|
-
<h4 className="text-fm-primary text-sm font-semibold">
|
|
1275
|
-
Keyboard Accessible
|
|
1276
|
-
</h4>
|
|
1277
|
-
<p className="text-fm-secondary text-sm">
|
|
1278
|
-
This hover card appears on both hover and keyboard focus.
|
|
1279
|
-
</p>
|
|
1280
|
-
</div>
|
|
1281
|
-
</HoverCardContent>
|
|
1282
|
-
</HoverCard>
|
|
1283
|
-
|
|
1284
|
-
<HoverCard>
|
|
1285
|
-
<HoverCardTrigger asChild>
|
|
1286
|
-
<a
|
|
1287
|
-
href="#"
|
|
1288
|
-
className="text-fm-info inline-flex items-center gap-2 rounded px-3 py-2 text-sm hover:text-blue-300 focus:ring-2 focus:ring-blue-500 focus:outline-none"
|
|
1289
|
-
onClick={(e) => e.preventDefault()}
|
|
1290
|
-
>
|
|
1291
|
-
<AlertIcon className="h-4 w-4" />
|
|
1292
|
-
Documentation Link
|
|
1293
|
-
</a>
|
|
1294
|
-
</HoverCardTrigger>
|
|
1295
|
-
<HoverCardContent>
|
|
1296
|
-
<div className="space-y-2">
|
|
1297
|
-
<h4 className="text-fm-primary text-sm font-semibold">
|
|
1298
|
-
Documentation
|
|
1299
|
-
</h4>
|
|
1300
|
-
<p className="text-fm-secondary text-sm">
|
|
1301
|
-
Comprehensive guides and API reference for developers.
|
|
1302
|
-
</p>
|
|
1303
|
-
<Button size="sm" className="w-full">
|
|
1304
|
-
View Docs
|
|
1305
|
-
</Button>
|
|
1306
|
-
</div>
|
|
1307
|
-
</HoverCardContent>
|
|
1308
|
-
</HoverCard>
|
|
1309
|
-
|
|
1310
|
-
<HoverCard>
|
|
254
|
+
<p className="text-fm-primary font-fm-text text-fm-md leading-fm-md">
|
|
255
|
+
Midnights ·{" "}
|
|
256
|
+
<HoverCard openDelay={300} closeDelay={150}>
|
|
1311
257
|
<HoverCardTrigger asChild>
|
|
1312
|
-
<button className="
|
|
1313
|
-
|
|
1314
|
-
Status Check
|
|
258
|
+
<button className="text-fm-primary cursor-pointer font-semibold underline underline-offset-2 outline-none">
|
|
259
|
+
Taylor Swift
|
|
1315
260
|
</button>
|
|
1316
261
|
</HoverCardTrigger>
|
|
1317
|
-
<HoverCardContent>
|
|
1318
|
-
<div className="space-y-
|
|
1319
|
-
<
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
<div className="bg-fm-surface-positive h-2 w-2 rounded-full"></div>
|
|
1325
|
-
<span>All systems operational</span>
|
|
262
|
+
<HoverCardContent className="w-72">
|
|
263
|
+
<div className="space-y-3">
|
|
264
|
+
<div className="flex items-center gap-3">
|
|
265
|
+
<div className="bg-fm-surface-primary border-fm-divider-secondary flex h-12 w-12 shrink-0 items-center justify-center rounded-full border">
|
|
266
|
+
<span className="text-fm-primary font-fm-brand text-fm-md leading-fm-md font-semibold">
|
|
267
|
+
TS
|
|
268
|
+
</span>
|
|
1326
269
|
</div>
|
|
1327
|
-
<div className="
|
|
1328
|
-
|
|
270
|
+
<div className="space-y-0.5">
|
|
271
|
+
<p className="text-fm-primary font-fm-text text-fm-md leading-fm-md font-semibold">
|
|
272
|
+
Taylor Swift
|
|
273
|
+
</p>
|
|
274
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
275
|
+
Pop · Country
|
|
276
|
+
</p>
|
|
1329
277
|
</div>
|
|
1330
278
|
</div>
|
|
279
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
280
|
+
11 studio albums · 85M+ monthly listeners
|
|
281
|
+
</p>
|
|
282
|
+
<div className="text-fm-tertiary font-fm-text text-fm-xs leading-fm-xs flex gap-2">
|
|
283
|
+
<span className="border-fm-divider-secondary rounded border px-2 py-0.5">
|
|
284
|
+
Pop
|
|
285
|
+
</span>
|
|
286
|
+
<span className="border-fm-divider-secondary rounded border px-2 py-0.5">
|
|
287
|
+
Country
|
|
288
|
+
</span>
|
|
289
|
+
<span className="border-fm-divider-secondary rounded border px-2 py-0.5">
|
|
290
|
+
Indie
|
|
291
|
+
</span>
|
|
292
|
+
</div>
|
|
1331
293
|
</div>
|
|
1332
294
|
</HoverCardContent>
|
|
1333
295
|
</HoverCard>
|
|
296
|
+
</p>
|
|
297
|
+
</div>
|
|
298
|
+
</div>
|
|
299
|
+
|
|
300
|
+
{/* Album info card */}
|
|
301
|
+
<div className="space-y-4">
|
|
302
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
303
|
+
Album Info Card
|
|
304
|
+
</h4>
|
|
305
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-xl border p-5">
|
|
306
|
+
<p className="text-fm-tertiary font-fm-text text-fm-sm leading-fm-sm mb-3">
|
|
307
|
+
Recently played albums
|
|
308
|
+
</p>
|
|
309
|
+
<div className="flex flex-wrap gap-3">
|
|
310
|
+
{[
|
|
311
|
+
{
|
|
312
|
+
name: "Midnights",
|
|
313
|
+
artist: "Taylor Swift",
|
|
314
|
+
year: "2022",
|
|
315
|
+
tracks: 13,
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
name: "Renaissance",
|
|
319
|
+
artist: "Beyoncé",
|
|
320
|
+
year: "2022",
|
|
321
|
+
tracks: 16,
|
|
322
|
+
},
|
|
323
|
+
{
|
|
324
|
+
name: "Harry's House",
|
|
325
|
+
artist: "Harry Styles",
|
|
326
|
+
year: "2022",
|
|
327
|
+
tracks: 13,
|
|
328
|
+
},
|
|
329
|
+
].map((album) => (
|
|
330
|
+
<HoverCard key={album.name} openDelay={400}>
|
|
331
|
+
<HoverCardTrigger asChild>
|
|
332
|
+
<div className="bg-fm-surface-primary border-fm-divider-secondary hover:border-fm-divider-primary flex h-16 w-16 cursor-pointer items-center justify-center rounded-lg border transition-colors">
|
|
333
|
+
<span className="text-fm-tertiary font-fm-text text-fm-xs leading-fm-xs px-1 text-center">
|
|
334
|
+
{album.name.slice(0, 3)}
|
|
335
|
+
</span>
|
|
336
|
+
</div>
|
|
337
|
+
</HoverCardTrigger>
|
|
338
|
+
<HoverCardContent className="w-64">
|
|
339
|
+
<div className="space-y-2">
|
|
340
|
+
<p className="text-fm-primary font-fm-text text-fm-md leading-fm-md font-semibold">
|
|
341
|
+
{album.name}
|
|
342
|
+
</p>
|
|
343
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
344
|
+
{album.artist}
|
|
345
|
+
</p>
|
|
346
|
+
<div className="text-fm-tertiary font-fm-text text-fm-xs leading-fm-xs flex gap-4 pt-1">
|
|
347
|
+
<span>{album.year}</span>
|
|
348
|
+
<span>{album.tracks} tracks</span>
|
|
349
|
+
</div>
|
|
350
|
+
</div>
|
|
351
|
+
</HoverCardContent>
|
|
352
|
+
</HoverCard>
|
|
353
|
+
))}
|
|
1334
354
|
</div>
|
|
1335
355
|
</div>
|
|
356
|
+
</div>
|
|
1336
357
|
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
358
|
+
{/* User mention preview */}
|
|
359
|
+
<div className="space-y-4">
|
|
360
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
361
|
+
User Mention Preview
|
|
362
|
+
</h4>
|
|
363
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary space-y-3 rounded-xl border p-5">
|
|
364
|
+
<p className="text-fm-tertiary font-fm-text text-fm-sm leading-fm-sm">
|
|
365
|
+
Activity feed
|
|
366
|
+
</p>
|
|
367
|
+
{[
|
|
368
|
+
{
|
|
369
|
+
handle: "@mikejameson",
|
|
370
|
+
action: "shared a playlist with you",
|
|
371
|
+
initials: "MJ",
|
|
372
|
+
name: "Mike Jameson",
|
|
373
|
+
role: "Music Producer",
|
|
374
|
+
followers: "4.1k",
|
|
375
|
+
},
|
|
376
|
+
{
|
|
377
|
+
handle: "@luna_beats",
|
|
378
|
+
action: "liked your track",
|
|
379
|
+
initials: "LB",
|
|
380
|
+
name: "Luna Beats",
|
|
381
|
+
role: "DJ · Electronic",
|
|
382
|
+
followers: "12k",
|
|
383
|
+
},
|
|
384
|
+
].map(({ handle, action, initials, name, role, followers }) => (
|
|
385
|
+
<div
|
|
386
|
+
key={handle}
|
|
387
|
+
className="text-fm-primary font-fm-text text-fm-md leading-fm-md flex items-center gap-2"
|
|
388
|
+
>
|
|
389
|
+
<HoverCard openDelay={300} closeDelay={200}>
|
|
390
|
+
<HoverCardTrigger asChild>
|
|
391
|
+
<button className="text-fm-primary cursor-pointer font-semibold underline underline-offset-2 outline-none">
|
|
392
|
+
{handle}
|
|
393
|
+
</button>
|
|
394
|
+
</HoverCardTrigger>
|
|
395
|
+
<HoverCardContent className="w-64">
|
|
396
|
+
<div className="space-y-3">
|
|
397
|
+
<div className="flex items-center gap-3">
|
|
398
|
+
<div className="bg-fm-surface-primary border-fm-divider-secondary flex h-10 w-10 shrink-0 items-center justify-center rounded-full border">
|
|
399
|
+
<span className="text-fm-primary font-fm-brand text-fm-sm leading-fm-sm font-semibold">
|
|
400
|
+
{initials}
|
|
401
|
+
</span>
|
|
402
|
+
</div>
|
|
403
|
+
<div>
|
|
404
|
+
<p className="text-fm-primary font-fm-text text-fm-md leading-fm-md font-semibold">
|
|
405
|
+
{name}
|
|
406
|
+
</p>
|
|
407
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
408
|
+
{role}
|
|
409
|
+
</p>
|
|
410
|
+
</div>
|
|
411
|
+
</div>
|
|
412
|
+
<p className="text-fm-tertiary font-fm-text text-fm-xs leading-fm-xs">
|
|
413
|
+
{followers} followers
|
|
414
|
+
</p>
|
|
415
|
+
</div>
|
|
416
|
+
</HoverCardContent>
|
|
417
|
+
</HoverCard>
|
|
418
|
+
<span className="text-fm-secondary">{action}</span>
|
|
419
|
+
</div>
|
|
420
|
+
))}
|
|
1349
421
|
</div>
|
|
1350
422
|
</div>
|
|
1351
423
|
</div>
|
|
1352
424
|
),
|
|
1353
|
-
parameters: {
|
|
1354
|
-
docs: {
|
|
1355
|
-
description: {
|
|
1356
|
-
story:
|
|
1357
|
-
"Accessibility features including keyboard navigation, focus management, and best practices for inclusive design.",
|
|
1358
|
-
},
|
|
1359
|
-
},
|
|
1360
|
-
},
|
|
1361
425
|
}
|