@acusti/dropdown 1.0.0-alpha.5 → 1.0.0-alpha.7
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 +133 -31
- package/dist/Dropdown.js +257 -256
- package/dist/Dropdown.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -524,7 +524,11 @@ Placement is best customized in CSS instead of props. The component exposes
|
|
|
524
524
|
CSS custom properties for the most common low-level placement controls:
|
|
525
525
|
|
|
526
526
|
- `--uktdd-body-position-area`
|
|
527
|
-
- `--uktdd-body-position-try-
|
|
527
|
+
- `--uktdd-body-position-try-fallback-1` and
|
|
528
|
+
`--uktdd-body-position-try-fallback-2` (the two author fallbacks, tried
|
|
529
|
+
in order after the primary placement)
|
|
530
|
+
- `--uktdd-body-fill-fallbacks` (the last-resort fill placements, tried
|
|
531
|
+
when the body fits nowhere at its natural size)
|
|
528
532
|
- `--uktdd-body-gap` (space between the trigger and the body)
|
|
529
533
|
- `--uktdd-body-min-height`
|
|
530
534
|
- `--uktdd-body-min-width`
|
|
@@ -536,8 +540,8 @@ Example:
|
|
|
536
540
|
```css
|
|
537
541
|
.settings-dropdown {
|
|
538
542
|
--uktdd-body-position-area: block-end span-inline-start;
|
|
539
|
-
--uktdd-body-position-try-
|
|
540
|
-
|
|
543
|
+
--uktdd-body-position-try-fallback-1: --uktdd-top-end;
|
|
544
|
+
--uktdd-body-position-try-fallback-2: --uktdd-bottom-start;
|
|
541
545
|
--uktdd-body-gap: 8px;
|
|
542
546
|
}
|
|
543
547
|
|
|
@@ -551,15 +555,17 @@ placement and sizing control when a product surface needs it.
|
|
|
551
555
|
|
|
552
556
|
### Changing the Default Direction
|
|
553
557
|
|
|
554
|
-
`--uktdd-body-position-area` and
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
558
|
+
`--uktdd-body-position-area` and its two fallback slots
|
|
559
|
+
(`--uktdd-body-position-try-fallback-1`,
|
|
560
|
+
`--uktdd-body-position-try-fallback-2`) always change together.
|
|
561
|
+
`--uktdd-body-position-area` is the primary placement, used whenever it
|
|
562
|
+
fits in the viewport — that’s what actually determines the direction a
|
|
563
|
+
dropdown opens by default. The fallback slots are tried in order only when
|
|
564
|
+
the primary placement doesn’t fit. Set all three together to ensure the
|
|
565
|
+
menu behaves the way you want it to in all possible contexts. If the new
|
|
566
|
+
direction has only one meaningful fallback (a centered menu, say), put it
|
|
567
|
+
in slot 1 and set slot 2 to the shipped no-op `--uktdd-noop` so it doesn’t
|
|
568
|
+
inherit that flip.
|
|
563
569
|
|
|
564
570
|
The four `@position-try` blocks the component ships (`--uktdd-top-start`,
|
|
565
571
|
`--uktdd-top-end`, `--uktdd-bottom-start`, `--uktdd-bottom-end`) are named
|
|
@@ -574,15 +580,21 @@ physical keyword on one axis with a logical one on the other — though
|
|
|
574
580
|
`block-start`/`block-end` read as `top`/`bottom` in the near-universal
|
|
575
581
|
horizontal-tb writing mode.
|
|
576
582
|
|
|
577
|
-
Pick the row matching the direction you want, and set
|
|
578
|
-
|
|
583
|
+
Pick the row matching the direction you want, and set the three CSS custom
|
|
584
|
+
properties to the corresponding values:
|
|
579
585
|
|
|
580
|
-
| Direction | `--uktdd-body-position-area` |
|
|
581
|
-
| ----------------------------------- | ------------------------------- |
|
|
582
|
-
| Bottom, start-aligned (the default) | `block-end span-inline-end` | `--uktdd-top-start
|
|
583
|
-
| Bottom, end-aligned | `block-end span-inline-start` | `--uktdd-top-end
|
|
584
|
-
| Top, start-aligned | `block-start span-inline-end` | `--uktdd-bottom-start
|
|
585
|
-
| Top, end-aligned | `block-start span-inline-start` | `--uktdd-bottom-end
|
|
586
|
+
| Direction | `--uktdd-body-position-area` | `…try-fallback-1` | `…try-fallback-2` |
|
|
587
|
+
| ----------------------------------- | ------------------------------- | ---------------------- | ---------------------- |
|
|
588
|
+
| Bottom, start-aligned (the default) | `block-end span-inline-end` | `--uktdd-top-start` | `--uktdd-bottom-end` |
|
|
589
|
+
| Bottom, end-aligned | `block-end span-inline-start` | `--uktdd-top-end` | `--uktdd-bottom-start` |
|
|
590
|
+
| Top, start-aligned | `block-start span-inline-end` | `--uktdd-bottom-start` | `--uktdd-top-end` |
|
|
591
|
+
| Top, end-aligned | `block-start span-inline-start` | `--uktdd-bottom-end` | `--uktdd-top-start` |
|
|
592
|
+
|
|
593
|
+
(The `…try-fallback-N` columns are `--uktdd-body-position-try-fallback-1`
|
|
594
|
+
and `-2`.)
|
|
595
|
+
|
|
596
|
+
The two Top rows should also flip the last-resort fill pair to match:
|
|
597
|
+
`--uktdd-body-fill-fallbacks: --uktdd-fill-top, --uktdd-fill-bottom`.
|
|
586
598
|
|
|
587
599
|
For example, to make a dropdown open upward and end-aligned (useful for a
|
|
588
600
|
trigger pinned to the bottom of the viewport, near the inline-end edge):
|
|
@@ -590,11 +602,17 @@ trigger pinned to the bottom of the viewport, near the inline-end edge):
|
|
|
590
602
|
```css
|
|
591
603
|
.bottom-toolbar-dropdown {
|
|
592
604
|
--uktdd-body-position-area: block-start span-inline-start;
|
|
593
|
-
--uktdd-body-position-try-
|
|
594
|
-
|
|
605
|
+
--uktdd-body-position-try-fallback-1: --uktdd-bottom-end;
|
|
606
|
+
--uktdd-body-position-try-fallback-2: --uktdd-top-start;
|
|
607
|
+
--uktdd-body-fill-fallbacks: --uktdd-fill-top, --uktdd-fill-bottom;
|
|
595
608
|
}
|
|
596
609
|
```
|
|
597
610
|
|
|
611
|
+
The last line flips the last-resort fill pair to match the recipe’s
|
|
612
|
+
direction: when the body is too tall to fit anywhere at its natural size,
|
|
613
|
+
it fills and scrolls on the upward side first (more on the fill pair
|
|
614
|
+
below).
|
|
615
|
+
|
|
598
616
|
See the [`DirectionRecipes` story][] for a live demo of all four.
|
|
599
617
|
|
|
600
618
|
[`DirectionRecipes` story]:
|
|
@@ -604,9 +622,77 @@ The primary placement wins whenever the body fits there at its natural
|
|
|
604
622
|
size, then the fallbacks are tried in order — the body opens in the
|
|
605
623
|
direction you asked for as long as that side can hold it, and never flips
|
|
606
624
|
to the opposite side just because the viewport happens to have more empty
|
|
607
|
-
space there. Only when the body fits in none of those placements
|
|
608
|
-
|
|
609
|
-
|
|
625
|
+
space there. Only when the body fits in none of those placements do the
|
|
626
|
+
`--uktdd-body-fill-fallbacks` placements
|
|
627
|
+
(`--uktdd-fill-bottom, --uktdd-fill-top` by default) take over: the body
|
|
628
|
+
sizes itself to the block-axis space below the trigger — or above it,
|
|
629
|
+
whichever the pair lists first that has room — and lets the content scroll,
|
|
630
|
+
so it never overflows the viewport or covers the trigger. A dropdown that
|
|
631
|
+
opens upward should flip the pair
|
|
632
|
+
(`--uktdd-body-fill-fallbacks: --uktdd-fill-top, --uktdd-fill-bottom`) so
|
|
633
|
+
the last-resort fill also prefers the upward side. In these fill placements
|
|
634
|
+
the body spans the trigger (centered over it, shifted inward as needed to
|
|
635
|
+
stay on-screen) rather than keeping the primary placement’s edge alignment.
|
|
636
|
+
Submenus have their own last-resort fills
|
|
637
|
+
([`--uktdd-submenu-fill-fallbacks`](#submenu-placement-and-styling)) that
|
|
638
|
+
keep them beside the parent rather than covering it, so this pair applies
|
|
639
|
+
to the body alone.
|
|
640
|
+
|
|
641
|
+
In the fills, `--uktdd-body-min-height` marks a side as too cramped to
|
|
642
|
+
bother with: a fill whose side is shorter than it is rejected so the
|
|
643
|
+
roomier opposite side is tried. That floor is capped at the worst-case side
|
|
644
|
+
— half the viewport minus the trigger, the most a vertically centered
|
|
645
|
+
trigger can guarantee — so a min-height above half the viewport (honored in
|
|
646
|
+
full by the named placements) can’t reject both fills: the body fills the
|
|
647
|
+
roomier side and scrolls rather than overflowing.
|
|
648
|
+
|
|
649
|
+
There are exactly two author fallback slots by design. The
|
|
650
|
+
[CSS spec](https://drafts.csswg.org/css-anchor-position-1/#fallback-apply)
|
|
651
|
+
requires implementations to support at least five position options,
|
|
652
|
+
including the element’s base position, and `@acusti/dropdown` appends two
|
|
653
|
+
last-resort placements to the end, so that leaves two fallbacks that you
|
|
654
|
+
can specify, hence why they are exposed as two separate custom properties.
|
|
655
|
+
The two default slots are the single-axis flips of the primary (a block
|
|
656
|
+
flip and an inline flip); the mirror opposite diagonal is intentionally not
|
|
657
|
+
a slot, so that a trigger crammed into the corner diagonal to the primary
|
|
658
|
+
opening direction lands in a fill rather than a natural placement. See the
|
|
659
|
+
[recipes above](#changing-the-default-direction) for different common
|
|
660
|
+
placement scenarios. For a recipe with a single meaningful fallback (a
|
|
661
|
+
centered menu, say), set slot 1 and leave slot 2 as the shipped no-op
|
|
662
|
+
`--uktdd-noop`, so it doesn’t inherit the default’s flip.
|
|
663
|
+
|
|
664
|
+
### Trading Trigger Coverage for a Full-Height Menu
|
|
665
|
+
|
|
666
|
+
The block-side fills never cover the trigger, which bounds their height by
|
|
667
|
+
where the trigger sits. When the body already fits horizontally, the opt-in
|
|
668
|
+
`--uktdd-fill-cover` placement (in no default list) can trade that
|
|
669
|
+
guarantee away: it keeps the strict start-aligned inline edge (compose
|
|
670
|
+
`--uktdd-fill-cover flip-inline` for end alignment) and loosens the block
|
|
671
|
+
axis instead, sizing the body to the viewport’s full block size — covering
|
|
672
|
+
the trigger — so a too-tall menu gets the whole viewport to scroll in
|
|
673
|
+
rather than one side of it.
|
|
674
|
+
|
|
675
|
+
```css
|
|
676
|
+
.tall-menu {
|
|
677
|
+
--uktdd-body-position-try-fallback-1: --uktdd-top-start;
|
|
678
|
+
--uktdd-body-position-try-fallback-2: --uktdd-bottom-end;
|
|
679
|
+
--uktdd-body-fill-fallbacks:
|
|
680
|
+
--uktdd-fill-cover, --uktdd-fill-bottom, --uktdd-fill-top;
|
|
681
|
+
}
|
|
682
|
+
```
|
|
683
|
+
|
|
684
|
+
The cover fill is rejected whenever the body is too wide for the region
|
|
685
|
+
between the trigger’s inline-start edge and the viewport edge, so the
|
|
686
|
+
guaranteed pair still rescues corner triggers — but the pair must stay
|
|
687
|
+
within the evaluation budget: with three fills you get at most two author
|
|
688
|
+
fallback slots, for six position options total. That’s the ceiling every
|
|
689
|
+
current engine clears (Chromium evaluates exactly six; Safari and Firefox
|
|
690
|
+
go well beyond), though only five are spec-guaranteed — drop to one author
|
|
691
|
+
fallback if you want the whole list within that floor. Two caveats: don’t
|
|
692
|
+
use it on searchable dropdowns, since the body overlays the trigger’s input
|
|
693
|
+
while open; and while the body covers the trigger, clicking the trigger’s
|
|
694
|
+
position hits the body instead — dismiss with Escape or a click elsewhere
|
|
695
|
+
outside.
|
|
610
696
|
|
|
611
697
|
Use `--uktdd-body-gap` for the space between the trigger and the body. It
|
|
612
698
|
is applied as a symmetric `margin-block`, so the gap lands on whichever
|
|
@@ -629,8 +715,8 @@ the menu size itself from its contents.
|
|
|
629
715
|
```css
|
|
630
716
|
.avatar-menu {
|
|
631
717
|
--uktdd-body-position-area: block-end span-inline-start;
|
|
632
|
-
--uktdd-body-position-try-
|
|
633
|
-
|
|
718
|
+
--uktdd-body-position-try-fallback-1: --uktdd-top-end;
|
|
719
|
+
--uktdd-body-position-try-fallback-2: --uktdd-top-start;
|
|
634
720
|
}
|
|
635
721
|
```
|
|
636
722
|
|
|
@@ -651,13 +737,17 @@ the trigger always overflows it — and `position-try` refuses to select a
|
|
|
651
737
|
fallback that overflows, so a `bottom center` → `top center` setup never
|
|
652
738
|
flips. `span-all` centers over the trigger identically but spans the full
|
|
653
739
|
width, so it flips cleanly and clamps to the viewport near an edge. The
|
|
654
|
-
menu opens below by default and flips above only when it doesn’t fit below
|
|
655
|
-
|
|
740
|
+
menu opens below by default and flips above only when it doesn’t fit below.
|
|
741
|
+
It has one meaningful fallback (the flipped centered placement), so set it
|
|
742
|
+
in slot 1 and leave slot 2 as the no-op — otherwise slot 2 keeps the
|
|
743
|
+
default’s corner flip and the menu can land off-center in a cramped
|
|
744
|
+
viewport:
|
|
656
745
|
|
|
657
746
|
```css
|
|
658
747
|
.centered-menu {
|
|
659
748
|
--uktdd-body-position-area: bottom span-all;
|
|
660
|
-
--uktdd-body-position-try-
|
|
749
|
+
--uktdd-body-position-try-fallback-1: --centered-menu-top;
|
|
750
|
+
--uktdd-body-position-try-fallback-2: --uktdd-noop;
|
|
661
751
|
}
|
|
662
752
|
|
|
663
753
|
/* define the flipped fallback in your own CSS */
|
|
@@ -778,7 +868,19 @@ it flush to the parent item’s edge across browsers. Placement custom
|
|
|
778
868
|
properties follow the established naming scheme:
|
|
779
869
|
|
|
780
870
|
- `--uktdd-submenu-position-area` (default: `inline-end span-block-end`)
|
|
781
|
-
- `--uktdd-submenu-position-try-
|
|
871
|
+
- `--uktdd-submenu-position-try-fallback` (default:
|
|
872
|
+
`--uktdd-submenu-inline-start`; a single slot, not a list)
|
|
873
|
+
- `--uktdd-submenu-fill-fallbacks` (the last-resort fills for a submenu too
|
|
874
|
+
tall to open beside its parent at natural size; default
|
|
875
|
+
`--uktdd-submenu-fill, --uktdd-submenu-fill flip-inline` — a full-height
|
|
876
|
+
fill on each inline side that anchor-centers on the block axis, so the
|
|
877
|
+
submenu fills the viewport height beside the parent and scrolls rather
|
|
878
|
+
than covering the parent menu, the way macOS never covers a parent with
|
|
879
|
+
its submenu. Flip the pair for a submenu that opens `inline-start` by
|
|
880
|
+
default. A submenu wider than the space on either side of its parent is
|
|
881
|
+
the one case this default doesn’t handle; append
|
|
882
|
+
`--uktdd-fill-bottom, --uktdd-fill-top` here to restore the
|
|
883
|
+
parent-covering rescue if you need it)
|
|
782
884
|
- `--uktdd-submenu-gap` (space between the parent item and the submenu;
|
|
783
885
|
applied as a symmetric `margin-inline`, the inline-axis counterpart to
|
|
784
886
|
`--uktdd-body-gap`, so it auto-reverses when the submenu flips to the
|