@sublimee/surfaces 0.1.1
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 +21 -0
- package/README.md +116 -0
- package/dist/index.d.mts +42 -0
- package/dist/index.d.ts +42 -0
- package/dist/index.js +99 -0
- package/dist/index.mjs +63 -0
- package/dist/surface.css +261 -0
- package/package.json +73 -0
- package/src/index.ts +32 -0
- package/src/surface.css +261 -0
- package/src/surface.stories.tsx +674 -0
- package/src/surface.tsx +108 -0
|
@@ -0,0 +1,674 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { Story, Meta } from '@ladle/react';
|
|
3
|
+
import { Surface } from './surface';
|
|
4
|
+
import './surface.css';
|
|
5
|
+
|
|
6
|
+
export default {
|
|
7
|
+
title: 'Surface',
|
|
8
|
+
} as Meta;
|
|
9
|
+
|
|
10
|
+
// Wrapper to show surfaces against a background using tokens
|
|
11
|
+
const StoryWrapper: React.FC<{ children: React.ReactNode; title?: string }> = ({
|
|
12
|
+
children,
|
|
13
|
+
title,
|
|
14
|
+
}) => (
|
|
15
|
+
<div
|
|
16
|
+
style={{
|
|
17
|
+
padding: '2rem',
|
|
18
|
+
minHeight: '100vh',
|
|
19
|
+
backgroundColor: 'var(--sublime-color-surface-0, #f3f4f6)',
|
|
20
|
+
fontFamily:
|
|
21
|
+
'var(--sublime-font-family-sans, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif)',
|
|
22
|
+
}}
|
|
23
|
+
>
|
|
24
|
+
{title && (
|
|
25
|
+
<h2
|
|
26
|
+
style={{
|
|
27
|
+
margin: '0 0 1.5rem 0',
|
|
28
|
+
fontSize: '1.25rem',
|
|
29
|
+
fontWeight: 600,
|
|
30
|
+
color: 'var(--sublime-color-text-primary, #111827)',
|
|
31
|
+
}}
|
|
32
|
+
>
|
|
33
|
+
{title}
|
|
34
|
+
</h2>
|
|
35
|
+
)}
|
|
36
|
+
{children}
|
|
37
|
+
</div>
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
// Sample content for surfaces using token-based colors
|
|
41
|
+
const SampleContent: React.FC<{ title?: string }> = ({ title = 'Surface Content' }) => (
|
|
42
|
+
<div>
|
|
43
|
+
<h3
|
|
44
|
+
style={{
|
|
45
|
+
margin: '0 0 0.5rem 0',
|
|
46
|
+
fontSize: '1.125rem',
|
|
47
|
+
fontWeight: 600,
|
|
48
|
+
color: 'var(--sublime-color-text-primary, #111827)',
|
|
49
|
+
}}
|
|
50
|
+
>
|
|
51
|
+
{title}
|
|
52
|
+
</h3>
|
|
53
|
+
<p
|
|
54
|
+
style={{
|
|
55
|
+
margin: 0,
|
|
56
|
+
fontSize: '0.875rem',
|
|
57
|
+
lineHeight: 1.6,
|
|
58
|
+
color: 'var(--sublime-color-text-secondary, #4b5563)',
|
|
59
|
+
}}
|
|
60
|
+
>
|
|
61
|
+
This is sample content inside a Surface component. Surfaces provide
|
|
62
|
+
semantic elevation, padding, and visual boundaries for your content.
|
|
63
|
+
</p>
|
|
64
|
+
</div>
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* NOTE ON GLASS SURFACE TEXT CONTRAST:
|
|
69
|
+
*
|
|
70
|
+
* The glass variant is semi-transparent and designed to be used over colorful
|
|
71
|
+
* backgrounds. The Surface does NOT modify text styling — it's the consumer's
|
|
72
|
+
* responsibility to ensure text readability.
|
|
73
|
+
*
|
|
74
|
+
* Options for text on glass:
|
|
75
|
+
* 1. Text shadow: textShadow: '0 1px 2px rgba(255, 255, 255, 0.5)'
|
|
76
|
+
* 2. High contrast colors: white or black text depending on background
|
|
77
|
+
* 3. Content backdrop: wrap text in a subtle solid overlay
|
|
78
|
+
*
|
|
79
|
+
* The Glass stories below demonstrate option 1 with inline styles.
|
|
80
|
+
*/
|
|
81
|
+
|
|
82
|
+
export const Default: Story = () => (
|
|
83
|
+
<StoryWrapper title="Default (Elevated)">
|
|
84
|
+
<div style={{ maxWidth: '400px' }}>
|
|
85
|
+
<Surface>
|
|
86
|
+
<SampleContent />
|
|
87
|
+
</Surface>
|
|
88
|
+
</div>
|
|
89
|
+
</StoryWrapper>
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
export const AllVariants: Story = () => (
|
|
93
|
+
<StoryWrapper title="All Variants (Without Border)">
|
|
94
|
+
<div
|
|
95
|
+
style={{
|
|
96
|
+
display: 'grid',
|
|
97
|
+
gap: '1.5rem',
|
|
98
|
+
maxWidth: '400px',
|
|
99
|
+
}}
|
|
100
|
+
>
|
|
101
|
+
<Surface variant="base">
|
|
102
|
+
<SampleContent title="Base Variant" />
|
|
103
|
+
</Surface>
|
|
104
|
+
|
|
105
|
+
<Surface variant="elevated">
|
|
106
|
+
<SampleContent title="Elevated Variant (Default)" />
|
|
107
|
+
</Surface>
|
|
108
|
+
|
|
109
|
+
<Surface variant="higher">
|
|
110
|
+
<SampleContent title="Higher Variant" />
|
|
111
|
+
</Surface>
|
|
112
|
+
|
|
113
|
+
<Surface variant="inset">
|
|
114
|
+
<SampleContent title="Inset Variant" />
|
|
115
|
+
</Surface>
|
|
116
|
+
</div>
|
|
117
|
+
</StoryWrapper>
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
export const AllVariantsWithBorder: Story = () => (
|
|
121
|
+
<StoryWrapper title="All Variants (With Border)">
|
|
122
|
+
<div
|
|
123
|
+
style={{
|
|
124
|
+
display: 'grid',
|
|
125
|
+
gap: '1.5rem',
|
|
126
|
+
maxWidth: '400px',
|
|
127
|
+
}}
|
|
128
|
+
>
|
|
129
|
+
<Surface variant="base" border>
|
|
130
|
+
<SampleContent title="Base + Border" />
|
|
131
|
+
</Surface>
|
|
132
|
+
|
|
133
|
+
<Surface variant="elevated" border>
|
|
134
|
+
<SampleContent title="Elevated + Border" />
|
|
135
|
+
</Surface>
|
|
136
|
+
|
|
137
|
+
<Surface variant="higher" border>
|
|
138
|
+
<SampleContent title="Higher + Border" />
|
|
139
|
+
</Surface>
|
|
140
|
+
|
|
141
|
+
<Surface variant="inset" border>
|
|
142
|
+
<SampleContent title="Inset + Border" />
|
|
143
|
+
</Surface>
|
|
144
|
+
</div>
|
|
145
|
+
</StoryWrapper>
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
export const PaddingSizes: Story = () => (
|
|
149
|
+
<StoryWrapper title="Padding Sizes">
|
|
150
|
+
<div
|
|
151
|
+
style={{
|
|
152
|
+
display: 'grid',
|
|
153
|
+
gap: '1.5rem',
|
|
154
|
+
maxWidth: '400px',
|
|
155
|
+
}}
|
|
156
|
+
>
|
|
157
|
+
<Surface padding="none">
|
|
158
|
+
<SampleContent title="Padding: None" />
|
|
159
|
+
</Surface>
|
|
160
|
+
|
|
161
|
+
<Surface padding="sm">
|
|
162
|
+
<SampleContent title="Padding: Small" />
|
|
163
|
+
</Surface>
|
|
164
|
+
|
|
165
|
+
<Surface padding="md">
|
|
166
|
+
<SampleContent title="Padding: Medium (Default)" />
|
|
167
|
+
</Surface>
|
|
168
|
+
|
|
169
|
+
<Surface padding="lg">
|
|
170
|
+
<SampleContent title="Padding: Large" />
|
|
171
|
+
</Surface>
|
|
172
|
+
|
|
173
|
+
<Surface padding="xl">
|
|
174
|
+
<SampleContent title="Padding: Extra Large" />
|
|
175
|
+
</Surface>
|
|
176
|
+
</div>
|
|
177
|
+
</StoryWrapper>
|
|
178
|
+
);
|
|
179
|
+
|
|
180
|
+
export const BorderRadius: Story = () => (
|
|
181
|
+
<StoryWrapper title="Border Radius Options">
|
|
182
|
+
<div
|
|
183
|
+
style={{
|
|
184
|
+
display: 'grid',
|
|
185
|
+
gap: '1.5rem',
|
|
186
|
+
maxWidth: '400px',
|
|
187
|
+
}}
|
|
188
|
+
>
|
|
189
|
+
<Surface radius="none">
|
|
190
|
+
<SampleContent title="Radius: None" />
|
|
191
|
+
</Surface>
|
|
192
|
+
|
|
193
|
+
<Surface radius="sm">
|
|
194
|
+
<SampleContent title="Radius: Small" />
|
|
195
|
+
</Surface>
|
|
196
|
+
|
|
197
|
+
<Surface radius="md">
|
|
198
|
+
<SampleContent title="Radius: Medium" />
|
|
199
|
+
</Surface>
|
|
200
|
+
|
|
201
|
+
<Surface radius="lg">
|
|
202
|
+
<SampleContent title="Radius: Large (Default)" />
|
|
203
|
+
</Surface>
|
|
204
|
+
|
|
205
|
+
<Surface radius="xl">
|
|
206
|
+
<SampleContent title="Radius: Extra Large" />
|
|
207
|
+
</Surface>
|
|
208
|
+
|
|
209
|
+
<Surface radius="full">
|
|
210
|
+
<div style={{ textAlign: 'center', color: 'var(--sublime-color-text-primary, #111827)' }}>
|
|
211
|
+
Radius: Full (pill shape)
|
|
212
|
+
</div>
|
|
213
|
+
</Surface>
|
|
214
|
+
</div>
|
|
215
|
+
</StoryWrapper>
|
|
216
|
+
);
|
|
217
|
+
|
|
218
|
+
export const WithBorder: Story = () => (
|
|
219
|
+
<StoryWrapper title="With Border">
|
|
220
|
+
<div
|
|
221
|
+
style={{
|
|
222
|
+
display: 'grid',
|
|
223
|
+
gap: '1.5rem',
|
|
224
|
+
maxWidth: '400px',
|
|
225
|
+
}}
|
|
226
|
+
>
|
|
227
|
+
<Surface variant="base" border>
|
|
228
|
+
<SampleContent title="Base + Border" />
|
|
229
|
+
</Surface>
|
|
230
|
+
|
|
231
|
+
<Surface variant="elevated" border>
|
|
232
|
+
<SampleContent title="Elevated + Border" />
|
|
233
|
+
</Surface>
|
|
234
|
+
|
|
235
|
+
<Surface variant="higher" border>
|
|
236
|
+
<SampleContent title="Higher + Border" />
|
|
237
|
+
</Surface>
|
|
238
|
+
|
|
239
|
+
<Surface variant="inset" border>
|
|
240
|
+
<SampleContent title="Inset + Border" />
|
|
241
|
+
</Surface>
|
|
242
|
+
</div>
|
|
243
|
+
</StoryWrapper>
|
|
244
|
+
);
|
|
245
|
+
|
|
246
|
+
export const Extruded: Story = () => (
|
|
247
|
+
<StoryWrapper title="Extruded (3D Effect) - Click to see press animation">
|
|
248
|
+
<div
|
|
249
|
+
style={{
|
|
250
|
+
display: 'grid',
|
|
251
|
+
gap: '2rem',
|
|
252
|
+
maxWidth: '400px',
|
|
253
|
+
}}
|
|
254
|
+
>
|
|
255
|
+
<Surface variant="extruded" interactive>
|
|
256
|
+
<SampleContent title="Extruded Surface (Interactive)" />
|
|
257
|
+
<p style={{ margin: '0.5rem 0 0 0', fontSize: '0.75rem', color: 'var(--sublime-color-text-muted, #9ca3af)' }}>
|
|
258
|
+
Click or tap to see the press effect
|
|
259
|
+
</p>
|
|
260
|
+
</Surface>
|
|
261
|
+
|
|
262
|
+
<Surface variant="extruded" interactive={false}>
|
|
263
|
+
<SampleContent title="Extruded Surface (Static)" />
|
|
264
|
+
<p style={{ margin: '0.5rem 0 0 0', fontSize: '0.75rem', color: 'var(--sublime-color-text-muted, #9ca3af)' }}>
|
|
265
|
+
Static - no interaction
|
|
266
|
+
</p>
|
|
267
|
+
</Surface>
|
|
268
|
+
|
|
269
|
+
<Surface variant="extruded" interactive padding="lg" radius="xl">
|
|
270
|
+
<div style={{ textAlign: 'center' }}>
|
|
271
|
+
<h3 style={{ margin: '0 0 0.5rem 0', fontSize: '1.25rem', fontWeight: 600, color: 'var(--sublime-color-text-primary, #111827)' }}>
|
|
272
|
+
Big Extruded Card
|
|
273
|
+
</h3>
|
|
274
|
+
<p style={{ margin: 0, color: 'var(--sublime-color-text-secondary, #6b7280)' }}>
|
|
275
|
+
Large padding + XL radius
|
|
276
|
+
</p>
|
|
277
|
+
</div>
|
|
278
|
+
</Surface>
|
|
279
|
+
</div>
|
|
280
|
+
</StoryWrapper>
|
|
281
|
+
);
|
|
282
|
+
|
|
283
|
+
export const InteractiveStates: Story = () => (
|
|
284
|
+
<StoryWrapper title="Interactive States (Hover to see shadow lift)">
|
|
285
|
+
<div
|
|
286
|
+
style={{
|
|
287
|
+
display: 'grid',
|
|
288
|
+
gap: '1.5rem',
|
|
289
|
+
maxWidth: '400px',
|
|
290
|
+
}}
|
|
291
|
+
>
|
|
292
|
+
<Surface interactive>
|
|
293
|
+
<SampleContent title="Interactive: true (Default)" />
|
|
294
|
+
<p style={{ margin: '0.5rem 0 0 0', fontSize: '0.75rem', color: 'var(--sublime-color-text-muted, #9ca3af)' }}>
|
|
295
|
+
Hover to see elevation lift
|
|
296
|
+
</p>
|
|
297
|
+
</Surface>
|
|
298
|
+
|
|
299
|
+
<Surface interactive={false}>
|
|
300
|
+
<SampleContent title="Interactive: false" />
|
|
301
|
+
<p style={{ margin: '0.5rem 0 0 0', fontSize: '0.75rem', color: 'var(--sublime-color-text-muted, #9ca3af)' }}>
|
|
302
|
+
Static shadow, no hover effect
|
|
303
|
+
</p>
|
|
304
|
+
</Surface>
|
|
305
|
+
|
|
306
|
+
<Surface variant="higher" interactive>
|
|
307
|
+
<SampleContent title="Higher + Interactive" />
|
|
308
|
+
<p style={{ margin: '0.5rem 0 0 0', fontSize: '0.75rem', color: 'var(--sublime-color-text-muted, #9ca3af)' }}>
|
|
309
|
+
Higher elevation with interactive lift
|
|
310
|
+
</p>
|
|
311
|
+
</Surface>
|
|
312
|
+
</div>
|
|
313
|
+
</StoryWrapper>
|
|
314
|
+
);
|
|
315
|
+
|
|
316
|
+
export const Polymorphic: Story = () => (
|
|
317
|
+
<StoryWrapper title="Polymorphic (as prop)">
|
|
318
|
+
<div
|
|
319
|
+
style={{
|
|
320
|
+
display: 'grid',
|
|
321
|
+
gap: '1.5rem',
|
|
322
|
+
maxWidth: '400px',
|
|
323
|
+
}}
|
|
324
|
+
>
|
|
325
|
+
<Surface as="article">
|
|
326
|
+
<SampleContent title="Rendered as <article>" />
|
|
327
|
+
<code
|
|
328
|
+
style={{
|
|
329
|
+
display: 'block',
|
|
330
|
+
marginTop: '0.5rem',
|
|
331
|
+
padding: '0.25rem 0.5rem',
|
|
332
|
+
fontSize: '0.75rem',
|
|
333
|
+
backgroundColor: 'var(--sublime-color-surface-0, #f3f4f6)',
|
|
334
|
+
color: 'var(--sublime-color-text-secondary, #4b5563)',
|
|
335
|
+
borderRadius: '4px',
|
|
336
|
+
}}
|
|
337
|
+
>
|
|
338
|
+
<Surface as="article">
|
|
339
|
+
</code>
|
|
340
|
+
</Surface>
|
|
341
|
+
|
|
342
|
+
<Surface as="section">
|
|
343
|
+
<SampleContent title="Rendered as <section>" />
|
|
344
|
+
<code
|
|
345
|
+
style={{
|
|
346
|
+
display: 'block',
|
|
347
|
+
marginTop: '0.5rem',
|
|
348
|
+
padding: '0.25rem 0.5rem',
|
|
349
|
+
fontSize: '0.75rem',
|
|
350
|
+
backgroundColor: 'var(--sublime-color-surface-0, #f3f4f6)',
|
|
351
|
+
color: 'var(--sublime-color-text-secondary, #4b5563)',
|
|
352
|
+
borderRadius: '4px',
|
|
353
|
+
}}
|
|
354
|
+
>
|
|
355
|
+
<Surface as="section">
|
|
356
|
+
</code>
|
|
357
|
+
</Surface>
|
|
358
|
+
|
|
359
|
+
<Surface as="aside">
|
|
360
|
+
<SampleContent title="Rendered as <aside>" />
|
|
361
|
+
<code
|
|
362
|
+
style={{
|
|
363
|
+
display: 'block',
|
|
364
|
+
marginTop: '0.5rem',
|
|
365
|
+
padding: '0.25rem 0.5rem',
|
|
366
|
+
fontSize: '0.75rem',
|
|
367
|
+
backgroundColor: 'var(--sublime-color-surface-0, #f3f4f6)',
|
|
368
|
+
color: 'var(--sublime-color-text-secondary, #4b5563)',
|
|
369
|
+
borderRadius: '4px',
|
|
370
|
+
}}
|
|
371
|
+
>
|
|
372
|
+
<Surface as="aside">
|
|
373
|
+
</code>
|
|
374
|
+
</Surface>
|
|
375
|
+
</div>
|
|
376
|
+
</StoryWrapper>
|
|
377
|
+
);
|
|
378
|
+
|
|
379
|
+
export const KitchenSink: Story = () => (
|
|
380
|
+
<StoryWrapper title="Kitchen Sink (Combined Props)">
|
|
381
|
+
<div
|
|
382
|
+
style={{
|
|
383
|
+
display: 'grid',
|
|
384
|
+
gap: '1.5rem',
|
|
385
|
+
maxWidth: '500px',
|
|
386
|
+
}}
|
|
387
|
+
>
|
|
388
|
+
<Surface variant="elevated" padding="lg" radius="xl" border interactive>
|
|
389
|
+
<div style={{ textAlign: 'center' }}>
|
|
390
|
+
<h3 style={{ margin: '0 0 0.5rem 0', fontSize: '1.25rem', fontWeight: 600, color: 'var(--sublime-color-text-primary, #111827)' }}>
|
|
391
|
+
Product Card
|
|
392
|
+
</h3>
|
|
393
|
+
<p style={{ margin: 0, color: 'var(--sublime-color-text-secondary, #6b7280)' }}>
|
|
394
|
+
Elevated + Large Padding + XL Radius + Border + Interactive
|
|
395
|
+
</p>
|
|
396
|
+
<button
|
|
397
|
+
style={{
|
|
398
|
+
marginTop: '1rem',
|
|
399
|
+
padding: '0.5rem 1rem',
|
|
400
|
+
backgroundColor: 'var(--sublime-color-interactive-primary, #111827)',
|
|
401
|
+
color: 'var(--sublime-color-interactive-primary-text, #ffffff)',
|
|
402
|
+
border: 'none',
|
|
403
|
+
borderRadius: 'var(--sublime-radius-lg, 0.5rem)',
|
|
404
|
+
fontSize: '0.875rem',
|
|
405
|
+
fontWeight: 500,
|
|
406
|
+
cursor: 'pointer',
|
|
407
|
+
}}
|
|
408
|
+
>
|
|
409
|
+
Action
|
|
410
|
+
</button>
|
|
411
|
+
</div>
|
|
412
|
+
</Surface>
|
|
413
|
+
|
|
414
|
+
<Surface variant="inset" padding="md" radius="md" border={false} interactive={false}>
|
|
415
|
+
<div>
|
|
416
|
+
<label
|
|
417
|
+
style={{
|
|
418
|
+
display: 'block',
|
|
419
|
+
marginBottom: '0.25rem',
|
|
420
|
+
fontSize: '0.875rem',
|
|
421
|
+
fontWeight: 500,
|
|
422
|
+
color: 'var(--sublime-color-text-secondary, #374151)',
|
|
423
|
+
}}
|
|
424
|
+
>
|
|
425
|
+
Input Well
|
|
426
|
+
</label>
|
|
427
|
+
<input
|
|
428
|
+
type="text"
|
|
429
|
+
placeholder="Type here..."
|
|
430
|
+
style={{
|
|
431
|
+
width: '100%',
|
|
432
|
+
padding: '0.5rem 0.75rem',
|
|
433
|
+
border: '1px solid var(--sublime-color-border-primary, #d1d5db)',
|
|
434
|
+
borderRadius: 'var(--sublime-radius-md, 0.375rem)',
|
|
435
|
+
fontSize: '0.875rem',
|
|
436
|
+
boxSizing: 'border-box',
|
|
437
|
+
backgroundColor: 'var(--sublime-color-surface-0, #ffffff)',
|
|
438
|
+
color: 'var(--sublime-color-text-primary, #111827)',
|
|
439
|
+
}}
|
|
440
|
+
/>
|
|
441
|
+
<p style={{ margin: '0.5rem 0 0 0', fontSize: '0.75rem', color: 'var(--sublime-color-text-muted, #9ca3af)' }}>
|
|
442
|
+
Inset + Medium Padding + Static (no hover)
|
|
443
|
+
</p>
|
|
444
|
+
</div>
|
|
445
|
+
</Surface>
|
|
446
|
+
</div>
|
|
447
|
+
</StoryWrapper>
|
|
448
|
+
);
|
|
449
|
+
|
|
450
|
+
// Predefined vibrant backgrounds to showcase glass effect
|
|
451
|
+
const GLASS_BACKGROUNDS = [
|
|
452
|
+
{ name: 'Sunset', value: 'linear-gradient(135deg, #667eea 0%, #764ba2 25%, #f093fb 50%, #f5576c 75%, #ffa95c 100%)' },
|
|
453
|
+
{ name: 'Ocean', value: 'linear-gradient(135deg, #0061ff 0%, #60efff 100%)' },
|
|
454
|
+
{ name: 'Forest', value: 'linear-gradient(135deg, #0ba360 0%, #3cba92 100%)' },
|
|
455
|
+
{ name: 'Aurora', value: 'linear-gradient(135deg, #0f2027 0%, #203a43 50%, #2c5364 100%)' },
|
|
456
|
+
{ name: 'Berry', value: 'linear-gradient(135deg, #8e2de2 0%, #4a00e0 100%)' },
|
|
457
|
+
{ name: 'Coral', value: 'linear-gradient(135deg, #ff6b6b 0%, #feca57 100%)' },
|
|
458
|
+
{ name: 'Midnight', value: 'linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%)' },
|
|
459
|
+
{ name: 'Peach', value: 'linear-gradient(135deg, #ff9a9e 0%, #fecfef 50%, #fecfef 100%)' },
|
|
460
|
+
];
|
|
461
|
+
|
|
462
|
+
// Glass story wrapper with colorful background and color picker
|
|
463
|
+
const GlassStoryWrapper: React.FC<{ children: React.ReactNode; title?: string }> = ({
|
|
464
|
+
children,
|
|
465
|
+
title,
|
|
466
|
+
}) => {
|
|
467
|
+
const [bgIndex, setBgIndex] = React.useState(0);
|
|
468
|
+
|
|
469
|
+
return (
|
|
470
|
+
<div
|
|
471
|
+
style={{
|
|
472
|
+
padding: '2rem',
|
|
473
|
+
minHeight: '100vh',
|
|
474
|
+
background: GLASS_BACKGROUNDS[bgIndex].value,
|
|
475
|
+
backgroundAttachment: 'fixed',
|
|
476
|
+
fontFamily:
|
|
477
|
+
'var(--sublime-font-family-sans, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif)',
|
|
478
|
+
transition: 'background 0.5s ease',
|
|
479
|
+
}}
|
|
480
|
+
>
|
|
481
|
+
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: '1.5rem', flexWrap: 'wrap', gap: '1rem' }}>
|
|
482
|
+
{title && (
|
|
483
|
+
<h2
|
|
484
|
+
style={{
|
|
485
|
+
margin: 0,
|
|
486
|
+
fontSize: '1.25rem',
|
|
487
|
+
fontWeight: 600,
|
|
488
|
+
color: '#ffffff',
|
|
489
|
+
textShadow: '0 2px 4px rgba(0,0,0,0.2)',
|
|
490
|
+
}}
|
|
491
|
+
>
|
|
492
|
+
{title}
|
|
493
|
+
</h2>
|
|
494
|
+
)}
|
|
495
|
+
<button
|
|
496
|
+
onClick={() => setBgIndex((prev) => (prev + 1) % GLASS_BACKGROUNDS.length)}
|
|
497
|
+
style={{
|
|
498
|
+
padding: '0.5rem 1rem',
|
|
499
|
+
fontSize: '0.875rem',
|
|
500
|
+
fontWeight: 500,
|
|
501
|
+
color: '#1f2937',
|
|
502
|
+
background: 'rgba(255, 255, 255, 0.9)',
|
|
503
|
+
border: 'none',
|
|
504
|
+
borderRadius: '8px',
|
|
505
|
+
cursor: 'pointer',
|
|
506
|
+
boxShadow: '0 2px 8px rgba(0,0,0,0.15)',
|
|
507
|
+
transition: 'all 0.2s ease',
|
|
508
|
+
display: 'flex',
|
|
509
|
+
alignItems: 'center',
|
|
510
|
+
gap: '0.5rem',
|
|
511
|
+
}}
|
|
512
|
+
onMouseEnter={(e) => {
|
|
513
|
+
e.currentTarget.style.background = 'rgba(255, 255, 255, 1)';
|
|
514
|
+
e.currentTarget.style.transform = 'translateY(-1px)';
|
|
515
|
+
e.currentTarget.style.boxShadow = '0 4px 12px rgba(0,0,0,0.2)';
|
|
516
|
+
}}
|
|
517
|
+
onMouseLeave={(e) => {
|
|
518
|
+
e.currentTarget.style.background = 'rgba(255, 255, 255, 0.9)';
|
|
519
|
+
e.currentTarget.style.transform = 'translateY(0)';
|
|
520
|
+
e.currentTarget.style.boxShadow = '0 2px 8px rgba(0,0,0,0.15)';
|
|
521
|
+
}}
|
|
522
|
+
>
|
|
523
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
524
|
+
<circle cx="12" cy="12" r="10"/>
|
|
525
|
+
<path d="M12 2v20"/>
|
|
526
|
+
<path d="M2 12h20"/>
|
|
527
|
+
</svg>
|
|
528
|
+
Background: {GLASS_BACKGROUNDS[bgIndex].name}
|
|
529
|
+
</button>
|
|
530
|
+
</div>
|
|
531
|
+
{children}
|
|
532
|
+
</div>
|
|
533
|
+
);
|
|
534
|
+
};
|
|
535
|
+
|
|
536
|
+
export const Glass: Story = () => (
|
|
537
|
+
<GlassStoryWrapper title="Architectural Glass Surface">
|
|
538
|
+
<div
|
|
539
|
+
style={{
|
|
540
|
+
display: 'grid',
|
|
541
|
+
gap: '1.5rem',
|
|
542
|
+
maxWidth: '500px',
|
|
543
|
+
}}
|
|
544
|
+
>
|
|
545
|
+
<Surface variant="glass" interactive>
|
|
546
|
+
<SampleContent title="Architectural Glass" />
|
|
547
|
+
<p style={{ margin: '0.5rem 0 0 0', fontSize: '0.75rem', color: 'var(--sublime-color-text-muted, #6b7280)' }}>
|
|
548
|
+
Milky translucent with subtle vertical texture
|
|
549
|
+
</p>
|
|
550
|
+
</Surface>
|
|
551
|
+
|
|
552
|
+
<Surface variant="glass" border padding="lg" interactive>
|
|
553
|
+
<SampleContent title="Glass with Border" />
|
|
554
|
+
<p style={{ margin: '0.5rem 0 0 0', fontSize: '0.75rem', color: 'var(--sublime-color-text-muted, #6b7280)' }}>
|
|
555
|
+
Enhanced edge definition
|
|
556
|
+
</p>
|
|
557
|
+
</Surface>
|
|
558
|
+
|
|
559
|
+
<Surface variant="glass" radius="xl" padding="xl" interactive>
|
|
560
|
+
<SampleContent title="Large Glass Card" />
|
|
561
|
+
<p style={{ margin: '0.5rem 0 0 0', fontSize: '0.75rem', color: 'var(--sublime-color-text-muted, #6b7280)' }}>
|
|
562
|
+
XL radius and padding
|
|
563
|
+
</p>
|
|
564
|
+
</Surface>
|
|
565
|
+
|
|
566
|
+
<Surface variant="glass" interactive={false}>
|
|
567
|
+
<SampleContent title="Static Glass" />
|
|
568
|
+
<p style={{ margin: '0.5rem 0 0 0', fontSize: '0.75rem', color: 'var(--sublime-color-text-muted, #6b7280)' }}>
|
|
569
|
+
Non-interactive display
|
|
570
|
+
</p>
|
|
571
|
+
</Surface>
|
|
572
|
+
</div>
|
|
573
|
+
</GlassStoryWrapper>
|
|
574
|
+
);
|
|
575
|
+
|
|
576
|
+
export const GlassShowcase: Story = () => (
|
|
577
|
+
<GlassStoryWrapper title="Glass Showcase">
|
|
578
|
+
<div
|
|
579
|
+
style={{
|
|
580
|
+
display: 'grid',
|
|
581
|
+
gap: '2rem',
|
|
582
|
+
maxWidth: '600px',
|
|
583
|
+
}}
|
|
584
|
+
>
|
|
585
|
+
<Surface variant="glass" padding="xl" radius="xl" interactive>
|
|
586
|
+
<div style={{ textAlign: 'center' }}>
|
|
587
|
+
<h3 style={{ margin: '0 0 1rem 0', fontSize: '1.5rem', fontWeight: 600, color: 'var(--sublime-color-text-primary, #111827)' }}>
|
|
588
|
+
Luxury Architectural Glass
|
|
589
|
+
</h3>
|
|
590
|
+
<p style={{ margin: 0, fontSize: '1rem', lineHeight: 1.7, color: 'var(--sublime-color-text-secondary, #4b5563)' }}>
|
|
591
|
+
Inspired by high-end interior glass partitions. The subtle vertical texture catches light while the milky translucency provides privacy.
|
|
592
|
+
</p>
|
|
593
|
+
</div>
|
|
594
|
+
</Surface>
|
|
595
|
+
|
|
596
|
+
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '1.5rem' }}>
|
|
597
|
+
<Surface variant="glass" padding="lg" interactive>
|
|
598
|
+
<h4 style={{ margin: '0 0 0.5rem 0', fontSize: '1rem', color: 'var(--sublime-color-text-primary, #111827)' }}>
|
|
599
|
+
Interactive
|
|
600
|
+
</h4>
|
|
601
|
+
<p style={{ margin: 0, fontSize: '0.875rem', color: 'var(--sublime-color-text-secondary, #6b7280)' }}>
|
|
602
|
+
Hover to lift
|
|
603
|
+
</p>
|
|
604
|
+
</Surface>
|
|
605
|
+
|
|
606
|
+
<Surface variant="glass" padding="lg" interactive>
|
|
607
|
+
<h4 style={{ margin: '0 0 0.5rem 0', fontSize: '1rem', color: 'var(--sublime-color-text-primary, #111827)' }}>
|
|
608
|
+
Glass Card
|
|
609
|
+
</h4>
|
|
610
|
+
<p style={{ margin: 0, fontSize: '0.875rem', color: 'var(--sublime-color-text-secondary, #6b7280)' }}>
|
|
611
|
+
Click to press
|
|
612
|
+
</p>
|
|
613
|
+
</Surface>
|
|
614
|
+
</div>
|
|
615
|
+
|
|
616
|
+
<Surface variant="glass" border radius="full" padding="lg" interactive>
|
|
617
|
+
<div style={{ textAlign: 'center' }}>
|
|
618
|
+
<h3 style={{ margin: 0, fontSize: '1.125rem', fontWeight: 600, color: 'var(--sublime-color-text-primary, #111827)' }}>
|
|
619
|
+
Pill Shaped Glass
|
|
620
|
+
</h3>
|
|
621
|
+
</div>
|
|
622
|
+
</Surface>
|
|
623
|
+
</div>
|
|
624
|
+
</GlassStoryWrapper>
|
|
625
|
+
);
|
|
626
|
+
|
|
627
|
+
export const GlassUtilityClass: Story = () => (
|
|
628
|
+
<GlassStoryWrapper title="Glass Utility Class (sublime-glassed)">
|
|
629
|
+
<div
|
|
630
|
+
style={{
|
|
631
|
+
display: 'grid',
|
|
632
|
+
gap: '1.5rem',
|
|
633
|
+
maxWidth: '500px',
|
|
634
|
+
}}
|
|
635
|
+
>
|
|
636
|
+
{/* Using the utility class directly */}
|
|
637
|
+
<div className="sublime-glassed" style={{ padding: '1.5rem' }}>
|
|
638
|
+
<h3 style={{ margin: '0 0 0.5rem 0', fontSize: '1.125rem', fontWeight: 600, color: '#1f2937' }}>
|
|
639
|
+
Utility Class Glass
|
|
640
|
+
</h3>
|
|
641
|
+
<p style={{ margin: 0, fontSize: '0.875rem', color: '#4b5563' }}>
|
|
642
|
+
Applied directly with className="sublime-glassed". Same glass effect, full control over padding.
|
|
643
|
+
</p>
|
|
644
|
+
</div>
|
|
645
|
+
|
|
646
|
+
{/* Comparison: Surface component */}
|
|
647
|
+
<Surface variant="glass" padding="lg">
|
|
648
|
+
<h3 style={{ margin: '0 0 0.5rem 0', fontSize: '1.125rem', fontWeight: 600, color: '#1f2937' }}>
|
|
649
|
+
Surface Component Glass
|
|
650
|
+
</h3>
|
|
651
|
+
<p style={{ margin: 0, fontSize: '0.875rem', color: '#4b5563' }}>
|
|
652
|
+
Using Surface variant="glass". Provides consistent padding and additional features.
|
|
653
|
+
</p>
|
|
654
|
+
</Surface>
|
|
655
|
+
|
|
656
|
+
{/* Mixed: Utility class with custom styling */}
|
|
657
|
+
<div
|
|
658
|
+
className="sublime-glassed"
|
|
659
|
+
style={{
|
|
660
|
+
padding: '2rem',
|
|
661
|
+
borderRadius: '24px',
|
|
662
|
+
textAlign: 'center',
|
|
663
|
+
}}
|
|
664
|
+
>
|
|
665
|
+
<h3 style={{ margin: '0 0 0.75rem 0', fontSize: '1.25rem', fontWeight: 600, color: '#1f2937' }}>
|
|
666
|
+
Custom Styled Glass
|
|
667
|
+
</h3>
|
|
668
|
+
<p style={{ margin: 0, fontSize: '0.875rem', color: '#4b5563' }}>
|
|
669
|
+
Utility class with custom padding and larger border-radius override.
|
|
670
|
+
</p>
|
|
671
|
+
</div>
|
|
672
|
+
</div>
|
|
673
|
+
</GlassStoryWrapper>
|
|
674
|
+
);
|