@latte-macchiat-io/latte-vanilla-components 0.0.191 → 0.0.193

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.
Files changed (99) hide show
  1. package/package.json +4 -1
  2. package/src/components/Actions/index.tsx +20 -0
  3. package/src/components/Actions/styles.css.ts +54 -0
  4. package/src/components/Button/index.tsx +29 -0
  5. package/src/components/Button/stories.tsx +4 -22
  6. package/src/components/Button/styles.css.ts +131 -0
  7. package/src/components/Carousel/{Carousel.tsx → index.tsx} +18 -115
  8. package/src/components/Carousel/styles.css.ts +176 -0
  9. package/src/components/Columns/index.tsx +36 -0
  10. package/src/components/Columns/styles.css.ts +70 -0
  11. package/src/components/ConsentCookie/ConsentCookie.css.ts +1 -1
  12. package/src/components/ConsentCookie/ConsentCookie.tsx +3 -3
  13. package/src/components/Footer/index.tsx +21 -0
  14. package/src/components/Footer/styles.css.ts +33 -0
  15. package/src/components/Form/Form.css.ts +1 -1
  16. package/src/components/Form/Row/Row.css.ts +1 -1
  17. package/src/components/Form/TextField/Input/Input.css.ts +1 -1
  18. package/src/components/Form/TextField/Label/Label.css.ts +1 -1
  19. package/src/components/Form/TextField/TextField.css.ts +1 -1
  20. package/src/components/Form/TextField/Textarea/Textarea.css.ts +1 -1
  21. package/src/components/Header/index.tsx +53 -0
  22. package/src/components/Header/styles.css.ts +89 -0
  23. package/src/components/Heading/index.tsx +22 -0
  24. package/src/components/Heading/styles.css.ts +66 -0
  25. package/src/components/Heading/types.tsx +1 -0
  26. package/src/components/Icon/index.tsx +25 -0
  27. package/src/components/Icon/style.css.ts +11 -0
  28. package/src/components/KeyNumber/index.tsx +51 -0
  29. package/src/components/KeyNumber/styles.css.ts +76 -0
  30. package/src/components/LanguageSwitcher/index.tsx +80 -0
  31. package/src/components/LanguageSwitcher/{LanguageSwitcher.css.ts → styles.css.ts} +1 -1
  32. package/src/components/Logo/index.tsx +13 -0
  33. package/src/components/Logo/styles.css.ts +14 -0
  34. package/src/components/Main/index.tsx +17 -0
  35. package/src/components/Main/styles.css.ts +14 -0
  36. package/src/components/Modal/index.tsx +42 -0
  37. package/src/components/Modal/stories.tsx +14 -358
  38. package/src/components/Modal/styles.css.ts +90 -0
  39. package/src/components/Nav/index.tsx +22 -0
  40. package/src/components/Nav/styles.css.ts +30 -0
  41. package/src/components/NavLegal/index.tsx +17 -0
  42. package/src/components/NavLegal/styles.css.ts +20 -0
  43. package/src/components/NavSocial/index.tsx +32 -0
  44. package/src/components/NavSocial/styles.css.ts +33 -0
  45. package/src/components/Section/index.tsx +20 -0
  46. package/src/components/Section/stories.tsx +5 -57
  47. package/src/components/Section/styles.css.ts +106 -0
  48. package/src/components/ThemeTest/ThemeTest.css.ts +11 -0
  49. package/src/components/ThemeTest/ThemeTest.tsx +12 -0
  50. package/src/components/ThemeToggle/ThemeToggle.tsx +30 -0
  51. package/src/components/Video/index.tsx +117 -0
  52. package/src/components/Video/styles.css.ts +200 -0
  53. package/src/index.ts +31 -41
  54. package/src/styles/mediaqueries.ts +2 -0
  55. package/src/styles/sprinkles.css.ts +11 -8
  56. package/src/theme/baseThemeValues.ts +1235 -0
  57. package/src/theme/contract.css.ts +676 -0
  58. package/src/{themes → theme}/createTheme.ts +40 -1
  59. package/src/theme/default.css.ts +10 -0
  60. package/src/utils/combineResponsive.ts +9 -0
  61. package/src/utils/generateResponsiveMedia.ts +19 -0
  62. package/src/components/Actions/Actions.css.ts +0 -113
  63. package/src/components/Actions/Actions.tsx +0 -132
  64. package/src/components/Button/Button.css.ts +0 -119
  65. package/src/components/Button/Button.tsx +0 -132
  66. package/src/components/Carousel/Carousel.css.ts +0 -179
  67. package/src/components/Columns/Columns.css.ts +0 -185
  68. package/src/components/Columns/Columns.tsx +0 -142
  69. package/src/components/Footer/Footer.css.ts +0 -108
  70. package/src/components/Footer/Footer.tsx +0 -130
  71. package/src/components/Header/Header.css.ts +0 -111
  72. package/src/components/Header/Header.tsx +0 -158
  73. package/src/components/Icon/Icon.css.ts +0 -101
  74. package/src/components/Icon/Icon.tsx +0 -159
  75. package/src/components/KeyNumber/KeyNumber.css.ts +0 -158
  76. package/src/components/KeyNumber/KeyNumber.tsx +0 -166
  77. package/src/components/LanguageSwitcher/LanguageSwitcher.tsx +0 -168
  78. package/src/components/Logo/Logo.css.ts +0 -98
  79. package/src/components/Logo/Logo.tsx +0 -137
  80. package/src/components/Main/Main.css.ts +0 -62
  81. package/src/components/Main/Main.tsx +0 -130
  82. package/src/components/Modal/Modal.css.ts +0 -203
  83. package/src/components/Modal/Modal.tsx +0 -194
  84. package/src/components/Nav/Nav.css.ts +0 -123
  85. package/src/components/Nav/Nav.tsx +0 -130
  86. package/src/components/NavLegal/NavLegal.css.ts +0 -121
  87. package/src/components/NavLegal/NavLegal.tsx +0 -133
  88. package/src/components/NavSocial/NavSocial.css.ts +0 -121
  89. package/src/components/NavSocial/NavSocial.tsx +0 -169
  90. package/src/components/Section/Section.css.ts +0 -101
  91. package/src/components/Section/Section.tsx +0 -130
  92. package/src/components/Video/Video.css.ts +0 -210
  93. package/src/components/Video/Video.tsx +0 -243
  94. package/src/components/VideoFullWidth/VideoFullWidth.css.ts +0 -50
  95. package/src/components/VideoFullWidth/VideoFullWidth.tsx +0 -152
  96. package/src/components/VideoFullWidth/export.tsx +0 -2
  97. package/src/themes/baseThemeValues.ts +0 -160
  98. package/src/themes/contract.css.ts +0 -83
  99. 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 { Section } from './Section';
4
- import { Button } from '../Button/Button';
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" backgroundColor="primary">
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 spacing="lg">
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" spacing="lg">
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
+ ]);