Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Chip #11

Merged
merged 9 commits into from
Apr 14, 2021
20 changes: 20 additions & 0 deletions packages/react-components/src/Chip/chip.story.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import * as React from 'react';
import { Chip } from './index';

export const Playground = (args: any) => (
<Chip
{...args}
/>
);

Playground.args = {
children: 'Hello',
};

export default {
title: 'Components/Chip',
component: Chip,
argTypes: {
children: { control: 'text' },
},
};
149 changes: 149 additions & 0 deletions packages/react-components/src/Chip/chip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
import * as React from 'react';
import { css, cx } from '../styles';
import { Typography } from '../Typography';
import { CheckmarkIcon } from '../icons';

type BaseProps = {
/**
* The content of the component.
*/
children: React.ReactNode;
/**
* If `true`, the chip will be disabled.
*/
disabled?: boolean;
/**
* The variant to use.
*/
variant?: ('choice' | 'filter');
/**
* If `true`, the chip will be selected.
*/
selected: boolean;
/**
* The className of the component.
*/
className?: string;
dataTestId?: string;
};

type ChipProps = BaseProps & React.ButtonHTMLAttributes<HTMLButtonElement>;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now Chip component can use props from HTMLButtonElement, but you forgot to add ...other props to your root element.


const stylesBase = () => css({
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Chip it's an inline component (from mockup):

image

Current solution broken with multiple elements:
image

label: 'Chip',
display: 'inline-flex',
alignItems: 'center',
fontFamily: 'inherit',
outline: 'none',
boxSizing: 'border-box',
borderStyle: 'solid',
borderWidth: '1px',
borderColor: 'var(--pv-color-gray-6)',
borderRadius: '15px',
padding: '0 10px',
height: '30px',
backgroundColor: 'transparent',
color: 'var(--pv-color-gray-9)',
transition: 'background-color 200ms, color 200ms, border-color 200ms',
margin: '0 5px',
'&:disabled': {
cursor: 'not-allowed',
color: 'var(--pv-color-gray-7)',
borderColor: 'var(--pv-color-gray-4)',
backgroundColor: 'transparent',
},
});

const stylesEffects = () => css({
label: 'effects',
cursor: 'pointer',
'&:not(:disabled)': {
'&:hover': {
backgroundColor: 'var(--pv-color-gray-3)',
color: 'var(--pv-color-gray-9)',
},
'&:focus': {
backgroundColor: 'var(--pv-color-gray-5)',
color: 'var(--pv-color-black)',
borderColor: 'var(--pv-color-gray-9)',
},
'&:active': {
backgroundColor: 'var(--pv-color-gray-4)',
color: 'var(--pv-color-gray-9)',
borderColor: 'var(--pv-color-gray-9)',
},
},
});

const stylesChoiceSelected = () => css({
label: 'choice-selected',
backgroundColor: 'var(--pv-color-secondary-tint-5)',
color: 'var(--pv-color-secondary)',
borderColor: 'var(--pv-color-secondary-tint-3)',
});

const stylesFilterSelected = () => css({
label: 'filter-selected',
backgroundColor: 'var(--pv-color-gray-4)',
color: 'var(--pv-color-black)',
borderColor: 'var(--pv-color-gray-7)',
});

const stylesIcon = () => css({
label: 'Chip-icon',
marginRight: '10px',
display: 'flex',
alignItems: 'center',
});

export const Chip = React.forwardRef<HTMLButtonElement, ChipProps>((props, ref) => {
donskov marked this conversation as resolved.
Show resolved Hide resolved
const {
children,
className,
dataTestId,
disabled,
variant,
selected,
tabIndex,
...other
} = props;
const isChoice = variant === 'choice';

const Icon = selected && !isChoice && (
<div className={cx(stylesIcon())}>
<CheckmarkIcon />
</div>
);

return (
<button
{...other}
disabled={disabled}
ref={ref}
type="button"
className={cx({
[stylesBase()]: true,
[stylesChoiceSelected()]: selected && isChoice,
[stylesFilterSelected()]: selected && !isChoice,
[stylesEffects()]: !selected || !isChoice,
[className]: !!className,
})}
tabIndex={selected && isChoice ? -1 : tabIndex}
data-testid={dataTestId}
>
{Icon}
<Typography
variant="b3"
>
{children}
</Typography>
</button>
);
});

Chip.displayName = 'Chip';

Chip.defaultProps = {
disabled: false,
variant: 'choice',
};
1 change: 1 addition & 0 deletions packages/react-components/src/Chip/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { Chip } from './chip';
18 changes: 18 additions & 0 deletions packages/react-components/src/icons/checkmark_icon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import React from 'react';

type IconProps = React.HTMLAttributes<HTMLOrSVGElement>;

export const CheckmarkIcon: React.FC<IconProps> = (props) => (
<svg
{...props}
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 20 20"
width="20px"
>
<path
fill="currentColor"
d="M3.6 9.7l4.9 4.6c.4.4 1 .4 1.4 0l5.9-7v-.6l-.4-.3a.4.4 0 00-.6 0L9.1 13 4.5 8.8a.4.4 0 00-.6 0l-.3.3c-.2.2-.2.5 0 .6z"
/>
</svg>
);
1 change: 1 addition & 0 deletions packages/react-components/src/icons/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { CheckmarkIcon } from './checkmark_icon';
1 change: 1 addition & 0 deletions packages/react-components/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export * from './Avatar';
export * from './Box';
export * from './Button';
export * from './Chip';
export * from './Collapse';
export * from './Drawer';
export * from './Fab';
Expand Down