Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | 5x 13x 4x | import { Badge, Card, Icon, Stack, Text } from '@wordpress/ui';
import type { ComponentProps, ReactElement, ReactNode } from 'react';
export type CardStatus = { label: string; intent: ComponentProps< typeof Badge >[ 'intent' ] };
type CardProps = {
icon: ReactElement;
title: string;
description?: string;
status?: CardStatus;
actions?: ReactNode;
children: ReactNode;
};
/**
* A Protect dashboard card: a titled header, then rows divided by rules.
*
* @param props - Component props.
* @param props.icon - The feature's icon.
* @param props.title - The feature's name.
* @param props.description - Optional line under the title.
* @param props.status - Optional status badge.
* @param props.actions - Optional controls beside the badge.
* @param props.children - The card's rows.
* @return The card.
*/
export function ProtectCard( { icon, title, description, status, actions, children }: CardProps ) {
return (
<Card.Root render={ <section /> } className="jp-protect-card" aria-label={ title }>
<Card.Header
render={ <Stack direction="row" gap="sm" align="center" justify="space-between" /> }
>
<Stack direction="row" gap="sm" align={ description ? 'start' : 'center' }>
<Icon icon={ icon } size={ 24 } />
<Stack direction="column" gap="xs">
<Card.Title render={ <h2 className="jp-protect-card__title" /> }>{ title }</Card.Title>
{ description && (
<Text variant="body-sm" className="jp-protect-card__muted">
{ description }
</Text>
) }
</Stack>
</Stack>
<Stack className="jp-protect-card__header-end" direction="row" gap="sm" align="center">
{ status && <Badge intent={ status.intent }>{ status.label }</Badge> }
{ actions }
</Stack>
</Card.Header>
<Card.Content>{ children }</Card.Content>
</Card.Root>
);
}
/**
* One row of a card.
*
* @param props - Component props.
* @param props.children - Row contents.
* @param props.className - Extra class names.
* @return The row.
*/
export function CardRow( {
children,
className = '',
}: {
children: ReactNode;
className?: string;
} ) {
return (
<Card.FullBleed className={ `jp-protect-card__row ${ className }`.trim() }>
{ children }
</Card.FullBleed>
);
}
/**
* A labelled figure, such as a count of blocked requests.
*
* @param props - Component props.
* @param props.label - What the figure counts.
* @param props.value - The figure.
* @param props.warning - Whether to highlight the figure as needing attention.
* @return The stat.
*/
export function Stat( {
label,
value,
warning = false,
}: {
label: string;
value: ReactNode;
warning?: boolean;
} ) {
return (
<Stack direction="column" gap="xs">
<Text variant="body-md">{ label }</Text>
<Text
variant="heading-2xl"
className={
warning ? 'jp-protect-card__stat-value is-warning' : 'jp-protect-card__stat-value'
}
>
{ value }
</Text>
</Stack>
);
}
|