@timmo001/groundwork-ui 0.9.29 → 0.9.30
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 +45 -7
- package/package.json +1 -1
- package/src/fields.ts +3 -0
- package/src/gw-alert.ts +1 -1
- package/src/gw-card.ts +45 -7
- package/src/gw-command-menu.ts +6 -0
- package/src/gw-notification.ts +1 -1
- package/src/gw-option-list.ts +3 -1
- package/src/gw-theme-picker.ts +9 -0
- package/src/gw-toast.ts +1 -1
package/custom-elements.json
CHANGED
|
@@ -660,7 +660,7 @@
|
|
|
660
660
|
{
|
|
661
661
|
"kind": "variable",
|
|
662
662
|
"name": "fieldStyles",
|
|
663
|
-
"default": "css` :where(gw-input, gw-select, gw-switch, gw-checkbox) { display: flex; flex-direction: column; gap: var(--gw-space-2); font-family: var(--gw-font-sans); color: var(--gw-color-text-primary); } :where(gw-input, gw-select) .gw-field-heading { display: flex; gap: var(--gw-space-1); align-items: center; } :where(gw-input, gw-select) .gw-field-heading > label { font-size: var(--gw-font-size-s); font-weight: var(--gw-font-weight-strong); color: var(--gw-color-text-strong); } /* The (i) button by the label that opens a field's longer help */ :where(gw-input, gw-select) .gw-info { display: inline-grid; place-items: center; width: 1.5rem; height: 1.5rem; padding: 0; color: var(--gw-color-text-secondary); cursor: pointer; background: none; border: 0; border-radius: var(--gw-radius-pill); transition: color var(--gw-motion-fast) var(--gw-motion-easing), background-color var(--gw-motion-fast) var(--gw-motion-easing); } :where(gw-input, gw-select) .gw-info:hover { color: var(--gw-color-text-strong); background: var(--gw-color-fill-neutral-hovered); } :where(gw-input, gw-select) .gw-info:focus-visible { outline: var(--gw-focus-width) solid var(--gw-color-focus); outline-offset: var(--gw-focus-offset); } :where(gw-input, gw-select) .gw-info[hidden] { display: none; } :where(gw-input, gw-select) .gw-info > .icon { width: 1rem; height: 1rem; fill: currentColor; } /* Sizes run xs to xl through --gw-field-scale, around 1 for medium, and the control's height follows the theme's density too */ :where(gw-input, gw-select)[size=\"xs\"] { --gw-field-scale: 0.6; } :where(gw-input, gw-select)[size=\"small\"] { --gw-field-scale: 0.8; } :where(gw-input, gw-select)[size=\"large\"] { --gw-field-scale: 1.2; } :where(gw-input, gw-select)[size=\"xl\"] { --gw-field-scale: 1.4; } :where(gw-input, gw-select) :where(input, textarea, .gw-select-trigger) { --gw-field-size: var(--gw-field-scale, 1); --gw-icon-size: calc( 1.25rem * var(--gw-field-size) * var(--gw-control-scale, 1) ); width: 100%; min-height: calc( 2.5rem * var(--gw-field-size) * var(--gw-control-scale, 1) ); padding: 0 calc(var(--gw-space-3) * var(--gw-field-size)); font: inherit; font-size: calc(var(--gw-font-size-s) * var(--gw-field-size)); color: var(--gw-color-text-strong); background: var(--gw-color-surface-lower); border: var(--gw-border-width) solid var(--gw-color-border-normal); border-radius: var(--gw-radius-control); transition: border-color var(--gw-motion-fast) var(--gw-motion-easing); } /* An icon inside the field, before the text, with the text moved clear of it */ gw-input .gw-input-control { position: relative; display: flex; align-items: center; } gw-input .gw-input-control > .icon { position: absolute; inset-inline-start: calc(var(--gw-space-3) * var(--gw-field-scale, 1)); width: calc(1.125rem * var(--gw-field-scale, 1)); height: calc(1.125rem * var(--gw-field-scale, 1)); color: var(--gw-color-text-secondary); pointer-events: none; fill: currentColor; } gw-input .gw-input-control > .icon[hidden] { display: none; } gw-input .gw-input-control > .icon:not([hidden]) + input { padding-inline-start: calc( (var(--gw-space-3) * 2 + 1.125rem) * var(--gw-field-scale, 1) ); } /* A textarea keeps the field's padding on every side and grows by its corner, never sideways out of the layout */ gw-input textarea { display: block; padding-block: calc(var(--gw-space-2) * var(--gw-field-size)); line-height: 1.5; resize: vertical; } gw-input[monospace] :where(input, textarea) { font-family: var(--gw-font-mono); } gw-input .gw-optional { font-weight: var(--gw-font-weight-regular); color: var(--gw-color-text-secondary); } gw-input .gw-optional[hidden] { display: none; } /* The show and hide button sits inside the end of a password field, with the text kept clear of it */ gw-input .gw-reveal { position: absolute; inset-inline-end: calc(var(--gw-space-1) * var(--gw-field-scale, 1)); display: grid; place-items: center; width: calc(2rem * var(--gw-field-scale, 1)); height: calc(2rem * var(--gw-field-scale, 1)); padding: 0; color: var(--gw-color-text-secondary); cursor: pointer; background: none; border: 0; border-radius: var(--gw-radius-control); transition: color var(--gw-motion-fast) var(--gw-motion-easing), background-color var(--gw-motion-fast) var(--gw-motion-easing); } gw-input .gw-reveal:hover:not(:disabled) { color: var(--gw-color-text-strong); background: var(--gw-color-fill-neutral-hovered); } gw-input .gw-reveal:focus-visible { outline: var(--gw-focus-width) solid var(--gw-color-focus); outline-offset: calc(var(--gw-focus-width) * -1); } gw-input .gw-reveal:disabled { cursor: not-allowed; opacity: 0.5; } gw-input .gw-reveal[hidden] { display: none; } gw-input .gw-reveal > .icon { width: calc(1.125rem * var(--gw-field-scale, 1)); height: calc(1.125rem * var(--gw-field-scale, 1)); fill: currentColor; } gw-input .gw-input-control:has(> .gw-reveal:not([hidden])) > input { padding-inline-end: calc( (var(--gw-space-1) + 2rem + var(--gw-space-1)) * var(--gw-field-scale, 1) ); } /* The trigger shows the chosen option, with its icon, and a chevron with room around it that turns over while the list is open */ gw-select .gw-select-trigger { display: flex; gap: calc(var(--gw-space-2) * var(--gw-field-size)); align-items: center; padding-inline-end: calc(var(--gw-space-3) * var(--gw-field-size)); text-align: start; cursor: pointer; } gw-select .gw-select-value { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } /* With an inline label the select sits among toolbar controls, so it's a pill that fits its content, like the toggles and buttons beside it */ gw-select[inline-label] { display: inline-flex; } gw-select[inline-label] .gw-select-trigger { width: auto; padding-inline: calc(var(--gw-space-4) * var(--gw-field-size)) calc(var(--gw-space-3) * var(--gw-field-size)); border-radius: var(--gw-radius-pill); } /* An inline label reads as a quiet prefix to the value */ gw-select .gw-select-inline-label { flex: none; color: var(--gw-color-text-secondary); } gw-select .gw-select-inline-label[hidden] { display: none; } gw-select .gw-select-value[data-placeholder] { color: var(--gw-color-text-secondary); } gw-select .gw-select-trigger > .icon { flex: none; width: var(--gw-icon-size, 1.25rem); height: var(--gw-icon-size, 1.25rem); fill: currentColor; } gw-select .gw-select-trigger > .icon:last-child { color: var(--gw-color-text-secondary); transition: rotate var(--gw-motion-normal) var(--gw-motion-easing); } gw-select[open] .gw-select-trigger > .icon:last-child { rotate: 180deg; } gw-select .gw-select-trigger > .icon[hidden] { display: none; } /* The list opens under the trigger, growing from it, or as a bottom sheet sliding up on phones */ gw-select .gw-select-popup { position: fixed; inset: unset; box-sizing: border-box; max-width: calc(100vw - 12px); padding: 0; margin: 0; overflow: hidden; color: var(--gw-color-text-primary); background: var(--gw-color-surface-overlay); border: max(var(--gw-border-width), 1px) solid var(--gw-color-border-normal); border-radius: var(--gw-radius-panel); box-shadow: var(--gw-shadow-l); opacity: 0; scale: 1 0.96; transform-origin: top; transition: opacity var(--gw-motion-fast) var(--gw-motion-easing), scale var(--gw-motion-normal) var(--gw-motion-easing), translate var(--gw-motion-normal) var(--gw-motion-easing), display var(--gw-motion-normal) allow-discrete, overlay var(--gw-motion-normal) allow-discrete; } gw-select .gw-select-popup[data-placement=\"above\"] { transform-origin: bottom; } gw-select .gw-select-popup:popover-open { opacity: 1; scale: 1; } @starting-style { gw-select .gw-select-popup:popover-open { opacity: 0; scale: 1 0.96; } } gw-select .gw-select-popup[data-placement=\"sheet\"] { inset: auto 0 0; width: 100%; max-width: none; padding-block-end: env(safe-area-inset-bottom); border-end-start-radius: 0; border-end-end-radius: 0; scale: 1; translate: 0 100%; --gw-option-list-height: 60vh; } gw-select .gw-select-popup[data-placement=\"sheet\"]:popover-open { translate: 0 0; } @starting-style { gw-select .gw-select-popup[data-placement=\"sheet\"]:popover-open { translate: 0 100%; } } gw-select .gw-select-popup[data-placement=\"sheet\"]::backdrop { background: rgb(0 0 0 / 40%); } /* With multiple, a full-width Clear under the list empties the choice */ gw-select .gw-select-clear { display: block; width: 100%; min-height: 2.5rem; padding: 0 var(--gw-space-3); font: inherit; font-size: var(--gw-font-size-s); font-weight: var(--gw-font-weight-strong); color: var(--gw-color-text-secondary); cursor: pointer; background: none; border: 0; border-block-start: var(--gw-border-width) solid var(--gw-color-border-quiet); transition: color var(--gw-motion-fast) var(--gw-motion-easing), background-color var(--gw-motion-fast) var(--gw-motion-easing); } gw-select .gw-select-clear:hover { color: var(--gw-color-text-strong); background: var(--gw-color-fill-neutral-hovered); } gw-select .gw-select-clear:focus-visible { outline: var(--gw-focus-width) solid var(--gw-color-focus); outline-offset: calc(var(--gw-focus-width) * -1); } gw-select .gw-select-clear[hidden] { display: none; } :where(gw-input) .gw-input-control:focus-within > .icon { color: var(--gw-color-text-strong); } :where(gw-input, gw-select) :where(input, textarea, .gw-select-trigger):hover { border-color: var(--gw-color-border-loud); } :where(gw-input, gw-select, gw-switch, gw-checkbox) :where(input, textarea, .gw-select-trigger):focus-visible { outline: var(--gw-focus-width) solid var(--gw-color-focus); outline-offset: var(--gw-focus-offset); } :where(gw-input, gw-select) [aria-invalid=\"true\"] { border-color: var(--gw-color-border-danger); } :where(gw-input, gw-select, gw-switch, gw-checkbox) :disabled { color: var(--gw-color-text-disabled); cursor: not-allowed; } :where(gw-input, gw-select, gw-switch, gw-checkbox) .gw-hint { margin: 0; font-size: var(--gw-font-size-xs); color: var(--gw-color-text-secondary); } :where(gw-input, gw-select, gw-switch, gw-checkbox) .gw-error { margin: 0; font-size: var(--gw-font-size-xs); color: var(--gw-color-danger); } :where(gw-switch, gw-checkbox) > label { display: inline-flex; gap: var(--gw-space-3); align-items: center; font-size: var(--gw-font-size-s); cursor: pointer; } :where(gw-input, gw-switch, gw-checkbox, gw-select) .gw-visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; } gw-checkbox input { width: 1.125rem; height: 1.125rem; margin: 0; accent-color: var(--gw-color-fill-accent-resting); } gw-switch input { position: relative; flex: none; width: 2.5rem; height: 1.5rem; margin: 0; cursor: pointer; appearance: none; background: var(--gw-color-surface-lower); border: var(--gw-border-width) solid var(--gw-color-border-loud); border-radius: var(--gw-radius-pill); transition: background-color var(--gw-motion-normal) var(--gw-motion-easing), border-color var(--gw-motion-normal) var(--gw-motion-easing); } gw-switch input::after { position: absolute; inset-block-start: 0.1875rem; inset-inline-start: 0.1875rem; width: 1rem; height: 1rem; content: \"\"; background: var(--gw-color-text-secondary); border-radius: 50%; transition: translate var(--gw-motion-normal) var(--gw-motion-easing), background-color var(--gw-motion-normal) var(--gw-motion-easing); } gw-switch input:checked { background: var(--gw-color-fill-accent-resting); border-color: transparent; } gw-switch input:checked::after { translate: 1rem 0; background: var(--gw-color-on-accent); } gw-switch input:disabled { opacity: 0.5; } gw-range { display: flex; flex-direction: column; gap: var(--gw-space-2); min-width: 0; font-family: var(--gw-font-sans); color: var(--gw-color-text-primary); } gw-range > label { font-size: var(--gw-font-size-s); font-weight: var(--gw-font-weight-strong); color: var(--gw-color-text-strong); } gw-range .gw-range-row { display: flex; gap: var(--gw-space-3); align-items: center; } gw-range .gw-range-control { position: relative; display: block; flex: 1; min-width: 0; } /* The value beside the track, with readout */ gw-range .gw-range-readout { min-width: 5ch; font-size: var(--gw-font-size-s); font-variant-numeric: tabular-nums; color: var(--gw-color-text-secondary); text-align: end; white-space: nowrap; } gw-range .gw-range-readout[hidden] { display: none; } gw-range input { display: block; width: 100%; margin: 0; accent-color: var(--gw-color-fill-accent-resting); cursor: pointer; } gw-range input:focus-visible { outline: var(--gw-focus-width) solid var(--gw-color-focus); outline-offset: var(--gw-focus-offset); } gw-range input:disabled { cursor: not-allowed; opacity: 0.5; } /* The value above the thumb while it's held */ gw-range .gw-range-bubble { position: absolute; bottom: calc(100% + var(--gw-space-1)); padding: var(--gw-space-1) var(--gw-space-2); font-size: var(--gw-font-size-xs); font-variant-numeric: tabular-nums; color: var(--gw-color-on-accent); white-space: nowrap; pointer-events: none; background: var(--gw-color-fill-accent-resting); border-radius: var(--gw-radius-control); box-shadow: var(--gw-shadow-s); translate: -50% 0; } gw-range .gw-range-bubble[hidden] { display: none; } gw-range .gw-hint { margin: 0; font-size: var(--gw-font-size-xs); color: var(--gw-color-text-secondary); } gw-range .gw-visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; } `",
|
|
663
|
+
"default": "css` :where(gw-input, gw-select, gw-switch, gw-checkbox) { display: flex; flex-direction: column; gap: var(--gw-space-2); font-family: var(--gw-font-sans); color: var(--gw-color-text-primary); } :where(gw-input, gw-select) .gw-field-heading { display: flex; gap: var(--gw-space-1); align-items: center; } :where(gw-input, gw-select) .gw-field-heading > label { font-size: var(--gw-font-size-s); font-weight: var(--gw-font-weight-strong); color: var(--gw-color-text-strong); } /* The (i) button by the label that opens a field's longer help */ :where(gw-input, gw-select) .gw-info { display: inline-grid; place-items: center; width: 1.5rem; height: 1.5rem; padding: 0; color: var(--gw-color-text-secondary); cursor: pointer; background: none; border: 0; border-radius: var(--gw-radius-pill); transition: color var(--gw-motion-fast) var(--gw-motion-easing), background-color var(--gw-motion-fast) var(--gw-motion-easing); } :where(gw-input, gw-select) .gw-info:hover { color: var(--gw-color-text-strong); background: var(--gw-color-fill-neutral-hovered); } :where(gw-input, gw-select) .gw-info:focus-visible { outline: var(--gw-focus-width) solid var(--gw-color-focus); outline-offset: var(--gw-focus-offset); } :where(gw-input, gw-select) .gw-info[hidden] { display: none; } :where(gw-input, gw-select) .gw-info > .icon { width: 1rem; height: 1rem; fill: currentColor; } /* Sizes run xs to xl through --gw-field-scale, around 1 for medium, and the control's height follows the theme's density too */ :where(gw-input, gw-select)[size=\"xs\"] { --gw-field-scale: 0.6; } :where(gw-input, gw-select)[size=\"small\"] { --gw-field-scale: 0.8; } :where(gw-input, gw-select)[size=\"large\"] { --gw-field-scale: 1.2; } :where(gw-input, gw-select)[size=\"xl\"] { --gw-field-scale: 1.4; } :where(gw-input, gw-select) :where(input, textarea, .gw-select-trigger) { --gw-field-size: var(--gw-field-scale, 1); --gw-icon-size: calc( 1.25rem * var(--gw-field-size) * var(--gw-control-scale, 1) ); width: 100%; min-height: calc( 2.5rem * var(--gw-field-size) * var(--gw-control-scale, 1) ); padding: 0 calc(var(--gw-space-3) * var(--gw-field-size)); font: inherit; font-size: calc(var(--gw-font-size-s) * var(--gw-field-size)); color: var(--gw-color-text-strong); background: var(--gw-color-surface-lower); border: var(--gw-border-width) solid var(--gw-color-border-normal); border-radius: var(--gw-radius-control); transition: border-color var(--gw-motion-fast) var(--gw-motion-easing); } /* An icon inside the field, before the text, with the text moved clear of it */ gw-input .gw-input-control { position: relative; display: flex; align-items: center; } gw-input .gw-input-control > .icon { position: absolute; inset-inline-start: calc(var(--gw-space-3) * var(--gw-field-scale, 1)); width: calc(1.125rem * var(--gw-field-scale, 1)); height: calc(1.125rem * var(--gw-field-scale, 1)); color: var(--gw-color-text-secondary); pointer-events: none; fill: currentColor; } gw-input .gw-input-control > .icon[hidden] { display: none; } gw-input .gw-input-control > .icon:not([hidden]) + input { padding-inline-start: calc( (var(--gw-space-3) * 2 + 1.125rem) * var(--gw-field-scale, 1) ); } /* A textarea keeps the field's padding on every side and grows by its corner, never sideways out of the layout */ gw-input textarea { display: block; /* Pill-shaped controls would make a tall box a stadium, so it rounds no more than a panel */ border-radius: min(var(--gw-radius-control), var(--gw-radius-panel)); padding-block: calc(var(--gw-space-2) * var(--gw-field-size)); line-height: 1.5; resize: vertical; } gw-input[monospace] :where(input, textarea) { font-family: var(--gw-font-mono); } gw-input .gw-optional { font-weight: var(--gw-font-weight-regular); color: var(--gw-color-text-secondary); } gw-input .gw-optional[hidden] { display: none; } /* The show and hide button sits inside the end of a password field, with the text kept clear of it */ gw-input .gw-reveal { position: absolute; inset-inline-end: calc(var(--gw-space-1) * var(--gw-field-scale, 1)); display: grid; place-items: center; width: calc(2rem * var(--gw-field-scale, 1)); height: calc(2rem * var(--gw-field-scale, 1)); padding: 0; color: var(--gw-color-text-secondary); cursor: pointer; background: none; border: 0; border-radius: var(--gw-radius-control); transition: color var(--gw-motion-fast) var(--gw-motion-easing), background-color var(--gw-motion-fast) var(--gw-motion-easing); } gw-input .gw-reveal:hover:not(:disabled) { color: var(--gw-color-text-strong); background: var(--gw-color-fill-neutral-hovered); } gw-input .gw-reveal:focus-visible { outline: var(--gw-focus-width) solid var(--gw-color-focus); outline-offset: calc(var(--gw-focus-width) * -1); } gw-input .gw-reveal:disabled { cursor: not-allowed; opacity: 0.5; } gw-input .gw-reveal[hidden] { display: none; } gw-input .gw-reveal > .icon { width: calc(1.125rem * var(--gw-field-scale, 1)); height: calc(1.125rem * var(--gw-field-scale, 1)); fill: currentColor; } gw-input .gw-input-control:has(> .gw-reveal:not([hidden])) > input { padding-inline-end: calc( (var(--gw-space-1) + 2rem + var(--gw-space-1)) * var(--gw-field-scale, 1) ); } /* The trigger shows the chosen option, with its icon, and a chevron with room around it that turns over while the list is open */ gw-select .gw-select-trigger { display: flex; gap: calc(var(--gw-space-2) * var(--gw-field-size)); align-items: center; padding-inline-end: calc(var(--gw-space-3) * var(--gw-field-size)); text-align: start; cursor: pointer; } gw-select .gw-select-value { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } /* With an inline label the select sits among toolbar controls, so it's a pill that fits its content, like the toggles and buttons beside it */ gw-select[inline-label] { display: inline-flex; } gw-select[inline-label] .gw-select-trigger { width: auto; padding-inline: calc(var(--gw-space-4) * var(--gw-field-size)) calc(var(--gw-space-3) * var(--gw-field-size)); border-radius: var(--gw-radius-pill); } /* An inline label reads as a quiet prefix to the value */ gw-select .gw-select-inline-label { flex: none; color: var(--gw-color-text-secondary); } gw-select .gw-select-inline-label[hidden] { display: none; } gw-select .gw-select-value[data-placeholder] { color: var(--gw-color-text-secondary); } gw-select .gw-select-trigger > .icon { flex: none; width: var(--gw-icon-size, 1.25rem); height: var(--gw-icon-size, 1.25rem); fill: currentColor; } gw-select .gw-select-trigger > .icon:last-child { color: var(--gw-color-text-secondary); transition: rotate var(--gw-motion-normal) var(--gw-motion-easing); } gw-select[open] .gw-select-trigger > .icon:last-child { rotate: 180deg; } gw-select .gw-select-trigger > .icon[hidden] { display: none; } /* The list opens under the trigger, growing from it, or as a bottom sheet sliding up on phones */ gw-select .gw-select-popup { position: fixed; inset: unset; box-sizing: border-box; max-width: calc(100vw - 12px); padding: 0; margin: 0; overflow: hidden; color: var(--gw-color-text-primary); background: var(--gw-color-surface-overlay); border: max(var(--gw-border-width), 1px) solid var(--gw-color-border-normal); border-radius: var(--gw-radius-panel); box-shadow: var(--gw-shadow-l); opacity: 0; scale: 1 0.96; transform-origin: top; transition: opacity var(--gw-motion-fast) var(--gw-motion-easing), scale var(--gw-motion-normal) var(--gw-motion-easing), translate var(--gw-motion-normal) var(--gw-motion-easing), display var(--gw-motion-normal) allow-discrete, overlay var(--gw-motion-normal) allow-discrete; } gw-select .gw-select-popup[data-placement=\"above\"] { transform-origin: bottom; } gw-select .gw-select-popup:popover-open { opacity: 1; scale: 1; } @starting-style { gw-select .gw-select-popup:popover-open { opacity: 0; scale: 1 0.96; } } gw-select .gw-select-popup[data-placement=\"sheet\"] { inset: auto 0 0; width: 100%; max-width: none; padding-block-end: env(safe-area-inset-bottom); border-end-start-radius: 0; border-end-end-radius: 0; scale: 1; translate: 0 100%; --gw-option-list-height: 60vh; } gw-select .gw-select-popup[data-placement=\"sheet\"]:popover-open { translate: 0 0; } @starting-style { gw-select .gw-select-popup[data-placement=\"sheet\"]:popover-open { translate: 0 100%; } } gw-select .gw-select-popup[data-placement=\"sheet\"]::backdrop { background: rgb(0 0 0 / 40%); } /* With multiple, a full-width Clear under the list empties the choice */ gw-select .gw-select-clear { display: block; width: 100%; min-height: 2.5rem; padding: 0 var(--gw-space-3); font: inherit; font-size: var(--gw-font-size-s); font-weight: var(--gw-font-weight-strong); color: var(--gw-color-text-secondary); cursor: pointer; background: none; border: 0; border-block-start: var(--gw-border-width) solid var(--gw-color-border-quiet); transition: color var(--gw-motion-fast) var(--gw-motion-easing), background-color var(--gw-motion-fast) var(--gw-motion-easing); } gw-select .gw-select-clear:hover { color: var(--gw-color-text-strong); background: var(--gw-color-fill-neutral-hovered); } gw-select .gw-select-clear:focus-visible { outline: var(--gw-focus-width) solid var(--gw-color-focus); outline-offset: calc(var(--gw-focus-width) * -1); } gw-select .gw-select-clear[hidden] { display: none; } :where(gw-input) .gw-input-control:focus-within > .icon { color: var(--gw-color-text-strong); } :where(gw-input, gw-select) :where(input, textarea, .gw-select-trigger):hover { border-color: var(--gw-color-border-loud); } :where(gw-input, gw-select, gw-switch, gw-checkbox) :where(input, textarea, .gw-select-trigger):focus-visible { outline: var(--gw-focus-width) solid var(--gw-color-focus); outline-offset: var(--gw-focus-offset); } :where(gw-input, gw-select) [aria-invalid=\"true\"] { border-color: var(--gw-color-border-danger); } :where(gw-input, gw-select, gw-switch, gw-checkbox) :disabled { color: var(--gw-color-text-disabled); cursor: not-allowed; } :where(gw-input, gw-select, gw-switch, gw-checkbox) .gw-hint { margin: 0; font-size: var(--gw-font-size-xs); color: var(--gw-color-text-secondary); } :where(gw-input, gw-select, gw-switch, gw-checkbox) .gw-error { margin: 0; font-size: var(--gw-font-size-xs); color: var(--gw-color-danger); } :where(gw-switch, gw-checkbox) > label { display: inline-flex; gap: var(--gw-space-3); align-items: center; font-size: var(--gw-font-size-s); cursor: pointer; } :where(gw-input, gw-switch, gw-checkbox, gw-select) .gw-visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; } gw-checkbox input { width: 1.125rem; height: 1.125rem; margin: 0; accent-color: var(--gw-color-fill-accent-resting); } gw-switch input { position: relative; flex: none; width: 2.5rem; height: 1.5rem; margin: 0; cursor: pointer; appearance: none; background: var(--gw-color-surface-lower); border: var(--gw-border-width) solid var(--gw-color-border-loud); border-radius: var(--gw-radius-pill); transition: background-color var(--gw-motion-normal) var(--gw-motion-easing), border-color var(--gw-motion-normal) var(--gw-motion-easing); } gw-switch input::after { position: absolute; inset-block-start: 0.1875rem; inset-inline-start: 0.1875rem; width: 1rem; height: 1rem; content: \"\"; background: var(--gw-color-text-secondary); border-radius: 50%; transition: translate var(--gw-motion-normal) var(--gw-motion-easing), background-color var(--gw-motion-normal) var(--gw-motion-easing); } gw-switch input:checked { background: var(--gw-color-fill-accent-resting); border-color: transparent; } gw-switch input:checked::after { translate: 1rem 0; background: var(--gw-color-on-accent); } gw-switch input:disabled { opacity: 0.5; } gw-range { display: flex; flex-direction: column; gap: var(--gw-space-2); min-width: 0; font-family: var(--gw-font-sans); color: var(--gw-color-text-primary); } gw-range > label { font-size: var(--gw-font-size-s); font-weight: var(--gw-font-weight-strong); color: var(--gw-color-text-strong); } gw-range .gw-range-row { display: flex; gap: var(--gw-space-3); align-items: center; } gw-range .gw-range-control { position: relative; display: block; flex: 1; min-width: 0; } /* The value beside the track, with readout */ gw-range .gw-range-readout { min-width: 5ch; font-size: var(--gw-font-size-s); font-variant-numeric: tabular-nums; color: var(--gw-color-text-secondary); text-align: end; white-space: nowrap; } gw-range .gw-range-readout[hidden] { display: none; } gw-range input { display: block; width: 100%; margin: 0; accent-color: var(--gw-color-fill-accent-resting); cursor: pointer; } gw-range input:focus-visible { outline: var(--gw-focus-width) solid var(--gw-color-focus); outline-offset: var(--gw-focus-offset); } gw-range input:disabled { cursor: not-allowed; opacity: 0.5; } /* The value above the thumb while it's held */ gw-range .gw-range-bubble { position: absolute; bottom: calc(100% + var(--gw-space-1)); padding: var(--gw-space-1) var(--gw-space-2); font-size: var(--gw-font-size-xs); font-variant-numeric: tabular-nums; color: var(--gw-color-on-accent); white-space: nowrap; pointer-events: none; background: var(--gw-color-fill-accent-resting); border-radius: var(--gw-radius-control); box-shadow: var(--gw-shadow-s); translate: -50% 0; } gw-range .gw-range-bubble[hidden] { display: none; } gw-range .gw-hint { margin: 0; font-size: var(--gw-font-size-xs); color: var(--gw-color-text-secondary); } gw-range .gw-visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; } `",
|
|
664
664
|
"description": "Field components render their native control in light DOM, never in a\nshadow root: password managers and `<label for>` can't reach across one,\nand a form only submits controls it can see. Their styles are adopted into\nwhichever document or shadow root they sit in."
|
|
665
665
|
},
|
|
666
666
|
{
|
|
@@ -1107,7 +1107,7 @@
|
|
|
1107
1107
|
"text": "readonly CSSStyleSheet[]"
|
|
1108
1108
|
},
|
|
1109
1109
|
"static": true,
|
|
1110
|
-
"default": "[ base, css` :host { display: block; } .alert { display: flex; gap: var(--gw-space-2); align-items: flex-start; padding: var(--gw-space-2) var(--gw-space-3); font-size: var(--gw-font-size-s); color: var(--gw-color-text-primary); background: var(--gw-tone-fill, var(--gw-color-fill-info-quiet)); border: var(--gw-border-width) solid var(--gw-tone-border, var(--gw-color-border-info)); border-inline-start-width: calc(var(--gw-border-width) * 4); border-radius: var(--gw-radius-control); } ::slotted(p) { margin: 0; } ::slotted([slot=\"actions\"]) { align-self: center; } ::slotted([slot=\"icon\"]), .icon { flex: none; color: var(--gw-tone, var(--gw-color-info)); } .body { flex: 1; min-width: 0; } strong { display: block; font-weight: var(--gw-font-weight-strong); color: var(--gw-color-text-strong); } `, ]",
|
|
1110
|
+
"default": "[ base, css` :host { display: block; } .alert { display: flex; gap: var(--gw-space-2); align-items: flex-start; padding: var(--gw-space-2) var(--gw-space-3); font-size: var(--gw-font-size-s); color: var(--gw-color-text-primary); background: var(--gw-tone-fill, var(--gw-color-fill-info-quiet)); border: var(--gw-border-width) solid var(--gw-tone-border, var(--gw-color-border-info)); border-inline-start-width: calc(var(--gw-border-width) * 4); border-radius: min(var(--gw-radius-control), var(--gw-radius-panel)); } ::slotted(p) { margin: 0; } ::slotted([slot=\"actions\"]) { align-self: center; } ::slotted([slot=\"icon\"]), .icon { flex: none; color: var(--gw-tone, var(--gw-color-info)); } .body { flex: 1; min-width: 0; } strong { display: block; font-weight: var(--gw-font-weight-strong); color: var(--gw-color-text-strong); } `, ]",
|
|
1111
1111
|
"inheritedFrom": {
|
|
1112
1112
|
"name": "GwElement",
|
|
1113
1113
|
"module": "src/element.ts"
|
|
@@ -3836,7 +3836,7 @@
|
|
|
3836
3836
|
"text": "Properties"
|
|
3837
3837
|
},
|
|
3838
3838
|
"static": true,
|
|
3839
|
-
"default": "{ heading: {}, description: {}, icon: {}, level: { type: \"number\" }, href: {}, flush: { type: \"boolean\", reflect: true }, loading: { type: \"boolean\", reflect: true }, lines: { type: \"number\" }, }",
|
|
3839
|
+
"default": "{ heading: {}, description: {}, icon: {}, level: { type: \"number\" }, href: {}, titleLink: { attribute: \"title-link\", type: \"boolean\", reflect: true }, flush: { type: \"boolean\", reflect: true }, loading: { type: \"boolean\", reflect: true }, lines: { type: \"number\" }, }",
|
|
3840
3840
|
"inheritedFrom": {
|
|
3841
3841
|
"name": "GwElement",
|
|
3842
3842
|
"module": "src/element.ts"
|
|
@@ -3849,7 +3849,7 @@
|
|
|
3849
3849
|
"text": "readonly CSSStyleSheet[]"
|
|
3850
3850
|
},
|
|
3851
3851
|
"static": true,
|
|
3852
|
-
"default": "[ base, css` :host { display: block; } .card { display: flex; flex-direction: column; gap: var(--gw-space-3); height: 100%; padding: var(--gw-space-4); color: inherit; text-decoration: none; background: var(--gw-color-surface-raised); border: var(--gw-border-width) solid var(--gw-color-border-normal); border-radius: var(--gw-radius-panel); box-shadow: var(--gw-shadow-s); } :host([flush]) .card { padding: 0; overflow: hidden; } a.card { transition: border-color var(--gw-motion-fast) var(--gw-motion-easing); } a.card:hover, .card.linked:hover { border-color: var(--gw-color-border-accent); } /* A card following a link in its heading slot */ .card.linked { cursor: pointer; transition: border-color var(--gw-motion-fast) var(--gw-motion-easing); } .card.focused { outline: var(--gw-focus-width) solid var(--gw-color-focus); outline-offset: var(--gw-focus-offset); } ::slotted([slot=\"heading\"]) { font: inherit; color: inherit; } ::slotted(a[slot=\"heading\"]) { text-decoration: none; outline: none; } header { display: flex; gap: var(--gw-space-2); align-items: center; } header > .icon { flex-shrink: 0; margin-inline-end: var(--gw-space-1); color: var(--gw-color-accent); } .titles { display: flex; flex: 1; flex-direction: column; gap: var(--gw-space-0-5); min-width: 0; } .title { margin: 0; font-size: var(--gw-font-size-m); font-weight: var(--gw-font-weight-strong); color: var(--gw-color-text-strong); } .description { font-size: var(--gw-font-size-xs); color: var(--gw-color-text-secondary); } /* The divider runs to the card's edges */ footer:not([hidden]) { display: flex; flex-direction: column; gap: inherit; margin-inline: calc(-1 * var(--gw-space-4)); padding: var(--gw-space-3) var(--gw-space-4) 0; border-top: var(--gw-border-width) solid var(--gw-color-border-normal); } :host([flush]) footer:not([hidden]) { margin-inline: 0; padding-bottom: var(--gw-space-3); } .body:not([hidden]) { display: flex; flex-direction: column; gap: inherit; } `, ]",
|
|
3852
|
+
"default": "[ base, css` :host { display: block; } .card { display: flex; flex-direction: column; gap: var(--gw-space-3); height: 100%; padding: var(--gw-space-4); color: inherit; text-decoration: none; background: var(--gw-color-surface-raised); border: var(--gw-border-width) solid var(--gw-color-border-normal); border-radius: var(--gw-radius-panel); box-shadow: var(--gw-shadow-s); } :host([flush]) .card { padding: 0; overflow: hidden; } a.card { transition: border-color var(--gw-motion-fast) var(--gw-motion-easing); } a.card:hover, .card.linked:hover { border-color: var(--gw-color-border-accent); } /* A card following a link in its heading slot */ .card.linked { cursor: pointer; transition: border-color var(--gw-motion-fast) var(--gw-motion-easing); } .card.focused { outline: var(--gw-focus-width) solid var(--gw-color-focus); outline-offset: var(--gw-focus-offset); } ::slotted([slot=\"heading\"]) { font: inherit; color: inherit; } ::slotted(a[slot=\"heading\"]) { text-decoration: none; outline: none; } /* With title-link, only the heading is the link */ .title a { color: inherit; text-decoration: none; border-radius: var(--gw-radius-chip); } .title a[href]:hover, :host([title-link]) ::slotted(a[slot=\"heading\"]:hover) { color: var(--gw-color-accent); text-decoration: underline; } .title a[href]:focus-visible, :host([title-link]) ::slotted(a[slot=\"heading\"]:focus-visible) { outline: var(--gw-focus-width) solid var(--gw-color-focus); outline-offset: var(--gw-focus-offset); } header { display: flex; gap: var(--gw-space-2); align-items: center; } header > .icon { flex-shrink: 0; margin-inline-end: var(--gw-space-1); color: var(--gw-color-accent); } .titles { display: flex; flex: 1; flex-direction: column; gap: var(--gw-space-0-5); min-width: 0; } .title { margin: 0; font-size: var(--gw-font-size-m); font-weight: var(--gw-font-weight-strong); color: var(--gw-color-text-strong); } .description { font-size: var(--gw-font-size-xs); color: var(--gw-color-text-secondary); } /* The divider runs to the card's edges */ footer:not([hidden]) { display: flex; flex-direction: column; gap: inherit; margin-inline: calc(-1 * var(--gw-space-4)); padding: var(--gw-space-3) var(--gw-space-4) 0; border-top: var(--gw-border-width) solid var(--gw-color-border-normal); } :host([flush]) footer:not([hidden]) { margin-inline: 0; padding-bottom: var(--gw-space-3); } .body:not([hidden]) { display: flex; flex-direction: column; gap: inherit; } `, ]",
|
|
3853
3853
|
"inheritedFrom": {
|
|
3854
3854
|
"name": "GwElement",
|
|
3855
3855
|
"module": "src/element.ts"
|
|
@@ -3897,6 +3897,15 @@
|
|
|
3897
3897
|
},
|
|
3898
3898
|
"default": "\"\""
|
|
3899
3899
|
},
|
|
3900
|
+
{
|
|
3901
|
+
"kind": "field",
|
|
3902
|
+
"name": "titleLink",
|
|
3903
|
+
"type": {
|
|
3904
|
+
"text": "boolean"
|
|
3905
|
+
},
|
|
3906
|
+
"description": "Makes only the heading the link, rather than the whole card.",
|
|
3907
|
+
"default": "false"
|
|
3908
|
+
},
|
|
3900
3909
|
{
|
|
3901
3910
|
"kind": "field",
|
|
3902
3911
|
"name": "flush",
|
|
@@ -3928,6 +3937,12 @@
|
|
|
3928
3937
|
"privacy": "private",
|
|
3929
3938
|
"readonly": true
|
|
3930
3939
|
},
|
|
3940
|
+
{
|
|
3941
|
+
"kind": "field",
|
|
3942
|
+
"name": "#titleAnchor",
|
|
3943
|
+
"privacy": "private",
|
|
3944
|
+
"readonly": true
|
|
3945
|
+
},
|
|
3931
3946
|
{
|
|
3932
3947
|
"kind": "field",
|
|
3933
3948
|
"name": "#titleSkeleton",
|
|
@@ -4397,6 +4412,13 @@
|
|
|
4397
4412
|
"description": "Makes the whole card a link to this address.",
|
|
4398
4413
|
"name": "href"
|
|
4399
4414
|
},
|
|
4415
|
+
{
|
|
4416
|
+
"type": {
|
|
4417
|
+
"text": "boolean"
|
|
4418
|
+
},
|
|
4419
|
+
"description": "Makes only the heading the link, from `href` or an `<a>` in the `heading` slot, so the rest of the card stays plain.",
|
|
4420
|
+
"name": "title-link"
|
|
4421
|
+
},
|
|
4400
4422
|
{
|
|
4401
4423
|
"type": {
|
|
4402
4424
|
"text": "boolean"
|
|
@@ -6068,7 +6090,7 @@
|
|
|
6068
6090
|
"text": "Properties"
|
|
6069
6091
|
},
|
|
6070
6092
|
"static": true,
|
|
6071
|
-
"default": "{ options: { type: \"json\" }, label: {}, placeholder: {}, shortcut: {}, open: { type: \"boolean\", reflect: true }, }",
|
|
6093
|
+
"default": "{ options: { type: \"json\" }, value: {}, label: {}, placeholder: {}, shortcut: {}, open: { type: \"boolean\", reflect: true }, }",
|
|
6072
6094
|
"inheritedFrom": {
|
|
6073
6095
|
"name": "GwElement",
|
|
6074
6096
|
"module": "src/element.ts"
|
|
@@ -6095,6 +6117,15 @@
|
|
|
6095
6117
|
},
|
|
6096
6118
|
"default": "[]"
|
|
6097
6119
|
},
|
|
6120
|
+
{
|
|
6121
|
+
"kind": "field",
|
|
6122
|
+
"name": "value",
|
|
6123
|
+
"type": {
|
|
6124
|
+
"text": "string"
|
|
6125
|
+
},
|
|
6126
|
+
"description": "The current command, marked and selected when the menu opens.",
|
|
6127
|
+
"default": "\"\""
|
|
6128
|
+
},
|
|
6098
6129
|
{
|
|
6099
6130
|
"kind": "field",
|
|
6100
6131
|
"name": "label",
|
|
@@ -6486,6 +6517,13 @@
|
|
|
6486
6517
|
"description": "The commands, as JSON.",
|
|
6487
6518
|
"name": "options"
|
|
6488
6519
|
},
|
|
6520
|
+
{
|
|
6521
|
+
"type": {
|
|
6522
|
+
"text": "string"
|
|
6523
|
+
},
|
|
6524
|
+
"description": "The current command, such as the page you're on. It's marked, and selected and scrolled into view each time the menu opens.",
|
|
6525
|
+
"name": "value"
|
|
6526
|
+
},
|
|
6489
6527
|
{
|
|
6490
6528
|
"type": {
|
|
6491
6529
|
"text": "string"
|
|
@@ -12714,7 +12752,7 @@
|
|
|
12714
12752
|
"text": "readonly CSSStyleSheet[]"
|
|
12715
12753
|
},
|
|
12716
12754
|
"static": true,
|
|
12717
|
-
"default": "[ base, css` :host { display: block; } .card { display: grid; grid-template-columns: auto 1fr auto; gap: var(--gw-space-1) var(--gw-space-2); align-items: start; padding: var(--gw-space-3); font-size: var(--gw-font-size-s); color: var(--gw-color-text-primary); background: var(--gw-color-surface-raised); border: var(--gw-border-width) solid var(--gw-color-border-quiet); border-radius: var(--gw-radius-control); } /* An inset stripe, so unread and read cards line up */ :host([unread]) .card { box-shadow: inset calc(var(--gw-border-width) * 4) 0 0 var(--gw-tone, var(--gw-color-accent)); } :host([unread]:dir(rtl)) .card { box-shadow: inset calc(var(--gw-border-width) * -4) 0 0 var(--gw-tone, var(--gw-color-accent)); } .card > .icon { margin-block-start: 0.1em; color: var(--gw-tone, var(--gw-color-text-secondary)); } .card > .icon[hidden] { display: none; } .body { display: grid; gap: var(--gw-space-1); min-width: 0; } strong { font-weight: var(--gw-font-weight-strong); color: var(--gw-color-text-strong); } time { font-size: var(--gw-font-size-xs); color: var(--gw-color-text-secondary); } time:empty { display: none; } ::slotted(p) { margin: 0; } .actions { display: flex; flex-wrap: wrap; gap: var(--gw-space-1); margin-block-start: var(--gw-space-1); } .close { margin: calc(var(--gw-space-1) * -1); } `, ]",
|
|
12755
|
+
"default": "[ base, css` :host { display: block; } .card { display: grid; grid-template-columns: auto 1fr auto; gap: var(--gw-space-1) var(--gw-space-2); align-items: start; padding: var(--gw-space-3); font-size: var(--gw-font-size-s); color: var(--gw-color-text-primary); background: var(--gw-color-surface-raised); border: var(--gw-border-width) solid var(--gw-color-border-quiet); border-radius: min(var(--gw-radius-control), var(--gw-radius-panel)); } /* An inset stripe, so unread and read cards line up */ :host([unread]) .card { box-shadow: inset calc(var(--gw-border-width) * 4) 0 0 var(--gw-tone, var(--gw-color-accent)); } :host([unread]:dir(rtl)) .card { box-shadow: inset calc(var(--gw-border-width) * -4) 0 0 var(--gw-tone, var(--gw-color-accent)); } .card > .icon { margin-block-start: 0.1em; color: var(--gw-tone, var(--gw-color-text-secondary)); } .card > .icon[hidden] { display: none; } .body { display: grid; gap: var(--gw-space-1); min-width: 0; } strong { font-weight: var(--gw-font-weight-strong); color: var(--gw-color-text-strong); } time { font-size: var(--gw-font-size-xs); color: var(--gw-color-text-secondary); } time:empty { display: none; } ::slotted(p) { margin: 0; } .actions { display: flex; flex-wrap: wrap; gap: var(--gw-space-1); margin-block-start: var(--gw-space-1); } .close { margin: calc(var(--gw-space-1) * -1); } `, ]",
|
|
12718
12756
|
"inheritedFrom": {
|
|
12719
12757
|
"name": "GwElement",
|
|
12720
12758
|
"module": "src/element.ts"
|
|
@@ -21629,7 +21667,7 @@
|
|
|
21629
21667
|
"text": "readonly CSSStyleSheet[]"
|
|
21630
21668
|
},
|
|
21631
21669
|
"static": true,
|
|
21632
|
-
"default": "[ base, css` :host { position: fixed; inset: auto var(--gw-space-4) var(--gw-space-4) auto; width: min(22rem, calc(100vw - 2 * var(--gw-space-4))); padding: 0; margin: 0; overflow: visible; color: inherit; pointer-events: none; user-select: none; background: none; border: 0; } :host(:dir(rtl)) { inset: auto auto var(--gw-space-4) var(--gw-space-4); } :host(:not(:popover-open)) { display: none; } .list { display: flex; flex-direction: column; gap: var(--gw-space-1); align-items: flex-end; } .toast { max-width: 100%; padding: var(--gw-space-2) var(--gw-space-3); font-size: var(--gw-font-size-s); color: var(--gw-color-text-strong); background: var(--gw-color-surface-overlay); border: var(--gw-border-width) solid var(--gw-color-border-normal); border-inline-start: calc(var(--gw-border-width) * 4) solid var(--gw-toast-tone); border-radius: var(--gw-radius-control); box-shadow: var(--gw-shadow-m); } `, ]",
|
|
21670
|
+
"default": "[ base, css` :host { position: fixed; inset: auto var(--gw-space-4) var(--gw-space-4) auto; width: min(22rem, calc(100vw - 2 * var(--gw-space-4))); padding: 0; margin: 0; overflow: visible; color: inherit; pointer-events: none; user-select: none; background: none; border: 0; } :host(:dir(rtl)) { inset: auto auto var(--gw-space-4) var(--gw-space-4); } :host(:not(:popover-open)) { display: none; } .list { display: flex; flex-direction: column; gap: var(--gw-space-1); align-items: flex-end; } .toast { max-width: 100%; padding: var(--gw-space-2) var(--gw-space-3); font-size: var(--gw-font-size-s); color: var(--gw-color-text-strong); background: var(--gw-color-surface-overlay); border: var(--gw-border-width) solid var(--gw-color-border-normal); border-inline-start: calc(var(--gw-border-width) * 4) solid var(--gw-toast-tone); border-radius: min(var(--gw-radius-control), var(--gw-radius-panel)); box-shadow: var(--gw-shadow-m); } `, ]",
|
|
21633
21671
|
"inheritedFrom": {
|
|
21634
21672
|
"name": "GwElement",
|
|
21635
21673
|
"module": "src/element.ts"
|
package/package.json
CHANGED
package/src/fields.ts
CHANGED
|
@@ -140,6 +140,9 @@ export const fieldStyles = css`
|
|
|
140
140
|
corner, never sideways out of the layout */
|
|
141
141
|
gw-input textarea {
|
|
142
142
|
display: block;
|
|
143
|
+
/* Pill-shaped controls would make a tall box a stadium, so it rounds no
|
|
144
|
+
more than a panel */
|
|
145
|
+
border-radius: min(var(--gw-radius-control), var(--gw-radius-panel));
|
|
143
146
|
padding-block: calc(var(--gw-space-2) * var(--gw-field-size));
|
|
144
147
|
line-height: 1.5;
|
|
145
148
|
resize: vertical;
|
package/src/gw-alert.ts
CHANGED
|
@@ -70,7 +70,7 @@ export class GwAlert extends GwElement {
|
|
|
70
70
|
border: var(--gw-border-width) solid
|
|
71
71
|
var(--gw-tone-border, var(--gw-color-border-info));
|
|
72
72
|
border-inline-start-width: calc(var(--gw-border-width) * 4);
|
|
73
|
-
border-radius: var(--gw-radius-control);
|
|
73
|
+
border-radius: min(var(--gw-radius-control), var(--gw-radius-panel));
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
::slotted(p) {
|
package/src/gw-card.ts
CHANGED
|
@@ -29,6 +29,7 @@ import { base, createIcon, setIconPath } from "./styles.js";
|
|
|
29
29
|
* @attr {string} icon - SVG path data for an icon before the heading, such as on a card that links to a section.
|
|
30
30
|
* @attr {number} level - The heading's level for assistive tech, 2 by default. Use 3 for a card under a section heading.
|
|
31
31
|
* @attr {string} href - Makes the whole card a link to this address.
|
|
32
|
+
* @attr {boolean} title-link - Makes only the heading the link, from `href` or an `<a>` in the `heading` slot, so the rest of the card stays plain.
|
|
32
33
|
* @attr {boolean} flush - Drops the padding, for content that runs to the edges.
|
|
33
34
|
* @attr {boolean} loading - Shows skeleton lines for the content and any unknown heading.
|
|
34
35
|
* @attr {number} lines - How many skeleton lines while loading. Defaults to 3.
|
|
@@ -52,6 +53,7 @@ export class GwCard extends GwElement {
|
|
|
52
53
|
icon: {},
|
|
53
54
|
level: { type: "number" },
|
|
54
55
|
href: {},
|
|
56
|
+
titleLink: { attribute: "title-link", type: "boolean", reflect: true },
|
|
55
57
|
flush: { type: "boolean", reflect: true },
|
|
56
58
|
loading: { type: "boolean", reflect: true },
|
|
57
59
|
lines: { type: "number" },
|
|
@@ -113,6 +115,25 @@ export class GwCard extends GwElement {
|
|
|
113
115
|
outline: none;
|
|
114
116
|
}
|
|
115
117
|
|
|
118
|
+
/* With title-link, only the heading is the link */
|
|
119
|
+
.title a {
|
|
120
|
+
color: inherit;
|
|
121
|
+
text-decoration: none;
|
|
122
|
+
border-radius: var(--gw-radius-chip);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.title a[href]:hover,
|
|
126
|
+
:host([title-link]) ::slotted(a[slot="heading"]:hover) {
|
|
127
|
+
color: var(--gw-color-accent);
|
|
128
|
+
text-decoration: underline;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.title a[href]:focus-visible,
|
|
132
|
+
:host([title-link]) ::slotted(a[slot="heading"]:focus-visible) {
|
|
133
|
+
outline: var(--gw-focus-width) solid var(--gw-color-focus);
|
|
134
|
+
outline-offset: var(--gw-focus-offset);
|
|
135
|
+
}
|
|
136
|
+
|
|
116
137
|
header {
|
|
117
138
|
display: flex;
|
|
118
139
|
gap: var(--gw-space-2);
|
|
@@ -175,6 +196,8 @@ export class GwCard extends GwElement {
|
|
|
175
196
|
/** The heading's level for assistive tech. */
|
|
176
197
|
declare level: number;
|
|
177
198
|
declare href: string;
|
|
199
|
+
/** Makes only the heading the link, rather than the whole card. */
|
|
200
|
+
declare titleLink: boolean;
|
|
178
201
|
declare flush: boolean;
|
|
179
202
|
declare loading: boolean;
|
|
180
203
|
/** How many lines of skeleton stand in for the content while loading. */
|
|
@@ -182,6 +205,9 @@ export class GwCard extends GwElement {
|
|
|
182
205
|
|
|
183
206
|
readonly #title = h("span");
|
|
184
207
|
|
|
208
|
+
// A link only with title-link and href; without an href it's plain text
|
|
209
|
+
readonly #titleAnchor = h("a", {}, this.#title);
|
|
210
|
+
|
|
185
211
|
readonly #titleSkeleton = h("gw-skeleton-text");
|
|
186
212
|
|
|
187
213
|
readonly #headingSlot = h("slot", { name: "heading" });
|
|
@@ -189,7 +215,7 @@ export class GwCard extends GwElement {
|
|
|
189
215
|
readonly #heading = h(
|
|
190
216
|
"div",
|
|
191
217
|
{ class: "title", part: "heading", role: "heading", "aria-level": "2" },
|
|
192
|
-
this.#
|
|
218
|
+
this.#titleAnchor,
|
|
193
219
|
this.#headingSlot,
|
|
194
220
|
this.#titleSkeleton,
|
|
195
221
|
);
|
|
@@ -242,6 +268,7 @@ export class GwCard extends GwElement {
|
|
|
242
268
|
this.icon = "";
|
|
243
269
|
this.level = 2;
|
|
244
270
|
this.href = "";
|
|
271
|
+
this.titleLink = false;
|
|
245
272
|
this.flush = false;
|
|
246
273
|
this.loading = false;
|
|
247
274
|
this.lines = 3;
|
|
@@ -251,7 +278,7 @@ export class GwCard extends GwElement {
|
|
|
251
278
|
this.addEventListener("click", (event) => {
|
|
252
279
|
const link = this.#link();
|
|
253
280
|
|
|
254
|
-
if (link === null || this.loading) return;
|
|
281
|
+
if (link === null || this.loading || this.titleLink) return;
|
|
255
282
|
|
|
256
283
|
const path = event.composedPath();
|
|
257
284
|
const own = path.slice(0, path.indexOf(this));
|
|
@@ -277,7 +304,7 @@ export class GwCard extends GwElement {
|
|
|
277
304
|
const focus = () => {
|
|
278
305
|
this.#card.classList.toggle(
|
|
279
306
|
"focused",
|
|
280
|
-
this.#link()?.matches(":focus-visible") === true,
|
|
307
|
+
!this.titleLink && this.#link()?.matches(":focus-visible") === true,
|
|
281
308
|
);
|
|
282
309
|
};
|
|
283
310
|
|
|
@@ -327,11 +354,13 @@ export class GwCard extends GwElement {
|
|
|
327
354
|
|
|
328
355
|
const before = animate ? this.offsetHeight : 0;
|
|
329
356
|
|
|
357
|
+
const cardLink = Boolean(this.href) && !this.titleLink;
|
|
358
|
+
|
|
330
359
|
if (
|
|
331
|
-
changed.has("href") &&
|
|
332
|
-
(this.#card.tagName === "A") !==
|
|
360
|
+
(changed.has("href") || changed.has("titleLink")) &&
|
|
361
|
+
(this.#card.tagName === "A") !== cardLink
|
|
333
362
|
) {
|
|
334
|
-
const next =
|
|
363
|
+
const next = cardLink
|
|
335
364
|
? h("a", { class: "card", part: "card" })
|
|
336
365
|
: h("section", { class: "card", part: "card" });
|
|
337
366
|
|
|
@@ -342,11 +371,20 @@ export class GwCard extends GwElement {
|
|
|
342
371
|
|
|
343
372
|
if (this.#card instanceof HTMLAnchorElement) this.#card.href = this.href;
|
|
344
373
|
|
|
374
|
+
setAttribute(
|
|
375
|
+
this.#titleAnchor,
|
|
376
|
+
"href",
|
|
377
|
+
this.titleLink && this.href ? this.href : null,
|
|
378
|
+
);
|
|
379
|
+
|
|
345
380
|
setAttribute(this.#card, "aria-busy", this.loading ? "true" : null);
|
|
346
381
|
|
|
347
382
|
const slotted = this.querySelector(":scope > [slot='heading']") !== null;
|
|
348
383
|
|
|
349
|
-
this.#card.classList.toggle(
|
|
384
|
+
this.#card.classList.toggle(
|
|
385
|
+
"linked",
|
|
386
|
+
this.#link() !== null && !this.href && !this.titleLink,
|
|
387
|
+
);
|
|
350
388
|
this.#title.textContent = this.heading;
|
|
351
389
|
this.#heading.setAttribute("aria-level", String(this.level || 2));
|
|
352
390
|
this.#description.textContent = this.description;
|
package/src/gw-command-menu.ts
CHANGED
|
@@ -23,6 +23,7 @@ const sheetBelow = 600;
|
|
|
23
23
|
* @summary A searchable list of commands on Cmd+K or Ctrl+K.
|
|
24
24
|
*
|
|
25
25
|
* @attr {OptionItem[]} options - The commands, as JSON.
|
|
26
|
+
* @attr {string} value - The current command, such as the page you're on. It's marked, and selected and scrolled into view each time the menu opens.
|
|
26
27
|
* @attr {string} label - The accessible name. Defaults to `Commands`.
|
|
27
28
|
* @attr {string} placeholder - The search placeholder. Defaults to `Search commands`.
|
|
28
29
|
* @attr {string} shortcut - The key that opens it with Cmd or Ctrl, such as `mod+k`, or `none`. Defaults to `mod+k`.
|
|
@@ -37,6 +38,7 @@ const sheetBelow = 600;
|
|
|
37
38
|
export class GwCommandMenu extends GwElement {
|
|
38
39
|
static override properties = {
|
|
39
40
|
options: { type: "json" },
|
|
41
|
+
value: {},
|
|
40
42
|
label: {},
|
|
41
43
|
placeholder: {},
|
|
42
44
|
shortcut: {},
|
|
@@ -154,6 +156,8 @@ export class GwCommandMenu extends GwElement {
|
|
|
154
156
|
];
|
|
155
157
|
|
|
156
158
|
declare options: readonly OptionItem[];
|
|
159
|
+
/** The current command, marked and selected when the menu opens. */
|
|
160
|
+
declare value: string;
|
|
157
161
|
declare label: string;
|
|
158
162
|
declare placeholder: string;
|
|
159
163
|
/** `mod+k` (the default) opens it on Cmd+K or Ctrl+K; `none` turns that off. */
|
|
@@ -178,6 +182,7 @@ export class GwCommandMenu extends GwElement {
|
|
|
178
182
|
constructor() {
|
|
179
183
|
super();
|
|
180
184
|
this.options = [];
|
|
185
|
+
this.value = "";
|
|
181
186
|
this.label = "Commands";
|
|
182
187
|
this.placeholder = "Search commands";
|
|
183
188
|
this.shortcut = "mod+k";
|
|
@@ -268,6 +273,7 @@ export class GwCommandMenu extends GwElement {
|
|
|
268
273
|
const dialog = this.#dialog;
|
|
269
274
|
|
|
270
275
|
list.options = Array.isArray(this.options) ? this.options : [];
|
|
276
|
+
list.value = this.value;
|
|
271
277
|
list.label = this.label;
|
|
272
278
|
list.placeholder = this.placeholder;
|
|
273
279
|
dialog.setAttribute("aria-label", this.label);
|
package/src/gw-notification.ts
CHANGED
|
@@ -66,7 +66,7 @@ export class GwNotification extends GwElement {
|
|
|
66
66
|
color: var(--gw-color-text-primary);
|
|
67
67
|
background: var(--gw-color-surface-raised);
|
|
68
68
|
border: var(--gw-border-width) solid var(--gw-color-border-quiet);
|
|
69
|
-
border-radius: var(--gw-radius-control);
|
|
69
|
+
border-radius: min(var(--gw-radius-control), var(--gw-radius-panel));
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
/* An inset stripe, so unread and read cards line up */
|
package/src/gw-option-list.ts
CHANGED
|
@@ -557,8 +557,10 @@ export class GwOptionList extends GwElement {
|
|
|
557
557
|
const headed =
|
|
558
558
|
previous?.kind === "group" ? (this.#tops[position - 1] ?? top) : top;
|
|
559
559
|
|
|
560
|
+
// A third of the way down, so what's above it shows too without
|
|
561
|
+
// the option sitting at either edge
|
|
560
562
|
if (center) {
|
|
561
|
-
listbox.scrollTop = Math.max(0, top - listbox.clientHeight /
|
|
563
|
+
listbox.scrollTop = Math.max(0, top - listbox.clientHeight / 3);
|
|
562
564
|
} else if (headed - listPadding < listbox.scrollTop) {
|
|
563
565
|
listbox.scrollTop = Math.max(0, headed - listPadding);
|
|
564
566
|
} else if (
|
package/src/gw-theme-picker.ts
CHANGED
|
@@ -472,6 +472,15 @@ export class GwThemePicker extends GwElement {
|
|
|
472
472
|
this.#button.addEventListener("click", () => {
|
|
473
473
|
this.show();
|
|
474
474
|
});
|
|
475
|
+
|
|
476
|
+
// A theme or mode applies at once, so it isn't an edit for the popover
|
|
477
|
+
// to ask about discarding, and a click outside still closes it
|
|
478
|
+
for (const type of ["input", "change"]) {
|
|
479
|
+
this.#controls.addEventListener(type, (event) => {
|
|
480
|
+
if (event.target !== this.#controls) event.stopPropagation();
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
|
|
475
484
|
this.#mode.addEventListener("change", (event) => {
|
|
476
485
|
event.stopPropagation();
|
|
477
486
|
this.mode = this.#mode.value;
|
package/src/gw-toast.ts
CHANGED
|
@@ -71,7 +71,7 @@ export class GwToaster extends GwElement {
|
|
|
71
71
|
border: var(--gw-border-width) solid var(--gw-color-border-normal);
|
|
72
72
|
border-inline-start: calc(var(--gw-border-width) * 4) solid
|
|
73
73
|
var(--gw-toast-tone);
|
|
74
|
-
border-radius: var(--gw-radius-control);
|
|
74
|
+
border-radius: min(var(--gw-radius-control), var(--gw-radius-panel));
|
|
75
75
|
box-shadow: var(--gw-shadow-m);
|
|
76
76
|
}
|
|
77
77
|
`,
|