al-design-system 1.3.0 → 1.5.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/README.md +7 -5
- package/README.pt-BR.md +7 -5
- package/dist/al.css +603 -2
- package/dist/components/menu.css +236 -0
- package/dist/components/menu.js +111 -0
- package/dist/components/number-field.css +363 -0
- package/dist/components/number-field.js +83 -0
- package/dist/foundation.css +1 -1
- package/dist/tokens.json +1 -1
- package/package.json +1 -1
package/dist/al.css
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
/* AL Design System 1.
|
|
1
|
+
/* AL Design System 1.5.0 - Foundation + 28 components.
|
|
2
2
|
* MIT. https://github.com/guilhermedworakowski/al-design-system
|
|
3
3
|
*/
|
|
4
4
|
/* AL Design System - Foundation
|
|
5
|
-
* v1.
|
|
5
|
+
* v1.5.0 - MIT
|
|
6
6
|
* GENERATED by src/foundation/css.py. Do not edit by hand: run the script.
|
|
7
7
|
*/
|
|
8
8
|
|
|
@@ -7243,3 +7243,604 @@
|
|
|
7243
7243
|
outline-offset: var(--al-border-focus-offset);
|
|
7244
7244
|
}
|
|
7245
7245
|
}
|
|
7246
|
+
|
|
7247
|
+
/* AL Design System - Number field tokens
|
|
7248
|
+
* GENERATED by src/components/number-field/tokens.py. Do not edit by hand.
|
|
7249
|
+
*
|
|
7250
|
+
* There is no theme block here: each token points to a semantic, and the
|
|
7251
|
+
* theme switches on :root - the same element where these aliases are declared.
|
|
7252
|
+
*
|
|
7253
|
+
* Field height: 48px, derived, no token.
|
|
7254
|
+
* Stepper target: 24px = icon-size, no token of its own.
|
|
7255
|
+
*/
|
|
7256
|
+
|
|
7257
|
+
:root {
|
|
7258
|
+
|
|
7259
|
+
/* background - only disabled and readonly change it */
|
|
7260
|
+
--al-number-field-bg: var(--al-bg-surface-raised);
|
|
7261
|
+
--al-number-field-bg-disabled: var(--al-bg-disabled);
|
|
7262
|
+
--al-number-field-bg-readonly: var(--al-bg-subtle);
|
|
7263
|
+
|
|
7264
|
+
/* border - the axis that carries the state */
|
|
7265
|
+
--al-number-field-border: var(--al-border-default);
|
|
7266
|
+
--al-number-field-border-hover: var(--al-border-strong);
|
|
7267
|
+
--al-number-field-border-focus: var(--al-border-brand);
|
|
7268
|
+
--al-number-field-border-error: var(--al-border-danger);
|
|
7269
|
+
--al-number-field-border-disabled: var(--al-border-default);
|
|
7270
|
+
--al-number-field-border-readonly: var(--al-border-subtle);
|
|
7271
|
+
|
|
7272
|
+
/* value - no placeholder, the field always has a value */
|
|
7273
|
+
--al-number-field-text-value: var(--al-text-primary);
|
|
7274
|
+
--al-number-field-text-disabled: var(--al-text-disabled);
|
|
7275
|
+
|
|
7276
|
+
/* steppers - out of the Tab order, no hover or ring of their own */
|
|
7277
|
+
--al-number-field-stepper-icon: var(--al-text-primary);
|
|
7278
|
+
--al-number-field-stepper-icon-disabled: var(--al-text-disabled);
|
|
7279
|
+
|
|
7280
|
+
/* label, mark and help - they live outside the field, on the canvas */
|
|
7281
|
+
--al-number-field-label: var(--al-text-primary);
|
|
7282
|
+
--al-number-field-label-error: var(--al-text-danger);
|
|
7283
|
+
--al-number-field-label-disabled: var(--al-text-disabled);
|
|
7284
|
+
--al-number-field-optional: var(--al-text-secondary);
|
|
7285
|
+
--al-number-field-help: var(--al-text-secondary);
|
|
7286
|
+
--al-number-field-help-error: var(--al-text-danger);
|
|
7287
|
+
|
|
7288
|
+
/* focus ring - points to the composite shadow, not the raw color */
|
|
7289
|
+
--al-number-field-ring: var(--al-focus-ring-default);
|
|
7290
|
+
--al-number-field-ring-error: var(--al-focus-ring-error);
|
|
7291
|
+
|
|
7292
|
+
/* geometry */
|
|
7293
|
+
--al-number-field-padding-x: var(--al-space-12);
|
|
7294
|
+
--al-number-field-padding-y: var(--al-space-12);
|
|
7295
|
+
--al-number-field-gap: var(--al-space-8);
|
|
7296
|
+
--al-number-field-stepper-gap: var(--al-space-24);
|
|
7297
|
+
--al-number-field-radius: var(--al-radius-lg);
|
|
7298
|
+
--al-number-field-border-width: var(--al-border-width-1);
|
|
7299
|
+
--al-number-field-icon-size: var(--al-icon-size-24);
|
|
7300
|
+
|
|
7301
|
+
/* width of the box - declared literal, the Foundation has no width scale */
|
|
7302
|
+
--al-number-field-width: 140px;
|
|
7303
|
+
|
|
7304
|
+
/* typography - one style becomes four vars */
|
|
7305
|
+
--al-number-field-font-size: var(--al-font-size-md);
|
|
7306
|
+
--al-number-field-line-height: var(--al-line-height-md);
|
|
7307
|
+
--al-number-field-font-weight: 400;
|
|
7308
|
+
--al-number-field-tracking: 0em;
|
|
7309
|
+
--al-number-field-label-font-size: var(--al-font-size-md);
|
|
7310
|
+
--al-number-field-label-line-height: var(--al-line-height-md);
|
|
7311
|
+
--al-number-field-label-font-weight: 400;
|
|
7312
|
+
--al-number-field-label-tracking: 0em;
|
|
7313
|
+
--al-number-field-optional-font-size: var(--al-font-size-sm);
|
|
7314
|
+
--al-number-field-optional-line-height: var(--al-line-height-sm);
|
|
7315
|
+
--al-number-field-optional-font-weight: 400;
|
|
7316
|
+
--al-number-field-optional-tracking: 0em;
|
|
7317
|
+
--al-number-field-help-font-size: var(--al-font-size-xs);
|
|
7318
|
+
--al-number-field-help-line-height: var(--al-line-height-xs);
|
|
7319
|
+
--al-number-field-help-font-weight: 400;
|
|
7320
|
+
--al-number-field-help-tracking: 0.01em;
|
|
7321
|
+
}
|
|
7322
|
+
|
|
7323
|
+
/* AL Design System - Number field
|
|
7324
|
+
*
|
|
7325
|
+
* Depends on: foundation/al-foundation.css
|
|
7326
|
+
* + components/number-field/al-number-field-tokens.css
|
|
7327
|
+
* + components/icon/icon.css
|
|
7328
|
+
* + components/number-field/number-field.js (the steppers)
|
|
7329
|
+
*
|
|
7330
|
+
* A QUANTITY THE PERSON ADJUSTS A LITTLE AT A TIME
|
|
7331
|
+
* A native <input type="number"> between a - and a + button. Numbers that
|
|
7332
|
+
* are not quantities (zip code, phone, card) are the Input with
|
|
7333
|
+
* inputmode="numeric" - rule 2.
|
|
7334
|
+
*
|
|
7335
|
+
* ANATOMY
|
|
7336
|
+
* <div class="al-number-field">
|
|
7337
|
+
* <div class="al-number-field__labelrow">
|
|
7338
|
+
* <label class="al-number-field__label" for="qty">Quantity</label>
|
|
7339
|
+
* <span class="al-number-field__optional">(Optional)</span>
|
|
7340
|
+
* </div>
|
|
7341
|
+
* <div class="al-number-field__control">
|
|
7342
|
+
* <button class="al-number-field__step" type="button" tabindex="-1"
|
|
7343
|
+
* data-step="down" aria-controls="qty"
|
|
7344
|
+
* aria-label="Decrease quantity" hidden>
|
|
7345
|
+
* <svg class="al-icon" aria-hidden="true" focusable="false">minus</svg>
|
|
7346
|
+
* </button>
|
|
7347
|
+
* <input class="al-number-field__field" id="qty" type="number"
|
|
7348
|
+
* min="1" max="10" step="1" value="1"
|
|
7349
|
+
* aria-describedby="qty-help">
|
|
7350
|
+
* <button class="al-number-field__step" type="button" tabindex="-1"
|
|
7351
|
+
* data-step="up" aria-controls="qty"
|
|
7352
|
+
* aria-label="Increase quantity" hidden>
|
|
7353
|
+
* <svg class="al-icon" aria-hidden="true" focusable="false">plus</svg>
|
|
7354
|
+
* </button>
|
|
7355
|
+
* </div>
|
|
7356
|
+
* <p class="al-number-field__help" id="qty-help">From 1 to 10</p>
|
|
7357
|
+
* </div>
|
|
7358
|
+
*
|
|
7359
|
+
* THE STEPPERS ARE OUT OF THE TAB ORDER
|
|
7360
|
+
* One tab stop: the arrow keys and typing change the value (Carbon, rule
|
|
7361
|
+
* 13). So the buttons carry tabindex="-1", have no ring and no hover of
|
|
7362
|
+
* their own (rule 14) - the field's border and ring say where pointer and
|
|
7363
|
+
* focus are. They are born `hidden`: without JavaScript the arrow keys
|
|
7364
|
+
* still work and a button that does nothing never shows (the same as the
|
|
7365
|
+
* Password's eye).
|
|
7366
|
+
*
|
|
7367
|
+
* THE STEPPER AT THE LIMIT IS A DISABLED <button>
|
|
7368
|
+
* At the minimum the - is `disabled`, at the maximum the + (rule 10). The
|
|
7369
|
+
* JS sets the attribute; the CSS only reads `:disabled`. There is no Figma
|
|
7370
|
+
* variant for it.
|
|
7371
|
+
*
|
|
7372
|
+
* THE BOX IS `__control`, NOT THE <input>
|
|
7373
|
+
* The same as the Input: border, background, radius and ring live on
|
|
7374
|
+
* `__control` and the state is read through `:has()`. Without `:has()` the
|
|
7375
|
+
* native outline stays (it is only removed inside @supports).
|
|
7376
|
+
*
|
|
7377
|
+
* THE STATE IS DRIVEN BY THE MARKUP
|
|
7378
|
+
* Error reads `aria-invalid="true"`; disabled `:disabled`; read-only
|
|
7379
|
+
* `[readonly]` - never `:read-only`, which also matches disabled. The same
|
|
7380
|
+
* precedence by variable as the Input: error, read-only, disabled in file
|
|
7381
|
+
* order, disabled wins over all.
|
|
7382
|
+
*
|
|
7383
|
+
* READ-ONLY HAS NO STEPPERS (rule 17)
|
|
7384
|
+
* Nothing can change, so they are hidden and the value stays centered.
|
|
7385
|
+
*
|
|
7386
|
+
* THE BROWSER'S OWN SPINNERS ARE HIDDEN
|
|
7387
|
+
* WebKit draws arrows inside type=number and Firefox draws its own. With
|
|
7388
|
+
* AL's buttons there would be two pairs.
|
|
7389
|
+
*
|
|
7390
|
+
* HEIGHT AND WIDTH
|
|
7391
|
+
* 48 = padding-y x2 + line height, border subtracted from the padding.
|
|
7392
|
+
* The box is fixed at `--al-number-field-width` (140), decided on
|
|
7393
|
+
* 2026-10-21. Label and help text are not limited by it - they may be
|
|
7394
|
+
* wider than the box.
|
|
7395
|
+
*
|
|
7396
|
+
* HANDWRITTEN. The tokens it consumes are generated by tokens.py.
|
|
7397
|
+
*/
|
|
7398
|
+
|
|
7399
|
+
/* ---------------------------------------------------------------- root */
|
|
7400
|
+
.al-number-field {
|
|
7401
|
+
display: flex;
|
|
7402
|
+
flex-direction: column;
|
|
7403
|
+
gap: var(--al-number-field-gap);
|
|
7404
|
+
}
|
|
7405
|
+
|
|
7406
|
+
/* ------------------------------------------------------------ label */
|
|
7407
|
+
.al-number-field__labelrow {
|
|
7408
|
+
display: flex;
|
|
7409
|
+
align-items: baseline;
|
|
7410
|
+
gap: var(--al-number-field-gap);
|
|
7411
|
+
}
|
|
7412
|
+
|
|
7413
|
+
.al-number-field__label {
|
|
7414
|
+
color: var(--al-number-field-label);
|
|
7415
|
+
font-family: var(--al-font-sans);
|
|
7416
|
+
font-size: var(--al-number-field-label-font-size);
|
|
7417
|
+
line-height: var(--al-number-field-label-line-height);
|
|
7418
|
+
font-weight: var(--al-number-field-label-font-weight);
|
|
7419
|
+
letter-spacing: var(--al-number-field-label-tracking);
|
|
7420
|
+
}
|
|
7421
|
+
|
|
7422
|
+
.al-number-field__optional {
|
|
7423
|
+
color: var(--al-number-field-optional);
|
|
7424
|
+
font-family: var(--al-font-sans);
|
|
7425
|
+
font-size: var(--al-number-field-optional-font-size);
|
|
7426
|
+
line-height: var(--al-number-field-optional-line-height);
|
|
7427
|
+
font-weight: var(--al-number-field-optional-font-weight);
|
|
7428
|
+
letter-spacing: var(--al-number-field-optional-tracking);
|
|
7429
|
+
}
|
|
7430
|
+
|
|
7431
|
+
/* --------------------------------------------------------------- box */
|
|
7432
|
+
.al-number-field__control {
|
|
7433
|
+
--_border-state: var(--al-number-field-border);
|
|
7434
|
+
|
|
7435
|
+
box-sizing: border-box;
|
|
7436
|
+
display: flex;
|
|
7437
|
+
align-items: center;
|
|
7438
|
+
gap: var(--al-number-field-stepper-gap);
|
|
7439
|
+
width: var(--al-number-field-width);
|
|
7440
|
+
|
|
7441
|
+
padding: calc(var(--al-number-field-padding-y) - var(--al-number-field-border-width))
|
|
7442
|
+
calc(var(--al-number-field-padding-x) - var(--al-number-field-border-width));
|
|
7443
|
+
|
|
7444
|
+
border: var(--al-number-field-border-width) solid
|
|
7445
|
+
var(--_border-force, var(--_border-state));
|
|
7446
|
+
border-radius: var(--al-number-field-radius);
|
|
7447
|
+
background-color: var(--_bg-force, var(--al-number-field-bg));
|
|
7448
|
+
cursor: text;
|
|
7449
|
+
|
|
7450
|
+
transition:
|
|
7451
|
+
border-color var(--al-motion-duration-feedback) var(--al-motion-easing-exit),
|
|
7452
|
+
box-shadow var(--al-motion-duration-feedback) var(--al-motion-easing-exit);
|
|
7453
|
+
}
|
|
7454
|
+
|
|
7455
|
+
/* ------------------------------------------------------------- field */
|
|
7456
|
+
.al-number-field__field {
|
|
7457
|
+
--_text-state: var(--al-number-field-text-value);
|
|
7458
|
+
|
|
7459
|
+
flex: 1 1 0;
|
|
7460
|
+
min-width: 0;
|
|
7461
|
+
width: 100%;
|
|
7462
|
+
margin: 0;
|
|
7463
|
+
padding: 0;
|
|
7464
|
+
border: 0;
|
|
7465
|
+
background: none;
|
|
7466
|
+
color: var(--_text-force, var(--_text-state));
|
|
7467
|
+
text-align: center;
|
|
7468
|
+
|
|
7469
|
+
font-family: var(--al-font-sans);
|
|
7470
|
+
font-size: var(--al-number-field-font-size);
|
|
7471
|
+
line-height: var(--al-number-field-line-height);
|
|
7472
|
+
font-weight: var(--al-number-field-font-weight);
|
|
7473
|
+
letter-spacing: var(--al-number-field-tracking);
|
|
7474
|
+
font-variant-numeric: tabular-nums;
|
|
7475
|
+
|
|
7476
|
+
-moz-appearance: textfield;
|
|
7477
|
+
appearance: textfield;
|
|
7478
|
+
}
|
|
7479
|
+
|
|
7480
|
+
/* the browser's own spinners - see the header */
|
|
7481
|
+
.al-number-field__field::-webkit-inner-spin-button,
|
|
7482
|
+
.al-number-field__field::-webkit-outer-spin-button {
|
|
7483
|
+
-webkit-appearance: none;
|
|
7484
|
+
margin: 0;
|
|
7485
|
+
}
|
|
7486
|
+
|
|
7487
|
+
@supports selector(:has(*)) {
|
|
7488
|
+
.al-number-field__field:focus {
|
|
7489
|
+
outline: none;
|
|
7490
|
+
}
|
|
7491
|
+
}
|
|
7492
|
+
|
|
7493
|
+
/* --------------------------------------------------------- the steppers */
|
|
7494
|
+
.al-number-field__step {
|
|
7495
|
+
display: inline-flex;
|
|
7496
|
+
align-items: center;
|
|
7497
|
+
justify-content: center;
|
|
7498
|
+
flex: none;
|
|
7499
|
+
|
|
7500
|
+
box-sizing: border-box;
|
|
7501
|
+
width: var(--al-number-field-icon-size);
|
|
7502
|
+
height: var(--al-number-field-icon-size);
|
|
7503
|
+
margin: 0;
|
|
7504
|
+
padding: 0;
|
|
7505
|
+
border: 0;
|
|
7506
|
+
background: none;
|
|
7507
|
+
/* the svg inherits from here through currentColor - the Icon contract */
|
|
7508
|
+
color: var(--al-number-field-stepper-icon);
|
|
7509
|
+
|
|
7510
|
+
cursor: pointer;
|
|
7511
|
+
-webkit-appearance: none;
|
|
7512
|
+
appearance: none;
|
|
7513
|
+
-webkit-tap-highlight-color: transparent;
|
|
7514
|
+
}
|
|
7515
|
+
|
|
7516
|
+
/* `display` above would beat the attribute - without JS the buttons don't show */
|
|
7517
|
+
.al-number-field__step[hidden] {
|
|
7518
|
+
display: none;
|
|
7519
|
+
}
|
|
7520
|
+
|
|
7521
|
+
.al-number-field__step > svg {
|
|
7522
|
+
display: block;
|
|
7523
|
+
flex: none;
|
|
7524
|
+
width: var(--al-number-field-icon-size);
|
|
7525
|
+
height: var(--al-number-field-icon-size);
|
|
7526
|
+
}
|
|
7527
|
+
|
|
7528
|
+
/* at the limit, and in a disabled field - rule 10 */
|
|
7529
|
+
.al-number-field__step:disabled {
|
|
7530
|
+
color: var(--al-number-field-stepper-icon-disabled);
|
|
7531
|
+
cursor: not-allowed;
|
|
7532
|
+
}
|
|
7533
|
+
|
|
7534
|
+
/* ------------------------------------------------------------ help text */
|
|
7535
|
+
.al-number-field__help {
|
|
7536
|
+
color: var(--al-number-field-help);
|
|
7537
|
+
font-family: var(--al-font-sans);
|
|
7538
|
+
font-size: var(--al-number-field-help-font-size);
|
|
7539
|
+
line-height: var(--al-number-field-help-line-height);
|
|
7540
|
+
font-weight: var(--al-number-field-help-font-weight);
|
|
7541
|
+
letter-spacing: var(--al-number-field-help-tracking);
|
|
7542
|
+
margin: 0;
|
|
7543
|
+
}
|
|
7544
|
+
|
|
7545
|
+
/* -------------------------------------------------------------- states */
|
|
7546
|
+
.al-number-field__control:hover:not(:has(.al-number-field__field:disabled, .al-number-field__field[readonly])) {
|
|
7547
|
+
--_border-state: var(--al-number-field-border-hover);
|
|
7548
|
+
}
|
|
7549
|
+
|
|
7550
|
+
.al-number-field__control:has(.al-number-field__field:focus-visible) {
|
|
7551
|
+
--_border-state: var(--al-number-field-border-focus);
|
|
7552
|
+
box-shadow: var(--_ring-force, var(--al-number-field-ring));
|
|
7553
|
+
}
|
|
7554
|
+
|
|
7555
|
+
/* error - beats hover and focus by writing to another property */
|
|
7556
|
+
.al-number-field__control:has(.al-number-field__field[aria-invalid="true"]) {
|
|
7557
|
+
--_border-force: var(--al-number-field-border-error);
|
|
7558
|
+
--_ring-force: var(--al-number-field-ring-error);
|
|
7559
|
+
}
|
|
7560
|
+
|
|
7561
|
+
.al-number-field:has(.al-number-field__field[aria-invalid="true"]) .al-number-field__label {
|
|
7562
|
+
color: var(--al-number-field-label-error);
|
|
7563
|
+
}
|
|
7564
|
+
|
|
7565
|
+
.al-number-field:has(.al-number-field__field[aria-invalid="true"]) .al-number-field__help {
|
|
7566
|
+
color: var(--al-number-field-help-error);
|
|
7567
|
+
}
|
|
7568
|
+
|
|
7569
|
+
/* read-only - `[readonly]`, never `:read-only`. No steppers - rule 17. */
|
|
7570
|
+
.al-number-field__control:has(.al-number-field__field[readonly]) {
|
|
7571
|
+
--_border-force: var(--al-number-field-border-readonly);
|
|
7572
|
+
--_bg-force: var(--al-number-field-bg-readonly);
|
|
7573
|
+
cursor: default;
|
|
7574
|
+
}
|
|
7575
|
+
|
|
7576
|
+
.al-number-field__control:has(.al-number-field__field[readonly]) .al-number-field__step {
|
|
7577
|
+
display: none;
|
|
7578
|
+
}
|
|
7579
|
+
|
|
7580
|
+
/* disabled - last, because it wins over all */
|
|
7581
|
+
.al-number-field__control:has(.al-number-field__field:disabled) {
|
|
7582
|
+
--_border-force: var(--al-number-field-border-disabled);
|
|
7583
|
+
--_bg-force: var(--al-number-field-bg-disabled);
|
|
7584
|
+
cursor: not-allowed;
|
|
7585
|
+
}
|
|
7586
|
+
|
|
7587
|
+
.al-number-field__field:disabled {
|
|
7588
|
+
--_text-force: var(--al-number-field-text-disabled);
|
|
7589
|
+
cursor: not-allowed;
|
|
7590
|
+
}
|
|
7591
|
+
|
|
7592
|
+
.al-number-field:has(.al-number-field__field:disabled) .al-number-field__label,
|
|
7593
|
+
.al-number-field:has(.al-number-field__field:disabled) .al-number-field__optional {
|
|
7594
|
+
color: var(--al-number-field-label-disabled);
|
|
7595
|
+
}
|
|
7596
|
+
|
|
7597
|
+
/* ENTER - CSS uses the curve of the state the transition goes to. */
|
|
7598
|
+
.al-number-field__control:hover,
|
|
7599
|
+
.al-number-field__control:has(.al-number-field__field:focus-visible),
|
|
7600
|
+
.al-number-field__control:has(.al-number-field__field[aria-invalid="true"]) {
|
|
7601
|
+
transition-timing-function: var(--al-motion-easing-enter);
|
|
7602
|
+
}
|
|
7603
|
+
|
|
7604
|
+
/* --------------------------------------------------------- environment */
|
|
7605
|
+
@media (prefers-reduced-motion: reduce) {
|
|
7606
|
+
.al-number-field__control {
|
|
7607
|
+
transition: none;
|
|
7608
|
+
}
|
|
7609
|
+
}
|
|
7610
|
+
|
|
7611
|
+
/* AL Design System - Menu tokens
|
|
7612
|
+
* GENERATED by src/components/menu/tokens.py. Do not edit by hand.
|
|
7613
|
+
*
|
|
7614
|
+
* Every color is a semantic the theme switches on :root.
|
|
7615
|
+
*/
|
|
7616
|
+
|
|
7617
|
+
:root {
|
|
7618
|
+
/* color - -raised hover and pressed (the menu lives on surface-raised) */
|
|
7619
|
+
--al-menu-bg: var(--al-bg-surface-raised);
|
|
7620
|
+
--al-menu-border: var(--al-border-default);
|
|
7621
|
+
--al-menu-item-label: var(--al-text-primary);
|
|
7622
|
+
--al-menu-item-meta: var(--al-text-secondary);
|
|
7623
|
+
--al-menu-item-meta-hover: var(--al-text-primary);
|
|
7624
|
+
--al-menu-item-bg-hover: var(--al-bg-hover-raised);
|
|
7625
|
+
--al-menu-item-bg-active: var(--al-bg-active-raised);
|
|
7626
|
+
--al-menu-item-label-disabled: var(--al-text-disabled);
|
|
7627
|
+
--al-menu-danger-label: var(--al-text-danger);
|
|
7628
|
+
--al-menu-danger-bg-hover: var(--al-bg-danger-subtle);
|
|
7629
|
+
--al-menu-danger-bg-active: var(--al-bg-danger);
|
|
7630
|
+
--al-menu-danger-label-active: var(--al-text-on-solid);
|
|
7631
|
+
--al-menu-ring: var(--al-border-focus);
|
|
7632
|
+
|
|
7633
|
+
/* elevation - height, not state */
|
|
7634
|
+
--al-menu-shadow: var(--al-elevation-3);
|
|
7635
|
+
|
|
7636
|
+
/* geometry */
|
|
7637
|
+
--al-menu-padding: var(--al-space-4);
|
|
7638
|
+
--al-menu-gap: var(--al-space-2);
|
|
7639
|
+
--al-menu-offset: var(--al-space-4);
|
|
7640
|
+
--al-menu-radius: var(--al-radius-xl);
|
|
7641
|
+
--al-menu-border-width: var(--al-border-width-1);
|
|
7642
|
+
--al-menu-item-padding-y: var(--al-space-8);
|
|
7643
|
+
--al-menu-item-padding-x: var(--al-space-12);
|
|
7644
|
+
--al-menu-item-gap: var(--al-space-8);
|
|
7645
|
+
--al-menu-item-radius: var(--al-radius-lg);
|
|
7646
|
+
--al-menu-item-icon-size: var(--al-icon-size-16);
|
|
7647
|
+
--al-menu-ring-width: var(--al-border-width-2);
|
|
7648
|
+
|
|
7649
|
+
/* width - declared value, no scale in the Foundation */
|
|
7650
|
+
--al-menu-width: 200px;
|
|
7651
|
+
|
|
7652
|
+
/* typography - one style becomes four vars */
|
|
7653
|
+
--al-menu-font-size: var(--al-font-size-sm);
|
|
7654
|
+
--al-menu-line-height: var(--al-line-height-sm);
|
|
7655
|
+
--al-menu-font-weight: 400;
|
|
7656
|
+
--al-menu-tracking: 0em;
|
|
7657
|
+
}
|
|
7658
|
+
|
|
7659
|
+
/* AL Design System - Menu
|
|
7660
|
+
*
|
|
7661
|
+
* Written by hand. Depends on al-foundation.css, the Icon Button (trigger),
|
|
7662
|
+
* the Icon, the Divider (separator) and al-menu-tokens.css. Behavior:
|
|
7663
|
+
* menu.js.
|
|
7664
|
+
*
|
|
7665
|
+
* No value here is literal: color, space, radius, border, shadow, ring, width
|
|
7666
|
+
* and type come from var(--al-menu-*). The check.py next to it rejects the
|
|
7667
|
+
* file if any escapes.
|
|
7668
|
+
*
|
|
7669
|
+
* MARKUP (WAI-ARIA menu button)
|
|
7670
|
+
*
|
|
7671
|
+
* <div class="al-menu">
|
|
7672
|
+
* <button class="al-icon-btn al-icon-btn--ghost al-icon-btn--sm"
|
|
7673
|
+
* aria-label="More actions" aria-haspopup="menu"
|
|
7674
|
+
* aria-expanded="false" aria-controls="m1">...</button>
|
|
7675
|
+
* <ul class="al-menu__list" role="menu" id="m1" aria-label="More actions" hidden>
|
|
7676
|
+
* <li role="none">
|
|
7677
|
+
* <button class="al-menu__item" role="menuitem" tabindex="-1"
|
|
7678
|
+
* aria-keyshortcuts="Meta+E">
|
|
7679
|
+
* <svg class="al-icon al-icon--16" aria-hidden="true">...</svg>
|
|
7680
|
+
* <span class="al-menu__label">Edit</span>
|
|
7681
|
+
* <kbd class="al-menu__shortcut" aria-hidden="true">⌘E</kbd>
|
|
7682
|
+
* </button>
|
|
7683
|
+
* </li>
|
|
7684
|
+
* <li class="al-divider" role="separator"></li>
|
|
7685
|
+
* <li role="none">
|
|
7686
|
+
* <button class="al-menu__item al-menu__item--danger" role="menuitem"
|
|
7687
|
+
* tabindex="-1">...Delete...</button>
|
|
7688
|
+
* </li>
|
|
7689
|
+
* </ul>
|
|
7690
|
+
* </div>
|
|
7691
|
+
*
|
|
7692
|
+
* Disabled: aria-disabled="true" on the item, never `disabled` - the item
|
|
7693
|
+
* stays focusable and is announced as unavailable (rule A=a, APG).
|
|
7694
|
+
* The shortcut is aria-hidden: aria-keyshortcuts already announces it, and
|
|
7695
|
+
* the product implements the key (rule 11).
|
|
7696
|
+
*
|
|
7697
|
+
* STATES
|
|
7698
|
+
*
|
|
7699
|
+
* hover :hover, not while focused - the ring on bg-hover-raised would
|
|
7700
|
+
* drop to 2.88:1 (rule 25)
|
|
7701
|
+
* pressed :active
|
|
7702
|
+
* focus :focus-visible, inset ring (an outer ring hits the neighbours)
|
|
7703
|
+
* danger hover bg-danger-subtle, pressed bg-danger with white ink (rule 16)
|
|
7704
|
+
*
|
|
7705
|
+
* The item has no height: 36 = padding-y x 2 + line height.
|
|
7706
|
+
*
|
|
7707
|
+
* MOTION
|
|
7708
|
+
*
|
|
7709
|
+
* Same fade as the Breadcrumb menu: `motion-duration-feedback`, ease-out
|
|
7710
|
+
* on opening, ease-in on closing. None with prefers-reduced-motion.
|
|
7711
|
+
*/
|
|
7712
|
+
|
|
7713
|
+
.al-menu {
|
|
7714
|
+
position: relative;
|
|
7715
|
+
display: inline-block;
|
|
7716
|
+
}
|
|
7717
|
+
|
|
7718
|
+
/* ------------------------------------------------------------------ panel */
|
|
7719
|
+
/* Aligned to the trigger's start edge, `offset` below it - as in Figma. */
|
|
7720
|
+
.al-menu__list {
|
|
7721
|
+
position: absolute;
|
|
7722
|
+
top: calc(100% + var(--al-menu-offset));
|
|
7723
|
+
left: 0;
|
|
7724
|
+
z-index: 1;
|
|
7725
|
+
display: flex;
|
|
7726
|
+
inline-size: var(--al-menu-width);
|
|
7727
|
+
box-sizing: border-box;
|
|
7728
|
+
flex-direction: column;
|
|
7729
|
+
gap: var(--al-menu-gap);
|
|
7730
|
+
margin: 0;
|
|
7731
|
+
padding: var(--al-menu-padding);
|
|
7732
|
+
list-style: none;
|
|
7733
|
+
border: var(--al-menu-border-width) solid var(--al-menu-border);
|
|
7734
|
+
border-radius: var(--al-menu-radius);
|
|
7735
|
+
background-color: var(--al-menu-bg);
|
|
7736
|
+
box-shadow: var(--al-menu-shadow);
|
|
7737
|
+
transition:
|
|
7738
|
+
opacity var(--al-motion-duration-feedback) var(--al-motion-easing-exit),
|
|
7739
|
+
display var(--al-motion-duration-feedback) var(--al-motion-easing-exit) allow-discrete;
|
|
7740
|
+
}
|
|
7741
|
+
|
|
7742
|
+
.al-menu__list[hidden] {
|
|
7743
|
+
display: none;
|
|
7744
|
+
opacity: 0;
|
|
7745
|
+
}
|
|
7746
|
+
|
|
7747
|
+
.al-menu__list:not([hidden]) {
|
|
7748
|
+
transition-timing-function: var(--al-motion-easing-enter);
|
|
7749
|
+
}
|
|
7750
|
+
|
|
7751
|
+
@starting-style {
|
|
7752
|
+
.al-menu__list:not([hidden]) {
|
|
7753
|
+
opacity: 0;
|
|
7754
|
+
}
|
|
7755
|
+
}
|
|
7756
|
+
|
|
7757
|
+
/* ------------------------------------------------------------------- item */
|
|
7758
|
+
.al-menu__item {
|
|
7759
|
+
--al-icon-box: var(--al-menu-item-icon-size);
|
|
7760
|
+
|
|
7761
|
+
display: flex;
|
|
7762
|
+
inline-size: 100%;
|
|
7763
|
+
box-sizing: border-box;
|
|
7764
|
+
align-items: center;
|
|
7765
|
+
gap: var(--al-menu-item-gap);
|
|
7766
|
+
margin: 0;
|
|
7767
|
+
padding: var(--al-menu-item-padding-y) var(--al-menu-item-padding-x);
|
|
7768
|
+
border: 0;
|
|
7769
|
+
border-radius: var(--al-menu-item-radius);
|
|
7770
|
+
background-color: transparent;
|
|
7771
|
+
color: var(--al-menu-item-meta);
|
|
7772
|
+
font-family: inherit;
|
|
7773
|
+
font-size: var(--al-menu-font-size);
|
|
7774
|
+
line-height: var(--al-menu-line-height);
|
|
7775
|
+
font-weight: var(--al-menu-font-weight);
|
|
7776
|
+
letter-spacing: var(--al-menu-tracking);
|
|
7777
|
+
text-align: start;
|
|
7778
|
+
cursor: pointer;
|
|
7779
|
+
transition: background-color var(--al-motion-duration-feedback) var(--al-motion-easing-exit);
|
|
7780
|
+
}
|
|
7781
|
+
|
|
7782
|
+
.al-menu__label {
|
|
7783
|
+
flex: 1 1 auto;
|
|
7784
|
+
min-inline-size: 0;
|
|
7785
|
+
overflow: hidden;
|
|
7786
|
+
color: var(--al-menu-item-label);
|
|
7787
|
+
white-space: nowrap;
|
|
7788
|
+
text-overflow: ellipsis;
|
|
7789
|
+
}
|
|
7790
|
+
|
|
7791
|
+
.al-menu__shortcut {
|
|
7792
|
+
flex: none;
|
|
7793
|
+
font: inherit;
|
|
7794
|
+
}
|
|
7795
|
+
|
|
7796
|
+
/* hover and pressed: icon and shortcut darken with the label */
|
|
7797
|
+
.al-menu__item:hover:not(:focus-visible):not([aria-disabled="true"]) {
|
|
7798
|
+
background-color: var(--al-menu-item-bg-hover);
|
|
7799
|
+
color: var(--al-menu-item-meta-hover);
|
|
7800
|
+
transition-timing-function: var(--al-motion-easing-enter);
|
|
7801
|
+
}
|
|
7802
|
+
|
|
7803
|
+
.al-menu__item:active:not([aria-disabled="true"]) {
|
|
7804
|
+
background-color: var(--al-menu-item-bg-active);
|
|
7805
|
+
color: var(--al-menu-item-meta-hover);
|
|
7806
|
+
}
|
|
7807
|
+
|
|
7808
|
+
.al-menu__item:focus-visible {
|
|
7809
|
+
outline: none;
|
|
7810
|
+
box-shadow: inset 0 0 0 var(--al-menu-ring-width) var(--al-menu-ring);
|
|
7811
|
+
}
|
|
7812
|
+
|
|
7813
|
+
/* ----------------------------------------------------------------- danger */
|
|
7814
|
+
.al-menu__item--danger,
|
|
7815
|
+
.al-menu__item--danger .al-menu__label {
|
|
7816
|
+
color: var(--al-menu-danger-label);
|
|
7817
|
+
}
|
|
7818
|
+
|
|
7819
|
+
.al-menu__item--danger:hover:not(:focus-visible):not([aria-disabled="true"]) {
|
|
7820
|
+
background-color: var(--al-menu-danger-bg-hover);
|
|
7821
|
+
color: var(--al-menu-danger-label);
|
|
7822
|
+
}
|
|
7823
|
+
|
|
7824
|
+
.al-menu__item--danger:active:not([aria-disabled="true"]) {
|
|
7825
|
+
background-color: var(--al-menu-danger-bg-active);
|
|
7826
|
+
}
|
|
7827
|
+
|
|
7828
|
+
.al-menu__item--danger:active:not([aria-disabled="true"]),
|
|
7829
|
+
.al-menu__item--danger:active:not([aria-disabled="true"]) .al-menu__label {
|
|
7830
|
+
color: var(--al-menu-danger-label-active);
|
|
7831
|
+
}
|
|
7832
|
+
|
|
7833
|
+
/* --------------------------------------------------------------- disabled */
|
|
7834
|
+
/* Below AA on purpose (WCAG 1.4.3 exempts disabled controls, rule 18). */
|
|
7835
|
+
.al-menu__item[aria-disabled="true"],
|
|
7836
|
+
.al-menu__item[aria-disabled="true"] .al-menu__label {
|
|
7837
|
+
color: var(--al-menu-item-label-disabled);
|
|
7838
|
+
cursor: not-allowed;
|
|
7839
|
+
}
|
|
7840
|
+
|
|
7841
|
+
@media (prefers-reduced-motion: reduce) {
|
|
7842
|
+
.al-menu__list,
|
|
7843
|
+
.al-menu__item {
|
|
7844
|
+
transition: none;
|
|
7845
|
+
}
|
|
7846
|
+
}
|