takeat-design-system-ui-kit 0.0.0
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/.storybook/main.ts +17 -0
- package/.storybook/preview.tsx +41 -0
- package/README.md +50 -0
- package/cli/create-story.js +65 -0
- package/eslint.config.js +26 -0
- package/index.html +13 -0
- package/package.json +66 -0
- package/public/vite.svg +1 -0
- package/src/App.css +42 -0
- package/src/App.tsx +7 -0
- package/src/LibraryProvider.tsx +17 -0
- package/src/assets/Spinner.svg +3 -0
- package/src/assets/icons/addCircleFilled.svg +8 -0
- package/src/assets/icons/arrowDown.svg +8 -0
- package/src/assets/icons/arrowDropDown.svg +8 -0
- package/src/assets/icons/arrowDropUp.svg +8 -0
- package/src/assets/icons/arrowUp.svg +8 -0
- package/src/assets/icons/barGraph.svg +8 -0
- package/src/assets/icons/bell.svg +8 -0
- package/src/assets/icons/bellFilled.svg +8 -0
- package/src/assets/icons/bellNotification.svg +8 -0
- package/src/assets/icons/bellNotificationFilled.svg +8 -0
- package/src/assets/icons/bill.svg +8 -0
- package/src/assets/icons/billFilled.svg +8 -0
- package/src/assets/icons/bookOpen.svg +8 -0
- package/src/assets/icons/bookOpenFilled.svg +8 -0
- package/src/assets/icons/bullhorn.svg +3 -0
- package/src/assets/icons/cached.svg +8 -0
- package/src/assets/icons/calendar.svg +8 -0
- package/src/assets/icons/calendarCheck.svg +8 -0
- package/src/assets/icons/calendarCheckFilled.svg +8 -0
- package/src/assets/icons/calendarFilled.svg +8 -0
- package/src/assets/icons/cashier.svg +35 -0
- package/src/assets/icons/cashierFilled.svg +6 -0
- package/src/assets/icons/chat.svg +8 -0
- package/src/assets/icons/chatFilled.svg +8 -0
- package/src/assets/icons/check.svg +8 -0
- package/src/assets/icons/checkbox.svg +8 -0
- package/src/assets/icons/checkboxChecked.svg +8 -0
- package/src/assets/icons/checkboxCheckedFilled.svg +11 -0
- package/src/assets/icons/chevronDown.svg +3 -0
- package/src/assets/icons/chevronLeft.svg +3 -0
- package/src/assets/icons/chevronRight.svg +3 -0
- package/src/assets/icons/chevronUp.svg +3 -0
- package/src/assets/icons/clipboardCheck.svg +8 -0
- package/src/assets/icons/clipboardCheckFilled.svg +8 -0
- package/src/assets/icons/clock.svg +8 -0
- package/src/assets/icons/close.svg +8 -0
- package/src/assets/icons/closeCircle.svg +8 -0
- package/src/assets/icons/closeCircleFilled.svg +8 -0
- package/src/assets/icons/cloud.svg +8 -0
- package/src/assets/icons/cloudFilled.svg +8 -0
- package/src/assets/icons/copy.svg +4 -0
- package/src/assets/icons/copyFilled.svg +4 -0
- package/src/assets/icons/deleteFilled.svg +8 -0
- package/src/assets/icons/dollarSign.svg +8 -0
- package/src/assets/icons/download.svg +8 -0
- package/src/assets/icons/exchange.svg +8 -0
- package/src/assets/icons/exclamation.svg +8 -0
- package/src/assets/icons/externalLink.svg +4 -0
- package/src/assets/icons/eye.svg +3 -0
- package/src/assets/icons/eyeFilled.svg +3 -0
- package/src/assets/icons/eyeSlash.svg +8 -0
- package/src/assets/icons/eyeSlashFilled.svg +8 -0
- package/src/assets/icons/filterList.svg +10 -0
- package/src/assets/icons/folderOpen.svg +8 -0
- package/src/assets/icons/folderOpenFilled.svg +8 -0
- package/src/assets/icons/hand.svg +8 -0
- package/src/assets/icons/handFilled.svg +8 -0
- package/src/assets/icons/helpFilled.svg +8 -0
- package/src/assets/icons/home.svg +8 -0
- package/src/assets/icons/homeFilled.svg +9 -0
- package/src/assets/icons/idCard.svg +8 -0
- package/src/assets/icons/idCardFilled.svg +8 -0
- package/src/assets/icons/info.svg +8 -0
- package/src/assets/icons/infoFilled.svg +8 -0
- package/src/assets/icons/instagram.svg +5 -0
- package/src/assets/icons/like.svg +3 -0
- package/src/assets/icons/likeFilled.svg +4 -0
- package/src/assets/icons/loading.svg +17 -0
- package/src/assets/icons/logout.svg +4 -0
- package/src/assets/icons/mail.svg +8 -0
- package/src/assets/icons/mailFilled.svg +8 -0
- package/src/assets/icons/manager.svg +4 -0
- package/src/assets/icons/menu.svg +8 -0
- package/src/assets/icons/menuCircles.svg +8 -0
- package/src/assets/icons/minus.svg +8 -0
- package/src/assets/icons/minusCircle.svg +8 -0
- package/src/assets/icons/minusCircleFilled.svg +8 -0
- package/src/assets/icons/money.svg +8 -0
- package/src/assets/icons/moneyCircle.svg +8 -0
- package/src/assets/icons/moneyFilled.svg +8 -0
- package/src/assets/icons/motorcycle.svg +3 -0
- package/src/assets/icons/pencil.svg +3 -0
- package/src/assets/icons/pencilFilled.svg +4 -0
- package/src/assets/icons/percent.svg +8 -0
- package/src/assets/icons/phone.svg +8 -0
- package/src/assets/icons/phoneFilled.svg +8 -0
- package/src/assets/icons/piggyBank.svg +8 -0
- package/src/assets/icons/piggyBankFilled.svg +8 -0
- package/src/assets/icons/playCircle.svg +8 -0
- package/src/assets/icons/playCircleFilled.svg +8 -0
- package/src/assets/icons/playSquare.svg +8 -0
- package/src/assets/icons/playSquareFilled.svg +8 -0
- package/src/assets/icons/plus.svg +8 -0
- package/src/assets/icons/plusCircle.svg +8 -0
- package/src/assets/icons/power.svg +8 -0
- package/src/assets/icons/printer.svg +8 -0
- package/src/assets/icons/printerFilled.svg +8 -0
- package/src/assets/icons/qrCode.svg +8 -0
- package/src/assets/icons/question.svg +8 -0
- package/src/assets/icons/radioButton.svg +8 -0
- package/src/assets/icons/radioButtonChecked.svg +8 -0
- package/src/assets/icons/refresh.svg +8 -0
- package/src/assets/icons/scheduleFilled.svg +8 -0
- package/src/assets/icons/search.svg +8 -0
- package/src/assets/icons/settings.svg +4 -0
- package/src/assets/icons/settingsFilled.svg +3 -0
- package/src/assets/icons/star.svg +8 -0
- package/src/assets/icons/starFilled.svg +8 -0
- package/src/assets/icons/store.svg +8 -0
- package/src/assets/icons/storeFilled.svg +8 -0
- package/src/assets/icons/takeatIcon.svg +6 -0
- package/src/assets/icons/takeatIconFilled.svg +6 -0
- package/src/assets/icons/ticket.svg +8 -0
- package/src/assets/icons/ticketFilled.svg +8 -0
- package/src/assets/icons/trash.svg +8 -0
- package/src/assets/icons/trendingDown.svg +8 -0
- package/src/assets/icons/trendingUp.svg +8 -0
- package/src/assets/icons/user.svg +8 -0
- package/src/assets/icons/userAdd.svg +8 -0
- package/src/assets/icons/userAddFilled.svg +8 -0
- package/src/assets/icons/userCircle.svg +8 -0
- package/src/assets/icons/userCircleFilled.svg +8 -0
- package/src/assets/icons/userFilled.svg +8 -0
- package/src/assets/icons/utensils.svg +8 -0
- package/src/assets/icons/waiter.svg +3 -0
- package/src/assets/icons/warning.svg +8 -0
- package/src/assets/icons/warningFilled.svg +8 -0
- package/src/assets/icons/whatsapp.svg +10 -0
- package/src/assets/icons/whatsappFilled.svg +10 -0
- package/src/components/Accordion/Accordion.stories.tsx +19 -0
- package/src/components/Accordion/index.tsx +8 -0
- package/src/components/Accordion/styles.ts +1 -0
- package/src/components/Badge/Badge.stories.tsx +21 -0
- package/src/components/Badge/index.tsx +8 -0
- package/src/components/Badge/styles.ts +1 -0
- package/src/components/Button/Button.stories.tsx +186 -0
- package/src/components/Button/index.tsx +71 -0
- package/src/components/Button/styles.ts +216 -0
- package/src/components/Calendar/Calendar.stories.tsx +69 -0
- package/src/components/Calendar/CalendarComponents/index.tsx +214 -0
- package/src/components/Calendar/CalendarComponents/styles.ts +46 -0
- package/src/components/Calendar/index.tsx +290 -0
- package/src/components/Calendar/styles.ts +203 -0
- package/src/components/Divider/Divider.stories.tsx +57 -0
- package/src/components/Divider/index.tsx +22 -0
- package/src/components/Divider/styles.ts +25 -0
- package/src/components/FormItens/Checkbox/Checkbox.stories.tsx +50 -0
- package/src/components/FormItens/Checkbox/index.tsx +34 -0
- package/src/components/FormItens/Checkbox/styles.ts +96 -0
- package/src/components/FormItens/Input/Input.stories.tsx +138 -0
- package/src/components/FormItens/Input/index.tsx +72 -0
- package/src/components/FormItens/Input/styles.ts +136 -0
- package/src/components/FormItens/Radio/Radio.stories.tsx +76 -0
- package/src/components/FormItens/Radio/index.tsx +35 -0
- package/src/components/FormItens/Radio/styles.ts +112 -0
- package/src/components/FormItens/Select/Select.stories.tsx +83 -0
- package/src/components/FormItens/Select/index.tsx +117 -0
- package/src/components/FormItens/Select/styles.ts +149 -0
- package/src/components/FormItens/Switch/Switch.stories.tsx +127 -0
- package/src/components/FormItens/Switch/index.tsx +59 -0
- package/src/components/FormItens/Switch/styles.ts +123 -0
- package/src/components/Icon/Icon.stories.tsx +87 -0
- package/src/components/Icon/index.tsx +24 -0
- package/src/components/Icon/styles.ts +36 -0
- package/src/components/Layouts/ColumnsGrid/ColumnsGrid.stories.tsx +66 -0
- package/src/components/Layouts/ColumnsGrid/index.tsx +35 -0
- package/src/components/Layouts/ColumnsGrid/styles.ts +21 -0
- package/src/components/Layouts/Grid/Grid.stories.tsx +61 -0
- package/src/components/Layouts/Grid/index.tsx +42 -0
- package/src/components/Layouts/Grid/styles.ts +16 -0
- package/src/components/Layouts/GridArea/GridArea.stories.tsx +64 -0
- package/src/components/Layouts/GridArea/index.tsx +51 -0
- package/src/components/Layouts/GridArea/styles.ts +12 -0
- package/src/components/Layouts/ResponsiveGrid/ResponsiveGrid.stories.tsx +71 -0
- package/src/components/Layouts/ResponsiveGrid/index.tsx +34 -0
- package/src/components/Layouts/ResponsiveGrid/styles.ts +19 -0
- package/src/components/MockComponent/index.tsx +9 -0
- package/src/components/MockComponent/styles.ts +14 -0
- package/src/components/Modal/Modal.stories.tsx +75 -0
- package/src/components/Modal/index.tsx +81 -0
- package/src/components/Modal/styles.ts +75 -0
- package/src/components/NotificationBanner/NotificationBanner.stories.tsx +49 -0
- package/src/components/NotificationBanner/index.tsx +54 -0
- package/src/components/NotificationBanner/styles.ts +48 -0
- package/src/components/SingleTab/SingleTab.stories.tsx +50 -0
- package/src/components/SingleTab/index.tsx +36 -0
- package/src/components/SingleTab/styles.ts +110 -0
- package/src/components/Spinner/Spinner.stories.tsx +20 -0
- package/src/components/Spinner/index.tsx +14 -0
- package/src/components/Spinner/styles.ts +31 -0
- package/src/components/StoriesComponents/index.tsx +0 -0
- package/src/components/StoriesComponents/styles.ts +17 -0
- package/src/components/TabGroup/TabGroup.stories.tsx +64 -0
- package/src/components/TabGroup/index.tsx +75 -0
- package/src/components/TabGroup/styles.ts +7 -0
- package/src/components/Tooltip/Tooltip.stories.tsx +78 -0
- package/src/components/Tooltip/index.tsx +38 -0
- package/src/index.css +68 -0
- package/src/index.ts +19 -0
- package/src/main.tsx +10 -0
- package/src/styled.d.ts +6 -0
- package/src/svg.d.ts +9 -0
- package/src/utils/GlobalStyle.ts +47 -0
- package/src/utils/consts.ts +241 -0
- package/src/utils/functions.ts +327 -0
- package/src/utils/globalTypes.ts +8 -0
- package/src/utils/icons.tsx +15 -0
- package/src/vite-env.d.ts +1 -0
- package/tsconfig.app.json +24 -0
- package/tsconfig.json +7 -0
- package/tsconfig.node.json +22 -0
- package/vite.config.ts +8 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { Select } from ".";
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof Select> = {
|
|
5
|
+
component: Select,
|
|
6
|
+
title: "Design System/Select",
|
|
7
|
+
argTypes: {
|
|
8
|
+
options: {
|
|
9
|
+
description:
|
|
10
|
+
"Array de opções do select no padrão: `{ value: any, label: string }`",
|
|
11
|
+
},
|
|
12
|
+
isMulti: {
|
|
13
|
+
control: {
|
|
14
|
+
type: "boolean",
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
isClearable: {
|
|
18
|
+
control: {
|
|
19
|
+
type: "boolean",
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
isSearchable: {
|
|
23
|
+
control: {
|
|
24
|
+
type: "boolean",
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
register: {
|
|
28
|
+
description:
|
|
29
|
+
'Usado para integrar ao React Hook Form. Exemplo: `register("name", { required: "Campo obrigatório" })`',
|
|
30
|
+
control: {
|
|
31
|
+
disable: true,
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
name: {
|
|
35
|
+
description:
|
|
36
|
+
"Para integrar ao React Hook Form, o select requer que seja definido um 'name' igual ao que é passado para o register",
|
|
37
|
+
control: {
|
|
38
|
+
type: "text",
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
control: {
|
|
42
|
+
description:
|
|
43
|
+
"Para integrar ao React Hook Form, o select requer que seja definido um 'control' que é fornecido pelo useForm() do React Hook Form",
|
|
44
|
+
control: {
|
|
45
|
+
disable: true,
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
error: {
|
|
49
|
+
control: {
|
|
50
|
+
type: "text",
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
info: {
|
|
54
|
+
control: {
|
|
55
|
+
type: "text",
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
args: {
|
|
60
|
+
label: "Teste select",
|
|
61
|
+
isLoading: false,
|
|
62
|
+
isDisabled: false,
|
|
63
|
+
options: [
|
|
64
|
+
{ value: "chocolate", label: "Chocolate" },
|
|
65
|
+
{ value: "strawberry", label: "Strawberry" },
|
|
66
|
+
{ value: "vanilla", label: "Vanilla" },
|
|
67
|
+
],
|
|
68
|
+
info: "Informação adicional",
|
|
69
|
+
error: "",
|
|
70
|
+
isMulti: false,
|
|
71
|
+
isSearchable: false,
|
|
72
|
+
isClearable: false,
|
|
73
|
+
name: "teste",
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export default meta;
|
|
78
|
+
|
|
79
|
+
type Story = StoryObj<typeof Select>;
|
|
80
|
+
|
|
81
|
+
export const Example: Story = {
|
|
82
|
+
args: {},
|
|
83
|
+
};
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import ReactSelect, { Props as ReactSelectProps } from "react-select";
|
|
2
|
+
import { AdditionalInfo, SelectWrapper } from "./styles";
|
|
3
|
+
import { Controller, UseFormRegisterReturn } from "react-hook-form";
|
|
4
|
+
import React from "react";
|
|
5
|
+
import { Icon } from "../../Icon";
|
|
6
|
+
import { Spinner } from "../../Spinner";
|
|
7
|
+
import { useTheme } from "styled-components";
|
|
8
|
+
|
|
9
|
+
interface Option {
|
|
10
|
+
label: string;
|
|
11
|
+
value: any;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface CustomSelectProps extends ReactSelectProps<Option, false> {
|
|
15
|
+
name?: string;
|
|
16
|
+
label?: string;
|
|
17
|
+
register?: UseFormRegisterReturn;
|
|
18
|
+
control?: any;
|
|
19
|
+
error?: string;
|
|
20
|
+
info?: React.ReactNode | string;
|
|
21
|
+
isLoading?: boolean;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const RawSelect = ({
|
|
25
|
+
label,
|
|
26
|
+
error,
|
|
27
|
+
control,
|
|
28
|
+
info,
|
|
29
|
+
isDisabled,
|
|
30
|
+
isLoading,
|
|
31
|
+
...props
|
|
32
|
+
}: CustomSelectProps) => {
|
|
33
|
+
const theme = useTheme();
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<SelectWrapper disabled={isDisabled || isLoading} hasError={!!error}>
|
|
37
|
+
{label}
|
|
38
|
+
<ReactSelect
|
|
39
|
+
components={{
|
|
40
|
+
DropdownIndicator: () => {
|
|
41
|
+
if (isLoading) {
|
|
42
|
+
return (
|
|
43
|
+
<Spinner
|
|
44
|
+
color={theme.colors.neutral.light}
|
|
45
|
+
size={16}
|
|
46
|
+
style={{ marginRight: 8 }}
|
|
47
|
+
/>
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
return (
|
|
51
|
+
<Icon
|
|
52
|
+
className="custom-dropdown-icon"
|
|
53
|
+
icon="chevronDown"
|
|
54
|
+
size={28}
|
|
55
|
+
/>
|
|
56
|
+
);
|
|
57
|
+
},
|
|
58
|
+
}}
|
|
59
|
+
isDisabled={isDisabled || isLoading}
|
|
60
|
+
classNamePrefix="react-select"
|
|
61
|
+
noOptionsMessage={() => "Nada encontrado"}
|
|
62
|
+
{...props}
|
|
63
|
+
/>
|
|
64
|
+
{(!!control || !!error || !!info) && (
|
|
65
|
+
<AdditionalInfo
|
|
66
|
+
className="additional-info"
|
|
67
|
+
disabled={isDisabled || isLoading}
|
|
68
|
+
isError={!!error}
|
|
69
|
+
>
|
|
70
|
+
{error || info}
|
|
71
|
+
</AdditionalInfo>
|
|
72
|
+
)}
|
|
73
|
+
</SelectWrapper>
|
|
74
|
+
);
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export const Select = ({
|
|
78
|
+
name,
|
|
79
|
+
label,
|
|
80
|
+
register,
|
|
81
|
+
control,
|
|
82
|
+
error,
|
|
83
|
+
info,
|
|
84
|
+
isLoading,
|
|
85
|
+
...props
|
|
86
|
+
}: CustomSelectProps) => {
|
|
87
|
+
return control ? (
|
|
88
|
+
<Controller
|
|
89
|
+
name={name || ""}
|
|
90
|
+
control={control}
|
|
91
|
+
render={({ field }) => {
|
|
92
|
+
return (
|
|
93
|
+
<RawSelect
|
|
94
|
+
label={label}
|
|
95
|
+
error={error}
|
|
96
|
+
info={info}
|
|
97
|
+
control={control}
|
|
98
|
+
isLoading={isLoading}
|
|
99
|
+
isDisabled={props.isDisabled}
|
|
100
|
+
{...props}
|
|
101
|
+
{...field}
|
|
102
|
+
/>
|
|
103
|
+
);
|
|
104
|
+
}}
|
|
105
|
+
/>
|
|
106
|
+
) : (
|
|
107
|
+
<RawSelect
|
|
108
|
+
label={label}
|
|
109
|
+
error={error}
|
|
110
|
+
info={info}
|
|
111
|
+
control={control}
|
|
112
|
+
isLoading={isLoading}
|
|
113
|
+
isDisabled={props.isDisabled}
|
|
114
|
+
{...props}
|
|
115
|
+
/>
|
|
116
|
+
);
|
|
117
|
+
};
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import styled from "styled-components";
|
|
2
|
+
|
|
3
|
+
interface SelectWrapperProps {
|
|
4
|
+
hasError?: boolean;
|
|
5
|
+
disabled?: boolean;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const SelectWrapper = styled.label<SelectWrapperProps>`
|
|
9
|
+
display: flex;
|
|
10
|
+
flex-direction: column;
|
|
11
|
+
gap: 4px;
|
|
12
|
+
font-size: 16px;
|
|
13
|
+
font-style: normal;
|
|
14
|
+
font-weight: 600;
|
|
15
|
+
line-height: 24px;
|
|
16
|
+
letter-spacing: 0.15px;
|
|
17
|
+
color: ${({ theme, disabled }) =>
|
|
18
|
+
disabled ? theme.colors.neutral.light : theme.colors.neutral.dark};
|
|
19
|
+
width: fit-content;
|
|
20
|
+
|
|
21
|
+
.custom-dropdown-icon {
|
|
22
|
+
fill: ${({ theme, disabled }) =>
|
|
23
|
+
disabled ? theme.colors.neutral.light : theme.colors.neutral.dark};
|
|
24
|
+
|
|
25
|
+
padding-right: 8px;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.react-select__control {
|
|
29
|
+
border-radius: ${({ theme }) => theme.radius.m};
|
|
30
|
+
border-color: ${({ theme, hasError }) =>
|
|
31
|
+
hasError ? theme.colors.red.default : theme.colors.neutral.dark};
|
|
32
|
+
color: ${({ theme }) => theme.colors.neutral.dark};
|
|
33
|
+
font-size: 14px;
|
|
34
|
+
font-style: normal;
|
|
35
|
+
font-weight: 400;
|
|
36
|
+
line-height: 20px;
|
|
37
|
+
letter-spacing: 0.1px;
|
|
38
|
+
cursor: pointer;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
[class$="-control"]:hover {
|
|
42
|
+
border-color: ${({ theme }) => theme.colors.neutral.dark};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.react-select__control--is-focused {
|
|
46
|
+
outline: none;
|
|
47
|
+
border-color: ${({ theme }) => theme.colors.blue.dark};
|
|
48
|
+
box-shadow: none;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.react-select__control--is-disabled {
|
|
52
|
+
background-color: transparent;
|
|
53
|
+
border-color: ${({ theme }) => theme.colors.neutral.light};
|
|
54
|
+
color: ${({ theme }) => theme.colors.neutral.light};
|
|
55
|
+
|
|
56
|
+
.react-select__placeholder {
|
|
57
|
+
color: ${({ theme }) => theme.colors.neutral.light};
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.react-select__indicator-separator {
|
|
62
|
+
display: none;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.react-select__menu {
|
|
66
|
+
border-radius: ${({ theme }) => theme.radius.m};
|
|
67
|
+
padding: ${({ theme }) => theme.spacing.xs};
|
|
68
|
+
border-color: transparent;
|
|
69
|
+
box-shadow: ${({ theme }) => theme.shadows.default};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.react-select__menu-list {
|
|
73
|
+
padding: 0;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.react-select__option {
|
|
77
|
+
padding: ${({ theme }) => theme.spacing.xs};
|
|
78
|
+
border-radius: ${({ theme }) => theme.radius.s};
|
|
79
|
+
color: ${({ theme }) => theme.colors.neutral.dark};
|
|
80
|
+
font-family: ${({ theme }) => theme.typography.family.default};
|
|
81
|
+
font-size: 14px;
|
|
82
|
+
font-style: normal;
|
|
83
|
+
font-weight: 400;
|
|
84
|
+
line-height: 20px;
|
|
85
|
+
letter-spacing: 0.014px;
|
|
86
|
+
transition: all 0.3s;
|
|
87
|
+
cursor: pointer;
|
|
88
|
+
|
|
89
|
+
&:hover {
|
|
90
|
+
background-color: ${({ theme }) => theme.colors.neutral.lighter};
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.react-select__option--is-focused {
|
|
95
|
+
background-color: transparent;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.react-select__option--is-selected {
|
|
99
|
+
background-color: ${({ theme }) => theme.colors.primary.lightest};
|
|
100
|
+
color: ${({ theme }) => theme.colors.neutral.darker};
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.react-select__multi-value {
|
|
104
|
+
border-radius: ${({ theme }) => theme.radius.s};
|
|
105
|
+
background-color: ${({ theme }) => theme.colors.neutral.lighter};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.react-select__multi-value__label {
|
|
109
|
+
padding: ${({ theme }) => theme.spacing.xxs};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.react-select__multi-value__remove:hover {
|
|
113
|
+
background-color: ${({ theme }) => theme.colors.red.lightest};
|
|
114
|
+
|
|
115
|
+
svg {
|
|
116
|
+
fill: ${({ theme }) => theme.colors.red.default};
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.react-select__menu-notice {
|
|
121
|
+
color: ${({ theme }) => theme.colors.neutral.default};
|
|
122
|
+
font-family: ${({ theme }) => theme.typography.family.default};
|
|
123
|
+
font-size: 14px;
|
|
124
|
+
font-style: normal;
|
|
125
|
+
font-weight: 400;
|
|
126
|
+
line-height: 20px;
|
|
127
|
+
letter-spacing: 0.014px;
|
|
128
|
+
}
|
|
129
|
+
`;
|
|
130
|
+
|
|
131
|
+
interface AdditionalInfo {
|
|
132
|
+
isError?: boolean;
|
|
133
|
+
disabled?: boolean;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export const AdditionalInfo = styled.div<AdditionalInfo>`
|
|
137
|
+
color: ${({ theme, isError, disabled }) =>
|
|
138
|
+
isError
|
|
139
|
+
? theme.colors.primary.default
|
|
140
|
+
: disabled
|
|
141
|
+
? theme.colors.neutral.light
|
|
142
|
+
: theme.colors.neutral.dark};
|
|
143
|
+
font-size: 12px;
|
|
144
|
+
font-style: normal;
|
|
145
|
+
font-weight: 400;
|
|
146
|
+
line-height: 16px;
|
|
147
|
+
height: 16px;
|
|
148
|
+
letter-spacing: 0.4px;
|
|
149
|
+
`;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { Switch } from ".";
|
|
3
|
+
import { Subtitle } from "../../StoriesComponents/styles";
|
|
4
|
+
|
|
5
|
+
const meta: Meta<typeof Switch> = {
|
|
6
|
+
title: "Design System/Switch",
|
|
7
|
+
component: Switch,
|
|
8
|
+
parameters: {
|
|
9
|
+
componentSubtitle: (
|
|
10
|
+
<Subtitle>
|
|
11
|
+
Um Switch é um componente de interface que permite ao usuário alternar
|
|
12
|
+
entre dois estados mutuamente exclusivos, como ligar ou desligar uma
|
|
13
|
+
funcionalidade.
|
|
14
|
+
<br />
|
|
15
|
+
<br /> Esses controles são mais adequados para{" "}
|
|
16
|
+
<b>ações imediatas e contextuais</b>, onde o efeito da mudança de estado
|
|
17
|
+
é percebido instantaneamente. É ideal para ajustes simples e rápidos,
|
|
18
|
+
<b> sem necessidade de confirmação adicional.</b>
|
|
19
|
+
</Subtitle>
|
|
20
|
+
),
|
|
21
|
+
},
|
|
22
|
+
argTypes: {
|
|
23
|
+
label: {
|
|
24
|
+
control: {
|
|
25
|
+
type: "text",
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
labelPosition: {
|
|
29
|
+
control: {
|
|
30
|
+
type: "inline-radio",
|
|
31
|
+
options: ["left", "right", "top", "bottom"],
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
customColor: {
|
|
35
|
+
description: "Cor customizada do switch ativo (hexadecimal)",
|
|
36
|
+
control: {
|
|
37
|
+
type: "color",
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
isLoading: {
|
|
41
|
+
control: {
|
|
42
|
+
type: "boolean",
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
checked: {
|
|
46
|
+
description: "Valor do switch caso precise ter estado controlado",
|
|
47
|
+
control: {
|
|
48
|
+
type: "boolean",
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
onChange: {
|
|
52
|
+
description:
|
|
53
|
+
"Função de callback para quando o switch for alterado. Retorna um ChangeEvent. Exemplo: `onChange={(e) => console.log(e.target.checked)}`",
|
|
54
|
+
action: "changed",
|
|
55
|
+
},
|
|
56
|
+
register: {
|
|
57
|
+
description:
|
|
58
|
+
'Usado para integrar ao React Hook Form. Exemplo: `register("name", { required: "Campo obrigatório" })`',
|
|
59
|
+
control: {
|
|
60
|
+
disable: true,
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
|
|
65
|
+
args: {
|
|
66
|
+
label: "Switch",
|
|
67
|
+
labelPosition: "right",
|
|
68
|
+
disabled: false,
|
|
69
|
+
isLoading: false,
|
|
70
|
+
customColor: undefined,
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export default meta;
|
|
75
|
+
|
|
76
|
+
type Story = StoryObj<typeof Switch>;
|
|
77
|
+
|
|
78
|
+
export const Example: Story = {
|
|
79
|
+
name: "Exemplo",
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
export const List: Story = {
|
|
83
|
+
name: "Lista de todos os estados",
|
|
84
|
+
render: () => {
|
|
85
|
+
return (
|
|
86
|
+
<div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
|
|
87
|
+
<Switch label="Marcado" checked />
|
|
88
|
+
<Switch label="Marcado e desabilitado" disabled checked />
|
|
89
|
+
<Switch label="Desmarcado" checked={false} />
|
|
90
|
+
<Switch label="Desmarcado e desabilitado" disabled />
|
|
91
|
+
</div>
|
|
92
|
+
);
|
|
93
|
+
},
|
|
94
|
+
// Disable all controls
|
|
95
|
+
argTypes: {
|
|
96
|
+
label: {
|
|
97
|
+
table: {
|
|
98
|
+
disable: true,
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
checked: {
|
|
102
|
+
table: {
|
|
103
|
+
disable: true,
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
disabled: {
|
|
107
|
+
table: {
|
|
108
|
+
disable: true,
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
isLoading: {
|
|
112
|
+
table: {
|
|
113
|
+
disable: true,
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
labelPosition: {
|
|
117
|
+
table: {
|
|
118
|
+
disable: true,
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
customColor: {
|
|
122
|
+
table: {
|
|
123
|
+
disable: true,
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { UseFormRegisterReturn } from "react-hook-form";
|
|
2
|
+
import { generateColorVariants } from "../../../utils/functions";
|
|
3
|
+
import { SwitchArea, SwitchLabel } from "./styles";
|
|
4
|
+
import { forwardRef, useMemo } from "react";
|
|
5
|
+
import { LABEL_POSITIONS } from "../../../utils/consts";
|
|
6
|
+
import { Spinner } from "../../Spinner";
|
|
7
|
+
import { useTheme } from "styled-components";
|
|
8
|
+
|
|
9
|
+
interface SwitchProps extends React.InputHTMLAttributes<HTMLInputElement> {
|
|
10
|
+
label?: string | React.ReactNode;
|
|
11
|
+
labelPosition?: keyof typeof LABEL_POSITIONS;
|
|
12
|
+
customColor?: string;
|
|
13
|
+
isLoading?: boolean;
|
|
14
|
+
register?: UseFormRegisterReturn;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const Switch = forwardRef(function Switch(
|
|
18
|
+
{
|
|
19
|
+
label,
|
|
20
|
+
labelPosition = "right",
|
|
21
|
+
customColor,
|
|
22
|
+
isLoading,
|
|
23
|
+
register,
|
|
24
|
+
...props
|
|
25
|
+
}: SwitchProps,
|
|
26
|
+
ref: React.Ref<HTMLInputElement>
|
|
27
|
+
) {
|
|
28
|
+
const theme = useTheme();
|
|
29
|
+
const colorVariants = customColor
|
|
30
|
+
? useMemo(() => generateColorVariants(customColor), [customColor])
|
|
31
|
+
: undefined;
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<SwitchLabel labelPosition={labelPosition}>
|
|
35
|
+
<input
|
|
36
|
+
ref={ref}
|
|
37
|
+
type="checkbox"
|
|
38
|
+
{...props}
|
|
39
|
+
disabled={isLoading || props.disabled}
|
|
40
|
+
{...register}
|
|
41
|
+
/>
|
|
42
|
+
{label && <span>{label}</span>}
|
|
43
|
+
<SwitchArea colorVariants={colorVariants} isLoading={isLoading}>
|
|
44
|
+
<Spinner
|
|
45
|
+
size={10}
|
|
46
|
+
color={theme.colors.neutral.lighter}
|
|
47
|
+
style={{
|
|
48
|
+
position: "absolute",
|
|
49
|
+
left: 14,
|
|
50
|
+
top: 4,
|
|
51
|
+
transition: "all 0.3s cubic-bezier(0.65, 0, 0.35, 1)",
|
|
52
|
+
zIndex: 1,
|
|
53
|
+
opacity: isLoading ? 1 : 0,
|
|
54
|
+
}}
|
|
55
|
+
/>
|
|
56
|
+
</SwitchArea>
|
|
57
|
+
</SwitchLabel>
|
|
58
|
+
);
|
|
59
|
+
});
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import styled from "styled-components";
|
|
2
|
+
import { LABEL_POSITIONS, spacing } from "../../../utils/consts";
|
|
3
|
+
import { ColorVariants } from "../../../utils/globalTypes";
|
|
4
|
+
|
|
5
|
+
interface SwitchLabelProps {
|
|
6
|
+
labelPosition: keyof typeof LABEL_POSITIONS;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const SwitchLabel = styled.label<SwitchLabelProps>`
|
|
10
|
+
display: flex;
|
|
11
|
+
gap: ${spacing.xs};
|
|
12
|
+
align-items: center;
|
|
13
|
+
justify-content: center;
|
|
14
|
+
width: fit-content;
|
|
15
|
+
flex-direction: ${({ labelPosition }) => LABEL_POSITIONS[labelPosition]};
|
|
16
|
+
border-radius: ${spacing.xxs};
|
|
17
|
+
cursor: pointer;
|
|
18
|
+
user-select: none;
|
|
19
|
+
|
|
20
|
+
input {
|
|
21
|
+
opacity: 0;
|
|
22
|
+
width: 0;
|
|
23
|
+
height: 0;
|
|
24
|
+
position: absolute;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
&:has(> input[type="checkbox"]:focus-visible) {
|
|
28
|
+
outline: 1px solid black;
|
|
29
|
+
outline-offset: 2px;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
span {
|
|
33
|
+
color: ${({ theme }) => theme.colors.neutral.darker};
|
|
34
|
+
font-family: Poppins;
|
|
35
|
+
font-size: 14px;
|
|
36
|
+
font-style: normal;
|
|
37
|
+
font-weight: 500;
|
|
38
|
+
line-height: 20px; /* 142.857% */
|
|
39
|
+
letter-spacing: 0.1px;
|
|
40
|
+
transition: all 0.3s;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
&:has(> input[type="checkbox"]:disabled) {
|
|
44
|
+
cursor: default;
|
|
45
|
+
|
|
46
|
+
span {
|
|
47
|
+
color: ${({ theme }) => theme.colors.neutral.light};
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
`;
|
|
51
|
+
|
|
52
|
+
interface SwitchAreaProps {
|
|
53
|
+
isLoading?: boolean;
|
|
54
|
+
colorVariants?: ColorVariants;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export const SwitchArea = styled.div<SwitchAreaProps>`
|
|
58
|
+
flex-shrink: 0;
|
|
59
|
+
position: relative;
|
|
60
|
+
width: 40px;
|
|
61
|
+
height: 20px;
|
|
62
|
+
border-radius: 20px;
|
|
63
|
+
transition: all 0.3s;
|
|
64
|
+
background-color: ${({ theme }) => theme.colors.neutral.default};
|
|
65
|
+
border: 1px solid transparent;
|
|
66
|
+
|
|
67
|
+
label:hover > & {
|
|
68
|
+
background-color: ${({ theme }) => theme.colors.neutral.dark};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Switch button
|
|
72
|
+
&::after {
|
|
73
|
+
content: "";
|
|
74
|
+
position: absolute;
|
|
75
|
+
width: 14px;
|
|
76
|
+
height: 14px;
|
|
77
|
+
border-radius: 50%;
|
|
78
|
+
background-color: white;
|
|
79
|
+
transition: all 0.3s;
|
|
80
|
+
top: 2px;
|
|
81
|
+
left: ${({ isLoading }: SwitchAreaProps) => (isLoading ? "12px" : "2px")};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Checked
|
|
85
|
+
input[type="checkbox"]:checked ~ & {
|
|
86
|
+
background-color: ${({ colorVariants, theme }) =>
|
|
87
|
+
colorVariants?.default || theme.colors.green.default};
|
|
88
|
+
|
|
89
|
+
label:hover > & {
|
|
90
|
+
background-color: ${({ colorVariants, theme }) =>
|
|
91
|
+
colorVariants?.dark || theme.colors.green.dark};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
&::after {
|
|
95
|
+
left: ${({ isLoading }: SwitchAreaProps) =>
|
|
96
|
+
isLoading ? "12px" : "22px"};
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Disabled
|
|
101
|
+
input[type="checkbox"]:disabled ~ & {
|
|
102
|
+
background-color: #fff;
|
|
103
|
+
border-color: ${({ theme }) => theme.colors.neutral.light};
|
|
104
|
+
|
|
105
|
+
&::after {
|
|
106
|
+
background-color: ${({ theme }) => theme.colors.neutral.light};
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
//Disabled and checked
|
|
111
|
+
input[type="checkbox"]:disabled:checked ~ & {
|
|
112
|
+
background-color: ${({ theme }) => theme.colors.neutral.lighter};
|
|
113
|
+
border-color: transparent;
|
|
114
|
+
|
|
115
|
+
label:hover > & {
|
|
116
|
+
background-color: ${({ theme }) => theme.colors.neutral.lighter};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
&::after {
|
|
120
|
+
background-color: ${({ theme }) => theme.colors.neutral.light};
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
`;
|