@fpkit/acss 0.6.2 → 1.0.0-beta.1
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/components/alert/alert.css +1 -1
- package/libs/components/alert/alert.css.map +1 -1
- package/libs/components/alert/alert.min.css +2 -2
- package/libs/components/badge/badge.css +1 -1
- package/libs/components/badge/badge.css.map +1 -1
- package/libs/components/badge/badge.min.css +2 -2
- package/libs/components/breadcrumbs/breadcrumb.css +1 -1
- package/libs/components/breadcrumbs/breadcrumb.css.map +1 -1
- package/libs/components/breadcrumbs/breadcrumb.min.css +2 -2
- package/libs/components/buttons/button.css +1 -1
- package/libs/components/buttons/button.css.map +1 -1
- package/libs/components/buttons/button.min.css +2 -2
- package/libs/components/cards/card.css +1 -1
- package/libs/components/cards/card.css.map +1 -1
- package/libs/components/cards/card.min.css +2 -2
- package/libs/components/details/details.css +1 -1
- package/libs/components/details/details.css.map +1 -1
- package/libs/components/details/details.min.css +2 -2
- package/libs/components/dialog/dialog.css +1 -1
- package/libs/components/dialog/dialog.css.map +1 -1
- package/libs/components/dialog/dialog.min.css +2 -2
- package/libs/components/form/form.css +1 -1
- package/libs/components/form/form.css.map +1 -1
- package/libs/components/form/form.min.css +2 -2
- package/libs/components/icons/icon.d.cts +32 -32
- package/libs/components/icons/icon.d.ts +32 -32
- package/libs/components/images/img.css +1 -1
- package/libs/components/images/img.css.map +1 -1
- package/libs/components/images/img.min.css +2 -2
- package/libs/components/layout/landmarks.css +1 -1
- package/libs/components/layout/landmarks.css.map +1 -1
- package/libs/components/layout/landmarks.min.css +2 -2
- package/libs/components/link/link.css +1 -1
- package/libs/components/link/link.css.map +1 -1
- package/libs/components/link/link.min.css +2 -2
- package/libs/components/nav/nav.css +1 -1
- package/libs/components/nav/nav.css.map +1 -1
- package/libs/components/nav/nav.min.css +2 -2
- package/libs/components/progress/progress.css +1 -1
- package/libs/components/progress/progress.css.map +1 -1
- package/libs/components/progress/progress.min.css +2 -2
- package/libs/components/tag/tag.css +1 -1
- package/libs/components/tag/tag.css.map +1 -1
- package/libs/components/tag/tag.min.css +2 -2
- package/libs/index.css +1 -1
- package/libs/index.css.map +1 -1
- package/package.json +1 -1
- package/src/components/alert/alert.scss +4 -4
- package/src/components/alert/alert.scss.backup +184 -0
- package/src/components/alert/alert.stories.tsx +53 -2
- package/src/components/badge/badge.scss +2 -2
- package/src/components/badge/badge.scss.backup +39 -0
- package/src/components/badge/badge.stories.tsx +40 -0
- package/src/components/breadcrumbs/breadcrumb.scss +5 -5
- package/src/components/breadcrumbs/breadcrumb.scss.backup +35 -0
- package/src/components/breadcrumbs/breadcrumb.stories.tsx +17 -1
- package/src/components/buttons/button.scss +27 -27
- package/src/components/buttons/button.scss.backup +145 -0
- package/src/components/buttons/button.stories.tsx +188 -2
- package/src/components/cards/card.scss +39 -5
- package/src/components/cards/card.scss.backup +67 -0
- package/src/components/cards/card.stories.tsx +183 -0
- package/src/components/details/details.scss +14 -14
- package/src/components/details/details.scss.backup +126 -0
- package/src/components/details/details.stories.tsx +40 -0
- package/src/components/dialog/dialog.scss +3 -3
- package/src/components/dialog/dialog.scss.backup +126 -0
- package/src/components/form/form.scss +25 -9
- package/src/components/form/form.scss.backup +87 -0
- package/src/components/form/form.stories.tsx +271 -0
- package/src/components/form/input.stories.tsx +158 -0
- package/src/components/images/figure.stories.tsx +41 -1
- package/src/components/images/img.scss +8 -8
- package/src/components/images/img.scss.backup +59 -0
- package/src/components/layout/_header.scss +14 -14
- package/src/components/layout/_header.scss.backup +72 -0
- package/src/components/layout/landmarks.scss +7 -7
- package/src/components/layout/landmarks.scss.backup +51 -0
- package/src/components/layout/landmarks.stories.tsx +42 -0
- package/src/components/link/link.scss +5 -5
- package/src/components/link/link.scss.backup +145 -0
- package/src/components/link/link.stories.tsx +38 -2
- package/src/components/nav/nav.scss +17 -17
- package/src/components/nav/nav.scss.backup +123 -0
- package/src/components/nav/nav.stories.tsx +35 -1
- package/src/components/progress/progress.scss +7 -7
- package/src/components/progress/progress.scss.backup +70 -0
- package/src/components/tag/tag.scss +10 -10
- package/src/components/tag/tag.scss.backup +130 -0
- package/src/components/tag/tag.stories.tsx +23 -2
- package/src/styles/alert/alert.css +4 -4
- package/src/styles/badge/badge.css +2 -2
- package/src/styles/breadcrumbs/breadcrumb.css +5 -5
- package/src/styles/buttons/button.css +26 -27
- package/src/styles/buttons/button.css.map +1 -1
- package/src/styles/cards/card.css +35 -5
- package/src/styles/cards/card.css.map +1 -1
- package/src/styles/details/details.css +14 -14
- package/src/styles/dialog/dialog.css +3 -3
- package/src/styles/form/form.css +20 -10
- package/src/styles/form/form.css.map +1 -1
- package/src/styles/images/img.css +8 -8
- package/src/styles/index.css +170 -131
- package/src/styles/index.css.map +1 -1
- package/src/styles/layout/landmarks.css +21 -21
- package/src/styles/link/link.css +5 -5
- package/src/styles/nav/nav.css +17 -17
- package/src/styles/progress/progress.css +6 -6
- package/src/styles/tag/tag.css +4 -4
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
header,
|
|
2
|
+
[data-hero],
|
|
3
|
+
[data-grid~='overlay'] {
|
|
4
|
+
// Name of the grid area
|
|
5
|
+
--overlay-grid-area: overlay;
|
|
6
|
+
// Placement of items in grid area
|
|
7
|
+
--overlay-placement: center;
|
|
8
|
+
// Controls display of grid
|
|
9
|
+
--overlay-display: grid;
|
|
10
|
+
// Overlay padding
|
|
11
|
+
--overlay-padding: 2rem;
|
|
12
|
+
--overlay-w: 100%;
|
|
13
|
+
--overlay-h: 40vh;
|
|
14
|
+
--overlay-max-h: 500px;
|
|
15
|
+
--overlay-color: currentColor;
|
|
16
|
+
--overlay-content-w: 80%;
|
|
17
|
+
--overlay-gap: 2rem;
|
|
18
|
+
--overlay-bg: whitesmoke;
|
|
19
|
+
--overlay-px: auto;
|
|
20
|
+
--overlay-py: auto;
|
|
21
|
+
--overlay-mx: auto;
|
|
22
|
+
--overlay-my: auto;
|
|
23
|
+
|
|
24
|
+
grid-template-areas: 'overlay';
|
|
25
|
+
display: var(--overlay-display);
|
|
26
|
+
place-items: var(--overlay-placement);
|
|
27
|
+
align-items: var(--overlay-placement);
|
|
28
|
+
min-height: var(--overlay-h);
|
|
29
|
+
width: var(--overlay-w);
|
|
30
|
+
color: var(--overlay-color);
|
|
31
|
+
background-color: var(--overlay-bg);
|
|
32
|
+
min-width: 20rem;
|
|
33
|
+
> * {
|
|
34
|
+
grid-area: overlay;
|
|
35
|
+
}
|
|
36
|
+
> img {
|
|
37
|
+
width: var(--overlay-w);
|
|
38
|
+
// height: auto;
|
|
39
|
+
background-size: contain;
|
|
40
|
+
}
|
|
41
|
+
> div,
|
|
42
|
+
> section {
|
|
43
|
+
--overlay-display: flex;
|
|
44
|
+
max-width: var(--overlay-content-w);
|
|
45
|
+
padding-inline: var(--spc-4);
|
|
46
|
+
margin-inline: var(--overlay-mx);
|
|
47
|
+
gap: var(--overlay-gap);
|
|
48
|
+
text-align: center;
|
|
49
|
+
p {
|
|
50
|
+
width: auto;
|
|
51
|
+
max-width: 60ch;
|
|
52
|
+
font-size: var(--fs-8);
|
|
53
|
+
line-height: 1.4;
|
|
54
|
+
}
|
|
55
|
+
> h1,
|
|
56
|
+
> h2 {
|
|
57
|
+
line-height: var(--header-lh, 1.1);
|
|
58
|
+
font-weight: 500;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
> h1 {
|
|
62
|
+
font-size: var(--fs-12);
|
|
63
|
+
}
|
|
64
|
+
> h2 {
|
|
65
|
+
font-size: var(--fs-11);
|
|
66
|
+
}
|
|
67
|
+
> h3 {
|
|
68
|
+
font-size: var(--fs-10);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
|
|
4
4
|
main,
|
|
5
5
|
footer {
|
|
6
|
-
--content-
|
|
7
|
-
--content-
|
|
8
|
-
--content-
|
|
6
|
+
--content-width: min(100%, 1480px);
|
|
7
|
+
--content-margin-inline: auto;
|
|
8
|
+
--content-padding-inline: 1rem;
|
|
9
9
|
--content-gap: 2rem;
|
|
10
10
|
padding-block: var(--overlay-padding);
|
|
11
11
|
> section {
|
|
12
|
-
width: var(--content-
|
|
13
|
-
margin-inline: var(--content-
|
|
12
|
+
width: var(--content-width);
|
|
13
|
+
margin-inline: var(--content-margin-inline);
|
|
14
14
|
padding-inline: var(--spc-6);
|
|
15
15
|
}
|
|
16
16
|
}
|
|
@@ -20,8 +20,8 @@ main {
|
|
|
20
20
|
font-size: var(--fs-3);
|
|
21
21
|
> section[aria-label],
|
|
22
22
|
> section {
|
|
23
|
-
width: var(--content-
|
|
24
|
-
margin-inline: var(--content-
|
|
23
|
+
width: var(--content-width);
|
|
24
|
+
margin-inline: var(--content-margin-inline);
|
|
25
25
|
&:has(> article, > aside) {
|
|
26
26
|
display: flex;
|
|
27
27
|
flex-wrap: wrap;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
@use './header';
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
main,
|
|
5
|
+
footer {
|
|
6
|
+
--content-w: min(100%, 1480px);
|
|
7
|
+
--content-mx: auto;
|
|
8
|
+
--content-px: 1rem;
|
|
9
|
+
--content-gap: 2rem;
|
|
10
|
+
padding-block: var(--overlay-padding);
|
|
11
|
+
> section {
|
|
12
|
+
width: var(--content-w);
|
|
13
|
+
margin-inline: var(--content-mx);
|
|
14
|
+
padding-inline: var(--spc-6);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
main {
|
|
19
|
+
flex: 1;
|
|
20
|
+
font-size: var(--fs-3);
|
|
21
|
+
> section[aria-label],
|
|
22
|
+
> section {
|
|
23
|
+
width: var(--content-w);
|
|
24
|
+
margin-inline: var(--content-mx);
|
|
25
|
+
&:has(> article, > aside) {
|
|
26
|
+
display: flex;
|
|
27
|
+
flex-wrap: wrap;
|
|
28
|
+
flex: 1;
|
|
29
|
+
gap: var(--content-gap);
|
|
30
|
+
> article {
|
|
31
|
+
flex-basis: 0;
|
|
32
|
+
flex-grow: 999;
|
|
33
|
+
min-inline-size: 50%;
|
|
34
|
+
}
|
|
35
|
+
> aside {
|
|
36
|
+
flex-basis: 20rem;
|
|
37
|
+
flex-grow: 1;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
footer {
|
|
44
|
+
> div {
|
|
45
|
+
display: flex;
|
|
46
|
+
align-items: center;
|
|
47
|
+
justify-content: center;
|
|
48
|
+
min-height: 5rem;
|
|
49
|
+
text-align: center;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -15,6 +15,48 @@ import Img from "#components/images/img";
|
|
|
15
15
|
const meta: Meta<typeof Header> = {
|
|
16
16
|
title: "FP.React Components/Layout/Landmarks",
|
|
17
17
|
component: Header,
|
|
18
|
+
parameters: {
|
|
19
|
+
docs: {
|
|
20
|
+
description: {
|
|
21
|
+
component: `Semantic landmark components including Header (banner), Main, and Footer with responsive content layout.
|
|
22
|
+
|
|
23
|
+
## CSS Variables (Header/Overlay)
|
|
24
|
+
|
|
25
|
+
### Layout & Display
|
|
26
|
+
- \`--overlay-display\`: Display mode (default: grid)
|
|
27
|
+
- \`--overlay-grid-area\`: Grid area name (default: overlay)
|
|
28
|
+
- \`--overlay-placement\`: Item placement (default: center)
|
|
29
|
+
|
|
30
|
+
### Sizing
|
|
31
|
+
- \`--overlay-width\`: Overlay width (default: 100%)
|
|
32
|
+
- \`--overlay-height\`: Minimum overlay height (default: 40vh)
|
|
33
|
+
- \`--overlay-max-height\`: Maximum overlay height (default: 500px)
|
|
34
|
+
- \`--overlay-content-width\`: Content max width (default: 80%)
|
|
35
|
+
|
|
36
|
+
### Spacing
|
|
37
|
+
- \`--overlay-padding\`: General padding (default: 2rem)
|
|
38
|
+
- \`--overlay-padding-inline\`: Horizontal padding (default: auto)
|
|
39
|
+
- \`--overlay-padding-block\`: Vertical padding (default: auto)
|
|
40
|
+
- \`--overlay-margin-inline\`: Horizontal margin (default: auto)
|
|
41
|
+
- \`--overlay-margin-block\`: Vertical margin (default: auto)
|
|
42
|
+
- \`--overlay-gap\`: Gap between elements (default: 2rem)
|
|
43
|
+
|
|
44
|
+
### Colors & Typography
|
|
45
|
+
- \`--overlay-color\`: Text color (default: currentColor)
|
|
46
|
+
- \`--overlay-bg\`: Background color (default: whitesmoke)
|
|
47
|
+
- \`--header-line-height\`: Heading line height (default: 1.1)
|
|
48
|
+
|
|
49
|
+
## CSS Variables (Main/Footer)
|
|
50
|
+
|
|
51
|
+
### Content Layout
|
|
52
|
+
- \`--content-width\`: Max content width (default: min(100%, 1480px))
|
|
53
|
+
- \`--content-margin-inline\`: Horizontal margin for centering (default: auto)
|
|
54
|
+
- \`--content-padding-inline\`: Horizontal padding (default: 1rem)
|
|
55
|
+
- \`--content-gap\`: Gap between article and aside (default: 2rem)
|
|
56
|
+
`,
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
},
|
|
18
60
|
args: {
|
|
19
61
|
children: "Default Header",
|
|
20
62
|
"data-testid": "banner",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
a[href] {
|
|
16
16
|
// Color & Typography
|
|
17
17
|
--link-color: #085ab7;
|
|
18
|
-
--link-
|
|
18
|
+
--link-fw: 400;
|
|
19
19
|
--link-fs: 1rem;
|
|
20
20
|
|
|
21
21
|
// Text Decoration
|
|
@@ -29,8 +29,8 @@ a[href] {
|
|
|
29
29
|
--link-radius: 0.25rem;
|
|
30
30
|
|
|
31
31
|
// Spacing (for button variants)
|
|
32
|
-
--link-
|
|
33
|
-
--link-
|
|
32
|
+
--link-padding-inline: 0;
|
|
33
|
+
--link-padding-block: 0;
|
|
34
34
|
|
|
35
35
|
// Transitions
|
|
36
36
|
--link-transition: all 0.75s ease-in-out;
|
|
@@ -44,7 +44,7 @@ a[href] {
|
|
|
44
44
|
// Apply base styles
|
|
45
45
|
color: var(--link-color);
|
|
46
46
|
font-size: var(--link-fs);
|
|
47
|
-
font-weight: var(--link-
|
|
47
|
+
font-weight: var(--link-fw);
|
|
48
48
|
text-decoration: var(--link-decoration);
|
|
49
49
|
text-underline-offset: var(--link-decoration-offset);
|
|
50
50
|
text-decoration-thickness: var(--link-decoration-thickness);
|
|
@@ -56,7 +56,7 @@ a[href] {
|
|
|
56
56
|
// Ensure child elements inherit weight/style
|
|
57
57
|
> i,
|
|
58
58
|
> b {
|
|
59
|
-
font-weight: var(--link-
|
|
59
|
+
font-weight: var(--link-fw);
|
|
60
60
|
font-style: normal;
|
|
61
61
|
}
|
|
62
62
|
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
@use '../../sass/mixins';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Link Component Styles
|
|
5
|
+
*
|
|
6
|
+
* Provides accessible, customizable link styles using CSS custom properties.
|
|
7
|
+
* Supports standard text links, button-styled links, and pill variants.
|
|
8
|
+
*
|
|
9
|
+
* WCAG 2.1 AA Compliance:
|
|
10
|
+
* - Focus indicators meet 2.4.7 (3:1 contrast minimum)
|
|
11
|
+
* - Color contrast meets 1.4.3 (4.5:1 for normal text)
|
|
12
|
+
* - Uses :focus-visible for better UX (keyboard vs mouse)
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
a[href] {
|
|
16
|
+
// Color & Typography
|
|
17
|
+
--link-color: #085ab7;
|
|
18
|
+
--link-weight: 400;
|
|
19
|
+
--link-fs: 1rem;
|
|
20
|
+
|
|
21
|
+
// Text Decoration
|
|
22
|
+
--link-decoration: none;
|
|
23
|
+
--link-decoration-offset: 0.09375rem; // 1.5px converted to rem
|
|
24
|
+
--link-decoration-thickness: 0.0625rem; // 1px converted to rem
|
|
25
|
+
--link-skip-ink: auto;
|
|
26
|
+
|
|
27
|
+
// Background & Border
|
|
28
|
+
--link-bg: transparent;
|
|
29
|
+
--link-radius: 0.25rem;
|
|
30
|
+
|
|
31
|
+
// Spacing (for button variants)
|
|
32
|
+
--link-px: 0;
|
|
33
|
+
--link-py: 0;
|
|
34
|
+
|
|
35
|
+
// Transitions
|
|
36
|
+
--link-transition: all 0.75s ease-in-out;
|
|
37
|
+
|
|
38
|
+
// Focus Indicator (WCAG 2.4.7 - 3:1 contrast minimum)
|
|
39
|
+
--link-focus-color: currentColor;
|
|
40
|
+
--link-focus-width: 0.125rem; // 2px
|
|
41
|
+
--link-focus-offset: 0.125rem; // 2px
|
|
42
|
+
--link-focus-style: solid;
|
|
43
|
+
|
|
44
|
+
// Apply base styles
|
|
45
|
+
color: var(--link-color);
|
|
46
|
+
font-size: var(--link-fs);
|
|
47
|
+
font-weight: var(--link-weight);
|
|
48
|
+
text-decoration: var(--link-decoration);
|
|
49
|
+
text-underline-offset: var(--link-decoration-offset);
|
|
50
|
+
text-decoration-thickness: var(--link-decoration-thickness);
|
|
51
|
+
text-decoration-skip-ink: var(--link-skip-ink);
|
|
52
|
+
background-color: var(--link-bg);
|
|
53
|
+
border-radius: var(--link-radius);
|
|
54
|
+
transition: var(--link-transition);
|
|
55
|
+
|
|
56
|
+
// Ensure child elements inherit weight/style
|
|
57
|
+
> i,
|
|
58
|
+
> b {
|
|
59
|
+
font-weight: var(--link-weight);
|
|
60
|
+
font-style: normal;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Hover state - add underline for clarity
|
|
64
|
+
&:hover {
|
|
65
|
+
--link-decoration: underline;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Focus state - WCAG 2.4.7 compliant focus indicator
|
|
69
|
+
&:focus {
|
|
70
|
+
outline: var(--link-focus-width) var(--link-focus-style)
|
|
71
|
+
var(--link-focus-color);
|
|
72
|
+
outline-offset: var(--link-focus-offset);
|
|
73
|
+
--link-decoration: underline;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Focus-visible for better UX (only show outline on keyboard focus)
|
|
77
|
+
&:focus-visible {
|
|
78
|
+
outline: var(--link-focus-width) var(--link-focus-style)
|
|
79
|
+
var(--link-focus-color);
|
|
80
|
+
outline-offset: var(--link-focus-offset);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Visited and active states
|
|
84
|
+
&:visited,
|
|
85
|
+
&:active {
|
|
86
|
+
--link-color: currentColor;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Button-styled links (via <b> wrapper, data-btn attribute, or <i> for pill)
|
|
90
|
+
&:has(> b),
|
|
91
|
+
&[data-btn],
|
|
92
|
+
&:has(> i) {
|
|
93
|
+
--link-button-color: var(--link-color);
|
|
94
|
+
--link-bg: transparent;
|
|
95
|
+
--link-decoration: none;
|
|
96
|
+
--link-border-width: 0.125rem; // 2px
|
|
97
|
+
--link-border-color: currentColor;
|
|
98
|
+
--link-border-style: solid;
|
|
99
|
+
--link-fs: 0.9rem;
|
|
100
|
+
|
|
101
|
+
color: var(--link-button-color);
|
|
102
|
+
background-color: var(--link-bg);
|
|
103
|
+
font-style: normal;
|
|
104
|
+
font-size: var(--link-fs);
|
|
105
|
+
padding-inline: var(--link-fs);
|
|
106
|
+
padding-block: calc(var(--link-fs) - 0.4rem);
|
|
107
|
+
border-radius: var(--link-radius, 99rem);
|
|
108
|
+
display: inline-flex;
|
|
109
|
+
align-items: center;
|
|
110
|
+
justify-content: center;
|
|
111
|
+
outline: var(--link-border-width) var(--link-border-color)
|
|
112
|
+
var(--link-border-style);
|
|
113
|
+
|
|
114
|
+
// Focus state for button links
|
|
115
|
+
&:focus,
|
|
116
|
+
&:focus-visible {
|
|
117
|
+
outline: var(--link-border-width) var(--link-border-color)
|
|
118
|
+
var(--link-border-style);
|
|
119
|
+
outline-offset: var(--link-focus-offset);
|
|
120
|
+
--link-decoration: none;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Hover state for button links
|
|
124
|
+
&:hover {
|
|
125
|
+
--link-decoration: none;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Apply scale transition from mixins
|
|
129
|
+
@include mixins.scale-transitions;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Pill variant (rounded corners)
|
|
133
|
+
&[data-link~='pill'],
|
|
134
|
+
&:has(> i) {
|
|
135
|
+
--link-radius: 99rem;
|
|
136
|
+
--link-decoration: none;
|
|
137
|
+
font-style: normal;
|
|
138
|
+
|
|
139
|
+
&:hover,
|
|
140
|
+
&:focus,
|
|
141
|
+
&:focus-visible {
|
|
142
|
+
--link-decoration: none;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
@@ -39,8 +39,44 @@ const meta = {
|
|
|
39
39
|
parameters: {
|
|
40
40
|
docs: {
|
|
41
41
|
description: {
|
|
42
|
-
component:
|
|
43
|
-
|
|
42
|
+
component: `A semantic, accessible anchor component with enhanced security for external links and flexible styling variants.
|
|
43
|
+
|
|
44
|
+
## CSS Variables
|
|
45
|
+
|
|
46
|
+
### Typography & Color
|
|
47
|
+
- \`--link-color\`: Link text color (default: #085ab7)
|
|
48
|
+
- \`--link-fw\`: Font weight (default: 400)
|
|
49
|
+
- \`--link-fs\`: Font size (default: 1rem)
|
|
50
|
+
|
|
51
|
+
### Text Decoration
|
|
52
|
+
- \`--link-decoration\`: Text decoration style (default: none, underline on hover/focus)
|
|
53
|
+
- \`--link-decoration-offset\`: Underline offset (default: 0.09375rem / 1.5px)
|
|
54
|
+
- \`--link-decoration-thickness\`: Underline thickness (default: 0.0625rem / 1px)
|
|
55
|
+
- \`--link-skip-ink\`: Text decoration skip ink (default: auto)
|
|
56
|
+
|
|
57
|
+
### Background & Border
|
|
58
|
+
- \`--link-bg\`: Background color (default: transparent)
|
|
59
|
+
- \`--link-radius\`: Border radius (default: 0.25rem, 99rem for pills)
|
|
60
|
+
|
|
61
|
+
### Spacing (Button Variants)
|
|
62
|
+
- \`--link-padding-inline\`: Horizontal padding (default: 0, calculated for button variants)
|
|
63
|
+
- \`--link-padding-block\`: Vertical padding (default: 0, calculated for button variants)
|
|
64
|
+
|
|
65
|
+
### Focus Indicators (WCAG 2.4.7)
|
|
66
|
+
- \`--link-focus-color\`: Focus outline color (default: currentColor)
|
|
67
|
+
- \`--link-focus-width\`: Focus outline width (default: 0.125rem / 2px)
|
|
68
|
+
- \`--link-focus-offset\`: Focus outline offset (default: 0.125rem / 2px)
|
|
69
|
+
- \`--link-focus-style\`: Focus outline style (default: solid)
|
|
70
|
+
|
|
71
|
+
### Transitions
|
|
72
|
+
- \`--link-transition\`: Transition timing (default: all 0.75s ease-in-out)
|
|
73
|
+
|
|
74
|
+
### Button Variants
|
|
75
|
+
- \`--link-button-color\`: Button link text color (default: var(--link-color))
|
|
76
|
+
- \`--link-border-width\`: Button border width (default: 0.125rem / 2px)
|
|
77
|
+
- \`--link-border-color\`: Button border color (default: currentColor)
|
|
78
|
+
- \`--link-border-style\`: Button border style (default: solid)
|
|
79
|
+
`,
|
|
44
80
|
},
|
|
45
81
|
},
|
|
46
82
|
},
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
body > nav,
|
|
2
2
|
[aria-label~="navbar"],
|
|
3
3
|
.navbar {
|
|
4
|
-
padding-inline: var(--nav-
|
|
5
|
-
min-height: var(--nav-
|
|
4
|
+
padding-inline: var(--nav-padding-inline, 1rem);
|
|
5
|
+
min-height: var(--nav-height, fit-content);
|
|
6
6
|
|
|
7
7
|
@media (max-width: 580px) {
|
|
8
8
|
flex-direction: column;
|
|
@@ -19,10 +19,10 @@ body > nav,
|
|
|
19
19
|
margin: 0;
|
|
20
20
|
padding: 0;
|
|
21
21
|
min-height: 100%;
|
|
22
|
-
padding-inline: var(--nav-
|
|
22
|
+
padding-inline: var(--nav-padding-inline, 0.75rem);
|
|
23
23
|
|
|
24
24
|
&:hover {
|
|
25
|
-
background-color: var(--nav-
|
|
25
|
+
background-color: var(--nav-hover-bg, #e8e8e8);
|
|
26
26
|
}
|
|
27
27
|
&:hover:where(img) {
|
|
28
28
|
background-color: transparent;
|
|
@@ -38,25 +38,25 @@ nav {
|
|
|
38
38
|
--nav-focus-offset: 0.125rem; // 2px
|
|
39
39
|
--nav-focus-style: solid;
|
|
40
40
|
|
|
41
|
-
display: var(--nav-
|
|
41
|
+
display: var(--nav-display, flex);
|
|
42
42
|
flex-direction: var(--nav-direction, row);
|
|
43
|
-
width: var(--nav-
|
|
43
|
+
width: var(--nav-width, auto);
|
|
44
44
|
place-items: var(--nav-align, center);
|
|
45
45
|
justify-content: var(--nav-justify, space-between);
|
|
46
|
-
margin-inline: var(--nav-
|
|
46
|
+
margin-inline: var(--nav-margin-inline, 0);
|
|
47
47
|
background-color: var(--nav-bg, initial);
|
|
48
48
|
|
|
49
49
|
> section,
|
|
50
50
|
> ul {
|
|
51
|
-
--nav-
|
|
51
|
+
--nav-display: flex;
|
|
52
52
|
flex-direction: var(--nav-direction, row);
|
|
53
|
-
display: var(--nav-
|
|
53
|
+
display: var(--nav-display, flex);
|
|
54
54
|
gap: var(--nav-gap, 0);
|
|
55
55
|
font-size: var(--nav-fs, 0.9rem);
|
|
56
56
|
align-items: var(--nav-align, center);
|
|
57
|
-
padding-inline: var(--nav-
|
|
58
|
-
padding-block: var(--nav-
|
|
59
|
-
margin-block-end: var(--nav-
|
|
57
|
+
padding-inline: var(--nav-padding-inline, 1rem);
|
|
58
|
+
padding-block: var(--nav-padding-block, 0);
|
|
59
|
+
margin-block-end: var(--nav-margin-block-end, 0);
|
|
60
60
|
height: 100%;
|
|
61
61
|
&[data-list~="block"] {
|
|
62
62
|
--nav-direction: column;
|
|
@@ -65,7 +65,7 @@ nav {
|
|
|
65
65
|
|
|
66
66
|
> section {
|
|
67
67
|
> div {
|
|
68
|
-
--
|
|
68
|
+
--nav-padding-block: 0;
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
71
|
|
|
@@ -77,18 +77,18 @@ nav {
|
|
|
77
77
|
margin: 0;
|
|
78
78
|
padding: 0;
|
|
79
79
|
min-height: 100%;
|
|
80
|
-
padding-inline: var(--nav-
|
|
80
|
+
padding-inline: var(--nav-padding-inline, 1rem);
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
img[alt] {
|
|
85
|
-
--
|
|
86
|
-
--
|
|
85
|
+
--nav-img-padding-inline: 0 var(--s1);
|
|
86
|
+
--nav-img-width: var(--brand-w, 3.6rem);
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
&[data-variant] {
|
|
90
90
|
background-color: var(--nav-bg);
|
|
91
|
-
color: var(--nav-
|
|
91
|
+
color: var(--nav-color);
|
|
92
92
|
font-size: var(--nav-fs, 0.9rem);
|
|
93
93
|
}
|
|
94
94
|
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
body > nav,
|
|
2
|
+
[aria-label~="navbar"],
|
|
3
|
+
.navbar {
|
|
4
|
+
padding-inline: var(--nav-px, 1rem);
|
|
5
|
+
min-height: var(--nav-h, fit-content);
|
|
6
|
+
|
|
7
|
+
@media (max-width: 580px) {
|
|
8
|
+
flex-direction: column;
|
|
9
|
+
height: fit-content;
|
|
10
|
+
min-height: fit-content;
|
|
11
|
+
padding-block: unset;
|
|
12
|
+
gap: 0.5rem;
|
|
13
|
+
}
|
|
14
|
+
ul {
|
|
15
|
+
> li {
|
|
16
|
+
display: flex;
|
|
17
|
+
align-items: center;
|
|
18
|
+
list-style: none;
|
|
19
|
+
margin: 0;
|
|
20
|
+
padding: 0;
|
|
21
|
+
min-height: 100%;
|
|
22
|
+
padding-inline: var(--nav-px, 0.75rem);
|
|
23
|
+
|
|
24
|
+
&:hover {
|
|
25
|
+
background-color: var(--nav-hov-bg, #e8e8e8);
|
|
26
|
+
}
|
|
27
|
+
&:hover:where(img) {
|
|
28
|
+
background-color: transparent;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
nav {
|
|
35
|
+
// Focus Indicator Variables (WCAG 2.4.7 - 3:1 contrast minimum)
|
|
36
|
+
--nav-focus-color: currentColor;
|
|
37
|
+
--nav-focus-width: 0.125rem; // 2px
|
|
38
|
+
--nav-focus-offset: 0.125rem; // 2px
|
|
39
|
+
--nav-focus-style: solid;
|
|
40
|
+
|
|
41
|
+
display: var(--nav-dsp, flex);
|
|
42
|
+
flex-direction: var(--nav-direction, row);
|
|
43
|
+
width: var(--nav-w, auto);
|
|
44
|
+
place-items: var(--nav-align, center);
|
|
45
|
+
justify-content: var(--nav-justify, space-between);
|
|
46
|
+
margin-inline: var(--nav-mx, 0);
|
|
47
|
+
background-color: var(--nav-bg, initial);
|
|
48
|
+
|
|
49
|
+
> section,
|
|
50
|
+
> ul {
|
|
51
|
+
--nav-dsp: flex;
|
|
52
|
+
flex-direction: var(--nav-direction, row);
|
|
53
|
+
display: var(--nav-dsp, flex);
|
|
54
|
+
gap: var(--nav-gap, 0);
|
|
55
|
+
font-size: var(--nav-fs, 0.9rem);
|
|
56
|
+
align-items: var(--nav-align, center);
|
|
57
|
+
padding-inline: var(--nav-px, 1rem);
|
|
58
|
+
padding-block: var(--nav-py, 0);
|
|
59
|
+
margin-block-end: var(--nav-mb, 0);
|
|
60
|
+
height: 100%;
|
|
61
|
+
&[data-list~="block"] {
|
|
62
|
+
--nav-direction: column;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
> section {
|
|
67
|
+
> div {
|
|
68
|
+
--py: 0;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
ul {
|
|
73
|
+
> li {
|
|
74
|
+
display: flex;
|
|
75
|
+
align-items: center;
|
|
76
|
+
list-style: none;
|
|
77
|
+
margin: 0;
|
|
78
|
+
padding: 0;
|
|
79
|
+
min-height: 100%;
|
|
80
|
+
padding-inline: var(--nav-px, 1rem);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
img[alt] {
|
|
85
|
+
--px: 0 var(--s1);
|
|
86
|
+
--w: var(--brand-w, 3.6rem);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
&[data-variant] {
|
|
90
|
+
background-color: var(--nav-bg);
|
|
91
|
+
color: var(--nav-cl);
|
|
92
|
+
font-size: var(--nav-fs, 0.9rem);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
> div {
|
|
96
|
+
margin-block-start: 0;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Focus indicators for links and buttons (WCAG 2.4.7)
|
|
100
|
+
a:focus {
|
|
101
|
+
outline: var(--nav-focus-width) var(--nav-focus-style)
|
|
102
|
+
var(--nav-focus-color);
|
|
103
|
+
outline-offset: var(--nav-focus-offset);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
a:focus-visible {
|
|
107
|
+
outline: var(--nav-focus-width) var(--nav-focus-style)
|
|
108
|
+
var(--nav-focus-color);
|
|
109
|
+
outline-offset: var(--nav-focus-offset);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
button:focus {
|
|
113
|
+
outline: var(--nav-focus-width) var(--nav-focus-style)
|
|
114
|
+
var(--nav-focus-color);
|
|
115
|
+
outline-offset: var(--nav-focus-offset);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
button:focus-visible {
|
|
119
|
+
outline: var(--nav-focus-width) var(--nav-focus-style)
|
|
120
|
+
var(--nav-focus-color);
|
|
121
|
+
outline-offset: var(--nav-focus-offset);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
@@ -14,7 +14,41 @@ const meta: Meta<typeof Nav> = {
|
|
|
14
14
|
actions: { argTypesRegex: "^on.*" },
|
|
15
15
|
docs: {
|
|
16
16
|
description: {
|
|
17
|
-
component:
|
|
17
|
+
component: `Navigation component with accessible markup and customizable styling via CSS variables.
|
|
18
|
+
|
|
19
|
+
## CSS Variables
|
|
20
|
+
|
|
21
|
+
### Layout & Sizing
|
|
22
|
+
- \`--nav-display\`: Display mode (default: flex)
|
|
23
|
+
- \`--nav-width\`: Nav width (default: auto)
|
|
24
|
+
- \`--nav-height\`: Minimum height (default: fit-content)
|
|
25
|
+
- \`--nav-direction\`: Flex direction (default: row)
|
|
26
|
+
- \`--nav-align\`: Vertical alignment (default: center)
|
|
27
|
+
- \`--nav-justify\`: Horizontal justification (default: space-between)
|
|
28
|
+
|
|
29
|
+
### Spacing
|
|
30
|
+
- \`--nav-padding-inline\`: Horizontal padding (default: 1rem)
|
|
31
|
+
- \`--nav-padding-block\`: Vertical padding (default: 0)
|
|
32
|
+
- \`--nav-margin-inline\`: Horizontal margin (default: 0)
|
|
33
|
+
- \`--nav-margin-block-end\`: Bottom margin (default: 0)
|
|
34
|
+
- \`--nav-gap\`: Gap between nav items (default: 0)
|
|
35
|
+
|
|
36
|
+
### Typography & Color
|
|
37
|
+
- \`--nav-fs\`: Font size (default: 0.9rem)
|
|
38
|
+
- \`--nav-color\`: Text color
|
|
39
|
+
- \`--nav-bg\`: Background color (default: initial)
|
|
40
|
+
- \`--nav-hover-bg\`: Background color on hover (default: #e8e8e8)
|
|
41
|
+
|
|
42
|
+
### Focus Indicators (WCAG 2.4.7)
|
|
43
|
+
- \`--nav-focus-color\`: Focus outline color (default: currentColor)
|
|
44
|
+
- \`--nav-focus-width\`: Focus outline width (default: 0.125rem / 2px)
|
|
45
|
+
- \`--nav-focus-offset\`: Focus outline offset (default: 0.125rem / 2px)
|
|
46
|
+
- \`--nav-focus-style\`: Focus outline style (default: solid)
|
|
47
|
+
|
|
48
|
+
### Image Elements
|
|
49
|
+
- \`--nav-img-padding-inline\`: Image padding (default: 0 var(--s1))
|
|
50
|
+
- \`--nav-img-width\`: Image width (default: var(--brand-w, 3.6rem))
|
|
51
|
+
`,
|
|
18
52
|
},
|
|
19
53
|
},
|
|
20
54
|
},
|