use-wc 1.0.0-pre.46 → 1.0.0-pre.48

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.
@@ -1454,7 +1454,7 @@
1454
1454
  "declarations": [
1455
1455
  {
1456
1456
  "kind": "class",
1457
- "description": "When the popover is opened the tabbable elements are found and indexed for\nkeyboard navigation. The first tabbable element is focused when the popover is opened. The\nfollowing selector is used to find tabbable elements:\n\n```css\n:is(\n [role=\"menuitem\"],\n [role=\"menuitemcheckbox\"],\n [role=\"menuitemradio\"],\n use-menu\n):not(:is(\n [disabled],\n [hidden],\n [inert],\n [aria-hidden=\"true\"]\n))\n```\n\nMenu items are not used for navigation, they are intended for related action\nitems that allows a user to manipulate a user interface or content. Read the\nWCAG guidance for more details:\n[https://www.w3.org/WAI/ARIA/apg/patterns/menubar/](https://www.w3.org/WAI/ARIA/apg/patterns/menubar/)",
1457
+ "description": "When the popover is opened the tabbable elements are found and indexed for\nkeyboard navigation. The first tabbable element is focused when the popover is opened. The\nfollowing selector is used to find tabbable elements:\n\n```css\n:is(\n [role=\"menuitem\"],\n [role=\"menuitemcheckbox\"],\n [role=\"menuitemradio\"],\n use-menu\n):not(:is(\n [disabled],\n [hidden],\n [inert],\n [aria-hidden=\"true\"]\n))\n```\n\nMenu items are not used for navigation, they are intended for related action\nitems that allows a user to manipulate a user interface or content. Read the\nWCAG guidance for more details:\n[https://www.w3.org/WAI/ARIA/apg/patterns/menubar/](https://www.w3.org/WAI/ARIA/apg/patterns/menubar/)\n\nFor an icon-only trigger, omit `label` and set `aria-label` on `use-dropdown` itself — it is\nforwarded to the trigger button so the control still has an accessible name.",
1458
1458
  "name": "UseDropdown",
1459
1459
  "slots": [
1460
1460
  {
@@ -1492,12 +1492,32 @@
1492
1492
  },
1493
1493
  "attribute": "label"
1494
1494
  },
1495
+ {
1496
+ "kind": "field",
1497
+ "name": "inlinealign",
1498
+ "type": {
1499
+ "text": "\"start\" | \"end\""
1500
+ },
1501
+ "default": "\"start\"",
1502
+ "description": "Aligns the menu along the inline axis relative to the trigger. Applies to top-level\nmenus; nested submenus are always positioned to the side of their parent trigger.\n\n- `start`: the menu's inline-start edge aligns with the trigger's inline-start edge\n- `end`: the menu's inline-end edge aligns with the trigger's inline-end edge",
1503
+ "attribute": "inlinealign",
1504
+ "reflects": true
1505
+ },
1495
1506
  {
1496
1507
  "kind": "method",
1497
1508
  "name": "getId"
1498
1509
  }
1499
1510
  ],
1500
1511
  "attributes": [
1512
+ {
1513
+ "description": "Aligns the menu along the inline axis relative to the trigger. Applies to top-level\nmenus; nested submenus are always positioned to the side of their parent trigger.\n\n- `start`: the menu's inline-start edge aligns with the trigger's inline-start edge\n- `end`: the menu's inline-end edge aligns with the trigger's inline-end edge",
1514
+ "name": "inlinealign",
1515
+ "type": {
1516
+ "text": "\"start\" | \"end\""
1517
+ },
1518
+ "default": "\"start\"",
1519
+ "fieldName": "inlinealign"
1520
+ },
1501
1521
  {
1502
1522
  "name": "disabled",
1503
1523
  "fieldName": "disabled"
@@ -266,6 +266,12 @@
266
266
  var(--usewc-color-button-border-static);
267
267
  }
268
268
 
269
+ &::part(trigger) {
270
+ padding-inline-end: calc(
271
+ var(--usewc-layout-button-padding-inline) - var(--usewc-layout-dropdown-trigger-icon-size) / 4
272
+ );
273
+ }
274
+
269
275
  &:is(use-dropdown) {
270
276
  display: contents;
271
277
  }
@@ -655,21 +661,13 @@
655
661
  }
656
662
  }
657
663
 
658
- select:not(.appearance-native),
659
- use-dropdown::part(trigger),
660
- use-dropdown use-dropdown::part(trigger) {
664
+ select:not(.appearance-native) {
661
665
  padding-inline-end: calc(var(--usewc-layout-input-padding-inline) * 2 + var(--usewc-layout-selector-width));
662
- background-image: var(--usewc-effect-dropdown-trigger-background-image, none);
666
+ background-image: var(--usewc-effect-select-trigger-background-image, none);
663
667
  /* TODO use logical position */
664
668
  background-position: right var(--usewc-layout-input-padding-inline) center;
665
669
  background-repeat: no-repeat;
666
- background-size: var(--usewc-effect-dropdown-trigger-background-size, 1em);
667
- background-blend-mode: var(--usewc-effect-dropdown-trigger-background-blend-mode, none);
668
- }
669
-
670
- use-dropdown use-dropdown::part(trigger) {
671
- background-image: var(--usewc-effect-dropdown-trigger-nested-background-image);
672
- background-position: right center;
670
+ background-size: var(--usewc-effect-select-trigger-background-size, 1em);
673
671
  }
674
672
 
675
673
  select:not(.appearance-native),
@@ -682,11 +680,32 @@
682
680
  anchor-scope: --use-popover-trigger;
683
681
  }
684
682
 
685
- use-dropdown::part(trigger-icon-default),
686
683
  use-option::part(selected-indicator-default) {
687
684
  display: none;
688
685
  }
689
686
 
687
+ use-dropdown::part(trigger-icon-default) {
688
+ display: inline-block;
689
+ overflow: hidden;
690
+ white-space: nowrap;
691
+ text-indent: 100%;
692
+ inline-size: var(--usewc-layout-dropdown-trigger-icon-size);
693
+ block-size: var(--usewc-layout-dropdown-trigger-icon-size);
694
+ background-color: var(--usewc-effect-dropdown-trigger-icon-background-color, currentColor);
695
+ mask-image: var(--usewc-effect-dropdown-trigger-icon-mask-image, none);
696
+ mask-size: contain;
697
+ mask-repeat: no-repeat;
698
+ mask-position: center;
699
+ }
700
+
701
+ use-dropdown use-dropdown::part(trigger-icon-default) {
702
+ mask-image: var(--usewc-effect-dropdown-trigger-icon-nested-mask-image, none);
703
+ }
704
+
705
+ use-dropdown use-dropdown::part(trigger-icon) {
706
+ margin-inline-start: auto;
707
+ }
708
+
690
709
  use-dropdown::part(menu) {
691
710
  --min-size: 30vh;
692
711
  --max-size: 80vh;
@@ -695,10 +714,13 @@
695
714
  height: unset;
696
715
  position-anchor: --use-popover-trigger;
697
716
  position: fixed;
698
- position-area: bottom span-right;
717
+ position-area: block-end span-inline-end;
699
718
  min-block-size: var(--min-size);
700
719
  max-block-size: min(100% - var(--usewc-layout-popover-menu-anchor-offset), var(--max-size));
701
- position-try: flip-block;
720
+ position-try:
721
+ flip-block,
722
+ flip-inline,
723
+ flip-inline flip-block;
702
724
  margin-block: var(--usewc-layout-popover-menu-anchor-offset);
703
725
  overflow: auto;
704
726
  border: var(--usewc-layout-popover-menu-border) var(--usewc-effect-popover-menu-border-style)
@@ -713,6 +735,10 @@
713
735
  }
714
736
  }
715
737
 
738
+ use-dropdown[inlinealign="end"]::part(menu) {
739
+ position-area: block-end span-inline-start;
740
+ }
741
+
716
742
  use-option,
717
743
  use-dropdown :is([role="menuitem"], [role="menuitemcheckbox"], [role="menuitemradio"]),
718
744
  use-dropdown use-dropdown::part(trigger) {
@@ -795,6 +821,12 @@
795
821
  }
796
822
 
797
823
  use-dropdown use-dropdown::part(menu) {
824
+ /*
825
+ * !important: this must win over use-dropdown[inlinealign="end"]::part(menu) above, which
826
+ * has higher specificity (an attribute selector) than this descendant selector does. Nested
827
+ * submenus always position to the side of their parent trigger, independent of inlinealign.
828
+ */
829
+ position-area: block-end span-inline-end !important;
798
830
  inset-inline-start: calc(anchor(end) + var(--usewc-layout-popover-menu-anchor-offset) * 2);
799
831
  inset-block-start: calc(
800
832
  anchor(start) - var(--usewc-layout-popover-menu-anchor-offset) -
@@ -813,6 +845,5 @@
813
845
  background-position: left var(--usewc-layout-input-padding-inline) center;
814
846
  background-repeat: no-repeat;
815
847
  background-size: var(--usewc-effect-menu-item-checkmark-background-size, 1em);
816
- background-blend-mode: var(--usewc-effect-menu-item-checkmark-background-blend-mode, none);
817
848
  }
818
849
  }
@@ -23,10 +23,18 @@ items that allows a user to manipulate a user interface or content. Read the
23
23
  WCAG guidance for more details:
24
24
  [https://www.w3.org/WAI/ARIA/apg/patterns/menubar/](https://www.w3.org/WAI/ARIA/apg/patterns/menubar/)
25
25
 
26
+ For an icon-only trigger, omit `label` and set `aria-label` on `use-dropdown` itself — it is
27
+ forwarded to the trigger button so the control still has an accessible name.
28
+
26
29
  ## Attributes
27
30
 
28
31
  | Name | Type | Default | Description |
29
32
  | --- | --- | --- | --- |
33
+ | inlinealign | `"start" \| "end"` | `"start"` | Aligns the menu along the inline axis relative to the trigger. Applies to top-level
34
+ menus; nested submenus are always positioned to the side of their parent trigger.
35
+
36
+ - `start`: the menu's inline-start edge aligns with the trigger's inline-start edge
37
+ - `end`: the menu's inline-end edge aligns with the trigger's inline-end edge |
30
38
  | disabled | - | - | - |
31
39
  | label | `string` | - | - |
32
40
 
package/dist/tokens.css CHANGED
@@ -177,13 +177,14 @@
177
177
  --usewc-color-input-segment-background-hover: transparent;
178
178
  --usewc-color-input-segment-background-focus: var(--usewc-color-blue-100);
179
179
  --usewc-color-input-segment-text-focus: var(--usewc-color-gray-700);
180
- --usewc-effect-dropdown-trigger-background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 16L5.0718 8.5L18.9282 8.5L12 16Z' fill='rgba(255,255,255,0.5' /%3E%3C/svg%3E");
181
- --usewc-effect-dropdown-trigger-nested-background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M16 12L8.5 18.9282L8.5 5.0718Z' fill='rgba(255,255,255,0.5' /%3E%3C/svg%3E");
182
- --usewc-effect-dropdown-trigger-background-size: 1em;
183
- --usewc-effect-dropdown-trigger-background-blend-mode: difference;
184
- --usewc-effect-menu-item-checkmark-background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M5 13L10 18L19 7' stroke='rgba(255,255,255,0.5)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C%2Fsvg%3E");
180
+ --usewc-effect-dropdown-trigger-icon-mask-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 16L5.0718 8.5L18.9282 8.5L12 16Z' fill='black' /%3E%3C/svg%3E");
181
+ --usewc-effect-dropdown-trigger-icon-nested-mask-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M16 12L8.5 18.9282L8.5 5.0718Z' fill='black' /%3E%3C/svg%3E");
182
+ --usewc-effect-dropdown-trigger-icon-background-color: color-mix(in oklab, currentColor 50%, transparent);
183
+ --usewc-layout-dropdown-trigger-icon-size: 1em;
184
+ --usewc-effect-select-trigger-background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 16L5.0718 8.5L18.9282 8.5L12 16Z' fill='rgb(55,65,81)' /%3E%3C/svg%3E");
185
+ --usewc-effect-select-trigger-background-size: 1em;
186
+ --usewc-effect-menu-item-checkmark-background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M5 13L10 18L19 7' stroke='rgb(55,65,81)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C%2Fsvg%3E");
185
187
  --usewc-effect-menu-item-checkmark-background-size: 1em;
186
- --usewc-effect-menu-item-checkmark-background-blend-mode: difference;
187
188
  /* - Layout */
188
189
  --usewc-layout-input-border: var(--usewc-space-1-relative);
189
190
  --usewc-layout-input-padding-block: calc(var(--usewc-space-4) - var(--usewc-layout-input-border));
@@ -428,6 +429,8 @@
428
429
  --usewc-color-range-track-border-static: var(--usewc-color-gray-700);
429
430
  --usewc-color-range-track-border-hover: var(--usewc-color-gray-600);
430
431
  --usewc-color-selector-background-hover: oklch(from var(--usewc-color-gray-700) l c h / 0.5);
432
+ --usewc-effect-select-trigger-background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 16L5.0718 8.5L18.9282 8.5L12 16Z' fill='rgb(229,231,235)' /%3E%3C/svg%3E");
433
+ --usewc-effect-menu-item-checkmark-background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M5 13L10 18L19 7' stroke='rgb(229,231,235)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C%2Fsvg%3E");
431
434
  }
432
435
  }
433
436
 
package/dist/use-wc.d.mts CHANGED
@@ -161,12 +161,18 @@ declare global {
161
161
  * WCAG guidance for more details:
162
162
  * [https://www.w3.org/WAI/ARIA/apg/patterns/menubar/](https://www.w3.org/WAI/ARIA/apg/patterns/menubar/)
163
163
  *
164
+ * For an icon-only trigger, omit `label` and set `aria-label` on `use-dropdown` itself — it is
165
+ * forwarded to the trigger button so the control still has an accessible name.
166
+ *
164
167
  * @slot default
165
168
  * @slot trigger-content
166
169
  * @slot trigger-label
167
170
  * @slot trigger-arrow
168
171
  *
169
172
  * @state open `use-dropdown:state(open)`: The open state of the dropdown.
173
+ * @attr inlinealign `"start" | "end"`: Aligns the menu along the inline axis relative to the
174
+ * trigger. Applies to top-level menus only; nested submenus are always positioned to the side
175
+ * of their parent trigger.
170
176
  */
171
177
  declare class UseDropdown extends LitElement {
172
178
  #private;
@@ -182,6 +188,14 @@ declare class UseDropdown extends LitElement {
182
188
  set disabled(flag: boolean);
183
189
  get disabled(): boolean;
184
190
  label: string;
191
+ /**
192
+ * Aligns the menu along the inline axis relative to the trigger. Applies to top-level
193
+ * menus; nested submenus are always positioned to the side of their parent trigger.
194
+ *
195
+ * - `start`: the menu's inline-start edge aligns with the trigger's inline-start edge
196
+ * - `end`: the menu's inline-end edge aligns with the trigger's inline-end edge
197
+ */
198
+ inlinealign: "start" | "end";
185
199
  constructor();
186
200
  getId(): string;
187
201
  firstUpdated(): void;
package/dist/use-wc.mjs CHANGED
@@ -1,5 +1,6 @@
1
1
  import { LitElement, css, html } from "lit";
2
2
  import { customElement, property, query, queryAssignedElements } from "lit/decorators.js";
3
+ import { ifDefined } from "lit/directives/if-defined.js";
3
4
  import { getTabIndex, isTabbable, tabbable } from "tabbable";
4
5
  import * as duration from "duration-fns";
5
6
  import { map } from "lit/directives/map.js";
@@ -523,6 +524,7 @@ let UseDropdown = class UseDropdown extends LitElement {
523
524
  this.#itemLabels = [];
524
525
  this.#isNested = this.parentElement?.closest("use-dropdown") != null;
525
526
  this.trigger = null;
527
+ this.inlinealign = "start";
526
528
  this.#id = createId();
527
529
  this.#internals = this.attachInternals();
528
530
  this.#initializeTabbables();
@@ -537,6 +539,9 @@ let UseDropdown = class UseDropdown extends LitElement {
537
539
  get #popoverId() {
538
540
  return `${this.getId()}-dropdown`;
539
541
  }
542
+ get #triggerAriaLabel() {
543
+ return this.getAttribute("aria-label") ?? void 0;
544
+ }
540
545
  #findTabbables() {
541
546
  return Array.from(this.querySelectorAll(TABBABLE_SELECTOR$1)).filter((element) => {
542
547
  return element.parentElement?.closest("use-dropdown") === this;
@@ -676,6 +681,7 @@ let UseDropdown = class UseDropdown extends LitElement {
676
681
  aria-controls=${this.#popoverId}
677
682
  aria-haspopup="menu"
678
683
  aria-expanded="false"
684
+ aria-label=${ifDefined(this.#triggerAriaLabel)}
679
685
  ?disabled=${this.disabled}
680
686
  @keydown=${this.#handleKeyDown}
681
687
  >
@@ -724,6 +730,10 @@ let UseDropdown = class UseDropdown extends LitElement {
724
730
  };
725
731
  __decorate([property({ type: Boolean })], UseDropdown.prototype, "disabled", null);
726
732
  __decorate([property()], UseDropdown.prototype, "label", void 0);
733
+ __decorate([property({
734
+ type: String,
735
+ reflect: true
736
+ })], UseDropdown.prototype, "inlinealign", void 0);
727
737
  UseDropdown = __decorate([customElement("use-dropdown")], UseDropdown);
728
738
  //#endregion
729
739
  //#region src/elements/use-duration-input/use-duration-input.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "use-wc",
3
- "version": "1.0.0-pre.46",
3
+ "version": "1.0.0-pre.48",
4
4
  "private": false,
5
5
  "homepage": "https://usewc.com",
6
6
  "bugs": "https://github.com/dang-rabbits/use-wc/issues",
@@ -74,8 +74,13 @@
74
74
  },
75
75
  {
76
76
  "name": "use-dropdown",
77
- "description": "When the popover is opened the tabbable elements are found and indexed for\nkeyboard navigation. The first tabbable element is focused when the popover is opened. The\nfollowing selector is used to find tabbable elements:\n\n```css\n:is(\n [role=\"menuitem\"],\n [role=\"menuitemcheckbox\"],\n [role=\"menuitemradio\"],\n use-menu\n):not(:is(\n [disabled],\n [hidden],\n [inert],\n [aria-hidden=\"true\"]\n))\n```\n\nMenu items are not used for navigation, they are intended for related action\nitems that allows a user to manipulate a user interface or content. Read the\nWCAG guidance for more details:\n[https://www.w3.org/WAI/ARIA/apg/patterns/menubar/](https://www.w3.org/WAI/ARIA/apg/patterns/menubar/)\n---\n\n\n### **Slots:**\n - **default** - undefined\n- **trigger-content** - undefined\n- **trigger-label** - undefined\n- **trigger-arrow** - undefined",
77
+ "description": "When the popover is opened the tabbable elements are found and indexed for\nkeyboard navigation. The first tabbable element is focused when the popover is opened. The\nfollowing selector is used to find tabbable elements:\n\n```css\n:is(\n [role=\"menuitem\"],\n [role=\"menuitemcheckbox\"],\n [role=\"menuitemradio\"],\n use-menu\n):not(:is(\n [disabled],\n [hidden],\n [inert],\n [aria-hidden=\"true\"]\n))\n```\n\nMenu items are not used for navigation, they are intended for related action\nitems that allows a user to manipulate a user interface or content. Read the\nWCAG guidance for more details:\n[https://www.w3.org/WAI/ARIA/apg/patterns/menubar/](https://www.w3.org/WAI/ARIA/apg/patterns/menubar/)\n\nFor an icon-only trigger, omit `label` and set `aria-label` on `use-dropdown` itself — it is\nforwarded to the trigger button so the control still has an accessible name.\n---\n\n\n### **Slots:**\n - **default** - undefined\n- **trigger-content** - undefined\n- **trigger-label** - undefined\n- **trigger-arrow** - undefined",
78
78
  "attributes": [
79
+ {
80
+ "name": "inlinealign",
81
+ "description": "Aligns the menu along the inline axis relative to the trigger. Applies to top-level\nmenus; nested submenus are always positioned to the side of their parent trigger.\n\n- `start`: the menu's inline-start edge aligns with the trigger's inline-start edge\n- `end`: the menu's inline-end edge aligns with the trigger's inline-end edge",
82
+ "values": [{ "name": "start" }, { "name": "end" }]
83
+ },
79
84
  { "name": "disabled", "values": [] },
80
85
  { "name": "label", "values": [] }
81
86
  ],