@latte-macchiat-io/latte-vanilla-components 0.0.186 → 0.0.188
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 +286 -10
- package/package.json +5 -3
- package/src/components/Actions/Actions.css.ts +1 -1
- package/src/components/Button/Button.css.ts +1 -1
- package/src/components/Button/stories.tsx +10 -17
- package/src/components/Carousel/Carousel.css.ts +1 -1
- package/src/components/Columns/Columns.css.ts +1 -1
- package/src/components/ConsentCookie/ConsentCookie.css.ts +1 -1
- package/src/components/Footer/Footer.css.ts +1 -1
- package/src/components/Form/Form.css.ts +1 -1
- package/src/components/Form/Row/Row.css.ts +1 -1
- package/src/components/Form/TextField/Input/Input.css.ts +1 -1
- package/src/components/Form/TextField/Label/Label.css.ts +1 -1
- package/src/components/Form/TextField/TextField.css.ts +1 -1
- package/src/components/Form/TextField/Textarea/Textarea.css.ts +1 -1
- package/src/components/Header/Header.css.ts +1 -1
- package/src/components/Header/HeaderOverlay/index.tsx +1 -1
- package/src/components/Header/HeaderOverlay/styles.css.ts +7 -7
- package/src/components/Header/ToggleNav/index.tsx +2 -5
- package/src/components/Icon/Icon.css.ts +0 -1
- package/src/components/KeyNumber/KeyNumber.css.ts +1 -1
- package/src/components/LanguageSwitcher/LanguageSwitcher.css.ts +1 -1
- package/src/components/Logo/Logo.css.ts +1 -1
- package/src/components/Logo/stories.tsx +1 -0
- package/src/components/Main/Main.css.ts +1 -1
- package/src/components/Modal/Modal.css.ts +1 -1
- package/src/components/Modal/stories.tsx +55 -89
- package/src/components/Nav/Nav.css.ts +1 -1
- package/src/components/Nav/Nav.tsx +1 -0
- package/src/components/NavLegal/NavLegal.css.ts +1 -1
- package/src/components/NavSocial/NavSocial.css.ts +1 -1
- package/src/components/Section/Section.css.ts +1 -1
- package/src/components/Section/stories.tsx +61 -61
- package/src/components/Video/Video.css.ts +1 -1
- package/src/components/VideoFullWidth/VideoFullWidth.css.ts +1 -1
- package/src/index.ts +9 -22
- package/src/styles/sprinkles.css.ts +1 -1
- package/src/themes/createTheme.css.ts +65 -0
- package/src/themes/dark.css.ts +4 -3
- package/src/themes/light.css.ts +3 -3
- package/src/types/withClassName.ts +1 -0
- package/src/assets/styles/default-theme.ts +0 -312
- package/src/assets/styles/mediaqueries.tsx +0 -24
- package/src/components/ToRemove/ToRemove.tsx +0 -3
- package/src/theme/index.ts +0 -6
- package/src/theme/utils.ts +0 -76
- package/src/types/theme.ts +0 -295
- package/src/utils/quickTheme.ts +0 -38
- package/src/utils/theme.ts +0 -131
- /package/src/{theme → themes}/baseThemeValues.ts +0 -0
- /package/src/{theme → themes}/contract.css.ts +0 -0
@@ -1,7 +1,7 @@
|
|
1
1
|
import { keyframes, style } from '@vanilla-extract/css';
|
2
2
|
import { recipe, RecipeVariants } from '@vanilla-extract/recipes';
|
3
3
|
import { queries } from '../../styles/mediaqueries';
|
4
|
-
import { themeContract } from '../../
|
4
|
+
import { themeContract } from '../../themes/contract.css';
|
5
5
|
|
6
6
|
const fadeIn = keyframes({
|
7
7
|
from: { opacity: '0' },
|
@@ -1,3 +1,4 @@
|
|
1
|
+
import React from 'react';
|
1
2
|
import type { Meta, StoryObj } from '@storybook/react-vite';
|
2
3
|
import { useState } from 'react';
|
3
4
|
import { Modal } from './Modal';
|
@@ -76,13 +77,7 @@ const InteractiveModal = ({ size = 'medium', centered = true, ...args }: any) =>
|
|
76
77
|
<Button variant="primary" onClick={() => setIsOpen(true)}>
|
77
78
|
Open Modal
|
78
79
|
</Button>
|
79
|
-
<Modal
|
80
|
-
isOpen={isOpen}
|
81
|
-
onClose={() => setIsOpen(false)}
|
82
|
-
size={size}
|
83
|
-
centered={centered}
|
84
|
-
{...args}
|
85
|
-
>
|
80
|
+
<Modal isOpen={isOpen} onClose={() => setIsOpen(false)} size={size} centered={centered} {...args}>
|
86
81
|
<div style={{ padding: '2rem' }}>
|
87
82
|
<h2>Modal Title</h2>
|
88
83
|
<p>This is the modal content. You can put any React components here.</p>
|
@@ -103,7 +98,7 @@ const InteractiveModal = ({ size = 'medium', centered = true, ...args }: any) =>
|
|
103
98
|
export const Default: Story = {
|
104
99
|
render: (args) => <InteractiveModal {...args} />,
|
105
100
|
args: {
|
106
|
-
size: '
|
101
|
+
size: 'md',
|
107
102
|
centered: true,
|
108
103
|
showCloseButton: true,
|
109
104
|
closeOnBackdropClick: true,
|
@@ -194,24 +189,15 @@ export const ConfirmationDialog: Story = {
|
|
194
189
|
|
195
190
|
return (
|
196
191
|
<Section>
|
197
|
-
<Button variant="
|
192
|
+
<Button variant="danger" onClick={() => setIsOpen(true)}>
|
198
193
|
Delete Item
|
199
194
|
</Button>
|
200
|
-
<Modal
|
201
|
-
isOpen={isOpen}
|
202
|
-
onClose={() => setIsOpen(false)}
|
203
|
-
size="small"
|
204
|
-
centered={true}
|
205
|
-
>
|
195
|
+
<Modal isOpen={isOpen} onClose={() => setIsOpen(false)} size="sm" centered={true}>
|
206
196
|
<div style={{ padding: '2rem', textAlign: 'center' }}>
|
207
|
-
<h3 style={{ color: 'var(--latte-colors-error)', marginBottom: '1rem' }}>
|
208
|
-
|
209
|
-
</h3>
|
210
|
-
<p style={{ marginBottom: '2rem' }}>
|
211
|
-
Are you sure you want to delete this item? This action cannot be undone.
|
212
|
-
</p>
|
197
|
+
<h3 style={{ color: 'var(--latte-colors-error)', marginBottom: '1rem' }}>Delete Confirmation</h3>
|
198
|
+
<p style={{ marginBottom: '2rem' }}>Are you sure you want to delete this item? This action cannot be undone.</p>
|
213
199
|
<div style={{ display: 'flex', gap: '1rem', justifyContent: 'center' }}>
|
214
|
-
<Button variant="
|
200
|
+
<Button variant="danger" onClick={() => setIsOpen(false)}>
|
215
201
|
Delete
|
216
202
|
</Button>
|
217
203
|
<Button variant="secondary" onClick={() => setIsOpen(false)}>
|
@@ -241,58 +227,46 @@ export const FormModal: Story = {
|
|
241
227
|
<Button variant="primary" onClick={() => setIsOpen(true)}>
|
242
228
|
Add New User
|
243
229
|
</Button>
|
244
|
-
<Modal
|
245
|
-
isOpen={isOpen}
|
246
|
-
onClose={() => setIsOpen(false)}
|
247
|
-
size="medium"
|
248
|
-
centered={true}
|
249
|
-
>
|
230
|
+
<Modal isOpen={isOpen} onClose={() => setIsOpen(false)} size="md" centered={true}>
|
250
231
|
<div style={{ padding: '2rem' }}>
|
251
232
|
<h2 style={{ marginBottom: '2rem' }}>Add New User</h2>
|
252
233
|
<form style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
|
253
234
|
<div>
|
254
|
-
<label style={{ display: 'block', marginBottom: '0.5rem', fontWeight: '500' }}>
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
width: '100%',
|
261
|
-
padding: '0.75rem',
|
235
|
+
<label style={{ display: 'block', marginBottom: '0.5rem', fontWeight: '500' }}>Name</label>
|
236
|
+
<input
|
237
|
+
type="text"
|
238
|
+
style={{
|
239
|
+
width: '100%',
|
240
|
+
padding: '0.75rem',
|
262
241
|
border: '1px solid var(--latte-colors-border)',
|
263
242
|
borderRadius: 'var(--latte-radii-md)',
|
264
|
-
fontSize: 'var(--latte-fontSizes-md)'
|
265
|
-
}}
|
243
|
+
fontSize: 'var(--latte-fontSizes-md)',
|
244
|
+
}}
|
266
245
|
/>
|
267
246
|
</div>
|
268
247
|
<div>
|
269
|
-
<label style={{ display: 'block', marginBottom: '0.5rem', fontWeight: '500' }}>
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
width: '100%',
|
276
|
-
padding: '0.75rem',
|
248
|
+
<label style={{ display: 'block', marginBottom: '0.5rem', fontWeight: '500' }}>Email</label>
|
249
|
+
<input
|
250
|
+
type="email"
|
251
|
+
style={{
|
252
|
+
width: '100%',
|
253
|
+
padding: '0.75rem',
|
277
254
|
border: '1px solid var(--latte-colors-border)',
|
278
255
|
borderRadius: 'var(--latte-radii-md)',
|
279
|
-
fontSize: 'var(--latte-fontSizes-md)'
|
280
|
-
}}
|
256
|
+
fontSize: 'var(--latte-fontSizes-md)',
|
257
|
+
}}
|
281
258
|
/>
|
282
259
|
</div>
|
283
260
|
<div>
|
284
|
-
<label style={{ display: 'block', marginBottom: '0.5rem', fontWeight: '500' }}>
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
width: '100%',
|
290
|
-
padding: '0.75rem',
|
261
|
+
<label style={{ display: 'block', marginBottom: '0.5rem', fontWeight: '500' }}>Role</label>
|
262
|
+
<select
|
263
|
+
style={{
|
264
|
+
width: '100%',
|
265
|
+
padding: '0.75rem',
|
291
266
|
border: '1px solid var(--latte-colors-border)',
|
292
267
|
borderRadius: 'var(--latte-radii-md)',
|
293
|
-
fontSize: 'var(--latte-fontSizes-md)'
|
294
|
-
}}
|
295
|
-
>
|
268
|
+
fontSize: 'var(--latte-fontSizes-md)',
|
269
|
+
}}>
|
296
270
|
<option>User</option>
|
297
271
|
<option>Admin</option>
|
298
272
|
<option>Moderator</option>
|
@@ -346,50 +320,42 @@ export const ImageGallery: Story = {
|
|
346
320
|
key={index}
|
347
321
|
src={src}
|
348
322
|
alt={`Gallery ${index + 1}`}
|
349
|
-
style={{
|
350
|
-
width: '100%',
|
351
|
-
height: '150px',
|
352
|
-
objectFit: 'cover',
|
323
|
+
style={{
|
324
|
+
width: '100%',
|
325
|
+
height: '150px',
|
326
|
+
objectFit: 'cover',
|
353
327
|
borderRadius: 'var(--latte-radii-md)',
|
354
|
-
cursor: 'pointer'
|
328
|
+
cursor: 'pointer',
|
355
329
|
}}
|
356
330
|
onClick={() => openImage(index)}
|
357
331
|
/>
|
358
332
|
))}
|
359
333
|
</div>
|
360
|
-
<Modal
|
361
|
-
isOpen={isOpen}
|
362
|
-
onClose={() => setIsOpen(false)}
|
363
|
-
size="large"
|
364
|
-
centered={true}
|
365
|
-
>
|
334
|
+
<Modal isOpen={isOpen} onClose={() => setIsOpen(false)} size="lg" centered={true}>
|
366
335
|
<div style={{ padding: '1rem' }}>
|
367
336
|
<img
|
368
337
|
src={images[selectedImage]}
|
369
338
|
alt={`Gallery ${selectedImage + 1}`}
|
370
|
-
style={{
|
371
|
-
width: '100%',
|
372
|
-
height: 'auto',
|
373
|
-
borderRadius: 'var(--latte-radii-md)'
|
339
|
+
style={{
|
340
|
+
width: '100%',
|
341
|
+
height: 'auto',
|
342
|
+
borderRadius: 'var(--latte-radii-md)',
|
374
343
|
}}
|
375
344
|
/>
|
376
|
-
<div
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
onClick={() => setSelectedImage((prev) => (prev > 0 ? prev - 1 : images.length - 1))}
|
385
|
-
>
|
345
|
+
<div
|
346
|
+
style={{
|
347
|
+
marginTop: '1rem',
|
348
|
+
display: 'flex',
|
349
|
+
justifyContent: 'space-between',
|
350
|
+
alignItems: 'center',
|
351
|
+
}}>
|
352
|
+
<Button variant="ghost" onClick={() => setSelectedImage((prev) => (prev > 0 ? prev - 1 : images.length - 1))}>
|
386
353
|
← Previous
|
387
354
|
</Button>
|
388
|
-
<span>
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
>
|
355
|
+
<span>
|
356
|
+
Image {selectedImage + 1} of {images.length}
|
357
|
+
</span>
|
358
|
+
<Button variant="ghost" onClick={() => setSelectedImage((prev) => (prev < images.length - 1 ? prev + 1 : 0))}>
|
393
359
|
Next →
|
394
360
|
</Button>
|
395
361
|
</div>
|
@@ -405,4 +371,4 @@ export const ImageGallery: Story = {
|
|
405
371
|
},
|
406
372
|
},
|
407
373
|
},
|
408
|
-
};
|
374
|
+
};
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import { style } from '@vanilla-extract/css';
|
2
2
|
import { recipe, RecipeVariants } from '@vanilla-extract/recipes';
|
3
3
|
import { queries } from '../../styles/mediaqueries';
|
4
|
-
import { themeContract } from '../../
|
4
|
+
import { themeContract } from '../../themes/contract.css';
|
5
5
|
|
6
6
|
const navBase = style({
|
7
7
|
display: 'flex',
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import { style } from '@vanilla-extract/css';
|
2
2
|
import { recipe, RecipeVariants } from '@vanilla-extract/recipes';
|
3
3
|
import { queries } from '../../styles/mediaqueries';
|
4
|
-
import { themeContract } from '../../
|
4
|
+
import { themeContract } from '../../themes/contract.css';
|
5
5
|
|
6
6
|
const navLegalBase = style({
|
7
7
|
display: 'flex',
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import { style } from '@vanilla-extract/css';
|
2
2
|
import { recipe, RecipeVariants } from '@vanilla-extract/recipes';
|
3
3
|
import { queries } from '../../styles/mediaqueries';
|
4
|
-
import { themeContract } from '../../
|
4
|
+
import { themeContract } from '../../themes/contract.css';
|
5
5
|
|
6
6
|
const navSocialBase = style({
|
7
7
|
display: 'flex',
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import { style } from '@vanilla-extract/css';
|
2
2
|
import { recipe, RecipeVariants } from '@vanilla-extract/recipes';
|
3
|
-
import { themeContract } from '../../
|
3
|
+
import { themeContract } from '../../themes/contract.css';
|
4
4
|
|
5
5
|
const sectionBase = style({
|
6
6
|
width: '100%',
|
@@ -1,3 +1,4 @@
|
|
1
|
+
import React from 'react';
|
1
2
|
import type { Meta, StoryObj } from '@storybook/react-vite';
|
2
3
|
import { Section } from './Section';
|
3
4
|
import { Button } from '../Button/Button';
|
@@ -101,9 +102,7 @@ export const DarkSection: Story = {
|
|
101
102
|
children: (
|
102
103
|
<>
|
103
104
|
<h2 style={{ color: 'white' }}>Dark Section</h2>
|
104
|
-
<p style={{ color: 'rgba(255, 255, 255, 0.8)' }}>
|
105
|
-
This section has a dark background, great for creating visual contrast.
|
106
|
-
</p>
|
105
|
+
<p style={{ color: 'rgba(255, 255, 255, 0.8)' }}>This section has a dark background, great for creating visual contrast.</p>
|
107
106
|
<Button variant="primary">Get Started</Button>
|
108
107
|
</>
|
109
108
|
),
|
@@ -121,8 +120,12 @@ export const FullHeight: Story = {
|
|
121
120
|
This section takes up the full viewport height, perfect for hero sections and landing page intros.
|
122
121
|
</p>
|
123
122
|
<div style={{ display: 'flex', gap: '1rem' }}>
|
124
|
-
<Button variant="primary" size="
|
125
|
-
|
123
|
+
<Button variant="primary" size="lg">
|
124
|
+
Get Started
|
125
|
+
</Button>
|
126
|
+
<Button variant="secondary" size="lg">
|
127
|
+
Learn More
|
128
|
+
</Button>
|
126
129
|
</div>
|
127
130
|
</div>
|
128
131
|
),
|
@@ -143,7 +146,7 @@ export const NoSpacing: Story = {
|
|
143
146
|
|
144
147
|
export const SmallSpacing: Story = {
|
145
148
|
args: {
|
146
|
-
spacing: '
|
149
|
+
spacing: 'sm',
|
147
150
|
children: (
|
148
151
|
<>
|
149
152
|
<h2>Small Spacing Section</h2>
|
@@ -155,7 +158,7 @@ export const SmallSpacing: Story = {
|
|
155
158
|
|
156
159
|
export const LargeSpacing: Story = {
|
157
160
|
args: {
|
158
|
-
spacing: '
|
161
|
+
spacing: 'lg',
|
159
162
|
children: (
|
160
163
|
<>
|
161
164
|
<h2>Large Spacing Section</h2>
|
@@ -208,27 +211,27 @@ export const AsArticle: Story = {
|
|
208
211
|
export const HeroSection: Story = {
|
209
212
|
render: () => (
|
210
213
|
<Section isFullHeight={true} align="center" backgroundColor="primary">
|
211
|
-
<div
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
</h1>
|
214
|
+
<div
|
215
|
+
style={{
|
216
|
+
color: 'white',
|
217
|
+
textAlign: 'center',
|
218
|
+
display: 'flex',
|
219
|
+
flexDirection: 'column',
|
220
|
+
justifyContent: 'center',
|
221
|
+
alignItems: 'center',
|
222
|
+
height: '100%',
|
223
|
+
maxWidth: '800px',
|
224
|
+
margin: '0 auto',
|
225
|
+
}}>
|
226
|
+
<h1 style={{ fontSize: '3rem', marginBottom: '1rem' }}>Welcome to Our Platform</h1>
|
225
227
|
<p style={{ fontSize: '1.25rem', marginBottom: '3rem', opacity: 0.9 }}>
|
226
|
-
Build amazing applications with our comprehensive component library.
|
227
|
-
Get started in minutes and scale to millions of users.
|
228
|
+
Build amazing applications with our comprehensive component library. Get started in minutes and scale to millions of users.
|
228
229
|
</p>
|
229
230
|
<div style={{ display: 'flex', gap: '1rem', flexWrap: 'wrap', justifyContent: 'center' }}>
|
230
|
-
<Button variant="secondary" size="
|
231
|
-
|
231
|
+
<Button variant="secondary" size="lg">
|
232
|
+
Get Started Free
|
233
|
+
</Button>
|
234
|
+
<Button variant="ghost" size="lg" style={{ borderColor: 'white', color: 'white' }}>
|
232
235
|
Watch Demo
|
233
236
|
</Button>
|
234
237
|
</div>
|
@@ -246,60 +249,57 @@ export const HeroSection: Story = {
|
|
246
249
|
|
247
250
|
export const FeatureSection: Story = {
|
248
251
|
render: () => (
|
249
|
-
<Section spacing="
|
252
|
+
<Section spacing="lg">
|
250
253
|
<div style={{ maxWidth: '1200px', margin: '0 auto' }}>
|
251
254
|
<div style={{ textAlign: 'center', marginBottom: '3rem' }}>
|
252
|
-
<h2 style={{ fontSize: '2.5rem', marginBottom: '1rem' }}>
|
253
|
-
Why Choose Our Components?
|
254
|
-
</h2>
|
255
|
+
<h2 style={{ fontSize: '2.5rem', marginBottom: '1rem' }}>Why Choose Our Components?</h2>
|
255
256
|
<p style={{ fontSize: '1.1rem', color: 'var(--latte-colors-textSecondary)', maxWidth: '600px', margin: '0 auto' }}>
|
256
257
|
Built with modern best practices, accessibility in mind, and developer experience at the forefront.
|
257
258
|
</p>
|
258
259
|
</div>
|
259
|
-
|
260
|
-
<div
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
260
|
+
|
261
|
+
<div
|
262
|
+
style={{
|
263
|
+
display: 'grid',
|
264
|
+
gridTemplateColumns: 'repeat(auto-fit, minmax(300px, 1fr))',
|
265
|
+
gap: '2rem',
|
266
|
+
}}>
|
265
267
|
{[
|
266
268
|
{
|
267
269
|
title: '🎨 Theme System',
|
268
|
-
description: 'Flexible theming with light/dark modes and complete customization options.'
|
270
|
+
description: 'Flexible theming with light/dark modes and complete customization options.',
|
269
271
|
},
|
270
272
|
{
|
271
273
|
title: '⚡ Performance',
|
272
|
-
description: 'Zero-runtime CSS-in-JS with Vanilla Extract for optimal performance.'
|
274
|
+
description: 'Zero-runtime CSS-in-JS with Vanilla Extract for optimal performance.',
|
273
275
|
},
|
274
276
|
{
|
275
277
|
title: '🔒 Type Safety',
|
276
|
-
description: 'Full TypeScript support with excellent IntelliSense and autocomplete.'
|
278
|
+
description: 'Full TypeScript support with excellent IntelliSense and autocomplete.',
|
277
279
|
},
|
278
280
|
{
|
279
281
|
title: '📱 Responsive',
|
280
|
-
description: 'Mobile-first design with responsive utilities and breakpoint support.'
|
282
|
+
description: 'Mobile-first design with responsive utilities and breakpoint support.',
|
281
283
|
},
|
282
284
|
{
|
283
285
|
title: '♿ Accessible',
|
284
|
-
description: 'WCAG compliant components with proper ARIA attributes and keyboard navigation.'
|
286
|
+
description: 'WCAG compliant components with proper ARIA attributes and keyboard navigation.',
|
285
287
|
},
|
286
288
|
{
|
287
289
|
title: '🚀 Developer Experience',
|
288
|
-
description: 'Great documentation, hot reloading, and intuitive component APIs.'
|
289
|
-
}
|
290
|
+
description: 'Great documentation, hot reloading, and intuitive component APIs.',
|
291
|
+
},
|
290
292
|
].map((feature, index) => (
|
291
|
-
<div
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
</h3>
|
300
|
-
<p style={{ color: 'var(--latte-colors-textSecondary)' }}>
|
301
|
-
{feature.description}
|
302
|
-
</p>
|
293
|
+
<div
|
294
|
+
key={index}
|
295
|
+
style={{
|
296
|
+
padding: '2rem',
|
297
|
+
backgroundColor: 'var(--latte-colors-surface)',
|
298
|
+
borderRadius: 'var(--latte-radii-lg)',
|
299
|
+
border: '1px solid var(--latte-colors-border)',
|
300
|
+
}}>
|
301
|
+
<h3 style={{ marginBottom: '1rem', fontSize: '1.25rem' }}>{feature.title}</h3>
|
302
|
+
<p style={{ color: 'var(--latte-colors-textSecondary)' }}>{feature.description}</p>
|
303
303
|
</div>
|
304
304
|
))}
|
305
305
|
</div>
|
@@ -317,17 +317,17 @@ export const FeatureSection: Story = {
|
|
317
317
|
|
318
318
|
export const CallToActionSection: Story = {
|
319
319
|
render: () => (
|
320
|
-
<Section isDark={true} align="center" spacing="
|
320
|
+
<Section isDark={true} align="center" spacing="lg">
|
321
321
|
<div style={{ color: 'white', textAlign: 'center', maxWidth: '600px', margin: '0 auto' }}>
|
322
|
-
<h2 style={{ fontSize: '2.5rem', marginBottom: '1rem' }}>
|
323
|
-
Ready to Get Started?
|
324
|
-
</h2>
|
322
|
+
<h2 style={{ fontSize: '2.5rem', marginBottom: '1rem' }}>Ready to Get Started?</h2>
|
325
323
|
<p style={{ fontSize: '1.1rem', marginBottom: '2rem', opacity: 0.9 }}>
|
326
324
|
Join thousands of developers building amazing applications with our component library.
|
327
325
|
</p>
|
328
326
|
<div style={{ display: 'flex', gap: '1rem', justifyContent: 'center', flexWrap: 'wrap' }}>
|
329
|
-
<Button variant="primary" size="
|
330
|
-
|
327
|
+
<Button variant="primary" size="lg">
|
328
|
+
Start Building
|
329
|
+
</Button>
|
330
|
+
<Button variant="ghost" size="lg" style={{ borderColor: 'white', color: 'white' }}>
|
331
331
|
View Documentation
|
332
332
|
</Button>
|
333
333
|
</div>
|
@@ -341,4 +341,4 @@ export const CallToActionSection: Story = {
|
|
341
341
|
},
|
342
342
|
},
|
343
343
|
},
|
344
|
-
};
|
344
|
+
};
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import { style } from '@vanilla-extract/css';
|
2
2
|
import { recipe, RecipeVariants } from '@vanilla-extract/recipes';
|
3
|
-
import { themeContract } from '../../
|
3
|
+
import { themeContract } from '../../themes/contract.css';
|
4
4
|
|
5
5
|
const videoBase = style({
|
6
6
|
position: 'relative',
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import { style } from '@vanilla-extract/css';
|
2
2
|
import { recipe, RecipeVariants } from '@vanilla-extract/recipes';
|
3
|
-
import { themeContract } from '../../
|
3
|
+
import { themeContract } from '../../themes/contract.css';
|
4
4
|
|
5
5
|
const videoFullWidthBase = style({
|
6
6
|
height: 0,
|
package/src/index.ts
CHANGED
@@ -1,11 +1,17 @@
|
|
1
1
|
// Theme system - Import this first to apply global styles
|
2
|
-
export
|
2
|
+
export { themeContract } from './themes/contract.css';
|
3
|
+
export { baseLightTheme, baseDarkTheme } from './themes/baseThemeValues';
|
4
|
+
export { createLightTheme, createDarkTheme, type ThemeOverrides } from './themes/createTheme.css';
|
3
5
|
|
4
|
-
//
|
6
|
+
// Available themes
|
7
|
+
export { lightTheme } from './themes/light.css';
|
8
|
+
export { darkTheme } from './themes/dark.css';
|
9
|
+
|
10
|
+
// Styles utilities (sprinkles, media queries, etc.)
|
5
11
|
export { sprinkles, responsiveProperties, type Sprinkles } from './styles/sprinkles.css';
|
6
12
|
export { breakpoints, queries } from './styles/mediaqueries';
|
7
13
|
|
8
|
-
//
|
14
|
+
// Components
|
9
15
|
export { Button, type ButtonProps } from './components/Button/Button';
|
10
16
|
export { type ButtonVariants } from './components/Button/Button.css';
|
11
17
|
|
@@ -83,22 +89,3 @@ export { type InputVariants } from './components/Form/TextField/Input/Input.css'
|
|
83
89
|
|
84
90
|
export { Textarea, type TextareaProps } from './components/Form/TextField/Textarea/Textarea';
|
85
91
|
export { type TextareaVariants } from './components/Form/TextField/Textarea/Textarea.css';
|
86
|
-
|
87
|
-
export { ToRemove } from './components/ToRemove/ToRemove';
|
88
|
-
|
89
|
-
// Theme System - Core Exports
|
90
|
-
export { themeContract } from './theme/contract.css';
|
91
|
-
export { baseLightTheme, baseDarkTheme } from './theme/baseThemeValues';
|
92
|
-
|
93
|
-
// Pre-built Themes (Ready to Use)
|
94
|
-
export { lightTheme } from './themes/light.css';
|
95
|
-
export { darkTheme } from './themes/dark.css';
|
96
|
-
|
97
|
-
// Quick Theme Utilities (For Rapid Development)
|
98
|
-
export { quickTheme, createQuickTheme } from './utils/quickTheme';
|
99
|
-
|
100
|
-
// Advanced Theme Creation
|
101
|
-
export { createDarkTheme, createLightTheme, type ThemeOverrides } from './utils/theme';
|
102
|
-
|
103
|
-
// Theme Management Utilities
|
104
|
-
export { toggleTheme, setTheme, getCurrentTheme } from './theme/utils';
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import { createSprinkles, defineProperties } from '@vanilla-extract/sprinkles';
|
2
2
|
import { queries } from './mediaqueries';
|
3
|
-
import { themeContract } from '../
|
3
|
+
import { themeContract } from '../themes/contract.css';
|
4
4
|
|
5
5
|
const responsiveProperties = defineProperties({
|
6
6
|
conditions: {
|
@@ -0,0 +1,65 @@
|
|
1
|
+
import { createGlobalTheme } from '@vanilla-extract/css';
|
2
|
+
import { baseDarkTheme, baseLightTheme } from './baseThemeValues';
|
3
|
+
import { themeContract } from './contract.css';
|
4
|
+
|
5
|
+
// Type for partial theme overrides
|
6
|
+
export type ThemeOverrides = {
|
7
|
+
colors?: Partial<typeof baseLightTheme.colors>;
|
8
|
+
space?: Partial<typeof baseLightTheme.space>;
|
9
|
+
radii?: Partial<typeof baseLightTheme.radii>;
|
10
|
+
fonts?: Partial<typeof baseLightTheme.fonts>;
|
11
|
+
maxWidth?: Partial<typeof baseLightTheme.maxWidth>;
|
12
|
+
fontSizes?: Partial<typeof baseLightTheme.fontSizes>;
|
13
|
+
fontWeights?: Partial<typeof baseLightTheme.fontSizes>;
|
14
|
+
lineHeights?: Partial<typeof baseLightTheme.fontSizes>;
|
15
|
+
shadows?: Partial<typeof baseLightTheme.fontSizes>;
|
16
|
+
section?: Partial<typeof baseLightTheme.fontSizes>;
|
17
|
+
header?: Partial<typeof baseLightTheme.fontSizes>;
|
18
|
+
footer?: Partial<typeof baseLightTheme.fontSizes>;
|
19
|
+
};
|
20
|
+
|
21
|
+
// Utility to create a theme with partial overrides over light theme base
|
22
|
+
const createAppTheme = (selector: string, overrides: ThemeOverrides = {}) => {
|
23
|
+
return createGlobalTheme(selector, themeContract, {
|
24
|
+
colors: { ...baseLightTheme.colors, ...overrides.colors },
|
25
|
+
space: { ...baseLightTheme.space, ...overrides.space },
|
26
|
+
radii: { ...baseLightTheme.radii, ...overrides.radii },
|
27
|
+
fonts: { ...baseLightTheme.fonts, ...overrides.fonts },
|
28
|
+
maxWidth: `${baseLightTheme.maxWidth || overrides.maxWidth}`,
|
29
|
+
fontSizes: { ...baseLightTheme.fontSizes, ...overrides.fontSizes },
|
30
|
+
fontWeights: { ...baseLightTheme.fontWeights, ...overrides.fontWeights },
|
31
|
+
lineHeights: { ...baseLightTheme.lineHeights, ...overrides.lineHeights },
|
32
|
+
shadows: { ...baseLightTheme.shadows, ...overrides.shadows },
|
33
|
+
section: { ...baseLightTheme.section, ...overrides.section },
|
34
|
+
header: { ...baseLightTheme.header, ...overrides.header },
|
35
|
+
footer: { ...baseLightTheme.footer, ...overrides.footer },
|
36
|
+
});
|
37
|
+
};
|
38
|
+
|
39
|
+
// Utility to create a theme with partial overrides over dark theme base
|
40
|
+
const createAppDarkTheme = (selector: string, overrides: ThemeOverrides = {}) => {
|
41
|
+
return createGlobalTheme(selector, themeContract, {
|
42
|
+
colors: { ...baseDarkTheme.colors, ...overrides.colors },
|
43
|
+
space: { ...baseDarkTheme.space, ...overrides.space },
|
44
|
+
radii: { ...baseDarkTheme.radii, ...overrides.radii },
|
45
|
+
fonts: { ...baseDarkTheme.fonts, ...overrides.fonts },
|
46
|
+
maxWidth: overrides.maxWidth || `${baseDarkTheme.maxWidth}px`,
|
47
|
+
fontSizes: { ...baseDarkTheme.fontSizes, ...overrides.fontSizes },
|
48
|
+
fontWeights: { ...baseDarkTheme.fontWeights, ...overrides.fontWeights },
|
49
|
+
lineHeights: { ...baseDarkTheme.lineHeights, ...overrides.lineHeights },
|
50
|
+
shadows: { ...baseDarkTheme.shadows, ...overrides.shadows },
|
51
|
+
section: { ...baseDarkTheme.section, ...overrides.section },
|
52
|
+
header: { ...baseDarkTheme.header, ...overrides.header },
|
53
|
+
footer: { ...baseDarkTheme.footer, ...overrides.footer },
|
54
|
+
});
|
55
|
+
};
|
56
|
+
|
57
|
+
// Convenience function for light theme (extends base light theme)
|
58
|
+
export const createLightTheme = (overrides: ThemeOverrides = {}) => {
|
59
|
+
return createAppTheme('html', overrides);
|
60
|
+
};
|
61
|
+
|
62
|
+
// Convenience function for dark theme (extends base dark theme)
|
63
|
+
export const createDarkTheme = (overrides: ThemeOverrides = {}) => {
|
64
|
+
return createAppDarkTheme('html[data-theme="dark"]', overrides);
|
65
|
+
};
|
package/src/themes/dark.css.ts
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
import { createGlobalTheme } from '@vanilla-extract/css';
|
2
|
-
import {
|
3
|
-
import {
|
2
|
+
import { baseDarkTheme } from './baseThemeValues';
|
3
|
+
import { themeContract } from './contract.css';
|
4
4
|
|
5
5
|
// Create the dark theme at module level so Vanilla Extract can process it
|
6
|
+
// The dark theme will only be applied when the html element has a data-theme="dark" attribute
|
6
7
|
export const darkTheme = createGlobalTheme('html[data-theme="dark"]', themeContract, {
|
7
8
|
colors: baseDarkTheme.colors,
|
8
9
|
space: baseDarkTheme.space,
|
@@ -16,4 +17,4 @@ export const darkTheme = createGlobalTheme('html[data-theme="dark"]', themeContr
|
|
16
17
|
section: baseDarkTheme.section,
|
17
18
|
header: baseDarkTheme.header,
|
18
19
|
footer: baseDarkTheme.footer,
|
19
|
-
});
|
20
|
+
});
|