Skip to content

Commit 149ba72

Browse files
refactor(clerk-js): Introduce <PlanCardFeaturesList /> variants (#5379)
1 parent 5d4771e commit 149ba72

File tree

5 files changed

+73
-18
lines changed

5 files changed

+73
-18
lines changed

.changeset/violet-schools-repair.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@clerk/clerk-js': patch
3+
---
4+
5+
Introduce `<PlanCardFeaturesList/>` variants to render the avatar and description fields within `<PlanDetailsDrawer />`.

packages/clerk-js/src/ui/components/PricingTable/PlanCard.tsx

+58-17
Original file line numberDiff line numberDiff line change
@@ -340,11 +340,18 @@ export const PlanCardHeader = React.forwardRef<HTMLDivElement, PlanCardHeaderPro
340340

341341
interface PlanCardFeaturesListProps {
342342
plan: __experimental_CommercePlanResource;
343+
/**
344+
* @default false
345+
*/
343346
isCompact?: boolean;
347+
/**
348+
* @default `checkmark`
349+
*/
350+
variant?: 'checkmark' | 'avatar';
344351
}
345352

346353
export const PlanCardFeaturesList = React.forwardRef<HTMLDivElement, PlanCardFeaturesListProps>((props, ref) => {
347-
const { plan, isCompact } = props;
354+
const { plan, isCompact, variant = 'checkmark' } = props;
348355
const totalFeatures = plan.features.length;
349356
const [showAllFeatures, setShowAllFeatures] = React.useState(false);
350357
const canToggleFeatures = isCompact && totalFeatures > 3;
@@ -354,10 +361,7 @@ export const PlanCardFeaturesList = React.forwardRef<HTMLDivElement, PlanCardFea
354361
return (
355362
<Box
356363
ref={ref}
357-
elementDescriptor={descriptors.planCardFeaturesList}
358-
elementId={isCompact ? descriptors.planCardFeaturesList.setId('compact') : undefined}
359-
as='ul'
360-
role='list'
364+
elementDescriptor={descriptors.planCardFeatures}
361365
sx={t => ({
362366
display: 'grid',
363367
flex: '1',
@@ -366,12 +370,17 @@ export const PlanCardFeaturesList = React.forwardRef<HTMLDivElement, PlanCardFea
366370
>
367371
<Box
368372
elementDescriptor={descriptors.planCardFeaturesList}
373+
elementId={
374+
isCompact
375+
? descriptors.planCardFeaturesList.setId('compact')
376+
: descriptors.planCardFeaturesList.setId(variant)
377+
}
369378
as='ul'
370379
role='list'
371380
sx={t => ({
372381
display: 'grid',
373382
flex: '1',
374-
rowGap: isCompact ? t.space.$2 : t.space.$3,
383+
rowGap: variant === 'avatar' ? t.space.$4 : isCompact ? t.space.$2 : t.space.$3,
375384
})}
376385
>
377386
{plan.features.slice(0, showAllFeatures ? totalFeatures : 3).map(feature => (
@@ -383,19 +392,51 @@ export const PlanCardFeaturesList = React.forwardRef<HTMLDivElement, PlanCardFea
383392
sx={t => ({
384393
display: 'flex',
385394
alignItems: 'baseline',
386-
gap: t.space.$2,
395+
gap: variant === 'checkmark' ? t.space.$2 : t.space.$3,
387396
})}
388397
>
389-
<Icon
390-
icon={Check}
391-
colorScheme='neutral'
392-
size='sm'
393-
aria-hidden
394-
sx={t => ({
395-
transform: `translateY(${t.space.$0x25})`,
396-
})}
397-
/>
398-
<Text colorScheme='body'>{feature.description || feature.name}</Text>
398+
{variant === 'checkmark' ? (
399+
<Icon
400+
icon={Check}
401+
colorScheme='neutral'
402+
size='sm'
403+
aria-hidden
404+
sx={t => ({
405+
transform: `translateY(${t.space.$0x25})`,
406+
})}
407+
/>
408+
) : feature.avatarUrl ? (
409+
<Avatar
410+
size={_ => 24}
411+
title={feature.name}
412+
initials={feature.name[0]}
413+
rounded={false}
414+
imageUrl={feature.avatarUrl}
415+
/>
416+
) : null}
417+
<Span elementDescriptor={descriptors.planCardFeaturesListItemContent}>
418+
<Text
419+
elementDescriptor={descriptors.planCardFeaturesListItemTitle}
420+
colorScheme='body'
421+
sx={t => ({
422+
fontWeight: variant === 'checkmark' ? t.fontWeights.$normal : t.fontWeights.$medium,
423+
})}
424+
>
425+
{feature.name}
426+
</Text>
427+
{variant === 'avatar' && feature.description ? (
428+
<Text
429+
elementDescriptor={descriptors.planCardFeaturesListItemDescription}
430+
colorScheme='secondary'
431+
sx={t => ({
432+
marginBlockStart: t.space.$0x25,
433+
fontSize: t.fontSizes.$xs,
434+
})}
435+
>
436+
{feature.description}
437+
</Text>
438+
) : null}
439+
</Span>
399440
</Box>
400441
))}
401442
</Box>

packages/clerk-js/src/ui/components/PricingTable/PlanDetailDrawer.tsx

+4-1
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,10 @@ export function PlanDetailDrawer({
8282
padding: t.space.$4,
8383
})}
8484
>
85-
<PlanCardFeaturesList plan={plan} />
85+
<PlanCardFeaturesList
86+
plan={plan}
87+
variant='avatar'
88+
/>
8689
</Box>
8790
</Drawer.Body>
8891
) : null}

packages/clerk-js/src/ui/customizables/elementDescriptors.ts

+3
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,9 @@ export const APPEARANCE_KEYS = containsAllElementsConfigKeys([
239239
'planCardFeatures',
240240
'planCardFeaturesList',
241241
'planCardFeaturesListItem',
242+
'planCardFeaturesListItemContent',
243+
'planCardFeaturesListItemTitle',
244+
'planCardFeaturesListItemDescription',
242245
'planCardAction',
243246
'planCardPeriodToggle',
244247
'planCardFeeContainer',

packages/types/src/appearance.ts

+3
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,9 @@ export type ElementsConfig = {
367367
planCardFeatures: WithOptions;
368368
planCardFeaturesList: WithOptions<string>;
369369
planCardFeaturesListItem: WithOptions<string>;
370+
planCardFeaturesListItemContent: WithOptions;
371+
planCardFeaturesListItemTitle: WithOptions;
372+
planCardFeaturesListItemDescription: WithOptions;
370373
planCardAction: WithOptions;
371374
planCardPeriodToggle: WithOptions;
372375
planCardFeeContainer: WithOptions;

0 commit comments

Comments
 (0)