@acusti/dropdown 1.2.1 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +143 -7
- package/dist/Dropdown.d.ts +4 -2
- package/dist/Dropdown.js +350 -364
- package/dist/Dropdown.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -244,6 +244,15 @@ These are _newly available_ Baseline features: they work in up-to-date
|
|
|
244
244
|
browser versions but not in ones predating that support, which the
|
|
245
245
|
component requires.
|
|
246
246
|
|
|
247
|
+
The [trigger chevron](#the-trigger-chevron) also uses `clip-path: shape()`
|
|
248
|
+
([Baseline 2026](https://developer.mozilla.org/en-US/docs/Web/CSS/basic-shape/shape))
|
|
249
|
+
where it’s supported, for a stroke you can set, and falls back to an SVG
|
|
250
|
+
mask at the default stroke where it isn’t. Turning it off with
|
|
251
|
+
`--uktdd-trigger-icon: none` relies on container style queries
|
|
252
|
+
([Baseline 2026](https://developer.mozilla.org/en-US/docs/Web/CSS/@container#container_style_queries));
|
|
253
|
+
without them (Firefox before 151), the chevron is hidden but keeps its
|
|
254
|
+
space.
|
|
255
|
+
|
|
247
256
|
## API Reference
|
|
248
257
|
|
|
249
258
|
### Props
|
|
@@ -371,8 +380,10 @@ type Props = {
|
|
|
371
380
|
/**
|
|
372
381
|
* Called when an item is submitted (click, Enter, or Space). Parent items
|
|
373
382
|
* (submenus) disclose rather than submit, so this fires for leaf items
|
|
374
|
-
* only.
|
|
375
|
-
*
|
|
383
|
+
* only. A submit closes the dropdown 90ms later (unless the root dropdown
|
|
384
|
+
* sets keepOpenOnSubmit), and the dropdown ignores any other submit in
|
|
385
|
+
* that time, so this isn’t called twice for a double press. For a nested
|
|
386
|
+
* (submenu) Dropdown, fires for submissions within its subtree only.
|
|
376
387
|
*/
|
|
377
388
|
onSubmitItem?: (payload: Item) => void;
|
|
378
389
|
/**
|
|
@@ -494,6 +505,17 @@ Typography, sizing, and spacing:
|
|
|
494
505
|
| `--uktdd-submenu-gap` | `0px` (parent item ↔ submenu) |
|
|
495
506
|
| `--uktdd-label-gap` | `0.625em` (`props.label` text ↔ trigger) |
|
|
496
507
|
|
|
508
|
+
The generated trigger’s chevron (see
|
|
509
|
+
[The trigger chevron](#the-trigger-chevron)):
|
|
510
|
+
|
|
511
|
+
| Property | Default |
|
|
512
|
+
| ----------------------------- | -------------------------------- |
|
|
513
|
+
| `--uktdd-trigger-icon` | the built-in chevron (or `none`) |
|
|
514
|
+
| `--uktdd-trigger-icon-size` | `0.7em` (the chevron’s width) |
|
|
515
|
+
| `--uktdd-trigger-icon-stroke` | 2/17 of the size (`≈ 0.08em`) |
|
|
516
|
+
| `--uktdd-trigger-icon-gap` | `0.5em` (trigger text ↔ chevron) |
|
|
517
|
+
| `--uktdd-trigger-icon-rotate` | `0deg` |
|
|
518
|
+
|
|
497
519
|
Placement (see
|
|
498
520
|
[Placement Customization](#placement-customization-with-css-variables) and
|
|
499
521
|
[Submenu placement and styling](#submenu-placement-and-styling)):
|
|
@@ -523,7 +545,7 @@ part of the public API along with the `data-ukt-*` attributes:
|
|
|
523
545
|
- `.uktdropdown` — the root, with the state classes `.is-open`,
|
|
524
546
|
`.is-searchable`, and `.is-disabled`
|
|
525
547
|
- `.uktdropdown-trigger` — the generated trigger (a custom trigger keeps
|
|
526
|
-
its own classes)
|
|
548
|
+
its own classes), whose `::after` is the [chevron](#the-trigger-chevron)
|
|
527
549
|
- `.uktdropdown-label` and `.uktdropdown-label-text` — the wrapper and text
|
|
528
550
|
rendered for `props.label`
|
|
529
551
|
- `.uktdropdown-body` — the anchored popover shell, with `.has-items`
|
|
@@ -536,6 +558,112 @@ part of the public API along with the `data-ukt-*` attributes:
|
|
|
536
558
|
highlight, alongside `aria-expanded` on open parent items and
|
|
537
559
|
`aria-selected` on the selected option)
|
|
538
560
|
|
|
561
|
+
### The trigger chevron
|
|
562
|
+
|
|
563
|
+
The generated button trigger ends with a chevron that marks it as something
|
|
564
|
+
that opens. It’s an `::after` pseudo-element, so it adds no markup and
|
|
565
|
+
leaves the trigger’s accessible name alone, and it’s painted in the
|
|
566
|
+
trigger’s `currentColor`, so it follows the trigger’s text color (including
|
|
567
|
+
its disabled color). A searchable dropdown’s trigger is a text input, which
|
|
568
|
+
can’t have one, and [`Menubar`](#menubar) triggers don’t get one. A custom
|
|
569
|
+
trigger gets one only if it carries the `uktdropdown-trigger` class, since
|
|
570
|
+
the rule matches the class rather than the generated element.
|
|
571
|
+
|
|
572
|
+
The trigger is `white-space: nowrap`, like a native `<select>`, so the
|
|
573
|
+
chevron stays on the line with the label; a label too long for a
|
|
574
|
+
fixed-width trigger overflows it rather than wrapping. To let a long label
|
|
575
|
+
wrap, see the flex recipe at the end of this section.
|
|
576
|
+
|
|
577
|
+
The chevron is drawn with `clip-path: shape()`, so its stroke is a custom
|
|
578
|
+
property: `--uktdd-trigger-icon-stroke` sets it, and by default it stays
|
|
579
|
+
2/17 of `--uktdd-trigger-icon-size`, so resizing the chevron keeps its
|
|
580
|
+
weight in proportion. Browsers without `shape()` (it’s
|
|
581
|
+
[Baseline 2026](https://developer.mozilla.org/en-US/docs/Web/CSS/basic-shape/shape))
|
|
582
|
+
draw the same chevron as an SVG mask instead, at the default proportion,
|
|
583
|
+
ignoring `--uktdd-trigger-icon-stroke`. Its box is square and as wide as
|
|
584
|
+
the visible chevron, so `--uktdd-trigger-icon-size` is the chevron’s width
|
|
585
|
+
and `--uktdd-trigger-icon-gap` is the actual space between it and the text.
|
|
586
|
+
In a flex trigger, that gap adds to the trigger’s own `gap`; set it to `0`
|
|
587
|
+
there.
|
|
588
|
+
|
|
589
|
+
To use your own icon, set `--uktdd-trigger-icon` to an image: an SVG
|
|
590
|
+
`url()` or a gradient, used as a mask so it still takes the trigger’s color
|
|
591
|
+
(`--uktdd-trigger-icon-stroke` doesn’t apply to it). Crop its `viewBox`
|
|
592
|
+
tight to the icon horizontally and keep it square, or built-in side margins
|
|
593
|
+
will make it look smaller and further from the text than the size and gap
|
|
594
|
+
suggest:
|
|
595
|
+
|
|
596
|
+
```css
|
|
597
|
+
.uktdropdown-trigger {
|
|
598
|
+
--uktdd-trigger-icon: url('/icons/my-chevron.svg');
|
|
599
|
+
}
|
|
600
|
+
```
|
|
601
|
+
|
|
602
|
+
A relative `url()` in this property resolves against the page, not your
|
|
603
|
+
stylesheet: the property is substituted in the dropdown’s own stylesheet,
|
|
604
|
+
which is inline. Use a root-relative, absolute or `data:` URL, or, for a
|
|
605
|
+
file next to your stylesheet, set the mask on the `::after` directly:
|
|
606
|
+
|
|
607
|
+
```css
|
|
608
|
+
.uktdropdown-trigger::after {
|
|
609
|
+
clip-path: none;
|
|
610
|
+
mask: url('./my-chevron.svg') center / contain no-repeat;
|
|
611
|
+
}
|
|
612
|
+
```
|
|
613
|
+
|
|
614
|
+
Set `--uktdd-trigger-icon-size` to suit the icon: cropped to its ink, a
|
|
615
|
+
dense icon reads larger than an outlined one at the same size (the
|
|
616
|
+
[`TriggerChevron` story][] uses `1em` for an arrow in a circle and `0.8em`
|
|
617
|
+
for a pointing hand). The box stays centered on the label at any size, but
|
|
618
|
+
the icon’s strokes scale with it, so a much smaller icon needs a heavier
|
|
619
|
+
`stroke-width` in its SVG to keep its weight.
|
|
620
|
+
|
|
621
|
+
[`TriggerChevron` story]:
|
|
622
|
+
https://uikit.acusti.ca/?path=/docs/uikit-controls-Dropdown--docs#trigger-chevron
|
|
623
|
+
|
|
624
|
+
The default rules have the specificity of a bare element, so a class
|
|
625
|
+
selector overrides them regardless of stylesheet order.
|
|
626
|
+
|
|
627
|
+
The chevron is the trigger’s `currentColor`. Setting `color` on the
|
|
628
|
+
`::after` recolors it, but that color then also holds in forced colors
|
|
629
|
+
mode, where the trigger’s own text takes the forced color.
|
|
630
|
+
|
|
631
|
+
To remove the chevron, set `--uktdd-trigger-icon` to `none`, on a class or
|
|
632
|
+
inline through the dropdown’s `style` prop
|
|
633
|
+
(`style={{ '--uktdd-trigger-icon': 'none' }}`):
|
|
634
|
+
|
|
635
|
+
```css
|
|
636
|
+
.my-dropdown {
|
|
637
|
+
--uktdd-trigger-icon: none;
|
|
638
|
+
}
|
|
639
|
+
```
|
|
640
|
+
|
|
641
|
+
This relies on container style queries
|
|
642
|
+
([Baseline 2026](https://developer.mozilla.org/en-US/docs/Web/CSS/@container#container_style_queries)).
|
|
643
|
+
Without them (Firefox before 151), the chevron is hidden but keeps its
|
|
644
|
+
space. `all: revert` on the trigger’s `::after` removes it in every
|
|
645
|
+
browser, and leaves the `::after` free for an indicator of your own.
|
|
646
|
+
|
|
647
|
+
In a full-width trigger, the chevron trails the centered label. To pin it
|
|
648
|
+
to the inline end with the label at the start:
|
|
649
|
+
|
|
650
|
+
```css
|
|
651
|
+
.uktdropdown-trigger {
|
|
652
|
+
display: flex;
|
|
653
|
+
align-items: center;
|
|
654
|
+
gap: var(--uktdd-trigger-icon-gap);
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
.uktdropdown-trigger::after {
|
|
658
|
+
margin-inline-start: auto;
|
|
659
|
+
}
|
|
660
|
+
```
|
|
661
|
+
|
|
662
|
+
The same rule lets a long label wrap while the chevron keeps its own
|
|
663
|
+
column: add `white-space: normal` and `text-align: start`, and use
|
|
664
|
+
`align-items: first baseline` to keep the chevron beside the label’s first
|
|
665
|
+
line.
|
|
666
|
+
|
|
539
667
|
## Usage Examples
|
|
540
668
|
|
|
541
669
|
### Basic List Dropdown
|
|
@@ -763,6 +891,9 @@ Enter in such an input, in the body or the trigger, counts the way a form
|
|
|
763
891
|
would count it: not when a handler has prevented the key, as a combobox
|
|
764
892
|
does to pick an option, and not when it commits an IME composition.
|
|
765
893
|
|
|
894
|
+
The dropdown closes 90ms after a submit and ignores any other submit in
|
|
895
|
+
that time. The form’s own `onSubmit` still runs for every submit.
|
|
896
|
+
|
|
766
897
|
When a submit closes the dropdown while focus is in its body, focus returns
|
|
767
898
|
to the trigger, as it does on Escape.
|
|
768
899
|
|
|
@@ -841,8 +972,9 @@ properties to the corresponding values:
|
|
|
841
972
|
(The `…try-fallback-N` columns are `--uktdd-body-position-try-fallback-1`
|
|
842
973
|
and `-2`.)
|
|
843
974
|
|
|
844
|
-
The two Top rows should also flip the last-resort fill pair to match
|
|
845
|
-
`--uktdd-body-fill-fallbacks: --uktdd-fill-top, --uktdd-fill-bottom
|
|
975
|
+
The two Top rows should also flip the last-resort fill pair to match
|
|
976
|
+
(`--uktdd-body-fill-fallbacks: --uktdd-fill-top, --uktdd-fill-bottom`) and
|
|
977
|
+
turn the trigger chevron up (`--uktdd-trigger-icon-rotate: 180deg`).
|
|
846
978
|
|
|
847
979
|
For example, to make a dropdown open upward and end-aligned (useful for a
|
|
848
980
|
trigger pinned to the bottom of the viewport, near the inline-end edge):
|
|
@@ -853,13 +985,17 @@ trigger pinned to the bottom of the viewport, near the inline-end edge):
|
|
|
853
985
|
--uktdd-body-position-try-fallback-1: --uktdd-bottom-end;
|
|
854
986
|
--uktdd-body-position-try-fallback-2: --uktdd-top-start;
|
|
855
987
|
--uktdd-body-fill-fallbacks: --uktdd-fill-top, --uktdd-fill-bottom;
|
|
988
|
+
--uktdd-trigger-icon-rotate: 180deg;
|
|
856
989
|
}
|
|
857
990
|
```
|
|
858
991
|
|
|
859
|
-
The
|
|
992
|
+
The fill line flips the last-resort fill pair to match the recipe’s
|
|
860
993
|
direction: when the body is too tall to fit anywhere at its natural size,
|
|
861
994
|
it fills and scrolls on the upward side first (more on the fill pair
|
|
862
|
-
below).
|
|
995
|
+
below). The last line turns the [trigger chevron](#the-trigger-chevron) to
|
|
996
|
+
point in the recipe’s preferred direction. It’s static: when the primary
|
|
997
|
+
placement doesn’t fit and a fallback opens the body on the other side, the
|
|
998
|
+
chevron still points the preferred way.
|
|
863
999
|
|
|
864
1000
|
See the [`DirectionRecipes` story][] for a live demo of all four.
|
|
865
1001
|
|
package/dist/Dropdown.d.ts
CHANGED
|
@@ -147,8 +147,10 @@ export type Props = {
|
|
|
147
147
|
/**
|
|
148
148
|
* Called when an item is submitted (click, Enter, or Space). Parent items
|
|
149
149
|
* (submenus) disclose rather than submit, so this fires for leaf items
|
|
150
|
-
* only.
|
|
151
|
-
*
|
|
150
|
+
* only. A submit closes the dropdown 90ms later (unless the root dropdown
|
|
151
|
+
* sets keepOpenOnSubmit), and the dropdown ignores any other submit in
|
|
152
|
+
* that time, so this isn’t called twice for a double press. For a nested
|
|
153
|
+
* (submenu) Dropdown, fires for submissions within its subtree only.
|
|
152
154
|
*/
|
|
153
155
|
onSubmitItem?: (payload: Item) => void;
|
|
154
156
|
/**
|