@boostdev/design-system-components 1.2.6 → 1.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client.cjs +53 -52
- package/dist/client.css +479 -476
- package/dist/client.d.cts +6 -4
- package/dist/client.d.ts +6 -4
- package/dist/client.js +53 -52
- package/dist/index.cjs +53 -52
- package/dist/index.css +479 -476
- package/dist/index.d.cts +6 -4
- package/dist/index.d.ts +6 -4
- package/dist/index.js +53 -52
- package/package.json +1 -1
- package/src/components/layout/Card/Card.mdx +9 -1
- package/src/components/layout/Card/Card.module.css +8 -4
- package/src/components/layout/Card/Card.spec.tsx +30 -0
- package/src/components/layout/Card/Card.stories.tsx +3 -1
- package/src/components/layout/Card/Card.tsx +12 -8
|
@@ -30,4 +30,34 @@ describe('Card', () => {
|
|
|
30
30
|
const { container } = render(<Card className="custom">Content</Card>);
|
|
31
31
|
expect(container.firstChild).toHaveClass('custom');
|
|
32
32
|
});
|
|
33
|
+
|
|
34
|
+
it('renders as a custom element via the as prop', () => {
|
|
35
|
+
const { container } = render(<Card as="section">Section card</Card>);
|
|
36
|
+
expect(container.firstChild?.nodeName).toBe('SECTION');
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('renders as an anchor when as="a"', () => {
|
|
40
|
+
render(<Card as="a" href="/details">Link card</Card>);
|
|
41
|
+
const link = screen.getByRole('link');
|
|
42
|
+
expect(link).toHaveAttribute('href', '/details');
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('renders as a custom component via the as prop', () => {
|
|
46
|
+
const CustomWrapper = ({ children, ...props }: { children: React.ReactNode; className?: string }) => (
|
|
47
|
+
<article {...props} data-testid="custom">{children}</article>
|
|
48
|
+
);
|
|
49
|
+
render(<Card as={CustomWrapper}>Custom</Card>);
|
|
50
|
+
expect(screen.getByTestId('custom')).toBeInTheDocument();
|
|
51
|
+
expect(screen.getByTestId('custom').nodeName).toBe('ARTICLE');
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('prefers as prop over onClick button fallback', () => {
|
|
55
|
+
const { container } = render(<Card as="div" onClick={() => {}}>Content</Card>);
|
|
56
|
+
expect(container.firstChild?.nodeName).toBe('DIV');
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('renders the extra-large padding variant', () => {
|
|
60
|
+
const { container } = render(<Card padding="extra-large">Content</Card>);
|
|
61
|
+
expect(container.firstChild).toHaveClass('--padding-extra-large');
|
|
62
|
+
});
|
|
33
63
|
});
|
|
@@ -6,7 +6,7 @@ const meta = {
|
|
|
6
6
|
component: Card,
|
|
7
7
|
argTypes: {
|
|
8
8
|
variant: { control: 'select', options: ['default', 'elevated', 'outlined'] },
|
|
9
|
-
padding: { control: 'select', options: ['none', 'small', 'medium', 'large'] },
|
|
9
|
+
padding: { control: 'select', options: ['none', 'small', 'medium', 'large', 'extra-large'] },
|
|
10
10
|
textAlign: { control: 'select', options: ['start', 'center', 'end'] },
|
|
11
11
|
},
|
|
12
12
|
} satisfies Meta<typeof Card>;
|
|
@@ -18,6 +18,8 @@ export const Default: Story = { args: { children: 'Card content', variant: 'defa
|
|
|
18
18
|
export const Elevated: Story = { args: { children: 'Elevated card', variant: 'elevated' } };
|
|
19
19
|
export const Outlined: Story = { args: { children: 'Outlined card', variant: 'outlined' } };
|
|
20
20
|
export const Clickable: Story = { args: { children: 'Click me', onClick: () => alert('clicked') } };
|
|
21
|
+
export const AsLink: Story = { args: { children: 'Card as link', as: 'a', href: '#' } as Record<string, unknown> };
|
|
22
|
+
export const AsSection: Story = { args: { children: 'Card as section', as: 'section' } as Record<string, unknown> };
|
|
21
23
|
export const Centered: Story = { args: { children: 'Centered', textAlign: 'center' } };
|
|
22
24
|
export const AllVariants: Story = {
|
|
23
25
|
args: { children: '' },
|
|
@@ -1,23 +1,27 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ElementType, ComponentPropsWithoutRef } from 'react';
|
|
2
2
|
import css from './Card.module.css';
|
|
3
3
|
import { cn } from '@boostdev/design-system-foundation';
|
|
4
4
|
import type { WithClassName } from '../../../types';
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
type CardOwnProps = WithClassName & {
|
|
7
7
|
variant?: 'default' | 'elevated' | 'outlined';
|
|
8
|
-
padding?: 'none' | 'small' | 'medium' | 'large';
|
|
8
|
+
padding?: 'none' | 'small' | 'medium' | 'large' | 'extra-large';
|
|
9
9
|
textAlign?: 'start' | 'center' | 'end';
|
|
10
|
-
|
|
10
|
+
as?: ElementType;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
type CardProps<C extends ElementType = 'div'> = CardOwnProps & Omit<ComponentPropsWithoutRef<C>, keyof CardOwnProps>;
|
|
11
14
|
|
|
12
|
-
export function Card({
|
|
15
|
+
export function Card<C extends ElementType = 'div'>({
|
|
13
16
|
children,
|
|
14
17
|
className,
|
|
15
18
|
variant = 'default',
|
|
16
19
|
padding = 'medium',
|
|
17
20
|
textAlign = 'start',
|
|
21
|
+
as,
|
|
18
22
|
onClick,
|
|
19
23
|
...rest
|
|
20
|
-
}: CardProps) {
|
|
24
|
+
}: CardProps<C>) {
|
|
21
25
|
const classNames = cn(
|
|
22
26
|
css.card,
|
|
23
27
|
css[`--${variant}`],
|
|
@@ -27,14 +31,14 @@ export function Card({
|
|
|
27
31
|
className,
|
|
28
32
|
);
|
|
29
33
|
|
|
30
|
-
const Component = onClick ? 'button' : 'div';
|
|
34
|
+
const Component = as ?? (onClick ? 'button' : 'div');
|
|
31
35
|
|
|
32
36
|
return (
|
|
33
37
|
<Component
|
|
34
38
|
{...rest}
|
|
35
39
|
className={classNames}
|
|
36
40
|
onClick={onClick}
|
|
37
|
-
{...(onClick && { type: 'button' as const })}
|
|
41
|
+
{...(!as && onClick && { type: 'button' as const })}
|
|
38
42
|
>
|
|
39
43
|
{children}
|
|
40
44
|
</Component>
|