@fpkit/acss 3.5.0 → 3.7.0
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/libs/{chunk-URBGDUFN.cjs → chunk-75YQDONV.cjs} +3 -3
- package/libs/chunk-AOFQDQVS.cjs +17 -0
- package/libs/chunk-AOFQDQVS.cjs.map +1 -0
- package/libs/{chunk-ZF6Y7W57.js → chunk-G3TFKMWB.js} +2 -2
- package/libs/chunk-Q7OAQLUT.js +10 -0
- package/libs/chunk-Q7OAQLUT.js.map +1 -0
- package/libs/components/alert/alert.css +1 -0
- package/libs/components/alert/alert.css.map +1 -0
- package/libs/components/alert/alert.min.css +3 -0
- package/libs/components/badge/badge.css +1 -0
- package/libs/components/badge/badge.css.map +1 -0
- package/libs/components/badge/badge.min.css +3 -0
- package/libs/components/box/box.css +1 -0
- package/libs/components/box/box.css.map +1 -0
- package/libs/components/box/box.min.css +3 -0
- package/libs/components/breadcrumbs/breadcrumb.css +1 -0
- package/libs/components/breadcrumbs/breadcrumb.css.map +1 -0
- package/libs/components/breadcrumbs/breadcrumb.min.css +3 -0
- package/libs/components/buttons/button.css +1 -0
- package/libs/components/buttons/button.css.map +1 -0
- package/libs/components/buttons/button.min.css +3 -0
- package/libs/components/cards/card-style.css +1 -0
- package/libs/components/cards/card-style.css.map +1 -0
- package/libs/components/cards/card-style.min.css +3 -0
- package/libs/components/cards/card.css +1 -0
- package/libs/components/cards/card.css.map +1 -0
- package/libs/components/cards/card.min.css +3 -0
- package/libs/components/cluster/cluster.css +1 -0
- package/libs/components/cluster/cluster.css.map +1 -0
- package/libs/components/cluster/cluster.min.css +3 -0
- package/libs/components/details/details.css +1 -0
- package/libs/components/details/details.css.map +1 -0
- package/libs/components/details/details.min.css +3 -0
- package/libs/components/dialog/dialog.cjs +4 -4
- package/libs/components/dialog/dialog.css +1 -0
- package/libs/components/dialog/dialog.css.map +1 -0
- package/libs/components/dialog/dialog.js +2 -2
- package/libs/components/dialog/dialog.min.css +3 -0
- package/libs/components/flexbox/flex.css +1 -0
- package/libs/components/flexbox/flex.css.map +1 -0
- package/libs/components/flexbox/flex.min.css +3 -0
- package/libs/components/form/form.css +1 -0
- package/libs/components/form/form.css.map +1 -0
- package/libs/components/form/form.min.css +3 -0
- package/libs/components/grid/grid.css +1 -0
- package/libs/components/grid/grid.css.map +1 -0
- package/libs/components/grid/grid.min.css +3 -0
- package/libs/components/heading/heading.cjs +2 -2
- package/libs/components/heading/heading.d.cts +1 -1
- package/libs/components/heading/heading.d.ts +1 -1
- package/libs/components/heading/heading.js +1 -1
- package/libs/components/icons/icon.css +1 -0
- package/libs/components/icons/icon.css.map +1 -0
- package/libs/components/icons/icon.min.css +3 -0
- package/libs/components/images/img.css +1 -0
- package/libs/components/images/img.css.map +1 -0
- package/libs/components/images/img.min.css +3 -0
- package/libs/components/layout/landmarks.css +1 -0
- package/libs/components/layout/landmarks.css.map +1 -0
- package/libs/components/layout/landmarks.min.css +3 -0
- package/libs/components/link/link.css +1 -0
- package/libs/components/link/link.css.map +1 -0
- package/libs/components/link/link.min.css +3 -0
- package/libs/components/list/list.css +1 -0
- package/libs/components/list/list.css.map +1 -0
- package/libs/components/list/list.min.css +3 -0
- package/libs/components/nav/nav.css +1 -0
- package/libs/components/nav/nav.css.map +1 -0
- package/libs/components/nav/nav.min.css +3 -0
- package/libs/components/progress/progress.css +1 -0
- package/libs/components/progress/progress.css.map +1 -0
- package/libs/components/progress/progress.min.css +3 -0
- package/libs/components/stack/stack.css +1 -0
- package/libs/components/stack/stack.css.map +1 -0
- package/libs/components/stack/stack.min.css +3 -0
- package/libs/components/styles/index.css +1 -0
- package/libs/components/styles/index.css.map +1 -0
- package/libs/components/styles/index.min.css +3 -0
- package/libs/components/tag/tag.css +1 -0
- package/libs/components/tag/tag.css.map +1 -0
- package/libs/components/tag/tag.min.css +3 -0
- package/libs/components/text-to-speech/text-to-speech.css +1 -0
- package/libs/components/text-to-speech/text-to-speech.css.map +1 -0
- package/libs/components/text-to-speech/text-to-speech.min.css +3 -0
- package/libs/components/title/title.css +1 -0
- package/libs/components/title/title.css.map +1 -0
- package/libs/components/title/title.min.css +3 -0
- package/libs/{heading-7446cb46.d.ts → heading-81eef89a.d.ts} +42 -0
- package/libs/index.cjs +10 -10
- package/libs/index.cjs.map +1 -1
- package/libs/index.css +1 -0
- package/libs/index.css.map +1 -0
- package/libs/index.d.cts +25 -8
- package/libs/index.d.ts +25 -8
- package/libs/index.js +6 -6
- package/libs/index.js.map +1 -1
- package/package.json +2 -2
- package/src/components/box/box.stories.tsx +1 -1
- package/src/components/cluster/cluster.stories.tsx +1 -1
- package/src/components/col/README.mdx +233 -9
- package/src/components/col/STYLES.mdx +1380 -0
- package/src/components/col/col.stories.tsx +1614 -8
- package/src/components/grid/grid.stories.tsx +130 -35
- package/src/components/row/row.stories.tsx +1 -1
- package/src/components/row/row.tsx +9 -0
- package/src/components/row/row.types.ts +24 -7
- package/src/components/stack/stack.stories.tsx +219 -60
- package/src/components/title/README.mdx +87 -1
- package/src/components/title/STYLES.mdx +501 -0
- package/src/components/title/title.scss +51 -0
- package/src/components/title/title.stories.tsx +158 -0
- package/src/components/title/title.test.tsx +113 -0
- package/src/components/title/title.tsx +53 -1
- package/src/index.scss +1 -0
- package/src/sass/_columns.scss +122 -3
- package/src/sass/columns.stories.tsx +434 -10
- package/src/styles/index.css +533 -3
- package/src/styles/index.css.map +1 -1
- package/src/styles/title/title.css +75 -0
- package/src/styles/title/title.css.map +1 -0
- package/libs/chunk-2C3YLBWP.cjs +0 -17
- package/libs/chunk-2C3YLBWP.cjs.map +0 -1
- package/libs/chunk-KDMX3FAW.js +0 -10
- package/libs/chunk-KDMX3FAW.js.map +0 -1
- /package/libs/{chunk-URBGDUFN.cjs.map → chunk-75YQDONV.cjs.map} +0 -0
- /package/libs/{chunk-ZF6Y7W57.js.map → chunk-G3TFKMWB.js.map} +0 -0
|
@@ -70,6 +70,24 @@ If you're migrating from the deprecated \`Heading\` component:
|
|
|
70
70
|
control: "text",
|
|
71
71
|
description: "CSS class names to apply",
|
|
72
72
|
},
|
|
73
|
+
size: {
|
|
74
|
+
control: { type: "select" },
|
|
75
|
+
options: ["xs", "sm", "md", "lg", "xl", "2xl"],
|
|
76
|
+
description: "Visual size variant (independent of semantic level)",
|
|
77
|
+
table: {
|
|
78
|
+
type: { summary: "xs | sm | md | lg | xl | 2xl" },
|
|
79
|
+
defaultValue: { summary: "undefined" },
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
color: {
|
|
83
|
+
control: { type: "select" },
|
|
84
|
+
options: ["primary", "secondary", "accent", "muted", "inherit"],
|
|
85
|
+
description: "Color variant for the title text",
|
|
86
|
+
table: {
|
|
87
|
+
type: { summary: "primary | secondary | accent | muted | inherit" },
|
|
88
|
+
defaultValue: { summary: "undefined" },
|
|
89
|
+
},
|
|
90
|
+
},
|
|
73
91
|
},
|
|
74
92
|
args: {
|
|
75
93
|
children: "Default Title",
|
|
@@ -391,3 +409,143 @@ Use \`aria-label\` when the visible text doesn't provide enough context for scre
|
|
|
391
409
|
expect(heading).toHaveAttribute("aria-label", "User dashboard statistics overview");
|
|
392
410
|
},
|
|
393
411
|
};
|
|
412
|
+
|
|
413
|
+
/**
|
|
414
|
+
* Size variants demonstration.
|
|
415
|
+
*/
|
|
416
|
+
export const SizeVariants: Story = {
|
|
417
|
+
render: () => (
|
|
418
|
+
<div style={{ display: "flex", flexDirection: "column", gap: "1rem" }}>
|
|
419
|
+
<Title level="h2" size="xs">Extra Small (xs)</Title>
|
|
420
|
+
<Title level="h2" size="sm">Small (sm)</Title>
|
|
421
|
+
<Title level="h2" size="md">Medium (md)</Title>
|
|
422
|
+
<Title level="h2" size="lg">Large (lg)</Title>
|
|
423
|
+
<Title level="h2" size="xl">Extra Large (xl)</Title>
|
|
424
|
+
<Title level="h2" size="2xl">2X Large (2xl)</Title>
|
|
425
|
+
</div>
|
|
426
|
+
),
|
|
427
|
+
parameters: {
|
|
428
|
+
docs: {
|
|
429
|
+
description: {
|
|
430
|
+
story: "T-shirt size variants allow visual sizing independent of semantic heading level.",
|
|
431
|
+
},
|
|
432
|
+
},
|
|
433
|
+
},
|
|
434
|
+
};
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
* Color variants demonstration.
|
|
438
|
+
*/
|
|
439
|
+
export const ColorVariants: Story = {
|
|
440
|
+
render: () => (
|
|
441
|
+
<div style={{ display: "flex", flexDirection: "column", gap: "1rem" }}>
|
|
442
|
+
<Title size="lg" color="primary">Primary Color</Title>
|
|
443
|
+
<Title size="lg" color="secondary">Secondary Color</Title>
|
|
444
|
+
<Title size="lg" color="accent">Accent Color</Title>
|
|
445
|
+
<Title size="lg" color="muted">Muted Color</Title>
|
|
446
|
+
<Title size="lg" color="inherit">Inherit Color</Title>
|
|
447
|
+
</div>
|
|
448
|
+
),
|
|
449
|
+
parameters: {
|
|
450
|
+
docs: {
|
|
451
|
+
description: {
|
|
452
|
+
story: "Color variants meet WCAG AA contrast requirements. All colors tested at 4.5:1 minimum.",
|
|
453
|
+
},
|
|
454
|
+
},
|
|
455
|
+
},
|
|
456
|
+
};
|
|
457
|
+
|
|
458
|
+
/**
|
|
459
|
+
* Combined size and color variants.
|
|
460
|
+
*/
|
|
461
|
+
export const CombinedVariants: Story = {
|
|
462
|
+
render: () => (
|
|
463
|
+
<div style={{ display: "flex", flexDirection: "column", gap: "1rem" }}>
|
|
464
|
+
<Title level="h1" size="2xl" color="primary">
|
|
465
|
+
Large Primary Heading
|
|
466
|
+
</Title>
|
|
467
|
+
<Title level="h2" size="lg" color="secondary">
|
|
468
|
+
Medium Secondary Heading
|
|
469
|
+
</Title>
|
|
470
|
+
<Title level="h3" size="md" color="accent">
|
|
471
|
+
Small Accent Heading
|
|
472
|
+
</Title>
|
|
473
|
+
</div>
|
|
474
|
+
),
|
|
475
|
+
parameters: {
|
|
476
|
+
docs: {
|
|
477
|
+
description: {
|
|
478
|
+
story: "Combine size and color variants for flexible design while maintaining semantic HTML structure.",
|
|
479
|
+
},
|
|
480
|
+
},
|
|
481
|
+
},
|
|
482
|
+
play: async ({ canvasElement }) => {
|
|
483
|
+
const canvas = within(canvasElement);
|
|
484
|
+
const h1 = canvas.getByRole("heading", { level: 1 });
|
|
485
|
+
expect(h1).toHaveAttribute("data-title", "2xl primary");
|
|
486
|
+
expect(h1).toBeInTheDocument();
|
|
487
|
+
},
|
|
488
|
+
};
|
|
489
|
+
|
|
490
|
+
/**
|
|
491
|
+
* Visual vs semantic hierarchy example.
|
|
492
|
+
*/
|
|
493
|
+
export const VisualVsSemanticHierarchy: Story = {
|
|
494
|
+
render: () => (
|
|
495
|
+
<div style={{ display: "flex", flexDirection: "column", gap: "1.5rem" }}>
|
|
496
|
+
<div>
|
|
497
|
+
<Title level="h2" size="xl" color="primary">
|
|
498
|
+
h2 with XL Visual Size
|
|
499
|
+
</Title>
|
|
500
|
+
<p>Semantically an h2, but visually appears larger for design emphasis.</p>
|
|
501
|
+
</div>
|
|
502
|
+
|
|
503
|
+
<div>
|
|
504
|
+
<Title level="h1" size="md" color="secondary">
|
|
505
|
+
h1 with Medium Visual Size
|
|
506
|
+
</Title>
|
|
507
|
+
<p>Semantically the main heading (h1), but styled smaller for visual balance.</p>
|
|
508
|
+
</div>
|
|
509
|
+
</div>
|
|
510
|
+
),
|
|
511
|
+
parameters: {
|
|
512
|
+
docs: {
|
|
513
|
+
description: {
|
|
514
|
+
story: `
|
|
515
|
+
**Design Flexibility with Semantic Integrity**
|
|
516
|
+
|
|
517
|
+
Visual size can differ from semantic heading level. This allows:
|
|
518
|
+
- Design requirements to be met without sacrificing accessibility
|
|
519
|
+
- Proper document outline for screen readers (h1 → h2 → h3...)
|
|
520
|
+
- Visual hierarchy that matches design specs
|
|
521
|
+
|
|
522
|
+
**Example**: A page with multiple sections may need an h2 visually larger than an h1 for design, while maintaining proper semantic structure.
|
|
523
|
+
`,
|
|
524
|
+
},
|
|
525
|
+
},
|
|
526
|
+
},
|
|
527
|
+
};
|
|
528
|
+
|
|
529
|
+
/**
|
|
530
|
+
* CSS custom property override example.
|
|
531
|
+
*/
|
|
532
|
+
export const CustomPropertyOverride: Story = {
|
|
533
|
+
args: {
|
|
534
|
+
level: "h2",
|
|
535
|
+
size: "lg",
|
|
536
|
+
color: "primary",
|
|
537
|
+
styles: {
|
|
538
|
+
"--title-fs": "3rem",
|
|
539
|
+
"--title-color": "#10b981",
|
|
540
|
+
"--title-fw": "700",
|
|
541
|
+
},
|
|
542
|
+
children: "Custom Overridden Title",
|
|
543
|
+
},
|
|
544
|
+
parameters: {
|
|
545
|
+
docs: {
|
|
546
|
+
description: {
|
|
547
|
+
story: "Override CSS custom properties via the styles prop for maximum flexibility.",
|
|
548
|
+
},
|
|
549
|
+
},
|
|
550
|
+
},
|
|
551
|
+
};
|
|
@@ -249,3 +249,116 @@ describe("Title Component - Backwards Compatibility", () => {
|
|
|
249
249
|
});
|
|
250
250
|
});
|
|
251
251
|
});
|
|
252
|
+
|
|
253
|
+
describe("Title Size Variants", () => {
|
|
254
|
+
it("should render with size prop and correct data-title", () => {
|
|
255
|
+
render(<Title size="lg">Large</Title>);
|
|
256
|
+
const heading = screen.getByRole("heading", { level: 2 });
|
|
257
|
+
expect(heading).toHaveAttribute("data-title", "lg");
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
it.each([
|
|
261
|
+
["xs"],
|
|
262
|
+
["sm"],
|
|
263
|
+
["md"],
|
|
264
|
+
["lg"],
|
|
265
|
+
["xl"],
|
|
266
|
+
["2xl"],
|
|
267
|
+
] as const)("should render size variant %s", (size) => {
|
|
268
|
+
render(<Title size={size}>{size} Title</Title>);
|
|
269
|
+
const heading = screen.getByRole("heading", { level: 2 });
|
|
270
|
+
expect(heading).toHaveAttribute("data-title", size);
|
|
271
|
+
});
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
describe("Title Color Variants", () => {
|
|
275
|
+
it("should render with color prop and correct data-title", () => {
|
|
276
|
+
render(<Title color="primary">Primary</Title>);
|
|
277
|
+
const heading = screen.getByRole("heading", { level: 2 });
|
|
278
|
+
expect(heading).toHaveAttribute("data-title", "primary");
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
it.each([
|
|
282
|
+
["primary"],
|
|
283
|
+
["secondary"],
|
|
284
|
+
["accent"],
|
|
285
|
+
["muted"],
|
|
286
|
+
["inherit"],
|
|
287
|
+
] as const)("should render color variant %s", (color) => {
|
|
288
|
+
render(<Title color={color}>{color} Title</Title>);
|
|
289
|
+
const heading = screen.getByRole("heading", { level: 2 });
|
|
290
|
+
expect(heading).toHaveAttribute("data-title", color);
|
|
291
|
+
});
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
describe("Combined Size and Color Variants", () => {
|
|
295
|
+
it("should combine size and color in data-title attribute", () => {
|
|
296
|
+
render(<Title size="lg" color="primary">Combined</Title>);
|
|
297
|
+
const heading = screen.getByRole("heading", { level: 2 });
|
|
298
|
+
expect(heading).toHaveAttribute("data-title", "lg primary");
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
it("should render only size when no color provided", () => {
|
|
302
|
+
render(<Title size="xl">Size Only</Title>);
|
|
303
|
+
const heading = screen.getByRole("heading", { level: 2 });
|
|
304
|
+
expect(heading).toHaveAttribute("data-title", "xl");
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
it("should render only color when no size provided", () => {
|
|
308
|
+
render(<Title color="accent">Color Only</Title>);
|
|
309
|
+
const heading = screen.getByRole("heading", { level: 2 });
|
|
310
|
+
expect(heading).toHaveAttribute("data-title", "accent");
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
it("should render no data-title when no variants provided", () => {
|
|
314
|
+
render(<Title>No Variants</Title>);
|
|
315
|
+
const heading = screen.getByRole("heading", { level: 2 });
|
|
316
|
+
expect(heading).not.toHaveAttribute("data-title");
|
|
317
|
+
});
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
describe("Backward Compatibility with New Props", () => {
|
|
321
|
+
it("should maintain className functionality with variants", () => {
|
|
322
|
+
render(<Title size="lg" className="custom-class">Custom</Title>);
|
|
323
|
+
const heading = screen.getByRole("heading", { level: 2 });
|
|
324
|
+
expect(heading).toHaveClass("custom-class");
|
|
325
|
+
expect(heading).toHaveAttribute("data-title", "lg");
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
it("should maintain styles prop functionality with variants", () => {
|
|
329
|
+
render(<Title color="primary" styles={{ marginTop: "2rem" }}>Styled</Title>);
|
|
330
|
+
const heading = screen.getByRole("heading", { level: 2 });
|
|
331
|
+
expect(heading).toHaveStyle({ marginTop: "2rem" });
|
|
332
|
+
expect(heading).toHaveAttribute("data-title", "primary");
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
it("should preserve semantic heading level with visual size", () => {
|
|
336
|
+
render(<Title level="h3" size="xl">Large h3</Title>);
|
|
337
|
+
const heading = screen.getByRole("heading", { level: 3 });
|
|
338
|
+
expect(heading).toBeInTheDocument();
|
|
339
|
+
expect(heading).toHaveAttribute("data-title", "xl");
|
|
340
|
+
expect(heading.tagName.toLowerCase()).toBe("h3");
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
it("should work with all existing props plus new variants", () => {
|
|
344
|
+
render(
|
|
345
|
+
<Title
|
|
346
|
+
level="h2"
|
|
347
|
+
size="lg"
|
|
348
|
+
color="primary"
|
|
349
|
+
id="test-id"
|
|
350
|
+
className="test-class"
|
|
351
|
+
ui="section-title"
|
|
352
|
+
styles={{ padding: "1rem" }}
|
|
353
|
+
>
|
|
354
|
+
Full Props Test
|
|
355
|
+
</Title>
|
|
356
|
+
);
|
|
357
|
+
const heading = screen.getByRole("heading", { level: 2 });
|
|
358
|
+
expect(heading).toHaveAttribute("id", "test-id");
|
|
359
|
+
expect(heading).toHaveClass("test-class");
|
|
360
|
+
expect(heading).toHaveAttribute("data-ui", "section-title");
|
|
361
|
+
expect(heading).toHaveAttribute("data-title", "lg primary");
|
|
362
|
+
expect(heading).toHaveStyle({ padding: "1rem" });
|
|
363
|
+
});
|
|
364
|
+
});
|
|
@@ -21,6 +21,18 @@ import UI from "#components/ui";
|
|
|
21
21
|
*/
|
|
22
22
|
export type HeadingLevel = "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
|
|
23
23
|
|
|
24
|
+
/**
|
|
25
|
+
* Visual size variants for Title component.
|
|
26
|
+
* Independent of semantic heading level for flexible design.
|
|
27
|
+
*/
|
|
28
|
+
export type TitleSize = "xs" | "sm" | "md" | "lg" | "xl" | "2xl";
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Color variants for Title component.
|
|
32
|
+
* All variants meet WCAG 2.1 AA contrast requirements (4.5:1 minimum).
|
|
33
|
+
*/
|
|
34
|
+
export type TitleColor = "primary" | "secondary" | "accent" | "muted" | "inherit";
|
|
35
|
+
|
|
24
36
|
/**
|
|
25
37
|
* Props for the Title component.
|
|
26
38
|
*
|
|
@@ -93,6 +105,40 @@ export type TitleProps = {
|
|
|
93
105
|
* utility classes or custom overrides.
|
|
94
106
|
*/
|
|
95
107
|
className?: string;
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Visual size variant (independent of semantic heading level).
|
|
111
|
+
*
|
|
112
|
+
* @default undefined (uses browser default or custom CSS)
|
|
113
|
+
*
|
|
114
|
+
* @remarks
|
|
115
|
+
* Choose the appropriate visual size based on design needs:
|
|
116
|
+
* - xs: 0.75rem (12px) - Very small accent headings
|
|
117
|
+
* - sm: 0.875rem (14px) - Small headings
|
|
118
|
+
* - md: 1rem (16px) - Medium headings
|
|
119
|
+
* - lg: 1.5rem (24px) - Large headings
|
|
120
|
+
* - xl: 2rem (32px) - Extra large headings
|
|
121
|
+
* - 2xl: 2.5rem (40px) - Largest headings
|
|
122
|
+
*
|
|
123
|
+
* Visual size is independent of semantic level, allowing design
|
|
124
|
+
* flexibility while maintaining proper document structure.
|
|
125
|
+
*/
|
|
126
|
+
size?: TitleSize;
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Color variant for the title text.
|
|
130
|
+
*
|
|
131
|
+
* @default undefined (inherits color from parent)
|
|
132
|
+
*
|
|
133
|
+
* @remarks
|
|
134
|
+
* All color variants meet WCAG 2.1 Level AA contrast requirements (4.5:1 minimum):
|
|
135
|
+
* - primary: Dark blue (#1e3a8a) - 8.59:1 contrast
|
|
136
|
+
* - secondary: Gray (#4b5563) - 7.56:1 contrast
|
|
137
|
+
* - accent: Purple (#7c3aed) - 4.62:1 contrast
|
|
138
|
+
* - muted: Light gray (#6b7280) - 5.49:1 contrast
|
|
139
|
+
* - inherit: Inherits color from parent element
|
|
140
|
+
*/
|
|
141
|
+
color?: TitleColor;
|
|
96
142
|
} & React.ComponentPropsWithoutRef<typeof UI>;
|
|
97
143
|
|
|
98
144
|
/**
|
|
@@ -188,6 +234,8 @@ const Title = React.memo(
|
|
|
188
234
|
(
|
|
189
235
|
{
|
|
190
236
|
level = "h2",
|
|
237
|
+
size,
|
|
238
|
+
color,
|
|
191
239
|
id,
|
|
192
240
|
styles,
|
|
193
241
|
ui,
|
|
@@ -197,13 +245,17 @@ const Title = React.memo(
|
|
|
197
245
|
}: TitleProps,
|
|
198
246
|
ref
|
|
199
247
|
) => {
|
|
248
|
+
// Construct space-separated data-title attribute
|
|
249
|
+
const dataTitle = [size, color].filter(Boolean).join(" ") || undefined;
|
|
250
|
+
|
|
200
251
|
return (
|
|
201
252
|
<UI
|
|
202
253
|
as={level}
|
|
203
254
|
id={id}
|
|
204
255
|
styles={styles}
|
|
205
256
|
data-ui={ui}
|
|
206
|
-
|
|
257
|
+
data-title={dataTitle}
|
|
258
|
+
classes={className}
|
|
207
259
|
ref={ref}
|
|
208
260
|
{...props}
|
|
209
261
|
>
|
package/src/index.scss
CHANGED
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
@use "./components/list/list.scss";
|
|
28
28
|
@use "./components/alert/alert.scss";
|
|
29
29
|
@use "./components/text-to-speech/text-to-speech.scss";
|
|
30
|
+
@use "./components/title/title.scss";
|
|
30
31
|
@use "./components/flexbox/flex.scss";
|
|
31
32
|
@use "./sass/styles/shadows";
|
|
32
33
|
@use "./sass/styles/colors";
|
package/src/sass/_columns.scss
CHANGED
|
@@ -30,6 +30,32 @@
|
|
|
30
30
|
--col-12: 100%;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
/**
|
|
34
|
+
* Responsive Breakpoints (mobile-first)
|
|
35
|
+
* These CSS custom properties document the breakpoint values and can be
|
|
36
|
+
* accessed via JavaScript. SCSS uses literal values for media queries.
|
|
37
|
+
*/
|
|
38
|
+
:root {
|
|
39
|
+
--col-breakpoint-xs: 0rem; /* 0px - base mobile */
|
|
40
|
+
--col-breakpoint-sm: 30rem; /* 480px - large phones */
|
|
41
|
+
--col-breakpoint-md: 48rem; /* 768px - tablets */
|
|
42
|
+
--col-breakpoint-lg: 64rem; /* 1024px - desktops */
|
|
43
|
+
|
|
44
|
+
/* Legacy support - keep for backward compatibility */
|
|
45
|
+
--col-breakpoint: var(--col-breakpoint-md);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Breakpoint map for SCSS loop generation
|
|
50
|
+
* Uses literal rem values (not CSS custom properties) because
|
|
51
|
+
* @media queries require compile-time values, not runtime CSS variables.
|
|
52
|
+
*/
|
|
53
|
+
$col-breakpoints: (
|
|
54
|
+
'sm': 30rem,
|
|
55
|
+
'md': 48rem,
|
|
56
|
+
'lg': 64rem,
|
|
57
|
+
);
|
|
58
|
+
|
|
33
59
|
/* ============================================================================
|
|
34
60
|
Row Container Utility (Optional)
|
|
35
61
|
========================================================================== */
|
|
@@ -120,21 +146,68 @@
|
|
|
120
146
|
}
|
|
121
147
|
|
|
122
148
|
/* ============================================================================
|
|
123
|
-
|
|
149
|
+
Responsive Column Span Utilities (Generated)
|
|
150
|
+
========================================================================== */
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Generate responsive span utilities for all breakpoints
|
|
154
|
+
* Produces: .col-{sm|md|lg}-{1-12}, .col-{sm|md|lg}-auto, .col-{sm|md|lg}-flex
|
|
155
|
+
*
|
|
156
|
+
* These utilities enable mobile-first responsive layouts where columns can
|
|
157
|
+
* have different widths at different breakpoints. For example:
|
|
158
|
+
* .col-12.col-md-6.col-lg-4 creates a layout that:
|
|
159
|
+
* - Stacks full-width (100%) on mobile (< 768px)
|
|
160
|
+
* - Shows 2 columns (50%) on tablets (>= 768px)
|
|
161
|
+
* - Shows 3 columns (33.33%) on desktops (>= 1024px)
|
|
162
|
+
*/
|
|
163
|
+
@each $breakpoint, $min-width in $col-breakpoints {
|
|
164
|
+
@media (width >= #{$min-width}) {
|
|
165
|
+
// Generate .col-{breakpoint}-{1-12} classes
|
|
166
|
+
@for $i from 1 through 12 {
|
|
167
|
+
.col-#{$breakpoint}-#{$i} {
|
|
168
|
+
flex: 0 1 var(--col-#{$i});
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Auto-width variant - sizes to content
|
|
173
|
+
.col-#{$breakpoint}-auto {
|
|
174
|
+
flex: 0 0 auto;
|
|
175
|
+
width: auto;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Flex-grow variant - grows to fill remaining space
|
|
179
|
+
.col-#{$breakpoint}-flex {
|
|
180
|
+
flex: 1 1 0%;
|
|
181
|
+
min-width: 0;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/* ============================================================================
|
|
187
|
+
DEPRECATED: Proportional Layout Mode
|
|
124
188
|
========================================================================== */
|
|
125
189
|
|
|
126
190
|
/**
|
|
191
|
+
* @deprecated Use responsive utility classes instead (.col-sm-*, .col-md-*, .col-lg-*)
|
|
192
|
+
* This class will be removed in v5.0.0
|
|
193
|
+
*
|
|
127
194
|
* .col-row-proportional prevents columns from stacking on tablets and larger.
|
|
128
195
|
* Columns still stack on mobile phones (< 30rem / 480px) for readability,
|
|
129
196
|
* but maintain proportional widths on tablets and desktops (>= 30rem / 480px).
|
|
130
197
|
*
|
|
131
|
-
*
|
|
198
|
+
* Migration:
|
|
199
|
+
* Before: <Row alwaysProportional><Col span={6} /></Row>
|
|
200
|
+
* After: <Row><div className="col-sm-6" /></Row>
|
|
201
|
+
*
|
|
202
|
+
* Backward compatibility maintained for now, but use responsive utilities for new code.
|
|
203
|
+
*
|
|
204
|
+
* Usage with Row component (deprecated):
|
|
132
205
|
* <Row alwaysProportional>
|
|
133
206
|
* <Col span={6}>Column 1</Col>
|
|
134
207
|
* <Col span={6}>Column 2</Col>
|
|
135
208
|
* </Row>
|
|
136
209
|
*
|
|
137
|
-
* Usage with vanilla HTML:
|
|
210
|
+
* Usage with vanilla HTML (deprecated):
|
|
138
211
|
* <div className="col-row col-row-proportional">
|
|
139
212
|
* <div className="col-6">Column 1</div>
|
|
140
213
|
* <div className="col-6">Column 2</div>
|
|
@@ -236,6 +309,27 @@
|
|
|
236
309
|
}
|
|
237
310
|
}
|
|
238
311
|
|
|
312
|
+
/* ============================================================================
|
|
313
|
+
Responsive Column Offset Utilities (Generated)
|
|
314
|
+
========================================================================== */
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Generate responsive offset utilities for all breakpoints
|
|
318
|
+
* Produces: .col-{sm|md|lg}-offset-{0-11}
|
|
319
|
+
*
|
|
320
|
+
* Responsive offsets enable pushing columns to the right at specific breakpoints.
|
|
321
|
+
* For example: .col-md-offset-3 adds left margin equal to 3 columns on tablets+
|
|
322
|
+
*/
|
|
323
|
+
@each $breakpoint, $min-width in $col-breakpoints {
|
|
324
|
+
@media (width >= #{$min-width}) {
|
|
325
|
+
@for $i from 0 through 11 {
|
|
326
|
+
.col-#{$breakpoint}-offset-#{$i} {
|
|
327
|
+
margin-inline-start: if($i == 0, 0, var(--col-#{$i}));
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
239
333
|
/* Optional: Auto-Width Columns */
|
|
240
334
|
.col-auto {
|
|
241
335
|
width: auto;
|
|
@@ -324,6 +418,31 @@
|
|
|
324
418
|
}
|
|
325
419
|
}
|
|
326
420
|
|
|
421
|
+
/* ============================================================================
|
|
422
|
+
Responsive Column Order Utilities (Generated)
|
|
423
|
+
========================================================================== */
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* Generate responsive order utilities for all breakpoints
|
|
427
|
+
* Produces: .col-{sm|md|lg}-order-{first|last|0-12}
|
|
428
|
+
*
|
|
429
|
+
* Responsive ordering enables reordering columns at specific breakpoints.
|
|
430
|
+
* Visual order changes don't affect DOM order (important for accessibility).
|
|
431
|
+
* For example: .col-md-order-2 sets order:2 on tablets+
|
|
432
|
+
*/
|
|
433
|
+
@each $breakpoint, $min-width in $col-breakpoints {
|
|
434
|
+
@media (width >= #{$min-width}) {
|
|
435
|
+
.col-#{$breakpoint}-order-first { order: -1; }
|
|
436
|
+
.col-#{$breakpoint}-order-last { order: 13; }
|
|
437
|
+
|
|
438
|
+
@for $i from 0 through 12 {
|
|
439
|
+
.col-#{$breakpoint}-order-#{$i} {
|
|
440
|
+
order: $i;
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
327
446
|
/* ============================================================================
|
|
328
447
|
Row Variant Utilities (for Row React Component)
|
|
329
448
|
========================================================================== */
|