property-practice-ui 0.0.1
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/.prettierignore +3 -0
- package/.prettierrc +4 -0
- package/.storybook/main.ts +30 -0
- package/.storybook/preview.ts +32 -0
- package/.storybook/vitest.setup.ts +6 -0
- package/CHANGELOG.md +7 -0
- package/dist/index.js +10148 -0
- package/dist/index.mjs +10148 -0
- package/eslint.config.mjs +4 -0
- package/package.json +63 -0
- package/postcss.config.js +6 -0
- package/src/atoms/ArrowButton/ArrowButton.stories.tsx +52 -0
- package/src/atoms/ArrowButton/ArrowButton.tsx +71 -0
- package/src/atoms/Button/Button.stories.tsx +45 -0
- package/src/atoms/Button/Button.tsx +91 -0
- package/src/atoms/CheckboxItem/CheckboxItem.tsx +49 -0
- package/src/atoms/Description/Description.tsx +43 -0
- package/src/atoms/ExtendedButton/ExtendedButton.stories.tsx +61 -0
- package/src/atoms/ExtendedButton/ExtendedButton.tsx +40 -0
- package/src/atoms/FeatureItem/FeatureItem.stories.tsx +25 -0
- package/src/atoms/FeatureItem/FeatureItem.tsx +90 -0
- package/src/atoms/FormContainer/FormContainer.tsx +34 -0
- package/src/atoms/Header/Header.stories.tsx +22 -0
- package/src/atoms/Header/Header.tsx +53 -0
- package/src/atoms/Input/Input.stories.tsx +23 -0
- package/src/atoms/Input/Input.tsx +28 -0
- package/src/atoms/Label/Label.stories.tsx +28 -0
- package/src/atoms/Label/Label.tsx +53 -0
- package/src/atoms/Loader/Loader.tsx +49 -0
- package/src/atoms/Pill/Pill.stories.tsx +30 -0
- package/src/atoms/Pill/Pill.tsx +82 -0
- package/src/atoms/RadioItem/RadioItem.stories.tsx +25 -0
- package/src/atoms/RadioItem/RadioItem.tsx +54 -0
- package/src/atoms/SecondaryInput/SecondaryInput.stories.tsx +30 -0
- package/src/atoms/SecondaryInput/SecondaryInput.tsx +125 -0
- package/src/atoms/SocialButton/SocialButton.stories.tsx +79 -0
- package/src/atoms/SocialButton/SocialButton.tsx +90 -0
- package/src/atoms/TermsCheckbox/TermsCheckbox.stories.tsx +62 -0
- package/src/atoms/TermsCheckbox/TermsCheckbox.tsx +150 -0
- package/src/atoms/Text/Text.stories.tsx +32 -0
- package/src/atoms/Text/Text.tsx +49 -0
- package/src/atoms/TextButton/TextButton.stories.tsx +77 -0
- package/src/atoms/TextButton/TextButton.tsx +78 -0
- package/src/atoms/Textarea/Textarea.tsx +36 -0
- package/src/atoms/ToggleButton/ToggleButton.stories.tsx +32 -0
- package/src/atoms/ToggleButton/ToggleButton.tsx +106 -0
- package/src/atoms/index.ts +20 -0
- package/src/components/DynamicInput.tsx +54 -0
- package/src/components/FileUpload.tsx +123 -0
- package/src/components/Filter/Filter.tsx +33 -0
- package/src/components/ModeSwitch.tsx +66 -0
- package/src/components/NavMenu.tsx +83 -0
- package/src/components/SearchBar/Search.stories.tsx +25 -0
- package/src/components/SearchBar/Search.tsx +40 -0
- package/src/components/SortBy/SortBy.stories.tsx +27 -0
- package/src/components/SortBy/SortBy.tsx +45 -0
- package/src/components/Spinner.tsx +30 -0
- package/src/components/Table/Table.stories.tsx +56 -0
- package/src/components/Table/Table.tsx +25 -0
- package/src/components/TableInner/TableInner.tsx +27 -0
- package/src/components/TableInner/tableInner.stories.tsx +21 -0
- package/src/components/TableList.tsx +195 -0
- package/src/components/TableRow/TableRow.stories.tsx +55 -0
- package/src/components/TableRow/TableRow.tsx +343 -0
- package/src/components/Tabs/Tabs.stories.tsx +42 -0
- package/src/components/Tabs/Tabs.tsx +56 -0
- package/src/components/Toast.tsx +192 -0
- package/src/components/TopMenu.tsx +62 -0
- package/src/index.ts +20 -0
- package/src/molecules/Accordion/Accordion.stories.tsx +54 -0
- package/src/molecules/Accordion/Accordion.tsx +45 -0
- package/src/molecules/AccordionContent/AccordionContent.tsx +16 -0
- package/src/molecules/AccordionHeader/AccordionHeader.stories.tsx +31 -0
- package/src/molecules/AccordionHeader/AccordionHeader.tsx +67 -0
- package/src/molecules/Address/Address.stories.tsx +116 -0
- package/src/molecules/Address/Address.tsx +136 -0
- package/src/molecules/CTAContainer/CTAContainer.stories.tsx +67 -0
- package/src/molecules/CTAContainer/CTAContainer.tsx +98 -0
- package/src/molecules/Checkbox/Checkbox.tsx +60 -0
- package/src/molecules/ContentCard/ContentCard.stories.tsx +31 -0
- package/src/molecules/ContentCard/ContentCard.tsx +80 -0
- package/src/molecules/DocumentAccordionHeader/DocumentAccordionHeader.tsx +50 -0
- package/src/molecules/DocumentAccordionRow/DocumentAccordionRow.tsx +66 -0
- package/src/molecules/Dropdown/Dropdown.stories.tsx +39 -0
- package/src/molecules/Dropdown/Dropdown.tsx +89 -0
- package/src/molecules/EmptyState/EmptyState.stories.tsx +26 -0
- package/src/molecules/EmptyState/EmptyState.tsx +49 -0
- package/src/molecules/FAQAccordion/FAQAccordion.stories.tsx +63 -0
- package/src/molecules/FAQAccordion/FAQAccordion.tsx +98 -0
- package/src/molecules/FeatureContainer/FeatureContainer.stories.tsx +40 -0
- package/src/molecules/FeatureContainer/FeatureContainer.tsx +59 -0
- package/src/molecules/FileButton/FileButton.tsx +54 -0
- package/src/molecules/Input/Input.stories.tsx +30 -0
- package/src/molecules/Input/Input.tsx +31 -0
- package/src/molecules/InputContainer/InputContainer.tsx +60 -0
- package/src/molecules/JutaBrand/JutaBrand.stories.tsx +43 -0
- package/src/molecules/JutaBrand/JutaBrand.tsx +74 -0
- package/src/molecules/Modal/Modal.tsx +71 -0
- package/src/molecules/OverviewRowItem/OverviewRowItem.stories.tsx +23 -0
- package/src/molecules/OverviewRowItem/OverviewRowItem.tsx +39 -0
- package/src/molecules/PDFPreviewer/PDFPreviewer.tsx +42 -0
- package/src/molecules/PageLayout/PageLayout.tsx +60 -0
- package/src/molecules/ProductInfo/ProductInfo.stories.tsx +50 -0
- package/src/molecules/ProductInfo/ProductInfo.tsx +90 -0
- package/src/molecules/RadioGroup/RadioGroup.stories.tsx +47 -0
- package/src/molecules/RadioGroup/RadioGroup.tsx +55 -0
- package/src/molecules/RatesChart/RatesChart.stories.tsx +61 -0
- package/src/molecules/RatesChart/RatesChart.tsx +185 -0
- package/src/molecules/SideNav/SideNav.stories.tsx +64 -0
- package/src/molecules/SideNav/SideNav.tsx +140 -0
- package/src/molecules/SidePanel/SidePanel.stories.tsx +87 -0
- package/src/molecules/SidePanel/SidePanel.tsx +138 -0
- package/src/molecules/StepperHeaderTab/StepperHeaderTab.stories.tsx +23 -0
- package/src/molecules/StepperHeaderTab/StepperHeaderTab.tsx +43 -0
- package/src/molecules/Textarea/Textarea.tsx +29 -0
- package/src/molecules/index.ts +23 -0
- package/src/organism/ContactForm/ContactForm.stories.tsx +15 -0
- package/src/organism/ContactForm/ContactForm.tsx +54 -0
- package/src/organism/DocumentListAccordion/DocumentListAccordion.tsx +96 -0
- package/src/organism/FeatureCarousel/FeatureCarousel.stories.tsx +81 -0
- package/src/organism/FeatureCarousel/FeatureCarousel.tsx +162 -0
- package/src/organism/Footer/Footer.stories.tsx +77 -0
- package/src/organism/Footer/Footer.tsx +231 -0
- package/src/organism/Header/Header.stories.tsx +51 -0
- package/src/organism/Header/Header.tsx +76 -0
- package/src/organism/OverviewList/OverviewList.stories.tsx +43 -0
- package/src/organism/OverviewList/OverviewList.tsx +56 -0
- package/src/organism/ToastProvider/ToastProvider.tsx +40 -0
- package/src/organism/VersionLabel/VersionLabel.tsx +9 -0
- package/src/organism/index.ts +9 -0
- package/src/styles/tailwind.css +8 -0
- package/src/templates/AboutUs/AboutUs.stories.tsx +60 -0
- package/src/templates/AboutUs/AboutUs.tsx +97 -0
- package/src/templates/Contact/Contact.stories.tsx +62 -0
- package/src/templates/Contact/Contact.tsx +125 -0
- package/src/templates/FAQ/FAQ.stories.tsx +82 -0
- package/src/templates/FAQ/FAQ.tsx +91 -0
- package/src/templates/Features/Features.stories.tsx +94 -0
- package/src/templates/Features/Features.tsx +79 -0
- package/src/templates/Hero/Hero.stories.tsx +105 -0
- package/src/templates/Hero/Hero.tsx +139 -0
- package/src/templates/OtherProducts/OtherProducts.stories.tsx +77 -0
- package/src/templates/OtherProducts/OtherProducts.tsx +86 -0
- package/src/templates/index.ts +7 -0
- package/src/tokens/animations.ts +11 -0
- package/src/tokens/breakpoints.ts +7 -0
- package/src/tokens/colors.stories.tsx +77 -0
- package/src/tokens/colors.ts +59 -0
- package/src/tokens/radii.ts +6 -0
- package/src/tokens/sizes.ts +8 -0
- package/src/tokens/spaces.ts +21 -0
- package/src/types.ts +20 -0
- package/stories/Button.stories.ts +54 -0
- package/stories/Button.tsx +41 -0
- package/stories/Configure.mdx +364 -0
- package/stories/Header.stories.ts +34 -0
- package/stories/Header.tsx +71 -0
- package/stories/Page.stories.ts +33 -0
- package/stories/Page.tsx +91 -0
- package/stories/TopMenu.stories.tsx +51 -0
- package/stories/assets/accessibility.png +0 -0
- package/stories/assets/accessibility.svg +1 -0
- package/stories/assets/addon-library.png +0 -0
- package/stories/assets/assets.png +0 -0
- package/stories/assets/avif-test-image.avif +0 -0
- package/stories/assets/context.png +0 -0
- package/stories/assets/discord.svg +1 -0
- package/stories/assets/docs.png +0 -0
- package/stories/assets/figma-plugin.png +0 -0
- package/stories/assets/github.svg +1 -0
- package/stories/assets/share.png +0 -0
- package/stories/assets/styling.png +0 -0
- package/stories/assets/testing.png +0 -0
- package/stories/assets/theming.png +0 -0
- package/stories/assets/tutorials.svg +1 -0
- package/stories/assets/youtube.svg +1 -0
- package/stories/button.css +30 -0
- package/stories/header.css +32 -0
- package/stories/page.css +68 -0
- package/tailwind.config.js +34 -0
- package/tsconfig.json +8 -0
- package/types/index.ts +5 -0
- package/types/inputAttributes.ts +16 -0
- package/types/menuItem.ts +17 -0
- package/types/orderType.ts +2 -0
- package/types/tableListItem.ts +7 -0
- package/types/toast.ts +1 -0
- package/vitest.config.ts +37 -0
- package/vitest.shims.d.ts +1 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import styled from 'styled-components';
|
|
2
|
+
import { colors } from '../../tokens/colors';
|
|
3
|
+
|
|
4
|
+
const variants = ['primary', 'secondary', 'inverse', 'filled'] as const;
|
|
5
|
+
type Variant = (typeof variants)[number];
|
|
6
|
+
|
|
7
|
+
const StyledButton = styled.button<{ variant: Variant }>`
|
|
8
|
+
width: 2.5rem;
|
|
9
|
+
height: 2.5rem;
|
|
10
|
+
display: flex;
|
|
11
|
+
align-items: center;
|
|
12
|
+
justify-content: center;
|
|
13
|
+
border-radius: 4px;
|
|
14
|
+
background-color: ${(props) => {
|
|
15
|
+
switch (props.variant) {
|
|
16
|
+
case 'filled':
|
|
17
|
+
return colors.background.brand;
|
|
18
|
+
case 'primary':
|
|
19
|
+
case 'secondary':
|
|
20
|
+
case 'inverse':
|
|
21
|
+
default:
|
|
22
|
+
return 'transparent';
|
|
23
|
+
}
|
|
24
|
+
}};
|
|
25
|
+
border: 2px solid ${(props) => {
|
|
26
|
+
switch (props.variant) {
|
|
27
|
+
case 'primary':
|
|
28
|
+
return colors.text.brand;
|
|
29
|
+
case 'secondary':
|
|
30
|
+
return colors.text.blue;
|
|
31
|
+
case 'inverse':
|
|
32
|
+
return colors.text.secondary;
|
|
33
|
+
case 'filled':
|
|
34
|
+
return colors.background.brand;
|
|
35
|
+
default:
|
|
36
|
+
return colors.text.brand;
|
|
37
|
+
}
|
|
38
|
+
}};
|
|
39
|
+
color: ${(props) => {
|
|
40
|
+
switch (props.variant) {
|
|
41
|
+
case 'primary':
|
|
42
|
+
return colors.text.brand;
|
|
43
|
+
case 'secondary':
|
|
44
|
+
return colors.text.blue;
|
|
45
|
+
case 'inverse':
|
|
46
|
+
return colors.text.secondary;
|
|
47
|
+
case 'filled':
|
|
48
|
+
return colors.text.secondary;
|
|
49
|
+
default:
|
|
50
|
+
return colors.text.brand;
|
|
51
|
+
}
|
|
52
|
+
}};
|
|
53
|
+
cursor: pointer;
|
|
54
|
+
transition: all 0.2s;
|
|
55
|
+
|
|
56
|
+
&:hover {
|
|
57
|
+
opacity: 0.8;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
svg {
|
|
61
|
+
width: 1.25rem;
|
|
62
|
+
height: 1.25rem;
|
|
63
|
+
}
|
|
64
|
+
`;
|
|
65
|
+
|
|
66
|
+
interface SocialButtonProps {
|
|
67
|
+
icon: React.ReactNode;
|
|
68
|
+
onClick?: () => void;
|
|
69
|
+
variant?: Variant;
|
|
70
|
+
ariaLabel?: string;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export const SocialButton = ({
|
|
74
|
+
icon,
|
|
75
|
+
onClick,
|
|
76
|
+
variant = 'primary',
|
|
77
|
+
ariaLabel,
|
|
78
|
+
}: SocialButtonProps) => {
|
|
79
|
+
return (
|
|
80
|
+
<StyledButton
|
|
81
|
+
onClick={onClick}
|
|
82
|
+
variant={variant}
|
|
83
|
+
aria-label={ariaLabel}
|
|
84
|
+
>
|
|
85
|
+
{icon}
|
|
86
|
+
</StyledButton>
|
|
87
|
+
);
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
SocialButton.variants = variants;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { ComponentProps, useState } from 'react';
|
|
3
|
+
import { TermsCheckbox as Component } from './TermsCheckbox';
|
|
4
|
+
|
|
5
|
+
const meta: Meta = {
|
|
6
|
+
title: 'Atoms/TermsCheckbox',
|
|
7
|
+
component: Component,
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export default meta;
|
|
11
|
+
|
|
12
|
+
export const TermsCheckbox: StoryObj<Omit<ComponentProps<typeof Component>, 'onClick'>> = {
|
|
13
|
+
render: (args) => {
|
|
14
|
+
const [checked, setChecked] = useState(false);
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<Component
|
|
18
|
+
{...args}
|
|
19
|
+
checked={checked}
|
|
20
|
+
onChange={setChecked}
|
|
21
|
+
/>
|
|
22
|
+
);
|
|
23
|
+
},
|
|
24
|
+
args: {
|
|
25
|
+
text: "By submitting, I agree to Juta's",
|
|
26
|
+
termsText: 'Terms and Conditions',
|
|
27
|
+
termsUrl: '/terms',
|
|
28
|
+
cookieText: 'Cookie Policy',
|
|
29
|
+
cookieUrl: '/cookie-policy',
|
|
30
|
+
|
|
31
|
+
},
|
|
32
|
+
argTypes: {
|
|
33
|
+
text: { control: 'text' },
|
|
34
|
+
termsText: { control: 'text' },
|
|
35
|
+
termsUrl: { control: 'text' },
|
|
36
|
+
cookieText: { control: 'text' },
|
|
37
|
+
cookieUrl: { control: 'text' },
|
|
38
|
+
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export const Checked: StoryObj<ComponentProps<typeof Component>> = {
|
|
43
|
+
render: (args) => {
|
|
44
|
+
const [checked, setChecked] = useState(true);
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<Component
|
|
48
|
+
{...args}
|
|
49
|
+
checked={checked}
|
|
50
|
+
onChange={setChecked}
|
|
51
|
+
/>
|
|
52
|
+
);
|
|
53
|
+
},
|
|
54
|
+
args: {
|
|
55
|
+
text: "By submitting, I agree to Juta's",
|
|
56
|
+
termsText: 'Terms and Conditions',
|
|
57
|
+
termsUrl: '/terms',
|
|
58
|
+
cookieText: 'Cookie Policy',
|
|
59
|
+
cookieUrl: '/cookie-policy',
|
|
60
|
+
|
|
61
|
+
},
|
|
62
|
+
};
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import styled from 'styled-components';
|
|
2
|
+
import { colors } from '../../tokens/colors';
|
|
3
|
+
|
|
4
|
+
const variants = ['primary', 'secondary', 'subtle'] as const;
|
|
5
|
+
type Variant = (typeof variants)[number];
|
|
6
|
+
|
|
7
|
+
const CheckboxContainer = styled.label`
|
|
8
|
+
display: flex;
|
|
9
|
+
align-items: flex-start;
|
|
10
|
+
gap: 0.75rem;
|
|
11
|
+
cursor: pointer;
|
|
12
|
+
font-size: 0.875rem;
|
|
13
|
+
line-height: 1.5;
|
|
14
|
+
`;
|
|
15
|
+
|
|
16
|
+
const HiddenCheckbox = styled.input.attrs({ type: 'checkbox' })`
|
|
17
|
+
position: absolute;
|
|
18
|
+
opacity: 0;
|
|
19
|
+
cursor: pointer;
|
|
20
|
+
`;
|
|
21
|
+
|
|
22
|
+
const StyledCheckbox = styled.div<{ $checked: boolean; variant: Variant }>`
|
|
23
|
+
width: 1.25rem;
|
|
24
|
+
height: 1.25rem;
|
|
25
|
+
border: 2px solid ${props => {
|
|
26
|
+
if (props.$checked) {
|
|
27
|
+
switch (props.variant) {
|
|
28
|
+
case 'primary':
|
|
29
|
+
return colors.text.brand;
|
|
30
|
+
case 'secondary':
|
|
31
|
+
return colors.text.blue;
|
|
32
|
+
case 'subtle':
|
|
33
|
+
return colors.text.subtle;
|
|
34
|
+
default:
|
|
35
|
+
return colors.text.brand;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return colors.text.subtle;
|
|
39
|
+
}};
|
|
40
|
+
border-radius: 4px;
|
|
41
|
+
background-color: ${props => {
|
|
42
|
+
if (props.$checked) {
|
|
43
|
+
switch (props.variant) {
|
|
44
|
+
case 'primary':
|
|
45
|
+
return colors.text.brand;
|
|
46
|
+
case 'secondary':
|
|
47
|
+
return colors.text.blue;
|
|
48
|
+
case 'subtle':
|
|
49
|
+
return colors.text.subtle;
|
|
50
|
+
default:
|
|
51
|
+
return colors.text.brand;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return 'transparent';
|
|
55
|
+
}};
|
|
56
|
+
display: flex;
|
|
57
|
+
align-items: center;
|
|
58
|
+
justify-content: center;
|
|
59
|
+
flex-shrink: 0;
|
|
60
|
+
transition: all 0.2s;
|
|
61
|
+
|
|
62
|
+
&::after {
|
|
63
|
+
content: '✓';
|
|
64
|
+
color: ${colors.text.secondary}; // white checkmark
|
|
65
|
+
font-size: 0.875rem;
|
|
66
|
+
font-weight: bold;
|
|
67
|
+
display: ${props => props.$checked ? 'block' : 'none'};
|
|
68
|
+
}
|
|
69
|
+
`;
|
|
70
|
+
|
|
71
|
+
const Text = styled.span<{ variant: Variant }>`
|
|
72
|
+
color: ${(props) => {
|
|
73
|
+
switch (props.variant) {
|
|
74
|
+
case 'primary':
|
|
75
|
+
return colors.text.primary;
|
|
76
|
+
case 'secondary':
|
|
77
|
+
return colors.text.blue;
|
|
78
|
+
case 'subtle':
|
|
79
|
+
return colors.text.subtle;
|
|
80
|
+
default:
|
|
81
|
+
return colors.text.primary;
|
|
82
|
+
}
|
|
83
|
+
}};
|
|
84
|
+
`;
|
|
85
|
+
|
|
86
|
+
const Link = styled.a<{ variant: Variant }>`
|
|
87
|
+
color: ${(props) => {
|
|
88
|
+
switch (props.variant) {
|
|
89
|
+
case 'primary':
|
|
90
|
+
return colors.text.brand;
|
|
91
|
+
case 'secondary':
|
|
92
|
+
return colors.text.blue;
|
|
93
|
+
case 'subtle':
|
|
94
|
+
return colors.text.subtle;
|
|
95
|
+
default:
|
|
96
|
+
return colors.text.brand;
|
|
97
|
+
}
|
|
98
|
+
}};
|
|
99
|
+
font-weight: 700;
|
|
100
|
+
text-decoration: underline;
|
|
101
|
+
cursor: pointer;
|
|
102
|
+
|
|
103
|
+
&:hover {
|
|
104
|
+
opacity: 0.8;
|
|
105
|
+
}
|
|
106
|
+
`;
|
|
107
|
+
|
|
108
|
+
interface TermsCheckboxProps {
|
|
109
|
+
checked: boolean;
|
|
110
|
+
onChange: (checked: boolean) => void;
|
|
111
|
+
text?: string;
|
|
112
|
+
termsText?: string;
|
|
113
|
+
termsUrl?: string;
|
|
114
|
+
cookieText?: string;
|
|
115
|
+
cookieUrl?: string;
|
|
116
|
+
variant?: Variant;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export const TermsCheckbox = ({
|
|
120
|
+
checked,
|
|
121
|
+
onChange,
|
|
122
|
+
text = "By submitting, I agree to Juta's",
|
|
123
|
+
termsText = "Terms and Conditions",
|
|
124
|
+
termsUrl = "/terms",
|
|
125
|
+
cookieText = "Cookie Policy",
|
|
126
|
+
cookieUrl = "/cookie-policy",
|
|
127
|
+
variant = 'primary',
|
|
128
|
+
}: TermsCheckboxProps) => {
|
|
129
|
+
return (
|
|
130
|
+
<CheckboxContainer>
|
|
131
|
+
<HiddenCheckbox
|
|
132
|
+
checked={checked}
|
|
133
|
+
onChange={(e) => onChange(e.target.checked)}
|
|
134
|
+
/>
|
|
135
|
+
<StyledCheckbox $checked={checked} variant={variant} />
|
|
136
|
+
<Text variant={variant}>
|
|
137
|
+
{text}{' '}
|
|
138
|
+
<Link href={termsUrl} variant={variant} target="_blank" rel="noopener noreferrer">
|
|
139
|
+
{termsText}
|
|
140
|
+
</Link>
|
|
141
|
+
{' '}and{' '}
|
|
142
|
+
<Link href={cookieUrl} variant={variant} target="_blank" rel="noopener noreferrer">
|
|
143
|
+
{cookieText}
|
|
144
|
+
</Link>
|
|
145
|
+
</Text>
|
|
146
|
+
</CheckboxContainer>
|
|
147
|
+
);
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
TermsCheckbox.variants = variants;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { ComponentProps } from 'react';
|
|
3
|
+
import { colors } from '../../tokens/colors';
|
|
4
|
+
import { Text as Component } from './Text';
|
|
5
|
+
|
|
6
|
+
const meta: Meta = {
|
|
7
|
+
title: 'Atoms/Text',
|
|
8
|
+
component: Component,
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export default meta;
|
|
12
|
+
|
|
13
|
+
export const Text: StoryObj<ComponentProps<typeof Component>> = {
|
|
14
|
+
args: {
|
|
15
|
+
color: 'active',
|
|
16
|
+
variant: 'sm',
|
|
17
|
+
children: 'Text',
|
|
18
|
+
},
|
|
19
|
+
argTypes: {
|
|
20
|
+
children: {
|
|
21
|
+
control: 'text',
|
|
22
|
+
},
|
|
23
|
+
color: {
|
|
24
|
+
control: 'select',
|
|
25
|
+
options: Object.keys(colors.text),
|
|
26
|
+
},
|
|
27
|
+
variant: {
|
|
28
|
+
control: 'select',
|
|
29
|
+
options: Component.variants,
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import styled from 'styled-components';
|
|
2
|
+
import { colors } from '../../tokens/colors';
|
|
3
|
+
|
|
4
|
+
const sizes = ['sm', 'md', 'lg'] as const;
|
|
5
|
+
|
|
6
|
+
const variants = {
|
|
7
|
+
sm: {
|
|
8
|
+
fontSize: '14px',
|
|
9
|
+
fontWeight: 500,
|
|
10
|
+
},
|
|
11
|
+
md: {
|
|
12
|
+
fontSize: '16px',
|
|
13
|
+
fontWeight: 500,
|
|
14
|
+
},
|
|
15
|
+
lg: {
|
|
16
|
+
fontSize: '18px',
|
|
17
|
+
fontWeight: 500,
|
|
18
|
+
},
|
|
19
|
+
} as const;
|
|
20
|
+
|
|
21
|
+
type Variant = keyof typeof variants;
|
|
22
|
+
|
|
23
|
+
type Color = keyof typeof colors.text;
|
|
24
|
+
|
|
25
|
+
interface TextProps {
|
|
26
|
+
children: string;
|
|
27
|
+
variant?: Variant;
|
|
28
|
+
color?: Color;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const StyledText = styled.h1<{ variant: Variant; color: Color }>`
|
|
32
|
+
color: ${(props) => colors.text[props?.color]};
|
|
33
|
+
font-size: ${(props) => variants[props.variant].fontSize};
|
|
34
|
+
font-weight: ${(props) => variants[props.variant].fontWeight};
|
|
35
|
+
`;
|
|
36
|
+
|
|
37
|
+
export const Text = ({
|
|
38
|
+
children,
|
|
39
|
+
color = 'primary',
|
|
40
|
+
variant = 'md',
|
|
41
|
+
}: TextProps) => {
|
|
42
|
+
return (
|
|
43
|
+
<StyledText color={color} variant={variant}>
|
|
44
|
+
{children}
|
|
45
|
+
</StyledText>
|
|
46
|
+
);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
Text.variants = sizes;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { ComponentProps } from 'react';
|
|
3
|
+
import { TextButton as Component } from './TextButton';
|
|
4
|
+
|
|
5
|
+
const meta: Meta = {
|
|
6
|
+
title: 'Atoms/TextButton',
|
|
7
|
+
component: Component,
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export default meta;
|
|
11
|
+
|
|
12
|
+
export const TextButton: StoryObj<Omit<ComponentProps<typeof Component>, 'onClick'>> = {
|
|
13
|
+
args: {
|
|
14
|
+
text: 'Click Me',
|
|
15
|
+
bgVariant: 'brand',
|
|
16
|
+
textVariant: 'secondary',
|
|
17
|
+
uppercase: true,
|
|
18
|
+
bold: false,
|
|
19
|
+
},
|
|
20
|
+
argTypes: {
|
|
21
|
+
text: { control: 'text' },
|
|
22
|
+
bgVariant: {
|
|
23
|
+
control: 'select',
|
|
24
|
+
options: ['primary', 'secondary', 'tertiary', 'subtle', 'blue', 'brand', 'light', 'transparent'],
|
|
25
|
+
},
|
|
26
|
+
textVariant: {
|
|
27
|
+
control: 'select',
|
|
28
|
+
options: ['brand', 'primary', 'secondary', 'tertiary', 'subtle', 'light', 'error', 'blue'],
|
|
29
|
+
},
|
|
30
|
+
uppercase: { control: 'boolean' },
|
|
31
|
+
bold: { control: 'boolean' },
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export const DarkButton: StoryObj<ComponentProps<typeof Component>> = {
|
|
36
|
+
args: {
|
|
37
|
+
text: 'Dark Button',
|
|
38
|
+
bgVariant: 'brand',
|
|
39
|
+
textVariant: 'secondary',
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export const LightButton: StoryObj<ComponentProps<typeof Component>> = {
|
|
44
|
+
args: {
|
|
45
|
+
text: 'Light Button',
|
|
46
|
+
bgVariant: 'secondary',
|
|
47
|
+
textVariant: 'primary',
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export const TealButton: StoryObj<ComponentProps<typeof Component>> = {
|
|
52
|
+
args: {
|
|
53
|
+
text: 'Teal Button',
|
|
54
|
+
bgVariant: 'subtle',
|
|
55
|
+
textVariant: 'secondary',
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export const TransparentButton: StoryObj<ComponentProps<typeof Component>> = {
|
|
60
|
+
args: {
|
|
61
|
+
text: 'Transparent Button',
|
|
62
|
+
bgVariant: 'transparent',
|
|
63
|
+
textVariant: 'primary',
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export const AllCombinations: StoryObj = {
|
|
68
|
+
render: () => (
|
|
69
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
|
|
70
|
+
<Component text="Dark BG + White Text" bgVariant="brand" textVariant="secondary" />
|
|
71
|
+
<Component text="Light BG + Dark Text" bgVariant="secondary" textVariant="primary" />
|
|
72
|
+
<Component text="Teal BG + White Text" bgVariant="subtle" textVariant="secondary" />
|
|
73
|
+
<Component text="Blue BG + White Text" bgVariant="blue" textVariant="secondary" />
|
|
74
|
+
<Component text="Transparent + Dark Text" bgVariant="transparent" textVariant="primary" />
|
|
75
|
+
</div>
|
|
76
|
+
),
|
|
77
|
+
};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import styled from 'styled-components';
|
|
2
|
+
import { colors } from '../../tokens/colors';
|
|
3
|
+
|
|
4
|
+
const bgVariants = ['primary', 'secondary', 'tertiary', 'subtle', 'blue', 'brand', 'light', 'transparent'] as const;
|
|
5
|
+
const textVariants = ['brand', 'primary', 'secondary', 'tertiary', 'subtle', 'light', 'error', 'blue'] as const;
|
|
6
|
+
|
|
7
|
+
type BgVariant = (typeof bgVariants)[number];
|
|
8
|
+
type TextVariant = (typeof textVariants)[number];
|
|
9
|
+
|
|
10
|
+
const StyledContainer = styled.button<{
|
|
11
|
+
as?: 'button' | 'div';
|
|
12
|
+
bgVariant: BgVariant;
|
|
13
|
+
}>`
|
|
14
|
+
padding: 0 1rem;
|
|
15
|
+
height: 2.5rem;
|
|
16
|
+
display: flex;
|
|
17
|
+
align-items: center;
|
|
18
|
+
flex-shrink:0;
|
|
19
|
+
white-space: nowrap;
|
|
20
|
+
background-color: ${(props) => {
|
|
21
|
+
if (props.bgVariant === 'transparent') return 'transparent';
|
|
22
|
+
return colors.background[props.bgVariant];
|
|
23
|
+
}};
|
|
24
|
+
transition: all 0.2s;
|
|
25
|
+
border: none;
|
|
26
|
+
cursor: pointer;
|
|
27
|
+
|
|
28
|
+
&:hover {
|
|
29
|
+
opacity: 0.9;
|
|
30
|
+
}
|
|
31
|
+
`;
|
|
32
|
+
|
|
33
|
+
const StyledText = styled.span<{
|
|
34
|
+
textVariant: TextVariant;
|
|
35
|
+
$uppercase?: boolean;
|
|
36
|
+
$bold?: boolean;
|
|
37
|
+
}>`
|
|
38
|
+
color: ${(props) => colors.text[props.textVariant]};
|
|
39
|
+
font-size: 0.75rem;
|
|
40
|
+
letter-spacing: 0.05em;
|
|
41
|
+
text-transform: ${props => props.$uppercase ? 'uppercase' : 'none'};
|
|
42
|
+
font-weight: ${props => props.$bold ? 700 : 600};
|
|
43
|
+
`;
|
|
44
|
+
|
|
45
|
+
interface TextButtonProps {
|
|
46
|
+
text: string;
|
|
47
|
+
onClick?: () => void;
|
|
48
|
+
asChild?: boolean;
|
|
49
|
+
bgVariant?: BgVariant;
|
|
50
|
+
textVariant?: TextVariant;
|
|
51
|
+
uppercase?: boolean;
|
|
52
|
+
bold?: boolean;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export const TextButton = ({
|
|
56
|
+
text,
|
|
57
|
+
onClick,
|
|
58
|
+
asChild = false,
|
|
59
|
+
bgVariant = 'brand',
|
|
60
|
+
textVariant = 'secondary',
|
|
61
|
+
uppercase = true,
|
|
62
|
+
bold = false
|
|
63
|
+
}: TextButtonProps) => {
|
|
64
|
+
return (
|
|
65
|
+
<StyledContainer
|
|
66
|
+
as={asChild ? 'div' : 'button'}
|
|
67
|
+
onClick={onClick}
|
|
68
|
+
bgVariant={bgVariant}
|
|
69
|
+
>
|
|
70
|
+
<StyledText textVariant={textVariant} $uppercase={uppercase} $bold={bold}>
|
|
71
|
+
{text}
|
|
72
|
+
</StyledText>
|
|
73
|
+
</StyledContainer>
|
|
74
|
+
);
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
TextButton.bgVariants = bgVariants;
|
|
78
|
+
TextButton.textVariants = textVariants;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { ChangeEvent } from 'react';
|
|
2
|
+
import styled from 'styled-components';
|
|
3
|
+
import { colors } from '../../tokens/colors';
|
|
4
|
+
import { InputTypes, type BaseInputProps } from '../../types';
|
|
5
|
+
|
|
6
|
+
interface TextareaProps extends Omit<BaseInputProps, 'label'> {
|
|
7
|
+
onChange: (event: ChangeEvent<HTMLTextAreaElement>) => void;
|
|
8
|
+
disabled?: boolean;
|
|
9
|
+
value?: string | number;
|
|
10
|
+
rows?: number;
|
|
11
|
+
cols?: number;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const StyledTextarea = styled.textarea`
|
|
15
|
+
display: block;
|
|
16
|
+
width: 100%;
|
|
17
|
+
height: 100%;
|
|
18
|
+
outline: none;
|
|
19
|
+
background-color: transparent;
|
|
20
|
+
color: ${colors.text.subtle};
|
|
21
|
+
font-weight: 600;
|
|
22
|
+
resize: vertical;
|
|
23
|
+
`;
|
|
24
|
+
|
|
25
|
+
export const Textarea = ({
|
|
26
|
+
name,
|
|
27
|
+
onChange,
|
|
28
|
+
rows = 3,
|
|
29
|
+
...rest
|
|
30
|
+
}: TextareaProps) => {
|
|
31
|
+
return (
|
|
32
|
+
<StyledTextarea name={name} onChange={onChange} rows={rows} {...rest} />
|
|
33
|
+
);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
Textarea.types = InputTypes;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { ComponentProps, useState } from 'react';
|
|
3
|
+
import { ToggleButton as Component } from './ToggleButton';
|
|
4
|
+
|
|
5
|
+
const meta: Meta = {
|
|
6
|
+
title: 'Atoms/ToggleButton',
|
|
7
|
+
component: Component,
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export default meta;
|
|
11
|
+
|
|
12
|
+
export const ToggleButton: StoryObj<Omit<ComponentProps<typeof Component>, 'onClick'>> = {
|
|
13
|
+
render: (args) => {
|
|
14
|
+
const [activeOption, setActiveOption] = useState('GENERAL');
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<Component
|
|
18
|
+
{...args}
|
|
19
|
+
activeOption={activeOption}
|
|
20
|
+
onChange={setActiveOption}
|
|
21
|
+
/>
|
|
22
|
+
);
|
|
23
|
+
},
|
|
24
|
+
args: {
|
|
25
|
+
options: ['GENERAL', 'LEGAL'],
|
|
26
|
+
|
|
27
|
+
},
|
|
28
|
+
argTypes: {
|
|
29
|
+
options: { control: 'object' },
|
|
30
|
+
|
|
31
|
+
},
|
|
32
|
+
};
|