Skip to content

Commit 1acaf24

Browse files
author
Kubit
committed
Add new label prop to Pill Component
1 parent aa83775 commit 1acaf24

File tree

8 files changed

+104
-45
lines changed

8 files changed

+104
-45
lines changed

src/components/pill/__tests__/pill.test.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ const mockProps = {
1313
variant: 'DEFAULT',
1414
size: 'LARGE',
1515
dataTestId: 'pillComponent',
16+
label: { content: 'label' },
1617
};
1718

1819
describe('Pill component', () => {

src/components/pill/pill.styled.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,14 @@ import { getStyles, getTypographyStyles } from '@/utils/getStyles/getStyles';
66

77
import type { IPillStyled } from './types';
88

9+
export const ParentContainerStyled = styled.div<IPillStyled>`
10+
${props => getStyles(props.styles?.parentContainer)}
11+
`;
12+
13+
export const LabelContainerStyled = styled.div<IPillStyled>`
14+
${props => getStyles(props.styles?.labelContainer)}
15+
`;
16+
917
export const PillStyled = styled.div<IPillStyled & { focus?: boolean }>`
1018
${props => getStyles(props.styles?.container)}
1119
&:focus-visible {

src/components/pill/pillStandAlone.tsx

Lines changed: 64 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,15 @@ import { InputTypeType } from '@/components/input';
55
import { useId } from '@/hooks';
66
import { pickAriaProps } from '@/utils/aria/aria';
77

8-
import { IconContainerStyled, PillInputStyled, PillLabelStyled, PillStyled } from './pill.styled';
8+
import { Text, TextComponentType } from '../text';
9+
import {
10+
IconContainerStyled,
11+
LabelContainerStyled,
12+
ParentContainerStyled,
13+
PillInputStyled,
14+
PillLabelStyled,
15+
PillStyled,
16+
} from './pill.styled';
917
import { IPillStandAlone } from './types';
1018
import { getPillState } from './utils';
1119

@@ -37,52 +45,65 @@ const PillStandAloneComponent = (
3745
const stateStyles = styles[state];
3846

3947
return (
40-
<PillStyled
41-
ref={ref}
42-
data-testid={dataTestId}
43-
styles={stateStyles}
44-
tabIndex={tabIndex}
45-
onKeyDown={onKeyDown?.(value || '')}
46-
>
47-
<PillInputStyled
48-
aria-checked={selected}
49-
{...ariaProps}
50-
checked={selected}
51-
data-testid={`${dataTestId}Input`}
52-
disabled={disabled}
53-
id={id}
54-
name={name}
48+
<ParentContainerStyled styles={stateStyles}>
49+
<PillStyled
50+
ref={ref}
51+
data-testid={dataTestId}
5552
styles={stateStyles}
56-
tabIndex={-1}
57-
type={component}
58-
value={value}
59-
onChange={onPillChange}
60-
onFocus={onFocus}
61-
/>
62-
{decorativeIcon && (
63-
<IconContainerStyled styles={stateStyles}>
53+
tabIndex={tabIndex}
54+
onKeyDown={onKeyDown?.(value || '')}
55+
>
56+
<PillInputStyled
57+
aria-checked={selected}
58+
{...ariaProps}
59+
checked={selected}
60+
data-testid={`${dataTestId}Input`}
61+
disabled={disabled}
62+
id={id}
63+
name={name}
64+
styles={stateStyles}
65+
tabIndex={-1}
66+
type={component}
67+
value={value}
68+
onChange={onPillChange}
69+
onFocus={onFocus}
70+
/>
71+
{decorativeIcon && (
72+
<IconContainerStyled styles={stateStyles}>
73+
<ElementOrIcon
74+
color={stateStyles?.decorativeIcon?.color}
75+
dataTestId={dataTestId + 'DecorativeIcon'}
76+
height={stateStyles?.decorativeIcon?.height}
77+
width={stateStyles?.decorativeIcon?.width}
78+
{...decorativeIcon}
79+
/>
80+
</IconContainerStyled>
81+
)}
82+
<PillLabelStyled htmlFor={id} styles={stateStyles}>
83+
{children}
84+
</PillLabelStyled>
85+
{selectedIcon && selected && (
6486
<ElementOrIcon
65-
color={stateStyles?.decorativeIcon?.color}
66-
dataTestId={dataTestId + 'DecorativeIcon'}
67-
height={stateStyles?.decorativeIcon?.height}
68-
width={stateStyles?.decorativeIcon?.width}
69-
{...decorativeIcon}
87+
color={stateStyles?.selectedIcon?.color}
88+
dataTestId={dataTestId + 'SelectedIcon'}
89+
height={stateStyles?.selectedIcon?.height}
90+
width={stateStyles?.selectedIcon?.width}
91+
{...selectedIcon}
7092
/>
71-
</IconContainerStyled>
72-
)}
73-
<PillLabelStyled htmlFor={id} styles={stateStyles}>
74-
{children}
75-
</PillLabelStyled>
76-
{selectedIcon && selected && (
77-
<ElementOrIcon
78-
color={stateStyles?.selectedIcon?.color}
79-
dataTestId={dataTestId + 'SelectedIcon'}
80-
height={stateStyles?.selectedIcon?.height}
81-
width={stateStyles?.selectedIcon?.width}
82-
{...selectedIcon}
83-
/>
93+
)}
94+
</PillStyled>
95+
{props.label?.content && props.label.content !== null && (
96+
<LabelContainerStyled styles={stateStyles}>
97+
<Text
98+
component={TextComponentType.PARAGRAPH}
99+
customTypography={stateStyles?.labelContent}
100+
{...props.label}
101+
>
102+
{props.label.content}
103+
</Text>
104+
</LabelContainerStyled>
84105
)}
85-
</PillStyled>
106+
</ParentContainerStyled>
86107
);
87108
};
88109

src/components/pill/stories/argtypes.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,17 @@ export const argtypes = (
4242
category: CATEGORY_CONTROL.CONTENT,
4343
},
4444
},
45+
label: {
46+
description: 'Label outside of the pill',
47+
type: { name: 'string' },
48+
control: { type: 'text' },
49+
table: {
50+
type: {
51+
summary: 'string',
52+
},
53+
category: CATEGORY_CONTROL.CONTENT,
54+
},
55+
},
4556
initialState: {
4657
description: 'Boolean to indicate if Pill is selected initially',
4758
type: { name: 'boolean' },

src/components/pill/stories/pill.stories.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ const commonArgs: IPillUnControlled = {
3232
children: 'Pill',
3333
decorativeIcon: { icon: ICONS.ICON_PLACEHOLDER },
3434
selectedIcon: { icon: ICONS.ICON_PLACEHOLDER },
35+
dataTestId: 'PillTestId',
36+
label: {
37+
content: 'Label',
38+
},
3539
};
3640

3741
export const Pill: Story = {

src/components/pill/types/pill.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import * as React from 'react';
22

33
import { IElementOrIcon } from '@/components/elementOrIcon';
4+
import { IText } from '@/components/text';
45
import { CustomTokenTypes } from '@/types';
56

67
import type { PillStateStylesType, PillStylesType, PillVariantStylesType } from './pillTheme';
@@ -19,6 +20,10 @@ type PillAriaAttributes = Pick<
1920
| 'aria-disabled'
2021
>;
2122

23+
export type PillTextType = Omit<IText<string>, 'children'> & {
24+
content: React.ReactNode;
25+
};
26+
2227
export interface IPillStandAlone extends PillAriaAttributes {
2328
styles: PillVariantStylesType;
2429
onFocus?: React.FocusEventHandler<HTMLInputElement>;
@@ -34,6 +39,7 @@ export interface IPillStandAlone extends PillAriaAttributes {
3439
name?: string;
3540
tabIndex?: number;
3641
value?: string;
42+
label?: PillTextType;
3743
}
3844
export interface IPillControlled
3945
extends Omit<IPillStandAlone, 'styles' | 'onPillChange'>,

src/components/pill/types/pillTheme.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { CommonStyleType, IconTypes, TypographyTypes } from '@/types';
33
import type { PillStateType } from './state';
44

55
export type PillStateStylesType = {
6+
parentContainer?: CommonStyleType;
67
altVariant?: boolean;
78
container?: CommonStyleType;
89
container_focus?: {
@@ -14,7 +15,11 @@ export type PillStateStylesType = {
1415
decorativeIconContainer?: CommonStyleType;
1516
decorativeIcon?: IconTypes;
1617
selectedIcon?: IconTypes;
18+
// deprecated - "label" prop is applied to children. Change this name.
1719
label?: TypographyTypes;
20+
// deprecated - "labelContent" should be called "label". Change this name.
21+
labelContent?: TypographyTypes;
22+
labelContainer?: CommonStyleType;
1823
};
1924

2025
export type PillVariantStylesType = {

src/components/pillSelector/pillSelectorStandAlone.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,19 +52,22 @@ const PillSelectorStandAloneComponent = (
5252
)}
5353
{props.pills.length > 1 && props.pills.length <= maxPills
5454
? props.pills.map((pill, index) => {
55+
// deprecated - remove this line when this props are changed
56+
const { label, externalLabel, ...rest } = pill;
5557
const pillSelected = props.pillSelected?.includes(pill.value.toString());
5658
return (
5759
(props.pillSize || pill?.size) && (
5860
<Pill
5961
key={pill.value}
6062
dataTestId={`${dataTestId}Pill${index}`}
6163
focus={focus === index}
64+
label={externalLabel}
6265
multiSelect={props.multiSelect}
6366
name={props.name}
6467
selected={pillSelected}
6568
size={props.pillSize || ''}
6669
tabIndex={pillSelected || (!isPillSelected && index === 0) ? 0 : -1}
67-
{...pill}
70+
{...rest}
6871
value={pill.value.toString()}
6972
variant={props.pillVariant}
7073
onFocus={() => {
@@ -74,7 +77,7 @@ const PillSelectorStandAloneComponent = (
7477
}}
7578
onPillChange={props.onPillChange}
7679
>
77-
{pill.label}
80+
{label}
7881
</Pill>
7982
)
8083
);

0 commit comments

Comments
 (0)