@threadlabs/looma 0.26.24 → 0.26.26
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/components/ui-icon-button/ui-icon-button.html +12 -2
- package/components/ui-tooltip/ui-tooltip.html +2 -1
- package/components/ui-tooltip/ui-tooltip.js +20 -0
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/styles/ui-icon-button.css +9 -2
- package/vanilla/UiIconButton.d.ts +1 -0
- package/vanilla/UiIconButton.js +14 -14
- package/vue/UiIconButton.d.ts +9 -0
- package/vue/UiIconButton.vue +31 -2
- package/vue/UiTooltip.vue +1 -1
- package/vue/chunks/UiIconButton.js +26 -1
- package/vue/chunks/UiTooltip.js +2 -2
- package/vue/components.css +82 -76
- package/vue/editor/index.js +51 -67
|
@@ -23,6 +23,9 @@
|
|
|
23
23
|
<prop name="anticipatory" type="boolean" default="false"
|
|
24
24
|
>Keeps the button out of sight until it is wanted: at rest a fine pointer sees only a small guide dot, and the button appears on hover, on focus, or when
|
|
25
25
|
the pointer comes near inside a ui-affordance-scope. Touch devices and the solid variant always show it.</prop>
|
|
26
|
+
<prop name="guide" type="keyword" values="dot, bar" default="dot"
|
|
27
|
+
>The idle marker of an anticipatory button: dot for contextual actions, or a slim neutral rounded bar for a panel-edge control. The icon appears on hover or
|
|
28
|
+
keyboard focus; touch always shows the icon.</prop>
|
|
26
29
|
<prop name="round" type="boolean" default="false">Use a fully circular shape.</prop>
|
|
27
30
|
</defs>
|
|
28
31
|
<button
|
|
@@ -172,6 +175,13 @@
|
|
|
172
175
|
pointer-events: none;
|
|
173
176
|
}
|
|
174
177
|
|
|
178
|
+
:host([anticipatory][guide="bar"])::before {
|
|
179
|
+
inline-size: 2px;
|
|
180
|
+
block-size: 20px;
|
|
181
|
+
background: var(--ui-border-strong);
|
|
182
|
+
opacity: 1;
|
|
183
|
+
}
|
|
184
|
+
|
|
175
185
|
:host([anticipatory]):disabled::before {
|
|
176
186
|
opacity: 0;
|
|
177
187
|
}
|
|
@@ -226,7 +236,7 @@
|
|
|
226
236
|
border-color var(--ui-motion-fast) var(--ui-motion-ease),
|
|
227
237
|
color var(--ui-motion-fast) var(--ui-motion-ease),
|
|
228
238
|
box-shadow var(--ui-motion-base) var(--ui-motion-ease),
|
|
229
|
-
|
|
239
|
+
scale var(--ui-motion-fast) var(--ui-motion-ease);
|
|
230
240
|
}
|
|
231
241
|
|
|
232
242
|
@media (hover: none), (pointer: coarse) {
|
|
@@ -356,7 +366,7 @@
|
|
|
356
366
|
}
|
|
357
367
|
|
|
358
368
|
:host:active:enabled:not([aria-disabled="true"]) {
|
|
359
|
-
|
|
369
|
+
scale: var(--ui-icon-button-active-scale, 0.96);
|
|
360
370
|
}
|
|
361
371
|
|
|
362
372
|
:is(:host([loading]), :host([pending])) {
|
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
>Positions the description around its trigger. Start and end on top or bottom follow the writing direction.</prop>
|
|
11
11
|
<prop name="trigger" type="keyword" values="hover, click, focus" default="hover"
|
|
12
12
|
>How the trigger opens it. hover also opens on keyboard focus; click toggles it and suits a help button, where hovering a question mark says nothing; focus
|
|
13
|
-
opens only
|
|
13
|
+
opens only on keyboard-visible focus. Action activation dismisses hover/focus hints without removing focus; a fresh hover or keyboard focus can open them
|
|
14
|
+
again.</prop>
|
|
14
15
|
<prop name="showDelay" type="number" default="500">Waits this many milliseconds before showing after pointer entry.</prop>
|
|
15
16
|
<prop name="hideDelay" type="number" default="100">Waits this many milliseconds before hiding after pointer exit.</prop>
|
|
16
17
|
<prop name="inverse" type="boolean" default="false">Use the high-contrast inverse surface (dark on light themes, light on dark themes).</prop>
|
|
@@ -28,6 +28,7 @@ function connect(host) {
|
|
|
28
28
|
const overlayId = element.id || `ui-tooltip-${Math.random().toString(36).slice(2, 11)}`;
|
|
29
29
|
if (!element.id) element.id = overlayId;
|
|
30
30
|
let focused = false;
|
|
31
|
+
let pointerFocused = false;
|
|
31
32
|
let trigger = null;
|
|
32
33
|
let surface = null;
|
|
33
34
|
let showTimer = null;
|
|
@@ -71,6 +72,8 @@ function connect(host) {
|
|
|
71
72
|
}, Math.max(0, Number(host.props.hideDelay.value ?? 100)));
|
|
72
73
|
};
|
|
73
74
|
const onFocusin = () => {
|
|
75
|
+
// A pointer click may focus the action, but only visible keyboard focus keeps its hint open.
|
|
76
|
+
if (pointerFocused || !trigger?.matches(":focus-visible")) return;
|
|
74
77
|
focused = true;
|
|
75
78
|
clearTimers();
|
|
76
79
|
setOpen(true, "keyboard");
|
|
@@ -78,6 +81,7 @@ function connect(host) {
|
|
|
78
81
|
const onFocusout = (event) => {
|
|
79
82
|
if (event.relatedTarget && element.contains(event.relatedTarget)) return;
|
|
80
83
|
focused = false;
|
|
84
|
+
pointerFocused = false;
|
|
81
85
|
clearTimers();
|
|
82
86
|
setOpen(false, "keyboard");
|
|
83
87
|
};
|
|
@@ -88,6 +92,8 @@ function connect(host) {
|
|
|
88
92
|
else trigger.removeAttribute("aria-describedby");
|
|
89
93
|
trigger.removeEventListener("keydown", onKeydown);
|
|
90
94
|
trigger.removeEventListener("click", onClick);
|
|
95
|
+
trigger.removeEventListener("click", onActivate);
|
|
96
|
+
trigger.removeEventListener("pointerdown", onPointerDown);
|
|
91
97
|
trigger.removeAttribute("aria-expanded");
|
|
92
98
|
trigger.removeEventListener("pointerenter", onEnter);
|
|
93
99
|
trigger.removeEventListener("pointerleave", onLeave);
|
|
@@ -98,6 +104,18 @@ function connect(host) {
|
|
|
98
104
|
clearTimers();
|
|
99
105
|
setOpen(!host.state.internalOpen, "pointer");
|
|
100
106
|
};
|
|
107
|
+
const onPointerDown = () => {
|
|
108
|
+
pointerFocused = true;
|
|
109
|
+
focused = false;
|
|
110
|
+
clearTimers();
|
|
111
|
+
setOpen(false, "pointer");
|
|
112
|
+
};
|
|
113
|
+
const onActivate = (event) => {
|
|
114
|
+
// Action hints are spent once the action runs; the next hover or keyboard focus opens anew.
|
|
115
|
+
clearTimers();
|
|
116
|
+
focused = false;
|
|
117
|
+
setOpen(false, event.detail === 0 ? "keyboard" : "pointer");
|
|
118
|
+
};
|
|
101
119
|
const attach = () => {
|
|
102
120
|
if (!trigger) return;
|
|
103
121
|
const ids = new Set((trigger.getAttribute("aria-describedby") ?? "").split(/\s+/).filter(Boolean));
|
|
@@ -111,6 +129,8 @@ function connect(host) {
|
|
|
111
129
|
trigger.setAttribute("aria-expanded", String(Boolean(host.state.internalOpen)));
|
|
112
130
|
return;
|
|
113
131
|
}
|
|
132
|
+
trigger.addEventListener("pointerdown", onPointerDown);
|
|
133
|
+
trigger.addEventListener("click", onActivate);
|
|
114
134
|
if (how === "hover") {
|
|
115
135
|
trigger.addEventListener("pointerenter", onEnter);
|
|
116
136
|
trigger.addEventListener("pointerleave", onLeave);
|