Skip to content

Commit 3ec91da

Browse files
committed
feat(design): add LabCard component
1 parent 6abe1ce commit 3ec91da

3 files changed

Lines changed: 94 additions & 0 deletions

File tree

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { Link } from '../link'
2+
import type { FeaturedLab } from '../../../build/featured'
3+
4+
export function LabCard({ lab }: { lab: FeaturedLab }) {
5+
return (
6+
<article class="lab-card">
7+
<h3 class="lab-card__title">{lab.title}</h3>
8+
<p class="lab-card__tagline">{lab.tagline}</p>
9+
<ul class="lab-card__links">
10+
{lab.links.map((link) => (
11+
<li class="lab-card__link">
12+
<Link href={link.url} external>{link.label}</Link>
13+
</li>
14+
))}
15+
</ul>
16+
</article>
17+
)
18+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
@layer components {
2+
.lab-card {
3+
padding: var(--space-6);
4+
border-inline-start: 3px solid var(--color-accent);
5+
border-radius: var(--radius-sm);
6+
background: var(--color-surface);
7+
box-shadow: var(--shadow-card);
8+
display: flex;
9+
flex-direction: column;
10+
gap: var(--space-3);
11+
}
12+
13+
.lab-card__title {
14+
font-size: var(--step-2);
15+
line-height: 1.2;
16+
margin: 0;
17+
color: var(--color-ink);
18+
}
19+
20+
.lab-card__tagline {
21+
font-size: var(--step-0);
22+
color: var(--color-ink-subtle);
23+
max-inline-size: var(--measure-prose);
24+
margin: 0;
25+
}
26+
27+
.lab-card__links {
28+
list-style: none;
29+
padding: 0;
30+
margin: 0;
31+
display: flex;
32+
flex-direction: column;
33+
gap: var(--space-2);
34+
}
35+
36+
.lab-card__link {
37+
font-size: var(--step--1);
38+
}
39+
}

tests/views/components.test.tsx

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,40 @@ describe('StandardsList', () => {
5252
expect(html.match(/standards-list__item/g)!.length).toBe(5)
5353
})
5454
})
55+
56+
import { LabCard } from '../../src/design/components/lab-card'
57+
import type { FeaturedLab } from '../../src/build/featured'
58+
59+
describe('LabCard', () => {
60+
const lab: FeaturedLab = {
61+
title: 'Forms Lab',
62+
tagline: 'Digitize forms to create modern, accessible experiences for public outreach.',
63+
order: 1,
64+
links: [
65+
{ label: 'Demo (Forms Platform)', url: 'https://example.com/demo' },
66+
{ label: 'GitHub repository — Forms Platform', url: 'https://github.com/flexion/forms' },
67+
],
68+
}
69+
70+
test('renders the title as an h3 with no link', async () => {
71+
const html = await renderToHtml(<LabCard lab={lab} />)
72+
expect(html).toMatch(/<h3[^>]*class="lab-card__title"[^>]*>Forms Lab<\/h3>/)
73+
// Title should not be wrapped in an anchor
74+
expect(html).not.toMatch(/<h3[^>]*>[^<]*<a/)
75+
})
76+
77+
test('renders the tagline', async () => {
78+
const html = await renderToHtml(<LabCard lab={lab} />)
79+
expect(html).toContain('Digitize forms to create modern, accessible experiences')
80+
})
81+
82+
test('renders one link per entry with external treatment', async () => {
83+
const html = await renderToHtml(<LabCard lab={lab} />)
84+
expect(html).toContain('href="https://example.com/demo"')
85+
expect(html).toContain('href="https://github.com/flexion/forms"')
86+
expect(html).toContain('Demo (Forms Platform)')
87+
expect(html).toContain('GitHub repository — Forms Platform')
88+
// Uses the Link component with external variant
89+
expect(html.match(/data-variant="external"/g)?.length).toBe(2)
90+
})
91+
})

0 commit comments

Comments
 (0)