Skip to content

Commit

Permalink
feat: Service catalog card and icon (#666)
Browse files Browse the repository at this point in the history
  • Loading branch information
maciaszczykm authored Nov 28, 2024
1 parent 9b66c98 commit 74ef657
Show file tree
Hide file tree
Showing 7 changed files with 261 additions and 4 deletions.
4 changes: 2 additions & 2 deletions src/components/AppIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ const parentFillLevelToHue = {
} as const satisfies Record<FillLevel, AppIconHue>

const sizeToWidth = {
xxsmall: 32,
xxsmall: 36,
xsmall: 48,
small: 64,
medium: 96,
Expand All @@ -61,7 +61,7 @@ const sizeToWidth = {
} as const satisfies Record<AppIconSize, number>

const sizeToIconWidth = {
xxsmall: 16,
xxsmall: 20,
xsmall: 32,
small: 48,
medium: 64,
Expand Down
145 changes: 145 additions & 0 deletions src/components/CatalogCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import { type Ref, forwardRef } from 'react'
import { useTheme } from 'styled-components'

import { PrQueueIcon } from '../icons'

import Chip from './Chip'
import Card, { type CardProps } from './Card'
import AppIcon from './AppIcon'
import ChipList from './ChipList'
import Flex from './Flex'

type CatalogCardProps = CardProps & {
name?: string
author?: string
category?: string
description?: string
imageUrl?: string
tags?: string[]
}

function CatalogCardRef(
{
name,
author,
category,
description,
imageUrl,
tags = [],
...props
}: CatalogCardProps,
ref: Ref<any>
) {
const theme = useTheme()

return (
<Card
ref={ref}
clickable
style={{
flexDirection: 'column',
padding: theme.spacing.medium,
maxWidth: 456,
minWidth: 256,
width: '100%',
}}
{...props}
>
<Flex
height="100%"
align="flex-start"
gap="large"
>
<Flex
flexGrow={1}
direction="column"
height="100%"
overflow="hidden"
>
<Flex align="center">
<AppIcon
size="xxsmall"
url={imageUrl}
icon={<PrQueueIcon />}
/>
<Flex
direction="row"
marginLeft={theme.spacing.small}
width="100%"
align="flex-start"
justify="space-between"
>
<Flex direction="column">
<div
style={{
...theme.partials.text.body2Bold,
color: theme.colors.text,
}}
>
{name}
</div>
<div
style={{
...theme.partials.text.caption,
color: theme.colors['text-xlight'],
}}
>
by {author}
</div>
</Flex>
</Flex>
</Flex>
{description && (
<p
style={{
...theme.partials.text.body2,
margin: 0,
marginTop: theme.spacing.small,
color: theme.colors['text-light'],
display: '-webkit-box',
WebkitLineClamp: '2',
WebkitBoxOrient: 'vertical',
overflow: 'hidden',
}}
>
{description}
</p>
)}
<div style={{ flexGrow: 1 }} />
{(category || tags?.length > 0) && (
<Flex
alignItems="start"
gap="large"
justifyContent={category ? 'space-between' : 'end'}
marginTop={theme.spacing.medium}
>
{!!category && (
<Chip
size="small"
border="none"
fillLevel={3}
>
{category}
</Chip>
)}
<ChipList
size="small"
border="none"
fillLevel={3}
values={tags ?? []}
limit={1}
truncateWidth={100}
wrap="nowrap"
emptyState={null}
/>
</Flex>
)}
</Flex>
</Flex>
</Card>
)
}

const CatalogCard = forwardRef(CatalogCardRef)

export default CatalogCard
6 changes: 4 additions & 2 deletions src/components/ChipList.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Flex, Span } from 'honorable'
import { Flex, type FlexBaseProps, Span } from 'honorable'
import isEmpty from 'lodash-es/isEmpty'
import {
type ComponentProps,
Expand All @@ -19,6 +19,7 @@ export type ChipListProps<TValue> = {
values: TValue[]
transformValue?: TransformFn<TValue>
limit: number
wrap?: Pick<FlexBaseProps, 'wrap'>
emptyState?: JSX.Element | null
onClickCondition?: (value: TValue) => boolean
onClick?: Dispatch<TValue>
Expand All @@ -28,6 +29,7 @@ function ChipList<TValue = string>({
values = [],
transformValue,
limit = 4,
wrap = 'wrap',
emptyState,
onClickCondition,
onClick,
Expand All @@ -38,7 +40,7 @@ function ChipList<TValue = string>({
return (
<Flex
gap="xsmall"
wrap
wrap={wrap}
>
{isEmpty(values) &&
(emptyState !== undefined ? (
Expand Down
44 changes: 44 additions & 0 deletions src/components/icons/CatalogIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import createIcon from './createIcon'

export default createIcon(({ size, color }) => (
<svg
width={size}
viewBox="0 0 17 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M7.25039 12.05V14.65M7.25039 14.65C7.25039 15.05 6.95039 15.35 6.55039 15.35H1.35039C0.950391 15.35 0.650391 15.05 0.650391 14.65M7.25039 14.65L7.25039 9.44998C7.25039 9.04998 6.95039 8.74998 6.55039 8.74998L1.35039 8.74998M0.650391 14.65V9.44998M0.650391 14.65V12.95V9.44998M0.650391 9.44998C0.650391 9.04998 0.950391 8.74998 1.35039 8.74998M1.35039 8.74998H5.05039M15.5944 12.05V14.65M15.5944 14.65C15.5944 15.05 15.2944 15.35 14.8944 15.35H9.69439C9.29439 15.35 8.99439 15.05 8.99439 14.65M15.5944 14.65L15.5944 9.45002C15.5944 9.05002 15.2944 8.75002 14.8944 8.75002L9.69439 8.75002M8.99439 14.65V9.45002M8.99439 14.65V12.95V9.45002M8.99439 9.45002C8.99439 9.05002 9.29439 8.75002 9.69439 8.75002M9.69439 8.75002H13.3944M7.25039 3.92793V6.52793M7.25039 6.52793C7.25039 6.92793 6.95039 7.22793 6.55039 7.22793H1.35039C0.950391 7.22793 0.650391 6.92793 0.650391 6.52793M7.25039 6.52793L7.25039 1.32793C7.25039 0.92793 6.95039 0.62793 6.55039 0.62793L1.35039 0.627931M0.650391 6.52793V1.32793M0.650391 6.52793V4.82793V1.32793M0.650391 1.32793C0.650391 0.92793 0.950391 0.627931 1.35039 0.627931M1.35039 0.627931H5.05039"
stroke={color}
strokeMiterlimit="10"
/>
<path
d="M13.1211 5.15015L13.1211 8.98032"
stroke={color}
strokeWidth="0.992819"
strokeMiterlimit="10"
strokeLinejoin="round"
/>
<path
d="M7.33496 2.87915L10.9946 2.87915"
stroke={color}
strokeWidth="0.992819"
strokeMiterlimit="10"
strokeLinejoin="round"
/>
<path
d="M7.09082 8.9803L11.7382 4.42004"
stroke={color}
strokeWidth="0.992819"
strokeMiterlimit="10"
strokeLinejoin="round"
/>
<path
d="M13.1212 5.00615C14.2959 5.00615 15.2482 4.05384 15.2482 2.87911C15.2482 1.70438 14.2959 0.752075 13.1212 0.752075C11.9464 0.752075 10.9941 1.70438 10.9941 2.87911C10.9941 4.05384 11.9464 5.00615 13.1212 5.00615Z"
stroke={color}
strokeWidth="0.992819"
strokeMiterlimit="10"
strokeLinejoin="round"
/>
</svg>
))
1 change: 1 addition & 0 deletions src/icons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export { default as ArchitectureIcon } from './components/icons/ArchitectureIcon
export { default as ArrowLeftIcon } from './components/icons/ArrowLeftIcon'
export { default as ArrowRightIcon } from './components/icons/ArrowRightIcon'
export { default as ArrowRightLeftIcon } from './components/icons/ArrowRightLeftIcon'
export { default as CatalogIcon } from './components/icons/CatalogIcon'
export { default as ArrowTopRightIcon } from './components/icons/ArrowTopRightIcon'
export { default as AwsLogoIcon } from './components/icons/AwsLogoIcon'
export { default as AzureLogoIcon } from './components/icons/AzureLogoIcon'
Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export type { CardProps } from './components/Card'
export { default as Card } from './components/Card'
export type { CalloutProps } from './components/Callout'
export { default as Callout } from './components/Callout'
export { default as CatalogCard } from './components/CatalogCard'
export { default as Checkbox } from './components/Checkbox'
export { default as Chip, type ChipProps } from './components/Chip'
export { default as ChipList } from './components/ChipList'
Expand Down
64 changes: 64 additions & 0 deletions src/stories/CatlogCard.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { Div } from 'honorable'

import CatalogCard from '../components/CatalogCard'

export default {
title: 'CatalogCard',
component: CatalogCard,
}

function Template(args: any) {
return (
<Div
display="grid"
gap="large"
gridTemplateColumns="repeat(auto-fit, minmax(256px, 1fr))"
>
<CatalogCard {...args} />
<CatalogCard {...args} />
<CatalogCard {...args} />
<CatalogCard {...args} />
<CatalogCard
{...{
...args,

...{
imageUrl: '/logos/plural-logomark-only-white.svg',
tags: ['Loooooooooooooooooooong', 'Short'],
},
}}
/>
<CatalogCard
{...{
...args,
...{
category: null,
description: null,
imageUrl: '/logos/plural-logomark-only-white.svg',
tags: ['Tag-1', 'Tag-2', 'Tag-3'],
},
}}
/>
</Div>
)
}

export const Default = Template.bind({})

Default.args = {
name: 'Base catalog',
author: 'Plural',
category: 'Messaging',
description:
'The new open-source standard to sync data from applications, APIs & databases. One click deploys for data scientists and developers.',
tags: [
'Devops',
'Deployment',
'Fun',
'Turkey',
'Chickens',
'Handball',
'Cricket',
'Support',
],
}

0 comments on commit 74ef657

Please sign in to comment.