@buildcanada/components 0.3.4 → 0.3.5

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.
Files changed (69) hide show
  1. package/package.json +3 -2
  2. package/src/assets/fonts/financier-text-regular.woff2 +0 -0
  3. package/src/assets/fonts/founders-grotesk-mono-regular.woff2 +0 -0
  4. package/src/assets/fonts/soehne-kraftig.woff2 +0 -0
  5. package/src/content/Card/Card.scss +281 -0
  6. package/src/content/Card/Card.stories.tsx +389 -0
  7. package/src/content/Card/Card.tsx +170 -0
  8. package/src/content/Card/index.ts +22 -0
  9. package/src/content/Hero/Hero.scss +150 -0
  10. package/src/content/Hero/Hero.stories.tsx +299 -0
  11. package/src/content/Hero/Hero.tsx +63 -0
  12. package/src/content/Hero/index.ts +13 -0
  13. package/src/content/StatBlock/StatBlock.scss +83 -0
  14. package/src/content/StatBlock/StatBlock.stories.tsx +331 -0
  15. package/src/content/StatBlock/StatBlock.tsx +52 -0
  16. package/src/content/StatBlock/index.ts +2 -0
  17. package/src/feedback/Dialog/Dialog.scss +158 -0
  18. package/src/feedback/Dialog/Dialog.stories.tsx +286 -0
  19. package/src/feedback/Dialog/Dialog.tsx +120 -0
  20. package/src/feedback/Dialog/index.ts +1 -0
  21. package/src/feedback/PopupForm/PopupForm.scss +34 -0
  22. package/src/feedback/PopupForm/PopupForm.stories.tsx +341 -0
  23. package/src/feedback/PopupForm/PopupForm.tsx +90 -0
  24. package/src/feedback/PopupForm/index.ts +1 -0
  25. package/src/index.ts +61 -0
  26. package/src/layout/Container/Container.scss +40 -0
  27. package/src/layout/Container/Container.stories.tsx +153 -0
  28. package/src/layout/Container/Container.tsx +29 -0
  29. package/src/layout/Container/index.ts +2 -0
  30. package/src/layout/Divider/Divider.scss +117 -0
  31. package/src/layout/Divider/Divider.stories.tsx +204 -0
  32. package/src/layout/Divider/Divider.tsx +32 -0
  33. package/src/layout/Divider/index.ts +2 -0
  34. package/src/layout/Grid/Grid.scss +81 -0
  35. package/src/layout/Grid/Grid.stories.tsx +263 -0
  36. package/src/layout/Grid/Grid.tsx +75 -0
  37. package/src/layout/Grid/index.ts +2 -0
  38. package/src/layout/Section/Section.scss +74 -0
  39. package/src/layout/Section/Section.stories.tsx +173 -0
  40. package/src/layout/Section/Section.tsx +37 -0
  41. package/src/layout/Section/index.ts +2 -0
  42. package/src/layout/Stack/Stack.scss +61 -0
  43. package/src/layout/Stack/Stack.stories.tsx +342 -0
  44. package/src/layout/Stack/Stack.tsx +48 -0
  45. package/src/layout/Stack/index.ts +9 -0
  46. package/src/navigation/Footer/Footer.scss +233 -0
  47. package/src/navigation/Footer/Footer.stories.tsx +351 -0
  48. package/src/navigation/Footer/Footer.tsx +174 -0
  49. package/src/navigation/Footer/index.ts +2 -0
  50. package/src/navigation/Header/Header.scss +325 -0
  51. package/src/navigation/Header/Header.stories.tsx +346 -0
  52. package/src/navigation/Header/Header.tsx +185 -0
  53. package/src/navigation/Header/index.ts +2 -0
  54. package/src/primitives/Button/Button.scss +218 -0
  55. package/src/primitives/Button/Button.stories.tsx +300 -0
  56. package/src/primitives/Button/Button.tsx +120 -0
  57. package/src/primitives/Button/index.ts +2 -0
  58. package/src/primitives/Checkbox/Checkbox.scss +114 -0
  59. package/src/primitives/Checkbox/Checkbox.stories.tsx +204 -0
  60. package/src/primitives/Checkbox/Checkbox.tsx +75 -0
  61. package/src/primitives/Checkbox/index.ts +2 -0
  62. package/src/primitives/TextField/TextField.scss +93 -0
  63. package/src/primitives/TextField/TextField.stories.tsx +265 -0
  64. package/src/primitives/TextField/TextField.tsx +105 -0
  65. package/src/primitives/TextField/index.ts +2 -0
  66. package/src/styles/fonts.scss +27 -0
  67. package/src/styles/main.scss +36 -0
  68. package/src/styles/tokens.scss +301 -0
  69. package/src/styles/typography.scss +232 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@buildcanada/components",
3
- "version": "0.3.4",
3
+ "version": "0.3.5",
4
4
  "description": "Build Canada design system components",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -16,7 +16,8 @@
16
16
  "./src/*": "./src/*"
17
17
  },
18
18
  "files": [
19
- "dist"
19
+ "dist",
20
+ "src"
20
21
  ],
21
22
  "repository": {
22
23
  "type": "git",
@@ -0,0 +1,281 @@
1
+ @use "../../styles/tokens" as *;
2
+ @use "../../styles/typography" as *;
3
+
4
+ /*******************************************************************************
5
+ * Card Component
6
+ ******************************************************************************/
7
+
8
+ .bc-card {
9
+ display: flex;
10
+ flex-direction: column;
11
+ background-color: $white;
12
+ border: 1px solid $border-muted;
13
+ border-radius: $radius-none;
14
+ overflow: hidden;
15
+ text-decoration: none;
16
+ color: inherit;
17
+ transition: box-shadow $transition-fast, transform $transition-fast;
18
+
19
+ /***************************************************************************
20
+ * Variant: Default Card
21
+ ***************************************************************************/
22
+
23
+ &--default {
24
+ .bc-card__content {
25
+ padding: $space-3;
26
+ }
27
+
28
+ .bc-card__title {
29
+ @include h3;
30
+ margin: 0 0 $space-1;
31
+ }
32
+
33
+ .bc-card__description {
34
+ @include body-2;
35
+ color: $text-secondary;
36
+ margin: 0;
37
+ }
38
+
39
+ .bc-card__meta {
40
+ @include micro;
41
+ color: $text-muted;
42
+ margin-top: $space-2;
43
+ }
44
+ }
45
+
46
+ // Interactive cards (when rendered as a or button)
47
+ &--interactive {
48
+ cursor: pointer;
49
+
50
+ &:hover {
51
+ box-shadow: $shadow-md;
52
+ transform: translateY(-2px);
53
+ }
54
+
55
+ &:focus-visible {
56
+ outline: 2px solid $auburn;
57
+ outline-offset: 2px;
58
+ }
59
+ }
60
+
61
+ // Button-specific styles
62
+ &--button {
63
+ border: 1px solid $border-muted;
64
+ text-align: left;
65
+ width: 100%;
66
+ }
67
+
68
+ /***************************************************************************
69
+ * Variant: Project Card
70
+ ***************************************************************************/
71
+
72
+ &--project {
73
+ .bc-card__image {
74
+ aspect-ratio: 16 / 9;
75
+ }
76
+
77
+ .bc-card__content {
78
+ padding: $space-3;
79
+ }
80
+
81
+ .bc-card__title {
82
+ @include h3;
83
+ margin: 0 0 $space-1;
84
+ }
85
+
86
+ .bc-card__description {
87
+ @include body-3;
88
+ color: $text-secondary;
89
+ margin: 0;
90
+ }
91
+ }
92
+
93
+ /***************************************************************************
94
+ * Variant: Memo Card
95
+ ***************************************************************************/
96
+
97
+ &--memo {
98
+ .bc-card__content {
99
+ padding: $space-3;
100
+ }
101
+
102
+ .bc-card__title {
103
+ @include h3;
104
+ margin: 0 0 $space-1;
105
+ }
106
+
107
+ .bc-card__description {
108
+ @include body-2;
109
+ color: $text-secondary;
110
+ margin: 0 0 $space-2;
111
+ display: -webkit-box;
112
+ -webkit-line-clamp: 3;
113
+ -webkit-box-orient: vertical;
114
+ overflow: hidden;
115
+ }
116
+ }
117
+
118
+ /***************************************************************************
119
+ * Variant: Feature Card
120
+ ***************************************************************************/
121
+
122
+ &--feature {
123
+ text-align: center;
124
+ padding: $space-4;
125
+
126
+ .bc-card__icon {
127
+ display: flex;
128
+ align-items: center;
129
+ justify-content: center;
130
+ width: 64px;
131
+ height: 64px;
132
+ margin: 0 auto $space-2;
133
+ background-color: $linen;
134
+ border-radius: $radius-none;
135
+ color: $auburn;
136
+ font-size: 1.5rem;
137
+ }
138
+
139
+ .bc-card__title {
140
+ @include h4;
141
+ margin: 0 0 $space-1;
142
+ }
143
+
144
+ .bc-card__description {
145
+ @include body-3;
146
+ color: $text-secondary;
147
+ margin: 0;
148
+ }
149
+ }
150
+
151
+ /***************************************************************************
152
+ * Variant: Stat Card
153
+ ***************************************************************************/
154
+
155
+ &--stat {
156
+ padding: $space-3;
157
+ background-color: $linen;
158
+ border: none;
159
+
160
+ .bc-card__stat {
161
+ display: flex;
162
+ flex-direction: column;
163
+ gap: calc($space-1 / 2);
164
+ }
165
+
166
+ .bc-card__stat-value {
167
+ @include display-2;
168
+ color: $charcoal;
169
+ }
170
+
171
+ .bc-card__stat-label {
172
+ @include label;
173
+ color: $text-secondary;
174
+ }
175
+
176
+ .bc-card__stat-change {
177
+ @include mono-sm;
178
+ color: $text-secondary;
179
+
180
+ &--up {
181
+ color: $emerald-600;
182
+ }
183
+
184
+ &--down {
185
+ color: $auburn;
186
+ }
187
+ }
188
+ }
189
+
190
+ /***************************************************************************
191
+ * Variant: Profile Card
192
+ ***************************************************************************/
193
+
194
+ &--profile {
195
+ text-align: center;
196
+ padding: $space-4;
197
+
198
+ .bc-card__image {
199
+ width: 120px;
200
+ height: 120px;
201
+ margin: 0 auto $space-2;
202
+ border-radius: $radius-full;
203
+ overflow: hidden;
204
+
205
+ img {
206
+ width: 100%;
207
+ height: 100%;
208
+ object-fit: cover;
209
+ }
210
+ }
211
+
212
+ .bc-card__title {
213
+ @include h4;
214
+ margin: 0 0 calc($space-1 / 2);
215
+ }
216
+
217
+ .bc-card__description {
218
+ @include body-3;
219
+ color: $text-secondary;
220
+ margin: 0;
221
+ }
222
+
223
+ .bc-card__meta {
224
+ display: flex;
225
+ justify-content: center;
226
+ gap: $space-1;
227
+ margin-top: $space-2;
228
+ }
229
+ }
230
+
231
+ /***************************************************************************
232
+ * Subcomponents
233
+ ***************************************************************************/
234
+
235
+ &__image {
236
+ width: 100%;
237
+ overflow: hidden;
238
+
239
+ img {
240
+ width: 100%;
241
+ height: 100%;
242
+ object-fit: cover;
243
+ }
244
+ }
245
+
246
+ &__content {
247
+ flex: 1;
248
+ display: flex;
249
+ flex-direction: column;
250
+ }
251
+
252
+ &__author {
253
+ display: flex;
254
+ align-items: center;
255
+ gap: $space-1;
256
+ margin-top: auto;
257
+ padding-top: $space-2;
258
+ }
259
+
260
+ &__author-avatar {
261
+ width: 40px;
262
+ height: 40px;
263
+ border-radius: $radius-full;
264
+ object-fit: cover;
265
+ }
266
+
267
+ &__author-info {
268
+ display: flex;
269
+ flex-direction: column;
270
+ }
271
+
272
+ &__author-name {
273
+ @include label-sm;
274
+ color: $text-primary;
275
+ }
276
+
277
+ &__author-role {
278
+ @include body-3;
279
+ color: $text-secondary;
280
+ }
281
+ }
@@ -0,0 +1,389 @@
1
+ import type { Meta, StoryObj } from "@storybook/react"
2
+ import { within, userEvent, expect, fn } from "@storybook/test"
3
+ import { faLightbulb, faChartLine, faUsers, faCode } from "@fortawesome/free-solid-svg-icons"
4
+ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
5
+
6
+ import {
7
+ Card,
8
+ CardImage,
9
+ CardIcon,
10
+ CardContent,
11
+ CardTitle,
12
+ CardDescription,
13
+ CardMeta,
14
+ CardStat,
15
+ CardAuthor,
16
+ } from "./Card"
17
+
18
+ const meta: Meta<typeof Card> = {
19
+ title: "Components/Content/Card",
20
+ component: Card,
21
+ parameters: {
22
+ docs: {
23
+ description: {
24
+ component: `
25
+ A composable card component with multiple variants for different content types.
26
+
27
+ ## Usage
28
+
29
+ \`\`\`tsx
30
+ import { Card, CardContent, CardTitle, CardDescription } from "@buildcanada/components"
31
+
32
+ <Card variant="default">
33
+ <CardContent>
34
+ <CardTitle>Card Title</CardTitle>
35
+ <CardDescription>Card description text.</CardDescription>
36
+ </CardContent>
37
+ </Card>
38
+ \`\`\`
39
+
40
+ ## Variants
41
+
42
+ - **default**: Basic card for general content
43
+ - **project**: Card with image for project showcases
44
+ - **memo**: Card for articles/memos with author info
45
+ - **feature**: Card with icon for feature highlights
46
+ - **stat**: Card for displaying statistics
47
+ - **profile**: Card for team member profiles
48
+
49
+ ## Sub-components
50
+
51
+ - \`CardImage\`: Image header for the card
52
+ - \`CardIcon\`: Icon container for feature cards
53
+ - \`CardContent\`: Main content wrapper
54
+ - \`CardTitle\`: Card heading
55
+ - \`CardDescription\`: Card body text
56
+ - \`CardMeta\`: Metadata like dates
57
+ - \`CardStat\`: Statistics display with change indicators
58
+ - \`CardAuthor\`: Author info with avatar
59
+ `,
60
+ },
61
+ },
62
+ },
63
+ argTypes: {
64
+ variant: {
65
+ control: "select",
66
+ options: ["default", "project", "memo", "feature", "stat", "profile"],
67
+ description: "The visual style variant of the card",
68
+ },
69
+ },
70
+ }
71
+
72
+ export default meta
73
+ type Story = StoryObj<typeof Card>
74
+
75
+ export const Default: Story = {
76
+ args: {
77
+ variant: "default",
78
+ children: (
79
+ <CardContent>
80
+ <CardTitle>Card Title</CardTitle>
81
+ <CardDescription>
82
+ This is a description of the card content. It provides more
83
+ details about the subject.
84
+ </CardDescription>
85
+ </CardContent>
86
+ ),
87
+ },
88
+ }
89
+
90
+ export const ProjectCard: Story = {
91
+ args: {
92
+ variant: "project",
93
+ href: "#",
94
+ children: (
95
+ <>
96
+ <CardImage
97
+ src="https://images.unsplash.com/photo-1486406146926-c627a92ad1ab?w=600&h=400&fit=crop"
98
+ alt="Modern building"
99
+ />
100
+ <CardContent>
101
+ <CardTitle>Infrastructure Development</CardTitle>
102
+ <CardDescription>
103
+ A comprehensive analysis of Canada's infrastructure spending
104
+ and development priorities over the past decade.
105
+ </CardDescription>
106
+ <CardMeta>Published March 2024</CardMeta>
107
+ </CardContent>
108
+ </>
109
+ ),
110
+ },
111
+ }
112
+
113
+ export const MemoCard: Story = {
114
+ args: {
115
+ variant: "memo",
116
+ href: "#",
117
+ children: (
118
+ <CardContent>
119
+ <CardTitle>The Future of Canadian Manufacturing</CardTitle>
120
+ <CardDescription>
121
+ How policy changes and technological innovation are reshaping
122
+ Canada's manufacturing sector for the next generation.
123
+ </CardDescription>
124
+ <CardAuthor
125
+ name="Sarah Johnson"
126
+ role="Senior Analyst"
127
+ avatar="https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=100&h=100&fit=crop"
128
+ />
129
+ </CardContent>
130
+ ),
131
+ },
132
+ }
133
+
134
+ export const FeatureCard: Story = {
135
+ args: {
136
+ variant: "feature",
137
+ children: (
138
+ <>
139
+ <CardIcon>
140
+ <FontAwesomeIcon icon={faChartLine} size="2x" />
141
+ </CardIcon>
142
+ <CardContent>
143
+ <CardTitle>Data-Driven Insights</CardTitle>
144
+ <CardDescription>
145
+ Access comprehensive data analysis and visualizations
146
+ to understand government spending patterns.
147
+ </CardDescription>
148
+ </CardContent>
149
+ </>
150
+ ),
151
+ },
152
+ }
153
+
154
+ export const StatCard: Story = {
155
+ args: {
156
+ variant: "stat",
157
+ children: (
158
+ <CardContent>
159
+ <CardStat
160
+ value="$456.2B"
161
+ label="Total Federal Spending"
162
+ change="+8.3%"
163
+ changeDirection="up"
164
+ />
165
+ </CardContent>
166
+ ),
167
+ },
168
+ }
169
+
170
+ export const ProfileCard: Story = {
171
+ args: {
172
+ variant: "profile",
173
+ children: (
174
+ <>
175
+ <CardImage
176
+ src="https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=300&h=300&fit=crop"
177
+ alt="John Smith"
178
+ />
179
+ <CardContent>
180
+ <CardTitle as="h4">John Smith</CardTitle>
181
+ <CardDescription>Director of Research</CardDescription>
182
+ <CardMeta>Ottawa, ON</CardMeta>
183
+ </CardContent>
184
+ </>
185
+ ),
186
+ },
187
+ }
188
+
189
+ // Interactive test: Clickable card
190
+ export const ClickableCardTest: Story = {
191
+ args: {
192
+ variant: "default",
193
+ onClick: fn(),
194
+ children: (
195
+ <CardContent>
196
+ <CardTitle>Clickable Card</CardTitle>
197
+ <CardDescription>Click anywhere on this card.</CardDescription>
198
+ </CardContent>
199
+ ),
200
+ },
201
+ play: async ({ canvasElement, args }) => {
202
+ const canvas = within(canvasElement)
203
+ const card = canvas.getByRole("button")
204
+
205
+ await expect(card).toBeInTheDocument()
206
+ await userEvent.click(card)
207
+ await expect(args.onClick).toHaveBeenCalled()
208
+ },
209
+ }
210
+
211
+ // Interactive test: Link card
212
+ export const LinkCardTest: Story = {
213
+ args: {
214
+ variant: "project",
215
+ href: "#test-link",
216
+ children: (
217
+ <CardContent>
218
+ <CardTitle>Link Card</CardTitle>
219
+ <CardDescription>This card links somewhere.</CardDescription>
220
+ </CardContent>
221
+ ),
222
+ },
223
+ play: async ({ canvasElement }) => {
224
+ const canvas = within(canvasElement)
225
+ const link = canvas.getByRole("link")
226
+
227
+ await expect(link).toHaveAttribute("href", "#test-link")
228
+ },
229
+ }
230
+
231
+ // Interactive test: Card with hover
232
+ export const HoverCardTest: Story = {
233
+ args: {
234
+ variant: "project",
235
+ href: "#",
236
+ children: (
237
+ <>
238
+ <CardImage
239
+ src="https://images.unsplash.com/photo-1486406146926-c627a92ad1ab?w=600&h=400&fit=crop"
240
+ alt="Building"
241
+ />
242
+ <CardContent>
243
+ <CardTitle>Hover Card</CardTitle>
244
+ <CardDescription>Hover to see the effect.</CardDescription>
245
+ </CardContent>
246
+ </>
247
+ ),
248
+ },
249
+ play: async ({ canvasElement }) => {
250
+ const canvas = within(canvasElement)
251
+ const card = canvas.getByRole("link")
252
+
253
+ await userEvent.hover(card)
254
+ // Visual check for hover state
255
+ },
256
+ }
257
+
258
+ export const FeatureCardsGrid: Story = {
259
+ render: () => (
260
+ <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(280px, 1fr))", gap: "24px" }}>
261
+ <Card variant="feature">
262
+ <CardIcon>
263
+ <FontAwesomeIcon icon={faChartLine} size="2x" />
264
+ </CardIcon>
265
+ <CardContent>
266
+ <CardTitle>Analytics</CardTitle>
267
+ <CardDescription>
268
+ Comprehensive data analysis tools for government spending.
269
+ </CardDescription>
270
+ </CardContent>
271
+ </Card>
272
+ <Card variant="feature">
273
+ <CardIcon>
274
+ <FontAwesomeIcon icon={faUsers} size="2x" />
275
+ </CardIcon>
276
+ <CardContent>
277
+ <CardTitle>Collaboration</CardTitle>
278
+ <CardDescription>
279
+ Work together with researchers across Canada.
280
+ </CardDescription>
281
+ </CardContent>
282
+ </Card>
283
+ <Card variant="feature">
284
+ <CardIcon>
285
+ <FontAwesomeIcon icon={faLightbulb} size="2x" />
286
+ </CardIcon>
287
+ <CardContent>
288
+ <CardTitle>Insights</CardTitle>
289
+ <CardDescription>
290
+ Discover patterns and trends in public data.
291
+ </CardDescription>
292
+ </CardContent>
293
+ </Card>
294
+ <Card variant="feature">
295
+ <CardIcon>
296
+ <FontAwesomeIcon icon={faCode} size="2x" />
297
+ </CardIcon>
298
+ <CardContent>
299
+ <CardTitle>Open Source</CardTitle>
300
+ <CardDescription>
301
+ All our tools and data are freely available.
302
+ </CardDescription>
303
+ </CardContent>
304
+ </Card>
305
+ </div>
306
+ ),
307
+ }
308
+
309
+ export const StatCardsRow: Story = {
310
+ render: () => (
311
+ <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(200px, 1fr))", gap: "16px" }}>
312
+ <Card variant="stat">
313
+ <CardContent>
314
+ <CardStat
315
+ value="$456.2B"
316
+ label="Federal Spending"
317
+ change="+8.3%"
318
+ changeDirection="up"
319
+ />
320
+ </CardContent>
321
+ </Card>
322
+ <Card variant="stat">
323
+ <CardContent>
324
+ <CardStat
325
+ value="2.4M"
326
+ label="Public Servants"
327
+ change="-1.2%"
328
+ changeDirection="down"
329
+ />
330
+ </CardContent>
331
+ </Card>
332
+ <Card variant="stat">
333
+ <CardContent>
334
+ <CardStat
335
+ value="14"
336
+ label="Provinces & Territories"
337
+ changeDirection="neutral"
338
+ />
339
+ </CardContent>
340
+ </Card>
341
+ </div>
342
+ ),
343
+ }
344
+
345
+ export const ProjectCardsGrid: Story = {
346
+ render: () => (
347
+ <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(300px, 1fr))", gap: "24px" }}>
348
+ <Card variant="project" href="#">
349
+ <CardImage
350
+ src="https://images.unsplash.com/photo-1486406146926-c627a92ad1ab?w=600&h=400&fit=crop"
351
+ alt="Infrastructure"
352
+ />
353
+ <CardContent>
354
+ <CardTitle>Infrastructure Report 2024</CardTitle>
355
+ <CardDescription>
356
+ Analysis of federal infrastructure investments.
357
+ </CardDescription>
358
+ <CardMeta>March 2024</CardMeta>
359
+ </CardContent>
360
+ </Card>
361
+ <Card variant="project" href="#">
362
+ <CardImage
363
+ src="https://images.unsplash.com/photo-1454165804606-c3d57bc86b40?w=600&h=400&fit=crop"
364
+ alt="Budget"
365
+ />
366
+ <CardContent>
367
+ <CardTitle>Budget Breakdown</CardTitle>
368
+ <CardDescription>
369
+ Comprehensive federal budget analysis.
370
+ </CardDescription>
371
+ <CardMeta>February 2024</CardMeta>
372
+ </CardContent>
373
+ </Card>
374
+ <Card variant="project" href="#">
375
+ <CardImage
376
+ src="https://images.unsplash.com/photo-1551288049-bebda4e38f71?w=600&h=400&fit=crop"
377
+ alt="Healthcare"
378
+ />
379
+ <CardContent>
380
+ <CardTitle>Healthcare Spending</CardTitle>
381
+ <CardDescription>
382
+ Provincial healthcare expenditure trends.
383
+ </CardDescription>
384
+ <CardMeta>January 2024</CardMeta>
385
+ </CardContent>
386
+ </Card>
387
+ </div>
388
+ ),
389
+ }