@timmo001/groundwork-ui 0.7.0 → 0.9.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/custom-elements.json +63 -8
- package/package.json +1 -1
- package/src/gw-button.ts +26 -2
- package/src/gw-chip.ts +20 -1
- package/src/layout.ts +40 -5
- package/src/styles.ts +1 -0
package/custom-elements.json
CHANGED
|
@@ -3103,7 +3103,7 @@
|
|
|
3103
3103
|
"text": "Properties"
|
|
3104
3104
|
},
|
|
3105
3105
|
"static": true,
|
|
3106
|
-
"default": "{ variant: { reflect: true }, appearance: { reflect: true }, size: { reflect: true }, type: {}, href: {}, label: {}, disabled: { type: \"boolean\", reflect: true }, loading: { type: \"boolean\", reflect: true }, icon: {}, labels: { reflect: true }, }",
|
|
3106
|
+
"default": "{ variant: { reflect: true }, appearance: { reflect: true }, size: { reflect: true }, type: {}, href: {}, label: {}, disabled: { type: \"boolean\", reflect: true }, loading: { type: \"boolean\", reflect: true }, icon: {}, swatch: {}, labels: { reflect: true }, }",
|
|
3107
3107
|
"inheritedFrom": {
|
|
3108
3108
|
"name": "GwElement",
|
|
3109
3109
|
"module": "src/element.ts"
|
|
@@ -3130,7 +3130,7 @@
|
|
|
3130
3130
|
"text": "readonly CSSStyleSheet[]"
|
|
3131
3131
|
},
|
|
3132
3132
|
"static": true,
|
|
3133
|
-
"default": "[ base, controlSizes(\"button\"), css` :host { --gw-button-tone: var(--gw-color-accent); display: inline-block; } :host([variant=\"neutral\"]) { --gw-button-tone: var(--gw-color-text-secondary); --gw-button-ink: var(--gw-color-text-strong); } :host([variant=\"info\"]) { --gw-button-tone: var(--gw-color-info); } :host([variant=\"success\"]) { --gw-button-tone: var(--gw-color-success); } :host([variant=\"warning\"]) { --gw-button-tone: var(--gw-color-warning); } :host([variant=\"danger\"]) { --gw-button-tone: var(--gw-color-danger); } .button { --gw-size: var(--gw-button-scale, 1); --gw-scale: calc(var(--gw-size) * var(--gw-control-scale, 1)); --gw-icon-size: calc(1.125rem * var(--gw-scale)); position: relative; display: inline-flex; gap: calc(var(--gw-space-2) * var(--gw-size)); align-items: center; justify-content: center; min-height: calc(2.5rem * var(--gw-scale)); padding: 0 calc(var(--gw-space-4) * var(--gw-size)); font: inherit; font-size: calc(var(--gw-font-size-s) * var(--gw-size)); font-weight: var(--gw-font-weight-strong); line-height: 1; color: var(--gw-button-ink, var(--gw-button-tone)); text-decoration: none; text-transform: var(--gw-label-transform); letter-spacing: var(--gw-label-tracking); white-space: nowrap; cursor: pointer; background: transparent; border: max(var(--gw-border-width), 1px) solid transparent; border-radius: var(--gw-radius-pill); transition: background-color var(--gw-motion-fast) var(--gw-motion-easing), border-color var(--gw-motion-fast) var(--gw-motion-easing), color var(--gw-motion-fast) var(--gw-motion-easing), scale var(--gw-motion-fast) var(--gw-motion-easing); } /* A slight press, so a click feels physical */ .button:active { scale: 0.97; } .button:hover { background: color-mix(in oklch, var(--gw-button-tone) 16%, transparent); } .button:active { background: color-mix(in oklch, var(--gw-button-tone) 24%, transparent); } /* A solid fill, with text that flips between black and white by the fill's lightness so it reads on every theme's colors */ :host([appearance=\"accent\"]) .button { color: oklch( from var(--gw-button-tone) clamp(0, (0.66 - l) * 1000, 1) 0 0 ); background: var(--gw-button-tone); } :host([appearance=\"accent\"]) .button:hover { background: oklch( from var(--gw-button-tone) calc(l + (0.6 - l) * 0.2) c h ); } :host([appearance=\"accent\"]) .button:active { background: oklch( from var(--gw-button-tone) calc(l + (0.6 - l) * 0.35) c h ); } /* The tint lowers the tone's contrast, so the text leans toward the strongest text color to stay readable on it */ :host([appearance=\"filled\"]) .button { color: var( --gw-button-ink, color-mix( in oklch, var(--gw-button-tone) 70%, var(--gw-color-text-strong) ) ); background: color-mix(in oklch, var(--gw-button-tone) 16%, transparent); } :host([appearance=\"filled\"]) .button:hover { background: color-mix(in oklch, var(--gw-button-tone) 24%, transparent); } :host([appearance=\"filled\"]) .button:active { background: color-mix(in oklch, var(--gw-button-tone) 32%, transparent); } :host([appearance=\"outlined\"]) .button { border-color: var(--gw-button-tone); } /* A slotted link carries the text; the pill draws its focus ring */ ::slotted(a) { color: inherit; text-decoration: none; outline: none; } .button.focused { outline: var(--gw-focus-width) solid var(--gw-color-focus); outline-offset: var(--gw-focus-offset); } :host([appearance=\"plain\"]) .button.current, :host([appearance=\"outlined\"]) .button.current { background: color-mix(in oklch, var(--gw-button-tone) 16%, transparent); } :host([appearance=\"filled\"]) .button.current { background: color-mix(in oklch, var(--gw-button-tone) 32%, transparent); } .button:disabled, .button[aria-disabled=\"true\"] { color: var(--gw-color-text-disabled); pointer-events: none; cursor: not-allowed; background: var(--gw-color-fill-neutral-disabled); border-color: transparent; } :host([appearance=\"plain\"]) .button:disabled, :host([appearance=\"plain\"]) .button[aria-disabled=\"true\"] { background: transparent; } ::slotted([slot=\"icon\"]), .icon { flex: none; width: var(--gw-icon-size); height: var(--gw-icon-size); fill: currentColor; } /* The icon and the ring share one cell and crossfade */ .lead { display: grid; place-items: center; } .lead >
|
|
3133
|
+
"default": "[ base, controlSizes(\"button\"), css` :host { --gw-button-tone: var(--gw-color-accent); display: inline-block; } :host([variant=\"neutral\"]) { --gw-button-tone: var(--gw-color-text-secondary); --gw-button-ink: var(--gw-color-text-strong); } :host([variant=\"info\"]) { --gw-button-tone: var(--gw-color-info); } :host([variant=\"success\"]) { --gw-button-tone: var(--gw-color-success); } :host([variant=\"warning\"]) { --gw-button-tone: var(--gw-color-warning); } :host([variant=\"danger\"]) { --gw-button-tone: var(--gw-color-danger); } .button { --gw-size: var(--gw-button-scale, 1); --gw-scale: calc(var(--gw-size) * var(--gw-control-scale, 1)); --gw-icon-size: calc(1.125rem * var(--gw-scale)); position: relative; display: inline-flex; gap: calc(var(--gw-space-2) * var(--gw-size)); align-items: center; justify-content: center; min-height: calc(2.5rem * var(--gw-scale)); padding: 0 calc(var(--gw-space-4) * var(--gw-size)); font: inherit; font-size: calc(var(--gw-font-size-s) * var(--gw-size)); font-weight: var(--gw-font-weight-strong); line-height: 1; color: var(--gw-button-ink, var(--gw-button-tone)); text-decoration: none; text-transform: var(--gw-label-transform); letter-spacing: var(--gw-label-tracking); white-space: nowrap; cursor: pointer; background: transparent; border: max(var(--gw-border-width), 1px) solid transparent; border-radius: var(--gw-radius-pill); transition: background-color var(--gw-motion-fast) var(--gw-motion-easing), border-color var(--gw-motion-fast) var(--gw-motion-easing), color var(--gw-motion-fast) var(--gw-motion-easing), scale var(--gw-motion-fast) var(--gw-motion-easing); } /* A slight press, so a click feels physical */ .button:active { scale: 0.97; } .button:hover { background: color-mix(in oklch, var(--gw-button-tone) 16%, transparent); } .button:active { background: color-mix(in oklch, var(--gw-button-tone) 24%, transparent); } /* A solid fill, with text that flips between black and white by the fill's lightness so it reads on every theme's colors */ :host([appearance=\"accent\"]) .button { color: oklch( from var(--gw-button-tone) clamp(0, (0.66 - l) * 1000, 1) 0 0 ); background: var(--gw-button-tone); } :host([appearance=\"accent\"]) .button:hover { background: oklch( from var(--gw-button-tone) calc(l + (0.6 - l) * 0.2) c h ); } :host([appearance=\"accent\"]) .button:active { background: oklch( from var(--gw-button-tone) calc(l + (0.6 - l) * 0.35) c h ); } /* The tint lowers the tone's contrast, so the text leans toward the strongest text color to stay readable on it */ :host([appearance=\"filled\"]) .button { color: var( --gw-button-ink, color-mix( in oklch, var(--gw-button-tone) 70%, var(--gw-color-text-strong) ) ); background: color-mix(in oklch, var(--gw-button-tone) 16%, transparent); } :host([appearance=\"filled\"]) .button:hover { background: color-mix(in oklch, var(--gw-button-tone) 24%, transparent); } :host([appearance=\"filled\"]) .button:active { background: color-mix(in oklch, var(--gw-button-tone) 32%, transparent); } :host([appearance=\"outlined\"]) .button { border-color: var(--gw-button-tone); } /* A slotted link carries the text; the pill draws its focus ring */ ::slotted(a) { color: inherit; text-decoration: none; outline: none; } .button.focused { outline: var(--gw-focus-width) solid var(--gw-color-focus); outline-offset: var(--gw-focus-offset); } :host([appearance=\"plain\"]) .button.current, :host([appearance=\"outlined\"]) .button.current { background: color-mix(in oklch, var(--gw-button-tone) 16%, transparent); } :host([appearance=\"filled\"]) .button.current { background: color-mix(in oklch, var(--gw-button-tone) 32%, transparent); } .button:disabled, .button[aria-disabled=\"true\"] { color: var(--gw-color-text-disabled); pointer-events: none; cursor: not-allowed; background: var(--gw-color-fill-neutral-disabled); border-color: transparent; } :host([appearance=\"plain\"]) .button:disabled, :host([appearance=\"plain\"]) .button[aria-disabled=\"true\"] { background: transparent; } ::slotted([slot=\"icon\"]), .icon { flex: none; width: var(--gw-icon-size); height: var(--gw-icon-size); fill: currentColor; } /* The icon and the ring share one cell and crossfade */ .lead { display: grid; place-items: center; } /* The icon slot is display: contents, so its slotted icon is a grid item of its own and needs the shared cell too */ .lead > *, ::slotted([slot=\"icon\"]) { grid-area: 1 / 1; } /* A color dot in the icon's place */ .swatch { width: calc(var(--gw-icon-size) * 0.6); height: calc(var(--gw-icon-size) * 0.6); border: 1px solid color-mix(in oklab, var(--gw-color-text-primary) 20%, transparent); border-radius: 50%; } .lead > *, .text, .ring { transition: opacity var(--gw-motion-normal) cubic-bezier(0.4, 0, 0.2, 1); } /* Sized to the icon's drawn area, which is inset in its 24px box */ .ring { width: calc(var(--gw-icon-size) * 0.8); height: calc(var(--gw-icon-size) * 0.8); border: calc(2px * var(--gw-scale)) solid color-mix(in oklch, currentColor 25%, transparent); border-top-color: currentColor; border-radius: 50%; opacity: 0; animation: spin 0.9s linear infinite; } @keyframes spin { to { transform: rotate(360deg); } } /* Without an icon, the ring sits over the hidden text */ .ring.over { position: absolute; inset: 0; margin: auto; } :host([loading]) .button { cursor: progress; } :host([loading]) .lead > .ring, :host([loading]) .button:not(.has-icon) > .ring.over { opacity: 1; } :host([loading]) .lead > :not(.ring), :host([loading]) .button:not(.has-icon) > .text { opacity: 0; } .button:not(.has-icon) > .lead { display: none; } /* Icon only, to save space: square, with the text kept for assistive technology. auto does this on narrow screens */ :host([labels=\"hide\"]) .button.has-icon { min-width: calc(2.5rem * var(--gw-scale)); padding: 0; } :host([labels=\"hide\"]) .has-icon .text { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; } @media (width < 40rem) { :host([labels=\"auto\"]) .button.has-icon { min-width: calc(2.5rem * var(--gw-scale)); padding: 0; } :host([labels=\"auto\"]) .has-icon .text { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; } } `, ]",
|
|
3134
3134
|
"inheritedFrom": {
|
|
3135
3135
|
"name": "GwElement",
|
|
3136
3136
|
"module": "src/element.ts"
|
|
@@ -3210,6 +3210,15 @@
|
|
|
3210
3210
|
"description": "SVG path data for an icon before the text.",
|
|
3211
3211
|
"default": "\"\""
|
|
3212
3212
|
},
|
|
3213
|
+
{
|
|
3214
|
+
"kind": "field",
|
|
3215
|
+
"name": "swatch",
|
|
3216
|
+
"type": {
|
|
3217
|
+
"text": "string"
|
|
3218
|
+
},
|
|
3219
|
+
"description": "A CSS color, drawn as a small round dot in the icon's place.",
|
|
3220
|
+
"default": "\"\""
|
|
3221
|
+
},
|
|
3213
3222
|
{
|
|
3214
3223
|
"kind": "field",
|
|
3215
3224
|
"name": "labels",
|
|
@@ -3231,6 +3240,12 @@
|
|
|
3231
3240
|
"privacy": "private",
|
|
3232
3241
|
"readonly": true
|
|
3233
3242
|
},
|
|
3243
|
+
{
|
|
3244
|
+
"kind": "field",
|
|
3245
|
+
"name": "#swatch",
|
|
3246
|
+
"privacy": "private",
|
|
3247
|
+
"readonly": true
|
|
3248
|
+
},
|
|
3234
3249
|
{
|
|
3235
3250
|
"kind": "field",
|
|
3236
3251
|
"name": "#lead",
|
|
@@ -3630,6 +3645,13 @@
|
|
|
3630
3645
|
"description": "SVG path data for an icon before the text.",
|
|
3631
3646
|
"name": "icon"
|
|
3632
3647
|
},
|
|
3648
|
+
{
|
|
3649
|
+
"type": {
|
|
3650
|
+
"text": "string"
|
|
3651
|
+
},
|
|
3652
|
+
"description": "A CSS color, drawn as a small round dot in the icon's place, such as a tag's own color.",
|
|
3653
|
+
"name": "swatch"
|
|
3654
|
+
},
|
|
3633
3655
|
{
|
|
3634
3656
|
"type": {
|
|
3635
3657
|
"text": "\"show\"|\"hide\"|\"auto\""
|
|
@@ -5344,7 +5366,7 @@
|
|
|
5344
5366
|
"text": "Properties"
|
|
5345
5367
|
},
|
|
5346
5368
|
"static": true,
|
|
5347
|
-
"default": "{ tone: { reflect: true }, icon: {}, loading: { type: \"boolean\", reflect: true }, size: { reflect: true }, }",
|
|
5369
|
+
"default": "{ tone: { reflect: true }, icon: {}, swatch: {}, loading: { type: \"boolean\", reflect: true }, size: { reflect: true }, }",
|
|
5348
5370
|
"inheritedFrom": {
|
|
5349
5371
|
"name": "GwElement",
|
|
5350
5372
|
"module": "src/element.ts"
|
|
@@ -5357,7 +5379,7 @@
|
|
|
5357
5379
|
"text": "readonly CSSStyleSheet[]"
|
|
5358
5380
|
},
|
|
5359
5381
|
"static": true,
|
|
5360
|
-
"default": "[ base, controlSizes(\"chip\"), css` :host { display: inline-flex; } /* 32px at medium, with 12px padding */ .chip { --gw-size: var(--gw-chip-scale, 1); --gw-scale: calc(var(--gw-size) * var(--gw-control-scale, 1)); --gw-icon-size: calc(1rem * var(--gw-scale)); display: inline-flex; gap: calc(var(--gw-space-2) * var(--gw-size)); align-items: center; box-sizing: border-box; height: calc(2rem * var(--gw-scale)); padding: 0 calc(var(--gw-space-3) * var(--gw-size)); font-size: max( var(--gw-font-size-2xs), calc(var(--gw-font-size-xs) * var(--gw-size)) ); font-weight: var(--gw-font-weight-strong); color: var(--gw-color-text-strong); background: var(--gw-tone-fill, var(--gw-color-fill-neutral-resting)); border: var(--gw-border-width) solid var(--gw-tone-border, var(--gw-color-border-quiet)); border-radius: var(--gw-radius-chip); } .content { display: inline-flex; gap: inherit; align-items: center; } `, ]",
|
|
5382
|
+
"default": "[ base, controlSizes(\"chip\"), css` :host { display: inline-flex; } /* 32px at medium, with 12px padding */ .chip { --gw-size: var(--gw-chip-scale, 1); --gw-scale: calc(var(--gw-size) * var(--gw-control-scale, 1)); --gw-icon-size: calc(1rem * var(--gw-scale)); display: inline-flex; gap: calc(var(--gw-space-2) * var(--gw-size)); align-items: center; box-sizing: border-box; height: calc(2rem * var(--gw-scale)); padding: 0 calc(var(--gw-space-3) * var(--gw-size)); font-size: max( var(--gw-font-size-2xs), calc(var(--gw-font-size-xs) * var(--gw-size)) ); font-weight: var(--gw-font-weight-strong); color: var(--gw-color-text-strong); background: var(--gw-tone-fill, var(--gw-color-fill-neutral-resting)); border: var(--gw-border-width) solid var(--gw-tone-border, var(--gw-color-border-quiet)); border-radius: var(--gw-radius-chip); } .content { display: inline-flex; gap: inherit; align-items: center; } /* A color dot in the icon's place */ .swatch { flex: none; width: calc(var(--gw-icon-size) * 0.6); height: calc(var(--gw-icon-size) * 0.6); border: 1px solid color-mix(in oklab, var(--gw-color-text-primary) 20%, transparent); border-radius: 50%; } `, ]",
|
|
5361
5383
|
"inheritedFrom": {
|
|
5362
5384
|
"name": "GwElement",
|
|
5363
5385
|
"module": "src/element.ts"
|
|
@@ -5380,6 +5402,15 @@
|
|
|
5380
5402
|
"description": "SVG path data for an icon before the text, instead of the `icon` slot.",
|
|
5381
5403
|
"default": "\"\""
|
|
5382
5404
|
},
|
|
5405
|
+
{
|
|
5406
|
+
"kind": "field",
|
|
5407
|
+
"name": "swatch",
|
|
5408
|
+
"type": {
|
|
5409
|
+
"text": "string"
|
|
5410
|
+
},
|
|
5411
|
+
"description": "A CSS color, drawn as a small round dot in the icon's place.",
|
|
5412
|
+
"default": "\"\""
|
|
5413
|
+
},
|
|
5383
5414
|
{
|
|
5384
5415
|
"kind": "field",
|
|
5385
5416
|
"name": "loading",
|
|
@@ -5402,6 +5433,12 @@
|
|
|
5402
5433
|
"privacy": "private",
|
|
5403
5434
|
"readonly": true
|
|
5404
5435
|
},
|
|
5436
|
+
{
|
|
5437
|
+
"kind": "field",
|
|
5438
|
+
"name": "#swatch",
|
|
5439
|
+
"privacy": "private",
|
|
5440
|
+
"readonly": true
|
|
5441
|
+
},
|
|
5405
5442
|
{
|
|
5406
5443
|
"kind": "field",
|
|
5407
5444
|
"name": "#chip",
|
|
@@ -5747,6 +5784,13 @@
|
|
|
5747
5784
|
"description": "SVG path data for an icon before the text.",
|
|
5748
5785
|
"name": "icon"
|
|
5749
5786
|
},
|
|
5787
|
+
{
|
|
5788
|
+
"type": {
|
|
5789
|
+
"text": "string"
|
|
5790
|
+
},
|
|
5791
|
+
"description": "A CSS color, drawn as a small round dot in the icon's place, such as a tag's own color.",
|
|
5792
|
+
"name": "swatch"
|
|
5793
|
+
},
|
|
5750
5794
|
{
|
|
5751
5795
|
"type": {
|
|
5752
5796
|
"text": "boolean"
|
|
@@ -20249,7 +20293,7 @@
|
|
|
20249
20293
|
"text": "readonly CSSStyleSheet[]"
|
|
20250
20294
|
},
|
|
20251
20295
|
"static": true,
|
|
20252
|
-
"default": "[ base, css` :host { display: block; } .page { display: flex; flex-direction: column; gap: var(--gw-space-6); width: 100
|
|
20296
|
+
"default": "[ base, css` :host { display: block; } .page { display: flex; flex-direction: column; gap: var(--gw-space-6); /* The same box as gw-app-bar's content, so the two line up */ width: min(100% - 2 * var(--gw-space-3), var(--gw-content-width)); margin-inline: auto; } :host([narrow]) .page { width: min( 100% - 2 * var(--gw-space-3), var(--gw-content-width-narrow) ); } `, ]",
|
|
20253
20297
|
"inheritedFrom": {
|
|
20254
20298
|
"name": "GwElement",
|
|
20255
20299
|
"module": "src/element.ts"
|
|
@@ -21345,13 +21389,17 @@
|
|
|
21345
21389
|
},
|
|
21346
21390
|
{
|
|
21347
21391
|
"kind": "class",
|
|
21348
|
-
"description": "Fills as many columns as fit, each at least `--gw-grid-min` wide.",
|
|
21392
|
+
"description": "Fills as many columns as fit, each at least `--gw-grid-min` wide, and at\nmost `max` of them when it's set.",
|
|
21349
21393
|
"name": "GwGrid",
|
|
21350
21394
|
"cssProperties": [
|
|
21351
21395
|
{
|
|
21352
21396
|
"description": "The narrowest a column gets. Defaults to `18rem`.",
|
|
21353
21397
|
"name": "--gw-grid-min"
|
|
21354
21398
|
},
|
|
21399
|
+
{
|
|
21400
|
+
"description": "The most columns it shows, as a number. Unset by default, so as many fit as the width allows.",
|
|
21401
|
+
"name": "--gw-grid-max"
|
|
21402
|
+
},
|
|
21355
21403
|
{
|
|
21356
21404
|
"description": "The gap. Defaults to `--gw-space-3`.",
|
|
21357
21405
|
"name": "--gw-gap"
|
|
@@ -21371,7 +21419,7 @@
|
|
|
21371
21419
|
"text": "readonly CSSStyleSheet[]"
|
|
21372
21420
|
},
|
|
21373
21421
|
"static": true,
|
|
21374
|
-
"default": "[ base, gaps, css` :host { display: grid; grid-template-columns: repeat( auto-fill, minmax(min(100%, var(--gw-grid-min, 18rem)), 1fr) ); gap: var(--gw-gap, var(--gw-space-3)); } `, ]",
|
|
21422
|
+
"default": "[ base, gaps, css` :host { /* A column's width at the cap. Invalid while --gw-grid-max is unset, so the var() below falls back to 0px and the cap does nothing */ --_gw-grid-cap: calc( (100% - (var(--gw-grid-max) - 1) * var(--gw-gap, var(--gw-space-3))) / var(--gw-grid-max) ); display: grid; grid-template-columns: repeat( auto-fill, minmax( min(100%, max(var(--gw-grid-min, 18rem), var(--_gw-grid-cap, 0px))), 1fr ) ); gap: var(--gw-gap, var(--gw-space-3)); } :host([max=\"2\"]) { --gw-grid-max: 2; } :host([max=\"3\"]) { --gw-grid-max: 3; } :host([max=\"4\"]) { --gw-grid-max: 4; } :host([max=\"5\"]) { --gw-grid-max: 5; } :host([max=\"6\"]) { --gw-grid-max: 6; } `, ]",
|
|
21375
21423
|
"inheritedFrom": {
|
|
21376
21424
|
"name": "GwElement",
|
|
21377
21425
|
"module": "src/element.ts"
|
|
@@ -21709,6 +21757,13 @@
|
|
|
21709
21757
|
},
|
|
21710
21758
|
"description": "A smaller or larger gap.",
|
|
21711
21759
|
"name": "gap"
|
|
21760
|
+
},
|
|
21761
|
+
{
|
|
21762
|
+
"type": {
|
|
21763
|
+
"text": "\"2\"|\"3\"|\"4\"|\"5\"|\"6\""
|
|
21764
|
+
},
|
|
21765
|
+
"description": "The most columns it shows. Sets `--gw-grid-max`.",
|
|
21766
|
+
"name": "max"
|
|
21712
21767
|
}
|
|
21713
21768
|
],
|
|
21714
21769
|
"superclass": {
|
|
@@ -21988,7 +22043,7 @@
|
|
|
21988
22043
|
{
|
|
21989
22044
|
"kind": "variable",
|
|
21990
22045
|
"name": "base",
|
|
21991
|
-
"default": "css` :host { font-family: var(--gw-font-sans); color: var(--gw-color-text-primary); } *, *::before, *::after { box-sizing: border-box; } [hidden] { display: none !important; } :focus-visible { outline: var(--gw-focus-width) solid var(--gw-color-focus); outline-offset: var(--gw-focus-offset); } .icon { flex: none; width: var(--gw-icon-size, 1.25rem); height: var(--gw-icon-size, 1.25rem); fill: currentColor; } :host([tone=\"accent\"]) { --gw-tone: var(--gw-color-accent); --gw-tone-fill: var(--gw-color-fill-accent-quiet); --gw-tone-border: var(--gw-color-border-accent); } :host([tone=\"info\"]) { --gw-tone: var(--gw-color-info); --gw-tone-fill: var(--gw-color-fill-info-quiet); --gw-tone-border: var(--gw-color-border-info); } :host([tone=\"success\"]) { --gw-tone: var(--gw-color-success); --gw-tone-fill: var(--gw-color-fill-success-quiet); --gw-tone-border: var(--gw-color-border-success); } :host([tone=\"warning\"]) { --gw-tone: var(--gw-color-warning); --gw-tone-fill: var(--gw-color-fill-warning-quiet); --gw-tone-border: var(--gw-color-border-warning); } :host([tone=\"danger\"]) { --gw-tone: var(--gw-color-danger); --gw-tone-fill: var(--gw-color-fill-danger-quiet); --gw-tone-border: var(--gw-color-border-danger); } :host([tone=\"important\"]) { --gw-tone: var(--gw-color-important); --gw-tone-fill: var(--gw-color-fill-important-quiet); --gw-tone-border: var(--gw-color-border-important); } @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0s !important; transition-duration: 0s !important; } } `",
|
|
22046
|
+
"default": "css` :host { font-family: var(--gw-font-sans); color: var(--gw-color-text-primary); } *, *::before, *::after { box-sizing: border-box; } :host([hidden]), [hidden] { display: none !important; } :focus-visible { outline: var(--gw-focus-width) solid var(--gw-color-focus); outline-offset: var(--gw-focus-offset); } .icon { flex: none; width: var(--gw-icon-size, 1.25rem); height: var(--gw-icon-size, 1.25rem); fill: currentColor; } :host([tone=\"accent\"]) { --gw-tone: var(--gw-color-accent); --gw-tone-fill: var(--gw-color-fill-accent-quiet); --gw-tone-border: var(--gw-color-border-accent); } :host([tone=\"info\"]) { --gw-tone: var(--gw-color-info); --gw-tone-fill: var(--gw-color-fill-info-quiet); --gw-tone-border: var(--gw-color-border-info); } :host([tone=\"success\"]) { --gw-tone: var(--gw-color-success); --gw-tone-fill: var(--gw-color-fill-success-quiet); --gw-tone-border: var(--gw-color-border-success); } :host([tone=\"warning\"]) { --gw-tone: var(--gw-color-warning); --gw-tone-fill: var(--gw-color-fill-warning-quiet); --gw-tone-border: var(--gw-color-border-warning); } :host([tone=\"danger\"]) { --gw-tone: var(--gw-color-danger); --gw-tone-fill: var(--gw-color-fill-danger-quiet); --gw-tone-border: var(--gw-color-border-danger); } :host([tone=\"important\"]) { --gw-tone: var(--gw-color-important); --gw-tone-fill: var(--gw-color-fill-important-quiet); --gw-tone-border: var(--gw-color-border-important); } @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0s !important; transition-duration: 0s !important; } } `",
|
|
21992
22047
|
"description": "What every component shares: box sizing, the focus ring, icons and the\ntones that set `--gw-tone` from a `tone` attribute."
|
|
21993
22048
|
},
|
|
21994
22049
|
{
|
package/package.json
CHANGED
package/src/gw-button.ts
CHANGED
|
@@ -38,6 +38,7 @@ import { base, controlSizes, createIcon, setIconPath } from "./styles.js";
|
|
|
38
38
|
* @attr {boolean} disabled - Disables the button.
|
|
39
39
|
* @attr {boolean} loading - Shows a spinning ring in the icon's place and ignores clicks.
|
|
40
40
|
* @attr {string} icon - SVG path data for an icon before the text.
|
|
41
|
+
* @attr {string} swatch - A CSS color, drawn as a small round dot in the icon's place, such as a tag's own color.
|
|
41
42
|
* @attr {"show"|"hide"|"auto"} labels - Whether the text shows beside an icon: always, never, or not on narrow screens. Defaults to `show`.
|
|
42
43
|
*
|
|
43
44
|
* @slot - The text, or an `<a>` holding it, in place of `href`.
|
|
@@ -61,6 +62,7 @@ export class GwButton extends GwElement {
|
|
|
61
62
|
disabled: { type: "boolean", reflect: true },
|
|
62
63
|
loading: { type: "boolean", reflect: true },
|
|
63
64
|
icon: {},
|
|
65
|
+
swatch: {},
|
|
64
66
|
labels: { reflect: true },
|
|
65
67
|
} as const;
|
|
66
68
|
|
|
@@ -242,10 +244,22 @@ export class GwButton extends GwElement {
|
|
|
242
244
|
place-items: center;
|
|
243
245
|
}
|
|
244
246
|
|
|
245
|
-
|
|
247
|
+
/* The icon slot is display: contents, so its slotted icon is a grid
|
|
248
|
+
item of its own and needs the shared cell too */
|
|
249
|
+
.lead > *,
|
|
250
|
+
::slotted([slot="icon"]) {
|
|
246
251
|
grid-area: 1 / 1;
|
|
247
252
|
}
|
|
248
253
|
|
|
254
|
+
/* A color dot in the icon's place */
|
|
255
|
+
.swatch {
|
|
256
|
+
width: calc(var(--gw-icon-size) * 0.6);
|
|
257
|
+
height: calc(var(--gw-icon-size) * 0.6);
|
|
258
|
+
border: 1px solid
|
|
259
|
+
color-mix(in oklab, var(--gw-color-text-primary) 20%, transparent);
|
|
260
|
+
border-radius: 50%;
|
|
261
|
+
}
|
|
262
|
+
|
|
249
263
|
.lead > *,
|
|
250
264
|
.text,
|
|
251
265
|
.ring {
|
|
@@ -341,6 +355,8 @@ export class GwButton extends GwElement {
|
|
|
341
355
|
declare loading: boolean;
|
|
342
356
|
/** SVG path data for an icon before the text. */
|
|
343
357
|
declare icon: string;
|
|
358
|
+
/** A CSS color, drawn as a small round dot in the icon's place. */
|
|
359
|
+
declare swatch: string;
|
|
344
360
|
/** Whether the text shows beside an icon: always, never, or not on narrow screens. */
|
|
345
361
|
declare labels: "show" | "hide" | "auto";
|
|
346
362
|
|
|
@@ -348,10 +364,13 @@ export class GwButton extends GwElement {
|
|
|
348
364
|
|
|
349
365
|
readonly #iconSlot = h("slot", { name: "icon" });
|
|
350
366
|
|
|
367
|
+
readonly #swatch = h("span", { class: "swatch", "aria-hidden": "true" });
|
|
368
|
+
|
|
351
369
|
readonly #lead = h(
|
|
352
370
|
"span",
|
|
353
371
|
{ class: "lead" },
|
|
354
372
|
this.#icon,
|
|
373
|
+
this.#swatch,
|
|
355
374
|
this.#iconSlot,
|
|
356
375
|
h("span", { class: "ring" }),
|
|
357
376
|
);
|
|
@@ -376,6 +395,7 @@ export class GwButton extends GwElement {
|
|
|
376
395
|
constructor() {
|
|
377
396
|
super();
|
|
378
397
|
this.icon = "";
|
|
398
|
+
this.swatch = "";
|
|
379
399
|
this.labels = "show";
|
|
380
400
|
this.variant = "brand";
|
|
381
401
|
this.appearance = "accent";
|
|
@@ -456,7 +476,9 @@ export class GwButton extends GwElement {
|
|
|
456
476
|
const control = this.#control;
|
|
457
477
|
|
|
458
478
|
const hasIcon =
|
|
459
|
-
this.icon !== "" ||
|
|
479
|
+
this.icon !== "" ||
|
|
480
|
+
this.swatch !== "" ||
|
|
481
|
+
this.querySelector("[slot='icon']") !== null;
|
|
460
482
|
|
|
461
483
|
control.classList.toggle("has-icon", hasIcon);
|
|
462
484
|
control.classList.toggle(
|
|
@@ -466,6 +488,8 @@ export class GwButton extends GwElement {
|
|
|
466
488
|
);
|
|
467
489
|
setIconPath(this.#icon, this.icon);
|
|
468
490
|
this.#icon.style.display = this.icon ? "" : "none";
|
|
491
|
+
this.#swatch.style.background = this.swatch;
|
|
492
|
+
this.#swatch.hidden = this.swatch === "" || this.icon !== "";
|
|
469
493
|
setAttribute(
|
|
470
494
|
control,
|
|
471
495
|
"title",
|
package/src/gw-chip.ts
CHANGED
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
*
|
|
25
25
|
* @attr {"neutral"|"accent"|"info"|"success"|"warning"|"danger"|"important"} tone - The tint. Defaults to `neutral`.
|
|
26
26
|
* @attr {string} icon - SVG path data for an icon before the text.
|
|
27
|
+
* @attr {string} swatch - A CSS color, drawn as a small round dot in the icon's place, such as a tag's own color.
|
|
27
28
|
* @attr {boolean} loading - Shows a skeleton for the text.
|
|
28
29
|
* @attr {"xs"|"small"|"medium"|"large"|"xl"} size - The size, around 32px tall at medium. Defaults to `medium`.
|
|
29
30
|
*
|
|
@@ -41,6 +42,7 @@ export class GwChip extends GwElement {
|
|
|
41
42
|
static override properties = {
|
|
42
43
|
tone: { reflect: true },
|
|
43
44
|
icon: {},
|
|
45
|
+
swatch: {},
|
|
44
46
|
loading: { type: "boolean", reflect: true },
|
|
45
47
|
size: { reflect: true },
|
|
46
48
|
} as const;
|
|
@@ -82,17 +84,31 @@ export class GwChip extends GwElement {
|
|
|
82
84
|
gap: inherit;
|
|
83
85
|
align-items: center;
|
|
84
86
|
}
|
|
87
|
+
|
|
88
|
+
/* A color dot in the icon's place */
|
|
89
|
+
.swatch {
|
|
90
|
+
flex: none;
|
|
91
|
+
width: calc(var(--gw-icon-size) * 0.6);
|
|
92
|
+
height: calc(var(--gw-icon-size) * 0.6);
|
|
93
|
+
border: 1px solid
|
|
94
|
+
color-mix(in oklab, var(--gw-color-text-primary) 20%, transparent);
|
|
95
|
+
border-radius: 50%;
|
|
96
|
+
}
|
|
85
97
|
`,
|
|
86
98
|
];
|
|
87
99
|
|
|
88
100
|
declare tone: Tone;
|
|
89
101
|
/** SVG path data for an icon before the text, instead of the `icon` slot. */
|
|
90
102
|
declare icon: string;
|
|
103
|
+
/** A CSS color, drawn as a small round dot in the icon's place. */
|
|
104
|
+
declare swatch: string;
|
|
91
105
|
declare loading: boolean;
|
|
92
106
|
declare size: "xs" | "small" | "medium" | "large" | "xl";
|
|
93
107
|
|
|
94
108
|
readonly #icon = createIcon("");
|
|
95
109
|
|
|
110
|
+
readonly #swatch = h("span", { class: "swatch", "aria-hidden": "true" });
|
|
111
|
+
|
|
96
112
|
readonly #chip = h("span", { class: "chip", part: "chip" });
|
|
97
113
|
|
|
98
114
|
readonly #skeleton = h("gw-skeleton-text", {
|
|
@@ -102,7 +118,7 @@ export class GwChip extends GwElement {
|
|
|
102
118
|
readonly #content = h(
|
|
103
119
|
"span",
|
|
104
120
|
{ class: "content" },
|
|
105
|
-
h("slot", { name: "icon" }, this.#icon),
|
|
121
|
+
h("slot", { name: "icon" }, this.#icon, this.#swatch),
|
|
106
122
|
h("slot"),
|
|
107
123
|
);
|
|
108
124
|
|
|
@@ -110,6 +126,7 @@ export class GwChip extends GwElement {
|
|
|
110
126
|
super();
|
|
111
127
|
this.tone = "neutral";
|
|
112
128
|
this.icon = "";
|
|
129
|
+
this.swatch = "";
|
|
113
130
|
this.loading = false;
|
|
114
131
|
this.size = "medium";
|
|
115
132
|
}
|
|
@@ -124,6 +141,8 @@ export class GwChip extends GwElement {
|
|
|
124
141
|
|
|
125
142
|
setIconPath(this.#icon, this.icon);
|
|
126
143
|
this.#icon.toggleAttribute("hidden", !this.icon);
|
|
144
|
+
this.#swatch.style.background = this.swatch;
|
|
145
|
+
this.#swatch.hidden = this.swatch === "" || this.icon !== "";
|
|
127
146
|
|
|
128
147
|
setAttribute(this.#chip, "aria-busy", this.loading ? "true" : null);
|
|
129
148
|
this.#skeleton.hidden = !this.loading;
|
package/src/layout.ts
CHANGED
|
@@ -36,13 +36,16 @@ export class GwPage extends GwElement {
|
|
|
36
36
|
display: flex;
|
|
37
37
|
flex-direction: column;
|
|
38
38
|
gap: var(--gw-space-6);
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
/* The same box as gw-app-bar's content, so the two line up */
|
|
40
|
+
width: min(100% - 2 * var(--gw-space-3), var(--gw-content-width));
|
|
41
41
|
margin-inline: auto;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
:host([narrow]) .page {
|
|
45
|
-
|
|
45
|
+
width: min(
|
|
46
|
+
100% - 2 * var(--gw-space-3),
|
|
47
|
+
var(--gw-content-width-narrow)
|
|
48
|
+
);
|
|
46
49
|
}
|
|
47
50
|
`,
|
|
48
51
|
];
|
|
@@ -135,16 +138,19 @@ export class GwRow extends GwSlotted {
|
|
|
135
138
|
}
|
|
136
139
|
|
|
137
140
|
/**
|
|
138
|
-
* Fills as many columns as fit, each at least `--gw-grid-min` wide
|
|
141
|
+
* Fills as many columns as fit, each at least `--gw-grid-min` wide, and at
|
|
142
|
+
* most `max` of them when it's set.
|
|
139
143
|
*
|
|
140
144
|
* @element gw-grid
|
|
141
145
|
* @summary Children in responsive columns.
|
|
142
146
|
*
|
|
143
147
|
* @attr {"s"|"l"} gap - A smaller or larger gap.
|
|
148
|
+
* @attr {"2"|"3"|"4"|"5"|"6"} max - The most columns it shows. Sets `--gw-grid-max`.
|
|
144
149
|
*
|
|
145
150
|
* @slot - The children.
|
|
146
151
|
*
|
|
147
152
|
* @cssprop --gw-grid-min - The narrowest a column gets. Defaults to `18rem`.
|
|
153
|
+
* @cssprop --gw-grid-max - The most columns it shows, as a number. Unset by default, so as many fit as the width allows.
|
|
148
154
|
* @cssprop --gw-gap - The gap. Defaults to `--gw-space-3`.
|
|
149
155
|
*/
|
|
150
156
|
export class GwGrid extends GwSlotted {
|
|
@@ -153,13 +159,42 @@ export class GwGrid extends GwSlotted {
|
|
|
153
159
|
gaps,
|
|
154
160
|
css`
|
|
155
161
|
:host {
|
|
162
|
+
/* A column's width at the cap. Invalid while --gw-grid-max is unset,
|
|
163
|
+
so the var() below falls back to 0px and the cap does nothing */
|
|
164
|
+
--_gw-grid-cap: calc(
|
|
165
|
+
(100% - (var(--gw-grid-max) - 1) * var(--gw-gap, var(--gw-space-3))) /
|
|
166
|
+
var(--gw-grid-max)
|
|
167
|
+
);
|
|
156
168
|
display: grid;
|
|
157
169
|
grid-template-columns: repeat(
|
|
158
170
|
auto-fill,
|
|
159
|
-
minmax(
|
|
171
|
+
minmax(
|
|
172
|
+
min(100%, max(var(--gw-grid-min, 18rem), var(--_gw-grid-cap, 0px))),
|
|
173
|
+
1fr
|
|
174
|
+
)
|
|
160
175
|
);
|
|
161
176
|
gap: var(--gw-gap, var(--gw-space-3));
|
|
162
177
|
}
|
|
178
|
+
|
|
179
|
+
:host([max="2"]) {
|
|
180
|
+
--gw-grid-max: 2;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
:host([max="3"]) {
|
|
184
|
+
--gw-grid-max: 3;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
:host([max="4"]) {
|
|
188
|
+
--gw-grid-max: 4;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
:host([max="5"]) {
|
|
192
|
+
--gw-grid-max: 5;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
:host([max="6"]) {
|
|
196
|
+
--gw-grid-max: 6;
|
|
197
|
+
}
|
|
163
198
|
`,
|
|
164
199
|
];
|
|
165
200
|
}
|