Skip to content

Commit

Permalink
feat: Add ChipList component (#404)
Browse files Browse the repository at this point in the history
  • Loading branch information
floreks authored Feb 6, 2023
1 parent 4efaa3c commit 042f0e4
Show file tree
Hide file tree
Showing 2 changed files with 201 additions and 0 deletions.
74 changes: 74 additions & 0 deletions src/components/ChipList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { Flex, Span } from 'honorable'
import { ReactElement, useMemo, useState } from 'react'

import { HamburgerMenuCollapseIcon } from '../icons'

import Chip, { ChipProps } from './Chip'
import { useFillLevel } from './contexts/FillLevelContext'

type TransformFn<TValue> = (value: TValue) => string

export type ChipListProps<TValue> = {
values: Array<TValue>
transform?: TransformFn<TValue>
limit: number
} & ChipProps

function ChipList<TValue = string>({
values = [], transform, limit = 4, ...props
}: ChipListProps<TValue>): ReactElement {
const [collapsed, setCollapsed] = useState(true)
const parentFillLevel = useFillLevel()
const fillLevelClassName = useMemo(() => {
switch (parentFillLevel) {
case 0:
return 'fill-zero'
case 1:
return 'fill-one'
case 2:
return 'fill-two'
case 3:
return 'fill-three'
}
}, [parentFillLevel])

return (
<Flex
gap="xsmall"
wrap
>
{values.length === 0 && (
<Span body2>There is nothing to display here.</Span>
)}
{values.slice(0, collapsed ? limit : undefined).map(v => (
<Chip {...props}>
{transform ? transform(v) : `${v}`}
</Chip>
))}
{values.length > limit && (
<>
{collapsed && (
<Chip
onClick={() => setCollapsed(false)}
{...props}
clickable
background={fillLevelClassName}
> {`+${values.length - limit}`}
</Chip>
)}
{!collapsed && (
<Chip
onClick={() => setCollapsed(true)}
{...props}
clickable
background={fillLevelClassName}
><HamburgerMenuCollapseIcon />
</Chip>
)}
</>
)}
</Flex>
)
}

export default ChipList
127 changes: 127 additions & 0 deletions src/stories/ChipList.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import { ComponentProps } from 'react'

import Chip from '../components/Chip'
import Card from '../components/Card'
import ChipList from '../components/ChipList'

const sizes: ComponentProps<typeof Chip>['size'][] = [
'small',
'medium',
'large',
]

const severities: ComponentProps<typeof Chip>['severity'][] = [
'neutral',
'info',
'success',
'warning',
'error',
'critical',
]

export default {
title: 'ChipList',
component: ChipList,
argTypes: {
size: {
options: sizes,
},
severity: {
options: severities,
},
onFillLevel: {
options: [0, 1, 2, 3],
control: {
type: 'select',
labels: {
0: '0',
1: '1',
2: '2',
3: "3 - Shouldn't be used",
},
},
},
},
}

function TextTemplate({ onFillLevel, ...args }: any) {
const VALUES = ['avengers', 'iron man', 'doctor strange', 'thor', 'black panther', 'guardians of the galaxy']

return (
<Card
width="600px"
padding="medium"
fillLevel={onFillLevel}
>
<ChipList
values={VALUES}
{...args}
/>
</Card>
)
}

interface Label {
key?: string,
value: string
}

function LabelTemplate({ onFillLevel, ...args }: any) {
const VALUES: Array<Label> = [
{ key: 'app', value: 'plural' },
{ key: 'version', value: 'v1.8.11' },
{ key: 'managed-by', value: 'helm' },
{ key: 'controlled-by', value: 'deployment-1234' },
{ value: 'just-a-value' },
]

return (
<Card
width="600px"
padding="medium"
fillLevel={onFillLevel}
>
<ChipList<Label>
values={VALUES}
transform={v => `${v.key?.concat(':') ?? ''} ${v.value}`}
{...args}
/>
</Card>
)
}

function EmptyTemplate({ onFillLevel, ...args }: any) {
return (
<Card
width="600px"
padding="medium"
fillLevel={onFillLevel}
>
<ChipList
values={[]}
{...args}
/>
</Card>
)
}

export const Text = TextTemplate.bind({})
Text.args = {
severity: 'info',
size: 'small',
onFillLevel: 0,
}

export const Label = LabelTemplate.bind({})
Label.args = {
severity: 'info',
size: 'small',
onFillLevel: 0,
}

export const Empty = EmptyTemplate.bind({})
Empty.args = {
severity: 'info',
size: 'small',
onFillLevel: 0,
}

0 comments on commit 042f0e4

Please sign in to comment.