@latte-macchiat-io/latte-vanilla-components 0.0.177 → 0.0.179

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 (72) hide show
  1. package/package.json +3 -1
  2. package/src/assets/styles/mediaqueries.tsx +24 -0
  3. package/src/components/Actions/Actions.tsx +132 -0
  4. package/src/components/Actions/export.tsx +4 -0
  5. package/src/components/{Main/stories.ts → Actions/stories.tsx} +14 -13
  6. package/src/components/Button/Button.tsx +132 -0
  7. package/src/components/Button/export.tsx +5 -0
  8. package/src/components/Carousel/Carousel.tsx +328 -0
  9. package/src/components/Carousel/export.tsx +4 -0
  10. package/src/components/Columns/Columns.tsx +142 -0
  11. package/src/components/Columns/export.tsx +5 -0
  12. package/src/components/ConsentCookie/ConsentCookie.tsx +202 -0
  13. package/src/components/ConsentCookie/export.tsx +4 -0
  14. package/src/components/{Icon/stories.ts → ConsentCookie/stories.tsx} +7 -8
  15. package/src/components/Footer/Footer.tsx +130 -0
  16. package/src/components/Footer/export.tsx +4 -0
  17. package/src/components/Footer/stories.tsx +26 -0
  18. package/src/components/Form/Form.tsx +127 -0
  19. package/src/components/Form/Row/Row.tsx +137 -0
  20. package/src/components/Form/Row/index.tsx +0 -0
  21. package/src/components/Form/Row/stories.tsx +41 -0
  22. package/src/components/Form/TextField/Input/Input.tsx +139 -0
  23. package/src/components/Form/TextField/Input/export.tsx +6 -0
  24. package/src/components/Form/TextField/Label/Label.tsx +133 -0
  25. package/src/components/Form/TextField/Label/export.tsx +4 -0
  26. package/src/components/Form/TextField/TextField.tsx +200 -0
  27. package/src/components/Form/TextField/Textarea/Textarea.tsx +135 -0
  28. package/src/components/Form/TextField/Textarea/export.tsx +6 -0
  29. package/src/components/Form/TextField/Textarea/stories.tsx +44 -0
  30. package/src/components/Form/TextField/export.tsx +4 -0
  31. package/src/components/Form/export.tsx +4 -0
  32. package/src/components/Header/Header.tsx +158 -0
  33. package/src/components/Header/HeaderOverlay/index.tsx +32 -0
  34. package/src/components/Header/ToggleNav/index.tsx +32 -0
  35. package/src/components/Header/export.tsx +4 -0
  36. package/src/components/Header/stories.tsx +26 -0
  37. package/src/components/Icon/Icon.tsx +159 -0
  38. package/src/components/Icon/export.tsx +4 -0
  39. package/src/components/KeyNumber/KeyNumber.tsx +166 -0
  40. package/src/components/KeyNumber/export.tsx +4 -0
  41. package/src/components/LanguageSwitcher/LanguageSwitcher.tsx +168 -0
  42. package/src/components/LanguageSwitcher/export.tsx +4 -0
  43. package/src/components/Logo/Logo.tsx +137 -0
  44. package/src/components/Logo/export.tsx +4 -0
  45. package/src/components/Logo/stories.tsx +28 -0
  46. package/src/components/Main/Main.tsx +130 -0
  47. package/src/components/Main/export.tsx +4 -0
  48. package/src/components/Modal/Modal.tsx +194 -0
  49. package/src/components/Modal/export.tsx +4 -0
  50. package/src/components/Modal/types.tsx +5 -0
  51. package/src/components/Nav/Nav.tsx +129 -0
  52. package/src/components/Nav/export.tsx +4 -0
  53. package/src/components/Nav/stories.tsx +28 -0
  54. package/src/components/NavLegal/NavLegal.tsx +133 -0
  55. package/src/components/NavLegal/export.tsx +4 -0
  56. package/src/components/NavLegal/stories.tsx +28 -0
  57. package/src/components/NavLegal/types.tsx +1 -0
  58. package/src/components/NavSocial/NavSocial.tsx +169 -0
  59. package/src/components/NavSocial/export.tsx +5 -0
  60. package/src/components/{Columns/stories.ts → NavSocial/stories.tsx} +12 -14
  61. package/src/components/NavSocial/types.tsx +1 -0
  62. package/src/components/Section/Section.tsx +130 -0
  63. package/src/components/Section/export.tsx +6 -0
  64. package/src/components/ToRemove/ToRemove.tsx +3 -0
  65. package/src/components/Video/Video.tsx +243 -0
  66. package/src/components/Video/export.tsx +2 -0
  67. package/src/components/VideoFullWidth/VideoFullWidth.tsx +152 -0
  68. package/src/components/VideoFullWidth/export.tsx +2 -0
  69. package/src/index.ts +1 -1
  70. package/src/components/Button/stories.ts +0 -127
  71. package/src/components/Section/stories.ts +0 -64
  72. /package/src/utils/{theme.css.ts → theme.ts} +0 -0
@@ -0,0 +1,135 @@
1
+ import { clsx } from 'clsx';
2
+ import { forwardRef } from 'react';
3
+ import { textareaRecipe, type TextareaVariants } from './Textarea.css';
4
+ import { sprinkles, type Sprinkles } from '../../../../styles/sprinkles.css';
5
+
6
+ export interface TextareaProps
7
+ extends Omit<React.TextareaHTMLAttributes<HTMLTextAreaElement>, 'color' | 'size'>,
8
+ Sprinkles,
9
+ NonNullable<TextareaVariants> {
10
+ css?: string;
11
+ name: string;
12
+ hasError?: boolean;
13
+ }
14
+
15
+ export const Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>(
16
+ (
17
+ {
18
+ name,
19
+ hasError = false,
20
+ size,
21
+ variant,
22
+ resize,
23
+ css,
24
+ className,
25
+ // Extract sprinkles props
26
+ margin,
27
+ marginTop,
28
+ marginBottom,
29
+ marginLeft,
30
+ marginRight,
31
+ padding,
32
+ paddingTop,
33
+ paddingBottom,
34
+ paddingLeft,
35
+ paddingRight,
36
+ gap,
37
+ display,
38
+ flexDirection,
39
+ justifyContent,
40
+ flexWrap,
41
+ flex,
42
+ width,
43
+ height,
44
+ minWidth,
45
+ maxWidth,
46
+ minHeight,
47
+ position,
48
+ top,
49
+ bottom,
50
+ left,
51
+ right,
52
+ zIndex,
53
+ fontSize,
54
+ fontFamily,
55
+ lineHeight,
56
+ textAlign,
57
+ fontWeight,
58
+ color,
59
+ backgroundColor,
60
+ borderRadius,
61
+ borderWidth,
62
+ borderStyle,
63
+ borderColor,
64
+ boxShadow,
65
+ opacity,
66
+ overflow,
67
+ overflowX,
68
+ overflowY,
69
+ ...htmlProps
70
+ },
71
+ ref
72
+ ) => {
73
+ return (
74
+ <textarea
75
+ ref={ref}
76
+ id={name}
77
+ name={name}
78
+ className={clsx(
79
+ textareaRecipe({ size, variant, resize }),
80
+ sprinkles({
81
+ margin,
82
+ marginTop,
83
+ marginBottom,
84
+ marginLeft,
85
+ marginRight,
86
+ padding,
87
+ paddingTop,
88
+ paddingBottom,
89
+ paddingLeft,
90
+ paddingRight,
91
+ gap,
92
+ display,
93
+ flexDirection,
94
+ justifyContent,
95
+ flexWrap,
96
+ flex,
97
+ width,
98
+ height,
99
+ minWidth,
100
+ maxWidth,
101
+ minHeight,
102
+ position,
103
+ top,
104
+ bottom,
105
+ left,
106
+ right,
107
+ zIndex,
108
+ fontSize,
109
+ fontFamily,
110
+ lineHeight,
111
+ textAlign,
112
+ fontWeight,
113
+ color,
114
+ backgroundColor,
115
+ borderRadius,
116
+ borderWidth,
117
+ borderStyle,
118
+ borderColor,
119
+ boxShadow,
120
+ opacity,
121
+ overflow,
122
+ overflowX,
123
+ overflowY,
124
+ }),
125
+ css,
126
+ className
127
+ )}
128
+ data-error={hasError}
129
+ {...htmlProps}
130
+ />
131
+ );
132
+ }
133
+ );
134
+
135
+ Textarea.displayName = 'Textarea';
@@ -0,0 +1,6 @@
1
+ // export { TextFieldTextarea } from '.';
2
+ // export type { TextFieldTextareaProps } from '.';
3
+
4
+ // export { Type as TextareaType } from './types';
5
+
6
+ // export { styles as TextareaStyles } from './styles.css';
@@ -0,0 +1,44 @@
1
+ // import type { Meta, StoryObj } from '@storybook/react';
2
+ //
3
+ // import { TextFieldTextarea } from '../../../../index';
4
+ //
5
+ // // More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export
6
+ // const meta: Meta<typeof TextFieldTextarea> = {
7
+ // title: 'Latte Components / Form / Text Field / Textarea',
8
+ // component: TextFieldTextarea,
9
+ // parameters: {
10
+ // // Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/configure/story-layout
11
+ // layout: 'centered',
12
+ // },
13
+ // // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs
14
+ // tags: ['autodocs'],
15
+ // // More on argTypes: https://storybook.js.org/docs/api/argtypes
16
+ // argTypes: {},
17
+ // // Use `fn` to spy on the onClick arg, which will appear in the actions panel once invoked: https://storybook.js.org/docs/essentials/actions#action-args
18
+ // };
19
+ //
20
+ // export default meta;
21
+ // type Story = StoryObj<typeof meta>;
22
+ //
23
+ // // More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
24
+ // export const Default: Story = {
25
+ // args: {},
26
+ // };
27
+ //
28
+ // export const Placeholder: Story = {
29
+ // args: {
30
+ // placeholder: "It's a placeholder",
31
+ // },
32
+ // };
33
+ //
34
+ // export const Disabled: Story = {
35
+ // args: {
36
+ // disabled: true,
37
+ // },
38
+ // };
39
+ //
40
+ // export const Rows10: Story = {
41
+ // args: {
42
+ // rows: 10,
43
+ // },
44
+ // };
@@ -0,0 +1,4 @@
1
+ // export { TextField } from '.';
2
+ // export type { TextFieldProps } from '.';
3
+
4
+ // export { styles as TextFieldStyles } from './styles.css';
@@ -0,0 +1,4 @@
1
+ // export { Form } from '.';
2
+ // export type { FormProps } from '.';
3
+
4
+ // export { styles as FormStyles } from './styles.css';
@@ -0,0 +1,158 @@
1
+ import { clsx } from 'clsx';
2
+ import { forwardRef, useState } from 'react';
3
+ import { headerPlaceholder, headerRecipe, type HeaderVariants } from './Header.css';
4
+ import { sprinkles, type Sprinkles } from '../../styles/sprinkles.css';
5
+
6
+ export interface HeaderProps extends Omit<React.HTMLAttributes<HTMLElement>, 'color'>, Sprinkles, NonNullable<HeaderVariants> {
7
+ css?: string;
8
+ isFixed?: boolean; // Legacy prop for backwards compatibility
9
+ hideToggleNav?: boolean;
10
+ childrenOverlay?: React.ReactNode;
11
+ displayToggleNavOnDesktop?: boolean;
12
+ as?: 'header' | 'div';
13
+ }
14
+
15
+ export const Header = forwardRef<HTMLElement, HeaderProps>(
16
+ (
17
+ {
18
+ children,
19
+ position,
20
+ variant,
21
+ size,
22
+ isFixed, // Legacy prop
23
+ hideToggleNav,
24
+ childrenOverlay,
25
+ displayToggleNavOnDesktop,
26
+ as: Component = 'header',
27
+ css,
28
+ className,
29
+ // Extract sprinkles props
30
+ margin,
31
+ marginTop,
32
+ marginBottom,
33
+ marginLeft,
34
+ marginRight,
35
+ padding,
36
+ paddingTop,
37
+ paddingBottom,
38
+ paddingLeft,
39
+ paddingRight,
40
+ gap,
41
+ display,
42
+ flexDirection,
43
+ justifyContent,
44
+ flexWrap,
45
+ flex,
46
+ width,
47
+ height,
48
+ minWidth,
49
+ maxWidth,
50
+ minHeight,
51
+ zIndex,
52
+ fontSize,
53
+ fontFamily,
54
+ lineHeight,
55
+ textAlign,
56
+ fontWeight,
57
+ color,
58
+ backgroundColor,
59
+ borderRadius,
60
+ borderWidth,
61
+ borderStyle,
62
+ borderColor,
63
+ boxShadow,
64
+ opacity,
65
+ overflow,
66
+ overflowX,
67
+ overflowY,
68
+ ...htmlProps
69
+ },
70
+ ref
71
+ ) => {
72
+ const [isNavOpen, setNavOpen] = useState(false);
73
+
74
+ // Handle legacy isFixed prop
75
+ const headerPosition = position || (isFixed ? 'fixed' : 'relative');
76
+
77
+ return (
78
+ <>
79
+ <Component
80
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
81
+ ref={ref as any}
82
+ className={clsx(
83
+ headerRecipe({ variant, size }),
84
+ sprinkles({
85
+ margin,
86
+ marginTop,
87
+ marginBottom,
88
+ marginLeft,
89
+ marginRight,
90
+ padding,
91
+ paddingTop,
92
+ paddingBottom,
93
+ paddingLeft,
94
+ paddingRight,
95
+ gap,
96
+ display,
97
+ flexDirection,
98
+ justifyContent,
99
+ flexWrap,
100
+ flex,
101
+ width,
102
+ height,
103
+ minWidth,
104
+ maxWidth,
105
+ minHeight,
106
+ zIndex,
107
+ fontSize,
108
+ fontFamily,
109
+ lineHeight,
110
+ textAlign,
111
+ fontWeight,
112
+ color,
113
+ backgroundColor,
114
+ borderRadius,
115
+ borderWidth,
116
+ borderStyle,
117
+ borderColor,
118
+ boxShadow,
119
+ opacity,
120
+ overflow,
121
+ overflowX,
122
+ overflowY,
123
+ }),
124
+ css,
125
+ className
126
+ )}
127
+ {...htmlProps}>
128
+ {/* Overlay for mobile navigation */}
129
+ {childrenOverlay && <div className={clsx('header-overlay', isNavOpen && 'header-overlay--open')}>{childrenOverlay}</div>}
130
+
131
+ {children}
132
+
133
+ {/* Toggle navigation button */}
134
+ {!hideToggleNav && (
135
+ <button
136
+ type="button"
137
+ className="header-nav-toggle"
138
+ onClick={() => setNavOpen(!isNavOpen)}
139
+ aria-expanded={isNavOpen}
140
+ aria-label="Toggle navigation">
141
+ <span className="sr-only">Toggle navigation</span>
142
+ <div className={`hamburger ${isNavOpen ? 'hamburger--open' : ''}`}>
143
+ <span></span>
144
+ <span></span>
145
+ <span></span>
146
+ </div>
147
+ </button>
148
+ )}
149
+ </Component>
150
+
151
+ {/* Placeholder for fixed headers */}
152
+ {(headerPosition === 'fixed' || isFixed) && <div className={headerPlaceholder} />}
153
+ </>
154
+ );
155
+ }
156
+ );
157
+
158
+ Header.displayName = 'Header';
@@ -0,0 +1,32 @@
1
+ import { assignInlineVars } from '@vanilla-extract/dynamic';
2
+ import { useEffect } from 'react';
3
+ import { WithClassName } from '@/types/withClassName';
4
+
5
+ import { headerOverlayStyle, vars } from './styles.css';
6
+
7
+ export interface HeaderOverlayProps {
8
+ isOpen: boolean;
9
+ children: React.ReactNode;
10
+ }
11
+
12
+ const HeaderOverlay = ({ isOpen = false, children, className }: HeaderOverlayProps & WithClassName) => {
13
+ useEffect(() => {
14
+ const html = document.getElementsByTagName('html')[0];
15
+ html.style.overflow = '';
16
+
17
+ if (isOpen) html.style.overflow = 'hidden';
18
+ }, [isOpen]);
19
+
20
+ return (
21
+ <div
22
+ className={`${headerOverlayStyle} ${className}`}
23
+ style={assignInlineVars({
24
+ [vars.overlayBottom]: !isOpen ? '100%' : '-100vh',
25
+ [vars.overlayTransform]: isOpen ? 'translate(0, 0)' : 'translate(0, -100%)',
26
+ })}>
27
+ {children}
28
+ </div>
29
+ );
30
+ };
31
+
32
+ export default HeaderOverlay;
@@ -0,0 +1,32 @@
1
+ import { assignInlineVars } from '@vanilla-extract/dynamic';
2
+ import { Theme } from '@/types/theme';
3
+ import { WithClassName } from '@/types/withClassName';
4
+ import { toggleNavBarStyle, toggleNavStyle, vars } from './styles.css';
5
+ import { defaultTheme } from '../../../assets/styles/default-theme';
6
+
7
+ export type ToggleNavProps = {
8
+ theme?: Theme;
9
+ isNavOpen: boolean;
10
+ onToggleNav: () => void;
11
+ displayOnDesktop: boolean;
12
+ };
13
+
14
+ export const ToggleNav = ({ theme = defaultTheme, isNavOpen = false, onToggleNav, displayOnDesktop, className }: ToggleNavProps & WithClassName) => {
15
+ const handleClick = () => {
16
+ window.scrollTo({ top: 0, behavior: 'smooth' });
17
+ onToggleNav();
18
+ };
19
+
20
+ return (
21
+ <button
22
+ className={`${toggleNavStyle} ${className}`}
23
+ style={assignInlineVars({
24
+ [vars.displayOnDesktop]: displayOnDesktop ? 'block' : 'none',
25
+ })}
26
+ onClick={handleClick}
27
+ aria-label="Toggle nav">
28
+ <span className={toggleNavBarStyle} data-open={isNavOpen ? 'true' : 'false'} />
29
+ <span className={toggleNavBarStyle} data-open={isNavOpen ? 'true' : 'false'} />
30
+ </button>
31
+ );
32
+ };
@@ -0,0 +1,4 @@
1
+ // export { Header } from '.';
2
+ // export type { HeaderProps } from '.';
3
+
4
+ // export { styles as HeaderStyles } from './styles.css';
@@ -0,0 +1,26 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+
3
+ import { Header } from '../../index';
4
+
5
+ // More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export
6
+ const meta: Meta<typeof Header> = {
7
+ title: 'Latte Components / Layout / Header',
8
+ component: Header,
9
+ parameters: {
10
+ // Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/configure/story-layout
11
+ layout: 'centered',
12
+ },
13
+ // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs
14
+ tags: ['autodocs'],
15
+ // More on argTypes: https://storybook.js.org/docs/api/argtypes
16
+ argTypes: {},
17
+ // Use `fn` to spy on the onClick arg, which will appear in the actions panel once invoked: https://storybook.js.org/docs/essentials/actions#action-args
18
+ };
19
+
20
+ export default meta;
21
+ type Story = StoryObj<typeof meta>;
22
+
23
+ // More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
24
+ export const Default: Story = {
25
+ args: {},
26
+ };
@@ -0,0 +1,159 @@
1
+ import { clsx } from 'clsx';
2
+ import { forwardRef } from 'react';
3
+ import { iconRecipe, type IconVariants } from './Icon.css';
4
+ import iconPaths from './path';
5
+ import { sprinkles, type Sprinkles } from '../../styles/sprinkles.css';
6
+
7
+ export interface IconProps
8
+ extends Omit<
9
+ React.SVGProps<SVGSVGElement>,
10
+ 'color' | 'size' | 'display' | 'fontFamily' | 'fontSize' | 'fontWeight' | 'height' | 'opacity' | 'overflow' | 'width'
11
+ >,
12
+ Sprinkles,
13
+ NonNullable<IconVariants> {
14
+ css?: string;
15
+ icon?: keyof typeof iconPaths;
16
+ iconPath?: string;
17
+ customSize?: number;
18
+ customColor?: string;
19
+ viewBox?: string;
20
+ }
21
+
22
+ export const Icon = forwardRef<SVGSVGElement, IconProps>(
23
+ (
24
+ {
25
+ icon,
26
+ iconPath,
27
+ size,
28
+ color,
29
+ customSize,
30
+ customColor,
31
+ interactive,
32
+ viewBox = '0 0 24 24',
33
+ css,
34
+ className,
35
+ // Extract sprinkles props
36
+ margin,
37
+ marginTop,
38
+ marginBottom,
39
+ marginLeft,
40
+ marginRight,
41
+ padding,
42
+ paddingTop,
43
+ paddingBottom,
44
+ paddingLeft,
45
+ paddingRight,
46
+ gap,
47
+ display,
48
+ flexDirection,
49
+ justifyContent,
50
+ flexWrap,
51
+ flex,
52
+ width,
53
+ height,
54
+ minWidth,
55
+ maxWidth,
56
+ minHeight,
57
+ position,
58
+ top,
59
+ bottom,
60
+ left,
61
+ right,
62
+ zIndex,
63
+ fontSize,
64
+ fontFamily,
65
+ lineHeight,
66
+ textAlign,
67
+ fontWeight,
68
+ backgroundColor,
69
+ borderRadius,
70
+ borderWidth,
71
+ borderStyle,
72
+ borderColor,
73
+ boxShadow,
74
+ opacity,
75
+ overflow,
76
+ overflowX,
77
+ overflowY,
78
+ ...svgProps
79
+ },
80
+ ref
81
+ ) => {
82
+ const pathData = iconPath || (icon ? iconPaths[icon] : '');
83
+
84
+ const iconStyle = customSize
85
+ ? {
86
+ width: `${customSize}px`,
87
+ height: `${customSize}px`,
88
+ }
89
+ : {};
90
+
91
+ const pathStyle = customColor
92
+ ? {
93
+ fill: customColor,
94
+ }
95
+ : {};
96
+
97
+ return (
98
+ <svg
99
+ ref={ref}
100
+ viewBox={viewBox}
101
+ className={clsx(
102
+ iconRecipe({ size: customSize ? undefined : size, interactive }),
103
+ sprinkles({
104
+ margin,
105
+ marginTop,
106
+ marginBottom,
107
+ marginLeft,
108
+ marginRight,
109
+ padding,
110
+ paddingTop,
111
+ paddingBottom,
112
+ paddingLeft,
113
+ paddingRight,
114
+ gap,
115
+ display,
116
+ flexDirection,
117
+ justifyContent,
118
+ flexWrap,
119
+ flex,
120
+ width,
121
+ height,
122
+ minWidth,
123
+ maxWidth,
124
+ minHeight,
125
+ position,
126
+ top,
127
+ bottom,
128
+ left,
129
+ right,
130
+ zIndex,
131
+ fontSize,
132
+ fontFamily,
133
+ lineHeight,
134
+ textAlign,
135
+ fontWeight,
136
+ backgroundColor,
137
+ borderRadius,
138
+ borderWidth,
139
+ borderStyle,
140
+ borderColor,
141
+ boxShadow,
142
+ opacity,
143
+ overflow,
144
+ overflowX,
145
+ overflowY,
146
+ }),
147
+ css,
148
+ className
149
+ )}
150
+ style={iconStyle}
151
+ aria-hidden={!svgProps['aria-label'] && !svgProps['aria-labelledby']}
152
+ {...svgProps}>
153
+ <path className={iconPath} d={pathData} style={pathStyle} />
154
+ </svg>
155
+ );
156
+ }
157
+ );
158
+
159
+ Icon.displayName = 'Icon';
@@ -0,0 +1,4 @@
1
+ // export { Icon } from '.';
2
+ // export type { IconProps } from '.';
3
+
4
+ // export { styles as IconStyles } from './styles.css';