@spaethtech/svelte-ui 0.7.1-dev.43.72e77ad → 0.7.1-dev.44.97afb0d
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.
|
@@ -123,6 +123,7 @@
|
|
|
123
123
|
hamburger = true,
|
|
124
124
|
iconHoverExpand = false,
|
|
125
125
|
hoverExpandCloseMs = 200,
|
|
126
|
+
side = "left",
|
|
126
127
|
api = $bindable(),
|
|
127
128
|
class: additionalClass = "",
|
|
128
129
|
}: {
|
|
@@ -178,6 +179,10 @@
|
|
|
178
179
|
iconHoverExpand?: boolean;
|
|
179
180
|
/** Exit delay (ms) before a hover-expanded rail collapses on mouse-leave. Default `200`. */
|
|
180
181
|
hoverExpandCloseMs?: number;
|
|
182
|
+
/** Which edge the sidebar docks to. `"right"` mirrors everything: the frame border, the drawer
|
|
183
|
+
* slide direction, the hamburger corner, popout side + border, and item layout (icon on the
|
|
184
|
+
* right, labels right-aligned). Default `"left"`. */
|
|
185
|
+
side?: "left" | "right";
|
|
181
186
|
/** Imperative handle (bindable). Call `api.reset()` from your router's navigation lifecycle
|
|
182
187
|
* (SvelteKit `afterNavigate`, etc.) so a programmatic `goto()`/back-button closes the drawer +
|
|
183
188
|
* any open popout and returns a stepped drawer to the top. */
|
|
@@ -231,6 +236,16 @@
|
|
|
231
236
|
|
|
232
237
|
const isStepped = $derived(currentMode === "stepped");
|
|
233
238
|
const isDrawer = $derived(currentMode === "drawer" || currentMode === "stepped");
|
|
239
|
+
// Dock side. `right` mirrors the frame, drawer slide, hamburger corner, popout side, and item layout.
|
|
240
|
+
const dockRight = $derived(side === "right");
|
|
241
|
+
const popoutSide = $derived<"left" | "right">(dockRight ? "left" : "right");
|
|
242
|
+
const dockEdge = $derived(dockRight ? "right-0" : "left-0");
|
|
243
|
+
const dockOff = $derived(dockRight ? "translate-x-full" : "-translate-x-full");
|
|
244
|
+
const dockBorder = $derived(
|
|
245
|
+
dockRight
|
|
246
|
+
? "[border-left:1px_solid_color-mix(in_srgb,var(--ui-color-text)_15%,transparent)]"
|
|
247
|
+
: "[border-right:1px_solid_color-mix(in_srgb,var(--ui-color-text)_15%,transparent)]",
|
|
248
|
+
);
|
|
234
249
|
|
|
235
250
|
// ── Icon-mode hover-expand ──────────────────────────────────────
|
|
236
251
|
// When enabled + in `icon` mode, hovering the rail floats it out to the `expanded` render OVER a
|
|
@@ -505,7 +520,7 @@
|
|
|
505
520
|
// height get clamped to the viewport by the `anchored` engine
|
|
506
521
|
// boundary. That case also needs in-popout scroll (TODO) and
|
|
507
522
|
// the border rule may need to account for viewport-edge cases.
|
|
508
|
-
let borderClass = "border-r";
|
|
523
|
+
let borderClass = dockRight ? "border-l" : "border-r";
|
|
509
524
|
if (group === "bottom") {
|
|
510
525
|
borderClass += spans ? " border-t" : " border-t border-b";
|
|
511
526
|
} else {
|
|
@@ -564,7 +579,9 @@
|
|
|
564
579
|
what `truncate` (overflow-hidden + text-ellipsis) needs to
|
|
565
580
|
actually clip overflow. Without `min-w-0` the label refuses
|
|
566
581
|
to shrink past its natural width and the row overflows. -->
|
|
567
|
-
<span class="flex-1 min-w-0 truncate {labelClassResolved} {sz.text}"
|
|
582
|
+
<span class="flex-1 min-w-0 truncate {dockRight ? 'text-right' : ''} {labelClassResolved} {sz.text}"
|
|
583
|
+
>{item.label}</span
|
|
584
|
+
>
|
|
568
585
|
{#if isParent}
|
|
569
586
|
<!-- Chevron — visible only when the label is visible (no point
|
|
570
587
|
dangling a `>` next to an icon-only icon). Rotates 180° to
|
|
@@ -591,7 +608,7 @@
|
|
|
591
608
|
{@const hasLink = !!item.link}
|
|
592
609
|
{@const isOpen = !!opts.id && openId === opts.id}
|
|
593
610
|
{@const popoutId = opts.id ? "sbm-popout-" + opts.id.replace(":", "-") : undefined}
|
|
594
|
-
{@const rowClass = `group flex items-center w-full ${sz.row} lg:pr-3 transition-colors cursor-pointer ${active ? "[background-color:var(--ui-color-primary)] text-white" : isOpen ? "[background-color:color-mix(in_srgb,var(--ui-color-text)_10%,transparent)]" : "hover:[background-color:color-mix(in_srgb,var(--ui-color-text)_10%,transparent)]"}`}
|
|
611
|
+
{@const rowClass = `group flex items-center w-full ${sz.row} ${dockRight ? "flex-row-reverse lg:pl-3" : "lg:pr-3"} transition-colors cursor-pointer ${active ? "[background-color:var(--ui-color-primary)] text-white" : isOpen ? "[background-color:color-mix(in_srgb,var(--ui-color-text)_10%,transparent)]" : "hover:[background-color:color-mix(in_srgb,var(--ui-color-text)_10%,transparent)]"}`}
|
|
595
612
|
{#if hasLink}
|
|
596
613
|
<a
|
|
597
614
|
href={item.link}
|
|
@@ -706,7 +723,9 @@
|
|
|
706
723
|
to suppress this when the consumer provides its own trigger. -->
|
|
707
724
|
<button
|
|
708
725
|
type="button"
|
|
709
|
-
class="fixed top-3
|
|
726
|
+
class="fixed top-3 {dockRight
|
|
727
|
+
? 'right-3'
|
|
728
|
+
: 'left-3'} z-[80] inline-flex w-10 h-10 items-center justify-center cursor-pointer [background-color:var(--ui-color-background)] border [border-color:color-mix(in_srgb,var(--ui-color-text)_15%,transparent)] shadow-md [&_svg]:w-5 [&_svg]:h-5"
|
|
710
729
|
aria-label={open ? "Close menu" : "Open menu"}
|
|
711
730
|
aria-expanded={open}
|
|
712
731
|
onclick={() => (open = !open)}
|
|
@@ -741,14 +760,14 @@
|
|
|
741
760
|
flex flex-col z-[60] overflow-hidden
|
|
742
761
|
[background-color:var(--ui-color-background)]
|
|
743
762
|
[color:var(--ui-color-text)]
|
|
744
|
-
|
|
763
|
+
{dockBorder}
|
|
745
764
|
{currentMode === 'stepped'
|
|
746
|
-
? `absolute inset-y-0
|
|
765
|
+
? `absolute inset-y-0 ${dockEdge} w-full z-[75] transition-transform duration-200 ${open ? 'translate-x-0' : dockOff}`
|
|
747
766
|
: currentMode === 'drawer'
|
|
748
|
-
? `absolute inset-y-0
|
|
767
|
+
? `absolute inset-y-0 ${dockEdge} w-[var(--sbm-expanded-w)] z-[75] transition-transform duration-200 ${open ? 'translate-x-0' : dockOff}`
|
|
749
768
|
: currentMode === 'icon'
|
|
750
769
|
? hoverExpandActive
|
|
751
|
-
? `absolute inset-y-0
|
|
770
|
+
? `absolute inset-y-0 ${dockEdge} z-[65] transition-[width] duration-200 ${effectivelyExpanded ? 'w-[var(--sbm-expanded-w)] shadow-lg' : 'w-[var(--sbm-collapsed-w)]'}`
|
|
752
771
|
: 'relative w-[var(--sbm-collapsed-w)]'
|
|
753
772
|
: 'relative w-[var(--sbm-expanded-w)]'}
|
|
754
773
|
{additionalClass}
|
|
@@ -780,7 +799,7 @@
|
|
|
780
799
|
<Popup
|
|
781
800
|
anchor={geom.anchor}
|
|
782
801
|
open={openId === id}
|
|
783
|
-
side=
|
|
802
|
+
side={popoutSide}
|
|
784
803
|
align={geom.align}
|
|
785
804
|
offset={0}
|
|
786
805
|
onclose={() => {
|
|
@@ -816,7 +835,7 @@
|
|
|
816
835
|
<Popup
|
|
817
836
|
anchor={geom.anchor}
|
|
818
837
|
open={openId === id}
|
|
819
|
-
side=
|
|
838
|
+
side={popoutSide}
|
|
820
839
|
align={geom.align}
|
|
821
840
|
offset={0}
|
|
822
841
|
onclose={() => {
|
|
@@ -127,6 +127,10 @@ type $$ComponentProps = {
|
|
|
127
127
|
iconHoverExpand?: boolean;
|
|
128
128
|
/** Exit delay (ms) before a hover-expanded rail collapses on mouse-leave. Default `200`. */
|
|
129
129
|
hoverExpandCloseMs?: number;
|
|
130
|
+
/** Which edge the sidebar docks to. `"right"` mirrors everything: the frame border, the drawer
|
|
131
|
+
* slide direction, the hamburger corner, popout side + border, and item layout (icon on the
|
|
132
|
+
* right, labels right-aligned). Default `"left"`. */
|
|
133
|
+
side?: "left" | "right";
|
|
130
134
|
/** Imperative handle (bindable). Call `api.reset()` from your router's navigation lifecycle
|
|
131
135
|
* (SvelteKit `afterNavigate`, etc.) so a programmatic `goto()`/back-button closes the drawer +
|
|
132
136
|
* any open popout and returns a stepped drawer to the top. */
|