@sovereignfs/ui 0.21.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/LICENSE +661 -0
- package/NOTICE +24 -0
- package/dist/Avatar.module.css +38 -0
- package/dist/Badge.module.css +88 -0
- package/dist/Button.module.css +77 -0
- package/dist/Card.module.css +34 -0
- package/dist/Dialog.module.css +188 -0
- package/dist/Drawer.module.css +30 -0
- package/dist/EmptyState.module.css +27 -0
- package/dist/FormField.module.css +28 -0
- package/dist/Icon.module.css +22 -0
- package/dist/Input.module.css +37 -0
- package/dist/NavTabs.module.css +48 -0
- package/dist/PageHeader.module.css +32 -0
- package/dist/Popover.module.css +44 -0
- package/dist/SegmentedControl.module.css +53 -0
- package/dist/Select.module.css +69 -0
- package/dist/Spinner.module.css +39 -0
- package/dist/SystemBanner.module.css +67 -0
- package/dist/Tabs.module.css +49 -0
- package/dist/Toast.module.css +130 -0
- package/dist/Toggle.module.css +52 -0
- package/dist/Tooltip.module.css +51 -0
- package/dist/index.d.ts +327 -0
- package/dist/index.js +1370 -0
- package/dist/tokens/primitives.css +99 -0
- package/dist/tokens/semantic.css +111 -0
- package/dist/tokens.css +5 -0
- package/package.json +50 -0
- package/src/components/Avatar/Avatar.module.css +38 -0
- package/src/components/Avatar/Avatar.tsx +42 -0
- package/src/components/Badge/Badge.module.css +88 -0
- package/src/components/Badge/Badge.stories.tsx +118 -0
- package/src/components/Badge/Badge.tsx +59 -0
- package/src/components/Badge/__tests__/Badge.test.tsx +64 -0
- package/src/components/Button/Button.module.css +77 -0
- package/src/components/Button/Button.stories.tsx +76 -0
- package/src/components/Button/Button.tsx +36 -0
- package/src/components/Button/__tests__/Button.test.tsx +37 -0
- package/src/components/Card/Card.module.css +34 -0
- package/src/components/Card/Card.tsx +34 -0
- package/src/components/Dialog/Dialog.module.css +188 -0
- package/src/components/Dialog/Dialog.stories.tsx +97 -0
- package/src/components/Dialog/Dialog.tsx +137 -0
- package/src/components/Dialog/__tests__/Dialog.test.tsx +73 -0
- package/src/components/Drawer/Drawer.module.css +30 -0
- package/src/components/Drawer/Drawer.stories.tsx +88 -0
- package/src/components/Drawer/Drawer.tsx +103 -0
- package/src/components/Drawer/__tests__/Drawer.test.tsx +56 -0
- package/src/components/EmptyState/EmptyState.module.css +27 -0
- package/src/components/EmptyState/EmptyState.tsx +27 -0
- package/src/components/FormField/FormField.module.css +28 -0
- package/src/components/FormField/FormField.tsx +53 -0
- package/src/components/Icon/Icon.module.css +22 -0
- package/src/components/Icon/Icon.stories.tsx +94 -0
- package/src/components/Icon/Icon.tsx +43 -0
- package/src/components/Icon/__tests__/Icon.test.tsx +40 -0
- package/src/components/Icon/icons/activity.tsx +20 -0
- package/src/components/Icon/icons/alert-triangle.tsx +22 -0
- package/src/components/Icon/icons/bell.tsx +21 -0
- package/src/components/Icon/icons/check.tsx +20 -0
- package/src/components/Icon/icons/chevron-down.tsx +20 -0
- package/src/components/Icon/icons/chevron-left.tsx +20 -0
- package/src/components/Icon/icons/chevron-right.tsx +20 -0
- package/src/components/Icon/icons/chevron-up.tsx +20 -0
- package/src/components/Icon/icons/eye-off.tsx +23 -0
- package/src/components/Icon/icons/eye.tsx +21 -0
- package/src/components/Icon/icons/grid-2x2.tsx +22 -0
- package/src/components/Icon/icons/house.tsx +21 -0
- package/src/components/Icon/icons/index.ts +122 -0
- package/src/components/Icon/icons/info.tsx +22 -0
- package/src/components/Icon/icons/lock.tsx +21 -0
- package/src/components/Icon/icons/log-out.tsx +22 -0
- package/src/components/Icon/icons/mail.tsx +21 -0
- package/src/components/Icon/icons/package.tsx +23 -0
- package/src/components/Icon/icons/pencil.tsx +21 -0
- package/src/components/Icon/icons/plus.tsx +21 -0
- package/src/components/Icon/icons/rotate-ccw.tsx +21 -0
- package/src/components/Icon/icons/search.tsx +21 -0
- package/src/components/Icon/icons/settings.tsx +21 -0
- package/src/components/Icon/icons/shield.tsx +20 -0
- package/src/components/Icon/icons/sliders-horizontal.tsx +28 -0
- package/src/components/Icon/icons/terminal.tsx +19 -0
- package/src/components/Icon/icons/trash-2.tsx +24 -0
- package/src/components/Icon/icons/user.tsx +21 -0
- package/src/components/Icon/icons/x.tsx +21 -0
- package/src/components/Input/Input.module.css +37 -0
- package/src/components/Input/Input.stories.tsx +86 -0
- package/src/components/Input/Input.tsx +14 -0
- package/src/components/Input/__tests__/Input.test.tsx +22 -0
- package/src/components/NavTabs/NavTabs.module.css +48 -0
- package/src/components/NavTabs/NavTabs.tsx +33 -0
- package/src/components/PageHeader/PageHeader.module.css +32 -0
- package/src/components/PageHeader/PageHeader.tsx +21 -0
- package/src/components/Popover/Popover.module.css +44 -0
- package/src/components/Popover/Popover.stories.tsx +232 -0
- package/src/components/Popover/Popover.tsx +75 -0
- package/src/components/Popover/__tests__/Popover.test.tsx +98 -0
- package/src/components/SegmentedControl/SegmentedControl.module.css +53 -0
- package/src/components/SegmentedControl/SegmentedControl.stories.tsx +118 -0
- package/src/components/SegmentedControl/SegmentedControl.tsx +56 -0
- package/src/components/SegmentedControl/__tests__/SegmentedControl.test.tsx +63 -0
- package/src/components/Select/Select.module.css +69 -0
- package/src/components/Select/Select.stories.tsx +115 -0
- package/src/components/Select/Select.tsx +40 -0
- package/src/components/Select/__tests__/Select.test.tsx +59 -0
- package/src/components/Spinner/Spinner.module.css +39 -0
- package/src/components/Spinner/Spinner.tsx +23 -0
- package/src/components/SystemBanner/SystemBanner.module.css +67 -0
- package/src/components/SystemBanner/SystemBanner.stories.tsx +86 -0
- package/src/components/SystemBanner/SystemBanner.tsx +50 -0
- package/src/components/SystemBanner/__tests__/SystemBanner.test.tsx +50 -0
- package/src/components/Tabs/Tabs.module.css +49 -0
- package/src/components/Tabs/Tabs.stories.tsx +100 -0
- package/src/components/Tabs/Tabs.tsx +46 -0
- package/src/components/Tabs/__tests__/Tabs.test.tsx +45 -0
- package/src/components/Toast/Toast.module.css +130 -0
- package/src/components/Toast/Toast.stories.tsx +191 -0
- package/src/components/Toast/Toast.tsx +139 -0
- package/src/components/Toggle/Toggle.module.css +52 -0
- package/src/components/Toggle/Toggle.stories.tsx +95 -0
- package/src/components/Toggle/Toggle.tsx +39 -0
- package/src/components/Toggle/__tests__/Toggle.test.tsx +47 -0
- package/src/components/Tooltip/Tooltip.module.css +51 -0
- package/src/components/Tooltip/Tooltip.tsx +30 -0
- package/src/css-modules.d.ts +4 -0
- package/src/index.ts +45 -0
- package/src/stories/Avatar.stories.tsx +44 -0
- package/src/stories/Card.stories.tsx +35 -0
- package/src/stories/DesignSystemOverview.stories.tsx +1683 -0
- package/src/stories/EmptyState.stories.tsx +33 -0
- package/src/stories/FormField.stories.tsx +47 -0
- package/src/stories/MobilePatterns.stories.tsx +1285 -0
- package/src/stories/NavTabs.stories.tsx +35 -0
- package/src/stories/PageHeader.stories.tsx +31 -0
- package/src/stories/Spinner.stories.tsx +25 -0
- package/src/stories/TokenGallery.stories.tsx +355 -0
- package/src/stories/Tooltip.stories.tsx +59 -0
- package/src/tokens/primitives.css +99 -0
- package/src/tokens/semantic.css +111 -0
- package/src/tokens.css +5 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { NavTabs } from '../components/NavTabs/NavTabs';
|
|
3
|
+
|
|
4
|
+
const items = [
|
|
5
|
+
{ label: 'Overview', href: '#overview', active: true },
|
|
6
|
+
{ label: 'Users', href: '#users' },
|
|
7
|
+
{ label: 'Plugins', href: '#plugins' },
|
|
8
|
+
{ label: 'Settings', href: '#settings' },
|
|
9
|
+
];
|
|
10
|
+
|
|
11
|
+
const meta = {
|
|
12
|
+
title: 'Components/NavTabs',
|
|
13
|
+
component: NavTabs,
|
|
14
|
+
parameters: { layout: 'padded' },
|
|
15
|
+
args: { items },
|
|
16
|
+
} satisfies Meta<typeof NavTabs>;
|
|
17
|
+
|
|
18
|
+
export default meta;
|
|
19
|
+
type Story = StoryObj<typeof meta>;
|
|
20
|
+
|
|
21
|
+
export const Default: Story = {};
|
|
22
|
+
|
|
23
|
+
export const ManyTabs: Story = {
|
|
24
|
+
args: {
|
|
25
|
+
items: [
|
|
26
|
+
{ label: 'Profile', href: '#profile', active: true },
|
|
27
|
+
{ label: 'Security', href: '#security' },
|
|
28
|
+
{ label: 'Notifications', href: '#notifications' },
|
|
29
|
+
{ label: 'Preferences', href: '#preferences' },
|
|
30
|
+
{ label: 'Data & Privacy', href: '#data' },
|
|
31
|
+
{ label: 'Sessions', href: '#sessions' },
|
|
32
|
+
],
|
|
33
|
+
},
|
|
34
|
+
parameters: { viewport: { defaultViewport: 'mobile' } },
|
|
35
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { PageHeader } from '../components/PageHeader/PageHeader';
|
|
3
|
+
import { Button } from '../components/Button/Button';
|
|
4
|
+
|
|
5
|
+
const meta = {
|
|
6
|
+
title: 'Components/PageHeader',
|
|
7
|
+
component: PageHeader,
|
|
8
|
+
parameters: { layout: 'padded' },
|
|
9
|
+
} satisfies Meta<typeof PageHeader>;
|
|
10
|
+
|
|
11
|
+
export default meta;
|
|
12
|
+
type Story = StoryObj<typeof meta>;
|
|
13
|
+
|
|
14
|
+
export const Default: Story = {
|
|
15
|
+
args: { title: 'Users' },
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const WithDescription: Story = {
|
|
19
|
+
args: {
|
|
20
|
+
title: 'Users',
|
|
21
|
+
description: 'Manage who has access to this instance.',
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const WithAction: Story = {
|
|
26
|
+
args: {
|
|
27
|
+
title: 'Users',
|
|
28
|
+
description: 'Manage who has access to this instance.',
|
|
29
|
+
action: <Button size="sm">Invite user</Button>,
|
|
30
|
+
},
|
|
31
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { Spinner } from '../components/Spinner/Spinner';
|
|
3
|
+
|
|
4
|
+
const meta = {
|
|
5
|
+
title: 'Components/Spinner',
|
|
6
|
+
component: Spinner,
|
|
7
|
+
parameters: { layout: 'centered' },
|
|
8
|
+
} satisfies Meta<typeof Spinner>;
|
|
9
|
+
|
|
10
|
+
export default meta;
|
|
11
|
+
type Story = StoryObj<typeof meta>;
|
|
12
|
+
|
|
13
|
+
export const Default: Story = {};
|
|
14
|
+
export const Small: Story = { args: { size: 'sm' } };
|
|
15
|
+
export const Large: Story = { args: { size: 'lg' } };
|
|
16
|
+
|
|
17
|
+
export const AllSizes: Story = {
|
|
18
|
+
render: () => (
|
|
19
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: 16 }}>
|
|
20
|
+
<Spinner size="sm" />
|
|
21
|
+
<Spinner size="md" />
|
|
22
|
+
<Spinner size="lg" />
|
|
23
|
+
</div>
|
|
24
|
+
),
|
|
25
|
+
};
|
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
// Token Gallery — live rendering of every CSS custom property tier.
|
|
5
|
+
// Values are read from the computed style at render time so they always
|
|
6
|
+
// reflect the actual loaded CSS, not a hardcoded snapshot. Toggle dark mode
|
|
7
|
+
// via the Themes toolbar to compare both theme values side-by-side.
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
|
|
10
|
+
const SEMANTIC_COLORS = [
|
|
11
|
+
'--sv-color-surface',
|
|
12
|
+
'--sv-color-surface-sunken',
|
|
13
|
+
'--sv-color-surface-raised',
|
|
14
|
+
'--sv-color-text-primary',
|
|
15
|
+
'--sv-color-text-muted',
|
|
16
|
+
'--sv-color-text-subtle',
|
|
17
|
+
'--sv-color-text-on-accent',
|
|
18
|
+
'--sv-color-border',
|
|
19
|
+
'--sv-color-border-strong',
|
|
20
|
+
'--sv-color-accent',
|
|
21
|
+
'--sv-color-accent-hover',
|
|
22
|
+
'--sv-color-focus-ring',
|
|
23
|
+
'--sv-color-error-surface',
|
|
24
|
+
'--sv-color-error-text',
|
|
25
|
+
'--sv-color-error-border',
|
|
26
|
+
'--sv-color-warning-surface',
|
|
27
|
+
'--sv-color-warning-text',
|
|
28
|
+
'--sv-color-warning-border',
|
|
29
|
+
'--sv-color-success-surface',
|
|
30
|
+
'--sv-color-success-text',
|
|
31
|
+
'--sv-color-success-border',
|
|
32
|
+
'--sv-color-info-surface',
|
|
33
|
+
'--sv-color-info-text',
|
|
34
|
+
'--sv-color-info-border',
|
|
35
|
+
'--sv-color-scrim',
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
const SPACE_TOKENS = [
|
|
39
|
+
'--sv-space-1',
|
|
40
|
+
'--sv-space-2',
|
|
41
|
+
'--sv-space-3',
|
|
42
|
+
'--sv-space-4',
|
|
43
|
+
'--sv-space-5',
|
|
44
|
+
'--sv-space-6',
|
|
45
|
+
'--sv-space-8',
|
|
46
|
+
'--sv-space-10',
|
|
47
|
+
'--sv-space-12',
|
|
48
|
+
'--sv-space-16',
|
|
49
|
+
];
|
|
50
|
+
|
|
51
|
+
const RADIUS_TOKENS = [
|
|
52
|
+
'--sv-radius-sm',
|
|
53
|
+
'--sv-radius-md',
|
|
54
|
+
'--sv-radius-lg',
|
|
55
|
+
'--sv-radius-xl',
|
|
56
|
+
'--sv-radius-2xl',
|
|
57
|
+
'--sv-radius-3xl',
|
|
58
|
+
'--sv-radius-full',
|
|
59
|
+
];
|
|
60
|
+
const ICON_SIZE_TOKENS = ['--sv-icon-size-sm', '--sv-icon-size-md', '--sv-icon-size-lg'];
|
|
61
|
+
|
|
62
|
+
const FONT_SIZE_TOKENS = [
|
|
63
|
+
'--sv-font-size-label',
|
|
64
|
+
'--sv-font-size-xs',
|
|
65
|
+
'--sv-font-size-caption',
|
|
66
|
+
'--sv-font-size-sm',
|
|
67
|
+
'--sv-font-size-md',
|
|
68
|
+
'--sv-font-size-lg',
|
|
69
|
+
'--sv-font-size-xl',
|
|
70
|
+
'--sv-font-size-2xl',
|
|
71
|
+
];
|
|
72
|
+
|
|
73
|
+
const FONT_WEIGHT_TOKENS = [
|
|
74
|
+
'--sv-font-weight-normal',
|
|
75
|
+
'--sv-font-weight-medium',
|
|
76
|
+
'--sv-font-weight-semibold',
|
|
77
|
+
'--sv-font-weight-bold',
|
|
78
|
+
];
|
|
79
|
+
|
|
80
|
+
const SHADOW_TOKENS = [
|
|
81
|
+
'--sv-shadow-card',
|
|
82
|
+
'--sv-shadow-hover',
|
|
83
|
+
'--sv-shadow-popover',
|
|
84
|
+
'--sv-shadow-overlay',
|
|
85
|
+
];
|
|
86
|
+
|
|
87
|
+
// ---------------------------------------------------------------------------
|
|
88
|
+
|
|
89
|
+
const row: React.CSSProperties = {
|
|
90
|
+
display: 'flex',
|
|
91
|
+
alignItems: 'center',
|
|
92
|
+
gap: '12px',
|
|
93
|
+
padding: '6px 0',
|
|
94
|
+
borderBottom: '1px solid var(--sv-color-border)',
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const label: React.CSSProperties = {
|
|
98
|
+
fontFamily: 'monospace',
|
|
99
|
+
fontSize: '13px',
|
|
100
|
+
color: 'var(--sv-color-text-primary)',
|
|
101
|
+
minWidth: '300px',
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const value: React.CSSProperties = {
|
|
105
|
+
fontFamily: 'monospace',
|
|
106
|
+
fontSize: '12px',
|
|
107
|
+
color: 'var(--sv-color-text-muted)',
|
|
108
|
+
flex: 1,
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
// ---------------------------------------------------------------------------
|
|
112
|
+
|
|
113
|
+
function ColorRow({ token }: { token: string }) {
|
|
114
|
+
const computed =
|
|
115
|
+
typeof window !== 'undefined'
|
|
116
|
+
? getComputedStyle(document.documentElement).getPropertyValue(token).trim()
|
|
117
|
+
: '';
|
|
118
|
+
const swatch: React.CSSProperties = {
|
|
119
|
+
width: 28,
|
|
120
|
+
height: 28,
|
|
121
|
+
borderRadius: 4,
|
|
122
|
+
background: `var(${token})`,
|
|
123
|
+
border: '1px solid var(--sv-color-border)',
|
|
124
|
+
flexShrink: 0,
|
|
125
|
+
};
|
|
126
|
+
return (
|
|
127
|
+
<div style={row}>
|
|
128
|
+
<div style={swatch} />
|
|
129
|
+
<span style={label}>{token}</span>
|
|
130
|
+
<span style={value}>{computed}</span>
|
|
131
|
+
</div>
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function ScaleRow({
|
|
136
|
+
token,
|
|
137
|
+
renderPreview,
|
|
138
|
+
}: {
|
|
139
|
+
token: string;
|
|
140
|
+
renderPreview: (v: string) => React.ReactNode;
|
|
141
|
+
}) {
|
|
142
|
+
const computed =
|
|
143
|
+
typeof window !== 'undefined'
|
|
144
|
+
? getComputedStyle(document.documentElement).getPropertyValue(token).trim()
|
|
145
|
+
: '';
|
|
146
|
+
return (
|
|
147
|
+
<div style={row}>
|
|
148
|
+
{renderPreview(computed)}
|
|
149
|
+
<span style={label}>{token}</span>
|
|
150
|
+
<span style={value}>{computed}</span>
|
|
151
|
+
</div>
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function Section({ title, children }: { title: string; children: React.ReactNode }) {
|
|
156
|
+
return (
|
|
157
|
+
<section style={{ marginBottom: 40 }}>
|
|
158
|
+
<h2
|
|
159
|
+
style={{
|
|
160
|
+
fontFamily: 'var(--sv-font-family)',
|
|
161
|
+
fontSize: 18,
|
|
162
|
+
fontWeight: 600,
|
|
163
|
+
color: 'var(--sv-color-text-primary)',
|
|
164
|
+
marginBottom: 12,
|
|
165
|
+
borderBottom: '2px solid var(--sv-color-accent)',
|
|
166
|
+
paddingBottom: 4,
|
|
167
|
+
}}
|
|
168
|
+
>
|
|
169
|
+
{title}
|
|
170
|
+
</h2>
|
|
171
|
+
{children}
|
|
172
|
+
</section>
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// ---------------------------------------------------------------------------
|
|
177
|
+
|
|
178
|
+
function TokenGalleryComponent() {
|
|
179
|
+
return (
|
|
180
|
+
<div
|
|
181
|
+
style={{
|
|
182
|
+
padding: 24,
|
|
183
|
+
background: 'var(--sv-color-surface)',
|
|
184
|
+
minHeight: '100vh',
|
|
185
|
+
fontFamily: 'var(--sv-font-family)',
|
|
186
|
+
}}
|
|
187
|
+
>
|
|
188
|
+
<h1
|
|
189
|
+
style={{
|
|
190
|
+
fontSize: 24,
|
|
191
|
+
fontWeight: 700,
|
|
192
|
+
color: 'var(--sv-color-text-primary)',
|
|
193
|
+
marginBottom: 8,
|
|
194
|
+
}}
|
|
195
|
+
>
|
|
196
|
+
Sovereign Design Token Gallery
|
|
197
|
+
</h1>
|
|
198
|
+
<p style={{ color: 'var(--sv-color-text-muted)', marginBottom: 32, fontSize: 14 }}>
|
|
199
|
+
All values are read live from computed styles — they reflect the actual loaded CSS, not a
|
|
200
|
+
hardcoded snapshot. Use the Themes toolbar above to switch dark mode.
|
|
201
|
+
</p>
|
|
202
|
+
|
|
203
|
+
<Section title="Semantic colours">
|
|
204
|
+
{SEMANTIC_COLORS.map((t) => (
|
|
205
|
+
<ColorRow key={t} token={t} />
|
|
206
|
+
))}
|
|
207
|
+
</Section>
|
|
208
|
+
|
|
209
|
+
<Section title="Space scale">
|
|
210
|
+
{SPACE_TOKENS.map((t) => (
|
|
211
|
+
<ScaleRow
|
|
212
|
+
key={t}
|
|
213
|
+
token={t}
|
|
214
|
+
renderPreview={(_v) => (
|
|
215
|
+
<div
|
|
216
|
+
style={{
|
|
217
|
+
width: `var(${t})`,
|
|
218
|
+
height: 16,
|
|
219
|
+
background: 'var(--sv-color-accent)',
|
|
220
|
+
flexShrink: 0,
|
|
221
|
+
minWidth: 4,
|
|
222
|
+
}}
|
|
223
|
+
/>
|
|
224
|
+
)}
|
|
225
|
+
/>
|
|
226
|
+
))}
|
|
227
|
+
</Section>
|
|
228
|
+
|
|
229
|
+
<Section title="Font weight scale">
|
|
230
|
+
{FONT_WEIGHT_TOKENS.map((t) => (
|
|
231
|
+
<ScaleRow
|
|
232
|
+
key={t}
|
|
233
|
+
token={t}
|
|
234
|
+
renderPreview={(_v) => (
|
|
235
|
+
<span
|
|
236
|
+
style={{
|
|
237
|
+
fontFamily: 'var(--sv-font-family)',
|
|
238
|
+
fontSize: 'var(--sv-font-size-md)',
|
|
239
|
+
fontWeight: `var(${t})`,
|
|
240
|
+
color: 'var(--sv-color-text-primary)',
|
|
241
|
+
minWidth: 100,
|
|
242
|
+
}}
|
|
243
|
+
>
|
|
244
|
+
Sovereign
|
|
245
|
+
</span>
|
|
246
|
+
)}
|
|
247
|
+
/>
|
|
248
|
+
))}
|
|
249
|
+
</Section>
|
|
250
|
+
|
|
251
|
+
<Section title="Typography scale">
|
|
252
|
+
{FONT_SIZE_TOKENS.map((t) => (
|
|
253
|
+
<ScaleRow
|
|
254
|
+
key={t}
|
|
255
|
+
token={t}
|
|
256
|
+
renderPreview={(_v) => (
|
|
257
|
+
<span
|
|
258
|
+
style={{
|
|
259
|
+
fontSize: `var(${t})`,
|
|
260
|
+
color: 'var(--sv-color-text-primary)',
|
|
261
|
+
minWidth: 100,
|
|
262
|
+
lineHeight: 1,
|
|
263
|
+
}}
|
|
264
|
+
>
|
|
265
|
+
Aa
|
|
266
|
+
</span>
|
|
267
|
+
)}
|
|
268
|
+
/>
|
|
269
|
+
))}
|
|
270
|
+
</Section>
|
|
271
|
+
|
|
272
|
+
<Section title="Radius scale">
|
|
273
|
+
{RADIUS_TOKENS.map((t) => (
|
|
274
|
+
<ScaleRow
|
|
275
|
+
key={t}
|
|
276
|
+
token={t}
|
|
277
|
+
renderPreview={(_v) => (
|
|
278
|
+
<div
|
|
279
|
+
style={{
|
|
280
|
+
width: 40,
|
|
281
|
+
height: 24,
|
|
282
|
+
background: 'var(--sv-color-accent)',
|
|
283
|
+
borderRadius: `var(${t})`,
|
|
284
|
+
flexShrink: 0,
|
|
285
|
+
}}
|
|
286
|
+
/>
|
|
287
|
+
)}
|
|
288
|
+
/>
|
|
289
|
+
))}
|
|
290
|
+
</Section>
|
|
291
|
+
|
|
292
|
+
<Section title="Icon sizes">
|
|
293
|
+
{ICON_SIZE_TOKENS.map((t) => (
|
|
294
|
+
<ScaleRow
|
|
295
|
+
key={t}
|
|
296
|
+
token={t}
|
|
297
|
+
renderPreview={(_v) => (
|
|
298
|
+
<div
|
|
299
|
+
style={{
|
|
300
|
+
width: `var(${t})`,
|
|
301
|
+
height: `var(${t})`,
|
|
302
|
+
background: 'var(--sv-color-accent)',
|
|
303
|
+
borderRadius: 2,
|
|
304
|
+
flexShrink: 0,
|
|
305
|
+
}}
|
|
306
|
+
/>
|
|
307
|
+
)}
|
|
308
|
+
/>
|
|
309
|
+
))}
|
|
310
|
+
</Section>
|
|
311
|
+
|
|
312
|
+
<Section title="Shadows">
|
|
313
|
+
{SHADOW_TOKENS.map((t) => (
|
|
314
|
+
<ScaleRow
|
|
315
|
+
key={t}
|
|
316
|
+
token={t}
|
|
317
|
+
renderPreview={(_v) => (
|
|
318
|
+
<div
|
|
319
|
+
style={{
|
|
320
|
+
width: 48,
|
|
321
|
+
height: 28,
|
|
322
|
+
background: 'var(--sv-color-surface-raised)',
|
|
323
|
+
boxShadow: `var(${t})`,
|
|
324
|
+
borderRadius: 4,
|
|
325
|
+
flexShrink: 0,
|
|
326
|
+
}}
|
|
327
|
+
/>
|
|
328
|
+
)}
|
|
329
|
+
/>
|
|
330
|
+
))}
|
|
331
|
+
</Section>
|
|
332
|
+
</div>
|
|
333
|
+
);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// ---------------------------------------------------------------------------
|
|
337
|
+
|
|
338
|
+
const meta = {
|
|
339
|
+
title: 'Design Tokens/Token Gallery',
|
|
340
|
+
component: TokenGalleryComponent,
|
|
341
|
+
parameters: {
|
|
342
|
+
layout: 'fullscreen',
|
|
343
|
+
docs: {
|
|
344
|
+
description: {
|
|
345
|
+
component:
|
|
346
|
+
'Live gallery of every `--sv-*` CSS custom property. Values are read from `getComputedStyle` at render time — toggle dark mode via the Themes toolbar to see both themes.',
|
|
347
|
+
},
|
|
348
|
+
},
|
|
349
|
+
},
|
|
350
|
+
} satisfies Meta<typeof TokenGalleryComponent>;
|
|
351
|
+
|
|
352
|
+
export default meta;
|
|
353
|
+
type Story = StoryObj<typeof meta>;
|
|
354
|
+
|
|
355
|
+
export const AllTokens: Story = {};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { Tooltip } from '../components/Tooltip/Tooltip';
|
|
3
|
+
import { Button } from '../components/Button/Button';
|
|
4
|
+
import { Icon } from '../components/Icon/Icon';
|
|
5
|
+
|
|
6
|
+
const meta = {
|
|
7
|
+
title: 'Components/Tooltip',
|
|
8
|
+
component: Tooltip,
|
|
9
|
+
parameters: { layout: 'centered' },
|
|
10
|
+
} satisfies Meta<typeof Tooltip>;
|
|
11
|
+
|
|
12
|
+
export default meta;
|
|
13
|
+
type Story = StoryObj<typeof meta>;
|
|
14
|
+
|
|
15
|
+
export const Default: Story = {
|
|
16
|
+
args: {
|
|
17
|
+
content: 'This is a tooltip',
|
|
18
|
+
children: <Button variant="secondary">Hover me</Button>,
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const OnIcon: Story = {
|
|
23
|
+
args: {
|
|
24
|
+
content: 'More information',
|
|
25
|
+
children: (
|
|
26
|
+
<span style={{ color: 'var(--sv-color-text-muted)', cursor: 'default' }}>
|
|
27
|
+
<Icon name="info" size="md" aria-label="Info" />
|
|
28
|
+
</span>
|
|
29
|
+
),
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export const Sides: Story = {
|
|
34
|
+
args: { content: '', children: <span /> },
|
|
35
|
+
render: () => (
|
|
36
|
+
<div style={{ display: 'flex', gap: 48, alignItems: 'center', padding: 48 }}>
|
|
37
|
+
<Tooltip content="Top" side="top">
|
|
38
|
+
<Button variant="ghost" size="sm">
|
|
39
|
+
Top
|
|
40
|
+
</Button>
|
|
41
|
+
</Tooltip>
|
|
42
|
+
<Tooltip content="Bottom" side="bottom">
|
|
43
|
+
<Button variant="ghost" size="sm">
|
|
44
|
+
Bottom
|
|
45
|
+
</Button>
|
|
46
|
+
</Tooltip>
|
|
47
|
+
<Tooltip content="Left" side="left">
|
|
48
|
+
<Button variant="ghost" size="sm">
|
|
49
|
+
Left
|
|
50
|
+
</Button>
|
|
51
|
+
</Tooltip>
|
|
52
|
+
<Tooltip content="Right" side="right">
|
|
53
|
+
<Button variant="ghost" size="sm">
|
|
54
|
+
Right
|
|
55
|
+
</Button>
|
|
56
|
+
</Tooltip>
|
|
57
|
+
</div>
|
|
58
|
+
),
|
|
59
|
+
};
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Sovereign Design System — primitive tokens.
|
|
3
|
+
*
|
|
4
|
+
* Raw, context-free scales: the palette, spacing, type, and radii. These are
|
|
5
|
+
* fixed — tenant theming never overrides primitives (it overrides the semantic
|
|
6
|
+
* layer in semantic.css). Plugin code should reference SEMANTIC colour tokens,
|
|
7
|
+
* not these primitives directly.
|
|
8
|
+
*/
|
|
9
|
+
:root {
|
|
10
|
+
/* Neutral grey scale (monochrome identity) */
|
|
11
|
+
--sv-white: #ffffff;
|
|
12
|
+
|
|
13
|
+
/* Status colour primitives — amber (warning), green (success), red (error), blue (info).
|
|
14
|
+
Kept minimal: only the swatches the semantic status tokens reference.
|
|
15
|
+
Hex values align with the v3.1 design spec. */
|
|
16
|
+
--sv-amber-100: #fff7ed;
|
|
17
|
+
--sv-amber-200: #fed7aa;
|
|
18
|
+
--sv-amber-800: #b45309;
|
|
19
|
+
--sv-amber-900: #92400e;
|
|
20
|
+
--sv-green-100: #ecfdf3;
|
|
21
|
+
--sv-green-200: #bbf7d0;
|
|
22
|
+
--sv-green-800: #167c4a;
|
|
23
|
+
--sv-green-900: #14532d;
|
|
24
|
+
--sv-red-100: #fef2f2;
|
|
25
|
+
--sv-red-200: #fecaca;
|
|
26
|
+
--sv-red-700: #b91c1c;
|
|
27
|
+
--sv-red-800: #991b1b;
|
|
28
|
+
--sv-red-900: #7f1d1d;
|
|
29
|
+
--sv-blue-100: #eff6ff;
|
|
30
|
+
--sv-blue-200: #dbeafe;
|
|
31
|
+
--sv-blue-800: #1d4ed8;
|
|
32
|
+
--sv-blue-900: #1e3a8a;
|
|
33
|
+
--sv-black: #000000;
|
|
34
|
+
--sv-grey-50: #fafafa;
|
|
35
|
+
--sv-grey-100: #f4f4f5;
|
|
36
|
+
--sv-grey-200: #e4e4e7;
|
|
37
|
+
--sv-grey-300: #d4d4d8;
|
|
38
|
+
--sv-grey-400: #a1a1aa;
|
|
39
|
+
--sv-grey-500: #71717a;
|
|
40
|
+
--sv-grey-600: #52525b;
|
|
41
|
+
--sv-grey-700: #3f3f46;
|
|
42
|
+
--sv-grey-800: #27272a;
|
|
43
|
+
--sv-grey-900: #18181b;
|
|
44
|
+
--sv-grey-950: #09090b;
|
|
45
|
+
|
|
46
|
+
/* Spacing scale (4px base) */
|
|
47
|
+
--sv-space-1: 0.25rem;
|
|
48
|
+
--sv-space-2: 0.5rem;
|
|
49
|
+
--sv-space-3: 0.75rem;
|
|
50
|
+
--sv-space-4: 1rem;
|
|
51
|
+
--sv-space-5: 1.25rem;
|
|
52
|
+
--sv-space-6: 1.5rem;
|
|
53
|
+
--sv-space-8: 2rem;
|
|
54
|
+
--sv-space-10: 2.5rem;
|
|
55
|
+
--sv-space-12: 3rem;
|
|
56
|
+
--sv-space-16: 4rem;
|
|
57
|
+
|
|
58
|
+
/* Typography
|
|
59
|
+
Default pair: Hanken Grotesk (body) + JetBrains Mono (code/identifiers).
|
|
60
|
+
Operators supply the web font via <link> or instance CSS; the fallback
|
|
61
|
+
stack applies when the font is not loaded. */
|
|
62
|
+
--sv-font-family:
|
|
63
|
+
'Hanken Grotesk', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial,
|
|
64
|
+
sans-serif;
|
|
65
|
+
--sv-font-family-mono:
|
|
66
|
+
'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, Consolas, 'Liberation Mono', monospace;
|
|
67
|
+
--sv-font-size-label: 0.6875rem; /* 11px — all-caps section labels */
|
|
68
|
+
--sv-font-size-xs: 0.75rem; /* 12px — mono identifiers */
|
|
69
|
+
--sv-font-size-caption: 0.8125rem; /* 13px — secondary / supporting copy */
|
|
70
|
+
--sv-font-size-sm: 0.875rem; /* 14px — body copy */
|
|
71
|
+
--sv-font-size-md: 1rem; /* 16px */
|
|
72
|
+
--sv-font-size-lg: 1.125rem; /* 18px */
|
|
73
|
+
--sv-font-size-xl: 1.25rem; /* 20px */
|
|
74
|
+
--sv-font-size-2xl: 1.5rem; /* 24px */
|
|
75
|
+
--sv-font-weight-regular: 400;
|
|
76
|
+
--sv-font-weight-medium: 500;
|
|
77
|
+
--sv-font-weight-semibold: 600;
|
|
78
|
+
--sv-font-weight-bold: 700;
|
|
79
|
+
|
|
80
|
+
/* Icon sizes — scale tokens used directly by the Icon component */
|
|
81
|
+
--sv-icon-size-sm: 1rem; /* 16px — inline with body text */
|
|
82
|
+
--sv-icon-size-md: 1.25rem; /* 20px — standard affordance */
|
|
83
|
+
--sv-icon-size-lg: 1.5rem; /* 24px — prominent / standalone */
|
|
84
|
+
|
|
85
|
+
/* Border radii (v3.1 spec values) */
|
|
86
|
+
--sv-radius-sm: 0.375rem; /* 6px — badge, tag */
|
|
87
|
+
--sv-radius-md: 0.5rem; /* 8px — button, input */
|
|
88
|
+
--sv-radius-lg: 0.6875rem; /* 11px — sidebar icon, card */
|
|
89
|
+
--sv-radius-xl: 0.75rem; /* 12px — card, panel */
|
|
90
|
+
--sv-radius-2xl: 0.875rem; /* 14px — popover */
|
|
91
|
+
--sv-radius-3xl: 1.25rem; /* 20px — bottom sheet (Drawer top corners) */
|
|
92
|
+
--sv-radius-full: 9999px; /* pill / avatar */
|
|
93
|
+
|
|
94
|
+
/* Touch targets — minimum hit-area dimension for interactive controls.
|
|
95
|
+
44px follows the WCAG 2.5.5 / Apple HIG / Material guideline for reliable
|
|
96
|
+
touch without a pointing device. Applied to icon-only controls on mobile
|
|
97
|
+
(avatar, footer button, Drawer nav items). */
|
|
98
|
+
--sv-touch-target-min: 44px;
|
|
99
|
+
}
|