Skip to content

Commit 936a23d

Browse files
authored
Merge pull request #2431 from dxc-technology/PelayoFelgueroso/chip-redesign
[major] Reimplement Chip component
2 parents bb22812 + a2280a8 commit 936a23d

24 files changed

Lines changed: 885 additions & 563 deletions

apps/website/screens/components/chip/ChipPageLayout.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@ const ChipPageHeading = ({ children }: { children: ReactNode }) => {
1616
<DxcFlex direction="column" gap="var(--spacing-gap-xl)">
1717
<ComponentHeading name="Chip" />
1818
<DxcParagraph>
19-
A chip is a compact, interactive UI element used to represent small pieces of information, actions, or
20-
selections.
19+
A chip is a compact element used to label, filter, or represent pieces of information within an interface.
2120
</DxcParagraph>
2221
<TabsPageHeading tabs={tabs} />
2322
</DxcFlex>

apps/website/screens/components/chip/code/ChipCodePage.tsx

Lines changed: 62 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,11 @@ import { DxcFlex, DxcLink, DxcTable } from "@dxc-technology/halstack-react";
22
import QuickNavContainer from "@/common/QuickNavContainer";
33
import DocFooter from "@/common/DocFooter";
44
import Example from "@/common/example/Example";
5-
import basicUsage from "./examples/basicUsage";
6-
import icons from "./examples/icons";
75
import Code, { ExtendedTableCode, TableCode } from "@/common/Code";
86
import StatusBadge from "@/common/StatusBadge";
9-
import avatar from "./examples/avatar";
107
import Link from "next/link";
11-
12-
const actionTypeString = `{
13-
icon?: string | (React.ReactNode
14-
& React.SVGProps<SVGSVGElement>);
15-
onClick: () => void;
16-
title?: string;
17-
}`;
8+
import dismissible from "./examples/dismissible";
9+
import selectable from "./examples/selectable";
1810

1911
const prefixTypeString = `| string
2012
| SVG
@@ -26,7 +18,7 @@ const avatarPropsString = `{
2618
| 'error';
2719
icon?: string | SVG;
2820
imgSrc?: string;
29-
label?: string;
21+
profileName?: string;
3022
};`;
3123

3224
const sections = [
@@ -44,50 +36,67 @@ const sections = [
4436
</thead>
4537
<tbody>
4638
<tr>
39+
<td>disabled</td>
4740
<td>
48-
<DxcFlex direction="column" gap="var(--spacing-gap-xs)" alignItems="baseline">
49-
<StatusBadge status="new" />
50-
action
51-
</DxcFlex>
41+
<TableCode>boolean</TableCode>
5242
</td>
5343
<td>
54-
<ExtendedTableCode>{actionTypeString}</ExtendedTableCode>
44+
If true, the component will be disabled. When mode is <Code>"dismissible"</Code>, the chip cannot be
45+
disabled.
46+
</td>
47+
<td>
48+
<TableCode>false</TableCode>
5549
</td>
56-
<td>Action to be displayed on the right side of the chip after the label.</td>
57-
<td>-</td>
5850
</tr>
5951
<tr>
60-
<td>disabled</td>
52+
<td>label</td>
6153
<td>
62-
<TableCode>boolean</TableCode>
54+
<TableCode>string</TableCode>
6355
</td>
64-
<td>If true, the component will be disabled.</td>
6556
<td>
66-
<TableCode>false</TableCode>
57+
Text to be placed on the chip. When using an avatar as prefix or when mode is <Code>"dismissible"</Code>,
58+
the label is required to ensure proper accessibility.
6759
</td>
60+
<td>-</td>
6861
</tr>
6962
<tr>
7063
<td>
7164
<DxcFlex direction="column" gap="var(--spacing-gap-xs)" alignItems="baseline">
72-
<StatusBadge status="required" />
73-
label
65+
<StatusBadge status="new" />
66+
mode
7467
</DxcFlex>
7568
</td>
7669
<td>
77-
<TableCode>string</TableCode>
70+
<TableCode>"selectable" | "dismissible"</TableCode>
71+
</td>
72+
<td>
73+
Determines the visual style and functionality of the chip. Available modes are:
74+
<ul>
75+
<li>
76+
<strong>selectable</strong>: The whole chip is an interactive element that allows users to activate or
77+
clear options directly within the interface.
78+
</li>
79+
<li>
80+
<strong>dismissible</strong>: Dismissible chip is used to represent information generated by user
81+
input within an interface.
82+
</li>
83+
</ul>
84+
</td>
85+
<td>
86+
<TableCode>"selectable"</TableCode>
7887
</td>
79-
<td>Text to be placed on the chip.</td>
80-
<td>-</td>
8188
</tr>
8289
<tr>
83-
<td>margin</td>
8490
<td>
85-
<TableCode>'xxsmall' | 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge' | 'xxlarge' | Margin</TableCode>
91+
<DxcFlex direction="column" gap="var(--spacing-gap-xs)" alignItems="baseline">
92+
<StatusBadge status="new" />
93+
onClick
94+
</DxcFlex>
8695
</td>
8796
<td>
88-
Size of the margin to be applied to the component. You can pass an object with 'top', 'bottom', 'left' and
89-
'right' properties in order to specify different margin sizes.
97+
<TableCode>{"() => void"}</TableCode>
9098
</td>
99+
<td>Function to be called when the chip is clicked or the dismiss action is triggered.</td>
91100
<td>-</td>
92101
</tr>
93102
<tr>
@@ -119,14 +128,30 @@ const sections = [
119128
</td>
120129
<td>-</td>
121130
</tr>
131+
<tr>
132+
<td>
133+
<DxcFlex direction="column" gap="var(--spacing-gap-xs)" alignItems="baseline">
134+
<StatusBadge status="new" />
135+
selected
136+
</DxcFlex>
137+
</td>
138+
<td>
139+
<TableCode>boolean</TableCode>
140+
</td>
141+
<td>
142+
If true, the component will be selected. If undefined, the component manages its own internal state
143+
(uncontrolled mode). This property is only applicable when the mode is <Code>"selectable"</Code>.
144+
</td>
145+
<td>-</td>
146+
</tr>
122147
<tr>
123148
<td>tabIndex</td>
124149
<td>
125150
<TableCode>number</TableCode>
126151
</td>
127152
<td>
128-
Value of the <Code>tabindex</Code> attribute applied to both the component and the prefix and suffix icons
129-
when a function is given.
153+
Value of the <Code>tabindex</Code> attribute applied to the component when mode is{" "}
154+
<Code>"selectable"</Code> and clear icon when mode is <Code>"dismissible"</Code>.
130155
</td>
131156
<td>
132157
<TableCode>0</TableCode>
@@ -140,22 +165,14 @@ const sections = [
140165
title: "Examples",
141166
subSections: [
142167
{
143-
title: "Basic usage",
144-
content: <Example example={basicUsage} defaultIsVisible />,
145-
},
146-
{
147-
title: "Icons",
148-
content: (
149-
<>
150-
<Example example={icons} defaultIsVisible />
151-
</>
152-
),
168+
title: "Selectable",
169+
content: <Example example={selectable} defaultIsVisible />,
153170
},
154171
{
155-
title: "Avatar",
172+
title: "Dismissible",
156173
content: (
157174
<>
158-
<Example example={avatar} defaultIsVisible />
175+
<Example example={dismissible} defaultIsVisible />
159176
</>
160177
),
161178
},

apps/website/screens/components/chip/code/examples/avatar.tsx

Lines changed: 0 additions & 34 deletions
This file was deleted.

apps/website/screens/components/chip/code/examples/basicUsage.tsx

Lines changed: 0 additions & 21 deletions
This file was deleted.
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import { DxcChip, DxcFlex, DxcInset, DxcSelect } from "@dxc-technology/halstack-react";
2+
import { useState } from "react";
3+
4+
type Option = { label: string; value: string; icon: string };
5+
6+
const options: Option[] = [
7+
{ label: "Electric Car", value: "car", icon: "electric_car" },
8+
{ label: "Motorcycle", value: "motorcycle", icon: "Motorcycle" },
9+
{ label: "Train", value: "train", icon: "train" },
10+
{ label: "Bike", value: "bike", icon: "pedal_bike" },
11+
];
12+
13+
const findOptionByValue = (value: string): Option | null => options.find((opt) => opt.value === value) ?? null;
14+
15+
type TransportSelectProps = {
16+
selectedOptions: Option[];
17+
onChange: (selected: Option[]) => void;
18+
};
19+
20+
const TransportSelect = ({ selectedOptions, onChange }: TransportSelectProps) => {
21+
const handleSelectChange = ({ value }: { value: string | string[] }) => {
22+
if (Array.isArray(value)) {
23+
onChange(value.map((val) => findOptionByValue(val)).filter(Boolean) as Option[]);
24+
}
25+
};
26+
27+
return (
28+
<DxcSelect
29+
label="Select your favourite hobbies"
30+
placeholder="Choose your hobbies"
31+
options={options}
32+
onChange={handleSelectChange}
33+
value={selectedOptions.map((opt) => opt.value)}
34+
multiple
35+
enableSelectAll
36+
/>
37+
);
38+
};
39+
40+
const code = `() => {
41+
const [selectedOptions, setSelectedOptions] = useState([options[0], options[2]]);
42+
43+
const handleDismiss = (valueToRemove) => {
44+
setSelectedOptions(selectedOptions.filter(opt => opt.value !== valueToRemove));
45+
};
46+
47+
return (
48+
<DxcInset space="var(--spacing-padding-xl)">
49+
<DxcFlex direction="column" gap="var(--spacing-gap-m)">
50+
<TransportSelect selectedOptions={selectedOptions} onChange={setSelectedOptions} />
51+
52+
{selectedOptions.length > 0 && (
53+
<DxcFlex gap="var(--spacing-gap-s)" wrap="wrap">
54+
{selectedOptions.map((option) => (
55+
<DxcChip
56+
key={option.value}
57+
mode="dismissible"
58+
label={option.label}
59+
prefix={option.icon}
60+
onClick={() => handleDismiss(option.value)}
61+
/>
62+
))}
63+
</DxcFlex>
64+
)}
65+
</DxcFlex>
66+
</DxcInset>
67+
);
68+
}`;
69+
70+
const scope = {
71+
DxcChip,
72+
DxcInset,
73+
DxcFlex,
74+
useState,
75+
options,
76+
TransportSelect,
77+
};
78+
79+
export default { code, scope };

apps/website/screens/components/chip/code/examples/icons.tsx

Lines changed: 0 additions & 34 deletions
This file was deleted.

0 commit comments

Comments
 (0)