aural-ui 4.2.4 → 4.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/aspect-ratio/AspectRatio.stories.tsx +4 -4
- package/dist/components/badge/Badge.stories.tsx +3 -3
- package/dist/components/button/Button.stories.tsx +288 -366
- package/dist/components/button/index.tsx +3 -43
- package/dist/components/card/Card.stories.tsx +2 -2
- package/dist/components/card/index.tsx +1 -1
- package/dist/components/clamp-lines/index.tsx +0 -1
- package/dist/components/drawer/index.tsx +1 -1
- package/dist/components/hover-card/HoverCard.stories.tsx +7 -7
- package/dist/components/index.ts +1 -1
- package/dist/components/marquee/Marquee.stories.tsx +2 -6
- package/dist/components/offer-label/OfferLabel.stories.tsx +267 -0
- package/dist/components/offer-label/index.tsx +32 -0
- package/dist/components/offer-label/meta.ts +6 -0
- package/dist/components/otp-inputs/OtpInputs.stories.tsx +1 -1
- package/dist/components/popover/Popover.stories.tsx +1 -1
- package/dist/components/slider/index.tsx +1 -6
- package/dist/components/table/Table.stories.tsx +4 -4
- package/dist/components/toggle/Toggle.stories.tsx +4 -4
- package/dist/components/tooltip/index.tsx +1 -2
- package/dist/components/typography/Typography.stories.tsx +7 -19
- package/dist/components/typography/index.tsx +0 -2
- package/dist/fonts/LabGrotesque-Medium.ttf +0 -0
- package/dist/icons/all-icons.tsx +9 -7
- package/dist/icons/chain-link-icon/ChainLinkIcon.stories.tsx +167 -0
- package/dist/icons/chain-link-icon/index.tsx +30 -0
- package/dist/icons/chain-link-icon/meta.ts +8 -0
- package/dist/icons/clock-icon/ClockIcon.stories.tsx +210 -0
- package/dist/icons/clock-icon/index.tsx +28 -0
- package/dist/icons/clock-icon/meta.ts +8 -0
- package/dist/icons/headphone-icon/HeadphoneIcon.stories.tsx +186 -0
- package/dist/icons/headphone-icon/index.tsx +49 -0
- package/dist/icons/headphone-icon/meta.ts +8 -0
- package/dist/icons/index.ts +5 -1
- package/dist/icons/site-logo-icon/SiteLogoIcon.stories.tsx +3 -3
- package/dist/icons/underline-icon/UnderlineIcon.stories.tsx +238 -0
- package/dist/icons/underline-icon/index.tsx +58 -0
- package/dist/icons/underline-icon/meta.ts +8 -0
- package/dist/index.cjs +86 -86
- package/dist/index.js +86 -86
- package/package.json +5 -5
- package/dist/fonts/LabGrotesqueTRIAL-Bold.otf +0 -0
- package/dist/fonts/LabGrotesqueTRIAL-Light.otf +0 -0
- package/dist/fonts/LabGrotesqueTRIAL-Medium.otf +0 -0
- package/dist/fonts/LabGrotesqueTRIAL-Regular.otf +0 -0
- package/dist/fonts/PPSupplySans-Regular (1).otf +0 -0
- package/dist/fonts/PPSupplySans-Ultralight.otf +0 -0
|
@@ -80,18 +80,6 @@ export const innerButtonVariants = cva(
|
|
|
80
80
|
},
|
|
81
81
|
},
|
|
82
82
|
compoundVariants: [
|
|
83
|
-
{
|
|
84
|
-
variant: "primary",
|
|
85
|
-
noise: "low",
|
|
86
|
-
className:
|
|
87
|
-
"[background-image:var(--button-fm-noise-low),_radial-gradient(ellipse_var(--gradientSizeX)_var(--gradientSizeY)_at_50%_var(--gradientPositionY),_var(--color-fm-primary-600),_var(--color-fm-button-fg-end)),_linear-gradient(_to_top,_color-mix(in_srgb,var(--color-fm-primary-600)_50%,_transparent),_color-mix(in_srgb,var(--color-fm-primary-200)_50%,_transparent))]",
|
|
88
|
-
},
|
|
89
|
-
{
|
|
90
|
-
variant: "primary",
|
|
91
|
-
noise: "medium",
|
|
92
|
-
className:
|
|
93
|
-
"[background-image:var(--button-fm-noise),_radial-gradient(ellipse_var(--gradientSizeX)_var(--gradientSizeY)_at_50%_var(--gradientPositionY),_var(--color-fm-primary-600),_var(--color-fm-button-fg-end)),_linear-gradient(_to_top,_color-mix(in_srgb,var(--color-fm-primary-600)_50%,_transparent),_color-mix(in_srgb,var(--color-fm-primary-200)_50%,_transparent))]",
|
|
94
|
-
},
|
|
95
83
|
{
|
|
96
84
|
variant: "primary",
|
|
97
85
|
noise: "strong",
|
|
@@ -103,31 +91,6 @@ export const innerButtonVariants = cva(
|
|
|
103
91
|
noise: "low",
|
|
104
92
|
className: "[background-image:var(--button-fm-noise-low)]",
|
|
105
93
|
},
|
|
106
|
-
{
|
|
107
|
-
variant: "secondary",
|
|
108
|
-
noise: "medium",
|
|
109
|
-
className: "[background-image:var(--button-fm-noise)]",
|
|
110
|
-
},
|
|
111
|
-
{
|
|
112
|
-
variant: "secondary",
|
|
113
|
-
noise: "strong",
|
|
114
|
-
className: "[background-image:var(--button-fm-noise-strong)]",
|
|
115
|
-
},
|
|
116
|
-
{
|
|
117
|
-
variant: "chipActive",
|
|
118
|
-
noise: "low",
|
|
119
|
-
className: "[background-image:var(--button-fm-noise-low)]",
|
|
120
|
-
},
|
|
121
|
-
{
|
|
122
|
-
variant: "chipActive",
|
|
123
|
-
noise: "medium",
|
|
124
|
-
className: "[background-image:var(--button-fm-noise)]",
|
|
125
|
-
},
|
|
126
|
-
{
|
|
127
|
-
variant: "chipActive",
|
|
128
|
-
noise: "strong",
|
|
129
|
-
className: "[background-image:var(--button-fm-noise-strong)]",
|
|
130
|
-
},
|
|
131
94
|
],
|
|
132
95
|
defaultVariants: {
|
|
133
96
|
variant: "primary",
|
|
@@ -148,7 +111,6 @@ export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
|
148
111
|
isDisabled?: boolean
|
|
149
112
|
size?: "sm" | "md" | "lg"
|
|
150
113
|
variant?: "primary" | "secondary" | "outline" | "text" | "chip" | "chipActive"
|
|
151
|
-
noise?: "none" | "low" | "medium" | "strong"
|
|
152
114
|
}
|
|
153
115
|
|
|
154
116
|
export const RawButton = forwardRef<HTMLButtonElement, ButtonProps>(
|
|
@@ -156,7 +118,6 @@ export const RawButton = forwardRef<HTMLButtonElement, ButtonProps>(
|
|
|
156
118
|
{
|
|
157
119
|
variant = "primary",
|
|
158
120
|
size = "md",
|
|
159
|
-
noise: noiseProp,
|
|
160
121
|
children,
|
|
161
122
|
className = "",
|
|
162
123
|
innerClassName = "",
|
|
@@ -169,12 +130,11 @@ export const RawButton = forwardRef<HTMLButtonElement, ButtonProps>(
|
|
|
169
130
|
ref
|
|
170
131
|
) => {
|
|
171
132
|
const noise =
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
? "medium"
|
|
133
|
+
variant === "primary"
|
|
134
|
+
? "strong"
|
|
175
135
|
: variant === "secondary"
|
|
176
136
|
? "low"
|
|
177
|
-
: "none"
|
|
137
|
+
: "none"
|
|
178
138
|
|
|
179
139
|
const iconColor = isDisabled
|
|
180
140
|
? "var(--icon-fm-inactive)"
|
|
@@ -443,7 +443,7 @@ export const UseCases: Story = {
|
|
|
443
443
|
<div className="mx-auto max-w-md">
|
|
444
444
|
<Card>
|
|
445
445
|
<CardHeader>
|
|
446
|
-
<CardTitle className="text-fm-primary font-fm-text text-fm-lg leading-fm-lg flex items-center gap-2 font-
|
|
446
|
+
<CardTitle className="text-fm-primary font-fm-text text-fm-lg leading-fm-lg flex items-center gap-2 font-medium">
|
|
447
447
|
<MusicalNoteIcon className="text-fm-secondary size-4 shrink-0" />
|
|
448
448
|
Midnight Dreams
|
|
449
449
|
</CardTitle>
|
|
@@ -503,7 +503,7 @@ export const UseCases: Story = {
|
|
|
503
503
|
<Card>
|
|
504
504
|
<CardHeader className="border-b">
|
|
505
505
|
<CardTitle className="text-fm-primary font-fm-brand text-fm-xl leading-fm-xl flex items-center gap-3 font-semibold">
|
|
506
|
-
<div className="bg-fm-surface-secondary text-fm-primary flex size-10 shrink-0 items-center justify-center rounded-full font-
|
|
506
|
+
<div className="bg-fm-surface-secondary text-fm-primary flex size-10 shrink-0 items-center justify-center rounded-full font-medium">
|
|
507
507
|
NC
|
|
508
508
|
</div>
|
|
509
509
|
Neon Collective
|
|
@@ -31,7 +31,7 @@ function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
|
|
|
31
31
|
return (
|
|
32
32
|
<div
|
|
33
33
|
data-slot="card-title"
|
|
34
|
-
className={cn("leading-none font-
|
|
34
|
+
className={cn("leading-none font-medium", className)}
|
|
35
35
|
{...props}
|
|
36
36
|
/>
|
|
37
37
|
)
|
|
@@ -76,7 +76,7 @@ export const Parts: Story = {
|
|
|
76
76
|
</HoverCardTrigger>
|
|
77
77
|
<HoverCardContent>
|
|
78
78
|
<div className="space-y-1">
|
|
79
|
-
<p className="text-fm-primary font-fm-text text-fm-md leading-fm-md font-
|
|
79
|
+
<p className="text-fm-primary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
80
80
|
Aural Artist
|
|
81
81
|
</p>
|
|
82
82
|
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
@@ -106,7 +106,7 @@ export const Parts: Story = {
|
|
|
106
106
|
</HoverCardTrigger>
|
|
107
107
|
<HoverCardContent>
|
|
108
108
|
<div className="space-y-2">
|
|
109
|
-
<p className="text-fm-primary font-fm-text text-fm-md leading-fm-md font-
|
|
109
|
+
<p className="text-fm-primary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
110
110
|
Frosted glass panel
|
|
111
111
|
</p>
|
|
112
112
|
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
@@ -255,7 +255,7 @@ export const UseCases: Story = {
|
|
|
255
255
|
Midnights ·{" "}
|
|
256
256
|
<HoverCard openDelay={300} closeDelay={150}>
|
|
257
257
|
<HoverCardTrigger asChild>
|
|
258
|
-
<button className="text-fm-primary cursor-pointer font-
|
|
258
|
+
<button className="text-fm-primary cursor-pointer font-medium underline underline-offset-2 outline-none">
|
|
259
259
|
Taylor Swift
|
|
260
260
|
</button>
|
|
261
261
|
</HoverCardTrigger>
|
|
@@ -268,7 +268,7 @@ export const UseCases: Story = {
|
|
|
268
268
|
</span>
|
|
269
269
|
</div>
|
|
270
270
|
<div className="space-y-0.5">
|
|
271
|
-
<p className="text-fm-primary font-fm-text text-fm-md leading-fm-md font-
|
|
271
|
+
<p className="text-fm-primary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
272
272
|
Taylor Swift
|
|
273
273
|
</p>
|
|
274
274
|
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
@@ -337,7 +337,7 @@ export const UseCases: Story = {
|
|
|
337
337
|
</HoverCardTrigger>
|
|
338
338
|
<HoverCardContent className="w-64">
|
|
339
339
|
<div className="space-y-2">
|
|
340
|
-
<p className="text-fm-primary font-fm-text text-fm-md leading-fm-md font-
|
|
340
|
+
<p className="text-fm-primary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
341
341
|
{album.name}
|
|
342
342
|
</p>
|
|
343
343
|
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
@@ -388,7 +388,7 @@ export const UseCases: Story = {
|
|
|
388
388
|
>
|
|
389
389
|
<HoverCard openDelay={300} closeDelay={200}>
|
|
390
390
|
<HoverCardTrigger asChild>
|
|
391
|
-
<button className="text-fm-primary cursor-pointer font-
|
|
391
|
+
<button className="text-fm-primary cursor-pointer font-medium underline underline-offset-2 outline-none">
|
|
392
392
|
{handle}
|
|
393
393
|
</button>
|
|
394
394
|
</HoverCardTrigger>
|
|
@@ -401,7 +401,7 @@ export const UseCases: Story = {
|
|
|
401
401
|
</span>
|
|
402
402
|
</div>
|
|
403
403
|
<div>
|
|
404
|
-
<p className="text-fm-primary font-fm-text text-fm-md leading-fm-md font-
|
|
404
|
+
<p className="text-fm-primary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
405
405
|
{name}
|
|
406
406
|
</p>
|
|
407
407
|
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
package/dist/components/index.ts
CHANGED
|
@@ -23,9 +23,9 @@ export * from "./if-else"
|
|
|
23
23
|
export * from "./label"
|
|
24
24
|
export * from "./list"
|
|
25
25
|
export * from "./marquee"
|
|
26
|
+
export * from "./offer-label"
|
|
26
27
|
export * from "./otp-inputs"
|
|
27
28
|
export * from "./overlay"
|
|
28
|
-
export * from "./otp-inputs"
|
|
29
29
|
export * from "./pagination"
|
|
30
30
|
export * from "./popover"
|
|
31
31
|
export * from "./radio"
|
|
@@ -77,11 +77,7 @@ function TokenChip({
|
|
|
77
77
|
}: {
|
|
78
78
|
label: string
|
|
79
79
|
surface:
|
|
80
|
-
| "
|
|
81
|
-
| "info-sec"
|
|
82
|
-
| "positive-sec"
|
|
83
|
-
| "warning-sec"
|
|
84
|
-
| "negative-sec"
|
|
80
|
+
"secondary" | "info-sec" | "positive-sec" | "warning-sec" | "negative-sec"
|
|
85
81
|
}) {
|
|
86
82
|
const surfaceClass = {
|
|
87
83
|
secondary: "bg-fm-surface-secondary border-fm-divider-secondary",
|
|
@@ -344,7 +340,7 @@ export const UseCases: Story = {
|
|
|
344
340
|
Announcements Ticker
|
|
345
341
|
</h4>
|
|
346
342
|
<div className="border-fm-divider-secondary bg-fm-surface-secondary flex items-center gap-3 overflow-hidden rounded-lg border px-4 py-2">
|
|
347
|
-
<div className="bg-fm-surface-negative-sec text-fm-primary text-fm-xs leading-fm-xs shrink-0 rounded px-2 py-0.5 font-
|
|
343
|
+
<div className="bg-fm-surface-negative-sec text-fm-primary text-fm-xs leading-fm-xs shrink-0 rounded px-2 py-0.5 font-medium tracking-widest uppercase">
|
|
348
344
|
Live
|
|
349
345
|
</div>
|
|
350
346
|
<Marquee duration="28s" pauseOnHover className="flex-1">
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import React from "react"
|
|
2
|
+
import type { Meta, StoryObj } from "@storybook/react-vite"
|
|
3
|
+
|
|
4
|
+
import { AuralComponentDocsPage } from "src/ui/story-spec/components/component-story-docs-page"
|
|
5
|
+
|
|
6
|
+
import { OfferLabel } from "."
|
|
7
|
+
|
|
8
|
+
const meta: Meta<typeof OfferLabel> = {
|
|
9
|
+
title: "Components/UI/OfferLabel",
|
|
10
|
+
component: OfferLabel,
|
|
11
|
+
parameters: {
|
|
12
|
+
layout: "centered",
|
|
13
|
+
docs: {
|
|
14
|
+
description: {
|
|
15
|
+
component:
|
|
16
|
+
"An inline label that renders text with a decorative gradient underline stroke beneath it — ideal for surfacing promotional copy, highlighted offers, or key phrases.",
|
|
17
|
+
},
|
|
18
|
+
page: () => (
|
|
19
|
+
<AuralComponentDocsPage
|
|
20
|
+
features={[
|
|
21
|
+
{
|
|
22
|
+
title: "Gradient Underline",
|
|
23
|
+
description: "Animated SVG accent",
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
title: "Composable Text",
|
|
27
|
+
description: "Accepts any className",
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
title: "SSR Safe",
|
|
31
|
+
description: "Stable gradient ID prop",
|
|
32
|
+
},
|
|
33
|
+
]}
|
|
34
|
+
/>
|
|
35
|
+
),
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
tags: ["autodocs"],
|
|
39
|
+
argTypes: {
|
|
40
|
+
text: {
|
|
41
|
+
control: "text",
|
|
42
|
+
description: "The label text to display",
|
|
43
|
+
},
|
|
44
|
+
className: {
|
|
45
|
+
control: "text",
|
|
46
|
+
description: "CSS classes applied to the inner text span",
|
|
47
|
+
},
|
|
48
|
+
iconId: {
|
|
49
|
+
control: "text",
|
|
50
|
+
description: "Optional stable ID for the underline gradient",
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export default meta
|
|
56
|
+
type Story = StoryObj<typeof OfferLabel>
|
|
57
|
+
|
|
58
|
+
// ─── 1. Playground ────────────────────────────────────────────────────────────
|
|
59
|
+
|
|
60
|
+
export const Playground: Story = {
|
|
61
|
+
args: {
|
|
62
|
+
text: "Limited Offer",
|
|
63
|
+
className:
|
|
64
|
+
"text-fm-primary font-fm-brand text-fm-2xl leading-fm-2xl font-bold",
|
|
65
|
+
},
|
|
66
|
+
render: (args) => (
|
|
67
|
+
<div className="w-full max-w-sm space-y-4">
|
|
68
|
+
<div className="flex justify-center py-4">
|
|
69
|
+
<OfferLabel {...args} />
|
|
70
|
+
</div>
|
|
71
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border px-4 py-3">
|
|
72
|
+
<code className="text-fm-secondary text-fm-md leading-fm-md font-(--font-fm-mono)">{`<OfferLabel text="${args.text}" className="${args.className ?? ""}" />`}</code>
|
|
73
|
+
</div>
|
|
74
|
+
</div>
|
|
75
|
+
),
|
|
76
|
+
parameters: {
|
|
77
|
+
docs: {
|
|
78
|
+
description: {
|
|
79
|
+
story:
|
|
80
|
+
"Adjust the text and className using the controls panel in the sidebar.",
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// ─── 2. All Variants ──────────────────────────────────────────────────────────
|
|
87
|
+
|
|
88
|
+
export const AllVariants: Story = {
|
|
89
|
+
render: () => (
|
|
90
|
+
<div className="space-y-8">
|
|
91
|
+
<div className="space-y-4">
|
|
92
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
93
|
+
Typography Scale
|
|
94
|
+
</h4>
|
|
95
|
+
<div className="flex flex-wrap items-end gap-6">
|
|
96
|
+
<div className="space-y-2 text-center">
|
|
97
|
+
<OfferLabel
|
|
98
|
+
text="Headline"
|
|
99
|
+
className="text-fm-primary font-fm-brand text-fm-4xl leading-fm-4xl font-bold"
|
|
100
|
+
iconId="variant-4xl"
|
|
101
|
+
/>
|
|
102
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
103
|
+
4xl / bold
|
|
104
|
+
</p>
|
|
105
|
+
</div>
|
|
106
|
+
<div className="space-y-2 text-center">
|
|
107
|
+
<OfferLabel
|
|
108
|
+
text="Subheading"
|
|
109
|
+
className="text-fm-primary font-fm-brand text-fm-2xl leading-fm-2xl font-semibold"
|
|
110
|
+
iconId="variant-2xl"
|
|
111
|
+
/>
|
|
112
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
113
|
+
2xl / semibold
|
|
114
|
+
</p>
|
|
115
|
+
</div>
|
|
116
|
+
<div className="space-y-2 text-center">
|
|
117
|
+
<OfferLabel
|
|
118
|
+
text="Body label"
|
|
119
|
+
className="text-fm-primary font-fm-text text-fm-lg leading-fm-lg font-medium"
|
|
120
|
+
iconId="variant-lg"
|
|
121
|
+
/>
|
|
122
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
123
|
+
lg / medium
|
|
124
|
+
</p>
|
|
125
|
+
</div>
|
|
126
|
+
<div className="space-y-2 text-center">
|
|
127
|
+
<OfferLabel
|
|
128
|
+
text="Small"
|
|
129
|
+
className="text-fm-primary font-fm-text text-fm-sm leading-fm-sm"
|
|
130
|
+
iconId="variant-sm"
|
|
131
|
+
/>
|
|
132
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
133
|
+
sm / regular
|
|
134
|
+
</p>
|
|
135
|
+
</div>
|
|
136
|
+
</div>
|
|
137
|
+
</div>
|
|
138
|
+
|
|
139
|
+
<div className="space-y-4">
|
|
140
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
141
|
+
Text Color
|
|
142
|
+
</h4>
|
|
143
|
+
<div className="flex flex-wrap items-end gap-6">
|
|
144
|
+
<div className="space-y-2 text-center">
|
|
145
|
+
<OfferLabel
|
|
146
|
+
text="Primary"
|
|
147
|
+
className="text-fm-primary font-fm-brand text-fm-2xl leading-fm-2xl font-bold"
|
|
148
|
+
iconId="color-primary"
|
|
149
|
+
/>
|
|
150
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
151
|
+
text-fm-primary
|
|
152
|
+
</p>
|
|
153
|
+
</div>
|
|
154
|
+
<div className="space-y-2 text-center">
|
|
155
|
+
<OfferLabel
|
|
156
|
+
text="Secondary"
|
|
157
|
+
className="text-fm-secondary font-fm-brand text-fm-2xl leading-fm-2xl font-bold"
|
|
158
|
+
iconId="color-secondary"
|
|
159
|
+
/>
|
|
160
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
161
|
+
text-fm-secondary
|
|
162
|
+
</p>
|
|
163
|
+
</div>
|
|
164
|
+
<div className="space-y-2 text-center">
|
|
165
|
+
<OfferLabel
|
|
166
|
+
text="Tertiary"
|
|
167
|
+
className="text-fm-tertiary font-fm-brand text-fm-2xl leading-fm-2xl font-bold"
|
|
168
|
+
iconId="color-tertiary"
|
|
169
|
+
/>
|
|
170
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
171
|
+
text-fm-tertiary
|
|
172
|
+
</p>
|
|
173
|
+
</div>
|
|
174
|
+
</div>
|
|
175
|
+
</div>
|
|
176
|
+
</div>
|
|
177
|
+
),
|
|
178
|
+
parameters: {
|
|
179
|
+
docs: {
|
|
180
|
+
description: {
|
|
181
|
+
story:
|
|
182
|
+
"OfferLabel across different type scales and text color tokens — the gradient underline adapts naturally to each.",
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// ─── 3. Use Cases ─────────────────────────────────────────────────────────────
|
|
189
|
+
|
|
190
|
+
export const UseCases: Story = {
|
|
191
|
+
render: () => (
|
|
192
|
+
<div className="mx-auto max-w-3xl space-y-8 p-8">
|
|
193
|
+
<div className="space-y-4">
|
|
194
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
195
|
+
Promotional Hero Banner
|
|
196
|
+
</h4>
|
|
197
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary mx-auto max-w-md space-y-3 rounded-xl border p-6 text-center">
|
|
198
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm tracking-widest uppercase">
|
|
199
|
+
Pocket FM Premium
|
|
200
|
+
</p>
|
|
201
|
+
<div className="flex justify-center">
|
|
202
|
+
<OfferLabel
|
|
203
|
+
text="3 Months Free"
|
|
204
|
+
className="text-fm-primary font-fm-brand text-fm-4xl leading-fm-4xl font-bold"
|
|
205
|
+
iconId="use-case-hero"
|
|
206
|
+
/>
|
|
207
|
+
</div>
|
|
208
|
+
<p className="text-fm-secondary font-fm-text text-fm-md leading-fm-md">
|
|
209
|
+
Unlock unlimited access to all audio stories.
|
|
210
|
+
</p>
|
|
211
|
+
</div>
|
|
212
|
+
</div>
|
|
213
|
+
|
|
214
|
+
<div className="space-y-4">
|
|
215
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
216
|
+
Inline Promotional Copy
|
|
217
|
+
</h4>
|
|
218
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary mx-auto max-w-md rounded-xl border p-5">
|
|
219
|
+
<p className="text-fm-primary font-fm-text text-fm-lg leading-fm-xl">
|
|
220
|
+
Subscribe today and get{" "}
|
|
221
|
+
<OfferLabel
|
|
222
|
+
text="50% off"
|
|
223
|
+
className="text-fm-primary font-fm-brand text-fm-lg leading-fm-xl font-semibold"
|
|
224
|
+
iconId="use-case-inline"
|
|
225
|
+
/>{" "}
|
|
226
|
+
your first month — no strings attached.
|
|
227
|
+
</p>
|
|
228
|
+
</div>
|
|
229
|
+
</div>
|
|
230
|
+
|
|
231
|
+
<div className="space-y-4">
|
|
232
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
233
|
+
Pricing Card Highlight
|
|
234
|
+
</h4>
|
|
235
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary mx-auto max-w-sm space-y-4 rounded-xl border p-6">
|
|
236
|
+
<div className="space-y-1">
|
|
237
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm tracking-widest uppercase">
|
|
238
|
+
Annual Plan
|
|
239
|
+
</p>
|
|
240
|
+
<div className="flex items-baseline gap-1">
|
|
241
|
+
<OfferLabel
|
|
242
|
+
text="₹999"
|
|
243
|
+
className="text-fm-primary font-fm-brand text-fm-5xl leading-fm-5xl font-bold"
|
|
244
|
+
iconId="use-case-price"
|
|
245
|
+
/>
|
|
246
|
+
<span className="text-fm-secondary font-fm-text text-fm-md leading-fm-md">
|
|
247
|
+
/ year
|
|
248
|
+
</span>
|
|
249
|
+
</div>
|
|
250
|
+
</div>
|
|
251
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
252
|
+
Save 40% compared to the monthly plan.
|
|
253
|
+
</p>
|
|
254
|
+
</div>
|
|
255
|
+
</div>
|
|
256
|
+
</div>
|
|
257
|
+
),
|
|
258
|
+
parameters: {
|
|
259
|
+
layout: "fullscreen",
|
|
260
|
+
docs: {
|
|
261
|
+
description: {
|
|
262
|
+
story:
|
|
263
|
+
"Real-world usage: promotional hero banners, inline highlighted copy, and pricing card accents.",
|
|
264
|
+
},
|
|
265
|
+
},
|
|
266
|
+
},
|
|
267
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import React from "react"
|
|
2
|
+
import { UnderlineIcon } from "@icons/underline-icon"
|
|
3
|
+
import { cn } from "@lib/utils"
|
|
4
|
+
|
|
5
|
+
export interface IOfferLabelProps {
|
|
6
|
+
className?: string
|
|
7
|
+
iconClass?: string
|
|
8
|
+
/**
|
|
9
|
+
* Optional stable ID for the underline gradient. Can help if SSR hydration mismatches occur.
|
|
10
|
+
*/
|
|
11
|
+
iconId?: string
|
|
12
|
+
text: string
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function OfferLabel({
|
|
16
|
+
text,
|
|
17
|
+
className,
|
|
18
|
+
iconId,
|
|
19
|
+
iconClass,
|
|
20
|
+
}: IOfferLabelProps) {
|
|
21
|
+
return (
|
|
22
|
+
<span className="relative inline-block pb-1">
|
|
23
|
+
<span className={className}>{text}</span>
|
|
24
|
+
<UnderlineIcon
|
|
25
|
+
id={iconId}
|
|
26
|
+
aria-hidden="true"
|
|
27
|
+
withAccessibility={false}
|
|
28
|
+
className={cn("absolute left-0 w-8", iconClass)}
|
|
29
|
+
/>
|
|
30
|
+
</span>
|
|
31
|
+
)
|
|
32
|
+
}
|
|
@@ -376,7 +376,7 @@ export const Interactive: Story = {
|
|
|
376
376
|
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-xl border p-6">
|
|
377
377
|
<div className="space-y-4">
|
|
378
378
|
<div className="space-y-1">
|
|
379
|
-
<p className="text-fm-primary font-fm-text text-fm-md leading-fm-md font-
|
|
379
|
+
<p className="text-fm-primary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
380
380
|
Verify your identity
|
|
381
381
|
</p>
|
|
382
382
|
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
@@ -291,7 +291,7 @@ export const Configurations: Story = {
|
|
|
291
291
|
<PopoverContent className="w-64 rounded-lg p-4">
|
|
292
292
|
<div className="flex items-start justify-between gap-3">
|
|
293
293
|
<div className="space-y-1">
|
|
294
|
-
<p className="text-fm-primary font-fm-text text-fm-md leading-fm-md font-
|
|
294
|
+
<p className="text-fm-primary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
295
295
|
Quick note
|
|
296
296
|
</p>
|
|
297
297
|
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
@@ -61,12 +61,7 @@ interface SliderProps extends React.ComponentProps<
|
|
|
61
61
|
typeof SliderPrimitive.Root
|
|
62
62
|
> {
|
|
63
63
|
variant?:
|
|
64
|
-
| "
|
|
65
|
-
| "primary"
|
|
66
|
-
| "secondary"
|
|
67
|
-
| "positive"
|
|
68
|
-
| "warning"
|
|
69
|
-
| "info"
|
|
64
|
+
"default" | "primary" | "secondary" | "positive" | "warning" | "info"
|
|
70
65
|
size?: "sm" | "md" | "lg"
|
|
71
66
|
showLabel?: boolean
|
|
72
67
|
label?: string
|
|
@@ -298,8 +298,8 @@ export const Parts: Story = {
|
|
|
298
298
|
</TableBody>
|
|
299
299
|
<TableFooter>
|
|
300
300
|
<TableRow>
|
|
301
|
-
<TableCell className="font-
|
|
302
|
-
<TableCell className="text-right font-
|
|
301
|
+
<TableCell className="font-medium">Total</TableCell>
|
|
302
|
+
<TableCell className="text-right font-medium">2.09M</TableCell>
|
|
303
303
|
</TableRow>
|
|
304
304
|
</TableFooter>
|
|
305
305
|
</Table>
|
|
@@ -846,10 +846,10 @@ export const UseCases: Story = {
|
|
|
846
846
|
</TableBody>
|
|
847
847
|
<TableFooter>
|
|
848
848
|
<TableRow>
|
|
849
|
-
<TableCell colSpan={4} className="font-
|
|
849
|
+
<TableCell colSpan={4} className="font-medium">
|
|
850
850
|
4 albums
|
|
851
851
|
</TableCell>
|
|
852
|
-
<TableCell className="font-
|
|
852
|
+
<TableCell className="font-medium">
|
|
853
853
|
{albums.reduce((s, a) => s + a.tracks, 0)}
|
|
854
854
|
</TableCell>
|
|
855
855
|
<TableCell />
|
|
@@ -491,19 +491,19 @@ export const Interactive: Story = {
|
|
|
491
491
|
<div className="flex flex-col gap-1">
|
|
492
492
|
<p className="text-fm-primary font-fm-text text-fm-sm leading-fm-sm">
|
|
493
493
|
Shuffle:{" "}
|
|
494
|
-
<span className="font-
|
|
494
|
+
<span className="font-medium">
|
|
495
495
|
{playback.shuffle ? "ON" : "OFF"}
|
|
496
496
|
</span>
|
|
497
497
|
</p>
|
|
498
498
|
<p className="text-fm-primary font-fm-text text-fm-sm leading-fm-sm">
|
|
499
499
|
Repeat:{" "}
|
|
500
|
-
<span className="font-
|
|
500
|
+
<span className="font-medium">
|
|
501
501
|
{playback.repeat ? "ON" : "OFF"}
|
|
502
502
|
</span>
|
|
503
503
|
</p>
|
|
504
504
|
<p className="text-fm-primary font-fm-text text-fm-sm leading-fm-sm">
|
|
505
505
|
Mute:{" "}
|
|
506
|
-
<span className="font-
|
|
506
|
+
<span className="font-medium">
|
|
507
507
|
{playback.mute ? "ON" : "OFF"}
|
|
508
508
|
</span>
|
|
509
509
|
</p>
|
|
@@ -536,7 +536,7 @@ export const Interactive: Story = {
|
|
|
536
536
|
onPressedChange={() => toggleFormat("bold")}
|
|
537
537
|
aria-label="Toggle bold"
|
|
538
538
|
>
|
|
539
|
-
<span className="font-
|
|
539
|
+
<span className="font-medium">B</span>
|
|
540
540
|
</Toggle>
|
|
541
541
|
<Toggle
|
|
542
542
|
size="sm"
|
|
@@ -305,8 +305,7 @@ function TooltipContent({
|
|
|
305
305
|
|
|
306
306
|
export function withTooltip<
|
|
307
307
|
T extends
|
|
308
|
-
|
|
309
|
-
| React.ForwardRefExoticComponent<any>,
|
|
308
|
+
keyof React.JSX.IntrinsicElements | React.ForwardRefExoticComponent<any>,
|
|
310
309
|
>(Component: T) {
|
|
311
310
|
return React.forwardRef<
|
|
312
311
|
React.ElementRef<T>,
|