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,53 +1,85 @@
|
|
|
1
|
-
import React from "react"
|
|
1
|
+
import React, { useState } from "react"
|
|
2
2
|
import type { Meta, StoryObj } from "@storybook/react-vite"
|
|
3
|
-
|
|
3
|
+
|
|
4
|
+
import { AuralComponentDocsPage } from "src/ui/story-spec/components/component-story-docs-page"
|
|
4
5
|
|
|
5
6
|
import { ClampLines } from "."
|
|
6
|
-
import {
|
|
7
|
+
import { Button } from "../button"
|
|
8
|
+
|
|
9
|
+
// ─── Sample text in an audio-streaming context ──────────────────────────────
|
|
10
|
+
|
|
11
|
+
const EPISODE_DESC =
|
|
12
|
+
"In this episode we sit down with Grammy-winning producer Anya Reeves to discuss the craft of mixing live orchestral recordings, the challenges of capturing room acoustics in modern studios, and how emerging spatial audio formats are reshaping the way listeners experience music at home. We also explore her recent collaboration with the Aural Collective on their debut album and what the future holds for independent artists distributing exclusively through streaming platforms."
|
|
7
13
|
|
|
8
|
-
const
|
|
9
|
-
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
|
|
14
|
+
const SHORT_BIO = "DJ Kai spins deep house and Afrobeats every Friday night."
|
|
10
15
|
|
|
11
16
|
const meta: Meta<typeof ClampLines> = {
|
|
12
17
|
title: "Components/UI/ClampLines",
|
|
13
18
|
component: ClampLines,
|
|
14
19
|
parameters: {
|
|
15
20
|
layout: "centered",
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
docs: {
|
|
22
|
+
description: {
|
|
23
|
+
component:
|
|
24
|
+
"A utility component for truncating long text blocks by word count or CSS line-clamp, with a built-in expand/collapse toggle. Ideal for podcast episode descriptions, artist bios, and playlist notes where text length is unpredictable.",
|
|
25
|
+
},
|
|
26
|
+
page: () => (
|
|
27
|
+
<AuralComponentDocsPage
|
|
28
|
+
features={[
|
|
29
|
+
{
|
|
30
|
+
title: "Word Limit",
|
|
31
|
+
description: "Truncate by word count",
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
title: "Responsive",
|
|
35
|
+
description: "No-JS fallback mode",
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
title: "Render Prop",
|
|
39
|
+
description: "Render-prop toggle",
|
|
40
|
+
},
|
|
41
|
+
]}
|
|
42
|
+
/>
|
|
43
|
+
),
|
|
22
44
|
},
|
|
23
45
|
},
|
|
24
46
|
tags: ["autodocs"],
|
|
25
47
|
argTypes: {
|
|
26
48
|
wordLimit: {
|
|
27
49
|
control: "number",
|
|
28
|
-
description: "Max number of words
|
|
50
|
+
description: "Max number of words shown before truncation.",
|
|
29
51
|
},
|
|
30
52
|
responsive: {
|
|
31
53
|
control: "boolean",
|
|
32
|
-
description:
|
|
54
|
+
description:
|
|
55
|
+
"Scales the word limit proportionally to viewport width when true.",
|
|
33
56
|
},
|
|
34
57
|
minWordLimit: {
|
|
35
58
|
control: "number",
|
|
36
59
|
description:
|
|
37
|
-
"Minimum word limit
|
|
60
|
+
"Minimum word limit applied on the smallest viewports when responsive is true.",
|
|
61
|
+
},
|
|
62
|
+
readMoreText: {
|
|
63
|
+
control: "text",
|
|
64
|
+
description: "Label for the expand button.",
|
|
65
|
+
},
|
|
66
|
+
readLessText: {
|
|
67
|
+
control: "text",
|
|
68
|
+
description: "Label for the collapse button.",
|
|
38
69
|
},
|
|
39
70
|
button: {
|
|
40
71
|
control: false,
|
|
41
72
|
description:
|
|
42
|
-
"Render function for a custom toggle button. Receives `open` (boolean) and `toggle` (function)
|
|
73
|
+
"Render function for a fully custom toggle button. Receives `open` (boolean) and `toggle` (function). Return `null` to suppress the button entirely.",
|
|
43
74
|
},
|
|
44
75
|
classes: {
|
|
45
76
|
control: "object",
|
|
46
|
-
description:
|
|
77
|
+
description:
|
|
78
|
+
"Class overrides for internal elements: `root`, `content`, `clampLineBtn`, `clampLineBtnInnerClass`.",
|
|
47
79
|
},
|
|
48
80
|
children: {
|
|
49
81
|
control: "text",
|
|
50
|
-
description: "The text content to
|
|
82
|
+
description: "The text content to clamp.",
|
|
51
83
|
},
|
|
52
84
|
},
|
|
53
85
|
}
|
|
@@ -55,115 +87,212 @@ const meta: Meta<typeof ClampLines> = {
|
|
|
55
87
|
export default meta
|
|
56
88
|
type Story = StoryObj<typeof ClampLines>
|
|
57
89
|
|
|
58
|
-
|
|
59
|
-
args: {
|
|
60
|
-
children: LONG_TEXT,
|
|
61
|
-
wordLimit: 20,
|
|
62
|
-
},
|
|
63
|
-
}
|
|
90
|
+
// ─── 1. Configurations ───────────────────────────────────────────────────────
|
|
64
91
|
|
|
65
|
-
export const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
<
|
|
92
|
+
export const Configurations: Story = {
|
|
93
|
+
render: () => (
|
|
94
|
+
<div className="space-y-8" style={{ width: 440 }}>
|
|
95
|
+
{/* Word limit */}
|
|
96
|
+
<div>
|
|
97
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md mb-4 font-medium">
|
|
98
|
+
Word Limit
|
|
99
|
+
</h4>
|
|
100
|
+
<div className="space-y-6">
|
|
101
|
+
<div className="space-y-2">
|
|
102
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
103
|
+
20 words
|
|
104
|
+
</p>
|
|
105
|
+
<ClampLines wordLimit={20}>{EPISODE_DESC}</ClampLines>
|
|
106
|
+
</div>
|
|
107
|
+
<div className="space-y-2">
|
|
108
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
109
|
+
40 words
|
|
110
|
+
</p>
|
|
111
|
+
<ClampLines wordLimit={40}>{EPISODE_DESC}</ClampLines>
|
|
112
|
+
</div>
|
|
113
|
+
<div className="space-y-2">
|
|
114
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
115
|
+
CSS line-clamp — 3 lines (no wordLimit)
|
|
116
|
+
</p>
|
|
117
|
+
<ClampLines>{EPISODE_DESC}</ClampLines>
|
|
118
|
+
</div>
|
|
119
|
+
<div className="space-y-2">
|
|
120
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
121
|
+
Short text — no truncation triggered
|
|
122
|
+
</p>
|
|
123
|
+
<ClampLines wordLimit={30}>{SHORT_BIO}</ClampLines>
|
|
124
|
+
</div>
|
|
125
|
+
</div>
|
|
74
126
|
</div>
|
|
75
|
-
),
|
|
76
|
-
],
|
|
77
|
-
}
|
|
78
127
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
128
|
+
{/* Responsive mode */}
|
|
129
|
+
<div>
|
|
130
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md mb-4 font-medium">
|
|
131
|
+
Responsive Mode
|
|
132
|
+
</h4>
|
|
133
|
+
<div className="space-y-2">
|
|
134
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
135
|
+
wordLimit=50, minWordLimit=15 — resize the viewport to see the limit
|
|
136
|
+
adapt
|
|
137
|
+
</p>
|
|
138
|
+
<ClampLines wordLimit={50} responsive minWordLimit={15}>
|
|
139
|
+
{EPISODE_DESC}
|
|
140
|
+
</ClampLines>
|
|
141
|
+
</div>
|
|
142
|
+
</div>
|
|
87
143
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
>
|
|
107
|
-
{open ? "Show less ▲" : "Show more ▼"}
|
|
108
|
-
</button>
|
|
109
|
-
),
|
|
110
|
-
},
|
|
111
|
-
}
|
|
144
|
+
{/* Custom button text */}
|
|
145
|
+
<div>
|
|
146
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md mb-4 font-medium">
|
|
147
|
+
Custom Button Text
|
|
148
|
+
</h4>
|
|
149
|
+
<div className="space-y-2">
|
|
150
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
151
|
+
readMoreText / readLessText overrides
|
|
152
|
+
</p>
|
|
153
|
+
<ClampLines
|
|
154
|
+
wordLimit={25}
|
|
155
|
+
readMoreText="Continue reading →"
|
|
156
|
+
readLessText="← Show less"
|
|
157
|
+
>
|
|
158
|
+
{EPISODE_DESC}
|
|
159
|
+
</ClampLines>
|
|
160
|
+
</div>
|
|
161
|
+
</div>
|
|
112
162
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
163
|
+
{/* Custom render button */}
|
|
164
|
+
<div>
|
|
165
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md mb-4 font-medium">
|
|
166
|
+
Custom Render Button
|
|
167
|
+
</h4>
|
|
168
|
+
<div className="space-y-2">
|
|
169
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
170
|
+
Fully custom button via the button render-prop
|
|
171
|
+
</p>
|
|
172
|
+
<ClampLines
|
|
173
|
+
wordLimit={25}
|
|
174
|
+
button={(open, toggle) => (
|
|
175
|
+
<Button
|
|
176
|
+
variant="outline"
|
|
177
|
+
size="sm"
|
|
178
|
+
onClick={toggle}
|
|
179
|
+
className="ml-1 h-fit"
|
|
180
|
+
innerClassName="px-2 py-0.5"
|
|
181
|
+
>
|
|
182
|
+
{open ? "Show less ▲" : "Show more ▼"}
|
|
183
|
+
</Button>
|
|
184
|
+
)}
|
|
185
|
+
>
|
|
186
|
+
{EPISODE_DESC}
|
|
187
|
+
</ClampLines>
|
|
188
|
+
</div>
|
|
189
|
+
</div>
|
|
190
|
+
</div>
|
|
191
|
+
),
|
|
192
|
+
parameters: {
|
|
193
|
+
docs: {
|
|
194
|
+
description: {
|
|
195
|
+
story:
|
|
196
|
+
"Comparison of all configuration axes: word-count limits, CSS line-clamp mode, responsive scaling, custom button labels, and a custom render-prop button.",
|
|
197
|
+
},
|
|
124
198
|
},
|
|
125
199
|
},
|
|
126
|
-
decorators: [
|
|
127
|
-
(Story) => (
|
|
128
|
-
<>
|
|
129
|
-
<Story />
|
|
130
|
-
<Toaster />
|
|
131
|
-
</>
|
|
132
|
-
),
|
|
133
|
-
],
|
|
134
200
|
}
|
|
135
201
|
|
|
136
|
-
|
|
137
|
-
name: "Short Text (no truncation)",
|
|
138
|
-
args: {
|
|
139
|
-
children: "This text is short enough that it will never be truncated.",
|
|
140
|
-
wordLimit: 20,
|
|
141
|
-
},
|
|
142
|
-
}
|
|
202
|
+
// ─── 2. Interactive ──────────────────────────────────────────────────────────
|
|
143
203
|
|
|
144
|
-
export const
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
204
|
+
export const Interactive: Story = {
|
|
205
|
+
render: () => {
|
|
206
|
+
const [isOpen, setIsOpen] = useState(false)
|
|
207
|
+
const [toggleCount, setToggleCount] = useState(0)
|
|
208
|
+
|
|
209
|
+
const handleToggle = (open: boolean) => {
|
|
210
|
+
setIsOpen(open)
|
|
211
|
+
setToggleCount((c) => c + 1)
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return (
|
|
215
|
+
<div className="w-full p-8">
|
|
216
|
+
<div className="mx-auto max-w-3xl space-y-6">
|
|
217
|
+
<div className="grid grid-cols-1 gap-6 lg:grid-cols-3">
|
|
218
|
+
{/* Controls panel */}
|
|
219
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary space-y-5 rounded-xl border p-5">
|
|
220
|
+
<p className="text-fm-primary font-fm-brand text-fm-sm leading-fm-sm font-semibold tracking-widest uppercase">
|
|
221
|
+
Live State
|
|
222
|
+
</p>
|
|
223
|
+
|
|
224
|
+
<div className="space-y-3">
|
|
225
|
+
<div className="border-fm-divider-secondary rounded-lg border px-4 py-3">
|
|
226
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
227
|
+
Expanded
|
|
228
|
+
</p>
|
|
229
|
+
<p className="text-fm-primary font-fm-brand text-fm-md leading-fm-md font-semibold">
|
|
230
|
+
{isOpen ? "Yes" : "No"}
|
|
231
|
+
</p>
|
|
232
|
+
</div>
|
|
233
|
+
|
|
234
|
+
<div className="border-fm-divider-secondary rounded-lg border px-4 py-3">
|
|
235
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
236
|
+
Toggle count
|
|
237
|
+
</p>
|
|
238
|
+
<p className="text-fm-primary font-fm-brand text-fm-md leading-fm-md font-semibold">
|
|
239
|
+
{toggleCount}
|
|
240
|
+
</p>
|
|
241
|
+
</div>
|
|
242
|
+
</div>
|
|
243
|
+
|
|
244
|
+
<div className="border-fm-divider-secondary border-t pt-4" />
|
|
245
|
+
|
|
246
|
+
<div className="space-y-2">
|
|
247
|
+
<p className="text-fm-primary font-fm-brand text-fm-sm leading-fm-sm font-semibold tracking-widest uppercase">
|
|
248
|
+
About
|
|
249
|
+
</p>
|
|
250
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-4">
|
|
251
|
+
<p className="text-fm-secondary font-fm-text text-fm-md leading-fm-xl">
|
|
252
|
+
The <code className="font-(--font-fm-mono)">onToggle</code>{" "}
|
|
253
|
+
callback fires every time the user clicks the
|
|
254
|
+
expand/collapse button. Use it to track analytics, update
|
|
255
|
+
parent state, or trigger side-effects.
|
|
256
|
+
</p>
|
|
257
|
+
</div>
|
|
258
|
+
</div>
|
|
259
|
+
</div>
|
|
260
|
+
|
|
261
|
+
{/* Preview stage */}
|
|
262
|
+
<div className="flex flex-col gap-3 lg:col-span-2">
|
|
263
|
+
<div
|
|
264
|
+
className="border-fm-divider-secondary bg-fm-surface-secondary rounded-xl border p-6"
|
|
265
|
+
style={{ minHeight: 180 }}
|
|
266
|
+
>
|
|
267
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm mb-3">
|
|
268
|
+
Episode description — click READ MORE / READ LESS
|
|
269
|
+
</p>
|
|
270
|
+
<ClampLines wordLimit={30} onToggle={handleToggle}>
|
|
271
|
+
{EPISODE_DESC}
|
|
272
|
+
</ClampLines>
|
|
273
|
+
</div>
|
|
274
|
+
|
|
275
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border px-4 py-3">
|
|
276
|
+
<code className="text-fm-secondary text-fm-md leading-fm-md font-(--font-fm-mono)">
|
|
277
|
+
{`<ClampLines wordLimit={30} onToggle={(open) => setIsOpen(open)}>`}
|
|
278
|
+
<br />
|
|
279
|
+
{` {episodeDescription}`}
|
|
280
|
+
<br />
|
|
281
|
+
{`</ClampLines>`}
|
|
282
|
+
</code>
|
|
283
|
+
</div>
|
|
284
|
+
</div>
|
|
285
|
+
</div>
|
|
286
|
+
</div>
|
|
166
287
|
</div>
|
|
167
|
-
|
|
168
|
-
|
|
288
|
+
)
|
|
289
|
+
},
|
|
290
|
+
parameters: {
|
|
291
|
+
docs: {
|
|
292
|
+
description: {
|
|
293
|
+
story:
|
|
294
|
+
"Live expand/collapse demo wired to a local state tracker via the onToggle callback. The left panel reflects current open state and cumulative toggle count in real time.",
|
|
295
|
+
},
|
|
296
|
+
},
|
|
297
|
+
},
|
|
169
298
|
}
|