@timmo001/groundwork-ui 0.9.6 → 0.9.8

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.
@@ -1076,7 +1076,7 @@
1076
1076
  "text": "readonly CSSStyleSheet[]"
1077
1077
  },
1078
1078
  "static": true,
1079
- "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\"]) { 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); } `, ]",
1079
+ "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); } `, ]",
1080
1080
  "inheritedFrom": {
1081
1081
  "name": "GwElement",
1082
1082
  "module": "src/element.ts"
@@ -1118,6 +1118,12 @@
1118
1118
  "privacy": "private",
1119
1119
  "readonly": true
1120
1120
  },
1121
+ {
1122
+ "kind": "field",
1123
+ "name": "#icon",
1124
+ "privacy": "private",
1125
+ "readonly": true
1126
+ },
1121
1127
  {
1122
1128
  "kind": "method",
1123
1129
  "name": "create",
@@ -10368,7 +10374,7 @@
10368
10374
  "text": "Properties"
10369
10375
  },
10370
10376
  "static": true,
10371
- "default": "{ label: {}, heading: {}, icon: {}, empty: {}, items: { type: \"json\" }, actions: { type: \"json\" }, size: { reflect: true }, active: { type: \"boolean\", reflect: true }, labels: { reflect: true }, }",
10377
+ "default": "{ label: {}, heading: {}, icon: {}, empty: {}, items: { type: \"json\" }, actions: { type: \"json\" }, size: { reflect: true }, appearance: { reflect: true }, active: { type: \"boolean\", reflect: true }, labels: { reflect: true }, }",
10372
10378
  "inheritedFrom": {
10373
10379
  "name": "GwElement",
10374
10380
  "module": "src/element.ts"
@@ -10381,7 +10387,7 @@
10381
10387
  "text": "readonly CSSStyleSheet[]"
10382
10388
  },
10383
10389
  "static": true,
10384
- "default": "[ base, controlSizes(\"menu-button\"), css` :host { position: relative; display: inline-block; anchor-scope: --gw-menu; } .trigger { --gw-size: var(--gw-menu-button-scale, 1); --gw-scale: calc(var(--gw-size) * var(--gw-control-scale, 1)); --gw-icon-size: calc(1.25rem * var(--gw-scale)); display: inline-flex; gap: calc(var(--gw-space-2) * var(--gw-size)); align-items: center; box-sizing: border-box; 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); color: var(--gw-color-text-strong); cursor: pointer; background: var(--gw-color-fill-neutral-resting); border: var(--gw-border-width) solid var(--gw-border-color); border-radius: var(--gw-radius-control); transition: background-color var(--gw-motion-fast) var(--gw-motion-easing); anchor-name: --gw-menu; } .trigger:hover { background: var(--gw-color-fill-neutral-hovered); } :host([active]) .trigger { color: var(--gw-color-accent); border-color: var(--gw-color-accent); } /* Icon only, square, with the text kept for assistive technology */ :host([labels=\"hide\"]) .trigger.has-icon { padding: 0 calc(var(--gw-space-2) * var(--gw-size)); } :host([labels=\"hide\"]) .has-icon .label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; } @media (width < 40rem) { :host([labels=\"auto\"]) .trigger.has-icon { padding: 0 calc(var(--gw-space-2) * var(--gw-size)); } :host([labels=\"auto\"]) .has-icon .label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; } } .chevron { width: 0.4rem; height: 0.4rem; margin-inline-start: var(--gw-space-1); border-inline-end: 1.5px solid currentColor; border-block-end: 1.5px solid currentColor; rotate: 45deg; translate: 0 -0.125rem; transition: rotate var(--gw-motion-normal) var(--gw-motion-easing), translate var(--gw-motion-normal) var(--gw-motion-easing); } .trigger[aria-expanded=\"true\"] .chevron { rotate: 225deg; translate: 0 0.125rem; } [popover] { position-anchor: --gw-menu; position-try-fallbacks: flip-block, flip-inline; inset: auto; top: anchor(bottom); left: anchor(left); box-sizing: border-box; min-width: 15rem; max-height: min(24rem, 60vh); padding: 0; margin: var(--gw-space-1) 0 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-l); box-shadow: var(--gw-shadow-m); opacity: 0; translate: 0 -0.25rem; transition: opacity var(--gw-motion-fast) 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; } [popover]:popover-open { display: flex; flex-direction: column; opacity: 1; translate: 0 0; } @starting-style { [popover]:popover-open { opacity: 0; translate: 0 -0.25rem; } } /* The items scroll; the actions stay put below them, so \"Add\" is always in reach rather than at the end of a long list */ .items, .actions { display: flex; flex-direction: column; gap: var(--gw-space-0-5); padding: var(--gw-space-1); } .items { flex: 1; min-height: 0; overflow-y: auto; } .actions { border-block-start: max(var(--gw-border-width), 1px) solid var(--gw-color-border-normal); } .empty { padding: var(--gw-space-3); margin: 0; font-size: var(--gw-font-size-s); color: var(--gw-color-text-secondary); } .item { display: flex; gap: var(--gw-space-3); align-items: center; box-sizing: border-box; min-height: 2.5rem; padding: var(--gw-space-2) var(--gw-space-3); font: inherit; font-size: var(--gw-font-size-s); color: var(--gw-color-text-primary); text-align: start; cursor: pointer; background: transparent; border: 0; border-radius: var(--gw-radius-m); transition: background-color var(--gw-motion-fast) var(--gw-motion-easing); --gw-icon-size: 1.125rem; } .item:hover, .item:focus-visible { background: var(--gw-color-fill-neutral-hovered); outline: none; } .item:focus-visible { box-shadow: inset 0 0 0 var(--gw-focus-width) var(--gw-color-focus); } .item:disabled { color: var(--gw-color-text-disabled); cursor: not-allowed; background: transparent; } .action { font-weight: var(--gw-font-weight-strong); color: var(--gw-color-accent); } /* Holds the tick's place on every choice, so the labels line up */ .tick { flex: none; width: var(--gw-icon-size); height: var(--gw-icon-size); color: var(--gw-color-accent); } .item[aria-checked=\"false\"] .tick { visibility: hidden; } .separator { flex: none; height: 0; margin: var(--gw-space-0-5) calc(-1 * var(--gw-space-1)); border: 0; border-block-start: max(var(--gw-border-width), 1px) solid var(--gw-color-border-normal); } .text { display: flex; flex-direction: column; gap: var(--gw-space-0-5); } .description { font-size: var(--gw-font-size-xs); color: var(--gw-color-text-secondary); } `, ]",
10390
+ "default": "[ base, controlSizes(\"menu-button\"), css` :host { position: relative; display: inline-block; anchor-scope: --gw-menu; } .trigger { --gw-size: var(--gw-menu-button-scale, 1); --gw-scale: calc(var(--gw-size) * var(--gw-control-scale, 1)); --gw-icon-size: calc(1.25rem * var(--gw-scale)); display: inline-flex; gap: calc(var(--gw-space-2) * var(--gw-size)); align-items: center; box-sizing: border-box; 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); color: var(--gw-color-text-strong); cursor: pointer; background: var(--gw-color-fill-neutral-resting); border: var(--gw-border-width) solid var(--gw-border-color); border-radius: var(--gw-radius-control); transition: background-color var(--gw-motion-fast) var(--gw-motion-easing); anchor-name: --gw-menu; } .trigger:hover { background: var(--gw-color-fill-neutral-hovered); } /* The other appearances draw the trigger as gw-button draws a neutral one, a pill, so it sits in a row of buttons without a seam */ :host([appearance=\"accent\"]) .trigger, :host([appearance=\"outlined\"]) .trigger, :host([appearance=\"plain\"]) .trigger { 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); } :host([appearance=\"outlined\"]) .trigger { border-color: var(--gw-color-text-secondary); } :host([appearance=\"outlined\"]) .trigger:hover, :host([appearance=\"plain\"]) .trigger:hover { background: color-mix( in oklch, var(--gw-color-text-secondary) 16%, transparent ); } /* A solid fill, with text that flips between black and white by the fill's lightness, as gw-button's accent does */ :host([appearance=\"accent\"]) .trigger { color: oklch( from var(--gw-color-accent) clamp(0, (0.66 - l) * 1000, 1) 0 0 ); background: var(--gw-color-accent); } :host([appearance=\"accent\"]) .trigger:hover { background: oklch( from var(--gw-color-accent) calc(l + (0.6 - l) * 0.2) c h ); } :host([active]:not([appearance=\"accent\"])) .trigger { color: var(--gw-color-accent); border-color: var(--gw-color-accent); } /* Icon only, square, with the text kept for assistive technology */ :host([labels=\"hide\"]) .trigger.has-icon { padding: 0 calc(var(--gw-space-2) * var(--gw-size)); } :host([labels=\"hide\"]) .has-icon .label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; } @media (width < 40rem) { :host([labels=\"auto\"]) .trigger.has-icon { padding: 0 calc(var(--gw-space-2) * var(--gw-size)); } :host([labels=\"auto\"]) .has-icon .label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; } } .chevron { width: 0.4rem; height: 0.4rem; margin-inline-start: var(--gw-space-1); border-inline-end: 1.5px solid currentColor; border-block-end: 1.5px solid currentColor; rotate: 45deg; translate: 0 -0.125rem; transition: rotate var(--gw-motion-normal) var(--gw-motion-easing), translate var(--gw-motion-normal) var(--gw-motion-easing); } .trigger[aria-expanded=\"true\"] .chevron { rotate: 225deg; translate: 0 0.125rem; } [popover] { position-anchor: --gw-menu; position-try-fallbacks: flip-block, flip-inline; inset: auto; top: anchor(bottom); left: anchor(left); box-sizing: border-box; min-width: 15rem; max-height: min(24rem, 60vh); padding: 0; margin: var(--gw-space-1) 0 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-l); box-shadow: var(--gw-shadow-m); opacity: 0; translate: 0 -0.25rem; transition: opacity var(--gw-motion-fast) 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; } [popover]:popover-open { display: flex; flex-direction: column; opacity: 1; translate: 0 0; } @starting-style { [popover]:popover-open { opacity: 0; translate: 0 -0.25rem; } } /* The items scroll; the actions stay put below them, so \"Add\" is always in reach rather than at the end of a long list */ .items, .actions { display: flex; flex-direction: column; gap: var(--gw-space-0-5); padding: var(--gw-space-1); } .items { flex: 1; min-height: 0; overflow-y: auto; } .actions { border-block-start: max(var(--gw-border-width), 1px) solid var(--gw-color-border-normal); } .empty { padding: var(--gw-space-3); margin: 0; font-size: var(--gw-font-size-s); color: var(--gw-color-text-secondary); } .item { display: flex; gap: var(--gw-space-3); align-items: center; box-sizing: border-box; min-height: 2.5rem; padding: var(--gw-space-2) var(--gw-space-3); font: inherit; font-size: var(--gw-font-size-s); color: var(--gw-color-text-primary); text-align: start; cursor: pointer; background: transparent; border: 0; border-radius: var(--gw-radius-m); transition: background-color var(--gw-motion-fast) var(--gw-motion-easing); --gw-icon-size: 1.125rem; } .item:hover, .item:focus-visible { background: var(--gw-color-fill-neutral-hovered); outline: none; } .item:focus-visible { box-shadow: inset 0 0 0 var(--gw-focus-width) var(--gw-color-focus); } .item:disabled { color: var(--gw-color-text-disabled); cursor: not-allowed; background: transparent; } .action { font-weight: var(--gw-font-weight-strong); color: var(--gw-color-accent); } /* Holds the tick's place on every choice, so the labels line up */ .tick { flex: none; width: var(--gw-icon-size); height: var(--gw-icon-size); color: var(--gw-color-accent); } .item[aria-checked=\"false\"] .tick { visibility: hidden; } .separator { flex: none; height: 0; margin: var(--gw-space-0-5) calc(-1 * var(--gw-space-1)); border: 0; border-block-start: max(var(--gw-border-width), 1px) solid var(--gw-color-border-normal); } .text { display: flex; flex-direction: column; gap: var(--gw-space-0-5); } .description { font-size: var(--gw-font-size-xs); color: var(--gw-color-text-secondary); } `, ]",
10385
10391
  "inheritedFrom": {
10386
10392
  "name": "GwElement",
10387
10393
  "module": "src/element.ts"
@@ -10446,6 +10452,15 @@
10446
10452
  },
10447
10453
  "default": "\"medium\""
10448
10454
  },
10455
+ {
10456
+ "kind": "field",
10457
+ "name": "appearance",
10458
+ "type": {
10459
+ "text": "\"accent\" | \"filled\" | \"outlined\" | \"plain\""
10460
+ },
10461
+ "description": "How the trigger is drawn: a neutral fill, or as a neutral `gw-button` of that appearance.",
10462
+ "default": "\"filled\""
10463
+ },
10449
10464
  {
10450
10465
  "kind": "field",
10451
10466
  "name": "active",
@@ -10939,6 +10954,13 @@
10939
10954
  "description": "The trigger's size, 24 to 56px tall. Defaults to `medium`.",
10940
10955
  "name": "size"
10941
10956
  },
10957
+ {
10958
+ "type": {
10959
+ "text": "\"accent\"|\"filled\"|\"outlined\"|\"plain\""
10960
+ },
10961
+ "description": "How the trigger is drawn: `filled` is a neutral fill with a border, and the others match a neutral `gw-button` of that appearance, so it sits in a row of them. Defaults to `filled`.",
10962
+ "name": "appearance"
10963
+ },
10942
10964
  {
10943
10965
  "type": {
10944
10966
  "text": "boolean"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@timmo001/groundwork-ui",
3
- "version": "0.9.6",
3
+ "version": "0.9.8",
4
4
  "description": "Groundwork's framework-free web components, styled by the --gw-* tokens",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
package/src/gw-alert.ts CHANGED
@@ -5,7 +5,24 @@
5
5
  * @module
6
6
  */
7
7
  import { GwElement, css, h } from "./element.js";
8
- import { base, type Tone } from "./styles.js";
8
+ import { base, createIcon, setIconPath, type Tone } from "./styles.js";
9
+
10
+ // mdi's outlined information, check, alert and alert-decagram icons
11
+ const information =
12
+ "M11,9H13V7H11M12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M11,17H13V11H11V17Z";
13
+
14
+ const toneIcons: Readonly<Record<Tone, string>> = {
15
+ neutral: information,
16
+ accent: information,
17
+ info: information,
18
+ success:
19
+ "M12 2C6.5 2 2 6.5 2 12S6.5 22 12 22 22 17.5 22 12 17.5 2 12 2M12 20C7.59 20 4 16.41 4 12S7.59 4 12 4 20 7.59 20 12 16.41 20 12 20M16.59 7.58L10 14.17L7.41 11.59L6 13L10 17L18 9L16.59 7.58Z",
20
+ warning: "M12,2L1,21H23M12,6L19.53,19H4.47M11,10V14H13V10M11,16V18H13V16",
21
+ danger:
22
+ "M11,15H13V17H11V15M11,7H13V13H11V7M12,2C6.47,2 2,6.5 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M12,20A8,8 0 0,1 4,12A8,8 0 0,1 12,4A8,8 0 0,1 20,12A8,8 0 0,1 12,20Z",
23
+ important:
24
+ "M23,12L20.56,14.78L20.9,18.46L17.29,19.28L15.4,22.46L12,21L8.6,22.47L6.71,19.29L3.1,18.47L3.44,14.78L1,12L3.44,9.21L3.1,5.53L6.71,4.72L8.6,1.54L12,3L15.4,1.54L17.29,4.72L20.9,5.54L20.56,9.22L23,12M20.33,12L18.5,9.89L18.74,7.1L16,6.5L14.58,4.07L12,5.18L9.42,4.07L8,6.5L5.26,7.09L5.5,9.88L3.67,12L5.5,14.1L5.26,16.9L8,17.5L9.42,19.93L12,18.81L14.58,19.92L16,17.5L18.74,16.89L18.5,14.1L20.33,12M11,15H13V17H11V15M11,7H13V13H11V7",
25
+ };
9
26
 
10
27
  /**
11
28
  * A message in the flow of the page. `urgent` announces it at once, for
@@ -64,7 +81,9 @@ export class GwAlert extends GwElement {
64
81
  align-self: center;
65
82
  }
66
83
 
67
- ::slotted([slot="icon"]) {
84
+ ::slotted([slot="icon"]),
85
+ .icon {
86
+ flex: none;
68
87
  color: var(--gw-tone, var(--gw-color-info));
69
88
  }
70
89
 
@@ -89,6 +108,9 @@ export class GwAlert extends GwElement {
89
108
 
90
109
  readonly #heading = h("strong");
91
110
 
111
+ // The tone's icon, shown until an icon is slotted in its place
112
+ readonly #icon = createIcon("");
113
+
92
114
  constructor() {
93
115
  super();
94
116
  this.tone = "info";
@@ -98,7 +120,7 @@ export class GwAlert extends GwElement {
98
120
 
99
121
  protected override create(root: ShadowRoot) {
100
122
  this.#alert.append(
101
- h("slot", { name: "icon" }),
123
+ h("slot", { name: "icon" }, this.#icon),
102
124
  h("div", { class: "body" }, this.#heading, h("slot")),
103
125
  h("slot", { name: "actions" }),
104
126
  );
@@ -107,6 +129,7 @@ export class GwAlert extends GwElement {
107
129
 
108
130
  protected override update() {
109
131
  this.#alert.setAttribute("role", this.urgent ? "alert" : "status");
132
+ setIconPath(this.#icon, toneIcons[this.tone] ?? information);
110
133
  this.#heading.textContent = this.heading;
111
134
  this.#heading.hidden = !this.heading;
112
135
  }
@@ -53,6 +53,7 @@ const tick = "M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z";
53
53
  * @attr {MenuItem[]} items - The items, as JSON.
54
54
  * @attr {MenuItem[]} actions - Actions pinned under the items, as JSON.
55
55
  * @attr {"xs"|"small"|"medium"|"large"|"xl"} size - The trigger's size, 24 to 56px tall. Defaults to `medium`.
56
+ * @attr {"accent"|"filled"|"outlined"|"plain"} appearance - How the trigger is drawn: `filled` is a neutral fill with a border, and the others match a neutral `gw-button` of that appearance, so it sits in a row of them. Defaults to `filled`.
56
57
  * @attr {boolean} active - Marks the trigger as set, such as a grouping that's on, with an accent border and text.
57
58
  * @attr {"show"|"hide"|"auto"} labels - Whether the trigger's text shows beside its icon: always, never, or not on narrow screens. Defaults to `show`.
58
59
  *
@@ -72,6 +73,7 @@ export class GwMenuButton extends GwElement {
72
73
  items: { type: "json" },
73
74
  actions: { type: "json" },
74
75
  size: { reflect: true },
76
+ appearance: { reflect: true },
75
77
  active: { type: "boolean", reflect: true },
76
78
  labels: { reflect: true },
77
79
  } as const;
@@ -114,7 +116,49 @@ export class GwMenuButton extends GwElement {
114
116
  background: var(--gw-color-fill-neutral-hovered);
115
117
  }
116
118
 
117
- :host([active]) .trigger {
119
+ /* The other appearances draw the trigger as gw-button draws a neutral
120
+ one, a pill, so it sits in a row of buttons without a seam */
121
+ :host([appearance="accent"]) .trigger,
122
+ :host([appearance="outlined"]) .trigger,
123
+ :host([appearance="plain"]) .trigger {
124
+ background: transparent;
125
+ border: max(var(--gw-border-width), 1px) solid transparent;
126
+ border-radius: var(--gw-radius-pill);
127
+ transition:
128
+ background-color var(--gw-motion-fast) var(--gw-motion-easing),
129
+ border-color var(--gw-motion-fast) var(--gw-motion-easing),
130
+ color var(--gw-motion-fast) var(--gw-motion-easing);
131
+ }
132
+
133
+ :host([appearance="outlined"]) .trigger {
134
+ border-color: var(--gw-color-text-secondary);
135
+ }
136
+
137
+ :host([appearance="outlined"]) .trigger:hover,
138
+ :host([appearance="plain"]) .trigger:hover {
139
+ background: color-mix(
140
+ in oklch,
141
+ var(--gw-color-text-secondary) 16%,
142
+ transparent
143
+ );
144
+ }
145
+
146
+ /* A solid fill, with text that flips between black and white by the
147
+ fill's lightness, as gw-button's accent does */
148
+ :host([appearance="accent"]) .trigger {
149
+ color: oklch(
150
+ from var(--gw-color-accent) clamp(0, (0.66 - l) * 1000, 1) 0 0
151
+ );
152
+ background: var(--gw-color-accent);
153
+ }
154
+
155
+ :host([appearance="accent"]) .trigger:hover {
156
+ background: oklch(
157
+ from var(--gw-color-accent) calc(l + (0.6 - l) * 0.2) c h
158
+ );
159
+ }
160
+
161
+ :host([active]:not([appearance="accent"])) .trigger {
118
162
  color: var(--gw-color-accent);
119
163
  border-color: var(--gw-color-accent);
120
164
  }
@@ -320,6 +364,8 @@ export class GwMenuButton extends GwElement {
320
364
  declare items: readonly MenuItem[];
321
365
  declare actions: readonly MenuItem[];
322
366
  declare size: "xs" | "small" | "medium" | "large" | "xl";
367
+ /** How the trigger is drawn: a neutral fill, or as a neutral `gw-button` of that appearance. */
368
+ declare appearance: "accent" | "filled" | "outlined" | "plain";
323
369
  /** Marks the trigger as set, such as a grouping that's on. */
324
370
  declare active: boolean;
325
371
  /** Whether the trigger's text shows beside its icon: always, never, or not on narrow screens. */
@@ -366,6 +412,7 @@ export class GwMenuButton extends GwElement {
366
412
  this.items = [];
367
413
  this.actions = [];
368
414
  this.size = "medium";
415
+ this.appearance = "filled";
369
416
  this.active = false;
370
417
  this.labels = "show";
371
418
  }