Skip to content

Commit 7078736

Browse files
committed
💄 Add disable checkbox to props and modify flex property
1 parent 7cc7937 commit 7078736

File tree

4 files changed

+86
-34
lines changed

4 files changed

+86
-34
lines changed

src/components/DualListBox/DualListBox.stories.tsx

+70-27
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import DualListBox, {
55
DualListBoxItem,
66
DualListBoxProps,
77
} from "./DualListBox";
8-
import { ActionButton, Flex, Icon, Typography } from "..";
8+
import { ActionButton, Flex, Icon, Spacer, Typography } from "..";
99
import { useTheme } from "../../themes";
1010

1111
export default {
@@ -174,9 +174,8 @@ export const Nested: StoryObj<DualListBoxProps> = {
174174
};
175175

176176
/**
177-
* props に onAdd / onRemove を渡さない
178177
* 規定の Checkbox による選択・選択解除ではなく
179-
* DualListBoxItem Button を配置して選択・選択解除を行う
178+
* DualListBoxItem に配置した Button による選択・選択解除を行う
180179
*/
181180
export const WithoutCheckbox: StoryObj<DualListBoxProps> = {
182181
render: () => {
@@ -200,71 +199,115 @@ export const WithoutCheckbox: StoryObj<DualListBoxProps> = {
200199
[],
201200
);
202201

203-
const [selectedIds, setSelectedIds] = React.useState<string[]>([
204-
items[2].id,
205-
]);
202+
const [allowedIds, setAllowedIds] = React.useState<string[]>([items[2].id]);
206203

207-
const handleAdd = (id: string) => {
208-
setSelectedIds((prevState) => {
204+
const [disallowedIds, setDisallowedIds] = React.useState<string[]>([]);
205+
206+
const handleAllow = (id: string) => {
207+
setAllowedIds((prevState) => {
209208
if (prevState.includes(id)) {
210209
return prevState;
211210
}
212211
return [...prevState, id];
213212
});
214213
};
215214

216-
const handleRemove = (id: string) => {
217-
setSelectedIds((prevState) =>
218-
prevState.filter((selectedId) => selectedId !== id),
215+
const handleDisallow = (id: string) => {
216+
setDisallowedIds((prevState) => {
217+
if (prevState.includes(id)) {
218+
return prevState;
219+
}
220+
return [...prevState, id];
221+
});
222+
};
223+
224+
const handleRemove = (item: DualListBoxItem) => {
225+
setAllowedIds((prevState) =>
226+
prevState.filter((selectedId) => selectedId !== item.id),
227+
);
228+
setDisallowedIds((prevState) =>
229+
prevState.filter((selectedId) => selectedId !== item.id),
219230
);
220231
};
221232

222233
const candidateItems = React.useMemo(
223234
() =>
224235
items
225-
.filter((item) => !selectedIds.includes(item.id))
236+
.filter(
237+
(item) =>
238+
!allowedIds.includes(item.id) && !disallowedIds.includes(item.id),
239+
)
226240
.map((item) => ({
227241
id: item.id,
228242
content: (
229-
<Flex alignItems="center" display="flex" gap={1}>
243+
<Flex alignItems="center" display="flex" flex={1} gap={1}>
230244
<Typography>{item.content}</Typography>
231-
<ActionButton
232-
color="primary"
233-
onClick={() => handleAdd(item.id)}
245+
<Flex
246+
alignItems="center"
247+
display="flex"
248+
flex={1}
249+
justifyContent="flex-end"
250+
gap={1}
234251
>
235-
<Icon color="active" name="check_thin" />
236-
</ActionButton>
252+
<ActionButton
253+
color="primary"
254+
onClick={() => handleAllow(item.id)}
255+
>
256+
<Icon color="active" name="check_thin" />
257+
</ActionButton>
258+
<ActionButton
259+
color="warning"
260+
onClick={() => handleDisallow(item.id)}
261+
>
262+
<Icon color={theme.palette.danger.main} name="forbid" />
263+
</ActionButton>
264+
</Flex>
237265
</Flex>
238266
),
239267
})),
240-
[items, selectedIds],
268+
[allowedIds, disallowedIds, items, theme.palette.danger.main],
241269
);
242270

243271
const selectedItems = React.useMemo(
244272
() =>
245273
items
246-
.filter((item) => selectedIds.includes(item.id))
274+
.filter(
275+
(item) =>
276+
allowedIds.includes(item.id) || disallowedIds.includes(item.id),
277+
)
247278
.map((item) => ({
248279
id: item.id,
249280
content: (
250-
<Flex alignItems="center" display="flex" gap={1}>
281+
<Flex alignItems="center" display="flex" flex={1} gap={1}>
251282
<Typography>{item.content}</Typography>
252-
<ActionButton
253-
color="warning"
254-
onClick={() => handleRemove(item.id)}
283+
<Flex
284+
alignItems="center"
285+
display="flex"
286+
flex={1}
287+
justifyContent="flex-end"
288+
gap={1}
255289
>
256-
<Icon color={theme.palette.danger.main} name="delete_bin" />
257-
</ActionButton>
290+
<Spacer pr={2}>
291+
{allowedIds.includes(item.id) && (
292+
<Icon color="active" name="check_thin" />
293+
)}
294+
{disallowedIds.includes(item.id) && (
295+
<Icon color={theme.palette.danger.main} name="forbid" />
296+
)}
297+
</Spacer>
298+
</Flex>
258299
</Flex>
259300
),
260301
})),
261-
[items, selectedIds, theme.palette.danger.main],
302+
[allowedIds, disallowedIds, items, theme.palette.danger.main],
262303
);
263304

264305
return (
265306
<DualListBox
266307
candidateItems={candidateItems}
308+
disableCheckbox={true}
267309
selectedItems={selectedItems}
310+
onRemove={handleRemove}
268311
/>
269312
);
270313
},

src/components/DualListBox/DualListBox.tsx

+3
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export type DualListBoxCandidateItem = DualListBoxItem & {
1919
export type DualListBoxProps = {
2020
candidateItems: DualListBoxCandidateItem[];
2121
selectedItems: DualListBoxItem[];
22+
disableCheckbox?: boolean;
2223
onAdd?: (item: DualListBoxItem) => void;
2324
onRemove?: (item: DualListBoxItem) => void;
2425
};
@@ -36,6 +37,7 @@ const DualListBox = React.forwardRef<HTMLDivElement, DualListBoxProps>(
3637
candidateItems: candidateItemsProp,
3738
selectedItems,
3839
selectedItemTitle,
40+
disableCheckbox,
3941
onAdd: handleAdd,
4042
onRemove: handleRemove,
4143
} = useLocaleProps({ props: inProps, name: "DualListBox" });
@@ -50,6 +52,7 @@ const DualListBox = React.forwardRef<HTMLDivElement, DualListBoxProps>(
5052
return (
5153
<Styled.Container>
5254
<CandidateRenderer
55+
disableCheckbox={disableCheckbox}
5356
items={candidateItems}
5457
onAdd={handleAdd}
5558
onRemove={handleRemove}

src/components/DualListBox/internal/CandidateRenderer/CandidateRenderer.tsx

+8-2
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ import { DualListBoxCandidateItem, DualListBoxItem } from "../../DualListBox";
88
*/
99
export const CandidateRenderer: React.FunctionComponent<{
1010
items: DualListBoxCandidateItem[];
11+
disableCheckbox?: boolean;
1112
onAdd?: (item: DualListBoxItem) => void;
1213
onRemove?: (item: DualListBoxItem) => void;
13-
}> = ({ items, onAdd, onRemove }) => {
14+
}> = ({ disableCheckbox, items, onAdd, onRemove }) => {
1415
return (
1516
<Styled.Container>
1617
{items.map((item, i) => (
@@ -39,7 +40,12 @@ export const CandidateRenderer: React.FunctionComponent<{
3940
key={item.id}
4041
isLastIndex={i + 1 === items.length}
4142
>
42-
<SelectLabel item={item} onAdd={onAdd} onRemove={onRemove}>
43+
<SelectLabel
44+
disableCheckbox={disableCheckbox}
45+
item={item}
46+
onAdd={onAdd}
47+
onRemove={onRemove}
48+
>
4349
{item.content}
4450
</SelectLabel>
4551
</Styled.UnselectedItem>

src/components/DualListBox/internal/CandidateRenderer/internal/SelectLabel/SelectLabel.tsx

+5-5
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,18 @@ import React from "react";
22
import Flex from "../../../../../Flex/Flex";
33
import { CandidateItem, DualListBoxItem } from "../../../../DualListBox";
44
import Checkbox from "../../../../../Checkbox/Checkbox";
5-
import Typography from "../../../../../Typography/Typography";
65

76
export const SelectLabel: React.FunctionComponent<{
87
item: CandidateItem;
8+
disableCheckbox?: boolean;
99
onAdd?: (item: DualListBoxItem) => void;
1010
onRemove?: (item: DualListBoxItem) => void;
1111
children: React.ReactNode;
12-
}> = ({ children, item, onAdd, onRemove }) => {
12+
}> = ({ children, disableCheckbox = false, item, onAdd, onRemove }) => {
1313
return (
1414
<Flex display="flex" justifyContent="space-between">
15-
{item.items || !onAdd ? (
16-
<Typography>{children}</Typography>
15+
{item.items || disableCheckbox ? (
16+
children
1717
) : (
1818
<Checkbox
1919
checked={item?.selected ?? false}
@@ -26,7 +26,7 @@ export const SelectLabel: React.FunctionComponent<{
2626
onAdd?.(item);
2727
}}
2828
>
29-
<Typography>{children}</Typography>
29+
{children}
3030
</Checkbox>
3131
)}
3232
</Flex>

0 commit comments

Comments
 (0)