Skip to content

Commit

Permalink
fix: update Pill component to support latest colors
Browse files Browse the repository at this point in the history
  • Loading branch information
xiaofan2406 committed Sep 12, 2024
1 parent 38f5641 commit bc50bc7
Show file tree
Hide file tree
Showing 12 changed files with 181 additions and 297 deletions.
43 changes: 42 additions & 1 deletion src/components/Pill/Pill.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
import React from 'react';
import type { Meta, StoryObj } from '@storybook/react';

import Pill from './index';

const meta = {
title: 'Pending Review/Pill',
title: 'Components/Pill',
component: Pill,
tags: ['autodocs'],
argTypes: {
onClick: { control: false },
},
args: {
inverse: false,
onClick: undefined,
size: 'medium',
},
} satisfies Meta<typeof Pill>;

export default meta;
Expand All @@ -17,3 +26,35 @@ export const Default: Story = {
children: 'Default',
},
};

export const Colors: Story = {
args: {
children: 'Colors',
},
argTypes: {
color: { control: false },
},
render: (args) => (
<div style={{ display: 'flex', gap: 12 }}>
<Pill {...args} color="default" />
<Pill {...args} color="primary" />
<Pill {...args} color="secondary" />
<Pill {...args} color="danger" />
<Pill {...args} color="info" />
<Pill {...args} color="success" />
<Pill {...args} color="warning" />
</div>
),
};

export const Inverse: Story = {
args: {
children: 'Inverse',
inverse: true,
},
argTypes: {
color: { control: false },
inverse: { control: false },
},
render: Colors.render,
};
24 changes: 16 additions & 8 deletions src/components/Pill/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,38 @@
import * as React from 'react';

export type PillClassName = string | string[];
export type PillColor = 'default' | 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info';

export type PillSize = 'large' | 'medium' | 'small';

export interface PillProps {
/**
* Content inside pill
*/
children: React.ReactNode;
children?: React.ReactNode;
/**
* Custom classnames
*/
className?: PillClassName;
/**
* Custome onClick event
* The main color for the pill
*/
onClick?: (...args: any[]) => any;
color?: PillColor;
/**
* one of ["large", "medium", "small"]
*/
size?: PillSize;
/**
* Inverse the background and content color
*/
inverse?: boolean;
/**
* Custom onClick event
*/
onClick?: (...args: any[]) => any;
/**
* Generate "data-test-selector" on the pill
*/
dts?: string;
/**
* Custom classnames
*/
className?: string;
}

declare const Pill: React.FC<PillProps>;
Expand Down
47 changes: 30 additions & 17 deletions src/components/Pill/index.jsx
Original file line number Diff line number Diff line change
@@ -1,46 +1,59 @@
import classnames from 'classnames';
import PropTypes from 'prop-types';
import React from 'react';
import PropTypes from 'prop-types';
import cx from 'classnames';
import { colors } from '../Button';
import { expandDts } from '../../utils';
import './styles.css';

const sizes = ['large', 'medium', 'small'];

const Pill = ({ className, children, onClick, size, dts }) => (
const Pill = ({ children, color = colors[0], size = sizes[1], inverse = false, onClick, dts, className, ...rest }) => (
<div
className={classnames('aui--pill', `aui--pill-${size}`, { 'aui--pill-clickable': onClick }, className)}
{...rest}
className={cx(
'aui--pill',
size !== sizes[1] && `aui-${size}`,
color !== colors[0] && `aui-${color}`,
inverse && 'aui-inverse',
onClick && 'aui-clickable',
className
)}
onClick={onClick}
{...expandDts(dts)}
>
<div className="aui--pill-children">{children}</div>
{children}
</div>
);

Pill.defaultProps = {
size: sizes[1],
};

Pill.propTypes = {
/**
* Content inside pill
* Content inside pill
*/
children: PropTypes.node.isRequired,
children: PropTypes.node,
/**
* Custom classnames
* The main color for the pill
*/
className: PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)]),
/**
* Custome onClick event
*/
onClick: PropTypes.func,
color: PropTypes.oneOf(colors),
/**
* one of ["large", "medium", "small"]
*/
size: PropTypes.oneOf(sizes),
/**
* Inverse the background and content color
*/
inverse: PropTypes.bool,
/**
* Custom onClick event
*/
onClick: PropTypes.func,
/**
* Generate "data-test-selector" on the pill
*/
dts: PropTypes.string,
/**
* Custom classnames
*/
className: PropTypes.string,
};

export default Pill;
35 changes: 18 additions & 17 deletions src/components/Pill/index.spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,34 @@ import React from 'react';
import { render, screen, user } from 'testing';
import Pill from '.';

it('should have default style', () => {
it('is not clickable by default', () => {
render(<Pill>Test</Pill>);
expect(screen.queryAllByClass('aui--pill aui--pill-medium')).toHaveLength(1);
expect(screen.queryAllByClass('aui--pill-children')).toHaveLength(1);
expect(screen.queryAllByClass('aui--pill-clickable')).toHaveLength(0);
expect(screen.getByClass('aui--pill-children')).toHaveTextContent('Test');
const pill = screen.getByClass('aui--pill');
expect(pill).not.toHaveClass('aui-clickable');
expect(pill).toHaveTextContent('Test');
});

it('should allow className prop', () => {
it('supports custom className', () => {
render(<Pill className="test">Test</Pill>);
expect(screen.queryAllByClass('aui--pill aui--pill-medium test')).toHaveLength(1);
expect(screen.getByClass('aui--pill')).toHaveClass('test');
});

it('should allow size prop', () => {
it('supports size prop', () => {
render(<Pill size="large">Test</Pill>);
expect(screen.queryAllByClass('aui--pill aui--pill-large')).toHaveLength(1);
expect(screen.getByClass('aui--pill')).toHaveClass('aui-large');
});

it('should allow onClick prop', async () => {
const onClickMock = jest.fn();
render(<Pill onClick={onClickMock}>Test</Pill>);
expect(screen.queryAllByClass('aui--pill aui--pill-medium aui--pill-clickable')).toHaveLength(1);
await user.click(screen.getByClass('aui--pill aui--pill-medium aui--pill-clickable'));
expect(onClickMock).toHaveBeenCalledTimes(1);
it('is clickable if onClick is given', async () => {
const onClick = jest.fn();
render(<Pill onClick={onClick}>Test</Pill>);
const pill = screen.getByClass('aui--pill');
expect(pill).toHaveClass('aui-clickable');

await user.click(pill);
expect(onClick).toHaveBeenCalledTimes(1);
});

it('should support custom dts', () => {
it('supports dts', () => {
render(<Pill dts="test-dts">Test</Pill>);
expect(screen.getByClass('aui--pill aui--pill-medium')).toHaveAttribute('data-test-selector', 'test-dts');
expect(screen.getByClass('aui--pill')).toHaveAttribute('data-test-selector', 'test-dts');
});
106 changes: 75 additions & 31 deletions src/components/Pill/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,46 +3,90 @@
.aui--pill {
display: inline-flex;
align-items: center;
justify-content: center;
border: 1px solid $color-border-base;
user-select: none;
font-weight: $font-weight-bold;
line-height: 1;
color: $color-text-base;
background-color: $color-white;
}
background-color: $color-default-accent;
padding: 5px 12px;
font-size: $font-size-base;
border-radius: $border-radius-round;

.aui--pill-children {
display: flex;
align-items: center;
justify-content: center;
}
&.aui-small {
padding: 2px 5px;
font-size: $font-size-small;
border-radius: $border-radius-base;
}

.aui--pill-clickable:hover,
.aui--pill-clickable:focus {
background-color: $color-grey-200;
cursor: pointer;
}
&.aui-large {
padding: 6px 20px;
font-size: $font-size-medium;
border-radius: $border-radius-round;
}

.aui--pill-small {
padding: 2px 5px;
font-size: $font-size-small;
border-radius: $border-radius-base;
line-height: 1;
}
&.aui-clickable:hover,
&.aui-clickable:focus {
cursor: pointer;
}

.aui--pill-small .aui--svg-symbol-component {
width: 12px;
height: 12px;
}
&.aui-primary {
background-color: $color-primary-accent;
border-color: $color-primary-accent;
}

.aui--pill-medium {
padding: 5px 12px;
font-size: $font-size-base;
border-radius: $border-radius-round;
}
&.aui-secondary {
background-color: $color-secondary-accent;
border-color: $color-secondary-accent;
}

.aui--pill-large {
padding: 6px 20px;
font-size: $font-size-medium;
border-radius: $border-radius-round;
&.aui-success {
background-color: $color-success-accent;
border-color: $color-success-accent;
}

&.aui-info {
background-color: $color-info-accent;
border-color: $color-info-accent;
}

&.aui-warning {
background-color: $color-warning-accent;
border-color: $color-warning-accent;
}

&.aui-danger {
background-color: $color-danger-accent;
border-color: $color-danger-accent;
}

&.aui-inverse {
border-color: $color-border-base;
background-color: $color-white;

&.aui-primary {
color: $color-primary-base;
}

&.aui-secondary {
color: $color-secondary-base;
}

&.aui-success {
color: $color-success-base;
}

&.aui-info {
color: $color-info-base;
}

&.aui-warning {
color: $color-warning-base;
}

&.aui-danger {
color: $color-danger-base;
}
}
}
19 changes: 0 additions & 19 deletions src/components/StatusPill/StatusPill.stories.tsx

This file was deleted.

Loading

0 comments on commit bc50bc7

Please sign in to comment.