@heyramzi/ui 3.6.0 → 3.7.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/package.json +1 -1
- package/src/components/open-in/open-in.svelte +14 -15
- package/src/components/open-in/open-in.svelte.d.ts +2 -2
- package/src/effects/interactive-hover-button/InteractiveHoverButton.svelte +39 -15
- package/src/effects/interactive-hover-button/InteractiveHoverButton.svelte.d.ts +2 -1
- package/src/shadcn/sidebar/sidebar-provider.svelte +9 -2
- package/src/shadcn/sidebar/sidebar-provider.svelte.d.ts +5 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@heyramzi/ui",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.7.0",
|
|
4
4
|
"description": "Svelte 5 UI for apps: primitives, effects and animations, plus work (tasks and docs), charts, slides, an editor, onboarding and a canvas as subpaths.",
|
|
5
5
|
"homepage": "https://ui.heyramzi.com",
|
|
6
6
|
"license": "MIT",
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
/** `chip` is the bordered inline tag, `button` sits in a header beside other
|
|
17
|
-
* buttons
|
|
18
|
-
export type OpenInVariant = "chip" | "button"
|
|
17
|
+
* buttons. A bare-mark form was cut: at 20px it failed WCAG 2.5.8. */
|
|
18
|
+
export type OpenInVariant = "chip" | "button";
|
|
19
19
|
export type OpenInSize = "sm" | "default";
|
|
20
20
|
</script>
|
|
21
21
|
|
|
@@ -86,22 +86,21 @@
|
|
|
86
86
|
class={cn(
|
|
87
87
|
variant === "button"
|
|
88
88
|
? buttonVariants({ variant: "outline", size: size === "sm" ? "sm" : "default" })
|
|
89
|
-
:
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
89
|
+
: cn(
|
|
90
|
+
"inline-flex shrink-0 items-center gap-1.5 whitespace-nowrap rounded-md border border-border text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
|
|
91
|
+
// WHY the button heights: the sm chip was 19px, under the 24px target
|
|
92
|
+
// floor. Under a thumb it grows to 40 and 44, and the sm hit area to 44.
|
|
93
|
+
size === "sm"
|
|
94
|
+
? "relative h-7 px-2 text-2xs after:absolute after:top-1/2 after:left-1/2 after:h-[max(100%,1.5rem)] after:w-[max(100%,1.5rem)] after:-translate-x-1/2 after:-translate-y-1/2 any-pointer-coarse:h-10 any-pointer-coarse:after:h-[max(100%,2.75rem)] any-pointer-coarse:after:w-[max(100%,2.75rem)]"
|
|
95
|
+
: "h-8 px-2.5 text-xs any-pointer-coarse:h-11 any-pointer-coarse:px-3",
|
|
96
|
+
),
|
|
96
97
|
className,
|
|
97
98
|
)}
|
|
98
99
|
>
|
|
99
100
|
<Icon aria-hidden="true" size={iconSize} />
|
|
100
|
-
{
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
<ArrowSquareOut aria-hidden="true" size={iconSize} class="text-muted-foreground" />
|
|
105
|
-
{/if}
|
|
101
|
+
{text}
|
|
102
|
+
<!-- The one thing the mark can't say: this leaves the app. It stays muted
|
|
103
|
+
so the eye lands on the tool name first. -->
|
|
104
|
+
<ArrowSquareOut aria-hidden="true" size={iconSize} class="text-muted-foreground" />
|
|
106
105
|
</a>
|
|
107
106
|
</div>
|
|
@@ -15,8 +15,8 @@ export interface OpenInTool {
|
|
|
15
15
|
}>;
|
|
16
16
|
}
|
|
17
17
|
/** `chip` is the bordered inline tag, `button` sits in a header beside other
|
|
18
|
-
* buttons
|
|
19
|
-
export type OpenInVariant = "chip" | "button"
|
|
18
|
+
* buttons. A bare-mark form was cut: at 20px it failed WCAG 2.5.8. */
|
|
19
|
+
export type OpenInVariant = "chip" | "button";
|
|
20
20
|
export type OpenInSize = "sm" | "default";
|
|
21
21
|
interface Props {
|
|
22
22
|
/** The tool to link to: its name, accessible sentence and mark. */
|
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
/** `submit` posts the form the button sits in. */
|
|
13
13
|
type?: "button" | "submit";
|
|
14
14
|
disabled?: boolean;
|
|
15
|
-
|
|
15
|
+
/** `sm` is 40px for a condensed bar; under a thumb both are 44px. */
|
|
16
|
+
size?: "default" | "sm";
|
|
16
17
|
tone?: "ink" | "coral";
|
|
17
18
|
beam?: boolean;
|
|
18
19
|
dot?: boolean;
|
|
@@ -43,7 +44,6 @@
|
|
|
43
44
|
let classes = $derived(
|
|
44
45
|
[
|
|
45
46
|
"cta-hover",
|
|
46
|
-
size === "md" && "cta-hover--md",
|
|
47
47
|
size === "sm" && "cta-hover--sm",
|
|
48
48
|
tone === "coral" && "cta-hover--coral",
|
|
49
49
|
!beam && "cta-hover--no-beam",
|
|
@@ -168,28 +168,24 @@
|
|
|
168
168
|
pointer-events: none;
|
|
169
169
|
}
|
|
170
170
|
|
|
171
|
-
/* 40px
|
|
172
|
-
|
|
173
|
-
.cta-hover--
|
|
171
|
+
/* 40px for a CTA in a condensed bar. The old 32px was too small to read as
|
|
172
|
+
the main action, so only the label shrinks, to 13px. */
|
|
173
|
+
.cta-hover--sm {
|
|
174
174
|
height: 40px;
|
|
175
175
|
padding: 0 24px;
|
|
176
176
|
font-size: 13px;
|
|
177
177
|
}
|
|
178
178
|
|
|
179
|
-
.cta-hover--
|
|
179
|
+
.cta-hover--sm .cta-hover__dot {
|
|
180
180
|
width: 7px;
|
|
181
181
|
height: 7px;
|
|
182
182
|
}
|
|
183
183
|
|
|
184
|
-
.
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
.cta-hover--sm .cta-hover__dot {
|
|
191
|
-
width: 6px;
|
|
192
|
-
height: 6px;
|
|
184
|
+
/* Under a thumb both sizes clear the 44px touch target, as Button does. */
|
|
185
|
+
@media (any-pointer: coarse) {
|
|
186
|
+
.cta-hover--sm {
|
|
187
|
+
height: 44px;
|
|
188
|
+
}
|
|
193
189
|
}
|
|
194
190
|
|
|
195
191
|
.cta-hover--no-beam::before {
|
|
@@ -344,11 +340,39 @@
|
|
|
344
340
|
}
|
|
345
341
|
}
|
|
346
342
|
|
|
343
|
+
/* The beam stops, and hover swaps the fill and label in place: no dot
|
|
344
|
+
growing out, no label sliding across. */
|
|
347
345
|
@media (prefers-reduced-motion: reduce) {
|
|
348
346
|
.cta-hover::before {
|
|
349
347
|
animation: none;
|
|
350
348
|
opacity: 0;
|
|
351
349
|
}
|
|
350
|
+
|
|
351
|
+
.cta-hover,
|
|
352
|
+
.cta-hover__resting,
|
|
353
|
+
.cta-hover__dot,
|
|
354
|
+
.cta-hover__label,
|
|
355
|
+
.cta-hover__reveal,
|
|
356
|
+
:global(.cta-hover__arrow--inline) {
|
|
357
|
+
transition-property: opacity, background-color, color;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
@media (prefers-reduced-motion: reduce) and (hover: hover) and (pointer: fine) {
|
|
362
|
+
.cta-hover:hover .cta-hover__dot,
|
|
363
|
+
.cta-hover:not(.cta-hover--no-dot):hover .cta-hover__resting .cta-hover__label,
|
|
364
|
+
.cta-hover:not(.cta-hover--no-dot):hover .cta-hover__reveal,
|
|
365
|
+
.cta-hover--no-dot:hover :global(.cta-hover__arrow--inline) {
|
|
366
|
+
transform: none;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
.cta-hover:not(.cta-hover--no-dot):hover::after {
|
|
370
|
+
background: var(--color-signal-600);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
.cta-hover--coral:not(.cta-hover--no-dot):hover::after {
|
|
374
|
+
background: var(--color-ink);
|
|
375
|
+
}
|
|
352
376
|
}
|
|
353
377
|
}
|
|
354
378
|
|
|
@@ -3,7 +3,8 @@ interface Props {
|
|
|
3
3
|
/** `submit` posts the form the button sits in. */
|
|
4
4
|
type?: "button" | "submit";
|
|
5
5
|
disabled?: boolean;
|
|
6
|
-
|
|
6
|
+
/** `sm` is 40px for a condensed bar; under a thumb both are 44px. */
|
|
7
|
+
size?: "default" | "sm";
|
|
7
8
|
tone?: "ink" | "coral";
|
|
8
9
|
beam?: boolean;
|
|
9
10
|
dot?: boolean;
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
ref = $bindable(null),
|
|
15
15
|
open = $bindable(true),
|
|
16
16
|
onOpenChange = () => {},
|
|
17
|
+
persist = true,
|
|
17
18
|
class: className,
|
|
18
19
|
style,
|
|
19
20
|
children,
|
|
@@ -21,6 +22,11 @@
|
|
|
21
22
|
}: WithElementRef<HTMLAttributes<HTMLDivElement>> & {
|
|
22
23
|
open?: boolean;
|
|
23
24
|
onOpenChange?: (open: boolean) => void;
|
|
25
|
+
/**
|
|
26
|
+
* False for a sidebar that isn't the app's shell, such as a docs demo: it then
|
|
27
|
+
* writes no state cookie and takes no Cmd+B, so it can't fold the real one.
|
|
28
|
+
*/
|
|
29
|
+
persist?: boolean;
|
|
24
30
|
} = $props();
|
|
25
31
|
|
|
26
32
|
let openState = $state(open);
|
|
@@ -40,12 +46,13 @@
|
|
|
40
46
|
onOpenChange(value);
|
|
41
47
|
|
|
42
48
|
// This sets the cookie to keep the sidebar state.
|
|
43
|
-
|
|
49
|
+
if (persist)
|
|
50
|
+
document.cookie = `${SIDEBAR_COOKIE_NAME}=${value}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`;
|
|
44
51
|
},
|
|
45
52
|
});
|
|
46
53
|
</script>
|
|
47
54
|
|
|
48
|
-
<svelte:window onkeydown={sidebar.handleShortcutKeydown} />
|
|
55
|
+
<svelte:window onkeydown={persist ? sidebar.handleShortcutKeydown : undefined} />
|
|
49
56
|
|
|
50
57
|
<Tooltip.Provider delayDuration={0}>
|
|
51
58
|
<!-- An h-svh frame that never scrolls: the app puts its page in a
|
|
@@ -3,6 +3,11 @@ import type { HTMLAttributes } from "svelte/elements";
|
|
|
3
3
|
type $$ComponentProps = WithElementRef<HTMLAttributes<HTMLDivElement>> & {
|
|
4
4
|
open?: boolean;
|
|
5
5
|
onOpenChange?: (open: boolean) => void;
|
|
6
|
+
/**
|
|
7
|
+
* False for a sidebar that isn't the app's shell, such as a docs demo: it then
|
|
8
|
+
* writes no state cookie and takes no Cmd+B, so it can't fold the real one.
|
|
9
|
+
*/
|
|
10
|
+
persist?: boolean;
|
|
6
11
|
};
|
|
7
12
|
declare const $$Component: import("svelte").Component<$$ComponentProps, {}, "ref" | "open">;
|
|
8
13
|
type $$Component = ReturnType<typeof $$Component>;
|