@primer/css 0.0.0-20220620061649 → 0.0.0-20220621152621

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.
@@ -1,4 +1,4 @@
1
- // stylelint-disable primer/typography, primer/borders, primer/spacing, primer/box-shadow, max-nesting-depth
1
+ // stylelint-disable primer/typography, primer/borders, primer/spacing, max-nesting-depth, selector-max-type, selector-max-specificity, selector-no-qualifying-type
2
2
 
3
3
  // group label, field, caption and error message
4
4
  .FormGroup {
@@ -10,11 +10,6 @@
10
10
  // fill container
11
11
  .FormGroup--fullWidth {
12
12
  display: flex;
13
-
14
- // stretch field to fill container
15
- .FormControl-fieldWrap {
16
- flex-grow: 1;
17
- }
18
13
  }
19
14
 
20
15
  // <label>
@@ -22,6 +17,7 @@
22
17
  font-size: var(--primer-text-body-size-medium, 14px);
23
18
  font-weight: var(--base-text-weight-semibold, 600);
24
19
  line-height: var(--primer-text-body-lineHeight-medium, 20px);
20
+ color: var(--color-fg-default);
25
21
  user-select: none;
26
22
  }
27
23
 
@@ -44,7 +40,6 @@
44
40
  align-items: center;
45
41
  gap: var(--base-size-4, 4px);
46
42
 
47
- // stylelint-disable-next-line selector-max-type
48
43
  p {
49
44
  margin-bottom: 0;
50
45
  }
@@ -57,26 +52,56 @@
57
52
 
58
53
  &[disabled] {
59
54
  color: var(--color-primer-fg-disabled);
55
+ cursor: not-allowed;
60
56
  background-color: var(--color-input-disabled-bg);
61
57
  border-color: var(--color-border-default);
62
- -webkit-text-fill-color: var(--color-primer-fg-disabled);
63
58
  opacity: 1;
59
+ -webkit-text-fill-color: var(--color-primer-fg-disabled);
64
60
  }
65
61
 
66
62
  &:not(:focus)[invalid] {
67
63
  border-color: var(--color-danger-emphasis);
68
64
  }
69
65
 
66
+ &:not([type='checkbox']):not([type='radio']):focus {
67
+ @include focusBoxShadowInset;
68
+
69
+ // remove fallback :focus if :focus-visible is supported
70
+ &:not(:focus-visible) {
71
+ border-color: transparent;
72
+
73
+ @include focusBoxShadowInset(1px, transparent);
74
+ }
75
+ }
76
+
77
+ // default focus state
78
+ &:focus-visible {
79
+ @include focusBoxShadowInset;
80
+ }
81
+
82
+ &.FormControl--inset {
83
+ background-color: var(--color-canvas-inset);
84
+ }
85
+
86
+ &.FormControl--monospace {
87
+ font-family: var(
88
+ --primer-fontStack-monospace,
89
+ 'ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace'
90
+ );
91
+ }
92
+
70
93
  // <select> and <input>
71
94
  &.FormControl--input,
72
- &.FormControl--select {
73
- height: var(--primer-control-medium-size, 32px);
95
+ &.FormControl--select,
96
+ &.FormControl--textarea {
97
+ width: 100%;
74
98
  font-size: var(--primer-text-body-size-medium, 14px);
75
99
  line-height: var(--primer-text-body-lineHeight-medium, 20px);
76
100
  border-radius: var(--primer-borderRadius-medium, 6px);
77
- padding-inline: var(--primer-control-medium-paddingInline-condensed, 8px);
78
101
  transition: 80ms cubic-bezier(0.33, 1, 0.68, 1);
79
102
  transition-property: color, background-color, box-shadow, border-color;
103
+ padding-inline: var(--primer-control-medium-paddingInline-condensed, 8px);
104
+ padding-block: calc(var(--primer-control-medium-paddingBlock, 6px) - var(--primer-borderWidth-thin, 1px));
80
105
 
81
106
  &[disabled] {
82
107
  &::placeholder {
@@ -90,10 +115,18 @@
90
115
  }
91
116
  }
92
117
 
118
+ // <select> and <input>
119
+ &.FormControl--input,
120
+ &.FormControl--select {
121
+ height: var(--primer-control-medium-size, 32px);
122
+ }
123
+
93
124
  // sizes
94
125
 
95
126
  &.FormControl--small {
96
127
  height: var(--primer-control-small-size, 28px);
128
+ padding-inline: var(--primer-control-small-paddingInline-normal, 8px);
129
+ padding-block: var(--primer-control-small-paddingBlock, 4px);
97
130
  font-size: var(--primer-text-body-size-small, 12px);
98
131
  }
99
132
 
@@ -104,148 +137,173 @@
104
137
  &.FormControl--large {
105
138
  height: var(--primer-control-large-size, 40px);
106
139
  padding-inline: var(--primer-control-large-paddingInline-normal, 12px);
140
+ padding-block: var(--primer-control-large-paddingBlock, 10px);
107
141
  }
108
142
  }
109
143
 
110
- // pseudo input styles to allow for visual and action slots
111
- // set input styles on -fieldWrap, remove styles from <input>
144
+ // positioning for leading/trailing items
112
145
  .FormControl-fieldWrap {
113
- display: inline-grid;
114
- height: var(--primer-control-medium-size, 32px);
115
- background-color: var(--color-canvas-default);
116
- border-radius: var(--primer-borderRadius-medium, 6px);
117
- box-shadow: var(--primer-borderInset-thin, inset 0 0 0 max(1px, 0.0625rem)) var(--color-border-default);
118
- grid-template-rows: auto;
119
- gap: var(--primer-controlStack-medium-gap-condensed, 8px);
120
- align-items: center;
121
- align-content: center;
122
- padding-inline: var(--primer-control-medium-paddingInline-condensed, 8px);
123
-
124
- .FormControl {
125
- padding: unset;
126
- background-color: transparent;
127
- border: 0;
146
+ position: relative;
147
+ display: grid;
148
+
149
+ .FormControl--input-leadingVisualWrap {
150
+ position: absolute;
151
+ top: var(--base-size-8, 8px);
152
+ left: var(--base-size-8, 8px);
153
+ display: block;
154
+ width: var(--base-size-16, 16px);
155
+ height: var(--base-size-16, 16px);
156
+ color: var(--color-fg-muted);
157
+ pointer-events: none;
128
158
 
129
- &:focus-visible,
130
- &:focus {
131
- outline: none;
132
- box-shadow: none;
159
+ // octicon
160
+ .FormControl--input-leadingVisual {
161
+ display: block;
162
+ user-select: none;
133
163
  }
134
164
  }
135
165
 
136
- &:focus-within {
137
- @include focusBoxShadowInset(2px, var(--color-accent-fg));
138
- }
166
+ // TODO: replace with new Button component
167
+ .FormControl--input-trailingAction {
168
+ position: absolute;
169
+ top: var(--base-size-4, 4px);
170
+ right: var(--base-size-4, 4px);
171
+ z-index: 4;
172
+ display: grid;
173
+ width: var(--primer-control-xsmall-size, 24px);
174
+ height: var(--primer-control-xsmall-size, 24px);
175
+ padding: 0;
176
+ color: var(--color-fg-muted);
177
+ cursor: pointer;
178
+ background: transparent;
179
+ border: 0;
180
+ border-radius: var(--primer-borderRadius-small);
181
+ transition: 0.2s cubic-bezier(0.3, 0, 0.5, 1);
182
+ transition-property: color, background-color, border-color;
183
+ align-items: center;
184
+ justify-content: center;
139
185
 
140
- &.FormControl-fieldWrap--disabled {
141
- color: var(--color-primer-fg-disabled);
142
- background-color: var(--color-input-disabled-bg);
143
- }
186
+ svg {
187
+ user-select: none;
188
+ }
144
189
 
145
- &.FormControl-fieldWrap--invalid:not(:focus-within) {
146
- box-shadow: var(--primer-borderInset-thin, inset 0 0 0 max(1px, 0.0625rem)) var(--color-danger-emphasis);
147
- }
190
+ &[disabled] {
191
+ color: var(--color-primer-fg-disabled);
192
+ pointer-events: none;
193
+ }
148
194
 
149
- // if leadingVisual is present
150
- &.FormControl-fieldWrap--input-leadingVisual {
151
- grid-template-columns: var(--base-size-16, 16px) minmax(0, auto);
195
+ &:hover {
196
+ background: var(--color-action-list-item-default-hover-bg);
197
+ }
152
198
 
153
- .FormControl--input {
154
- padding-inline-start: calc(var(--base-size-16, 16px) + var(--primer-control-medium-paddingInline-condensed, 8px));
199
+ &:active {
200
+ background: var(--color-action-list-item-default-active-bg);
155
201
  }
156
202
 
157
- // if leadingVisual and trailingAction are present
158
- &.FormControl-fieldWrap--input-trailingAction {
159
- grid-template-columns: var(--base-size-16, 16px) minmax(0, auto) min-content;
203
+ // show vertical divider line between field and button
204
+ &::before {
205
+ position: absolute;
206
+ top: calc((var(--primer-control-xsmall-size) - var(--base-size-16)) / 2);
207
+ left: calc(var(--base-size-4, 4px) * -1);
208
+ display: block;
209
+ width: var(--primer-borderWidth-thin);
210
+ height: var(--base-size-16);
211
+ content: '';
212
+ background: var(--color-border-default);
213
+ }
160
214
 
161
- .FormControl--input-trailingAction {
162
- grid-column: 3 / 4;
215
+ &::after {
216
+ @include minTouchTarget(var(--primer-control-medium-size), var(--primer-control-medium-size));
217
+
218
+ @media (pointer: coarse) {
219
+ min-width: var(--primer-control-minTarget-coarse);
220
+ min-height: var(--primer-control-minTarget-coarse);
163
221
  }
164
222
  }
165
223
  }
166
224
 
167
- // if trailingAction is present
168
- &.FormControl-fieldWrap--input-trailingAction {
169
- grid-template-columns: minmax(0, auto) min-content;
170
- }
171
-
172
- &.FormControl-fieldWrap--input {
173
- grid-template-rows: max-content;
174
-
175
- .FormControl--input-leadingVisual {
176
- grid-column: 1 / 2;
177
- grid-row: 1;
225
+ // if leadingVisual is present
226
+ &.FormControl-fieldWrap--input-leadingVisual {
227
+ .FormControl--input {
228
+ padding-inline-start: calc(
229
+ var(--primer-control-medium-paddingInline-condensed, 8px) + var(--base-size-16, 16px) +
230
+ var(--primer-control-medium-gap, 8px) - var(--primer-borderWidth-thin, 1px)
231
+ );
178
232
  }
233
+ }
179
234
 
180
- // <input> spans entire grid
235
+ // if trailingAction is present
236
+ &.FormControl-fieldWrap--input-trailingAction {
181
237
  .FormControl--input {
182
- grid-column: 1 / -1;
183
- grid-row: 1;
238
+ padding-inline-end: calc(
239
+ var(--primer-control-medium-paddingInline-condensed, 8px) + var(--base-size-16, 16px) +
240
+ var(--primer-control-medium-gap, 8px) - var(--primer-borderWidth-thin, 1px)
241
+ );
184
242
  }
243
+ }
185
244
 
186
- // TODO: replace with new Button component
187
- // trailingAction will auto fill last grid slot
188
- .FormControl--input-trailingAction {
189
- display: grid;
190
- width: calc(var(--primer-control-medium-size, 32px) - var(--base-size-4, 4px));
191
- height: calc(var(--primer-control-medium-size, 32px) - var(--base-size-4, 4px));
192
- padding: 0;
193
- // optically align the icon with field padding
194
- margin-right: calc(calc(var(--primer-control-medium-paddingInline-condensed, 8px) - 0.125rem) * -1);
195
- color: var(--color-fg-muted);
196
- cursor: pointer;
197
- user-select: none;
198
- background-color: transparent;
199
- border: solid var(--primer-borderWidth-thin, 1px) transparent;
200
- border-radius: var(--primer-borderRadius-medium, 6px);
201
- transition: 0.2s cubic-bezier(0.3, 0, 0.5, 1);
202
- transition-property: color, background-color, border-color;
203
- grid-row: 1;
204
- place-content: center;
205
- place-self: center end;
206
- grid-column: 2 / 3;
207
-
208
- &:hover {
209
- background-color: var(--color-btn-hover-bg);
210
- border: solid var(--primer-borderWidth-thin, 1px) var(--color-btn-hover-bg);
245
+ // size modifications can be refactored with :has() - FormControl-fieldWrap:has(.FormControl--large)
246
+ // sizes
247
+ &.FormControl-fieldWrap--input {
248
+ &.FormControl--small {
249
+ .FormControl--input-leadingVisualWrap {
250
+ top: calc(var(--primer-control-medium-paddingInline-condensed, 8px) - 0.125rem); /* 6px */
251
+ left: calc(var(--primer-control-medium-paddingInline-condensed, 8px) - 0.125rem); /* 6px */
211
252
  }
212
253
 
213
- &[disabled] {
214
- color: var(--color-primer-fg-disabled);
215
- pointer-events: none;
254
+ &.FormControl-fieldWrap--input-trailingAction {
255
+ .FormControl--input.FormControl--small {
256
+ padding-inline-end: calc(
257
+ var(----primer-control-small-paddingInline-condensed, 8px) + var(--base-size-16, 16px) +
258
+ var(--primer-control-small-gap, 8px) - var(--primer-borderWidth-thin, 1px)
259
+ ); /* 27px */
260
+ }
216
261
  }
217
- }
218
-
219
- // sizes
220
-
221
- // these selectors can be refactored to use :has()
222
- &.FormControl--small {
223
- height: var(--primer-control-small-size, 28px);
224
- font-size: var(--primer-text-body-size-small, 12px);
225
262
 
226
263
  .FormControl--input-trailingAction {
227
264
  width: calc(var(--primer-control-small-size, 28px) - var(--base-size-8, 8px));
228
265
  height: calc(var(--primer-control-small-size, 28px) - var(--base-size-8, 8px));
266
+
267
+ &::before {
268
+ top: calc((var(--primer-control-xsmall-size) - var(--base-size-16)) / 4); /* 2px */
269
+ }
229
270
  }
230
271
  }
231
272
 
232
- &.FormControl--medium {
233
- height: var(--primer-control-medium-size, 32px);
273
+ &.FormControl--large {
274
+ .FormControl--input-leadingVisualWrap {
275
+ top: var(--primer-control-medium-paddingInline-normal, 12px);
276
+ left: var(--primer-control-medium-paddingInline-normal, 12px);
277
+ }
234
278
 
235
- .FormControl--input-trailingAction {
236
- width: calc(var(--primer-control-medium-size, 32px) - var(--base-size-8, 8px));
237
- height: calc(var(--primer-control-medium-size, 32px) - var(--base-size-8, 8px));
279
+ &.FormControl-fieldWrap--input-leadingVisual {
280
+ .FormControl--input.FormControl--large {
281
+ padding-inline-start: calc(
282
+ var(--primer-control-large-paddingInline-normal, 12px) + var(--base-size-16, 16px) +
283
+ var(--primer-control-large-gap, 8px) - var(--primer-borderWidth-thin, 1px)
284
+ ); /* 31px */
285
+ }
238
286
  }
239
- }
240
287
 
241
- &.FormControl--large {
242
- height: var(--primer-control-large-size, 40px);
243
- padding-inline: var(--primer-control-large-paddingInline-normal, 12px);
288
+ &.FormControl-fieldWrap--input-trailingAction {
289
+ .FormControl--input.FormControl--large {
290
+ padding-inline-end: calc(
291
+ var(--primer-control-large-paddingInline-normal, 12px) + var(--base-size-16, 16px) +
292
+ var(--primer-control-large-gap, 8px)
293
+ ); /* 36px */
294
+ }
295
+ }
244
296
 
245
297
  .FormControl--input-trailingAction {
246
- width: calc(var(--primer-control-large-size, 40px) - var(--base-size-8, 8px));
247
- height: calc(var(--primer-control-large-size, 40px) - var(--base-size-8, 8px));
248
- margin-right: calc(calc(var(--primer-control-medium-paddingInline-normal, 12px) - 0.125rem) * -1);
298
+ top: calc(var(--primer-control-medium-paddingInline-condensed, 8px) - 0.125rem); /* 6px */
299
+ right: calc(var(--primer-control-medium-paddingInline-condensed, 8px) - 0.125rem); /* 6px */
300
+ width: var(--primer-control-small-size, 28px);
301
+ height: var(--primer-control-small-size, 28px);
302
+
303
+ &::before {
304
+ top: unset;
305
+ height: var(--base-size-20);
306
+ }
249
307
  }
250
308
  }
251
309
  }
@@ -253,17 +311,18 @@
253
311
 
254
312
  .FormControl-fieldWrap--select {
255
313
  grid-template-columns: minmax(0, auto) var(--base-size-16, 16px);
256
- padding-inline-end: var(--primer-control-medium-paddingInline-condensed, 8px);
257
314
 
258
315
  // mask allows for background-color to respect themes
259
316
  &::after {
260
317
  width: var(--base-size-16, 16px);
261
318
  height: var(--base-size-16, 16px);
319
+ padding-right: var(--base-size-4, 4px);
262
320
  pointer-events: none;
263
321
  content: '';
264
322
  background-color: var(--color-fg-muted);
265
323
  mask: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0iIzU4NjA2OSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNNC40MjcgOS40MjdsMy4zOTYgMy4zOTZhLjI1MS4yNTEgMCAwMC4zNTQgMGwzLjM5Ni0zLjM5NkEuMjUuMjUgMCAwMDExLjM5NiA5SDQuNjA0YS4yNS4yNSAwIDAwLS4xNzcuNDI3ek00LjQyMyA2LjQ3TDcuODIgMy4wNzJhLjI1LjI1IDAgMDEuMzU0IDBMMTEuNTcgNi40N2EuMjUuMjUgMCAwMS0uMTc3LjQyN0g0LjZhLjI1LjI1IDAgMDEtLjE3Ny0uNDI3eiIgLz48L3N2Zz4=');
266
- mask-size: cover;
324
+ mask-size: contain;
325
+ mask-repeat: no-repeat;
267
326
  grid-column: 2;
268
327
  grid-row: 1;
269
328
  place-self: center end;
@@ -274,15 +333,26 @@
274
333
  grid-column: 1/-1;
275
334
  grid-row: 1;
276
335
  appearance: none;
277
- padding-right: var(--base-size-16, 16px);
336
+ padding-right: var(--base-size-20, 20px);
278
337
  }
279
338
  }
280
339
 
281
- .FormGroup--checkbox {
340
+ // checkbox + radio specific styles
341
+
342
+ .FormGroup--checkbox,
343
+ .FormGroup--radio {
282
344
  display: inline-grid;
283
345
  grid-template-areas: 'field label' '. caption';
346
+ grid-template-columns: min-content auto;
284
347
  gap: var(--base-size-8, 8px);
285
348
 
349
+ .FormControl--checkbox-labelWrap,
350
+ .FormControl--radio-labelWrap {
351
+ display: flex;
352
+ flex-direction: column;
353
+ gap: var(--base-size-4, 4px);
354
+ }
355
+
286
356
  .FormControl-label {
287
357
  grid-area: label;
288
358
  }
@@ -292,91 +362,128 @@
292
362
  }
293
363
  }
294
364
 
295
- // checkbox + radio specific styles
296
-
297
- .FormControl--checkbox,
298
- .FormControl--radio {
299
- position: absolute;
365
+ // these selectors are temporary to override base.scss
366
+ // once FormControl styles are widely adopted, we can adjust this and the global base styles
367
+ input[type='checkbox'].FormControl--checkbox,
368
+ input[type='radio'].FormControl--radio {
369
+ display: grid;
300
370
  width: var(--base-size-16, 16px);
301
371
  height: var(--base-size-16, 16px);
302
- opacity: 0;
372
+ margin: 0;
373
+ margin-top: 0.125rem; // 2px to center align with label (20px line-height)
374
+ border: solid var(--primer-borderWidth-thin, 1px) var(--color-border-default);
375
+ border-radius: var(--primer-borderRadius-small, 3px);
376
+ // stylelint-disable-next-line declaration-property-value-disallowed-list
377
+ transition: border-color, background 80ms cubic-bezier(0.33, 1, 0.68, 1) 120ms; // checked -> unchecked
378
+ appearance: none;
379
+ place-content: center;
380
+ grid-area: field;
381
+
382
+ &::before {
383
+ width: var(--base-size-16, 16px);
384
+ height: var(--base-size-16, 16px);
385
+ visibility: hidden;
386
+ content: '';
387
+ background-color: var(--color-fg-on-emphasis);
388
+ transition: visibility 0s linear 230ms;
389
+ clip-path: inset(var(--base-size-16, 16px) 0 0 0);
390
+ mask-image: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTIiIGhlaWdodD0iOSIgdmlld0JveD0iMCAwIDEyIDkiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMTEuNzgwMyAwLjIxOTYyNUMxMS45MjEgMC4zNjA0MjcgMTIgMC41NTEzMDUgMTIgMC43NTAzMTNDMTIgMC45NDkzMjEgMTEuOTIxIDEuMTQwMTkgMTEuNzgwMyAxLjI4MUw0LjUxODYgOC41NDA0MkM0LjM3Nzc1IDguNjgxIDQuMTg2ODIgOC43NiAzLjk4Nzc0IDguNzZDMy43ODg2NyA4Ljc2IDMuNTk3NzMgOC42ODEgMy40NTY4OSA4LjU0MDQyTDAuMjAxNjIyIDUuMjg2MkMwLjA2ODkyNzcgNS4xNDM4MyAtMC4wMDMzMDkwNSA0Ljk1NTU1IDAuMDAwMTE2NDkzIDQuNzYwOThDMC4wMDM1NTIwNSA0LjU2NjQzIDAuMDgyMzg5NCA0LjM4MDgxIDAuMjIwMDMyIDQuMjQzMjFDMC4zNTc2NjUgNC4xMDU2MiAwLjU0MzM1NSA0LjAyNjgxIDAuNzM3OTcgNC4wMjMzOEMwLjkzMjU4NCA0LjAxOTk0IDEuMTIwOTMgNC4wOTIxNyAxLjI2MzM0IDQuMjI0ODJMMy45ODc3NCA2Ljk0ODM1TDEwLjcxODYgMC4yMTk2MjVDMTAuODU5NSAwLjA3ODk5MjMgMTEuMDUwNCAwIDExLjI0OTUgMEMxMS40NDg1IDAgMTEuNjM5NSAwLjA3ODk5MjMgMTEuNzgwMyAwLjIxOTYyNVoiIGZpbGw9IndoaXRlIi8+Cjwvc3ZnPgo='); // octicon checkmark image
391
+ mask-size: contain;
392
+ mask-repeat: no-repeat;
393
+ mask-position: center;
394
+
395
+ @media screen and (prefers-reduced-motion: no-preference) {
396
+ animation: checkmarkOut 80ms cubic-bezier(0.65, 0, 0.35, 1) forwards; // slightly snappier animation out
397
+ }
398
+ }
303
399
 
304
400
  &:checked {
305
- + .FormControl--checkbox-svg {
306
- .FormControl--checkbox-background {
307
- fill: var(--color-accent-fg);
308
- stroke: var(--color-accent-fg);
309
- }
401
+ background: var(--color-accent-fg);
402
+ border-color: var(--color-accent-fg);
403
+ // stylelint-disable-next-line declaration-property-value-disallowed-list
404
+ transition: border-color, background 80ms cubic-bezier(0.32, 0, 0.67, 0) 0ms; // unchecked -> checked
310
405
 
311
- .FormControl--checkbox-check {
312
- fill: var(--color-fg-on-emphasis);
313
- visibility: visible;
406
+ &::before {
407
+ visibility: visible;
408
+ transition: visibility 0s linear 0s;
314
409
 
315
- @media screen and (prefers-reduced-motion: no-preference) {
316
- animation: checkmarkIn 200ms cubic-bezier(0.11, 0, 0.5, 0) forwards;
317
- }
410
+ @media screen and (prefers-reduced-motion: no-preference) {
411
+ animation: checkmarkIn 80ms cubic-bezier(0.65, 0, 0.35, 1) forwards 80ms;
318
412
  }
319
413
  }
320
414
  }
321
415
 
322
- &:indeterminate {
323
- + .FormControl--checkbox-svg {
324
- .FormControl--checkbox-background {
325
- fill: var(--color-accent-fg);
326
- stroke: var(--color-accent-fg);
327
- }
416
+ &:focus,
417
+ &:focus-visible {
418
+ outline-offset: 2px;
419
+ }
328
420
 
329
- .FormControl--checkbox-indeterminate {
330
- fill: var(--color-fg-on-emphasis);
331
- visibility: visible;
332
- }
421
+ &:indeterminate {
422
+ &::before {
423
+ mask-image: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAiIGhlaWdodD0iMiIgdmlld0JveD0iMCAwIDEwIDIiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMCAxQzAgMC40NDc3MTUgMC40NDc3MTUgMCAxIDBIOUM5LjU1MjI5IDAgMTAgMC40NDc3MTUgMTAgMUMxMCAxLjU1MjI4IDkuNTUyMjkgMiA5IDJIMUMwLjQ0NzcxNSAyIDAgMS41NTIyOCAwIDFaIiBmaWxsPSJ3aGl0ZSIvPgo8L3N2Zz4K');
424
+ visibility: visible;
333
425
  }
334
426
  }
427
+ }
335
428
 
336
- @keyframes checkmarkIn {
337
- from {
338
- clip-path: inset(16px 0 0 0);
339
- }
429
+ input[type='radio'].FormControl--radio {
430
+ border-radius: var(--primer-borderRadius-full, 100vh);
431
+
432
+ &::before {
433
+ clip-path: circle(0%);
434
+ mask-image: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAiIGhlaWdodD0iMTAiIHZpZXdCb3g9IjAgMCAxMCAxMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTUgOS4zNzVDNy40MTYyMiA5LjM3NSA5LjM3NSA3LjQxNjIyIDkuMzc1IDVDOS4zNzUgMi41ODM3NiA3LjQxNjIyIDAuNjI1IDUgMC42MjVDMi41ODM3NiAwLjYyNSAwLjYyNSAyLjU4Mzc2IDAuNjI1IDVDMC42MjUgNy40MTYyMiAyLjU4Mzc2IDkuMzc1IDUgOS4zNzVaIiBmaWxsPSJ3aGl0ZSIvPgo8L3N2Zz4K'); // checked circle image
435
+ mask-size: 65%;
340
436
 
341
- to {
342
- clip-path: inset(0 0 0 0);
437
+ @media screen and (prefers-reduced-motion: no-preference) {
438
+ animation: radioOut 80ms cubic-bezier(0.65, 0, 0.35, 1) forwards; // slightly snappier animation out
343
439
  }
344
440
  }
345
441
 
346
- @keyframes checkmarkOut {
347
- from {
348
- clip-path: inset(0 0 0 0);
442
+ &:checked {
443
+ &::before {
444
+ @media screen and (prefers-reduced-motion: no-preference) {
445
+ animation: radioIn 80ms cubic-bezier(0.65, 0, 0.35, 1) forwards 80ms;
446
+ }
349
447
  }
448
+ }
449
+ }
350
450
 
351
- to {
352
- clip-path: inset(16px 0 0 0);
353
- }
451
+ @keyframes checkmarkIn {
452
+ from {
453
+ clip-path: inset(var(--base-size-16, 16px) 0 0 0);
454
+ }
455
+
456
+ to {
457
+ clip-path: inset(0 0 0 0);
354
458
  }
355
459
  }
356
460
 
357
- .FormControl--checkbox-svg {
358
- width: var(--base-size-16, 16px);
359
- height: var(--base-size-16, 16px);
360
- margin-top: 0.125rem;
361
- cursor: pointer;
461
+ @keyframes checkmarkOut {
462
+ from {
463
+ clip-path: inset(0 0 0 0);
464
+ }
465
+
466
+ to {
467
+ clip-path: inset(var(--base-size-16, 16px) 0 0 0);
468
+ }
469
+ }
362
470
 
363
- .FormControl--checkbox-background {
364
- fill: var(--color-canvas-default);
365
- stroke: var(--color-border-default);
471
+ @keyframes radioIn {
472
+ from {
473
+ clip-path: circle(0%);
366
474
  }
367
475
 
368
- .FormControl--checkbox-check {
369
- visibility: hidden;
370
- transition: visibility 0s linear 200ms;
371
- clip-path: inset(16px 0 0 0);
476
+ to {
477
+ clip-path: circle(100%);
478
+ }
479
+ }
372
480
 
373
- @media screen and (prefers-reduced-motion: no-preference) {
374
- animation: checkmarkOut 200ms cubic-bezier(0.11, 0, 0.5, 0) forwards;
375
- }
481
+ @keyframes radioOut {
482
+ from {
483
+ clip-path: circle(100%);
376
484
  }
377
485
 
378
- .FormControl--checkbox-indeterminate {
379
- fill: transparent;
380
- visibility: hidden;
486
+ to {
487
+ clip-path: circle(0%);
381
488
  }
382
489
  }