@ubie/vitals-ui-consumer 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.
Files changed (170) hide show
  1. package/.storybook/main.ts +14 -0
  2. package/.storybook/preview.tsx +25 -0
  3. package/.storybook/vitest.setup.ts +7 -0
  4. package/dist/chunk-DKo7XVKm.mjs +33 -0
  5. package/dist/index.d.mts +1720 -0
  6. package/dist/index.d.mts.map +1 -0
  7. package/dist/index.mjs +10594 -0
  8. package/dist/index.mjs.map +1 -0
  9. package/dist/style.css +2299 -0
  10. package/package.json +47 -0
  11. package/src/components/Accordion/Accordion.module.css +75 -0
  12. package/src/components/Accordion/Accordion.spec.tsx +18 -0
  13. package/src/components/Accordion/Accordion.stories.tsx +61 -0
  14. package/src/components/Accordion/Accordion.tsx +89 -0
  15. package/src/components/ActionHalfModal/ActionHalfModal.module.css +180 -0
  16. package/src/components/ActionHalfModal/ActionHalfModal.spec.tsx +57 -0
  17. package/src/components/ActionHalfModal/ActionHalfModal.stories.tsx +469 -0
  18. package/src/components/ActionHalfModal/ActionHalfModal.tsx +269 -0
  19. package/src/components/ActionModal/ActionModal.module.css +145 -0
  20. package/src/components/ActionModal/ActionModal.spec.tsx +57 -0
  21. package/src/components/ActionModal/ActionModal.stories.tsx +302 -0
  22. package/src/components/ActionModal/ActionModal.tsx +232 -0
  23. package/src/components/Bold/Bold.module.css +4 -0
  24. package/src/components/Bold/Bold.spec.tsx +24 -0
  25. package/src/components/Bold/Bold.stories.tsx +54 -0
  26. package/src/components/Bold/Bold.tsx +31 -0
  27. package/src/components/Box/Box.module.css +46 -0
  28. package/src/components/Box/Box.spec.tsx +188 -0
  29. package/src/components/Box/Box.tsx +242 -0
  30. package/src/components/Button/Button.module.css +261 -0
  31. package/src/components/Button/Button.spec.tsx +82 -0
  32. package/src/components/Button/Button.tsx +99 -0
  33. package/src/components/Button/ButtonTypes.ts +107 -0
  34. package/src/components/Button/LinkButton.spec.tsx +86 -0
  35. package/src/components/Button/LinkButton.tsx +80 -0
  36. package/src/components/Button/VariantIcon.tsx +20 -0
  37. package/src/components/Button/useIcon.tsx +16 -0
  38. package/src/components/ButtonCard/ButtonCard.module.css +35 -0
  39. package/src/components/ButtonCard/ButtonCard.spec.tsx +18 -0
  40. package/src/components/ButtonCard/ButtonCard.stories.tsx +54 -0
  41. package/src/components/ButtonCard/ButtonCard.tsx +18 -0
  42. package/src/components/Center/Center.module.css +19 -0
  43. package/src/components/Center/Center.spec.tsx +143 -0
  44. package/src/components/Center/Center.tsx +108 -0
  45. package/src/components/Checkbox/Checkbox.module.css +124 -0
  46. package/src/components/Checkbox/Checkbox.spec.tsx +17 -0
  47. package/src/components/Checkbox/Checkbox.stories.tsx +213 -0
  48. package/src/components/Checkbox/Checkbox.tsx +50 -0
  49. package/src/components/CheckboxCard/CheckboxCard.module.css +102 -0
  50. package/src/components/CheckboxCard/CheckboxCard.spec.tsx +16 -0
  51. package/src/components/CheckboxCard/CheckboxCard.stories.tsx +205 -0
  52. package/src/components/CheckboxCard/CheckboxCard.tsx +53 -0
  53. package/src/components/CheckboxGroup/CheckboxGroup.module.css +16 -0
  54. package/src/components/CheckboxGroup/CheckboxGroup.spec.tsx +17 -0
  55. package/src/components/CheckboxGroup/CheckboxGroup.tsx +64 -0
  56. package/src/components/Color/Color.module.css +3 -0
  57. package/src/components/Color/Color.spec.tsx +24 -0
  58. package/src/components/Color/Color.stories.tsx +71 -0
  59. package/src/components/Color/Color.tsx +28 -0
  60. package/src/components/Divider/Divider.module.css +9 -0
  61. package/src/components/Divider/Divider.spec.tsx +42 -0
  62. package/src/components/Divider/Divider.stories.tsx +77 -0
  63. package/src/components/Divider/Divider.tsx +49 -0
  64. package/src/components/ErrorMessage/ErrorMessage.module.css +8 -0
  65. package/src/components/ErrorMessage/ErrorMessage.spec.tsx +12 -0
  66. package/src/components/ErrorMessage/ErrorMessage.tsx +20 -0
  67. package/src/components/Flex/Flex.module.css +24 -0
  68. package/src/components/Flex/Flex.spec.tsx +188 -0
  69. package/src/components/Flex/Flex.tsx +173 -0
  70. package/src/components/FlexItem/FlexItem.module.css +14 -0
  71. package/src/components/FlexItem/FlexItem.spec.tsx +84 -0
  72. package/src/components/FlexItem/FlexItem.tsx +106 -0
  73. package/src/components/Heading/Heading.module.css +131 -0
  74. package/src/components/Heading/Heading.tsx +86 -0
  75. package/src/components/HelperMessage/HelperMessage.module.css +8 -0
  76. package/src/components/HelperMessage/HelperMessage.tsx +15 -0
  77. package/src/components/Icon/Icon.module.css +6 -0
  78. package/src/components/Icon/Icon.spec.tsx +24 -0
  79. package/src/components/Icon/Icon.stories.tsx +100 -0
  80. package/src/components/Icon/Icon.tsx +101 -0
  81. package/src/components/Input/Input.module.css +51 -0
  82. package/src/components/Input/Input.spec.tsx +14 -0
  83. package/src/components/Input/Input.tsx +27 -0
  84. package/src/components/Label/Label.module.css +14 -0
  85. package/src/components/Label/Label.tsx +39 -0
  86. package/src/components/LinkCard/LinkCard.module.css +72 -0
  87. package/src/components/LinkCard/LinkCard.tsx +96 -0
  88. package/src/components/MessageHalfModal/MessageHalfModal.module.css +181 -0
  89. package/src/components/MessageHalfModal/MessageHalfModal.spec.tsx +73 -0
  90. package/src/components/MessageHalfModal/MessageHalfModal.stories.tsx +242 -0
  91. package/src/components/MessageHalfModal/MessageHalfModal.tsx +194 -0
  92. package/src/components/MessageModal/MessageModal.module.css +149 -0
  93. package/src/components/MessageModal/MessageModal.spec.tsx +57 -0
  94. package/src/components/MessageModal/MessageModal.stories.tsx +223 -0
  95. package/src/components/MessageModal/MessageModal.tsx +178 -0
  96. package/src/components/Pre/Pre.module.css +8 -0
  97. package/src/components/Pre/Pre.spec.tsx +11 -0
  98. package/src/components/Pre/Pre.stories.tsx +76 -0
  99. package/src/components/Pre/Pre.tsx +40 -0
  100. package/src/components/RadioButton/RadioButton.module.css +92 -0
  101. package/src/components/RadioButton/RadioButton.spec.tsx +25 -0
  102. package/src/components/RadioButton/RadioButton.tsx +55 -0
  103. package/src/components/RadioCard/RadioCard.module.css +109 -0
  104. package/src/components/RadioCard/RadioCard.tsx +61 -0
  105. package/src/components/RadioGroup/RadioGroup.module.css +16 -0
  106. package/src/components/RadioGroup/RadioGroup.spec.tsx +17 -0
  107. package/src/components/RadioGroup/RadioGroup.tsx +60 -0
  108. package/src/components/Select/Select.module.css +70 -0
  109. package/src/components/Select/Select.spec.tsx +12 -0
  110. package/src/components/Select/Select.tsx +56 -0
  111. package/src/components/Stack/Stack.module.css +10 -0
  112. package/src/components/Stack/Stack.spec.tsx +177 -0
  113. package/src/components/Stack/Stack.tsx +151 -0
  114. package/src/components/Stepper/Stepper.module.css +137 -0
  115. package/src/components/Stepper/Stepper.spec.tsx +198 -0
  116. package/src/components/Stepper/Stepper.stories.tsx +192 -0
  117. package/src/components/Stepper/Stepper.tsx +70 -0
  118. package/src/components/Stepper/StepperItem.tsx +113 -0
  119. package/src/components/Text/Text.module.css +168 -0
  120. package/src/components/Text/Text.tsx +192 -0
  121. package/src/components/TextArea/TextArea.module.css +46 -0
  122. package/src/components/TextArea/TextArea.spec.tsx +13 -0
  123. package/src/components/TextArea/TextArea.tsx +29 -0
  124. package/src/components/Toggle/Toggle.module.css +71 -0
  125. package/src/components/Toggle/Toggle.spec.tsx +21 -0
  126. package/src/components/Toggle/Toggle.tsx +56 -0
  127. package/src/font.ts +2 -0
  128. package/src/hooks/useScrollable.ts +58 -0
  129. package/src/icons/AppleIcon.tsx +14 -0
  130. package/src/icons/GoogleIcon.tsx +27 -0
  131. package/src/icons/LINEIcon.tsx +16 -0
  132. package/src/index.ts +35 -0
  133. package/src/sharedComponents/RequiredLabel/RequiredLabel.module.css +10 -0
  134. package/src/sharedComponents/RequiredLabel/RequiredLabel.tsx +8 -0
  135. package/src/sharedComponents/VisuallyHidden/VisuallyHidden.module.css +15 -0
  136. package/src/sharedComponents/VisuallyHidden/VisuallyHidden.tsx +22 -0
  137. package/src/stories/Accordion.stories.portable.ts +4 -0
  138. package/src/stories/Box.stories.tsx +474 -0
  139. package/src/stories/Button.stories.tsx +262 -0
  140. package/src/stories/Center.stories.tsx +126 -0
  141. package/src/stories/ErrorMessage.stories.tsx +19 -0
  142. package/src/stories/Flex.stories.tsx +345 -0
  143. package/src/stories/Form.stories.tsx +83 -0
  144. package/src/stories/Heading.stories.tsx +263 -0
  145. package/src/stories/HelperMessage.stories.tsx +22 -0
  146. package/src/stories/Input.stories.tsx +145 -0
  147. package/src/stories/Label.stories.tsx +32 -0
  148. package/src/stories/LinkButton.stories.tsx +207 -0
  149. package/src/stories/LinkCard.stories.tsx +90 -0
  150. package/src/stories/RadioButton.stories.tsx +168 -0
  151. package/src/stories/RadioCard.stories.tsx +236 -0
  152. package/src/stories/Select.stories.tsx +97 -0
  153. package/src/stories/Stack.stories.tsx +167 -0
  154. package/src/stories/Text.stories.tsx +396 -0
  155. package/src/stories/TextArea.stories.tsx +49 -0
  156. package/src/stories/Toggle.stories.tsx +30 -0
  157. package/src/test/vitest-jest-dom.d.ts +12 -0
  158. package/src/types/attributes.ts +6 -0
  159. package/src/types/global.d.ts +11 -0
  160. package/src/types/icon.ts +3 -0
  161. package/src/types/style.ts +254 -0
  162. package/src/utils/component.ts +8 -0
  163. package/src/utils/style.spec.ts +57 -0
  164. package/src/utils/style.ts +387 -0
  165. package/src/utils/types.ts +8 -0
  166. package/tsconfig.json +18 -0
  167. package/tsconfig.spec-lint.tsbuildinfo +1 -0
  168. package/tsconfig.tsbuildinfo +1 -0
  169. package/vite.config.ts +50 -0
  170. package/vitest.shims.d.ts +1 -0
@@ -0,0 +1,102 @@
1
+ .block {
2
+ width: 100%;
3
+ }
4
+
5
+ .checkbox {
6
+ position: absolute;
7
+ opacity: 0;
8
+ }
9
+
10
+ .label {
11
+ --ease-out-quint: cubic-bezier(0.22, 1, 0.36, 1);
12
+
13
+ position: relative;
14
+ box-sizing: border-box;
15
+ display: inline-block;
16
+ padding: 16px 12px 16px 48px;
17
+ font-size: var(--text-body-md-size);
18
+ font-weight: bold;
19
+ hyphens: auto;
20
+ line-height: var(--text-body-md-narrow-line);
21
+ color: var(--color-on-surface);
22
+ overflow-wrap: anywhere;
23
+ vertical-align: text-top;
24
+ cursor: pointer;
25
+ background: #fff;
26
+ border-radius: 8px;
27
+ outline: 1px solid var(--color-outline);
28
+ outline-offset: -1px;
29
+ transition:
30
+ outline-color 0.3s var(--ease-out-quint),
31
+ background-color 0.3s var(--ease-out-quint),
32
+ border-color 0.3s var(--ease-out-quint);
33
+ }
34
+
35
+ .label::before {
36
+ position: absolute;
37
+ top: 50%;
38
+ left: 12px;
39
+ box-sizing: border-box;
40
+ display: block;
41
+ width: 24px;
42
+ height: 24px;
43
+ content: "";
44
+ border: 2px solid var(--color-outline);
45
+ border-radius: var(--radius-sm);
46
+ transform: translateY(-50%);
47
+ }
48
+
49
+ @media (hover: hover) {
50
+ .label:hover:not(.disabled, .checked)::before {
51
+ background-color: var(--color-ubie-white);
52
+ border-color: var(--color-ubie-blue-500);
53
+ }
54
+ }
55
+
56
+ .label.checked::before {
57
+ background-color: var(--color-ubie-blue-600);
58
+ border: none;
59
+ }
60
+
61
+ .label.checked.disabled::before {
62
+ background-color: var(--color-placeholder);
63
+ border-color: transparent;
64
+ }
65
+
66
+ .label:not(.checked):has(.checkbox:focus-visible),
67
+ .label.checked:has(.checkbox:focus-visible) {
68
+ box-shadow: 0 0 0 2px var(--color-ubie-pink-500);
69
+ }
70
+
71
+ @media (hover: hover) {
72
+ .label:hover {
73
+ background-color: var(--color-ubie-blue-100);
74
+ }
75
+
76
+ .label.checked:not(.disabled):hover {
77
+ outline-color: var(--color-ubie-blue-700);
78
+ }
79
+
80
+ .label.checked:not(.disabled):hover::before {
81
+ background-color: var(--color-ubie-blue-700);
82
+ }
83
+ }
84
+
85
+ .label.disabled {
86
+ color: var(--color-placeholder);
87
+ background-color: var(--color-outline-variant);
88
+ outline-color: var(--color-outline);
89
+ }
90
+
91
+ .label.disabled::before {
92
+ border-color: var(--color-placeholder);
93
+ }
94
+
95
+ .checkIcon {
96
+ position: absolute;
97
+ top: 50%;
98
+ left: 14px;
99
+ line-height: 1;
100
+ color: var(--color-ubie-white);
101
+ translate: 0 -50%;
102
+ }
@@ -0,0 +1,16 @@
1
+ import { render, screen } from "@testing-library/react";
2
+ import { CheckboxCard } from "./CheckboxCard";
3
+
4
+ describe("<CheckboxCard>", () => {
5
+ it("receives id prop", () => {
6
+ render(<CheckboxCard id="checbox-id" />);
7
+ const checkbox = screen.getByRole("checkbox");
8
+ expect(checkbox.getAttribute("id")).toBe("checbox-id");
9
+ });
10
+
11
+ it("receives custom attribute", () => {
12
+ render(<CheckboxCard data-testid="checbox-id" />);
13
+ const checkbox = screen.getByTestId("checbox-id");
14
+ expect(checkbox).toBeInTheDocument();
15
+ });
16
+ });
@@ -0,0 +1,205 @@
1
+ import { Meta, StoryObj } from "@storybook/react-vite";
2
+ import { type ChangeEventHandler, ComponentProps, useCallback, useState } from "react";
3
+ import { CheckboxCard } from "./CheckboxCard";
4
+ import { CheckboxGroup } from "../CheckboxGroup/CheckboxGroup";
5
+ import { Stack } from "../Stack/Stack";
6
+
7
+ export default {
8
+ title: "Form/CheckboxCard",
9
+ component: CheckboxCard,
10
+ } satisfies Meta<typeof CheckboxCard>;
11
+
12
+ const defaultArgs: Partial<ComponentProps<typeof CheckboxCard>> = {};
13
+
14
+ const options = ["option1", "option2", "option3", "option4", "option5"];
15
+
16
+ type Story = StoryObj<typeof CheckboxCard>;
17
+
18
+ export const Default: Story = {
19
+ render: () => {
20
+ const [selectedItem, setSelectedItem] = useState<string[]>([options[0]]);
21
+
22
+ const onChange: ChangeEventHandler<HTMLInputElement> = useCallback(
23
+ (event) => {
24
+ if (event.currentTarget.checked) {
25
+ setSelectedItem([...selectedItem, event.currentTarget.value]);
26
+ } else {
27
+ setSelectedItem(selectedItem.filter((item) => item !== event.currentTarget.value));
28
+ }
29
+ },
30
+ [selectedItem],
31
+ );
32
+
33
+ return (
34
+ <Stack spacing="lg">
35
+ <CheckboxGroup label="Checkbox">
36
+ {options.map((option) => (
37
+ <CheckboxCard
38
+ block
39
+ name="default"
40
+ value={option}
41
+ onChange={onChange}
42
+ checked={selectedItem.includes(option)}
43
+ key={option}
44
+ >
45
+ {option}
46
+ </CheckboxCard>
47
+ ))}
48
+ </CheckboxGroup>
49
+
50
+ <dl>
51
+ <dt>Values</dt>
52
+ <dd>{selectedItem.join(",")}</dd>
53
+ </dl>
54
+ </Stack>
55
+ );
56
+ },
57
+ };
58
+
59
+ export const Disabled: Story = {
60
+ render: () => {
61
+ const [selectedItem, setSelectedItem] = useState<string[]>([options[0]]);
62
+
63
+ const onChange: ChangeEventHandler<HTMLInputElement> = useCallback(
64
+ (event) => {
65
+ if (event.currentTarget.checked) {
66
+ setSelectedItem([...selectedItem, event.currentTarget.value]);
67
+ } else {
68
+ setSelectedItem(selectedItem.filter((item) => item !== event.currentTarget.value));
69
+ }
70
+ },
71
+ [selectedItem],
72
+ );
73
+
74
+ return (
75
+ <CheckboxGroup label="Checkbox">
76
+ {options.map((option) => (
77
+ <CheckboxCard
78
+ disabled
79
+ name="default"
80
+ value={option}
81
+ onChange={onChange}
82
+ checked={selectedItem.includes(option)}
83
+ key={option}
84
+ >
85
+ {option}
86
+ </CheckboxCard>
87
+ ))}
88
+ </CheckboxGroup>
89
+ );
90
+ },
91
+ };
92
+
93
+ export const Horizontally: Story = {
94
+ render: () => {
95
+ const [selectedItem, setSelectedItem] = useState<string[]>([options[0]]);
96
+
97
+ const onChange: ChangeEventHandler<HTMLInputElement> = useCallback(
98
+ (event) => {
99
+ if (event.currentTarget.checked) {
100
+ setSelectedItem([...selectedItem, event.currentTarget.value]);
101
+ } else {
102
+ setSelectedItem(selectedItem.filter((item) => item !== event.currentTarget.value));
103
+ }
104
+ },
105
+ [selectedItem],
106
+ );
107
+
108
+ return (
109
+ <CheckboxGroup label="Checkbox" direction="row">
110
+ {options.map((option) => (
111
+ <CheckboxCard
112
+ name="horizontally"
113
+ value={option}
114
+ onChange={onChange}
115
+ checked={selectedItem.includes(option)}
116
+ id={option}
117
+ key={option}
118
+ >
119
+ {option}
120
+ </CheckboxCard>
121
+ ))}
122
+ </CheckboxGroup>
123
+ );
124
+ },
125
+ };
126
+
127
+ export const Block: Story = {
128
+ render: (args) => {
129
+ const [selectedItem, setSelectedItem] = useState<string[]>([options[0]]);
130
+
131
+ const onChange: ChangeEventHandler<HTMLInputElement> = useCallback(
132
+ (event) => {
133
+ if (event.currentTarget.checked) {
134
+ setSelectedItem([...selectedItem, event.currentTarget.value]);
135
+ } else {
136
+ setSelectedItem(selectedItem.filter((item) => item !== event.currentTarget.value));
137
+ }
138
+ },
139
+ [selectedItem],
140
+ );
141
+
142
+ return (
143
+ <CheckboxGroup label="Checkbox">
144
+ {options.map((option) => (
145
+ <CheckboxCard
146
+ block
147
+ {...args}
148
+ key={option}
149
+ checked={selectedItem.includes(option)}
150
+ value={option}
151
+ onChange={onChange}
152
+ name="block"
153
+ >
154
+ {option}
155
+ </CheckboxCard>
156
+ ))}
157
+ </CheckboxGroup>
158
+ );
159
+ },
160
+ args: {
161
+ ...defaultArgs,
162
+ name: "block",
163
+ block: true,
164
+ },
165
+ };
166
+
167
+ export const NoLabelOnGroup: Story = {
168
+ render: (args) => {
169
+ const [selectedItem, setSelectedItem] = useState<string[]>([options[0]]);
170
+
171
+ const onChange: ChangeEventHandler<HTMLInputElement> = useCallback(
172
+ (event) => {
173
+ if (event.currentTarget.checked) {
174
+ setSelectedItem([...selectedItem, event.currentTarget.value]);
175
+ } else {
176
+ setSelectedItem(selectedItem.filter((item) => item !== event.currentTarget.value));
177
+ }
178
+ },
179
+ [selectedItem],
180
+ );
181
+
182
+ return (
183
+ <CheckboxGroup>
184
+ {options.map((option) => (
185
+ <CheckboxCard
186
+ block
187
+ {...args}
188
+ key={option}
189
+ checked={selectedItem.includes(option)}
190
+ value={option}
191
+ onChange={onChange}
192
+ name="block"
193
+ >
194
+ {option}
195
+ </CheckboxCard>
196
+ ))}
197
+ </CheckboxGroup>
198
+ );
199
+ },
200
+ args: {
201
+ ...defaultArgs,
202
+ name: "block",
203
+ block: true,
204
+ },
205
+ };
@@ -0,0 +1,53 @@
1
+ "use client";
2
+
3
+ import { clsx } from "clsx";
4
+ import { forwardRef, type InputHTMLAttributes } from "react";
5
+ import styles from "./CheckboxCard.module.css";
6
+ import { Icon } from "../Icon/Icon";
7
+
8
+ type Props = InputHTMLAttributes<HTMLInputElement> & {
9
+ /**
10
+ * 横幅を100%占有する
11
+ */
12
+ block?: boolean;
13
+ };
14
+
15
+ /**
16
+ * カード状のチェックボックス
17
+ * タップ・クリック可能エリアが広いため操作が容易
18
+ */
19
+ const CheckboxCard = forwardRef<HTMLInputElement, Props>(
20
+ ({ name, value, checked, children, className, block = false, disabled, ...otherProps }, ref) => {
21
+ return (
22
+ <label
23
+ className={clsx(
24
+ styles.label,
25
+ block && styles.block,
26
+ checked && styles.checked,
27
+ disabled && styles.disabled,
28
+ )}
29
+ >
30
+ {checked && (
31
+ <span className={styles.checkIcon}>
32
+ <Icon size="sm" icon="CheckAIcon" aria-hidden="true" />
33
+ </span>
34
+ )}
35
+ <input
36
+ type="checkbox"
37
+ name={name}
38
+ value={value}
39
+ checked={checked}
40
+ className={clsx(className, styles.checkbox)}
41
+ ref={ref}
42
+ disabled={disabled}
43
+ {...otherProps}
44
+ />
45
+ {children}
46
+ </label>
47
+ );
48
+ },
49
+ );
50
+
51
+ CheckboxCard.displayName = "CheckboxCard";
52
+
53
+ export { CheckboxCard };
@@ -0,0 +1,16 @@
1
+ .wrapper {
2
+ padding: 0;
3
+ margin: 0;
4
+ border: none;
5
+ }
6
+
7
+ .legend {
8
+ display: flex;
9
+ gap: var(--size-spacing-xs);
10
+ align-items: center;
11
+ padding: 0;
12
+ margin-bottom: var(--size-spacing-md);
13
+ font-size: var(--text-body-sm-size);
14
+ font-weight: bold;
15
+ color: var(--color-on-surface-variant);
16
+ }
@@ -0,0 +1,17 @@
1
+ import { render } from "@testing-library/react";
2
+ import { createRef } from "react";
3
+ import { CheckboxGroup } from "./CheckboxGroup";
4
+
5
+ describe("CheckboxGroup", () => {
6
+ it("access to DOM through ref prop", () => {
7
+ const ref = createRef<HTMLFieldSetElement>();
8
+ render(
9
+ <CheckboxGroup label="test" ref={ref}>
10
+ <p>Test</p>
11
+ <p>Test</p>
12
+ </CheckboxGroup>,
13
+ );
14
+ expect(ref.current).not.toBeNull();
15
+ expect(ref.current?.tagName).toBe("FIELDSET");
16
+ });
17
+ });
@@ -0,0 +1,64 @@
1
+ "use client";
2
+
3
+ import { forwardRef, useMemo } from "react";
4
+ import styles from "./CheckboxGroup.module.css";
5
+ import { RequiredLabel } from "../../sharedComponents/RequiredLabel/RequiredLabel";
6
+ import { CustomDataAttributeProps } from "../../types/attributes";
7
+ import { Checkbox } from "../Checkbox/Checkbox";
8
+ import { CheckboxCard } from "../CheckboxCard/CheckboxCard";
9
+ import { Flex } from "../Flex/Flex";
10
+ import type { ReactElement } from "react";
11
+
12
+ /**
13
+ * チェックボックス系コンポーネントをグルーピングするコンテナー
14
+ */
15
+ export type Props = {
16
+ /**
17
+ * チェックボックス系のコンポーネント
18
+ */
19
+ children: ReactElement<typeof Checkbox>[] | ReactElement<typeof CheckboxCard>[];
20
+ /**
21
+ * グループの見出し
22
+ */
23
+ label?: string;
24
+ /**
25
+ * 必須ラベルの表示
26
+ */
27
+ showRequiredLabel?: boolean;
28
+ /**
29
+ * 配置方向
30
+ */
31
+ direction?: "column" | "row";
32
+ } & CustomDataAttributeProps;
33
+
34
+ const includesCheckboxCard = (children: Props["children"]): boolean => {
35
+ return children.some((child) => child.type === CheckboxCard);
36
+ };
37
+
38
+ export const CheckboxGroup = forwardRef<HTMLFieldSetElement, Props>(
39
+ ({ children, label, showRequiredLabel, direction = "column", ...otherProps }, ref) => {
40
+ const spacing = useMemo(() => {
41
+ return includesCheckboxCard(children) ? "sm" : "md";
42
+ }, [children]);
43
+
44
+ const wrap = useMemo(() => {
45
+ return direction === "row";
46
+ }, [direction]);
47
+
48
+ return (
49
+ <fieldset className={styles.wrapper} ref={ref} {...otherProps}>
50
+ {label && (
51
+ <legend className={styles.legend}>
52
+ {label}
53
+ {showRequiredLabel && <RequiredLabel />}
54
+ </legend>
55
+ )}
56
+ <Flex spacing={spacing} direction={direction} wrap={wrap}>
57
+ {children}
58
+ </Flex>
59
+ </fieldset>
60
+ );
61
+ },
62
+ );
63
+
64
+ CheckboxGroup.displayName = "CheckboxGroup";
@@ -0,0 +1,3 @@
1
+ .color {
2
+ color: var(--text-color);
3
+ }
@@ -0,0 +1,24 @@
1
+ import { composeStory } from "@storybook/react-vite";
2
+ import { render, screen } from "@testing-library/react";
3
+ import Meta, { WithId, WithCustomDataAttribute } from "./Color.stories";
4
+
5
+ const WithIdStory = composeStory(WithId, Meta);
6
+ const WithCustomDataAttributeStory = composeStory(WithCustomDataAttribute, Meta);
7
+
8
+ describe("Color", () => {
9
+ test("Add id", async () => {
10
+ render(<WithIdStory />);
11
+
12
+ const colorElement = screen.queryByText("色");
13
+
14
+ expect(colorElement).toHaveAttribute("id", "some-id");
15
+ });
16
+
17
+ test("Add custom data attribute", async () => {
18
+ render(<WithCustomDataAttributeStory />);
19
+
20
+ const colorElement = screen.queryByText("色");
21
+
22
+ expect(colorElement).toHaveAttribute("data-test-id", "some-id");
23
+ });
24
+ });
@@ -0,0 +1,71 @@
1
+ import { StoryObj, Meta } from "@storybook/react-vite";
2
+ import { Color } from "./Color";
3
+ import { Box } from "../Box/Box";
4
+ import { Stack } from "../Stack/Stack";
5
+ import { Text } from "../Text/Text";
6
+
7
+ export default {
8
+ title: "Typography/Font/Color",
9
+ component: Color,
10
+ } satisfies Meta<typeof Color>;
11
+
12
+ type Story = StoryObj<typeof Color>;
13
+
14
+ export const Colors: Story = {
15
+ render: () => {
16
+ return (
17
+ <Stack spacing="md">
18
+ <Color color="main">main</Color>
19
+ <Color color="sub">sub</Color>
20
+ <Color color="link">link</Color>
21
+ <Color color="linkSub">linkSub</Color>
22
+ <Color color="disabled">disabled</Color>
23
+ <Color color="blue">blue</Color>
24
+ <Color color="blueDarken">blueDarken</Color>
25
+ <Color color="pink">pink</Color>
26
+ <Color color="pinkDarken">pinkDarken</Color>
27
+ <Color color="orange">orange</Color>
28
+ <Color color="orangeDarken">orangeDarken</Color>
29
+ <Color color="purple">purple</Color>
30
+ <Color color="purpleDarken">purpleDarken</Color>
31
+ <Color color="green">green</Color>
32
+ <Color color="greenDarken">greenDarken</Color>
33
+ <Color color="red">red</Color>
34
+ <Color color="redDarken">redDarken</Color>
35
+ <Color color="black">black</Color>
36
+ <Color color="blackDarken">blackDarken</Color>
37
+ <Box pt="sm" pr="sm" pb="sm" pl="sm" backgroundColor="blackInverseDarken">
38
+ <Color color="white">white</Color>
39
+ </Box>
40
+ </Stack>
41
+ );
42
+ },
43
+ };
44
+
45
+ export const WithText: Story = {
46
+ render: () => {
47
+ return (
48
+ <Text type="body" size="lg" color="main">
49
+ 一部だけ<Color color="pink">色</Color>を変えたい
50
+ </Text>
51
+ );
52
+ },
53
+ };
54
+
55
+ export const WithId: Story = {
56
+ render: (args) => {
57
+ return <Color {...args}>色</Color>;
58
+ },
59
+ args: {
60
+ id: "some-id",
61
+ },
62
+ };
63
+
64
+ export const WithCustomDataAttribute: Story = {
65
+ render: (args) => {
66
+ return <Color {...args}>色</Color>;
67
+ },
68
+ args: {
69
+ "data-test-id": "some-id",
70
+ },
71
+ };
@@ -0,0 +1,28 @@
1
+ import { type FC, PropsWithChildren } from "react";
2
+ import styles from "./Color.module.css";
3
+ import { CustomDataAttributeProps } from "../../types/attributes";
4
+ import { TextColorVariant } from "../../types/style";
5
+ import { colorVariable } from "../../utils/style";
6
+
7
+ type Props = {
8
+ /**
9
+ * 文字色
10
+ * @default main
11
+ */
12
+ color?: TextColorVariant;
13
+ /**
14
+ * ネイティブ要素のid属性。ページで固有のIDを指定
15
+ */
16
+ id?: string;
17
+ } & CustomDataAttributeProps;
18
+
19
+ export const Color: FC<PropsWithChildren<Props>> = ({
20
+ color = "main",
21
+ children,
22
+ id,
23
+ ...otherProps
24
+ }) => (
25
+ <span id={id} className={styles.color} style={{ ...colorVariable(color) }} {...otherProps}>
26
+ {children}
27
+ </span>
28
+ );
@@ -0,0 +1,9 @@
1
+ .divider {
2
+ width: var(--width);
3
+ min-width: var(--min-width);
4
+ max-width: var(--max-width);
5
+ height: 1px;
6
+ margin: var(--margin-top) var(--margin-right) var(--margin-bottom) var(--margin-left);
7
+ border: 0;
8
+ border-top: var(--border-width) solid var(--border-color);
9
+ }
@@ -0,0 +1,42 @@
1
+ import { render, screen } from "@testing-library/react";
2
+ import { Divider } from "./Divider";
3
+
4
+ describe("<Divider>", () => {
5
+ it("receives date attribute", async () => {
6
+ render(<Divider data-testid="divider" />);
7
+ const divider = screen.getByTestId("divider");
8
+
9
+ expect(divider).toBeInTheDocument();
10
+ });
11
+
12
+ it("receives max-width", async () => {
13
+ render(<Divider data-testid="divider" maxWidth="400px" />);
14
+ const divider = screen.getByTestId("divider");
15
+
16
+ expect(divider).toHaveStyle("--max-width: 400px");
17
+ });
18
+
19
+ it("receives min-width", async () => {
20
+ render(<Divider data-testid="divider" minWidth="400px" />);
21
+ const divider = screen.getByTestId("divider");
22
+
23
+ expect(divider).toHaveStyle("--min-width: 400px");
24
+ });
25
+
26
+ it("receives width", async () => {
27
+ render(<Divider data-testid="divider" width="400px" />);
28
+ const divider = screen.getByTestId("divider");
29
+
30
+ expect(divider).toHaveStyle("--width: 400px");
31
+ });
32
+
33
+ it("receives margins", async () => {
34
+ render(<Divider data-testid="divider" mt="xxs" mr="xs" mb="sm" ml="md" />);
35
+ const divider = screen.getByTestId("divider");
36
+
37
+ expect(divider).toHaveStyle("--margin-top: var(--size-spacing-xxs)");
38
+ expect(divider).toHaveStyle("--margin-right: var(--size-spacing-xs)");
39
+ expect(divider).toHaveStyle("--margin-bottom: var(--size-spacing-sm)");
40
+ expect(divider).toHaveStyle("--margin-left: var(--size-spacing-md)");
41
+ });
42
+ });