@i-dot-ai-npm/component-library-frontend 0.0.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/package.json +38 -0
- package/src/components/_button.scss +31 -0
- package/src/components/_card.scss +78 -0
- package/src/components/_checkboxes.scss +6 -0
- package/src/components/_form-group.scss +8 -0
- package/src/components/_header.scss +5 -0
- package/src/components/_input.scss +5 -0
- package/src/components/_link.scss +22 -0
- package/src/components/_radios.scss +45 -0
- package/src/components/_select.scss +6 -0
- package/src/components/_table.scss +21 -0
- package/src/components/_textarea.scss +5 -0
- package/src/components/_toggle.scss +222 -0
- package/src/index.js +12 -0
- package/src/index.scss +19 -0
- package/src/scripts/toggle.js +68 -0
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@i-dot-ai-npm/component-library-frontend",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "i.AI GOV.UK design-system override layer (SCSS + JS). Layered on top of govuk-frontend.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": "./src/index.js",
|
|
8
|
+
"./scss": "./src/index.scss",
|
|
9
|
+
"./css": "./dist/i-ai-design-system.min.css",
|
|
10
|
+
"./min.js": "./dist/i-ai-design-system.min.js"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"src",
|
|
14
|
+
"dist"
|
|
15
|
+
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "npm run build:css && npm run build:js",
|
|
18
|
+
"build:css": "sass --no-source-map --style=compressed src/index.scss dist/i-ai-design-system.min.css",
|
|
19
|
+
"build:js": "esbuild src/index.js --bundle --minify --format=esm --outfile=dist/i-ai-design-system.min.js"
|
|
20
|
+
},
|
|
21
|
+
"peerDependencies": {
|
|
22
|
+
"govuk-frontend": ">=6"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"esbuild": "^0.25.0",
|
|
26
|
+
"sass": "^1.103.0"
|
|
27
|
+
},
|
|
28
|
+
"repository": {
|
|
29
|
+
"type": "git",
|
|
30
|
+
"url": "git+https://github.com/i-dot-ai/component-library.git",
|
|
31
|
+
"directory": "packages/frontend"
|
|
32
|
+
},
|
|
33
|
+
"publishConfig": {
|
|
34
|
+
"access": "public",
|
|
35
|
+
"registry": "https://registry.npmjs.org"
|
|
36
|
+
},
|
|
37
|
+
"license": "MIT"
|
|
38
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// Button overrides.
|
|
2
|
+
|
|
3
|
+
.govuk-button--tertiary {
|
|
4
|
+
background-color: #ffffff;
|
|
5
|
+
border: 1px solid var(--govuk-border-colour);
|
|
6
|
+
border-bottom: 3px solid transparent;
|
|
7
|
+
box-shadow: 0 2px 0 #858686;
|
|
8
|
+
color: var(--govuk-link-colour);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.govuk-button--tertiary:hover {
|
|
12
|
+
background-color: #f4f8fb;
|
|
13
|
+
color: var(--govuk-link-colour);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.govuk-button--small {
|
|
17
|
+
padding: 6px 8px 4px;
|
|
18
|
+
font-size: 0.875rem;
|
|
19
|
+
line-height: 1.25rem;
|
|
20
|
+
box-shadow: 0 1px 0 #858686;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.govuk-button-group:has(.govuk-button--small) {
|
|
24
|
+
margin-bottom: 0;
|
|
25
|
+
align-items: center;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.govuk-button-group .govuk-button--small {
|
|
29
|
+
margin-bottom: 0;
|
|
30
|
+
margin-right: 2px;
|
|
31
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// Card (i.AI component).
|
|
2
|
+
|
|
3
|
+
.iai-card-group {
|
|
4
|
+
display: flex;
|
|
5
|
+
flex-direction: column;
|
|
6
|
+
gap: 20px;
|
|
7
|
+
margin-bottom: 20px;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
@media (min-width: 768px) {
|
|
11
|
+
.iai-card-group {
|
|
12
|
+
display: grid;
|
|
13
|
+
grid-template-columns: repeat(3, 1fr);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.iai-card-group__item {
|
|
18
|
+
height: 100%;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.iai-card {
|
|
22
|
+
position: relative;
|
|
23
|
+
height: 100%;
|
|
24
|
+
box-sizing: border-box;
|
|
25
|
+
padding: 20px;
|
|
26
|
+
background-color: var(--card-surface, #ffffff);
|
|
27
|
+
border: var(--card-border-width, 2px) solid var(--card-border, #b1b4b6);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.iai-card__icon {
|
|
31
|
+
margin-bottom: 15px;
|
|
32
|
+
color: var(--card-icon, #505a5f);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.iai-card__icon svg {
|
|
36
|
+
display: block;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.iai-card:hover .iai-card__icon {
|
|
40
|
+
color: var(--card-text-hover, #ffffff);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.iai-card:hover {
|
|
44
|
+
background-color: var(--card-surface-hover, #0b0c0c);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.iai-card__heading {
|
|
48
|
+
margin: 0 0 5px;
|
|
49
|
+
font-size: 1.1875rem;
|
|
50
|
+
line-height: 1.3157894737;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.iai-card__link {
|
|
54
|
+
color: var(--govuk-link-colour, var(--grey-400));
|
|
55
|
+
text-decoration: underline;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.iai-card__link:after {
|
|
59
|
+
content: "";
|
|
60
|
+
position: absolute;
|
|
61
|
+
inset: 0;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.iai-card__content {
|
|
65
|
+
margin: 0;
|
|
66
|
+
color: var(--govuk-text-colour, #0b0c0c);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.iai-card:hover .iai-card__link,
|
|
70
|
+
.iai-card:hover .iai-card__content {
|
|
71
|
+
color: var(--card-text-hover, #ffffff) !important;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.iai-card--secondary {
|
|
75
|
+
padding: 15px 20px;
|
|
76
|
+
background-color: var(--card-surface-secondary, #f3f2f1);
|
|
77
|
+
border: none;
|
|
78
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// Link overrides.
|
|
2
|
+
|
|
3
|
+
.govuk-link--warning {
|
|
4
|
+
color: #ca3535 !important;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.govuk-link:focus {
|
|
8
|
+
color: var(--govuk-link-colour);
|
|
9
|
+
outline: 3px solid transparent;
|
|
10
|
+
background-color: transparent;
|
|
11
|
+
box-shadow: none;
|
|
12
|
+
text-decoration: none;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.govuk-link:focus-visible {
|
|
16
|
+
outline: 3px solid transparent;
|
|
17
|
+
background-color: var(--govuk-focus-colour, #fd0);
|
|
18
|
+
box-shadow:
|
|
19
|
+
0 -2px var(--govuk-focus-colour, #fd0),
|
|
20
|
+
0 4px var(--govuk-focus-text-colour, #0b0c0c);
|
|
21
|
+
text-decoration: none;
|
|
22
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// Radios overrides, including the i.AI card-style radios variant.
|
|
2
|
+
|
|
3
|
+
.govuk-radios__item {
|
|
4
|
+
align-content: flex-start;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.govuk-radios--cards {
|
|
8
|
+
align-items: stretch;
|
|
9
|
+
flex-direction: column;
|
|
10
|
+
gap: 1rem;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
@media (width > 48rem) {
|
|
14
|
+
.govuk-radios--cards {
|
|
15
|
+
flex-direction: row;
|
|
16
|
+
gap: 0.5rem;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.govuk-radios--cards .govuk-radios__item {
|
|
21
|
+
border: 2px solid transparent;
|
|
22
|
+
background-color: var(--govuk-surface-background-colour);
|
|
23
|
+
flex: 1;
|
|
24
|
+
box-shadow:
|
|
25
|
+
var(--tw-inset-shadow), var(--tw-inset-ring-shadow),
|
|
26
|
+
var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
|
27
|
+
--tw-shadow:
|
|
28
|
+
0 4px 6px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1)),
|
|
29
|
+
0 2px 4px -2px var(--tw-shadow-color, rgb(0 0 0 / 0.1));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.govuk-radios--cards .govuk-radios__item:has(.govuk-radios__input:checked) {
|
|
33
|
+
border-color: var(--govuk-brand-colour);
|
|
34
|
+
background-color: #d2e2f1;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.govuk-radios--cards .govuk-radios__input:checked + .govuk-radios__label:after {
|
|
38
|
+
right: 22px;
|
|
39
|
+
left: auto;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.govuk-radios--cards .govuk-radios__label::before {
|
|
43
|
+
right: 15px;
|
|
44
|
+
left: auto;
|
|
45
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// Table overrides.
|
|
2
|
+
|
|
3
|
+
.govuk-table--subtle {
|
|
4
|
+
border-collapse: separate;
|
|
5
|
+
border-spacing: 0;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.govuk-table--subtle .govuk-table__header {
|
|
9
|
+
font-size: 1rem;
|
|
10
|
+
color: #484949;
|
|
11
|
+
border-color: #484949;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.govuk-table--subtle .govuk-table__cell {
|
|
15
|
+
padding: 0;
|
|
16
|
+
vertical-align: middle;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.govuk-table__row:hover {
|
|
20
|
+
background-color: #f2f2f2;
|
|
21
|
+
}
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
// Toggle
|
|
2
|
+
//
|
|
3
|
+
// Authored as a self-contained control (no dependency on the GOV.UK checkbox
|
|
4
|
+
// classes). The developer writes only:
|
|
5
|
+
//
|
|
6
|
+
// <div class="iai-toggle__item" data-module="govuk-toggle">
|
|
7
|
+
// <input class="iai-toggle__input" type="checkbox" id="toggle">
|
|
8
|
+
// <label class="iai-toggle__label" for="toggle">Toggle label</label>
|
|
9
|
+
// </div>
|
|
10
|
+
//
|
|
11
|
+
// Progressive enhancement:
|
|
12
|
+
// - No JS: the control renders as a GOV.UK-style checkbox (box + tick),
|
|
13
|
+
// drawn here in CSS. Fully functional native checkbox.
|
|
14
|
+
// - JS (body.govuk-frontend-supported): toggle.js injects the decorative
|
|
15
|
+
// track (.iai-toggle__display) and the checkmark/cross icons, and the
|
|
16
|
+
// rules below switch the control into a sliding toggle.
|
|
17
|
+
|
|
18
|
+
// Item: lays out the control and its label on one line.
|
|
19
|
+
.iai-toggle__item {
|
|
20
|
+
display: flex;
|
|
21
|
+
position: relative;
|
|
22
|
+
align-items: center;
|
|
23
|
+
gap: 8px;
|
|
24
|
+
margin-bottom: 10px;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.iai-toggle__item:last-child {
|
|
28
|
+
margin-bottom: 0;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Label: mirrors GOV.UK checkbox label styling.
|
|
32
|
+
.iai-toggle__label {
|
|
33
|
+
align-self: center;
|
|
34
|
+
margin-bottom: 0;
|
|
35
|
+
padding: 7px 15px;
|
|
36
|
+
cursor: pointer;
|
|
37
|
+
touch-action: manipulation;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// No-JS control wrapper: a 40px square that holds the checkbox box + tick.
|
|
41
|
+
.iai-toggle {
|
|
42
|
+
display: inline-block;
|
|
43
|
+
position: relative;
|
|
44
|
+
width: 40px;
|
|
45
|
+
height: 40px;
|
|
46
|
+
flex: 0 0 auto;
|
|
47
|
+
cursor: pointer;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Empty check box (GOV.UK: 40px square, 2px current-colour border).
|
|
51
|
+
.iai-toggle::before {
|
|
52
|
+
content: "";
|
|
53
|
+
box-sizing: border-box;
|
|
54
|
+
position: absolute;
|
|
55
|
+
top: 0;
|
|
56
|
+
left: 0;
|
|
57
|
+
width: 40px;
|
|
58
|
+
height: 40px;
|
|
59
|
+
border: 2px solid currentcolor;
|
|
60
|
+
background: transparent;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Check mark (GOV.UK: rotated corner shape), hidden until checked.
|
|
64
|
+
.iai-toggle::after {
|
|
65
|
+
content: "";
|
|
66
|
+
box-sizing: border-box;
|
|
67
|
+
position: absolute;
|
|
68
|
+
top: 11px;
|
|
69
|
+
left: 8px;
|
|
70
|
+
width: 23px;
|
|
71
|
+
height: 12px;
|
|
72
|
+
transform: rotate(-45deg);
|
|
73
|
+
border: solid;
|
|
74
|
+
border-width: 0 0 5px 5px;
|
|
75
|
+
border-top-color: transparent;
|
|
76
|
+
opacity: 0;
|
|
77
|
+
background: transparent;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// The real checkbox: an invisible overlay filling the wrapper, so the whole
|
|
81
|
+
// box is clickable and it stays focusable/tabbable.
|
|
82
|
+
.iai-toggle__input {
|
|
83
|
+
position: absolute;
|
|
84
|
+
inset: 0;
|
|
85
|
+
z-index: 3;
|
|
86
|
+
width: 100%;
|
|
87
|
+
height: 100%;
|
|
88
|
+
margin: 0;
|
|
89
|
+
opacity: 0;
|
|
90
|
+
cursor: pointer;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Reveal the check mark when the input is checked.
|
|
94
|
+
.iai-toggle:has(.iai-toggle__input:checked)::after {
|
|
95
|
+
opacity: 1;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Focus ring on the box when the input is focused.
|
|
99
|
+
.iai-toggle:has(.iai-toggle__input:focus)::before {
|
|
100
|
+
border-width: 4px;
|
|
101
|
+
outline: 3px solid transparent;
|
|
102
|
+
outline-offset: 1px;
|
|
103
|
+
box-shadow: 0 0 0 3px #ffdd00;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Disabled.
|
|
107
|
+
.iai-toggle:has(.iai-toggle__input:disabled) {
|
|
108
|
+
cursor: not-allowed;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.iai-toggle__item:has(.iai-toggle__input:disabled) .iai-toggle__label {
|
|
112
|
+
opacity: 0.5;
|
|
113
|
+
cursor: not-allowed;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// The decorative track is not rendered until JS injects it.
|
|
117
|
+
.iai-toggle__display {
|
|
118
|
+
display: none;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// ------------------------------------------------------------------ *
|
|
122
|
+
// JS enhanced: turn the wrapper into the sliding toggle track. *
|
|
123
|
+
// ------------------------------------------------------------------ *
|
|
124
|
+
|
|
125
|
+
.govuk-frontend-supported .iai-toggle {
|
|
126
|
+
display: inline-flex;
|
|
127
|
+
width: auto;
|
|
128
|
+
height: auto;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Hide the no-JS checkbox box + tick.
|
|
132
|
+
.govuk-frontend-supported .iai-toggle::before,
|
|
133
|
+
.govuk-frontend-supported .iai-toggle::after {
|
|
134
|
+
content: none;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Show the track.
|
|
138
|
+
.govuk-frontend-supported .iai-toggle__display {
|
|
139
|
+
display: inline-block;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Track (pill).
|
|
143
|
+
.iai-toggle__display {
|
|
144
|
+
box-sizing: content-box;
|
|
145
|
+
position: relative;
|
|
146
|
+
width: 44px;
|
|
147
|
+
height: 24px;
|
|
148
|
+
border-radius: 100px;
|
|
149
|
+
background-color: #505a5f;
|
|
150
|
+
color: #fff;
|
|
151
|
+
transition: 150ms;
|
|
152
|
+
cursor: pointer;
|
|
153
|
+
// Decorative: let clicks fall through to the overlaid real input.
|
|
154
|
+
pointer-events: none;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Handle (sliding circle).
|
|
158
|
+
.iai-toggle__handle {
|
|
159
|
+
box-sizing: border-box;
|
|
160
|
+
position: absolute;
|
|
161
|
+
z-index: 2;
|
|
162
|
+
top: 50%;
|
|
163
|
+
left: 0;
|
|
164
|
+
width: 22px;
|
|
165
|
+
height: 22px;
|
|
166
|
+
border: 1px solid rgba(0, 0, 0, 0.25);
|
|
167
|
+
border-radius: 50%;
|
|
168
|
+
background-color: #fff;
|
|
169
|
+
transform: translateY(-50%);
|
|
170
|
+
transition: inherit;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Checked: green track, handle slides right.
|
|
174
|
+
.iai-toggle__input:checked ~ .iai-toggle__display {
|
|
175
|
+
background-color: #00703c;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
.iai-toggle__input:checked ~ .iai-toggle__display .iai-toggle__handle {
|
|
179
|
+
left: 22px;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Focus ring on the track.
|
|
183
|
+
.iai-toggle__input:focus-visible ~ .iai-toggle__display {
|
|
184
|
+
outline: 3px solid transparent;
|
|
185
|
+
outline-offset: 0;
|
|
186
|
+
box-shadow: 0 0 0 4px #ffdd00;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Disabled track.
|
|
190
|
+
.iai-toggle__input:disabled ~ .iai-toggle__display {
|
|
191
|
+
background-color: #b1b4b6;
|
|
192
|
+
border-color: #6f7276;
|
|
193
|
+
cursor: not-allowed;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Icons sit at the two handle rest positions.
|
|
197
|
+
.iai-toggle__icon {
|
|
198
|
+
position: absolute;
|
|
199
|
+
top: 50%;
|
|
200
|
+
width: 12px;
|
|
201
|
+
height: 12px;
|
|
202
|
+
transform: translate(-50%, -50%);
|
|
203
|
+
color: inherit;
|
|
204
|
+
fill: currentcolor;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
.iai-toggle__icon--checkmark {
|
|
208
|
+
left: 14px;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.iai-toggle__icon--cross {
|
|
212
|
+
left: 32px;
|
|
213
|
+
width: 10px;
|
|
214
|
+
height: 10px;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
@media (prefers-reduced-motion: reduce) {
|
|
218
|
+
.iai-toggle__display,
|
|
219
|
+
.iai-toggle__handle {
|
|
220
|
+
transition-duration: 0ms;
|
|
221
|
+
}
|
|
222
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// i.AI Design System — behaviour layer.
|
|
2
|
+
//
|
|
3
|
+
// Progressive enhancement for i.AI components. Call after govuk-frontend's
|
|
4
|
+
// initAll(). Each component's enhancement lives in its own module.
|
|
5
|
+
|
|
6
|
+
import { initToggles } from './scripts/toggle.js';
|
|
7
|
+
|
|
8
|
+
export { initToggles };
|
|
9
|
+
|
|
10
|
+
export function initAllIAIDesignSystem() {
|
|
11
|
+
initToggles();
|
|
12
|
+
}
|
package/src/index.scss
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// i.AI Design System — override layer for govuk-frontend.
|
|
2
|
+
//
|
|
3
|
+
// Load AFTER govuk-frontend's base styles. This layer only adjusts and adds
|
|
4
|
+
// to GOV.UK components; it has no base layout or typography of its own.
|
|
5
|
+
//
|
|
6
|
+
// Each component (GOV.UK override or i.AI-new) lives in its own module.
|
|
7
|
+
|
|
8
|
+
@forward "components/button";
|
|
9
|
+
@forward "components/link";
|
|
10
|
+
@forward "components/radios";
|
|
11
|
+
@forward "components/select";
|
|
12
|
+
@forward "components/input";
|
|
13
|
+
@forward "components/textarea";
|
|
14
|
+
@forward "components/checkboxes";
|
|
15
|
+
@forward "components/table";
|
|
16
|
+
@forward "components/form-group";
|
|
17
|
+
@forward "components/header";
|
|
18
|
+
@forward "components/toggle";
|
|
19
|
+
@forward "components/card";
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Toggle enhancement module.
|
|
3
|
+
*
|
|
4
|
+
* Progressive enhancement for elements marked with
|
|
5
|
+
* data-module="govuk-toggle". Without this script the control renders as a
|
|
6
|
+
* plain, fully-functional checkbox (styled by the toggle styles). With it, the
|
|
7
|
+
* checkbox is upgraded into a sliding toggle:
|
|
8
|
+
*
|
|
9
|
+
* - the input gains role="switch"
|
|
10
|
+
* - the input is wrapped in a .iai-toggle control
|
|
11
|
+
* - a decorative .iai-toggle__display track (handle + icons) is injected
|
|
12
|
+
*
|
|
13
|
+
* The enhanced appearance itself is gated in CSS on the
|
|
14
|
+
* body.govuk-frontend-supported class (added by the page template), so this
|
|
15
|
+
* script only builds the DOM the CSS needs.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
const CHECKMARK_SVG = '<svg aria-hidden="true" focusable="false" class="iai-toggle__icon iai-toggle__icon--checkmark" width="18" height="14" viewBox="0 0 18 14" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M6.08471 10.6237L2.29164 6.83059L1 8.11313L6.08471 13.1978L17 2.28255L15.7175 1L6.08471 10.6237Z" fill="currentcolor" stroke="currentcolor"></path></svg>';
|
|
19
|
+
|
|
20
|
+
const CROSS_SVG = '<svg aria-hidden="true" focusable="false" class="iai-toggle__icon iai-toggle__icon--cross" width="13" height="13" viewBox="0 0 13 13" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M11.167 0L6.5 4.667L1.833 0L0 1.833L4.667 6.5L0 11.167L1.833 13L6.5 8.333L11.167 13L13 11.167L8.333 6.5L13 1.833L11.167 0Z" fill="currentcolor"></path></svg>';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Enhance a single toggle item.
|
|
24
|
+
* @param {Element} item - element with data-module="govuk-toggle"
|
|
25
|
+
*/
|
|
26
|
+
function enhanceToggle(item) {
|
|
27
|
+
if (item.dataset.toggleInitialised === 'true') {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const input = item.querySelector('.iai-toggle__input');
|
|
32
|
+
if (!input) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Announce as a switch to assistive tech only once the visual switch exists.
|
|
37
|
+
input.setAttribute('role', 'switch');
|
|
38
|
+
|
|
39
|
+
/*
|
|
40
|
+
* If the input is already inside a control wrapper, reuse it; otherwise
|
|
41
|
+
* wrap it so the CSS has a .iai-toggle to key off.
|
|
42
|
+
*/
|
|
43
|
+
let control = input.closest('.iai-toggle');
|
|
44
|
+
if (!control) {
|
|
45
|
+
control = document.createElement('div');
|
|
46
|
+
control.className = 'iai-toggle';
|
|
47
|
+
input.parentNode.insertBefore(control, input);
|
|
48
|
+
control.appendChild(input);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Inject the decorative track (handle + icons) if not already present.
|
|
52
|
+
if (!control.querySelector('.iai-toggle__display')) {
|
|
53
|
+
const display = document.createElement('span');
|
|
54
|
+
display.className = 'iai-toggle__display';
|
|
55
|
+
display.setAttribute('aria-hidden', 'true');
|
|
56
|
+
display.innerHTML = `<span class="iai-toggle__handle"></span>${CHECKMARK_SVG}${CROSS_SVG}`;
|
|
57
|
+
control.appendChild(display);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
item.dataset.toggleInitialised = 'true';
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** Enhance all toggles on the page. */
|
|
64
|
+
export function initToggles() {
|
|
65
|
+
document
|
|
66
|
+
.querySelectorAll('[data-module="govuk-toggle"]')
|
|
67
|
+
.forEach(enhanceToggle);
|
|
68
|
+
}
|