@latte-macchiat-io/latte-vanilla-components 0.0.191 → 0.0.192
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/package.json +4 -1
- package/src/components/Actions/index.tsx +20 -0
- package/src/components/Actions/styles.css.ts +54 -0
- package/src/components/Button/index.tsx +29 -0
- package/src/components/Button/stories.tsx +4 -22
- package/src/components/Button/styles.css.ts +131 -0
- package/src/components/Carousel/{Carousel.tsx → index.tsx} +18 -115
- package/src/components/Carousel/styles.css.ts +176 -0
- package/src/components/Columns/index.tsx +36 -0
- package/src/components/Columns/styles.css.ts +70 -0
- package/src/components/ConsentCookie/ConsentCookie.css.ts +1 -1
- package/src/components/ConsentCookie/ConsentCookie.tsx +3 -3
- package/src/components/Footer/index.tsx +21 -0
- package/src/components/Footer/styles.css.ts +33 -0
- 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/index.tsx +53 -0
- package/src/components/Header/styles.css.ts +89 -0
- package/src/components/Heading/index.tsx +22 -0
- package/src/components/Heading/styles.css.ts +66 -0
- package/src/components/Heading/types.tsx +1 -0
- package/src/components/Icon/index.tsx +25 -0
- package/src/components/Icon/style.css.ts +11 -0
- package/src/components/KeyNumber/index.tsx +51 -0
- package/src/components/KeyNumber/styles.css.ts +76 -0
- package/src/components/LanguageSwitcher/index.tsx +80 -0
- package/src/components/LanguageSwitcher/{LanguageSwitcher.css.ts → styles.css.ts} +1 -1
- package/src/components/Logo/index.tsx +13 -0
- package/src/components/Logo/styles.css.ts +14 -0
- package/src/components/Main/index.tsx +17 -0
- package/src/components/Main/styles.css.ts +14 -0
- package/src/components/Modal/index.tsx +42 -0
- package/src/components/Modal/stories.tsx +14 -358
- package/src/components/Modal/styles.css.ts +90 -0
- package/src/components/Nav/index.tsx +22 -0
- package/src/components/Nav/styles.css.ts +30 -0
- package/src/components/NavLegal/index.tsx +17 -0
- package/src/components/NavLegal/styles.css.ts +20 -0
- package/src/components/NavSocial/index.tsx +32 -0
- package/src/components/NavSocial/styles.css.ts +33 -0
- package/src/components/Section/index.tsx +20 -0
- package/src/components/Section/stories.tsx +5 -57
- package/src/components/Section/styles.css.ts +106 -0
- package/src/components/ThemeTest/ThemeTest.css.ts +11 -0
- package/src/components/ThemeTest/ThemeTest.tsx +12 -0
- package/src/components/ThemeToggle/ThemeToggle.tsx +30 -0
- package/src/components/Video/index.tsx +117 -0
- package/src/components/Video/styles.css.ts +200 -0
- package/src/index.ts +29 -41
- package/src/styles/mediaqueries.ts +2 -0
- package/src/styles/sprinkles.css.ts +11 -8
- package/src/theme/baseThemeValues.ts +1235 -0
- package/src/theme/contract.css.ts +676 -0
- package/src/{themes → theme}/createTheme.ts +40 -1
- package/src/theme/default.css.ts +10 -0
- package/src/utils/combineResponsive.ts +9 -0
- package/src/utils/generateResponsiveMedia.ts +19 -0
- package/src/components/Actions/Actions.css.ts +0 -113
- package/src/components/Actions/Actions.tsx +0 -132
- package/src/components/Button/Button.css.ts +0 -119
- package/src/components/Button/Button.tsx +0 -132
- package/src/components/Carousel/Carousel.css.ts +0 -179
- package/src/components/Columns/Columns.css.ts +0 -185
- package/src/components/Columns/Columns.tsx +0 -142
- package/src/components/Footer/Footer.css.ts +0 -108
- package/src/components/Footer/Footer.tsx +0 -130
- package/src/components/Header/Header.css.ts +0 -111
- package/src/components/Header/Header.tsx +0 -158
- package/src/components/Icon/Icon.css.ts +0 -101
- package/src/components/Icon/Icon.tsx +0 -159
- package/src/components/KeyNumber/KeyNumber.css.ts +0 -158
- package/src/components/KeyNumber/KeyNumber.tsx +0 -166
- package/src/components/LanguageSwitcher/LanguageSwitcher.tsx +0 -168
- package/src/components/Logo/Logo.css.ts +0 -98
- package/src/components/Logo/Logo.tsx +0 -137
- package/src/components/Main/Main.css.ts +0 -62
- package/src/components/Main/Main.tsx +0 -130
- package/src/components/Modal/Modal.css.ts +0 -203
- package/src/components/Modal/Modal.tsx +0 -194
- package/src/components/Nav/Nav.css.ts +0 -123
- package/src/components/Nav/Nav.tsx +0 -130
- package/src/components/NavLegal/NavLegal.css.ts +0 -121
- package/src/components/NavLegal/NavLegal.tsx +0 -133
- package/src/components/NavSocial/NavSocial.css.ts +0 -121
- package/src/components/NavSocial/NavSocial.tsx +0 -169
- package/src/components/Section/Section.css.ts +0 -101
- package/src/components/Section/Section.tsx +0 -130
- package/src/components/Video/Video.css.ts +0 -210
- package/src/components/Video/Video.tsx +0 -243
- package/src/components/VideoFullWidth/VideoFullWidth.css.ts +0 -50
- package/src/components/VideoFullWidth/VideoFullWidth.tsx +0 -152
- package/src/components/VideoFullWidth/export.tsx +0 -2
- package/src/themes/baseThemeValues.ts +0 -160
- package/src/themes/contract.css.ts +0 -83
- package/src/types/withClassName.ts +0 -4
@@ -1,7 +1,7 @@
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/react-vite';
|
2
2
|
import React from 'react';
|
3
|
-
import {
|
4
|
-
import {
|
3
|
+
import { Button } from '../..';
|
4
|
+
import { Section } from '.';
|
5
5
|
|
6
6
|
const meta: Meta<typeof Section> = {
|
7
7
|
title: 'Layout Components/Section',
|
@@ -41,16 +41,6 @@ The Section component provides consistent spacing and layout for content section
|
|
41
41
|
control: 'boolean',
|
42
42
|
description: 'Make the section take full viewport height',
|
43
43
|
},
|
44
|
-
spacing: {
|
45
|
-
control: 'select',
|
46
|
-
options: ['none', 'small', 'medium', 'large'],
|
47
|
-
description: 'Amount of vertical padding',
|
48
|
-
},
|
49
|
-
as: {
|
50
|
-
control: 'select',
|
51
|
-
options: ['section', 'div', 'main', 'article', 'aside'],
|
52
|
-
description: 'HTML element to render as',
|
53
|
-
},
|
54
44
|
},
|
55
45
|
};
|
56
46
|
|
@@ -134,7 +124,6 @@ export const FullHeight: Story = {
|
|
134
124
|
|
135
125
|
export const NoSpacing: Story = {
|
136
126
|
args: {
|
137
|
-
spacing: 'none',
|
138
127
|
children: (
|
139
128
|
<>
|
140
129
|
<h2>No Spacing Section</h2>
|
@@ -146,7 +135,6 @@ export const NoSpacing: Story = {
|
|
146
135
|
|
147
136
|
export const SmallSpacing: Story = {
|
148
137
|
args: {
|
149
|
-
spacing: 'sm',
|
150
138
|
children: (
|
151
139
|
<>
|
152
140
|
<h2>Small Spacing Section</h2>
|
@@ -158,7 +146,6 @@ export const SmallSpacing: Story = {
|
|
158
146
|
|
159
147
|
export const LargeSpacing: Story = {
|
160
148
|
args: {
|
161
|
-
spacing: 'lg',
|
162
149
|
children: (
|
163
150
|
<>
|
164
151
|
<h2>Large Spacing Section</h2>
|
@@ -168,49 +155,10 @@ export const LargeSpacing: Story = {
|
|
168
155
|
},
|
169
156
|
};
|
170
157
|
|
171
|
-
export const AsMain: Story = {
|
172
|
-
args: {
|
173
|
-
as: 'main',
|
174
|
-
children: (
|
175
|
-
<>
|
176
|
-
<h1>Main Content Area</h1>
|
177
|
-
<p>This section is rendered as a main element for semantic HTML.</p>
|
178
|
-
</>
|
179
|
-
),
|
180
|
-
},
|
181
|
-
parameters: {
|
182
|
-
docs: {
|
183
|
-
description: {
|
184
|
-
story: 'Section rendered as a main element for the primary content area.',
|
185
|
-
},
|
186
|
-
},
|
187
|
-
},
|
188
|
-
};
|
189
|
-
|
190
|
-
export const AsArticle: Story = {
|
191
|
-
args: {
|
192
|
-
as: 'article',
|
193
|
-
children: (
|
194
|
-
<>
|
195
|
-
<h2>Article Section</h2>
|
196
|
-
<p>This section is rendered as an article element for standalone content.</p>
|
197
|
-
<p>Perfect for blog posts, news articles, or any self-contained content.</p>
|
198
|
-
</>
|
199
|
-
),
|
200
|
-
},
|
201
|
-
parameters: {
|
202
|
-
docs: {
|
203
|
-
description: {
|
204
|
-
story: 'Section rendered as an article element for standalone content.',
|
205
|
-
},
|
206
|
-
},
|
207
|
-
},
|
208
|
-
};
|
209
|
-
|
210
158
|
// Real-world Examples
|
211
159
|
export const HeroSection: Story = {
|
212
160
|
render: () => (
|
213
|
-
<Section isFullHeight={true} align="center"
|
161
|
+
<Section isFullHeight={true} align="center">
|
214
162
|
<div
|
215
163
|
style={{
|
216
164
|
color: 'white',
|
@@ -249,7 +197,7 @@ export const HeroSection: Story = {
|
|
249
197
|
|
250
198
|
export const FeatureSection: Story = {
|
251
199
|
render: () => (
|
252
|
-
<Section
|
200
|
+
<Section>
|
253
201
|
<div style={{ maxWidth: '1200px', margin: '0 auto' }}>
|
254
202
|
<div style={{ textAlign: 'center', marginBottom: '3rem' }}>
|
255
203
|
<h2 style={{ fontSize: '2.5rem', marginBottom: '1rem' }}>Why Choose Our Components?</h2>
|
@@ -317,7 +265,7 @@ export const FeatureSection: Story = {
|
|
317
265
|
|
318
266
|
export const CallToActionSection: Story = {
|
319
267
|
render: () => (
|
320
|
-
<Section isDark={true} align="center"
|
268
|
+
<Section isDark={true} align="center">
|
321
269
|
<div style={{ color: 'white', textAlign: 'center', maxWidth: '600px', margin: '0 auto' }}>
|
322
270
|
<h2 style={{ fontSize: '2.5rem', marginBottom: '1rem' }}>Ready to Get Started?</h2>
|
323
271
|
<p style={{ fontSize: '1.1rem', marginBottom: '2rem', opacity: 0.9 }}>
|
@@ -0,0 +1,106 @@
|
|
1
|
+
import { style } from '@vanilla-extract/css';
|
2
|
+
import { recipe, type RecipeVariants } from '@vanilla-extract/recipes';
|
3
|
+
|
4
|
+
import { themeContract } from '../../theme/contract.css';
|
5
|
+
import { generateResponsiveMedia } from '../../utils/generateResponsiveMedia';
|
6
|
+
|
7
|
+
export const sectionRecipe = recipe({
|
8
|
+
base: [
|
9
|
+
{
|
10
|
+
width: '100%',
|
11
|
+
display: 'flex',
|
12
|
+
margin: '0 auto',
|
13
|
+
position: 'relative',
|
14
|
+
flexDirection: 'column',
|
15
|
+
|
16
|
+
'@media': {
|
17
|
+
...generateResponsiveMedia({
|
18
|
+
paddingLeft: themeContract.global.paddingLeft,
|
19
|
+
paddingRight: themeContract.global.paddingRight,
|
20
|
+
}),
|
21
|
+
},
|
22
|
+
},
|
23
|
+
],
|
24
|
+
|
25
|
+
variants: {
|
26
|
+
align: {
|
27
|
+
left: {
|
28
|
+
textAlign: 'left',
|
29
|
+
alignItems: 'flex-start',
|
30
|
+
},
|
31
|
+
center: {
|
32
|
+
textAlign: 'center',
|
33
|
+
alignItems: 'center',
|
34
|
+
},
|
35
|
+
right: {
|
36
|
+
textAlign: 'right',
|
37
|
+
alignItems: 'flex-end',
|
38
|
+
},
|
39
|
+
},
|
40
|
+
isDark: {
|
41
|
+
true: {
|
42
|
+
color: themeContract.colors.textLight,
|
43
|
+
},
|
44
|
+
false: {
|
45
|
+
color: themeContract.colors.text,
|
46
|
+
},
|
47
|
+
},
|
48
|
+
isFullHeight: {
|
49
|
+
true: {
|
50
|
+
minHeight: '100vh',
|
51
|
+
justifyContent: 'center',
|
52
|
+
},
|
53
|
+
false: {
|
54
|
+
minHeight: 'auto',
|
55
|
+
justifyContent: 'flex-start',
|
56
|
+
},
|
57
|
+
},
|
58
|
+
withPaddingTop: {
|
59
|
+
true: {
|
60
|
+
'@media': {
|
61
|
+
...generateResponsiveMedia({
|
62
|
+
paddingTop: themeContract.section.paddingTop,
|
63
|
+
}),
|
64
|
+
},
|
65
|
+
},
|
66
|
+
false: { paddingTop: 'none' },
|
67
|
+
},
|
68
|
+
withPaddingBottom: {
|
69
|
+
true: {
|
70
|
+
'@media': {
|
71
|
+
...generateResponsiveMedia({
|
72
|
+
paddingBottom: themeContract.section.paddingBottom,
|
73
|
+
}),
|
74
|
+
},
|
75
|
+
},
|
76
|
+
false: { paddingBottom: 'none' },
|
77
|
+
},
|
78
|
+
},
|
79
|
+
|
80
|
+
defaultVariants: {
|
81
|
+
align: 'left',
|
82
|
+
isDark: false,
|
83
|
+
isFullHeight: false,
|
84
|
+
withPaddingTop: true,
|
85
|
+
withPaddingBottom: true,
|
86
|
+
},
|
87
|
+
});
|
88
|
+
|
89
|
+
export const sectionContent = style([
|
90
|
+
{
|
91
|
+
width: '100%',
|
92
|
+
display: 'flex',
|
93
|
+
margin: '0 auto',
|
94
|
+
flexDirection: 'column',
|
95
|
+
|
96
|
+
maxWidth: themeContract.maxWidth,
|
97
|
+
|
98
|
+
'@media': {
|
99
|
+
...generateResponsiveMedia({
|
100
|
+
gap: themeContract.section.gap,
|
101
|
+
}),
|
102
|
+
},
|
103
|
+
},
|
104
|
+
]);
|
105
|
+
|
106
|
+
export type SectionVariants = RecipeVariants<typeof sectionRecipe>;
|
@@ -0,0 +1,11 @@
|
|
1
|
+
import { style } from '@vanilla-extract/css';
|
2
|
+
import { themeContract } from '../../../theme/contract.css';
|
3
|
+
|
4
|
+
export const testStyle = style({
|
5
|
+
padding: themeContract.space.large,
|
6
|
+
backgroundColor: themeContract.colors.primary,
|
7
|
+
color: themeContract.colors.text,
|
8
|
+
borderRadius: themeContract.radii.medium,
|
9
|
+
margin: themeContract.space.medium,
|
10
|
+
border: `2px solid ${themeContract.colors.border}`,
|
11
|
+
});
|
@@ -0,0 +1,12 @@
|
|
1
|
+
import { testStyle } from './ThemeTest.css';
|
2
|
+
|
3
|
+
export function ThemeTest() {
|
4
|
+
return (
|
5
|
+
<div className={testStyle}>
|
6
|
+
<h3>Theme Test Component</h3>
|
7
|
+
<p>Background should be primary color</p>
|
8
|
+
<p>Text should be theme text color</p>
|
9
|
+
<p>This should change when you toggle the theme!</p>
|
10
|
+
</div>
|
11
|
+
);
|
12
|
+
}
|
@@ -0,0 +1,30 @@
|
|
1
|
+
'use client';
|
2
|
+
|
3
|
+
import { useEffect, useState } from 'react';
|
4
|
+
|
5
|
+
export function ThemeToggle() {
|
6
|
+
const [theme, setTheme] = useState<'light' | 'dark'>('light');
|
7
|
+
|
8
|
+
useEffect(() => {
|
9
|
+
// Get initial theme from localStorage or system preference
|
10
|
+
const savedTheme = localStorage.getItem('theme') as 'light' | 'dark' | null;
|
11
|
+
const systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
|
12
|
+
const initialTheme = savedTheme || systemTheme;
|
13
|
+
|
14
|
+
setTheme(initialTheme);
|
15
|
+
document.documentElement.dataset.theme = initialTheme;
|
16
|
+
}, []);
|
17
|
+
|
18
|
+
const toggleTheme = () => {
|
19
|
+
const newTheme = theme === 'light' ? 'dark' : 'light';
|
20
|
+
setTheme(newTheme);
|
21
|
+
document.documentElement.dataset.theme = newTheme;
|
22
|
+
localStorage.setItem('theme', newTheme);
|
23
|
+
};
|
24
|
+
|
25
|
+
return (
|
26
|
+
<button onClick={toggleTheme} aria-label="Toggle theme">
|
27
|
+
{theme === 'light' ? '🌙' : '☀️'}
|
28
|
+
</button>
|
29
|
+
);
|
30
|
+
}
|
@@ -0,0 +1,117 @@
|
|
1
|
+
'use client';
|
2
|
+
|
3
|
+
/* eslint-disable jsx-a11y/media-has-caption */
|
4
|
+
|
5
|
+
import { clsx } from 'clsx';
|
6
|
+
import { forwardRef, useEffect, useRef, useState } from 'react';
|
7
|
+
import {
|
8
|
+
closeButton,
|
9
|
+
pauseButton,
|
10
|
+
playButton,
|
11
|
+
posterImage,
|
12
|
+
soundButton,
|
13
|
+
videoElement,
|
14
|
+
videoPoster,
|
15
|
+
videoRecipe,
|
16
|
+
type VideoVariants,
|
17
|
+
} from './styles.css';
|
18
|
+
|
19
|
+
export type VideoProps = React.HTMLAttributes<HTMLDivElement> &
|
20
|
+
VideoVariants & {
|
21
|
+
css?: string;
|
22
|
+
video: string;
|
23
|
+
poster?: string;
|
24
|
+
isAutoPlay?: boolean;
|
25
|
+
startMuted?: boolean;
|
26
|
+
showControls?: boolean;
|
27
|
+
hidePlayButton?: boolean;
|
28
|
+
isPlayingFullScreen?: boolean;
|
29
|
+
onPlay?: () => void;
|
30
|
+
onClose?: () => void;
|
31
|
+
onEnded?: () => void;
|
32
|
+
};
|
33
|
+
|
34
|
+
export const Video = forwardRef<HTMLDivElement, VideoProps>(
|
35
|
+
(
|
36
|
+
{
|
37
|
+
video,
|
38
|
+
poster,
|
39
|
+
isAutoPlay = false,
|
40
|
+
startMuted = false,
|
41
|
+
showControls = false,
|
42
|
+
hidePlayButton = false,
|
43
|
+
isPlayingFullScreen = false,
|
44
|
+
onPlay,
|
45
|
+
onClose,
|
46
|
+
onEnded,
|
47
|
+
size,
|
48
|
+
css,
|
49
|
+
className,
|
50
|
+
},
|
51
|
+
ref
|
52
|
+
) => {
|
53
|
+
const videoRef = useRef<HTMLVideoElement>(null);
|
54
|
+
const [isPlaying, setIsPlaying] = useState(false);
|
55
|
+
const [isMuted, setIsMuted] = useState(isAutoPlay || startMuted);
|
56
|
+
|
57
|
+
const playVideo = () => {
|
58
|
+
onPlay?.();
|
59
|
+
videoRef.current?.play();
|
60
|
+
setIsPlaying(true);
|
61
|
+
};
|
62
|
+
|
63
|
+
const closeVideo = () => {
|
64
|
+
onClose?.();
|
65
|
+
videoRef.current?.pause();
|
66
|
+
setIsPlaying(false);
|
67
|
+
};
|
68
|
+
|
69
|
+
const pauseVideo = () => {
|
70
|
+
videoRef.current?.pause();
|
71
|
+
setIsPlaying(false);
|
72
|
+
};
|
73
|
+
|
74
|
+
const toggleMutedVideo = () => {
|
75
|
+
const newIsMuted = !isMuted;
|
76
|
+
setIsMuted(newIsMuted);
|
77
|
+
if (videoRef.current) videoRef.current.muted = newIsMuted;
|
78
|
+
};
|
79
|
+
|
80
|
+
const handleVideoEnded = () => {
|
81
|
+
onEnded?.();
|
82
|
+
closeVideo();
|
83
|
+
};
|
84
|
+
|
85
|
+
useEffect(() => {
|
86
|
+
if (videoRef.current) videoRef.current.muted = isMuted;
|
87
|
+
}, [isMuted]);
|
88
|
+
|
89
|
+
return (
|
90
|
+
<div ref={ref} className={clsx(videoRecipe({ size }), css, className)}>
|
91
|
+
<video ref={videoRef} className={videoElement} playsInline muted={isMuted} autoPlay={isAutoPlay} onEnded={handleVideoEnded}>
|
92
|
+
<source src={video} type="video/mp4" />
|
93
|
+
</video>
|
94
|
+
|
95
|
+
{poster && (
|
96
|
+
<div className={videoPoster} data-playing={isPlaying}>
|
97
|
+
<img src={poster} alt="Video poster" className={posterImage} />
|
98
|
+
</div>
|
99
|
+
)}
|
100
|
+
|
101
|
+
{!hidePlayButton && !isAutoPlay && (
|
102
|
+
<button className={playButton} data-playing={isPlaying} onClick={playVideo} aria-label="Play video" type="button" />
|
103
|
+
)}
|
104
|
+
|
105
|
+
{isPlayingFullScreen && <button className={closeButton} onClick={closeVideo} aria-label="Close video" type="button" />}
|
106
|
+
|
107
|
+
{isPlaying && showControls && <button className={pauseButton} onClick={pauseVideo} aria-label="Pause video" type="button" />}
|
108
|
+
|
109
|
+
{showControls && (
|
110
|
+
<button className={soundButton} onClick={toggleMutedVideo} aria-label={isMuted ? 'Unmute video' : 'Mute video'} type="button" />
|
111
|
+
)}
|
112
|
+
</div>
|
113
|
+
);
|
114
|
+
}
|
115
|
+
);
|
116
|
+
|
117
|
+
Video.displayName = 'Video';
|
@@ -0,0 +1,200 @@
|
|
1
|
+
import { style } from '@vanilla-extract/css';
|
2
|
+
import { calc } from '@vanilla-extract/css-utils';
|
3
|
+
import { recipe, RecipeVariants } from '@vanilla-extract/recipes';
|
4
|
+
|
5
|
+
import { queries } from '../../styles/mediaqueries';
|
6
|
+
import { themeContract } from '../../theme/contract.css';
|
7
|
+
import { generateResponsiveMedia } from '../../utils/generateResponsiveMedia';
|
8
|
+
|
9
|
+
export const videoRecipe = recipe({
|
10
|
+
base: {
|
11
|
+
width: '100%',
|
12
|
+
height: '100%',
|
13
|
+
overflow: 'hidden',
|
14
|
+
position: 'absolute',
|
15
|
+
|
16
|
+
backgroundColor: themeContract.colors.background,
|
17
|
+
},
|
18
|
+
|
19
|
+
variants: {
|
20
|
+
size: {
|
21
|
+
fullWidth: { width: '100%', aspectRatio: '16/9' },
|
22
|
+
fullScreen: [
|
23
|
+
{
|
24
|
+
width: '100vw',
|
25
|
+
aspectRatio: '16/9',
|
26
|
+
position: 'relative',
|
27
|
+
marginLeft: calc(themeContract.global.paddingLeft.mobile).negate().toString(),
|
28
|
+
marginRight: calc(themeContract.global.paddingRight.mobile).negate().toString(),
|
29
|
+
|
30
|
+
'@media': {
|
31
|
+
[queries.sm]: {
|
32
|
+
marginLeft: calc(themeContract.global.paddingLeft.sm).negate().toString(),
|
33
|
+
marginRight: calc(themeContract.global.paddingRight.sm).negate().toString(),
|
34
|
+
},
|
35
|
+
[queries.md]: {
|
36
|
+
marginLeft: calc(themeContract.global.paddingLeft.md).negate().toString(),
|
37
|
+
marginRight: calc(themeContract.global.paddingRight.md).negate().toString(),
|
38
|
+
},
|
39
|
+
[queries.lg]: {
|
40
|
+
marginLeft: calc(themeContract.global.paddingLeft.lg).negate().toString(),
|
41
|
+
marginRight: calc(themeContract.global.paddingRight.lg).negate().toString(),
|
42
|
+
},
|
43
|
+
[queries.xl]: {
|
44
|
+
marginLeft: calc(themeContract.global.paddingLeft.xl).negate().toString(),
|
45
|
+
marginRight: calc(themeContract.global.paddingRight.xl).negate().toString(),
|
46
|
+
},
|
47
|
+
[queries['2xl']]: {
|
48
|
+
marginLeft: `calc((100vw - ${themeContract.maxWidth}) / -2)`,
|
49
|
+
marginRight: `calc((100vw - ${themeContract.maxWidth}) / -2)`,
|
50
|
+
},
|
51
|
+
},
|
52
|
+
},
|
53
|
+
],
|
54
|
+
},
|
55
|
+
},
|
56
|
+
|
57
|
+
defaultVariants: {
|
58
|
+
size: 'fullWidth',
|
59
|
+
},
|
60
|
+
});
|
61
|
+
|
62
|
+
export type VideoVariants = RecipeVariants<typeof videoRecipe>;
|
63
|
+
|
64
|
+
export const videoElement = style({
|
65
|
+
top: '50%',
|
66
|
+
left: '50%',
|
67
|
+
width: 'auto',
|
68
|
+
minWidth: '100%',
|
69
|
+
minHeight: '100%',
|
70
|
+
position: 'absolute',
|
71
|
+
transform: 'translate(-50%, -50%)',
|
72
|
+
});
|
73
|
+
|
74
|
+
export const videoPoster = style({
|
75
|
+
top: 0,
|
76
|
+
left: 0,
|
77
|
+
opacity: 1,
|
78
|
+
width: '100%',
|
79
|
+
height: '100%',
|
80
|
+
position: 'absolute',
|
81
|
+
pointerEvents: 'auto',
|
82
|
+
transition: 'opacity 0.3s ease-in-out',
|
83
|
+
|
84
|
+
selectors: {
|
85
|
+
'&[data-playing="true"]': {
|
86
|
+
opacity: 0,
|
87
|
+
pointerEvents: 'none',
|
88
|
+
},
|
89
|
+
},
|
90
|
+
});
|
91
|
+
|
92
|
+
export const posterImage = style({
|
93
|
+
width: '100%',
|
94
|
+
height: '100%',
|
95
|
+
objectFit: 'cover',
|
96
|
+
});
|
97
|
+
|
98
|
+
export const playButton = style([
|
99
|
+
{
|
100
|
+
top: '50%',
|
101
|
+
left: '50%',
|
102
|
+
width: '40px',
|
103
|
+
height: '40px',
|
104
|
+
display: 'flex',
|
105
|
+
cursor: 'pointer',
|
106
|
+
alignItems: 'center',
|
107
|
+
position: 'absolute',
|
108
|
+
justifyContent: 'center',
|
109
|
+
transition: 'all 0.3s ease-in-out',
|
110
|
+
transform: 'translate(-50%, -50%)',
|
111
|
+
|
112
|
+
border: themeContract.video.playButton.border,
|
113
|
+
color: themeContract.video.playButton.iconColor,
|
114
|
+
borderRadius: themeContract.video.playButton.borderRadius,
|
115
|
+
backgroundColor: themeContract.video.playButton.backgroundColor,
|
116
|
+
|
117
|
+
selectors: {
|
118
|
+
'&[data-playing="true"]': {
|
119
|
+
opacity: 0,
|
120
|
+
pointerEvents: 'none',
|
121
|
+
},
|
122
|
+
},
|
123
|
+
|
124
|
+
'@media': {
|
125
|
+
...generateResponsiveMedia({
|
126
|
+
width: themeContract.video.playButton.width,
|
127
|
+
height: themeContract.video.playButton.height,
|
128
|
+
}),
|
129
|
+
},
|
130
|
+
},
|
131
|
+
]);
|
132
|
+
|
133
|
+
const controlButton = style({
|
134
|
+
border: 'none',
|
135
|
+
display: 'flex',
|
136
|
+
cursor: 'pointer',
|
137
|
+
position: 'absolute',
|
138
|
+
alignItems: 'center',
|
139
|
+
justifyContent: 'center',
|
140
|
+
transition: 'all 0.3s ease-in-out',
|
141
|
+
});
|
142
|
+
|
143
|
+
export const closeButton = style([
|
144
|
+
controlButton,
|
145
|
+
{
|
146
|
+
top: themeContract.space.md,
|
147
|
+
right: themeContract.space.md,
|
148
|
+
border: themeContract.video.closeButton.border,
|
149
|
+
color: themeContract.video.closeButton.iconColor,
|
150
|
+
borderRadius: themeContract.video.closeButton.borderRadius,
|
151
|
+
backgroundColor: themeContract.video.closeButton.backgroundColor,
|
152
|
+
|
153
|
+
'@media': {
|
154
|
+
...generateResponsiveMedia({
|
155
|
+
width: themeContract.video.closeButton.width,
|
156
|
+
height: themeContract.video.closeButton.height,
|
157
|
+
}),
|
158
|
+
},
|
159
|
+
},
|
160
|
+
]);
|
161
|
+
|
162
|
+
export const pauseButton = style([
|
163
|
+
controlButton,
|
164
|
+
{
|
165
|
+
right: '80px',
|
166
|
+
|
167
|
+
bottom: themeContract.space.md,
|
168
|
+
border: themeContract.video.pauseButton.border,
|
169
|
+
color: themeContract.video.pauseButton.iconColor,
|
170
|
+
borderRadius: themeContract.video.pauseButton.borderRadius,
|
171
|
+
backgroundColor: themeContract.video.pauseButton.backgroundColor,
|
172
|
+
|
173
|
+
'@media': {
|
174
|
+
...generateResponsiveMedia({
|
175
|
+
width: themeContract.video.pauseButton.width,
|
176
|
+
height: themeContract.video.pauseButton.height,
|
177
|
+
}),
|
178
|
+
},
|
179
|
+
},
|
180
|
+
]);
|
181
|
+
|
182
|
+
export const soundButton = style([
|
183
|
+
controlButton,
|
184
|
+
|
185
|
+
{
|
186
|
+
bottom: themeContract.space.md,
|
187
|
+
right: themeContract.space.md,
|
188
|
+
border: themeContract.video.soundButton.border,
|
189
|
+
color: themeContract.video.soundButton.iconColor,
|
190
|
+
borderRadius: themeContract.video.soundButton.borderRadius,
|
191
|
+
backgroundColor: themeContract.video.soundButton.backgroundColor,
|
192
|
+
|
193
|
+
'@media': {
|
194
|
+
...generateResponsiveMedia({
|
195
|
+
width: themeContract.video.soundButton.width,
|
196
|
+
height: themeContract.video.soundButton.height,
|
197
|
+
}),
|
198
|
+
},
|
199
|
+
},
|
200
|
+
]);
|