Skip to content

Commit 6a4fd32

Browse files
authored
Merge pull request #290 from Desmenez/napatpon/add-collection-card
2 parents 9cb8a25 + f3eeeaa commit 6a4fd32

12 files changed

Lines changed: 487 additions & 0 deletions

File tree

.changeset/forty-seas-drop.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@example/ui-playground": patch
3+
"@genseki/react": patch
4+
"@genseki/ui": minor
5+
---
6+
7+
[Feat]: add collection card v2
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { CubeIcon } from '@phosphor-icons/react'
2+
3+
import {
4+
CollectionCard,
5+
CollectionCardButton,
6+
CollectionCardDescription,
7+
CollectionCardHeader,
8+
CollectionCardIcon,
9+
CollectionCardTitle,
10+
Typography,
11+
} from '@genseki/react/v2'
12+
13+
export function CollectionCardSection() {
14+
return (
15+
<div className="grid grid-cols-2 gap-4">
16+
<CollectionCard>
17+
<CollectionCardIcon icon={CubeIcon} />
18+
<CollectionCardHeader>
19+
<CollectionCardTitle>
20+
<Typography type="h4" weight="semibold">
21+
Collection 1
22+
</Typography>
23+
</CollectionCardTitle>
24+
</CollectionCardHeader>
25+
<CollectionCardDescription>
26+
<Typography type="body" weight="normal" className="line-clamp-3">
27+
Lorem ipsum dolor s
28+
</Typography>
29+
</CollectionCardDescription>
30+
<CollectionCardButton onClick={() => {}}>
31+
<Typography type="body" weight="normal">
32+
View collection
33+
</Typography>
34+
</CollectionCardButton>
35+
</CollectionCard>
36+
37+
<CollectionCard>
38+
<CollectionCardIcon icon={CubeIcon} />
39+
<CollectionCardHeader>
40+
<CollectionCardTitle>
41+
<Typography type="h4" weight="semibold">
42+
Collection 1
43+
</Typography>
44+
</CollectionCardTitle>
45+
</CollectionCardHeader>
46+
<CollectionCardDescription>
47+
<Typography type="body" weight="normal" className="line-clamp-3">
48+
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. Lorem ipsum
49+
dolor sit amet consectetur adipisicing elit. Quisquam, quos. Lorem ipsum dolor sit amet
50+
consectetur adipisicing elit. Quisquam, quos. Lorem ipsum dolor sit amet consectetur
51+
adipisicing elit. Quisquam, quos. Lorem ipsum dolor sit amet consectetur adipisicing
52+
elit. Quisquam, quos.
53+
</Typography>
54+
</CollectionCardDescription>
55+
<CollectionCardButton onClick={() => {}}>
56+
<Typography type="body" weight="normal">
57+
View collection
58+
</Typography>
59+
</CollectionCardButton>
60+
</CollectionCard>
61+
</div>
62+
)
63+
}

examples/ui-playground/src/app/playground/shadcn/page-sidebar.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ const navigationItems = [
4141
{ href: '#textarea', label: 'Textarea' },
4242
{ href: '#toast', label: 'Toast' },
4343
{ href: '#rich-text-editor', label: 'Rich Text Editor' },
44+
{ href: '#collection-card', label: 'Collection Card' },
4445
{ href: '/playground/shadcn/sidebar', label: 'Sidebar' },
4546
]
4647

examples/ui-playground/src/app/playground/shadcn/page.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { Typography } from '@genseki/react/v2'
66
import { ButtonSection } from './button-section'
77
import { CheckboxSection } from './checkbox-section'
88
import { CollapsibleSection } from './collapsible-section'
9+
import { CollectionCardSection } from './collection-card-section'
910
import { ColorPickerSection } from './color-picker-section'
1011
import { ComboboxSection } from './combobox-section'
1112
import { DatePickerSection } from './date-picker-section'
@@ -143,6 +144,10 @@ export default function ComboboxPage() {
143144
Rich Text Editor
144145
</Typography>
145146
<RichTextSection />
147+
<Typography type="h2" weight="bold" id="collection-card">
148+
Collection Card
149+
</Typography>
150+
<CollectionCardSection />
146151
</div>
147152
<React.Suspense fallback={null}>
148153
<PageSidebar />
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
'use client'
2+
3+
import * as React from 'react'
4+
5+
import { IconChevronLgRight } from '@intentui/icons'
6+
import { CubeIcon, FolderIcon } from '@phosphor-icons/react'
7+
8+
import { BadgeOrange } from '../../../src/react/icons/badge-orange'
9+
import { DotsCard } from '../../../src/react/icons/dots-card'
10+
import { cn } from '../../../src/react/utils/cn'
11+
12+
function CollectionCard({ className, ...props }: React.ComponentProps<'div'>) {
13+
return (
14+
<div
15+
data-slot="collection-card"
16+
className={cn(
17+
'bg-white rounded-2xl shadow-sm p-2 w-full border border-bluegray-300 relative flex flex-col',
18+
className
19+
)}
20+
{...props}
21+
/>
22+
)
23+
}
24+
25+
function CollectionCardIcon({
26+
icon: Icon = CubeIcon,
27+
badgeClassName,
28+
iconClassName,
29+
}: {
30+
icon?: React.ComponentType<React.ComponentProps<typeof CubeIcon>>
31+
badgeClassName?: string
32+
iconClassName?: string
33+
}) {
34+
return (
35+
<>
36+
<BadgeOrange
37+
data-slot="collection-card-badge"
38+
className={cn('size-24 absolute top-0 left-6 -translate-y-1/2 z-[1]', badgeClassName)}
39+
/>
40+
<Icon
41+
data-slot="collection-card-icon"
42+
className={cn(
43+
'text-text-brand size-10 absolute top-0 left-8 -translate-y-1/2 z-[2] translate-x-1/2',
44+
iconClassName
45+
)}
46+
/>
47+
</>
48+
)
49+
}
50+
51+
function CollectionCardHeader({ className, ...props }: React.ComponentProps<'div'>) {
52+
return (
53+
<div
54+
data-slot="collection-card-header"
55+
className={cn(
56+
'flex justify-between items-center px-8 pb-4 pt-14 border-b border-bluegray-300 relative overflow-hidden',
57+
className
58+
)}
59+
{...props}
60+
>
61+
<div className="absolute top-0 left-0">
62+
<DotsCard />
63+
</div>
64+
{props.children}
65+
</div>
66+
)
67+
}
68+
69+
function CollectionCardTitle({ className, ...props }: React.ComponentProps<'p'>) {
70+
return (
71+
<div
72+
data-slot="collection-card-title"
73+
className={cn('text-bluegray-800', className)}
74+
{...props}
75+
/>
76+
)
77+
}
78+
79+
function CollectionCardItemCount({
80+
className,
81+
itemNumber,
82+
...props
83+
}: React.ComponentProps<'div'> & {
84+
itemNumber: number
85+
}) {
86+
return (
87+
<div
88+
data-slot="collection-card-item-count"
89+
className={cn('flex items-center gap-2', className)}
90+
{...props}
91+
>
92+
<FolderIcon className="text-text-secondary" />
93+
<span className="text-sm text-text-secondary">{itemNumber} items</span>
94+
</div>
95+
)
96+
}
97+
98+
function CollectionCardDescription({ className, ...props }: React.ComponentProps<'div'>) {
99+
return (
100+
<div
101+
data-slot="collection-card-description"
102+
className={cn('px-8 pb-8 pt-6 flex-grow text-text-secondary', className)}
103+
{...props}
104+
>
105+
{props.children}
106+
</div>
107+
)
108+
}
109+
110+
function CollectionCardButton({
111+
className,
112+
children,
113+
title = 'View',
114+
...props
115+
}: React.ComponentProps<'button'> & {
116+
title?: string
117+
}) {
118+
return (
119+
<button
120+
data-slot="collection-card-button"
121+
className={cn(
122+
'w-full py-6 px-8 bg-gradient-to-b from-pumpkin-50 to-pumpkin-100 rounded-lg text-text-secondary font-medium flex items-center justify-end hover:from-pumpkin-100 hover:to-pumpkin-300 transition cursor-pointer gap-3',
123+
className
124+
)}
125+
{...props}
126+
>
127+
<span>{children ?? title}</span>
128+
<IconChevronLgRight fontSize={24} className="size-10 text-text-secondary" />
129+
</button>
130+
)
131+
}
132+
133+
export {
134+
CollectionCard,
135+
CollectionCardButton,
136+
CollectionCardDescription,
137+
CollectionCardHeader,
138+
CollectionCardIcon,
139+
CollectionCardItemCount,
140+
CollectionCardTitle,
141+
}

legacies/react/v2/components/primitives/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ export * from './button-group'
44
export * from './calendar'
55
export * from './checkbox'
66
export * from './collapsible'
7+
export * from './collection-card'
78
export * from './color-picker'
89
export * from './combobox'
910
export * from './command'
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
'use client'
2+
3+
import * as React from 'react'
4+
5+
import { CaretRightIcon, CubeIcon, FolderIcon } from '@phosphor-icons/react'
6+
7+
import { BadgeOrange } from '../../icons/badge-orange'
8+
import { DotsCard } from '../../icons/dots-card'
9+
import { cn } from '../../utils/cn'
10+
11+
function CollectionCard({ className, ...props }: React.ComponentProps<'div'>) {
12+
return (
13+
<div
14+
data-slot="collection-card"
15+
className={cn(
16+
'bg-white rounded-2xl shadow-sm p-2 w-full border border-bluegray-300 relative flex flex-col',
17+
className
18+
)}
19+
{...props}
20+
/>
21+
)
22+
}
23+
24+
function CollectionCardIcon({
25+
icon: Icon = CubeIcon,
26+
badgeClassName,
27+
iconClassName,
28+
}: {
29+
icon?: React.ComponentType<React.ComponentProps<typeof CubeIcon>>
30+
badgeClassName?: string
31+
iconClassName?: string
32+
}) {
33+
return (
34+
<>
35+
<BadgeOrange
36+
data-slot="collection-card-badge"
37+
className={cn('size-24 absolute top-0 left-6 -translate-y-1/2 z-[1]', badgeClassName)}
38+
/>
39+
<Icon
40+
data-slot="collection-card-icon"
41+
className={cn(
42+
'text-text-brand size-10 absolute top-0 left-8 -translate-y-1/2 z-[2] translate-x-1/2',
43+
iconClassName
44+
)}
45+
/>
46+
</>
47+
)
48+
}
49+
50+
function CollectionCardHeader({ className, ...props }: React.ComponentProps<'div'>) {
51+
return (
52+
<div
53+
data-slot="collection-card-header"
54+
className={cn(
55+
'flex justify-between items-center px-8 pb-4 pt-14 border-b border-bluegray-300 relative overflow-hidden',
56+
className
57+
)}
58+
{...props}
59+
>
60+
<div className="absolute top-0 left-0">
61+
<DotsCard />
62+
</div>
63+
{props.children}
64+
</div>
65+
)
66+
}
67+
68+
function CollectionCardTitle({ className, ...props }: React.ComponentProps<'p'>) {
69+
return (
70+
<div
71+
data-slot="collection-card-title"
72+
className={cn('text-bluegray-800', className)}
73+
{...props}
74+
/>
75+
)
76+
}
77+
78+
function CollectionCardItemCount({
79+
className,
80+
itemNumber,
81+
...props
82+
}: React.ComponentProps<'div'> & {
83+
itemNumber: number
84+
}) {
85+
return (
86+
<div
87+
data-slot="collection-card-item-count"
88+
className={cn('flex items-center gap-2', className)}
89+
{...props}
90+
>
91+
<FolderIcon className="text-text-secondary" />
92+
<span className="text-sm text-text-secondary">{itemNumber} items</span>
93+
</div>
94+
)
95+
}
96+
97+
function CollectionCardDescription({ className, ...props }: React.ComponentProps<'div'>) {
98+
return (
99+
<div
100+
data-slot="collection-card-description"
101+
className={cn('px-8 pb-8 pt-6 flex-grow text-text-secondary', className)}
102+
{...props}
103+
>
104+
{props.children}
105+
</div>
106+
)
107+
}
108+
109+
function CollectionCardButton({
110+
className,
111+
children,
112+
title = 'View',
113+
...props
114+
}: React.ComponentProps<'button'> & {
115+
title?: string
116+
}) {
117+
return (
118+
<button
119+
data-slot="collection-card-button"
120+
className={cn(
121+
'w-full py-6 px-8 bg-gradient-to-b from-pumpkin-50 to-pumpkin-100 rounded-lg text-text-secondary font-medium flex items-center justify-end hover:from-pumpkin-100 hover:to-pumpkin-300 transition cursor-pointer gap-3',
122+
className
123+
)}
124+
{...props}
125+
>
126+
<span>{children ?? title}</span>
127+
<CaretRightIcon fontSize={24} className="size-10 text-text-secondary" />
128+
</button>
129+
)
130+
}
131+
132+
export {
133+
CollectionCard,
134+
CollectionCardButton,
135+
CollectionCardDescription,
136+
CollectionCardHeader,
137+
CollectionCardIcon,
138+
CollectionCardItemCount,
139+
CollectionCardTitle,
140+
}

packages/ui/src/components/primitives/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ export * from './button-group'
55
export * from './calendar'
66
export * from './checkbox'
77
export * from './collapsible'
8+
export * from './collection-card'
89
export * from './color-picker'
910
export * from './combobox'
1011
export * from './command'

0 commit comments

Comments
 (0)