@@ -9,83 +9,115 @@ import {
99 Text ,
1010 Heading ,
1111 Box ,
12- IconButton ,
1312 HStack ,
1413 Tag ,
15- MenuButton ,
16- Menu ,
17- MenuList ,
18- MenuItem ,
19- Link
14+ Skeleton ,
15+ SkeletonText
2016} from '@chakra-ui/react' ;
21- import { CollecticonEllipsisVertical } from '@devseed-ui/collecticons-chakra' ;
17+ import SmartLink from './SmartLink' ;
18+
19+ interface ItemCardProps {
20+ imageSrc ?: string ;
21+ imageAlt ?: string ;
22+ title ?: string ;
23+ subtitle ?: string ;
24+ description ?: string ;
25+ tags ?: string [ ] ;
26+ to ?: string ;
27+ renderMenu ?: ( ) => React . ReactNode ;
28+ }
29+
30+ export function ItemCard ( {
31+ imageSrc,
32+ imageAlt,
33+ title,
34+ subtitle,
35+ description,
36+ tags,
37+ to,
38+ renderMenu
39+ } : ItemCardProps ) {
40+ const renderLink = ( children : React . ReactNode ) => {
41+ return to ? (
42+ < SmartLink to = { to } color = 'inherit' >
43+ { children }
44+ </ SmartLink >
45+ ) : (
46+ < > { children } </ >
47+ ) ;
48+ } ;
2249
23- export default function ItemCard ( ) {
2450 return (
2551 < Card as = 'article' variant = 'filled' >
26- < Link href = '#' >
27- < Image
28- src = 'https://images.unsplash.com/photo-1618005182384-a83a8bd57fbe?q=80& w = 3464 & auto = format & fit = crop & ixlib = rb - 4.0 .3 & ixid = M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA % 3 D % 3 D '
29- alt = 'Abstract 3D render'
30- height = '16rem'
31- width = '100%'
32- objectFit = 'cover'
33- borderRadius = 'md'
34- />
35- </ Link >
52+ { imageSrc &&
53+ renderLink (
54+ < Image
55+ src = { imageSrc }
56+ alt = { imageAlt }
57+ height = '16rem'
58+ width = '100%'
59+ objectFit = 'cover'
60+ borderRadius = 'md'
61+ />
62+ ) }
3663 < CardHeader as = 'header' >
3764 < Flex direction = 'row' gap = { 4 } >
38- < Box flexBasis = '100%' >
39- < Heading size = 'sm' as = 'h3' >
40- < Link href = '#' color = 'inherit' >
41- Card title
42- </ Link >
43- </ Heading >
44- < Text as = 'p' fontSize = 'sm' color = 'base.400' >
45- Card subtitle
46- </ Text >
47- </ Box >
48- < Box >
49- < Menu >
50- < MenuButton
51- as = { IconButton }
52- aria-label = 'Options'
53- icon = { < CollecticonEllipsisVertical /> }
54- variant = 'outline'
55- size = 'sm'
56- />
57- < MenuList >
58- < MenuItem > View</ MenuItem >
59- < MenuItem > Edit</ MenuItem >
60- < MenuItem > Delete</ MenuItem >
61- </ MenuList >
62- </ Menu >
63- </ Box >
65+ { ( title || subtitle ) && (
66+ < Box flexBasis = '100%' >
67+ { title && (
68+ < Heading size = 'sm' as = 'h3' wordBreak = 'break-word' >
69+ { renderLink ( title ) }
70+ </ Heading >
71+ ) }
72+ { subtitle && (
73+ < Text as = 'p' fontSize = 'sm' color = 'base.400' >
74+ { subtitle }
75+ </ Text >
76+ ) }
77+ </ Box >
78+ ) }
79+ { renderMenu && < Box > { renderMenu ( ) } </ Box > }
6480 </ Flex >
6581 </ CardHeader >
66- < CardBody >
67- < Text size = 'md' >
68- Card Summary. Lorem ipsum dolor sit, amet consectetur adipisicing
69- elit. Non impedit vitae tempore repellat neque sunt aut, veniam
70- facere, corporis nihil voluptas quis quia magni.
71- </ Text >
72- </ CardBody >
73- < CardFooter as = 'footer' >
74- < HStack spacing = { 2 } >
75- < Tag size = 'sm' colorScheme = 'primary' as = 'a' href = '#' >
76- Tag
77- </ Tag >
78- < Tag size = 'sm' colorScheme = 'primary' as = 'a' href = '#' >
79- Tag
80- </ Tag >
81- < Tag size = 'sm' colorScheme = 'primary' as = 'a' href = '#' >
82- Tag
83- </ Tag >
84- < Tag size = 'sm' colorScheme = 'primary' as = 'a' href = '#' >
85- Tag
86- </ Tag >
87- </ HStack >
88- </ CardFooter >
82+ { description && (
83+ < CardBody >
84+ < Text size = 'md' > { description } </ Text >
85+ </ CardBody >
86+ ) }
87+ { tags && tags . length > 0 && (
88+ < CardFooter as = 'footer' >
89+ < HStack spacing = { 2 } wrap = 'wrap' >
90+ { tags . map ( ( tag ) => (
91+ // <Tag key={tag} size='sm' colorScheme='primary' as='a' href='#'>
92+ < Tag key = { tag } size = 'sm' colorScheme = 'primary' >
93+ { tag }
94+ </ Tag >
95+ ) ) }
96+ </ HStack >
97+ </ CardFooter >
98+ ) }
99+ </ Card >
100+ ) ;
101+ }
102+
103+ export function ItemCardLoading ( props : { mini ?: boolean } ) {
104+ return (
105+ < Card as = 'article' variant = 'filled' p = { 8 } >
106+ < Flex direction = 'column' gap = { 2 } >
107+ < Skeleton h = { 6 } width = '40%' />
108+ < Skeleton h = { 4 } width = '30%' />
109+ </ Flex >
110+
111+ { ! props . mini && (
112+ < >
113+ < SkeletonText mt = { 8 } noOfLines = { 4 } spacing = '4' skeletonHeight = '2' />
114+ < Flex gap = { 2 } mt = { 12 } >
115+ < Skeleton h = { 4 } width = { 12 } />
116+ < Skeleton h = { 4 } width = { 12 } />
117+ < Skeleton h = { 4 } width = { 12 } />
118+ </ Flex >
119+ </ >
120+ ) }
89121 </ Card >
90122 ) ;
91123}
0 commit comments