@latte-macchiat-io/latte-vanilla-components 0.0.553 → 0.0.554

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@latte-macchiat-io/latte-vanilla-components",
3
- "version": "0.0.553",
3
+ "version": "0.0.554",
4
4
  "description": "Beautiful components for amazing projects, with a touch of Vanilla 🥤",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
@@ -0,0 +1,2 @@
1
+ export { Checkbox, type CheckboxProps } from './';
2
+ export { type CheckboxVariants } from './styles.css';
@@ -0,0 +1,56 @@
1
+ import { useMemo } from 'react';
2
+
3
+ import { checkboxInput, checkboxLabel, checkboxRecipe, CheckboxVariants, errorMessage, messageContainer } from './styles.css';
4
+
5
+ import { cn } from '../../../utils/styleOverride';
6
+
7
+ export type CheckboxProps = React.InputHTMLAttributes<HTMLInputElement> &
8
+ CheckboxVariants & {
9
+ name: string;
10
+ label?: string;
11
+ errors?: string | string[];
12
+ onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
13
+ };
14
+
15
+ export const Checkbox = ({ name, label, errors, labelPosition, required, checked, disabled, onChange, className }: CheckboxProps) => {
16
+ const hasErrors = useMemo(() => {
17
+ if (!errors) return false;
18
+ if (Array.isArray(errors)) return errors.length > 0;
19
+ return Boolean(errors);
20
+ }, [errors]);
21
+
22
+ return (
23
+ <div className={cn(checkboxRecipe({ labelPosition }), className)}>
24
+ <input
25
+ id={name}
26
+ name={name}
27
+ type="checkbox"
28
+ required={required}
29
+ checked={checked}
30
+ disabled={disabled}
31
+ onChange={onChange}
32
+ className={checkboxInput}
33
+ />
34
+
35
+ {label && (
36
+ <label htmlFor={name} className={checkboxLabel}>
37
+ {label} {required && '*'}
38
+ </label>
39
+ )}
40
+
41
+ {hasErrors && (
42
+ <div className={messageContainer}>
43
+ {Array.isArray(errors) ? (
44
+ errors.map((error, index) => (
45
+ <span key={index} className={errorMessage}>
46
+ {error}
47
+ </span>
48
+ ))
49
+ ) : (
50
+ <span className={errorMessage}>{errors}</span>
51
+ )}
52
+ </div>
53
+ )}
54
+ </div>
55
+ );
56
+ };
@@ -0,0 +1,80 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+
3
+ import { Checkbox } from '.';
4
+
5
+ // More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export
6
+ const meta: Meta<typeof Checkbox> = {
7
+ title: '5. Forms / Checkbox',
8
+ component: Checkbox,
9
+ parameters: {
10
+ layout: 'centered',
11
+ },
12
+ tags: ['autodocs'],
13
+ argTypes: {},
14
+ decorators: [
15
+ (Story) => (
16
+ <div style={{ minWidth: '320px', maxWidth: '500px', width: '100%' }}>
17
+ <Story />
18
+ </div>
19
+ ),
20
+ ],
21
+ };
22
+
23
+ export default meta;
24
+ type Story = StoryObj<typeof meta>;
25
+
26
+ // More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
27
+ export const Default: Story = {
28
+ args: {
29
+ name: 'agree',
30
+ label: 'I agree to the terms and conditions',
31
+ },
32
+ };
33
+
34
+ export const Checked: Story = {
35
+ args: {
36
+ name: 'newsletter',
37
+ label: 'Subscribe to newsletter',
38
+ checked: true,
39
+ },
40
+ };
41
+
42
+ export const Required: Story = {
43
+ args: {
44
+ name: 'required-checkbox',
45
+ label: 'Accept terms',
46
+ required: true,
47
+ },
48
+ };
49
+
50
+ export const LabelLeft: Story = {
51
+ args: {
52
+ name: 'label-left',
53
+ label: 'Label on the left',
54
+ labelPosition: 'left',
55
+ },
56
+ };
57
+
58
+ export const Disabled: Story = {
59
+ args: {
60
+ name: 'disabled-checkbox',
61
+ label: 'This option is disabled',
62
+ disabled: true,
63
+ },
64
+ };
65
+
66
+ export const WithError: Story = {
67
+ args: {
68
+ name: 'terms',
69
+ label: 'I accept the terms',
70
+ errors: 'You must accept the terms to continue',
71
+ },
72
+ };
73
+
74
+ export const WithMultipleErrors: Story = {
75
+ args: {
76
+ name: 'gdpr',
77
+ label: 'I accept the GDPR policy',
78
+ errors: ['This field is required', 'You must be 18 or older to accept'],
79
+ },
80
+ };
@@ -0,0 +1,62 @@
1
+ import { style } from '@vanilla-extract/css';
2
+ import { recipe, RecipeVariants } from '@vanilla-extract/recipes';
3
+
4
+ import { themeContract } from '../../../theme/contract.css';
5
+
6
+ export const checkboxRecipe = recipe(
7
+ {
8
+ base: {
9
+ display: 'flex',
10
+ alignItems: 'center',
11
+ gap: themeContract.space.sm,
12
+ transition: 'all 0.2s ease-in-out',
13
+ },
14
+
15
+ variants: {
16
+ labelPosition: {
17
+ left: {
18
+ flexDirection: 'row-reverse',
19
+ justifyContent: 'flex-end',
20
+ },
21
+ right: {
22
+ flexDirection: 'row',
23
+ },
24
+ },
25
+ },
26
+
27
+ defaultVariants: {
28
+ labelPosition: 'right',
29
+ },
30
+ },
31
+ 'checkbox'
32
+ );
33
+
34
+ export const checkboxInput = style({
35
+ appearance: 'none',
36
+ cursor: 'pointer',
37
+ flexShrink: 0,
38
+ width: '1.25rem',
39
+ height: '1.25rem',
40
+ border: themeContract.form.textField.border,
41
+ borderRadius: themeContract.form.textField.borderRadius,
42
+ backgroundColor: themeContract.form.textField.backgroundColor,
43
+ transition: 'all 0.2s ease-in-out',
44
+
45
+ selectors: {
46
+ '&:checked': {
47
+ backgroundColor: themeContract.colors.primary,
48
+ },
49
+ },
50
+ });
51
+
52
+ export const checkboxLabel = style({
53
+ cursor: 'pointer',
54
+ fontFamily: themeContract.fonts.body,
55
+ color: themeContract.form.textField.color,
56
+ });
57
+
58
+ export const messageContainer = style({});
59
+
60
+ export const errorMessage = style({});
61
+
62
+ export type CheckboxVariants = RecipeVariants<typeof checkboxRecipe>;
@@ -4,3 +4,4 @@ export * from './Row/export';
4
4
 
5
5
  export * from './TextField/export';
6
6
  export * from './Select/export';
7
+ export * from './Checkbox/export';
@@ -1287,6 +1287,7 @@ export const themeContract = createGlobalThemeContract({
1287
1287
  '2xl': 'latte-textField-input-paddingLeft-2xl',
1288
1288
  },
1289
1289
  },
1290
+
1290
1291
  },
1291
1292
 
1292
1293
  consentCookie: {
@@ -1,40 +0,0 @@
1
- const themeActionsBase = {
2
- actions: {
3
- gap: {
4
- mobile: '15px',
5
- sm: '15px',
6
- md: '30px',
7
- lg: '30px',
8
- xl: '50px',
9
- '2xl': '50px',
10
- },
11
- paddingTop: {
12
- mobile: '15px',
13
- sm: '15px',
14
- md: '30px',
15
- lg: '30px',
16
- xl: '50px',
17
- '2xl': '50px',
18
- },
19
- paddingBottom: {
20
- mobile: '15px',
21
- sm: '15px',
22
- md: '30px',
23
- lg: '30px',
24
- xl: '50px',
25
- '2xl': '50px',
26
- },
27
- },
28
- };
29
-
30
- export const themeActionsLight = {
31
- actions: {
32
- ...themeActionsBase.actions,
33
- },
34
- };
35
-
36
- export const themeActionsDark = {
37
- actions: {
38
- ...themeActionsBase.actions,
39
- },
40
- };