@toolr/ui-design 0.1.10 → 0.1.12

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/agent-rules.json CHANGED
@@ -54,7 +54,7 @@
54
54
  "color": "#fb923c",
55
55
  "rules": [
56
56
  { "type": "do", "text": "Select, Tooltip, Modal all render via createPortal to document.body — parent overflow:hidden and z-index don't affect them" },
57
- { "type": "do", "text": "Popover background is rgba(0,0,0,0.8) — semi-transparent by design, which is why body background matters" },
57
+ { "type": "do", "text": "Popover background is rgba(0,0,0,0.9) — semi-transparent by design, which is why body background matters" },
58
58
  { "type": "dont", "text": "Never wrap portal components in overflow:hidden expecting to clip them — they escape to document.body" }
59
59
  ]
60
60
  },
@@ -140,11 +140,6 @@ export function isLightTheme(themeId: ThemeId): boolean {
140
140
  /**
141
141
  * Apply a theme to the document by setting CSS custom properties on the root element.
142
142
  *
143
- * IMPORTANT — body background: Portal-based components (Select, Tooltip) render at
144
- * document.body via createPortal. Their backgrounds use --popover which is semi-transparent
145
- * (rgba(0,0,0,0.8)). If <body> has no background-color, the browser default (white) bleeds
146
- * through, making dropdowns/tooltips appear gray instead of dark.
147
- *
148
143
  * Consuming apps MUST set: body { background-color: var(--background); }
149
144
  */
150
145
  export function applyTheme(themeId: ThemeId, accentHue: number | null, dims: Record<SurfaceKey, number> = DEFAULT_DIMS, outline: number = DEFAULT_OUTLINE, root: HTMLElement = document.documentElement): void {
@@ -186,4 +181,5 @@ export function applyTheme(themeId: ThemeId, accentHue: number | null, dims: Rec
186
181
  root.style.setProperty('--surface-hover', `${glassBase}${alphaToHex(10 / 100)}`)
187
182
  }
188
183
 
184
+
189
185
  }
@@ -26,7 +26,7 @@ import { useAccentColor } from '../lib/accent-context.ts'
26
26
  export interface InputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'onChange' | 'size' | 'type'> {
27
27
  value: string
28
28
  onChange: (value: string) => void
29
- type?: 'text' | 'search' | 'password'
29
+ type?: 'text' | 'search' | 'password' | 'email'
30
30
  debounceMs?: number
31
31
  error?: boolean | string
32
32
  variant?: 'filled' | 'outline'
@@ -247,6 +247,29 @@ export function Tooltip({
247
247
  return () => window.removeEventListener('scroll', handleScroll, true)
248
248
  }, [trigger, isVisible, position, align])
249
249
 
250
+ // Dismiss hover tooltips on scroll, keyboard, click elsewhere, or window blur to prevent orphans
251
+ useEffect(() => {
252
+ if (trigger !== 'hover' || !isVisible) return
253
+ const dismiss = () => setIsVisible(false)
254
+ window.addEventListener('scroll', dismiss, true)
255
+ window.addEventListener('keydown', dismiss)
256
+ window.addEventListener('pointerdown', dismiss)
257
+ window.addEventListener('blur', dismiss)
258
+ return () => {
259
+ window.removeEventListener('scroll', dismiss, true)
260
+ window.removeEventListener('keydown', dismiss)
261
+ window.removeEventListener('pointerdown', dismiss)
262
+ window.removeEventListener('blur', dismiss)
263
+ }
264
+ }, [trigger, isVisible])
265
+
266
+ // Clear pending hide timeout on unmount
267
+ useEffect(() => {
268
+ return () => {
269
+ if (hideTimeoutRef.current) clearTimeout(hideTimeoutRef.current)
270
+ }
271
+ }, [])
272
+
250
273
  const resolvedPos = position === 'auto' ? actualPosition : position
251
274
  const arrowClasses = getArrowClasses(resolvedPos, align)
252
275
 
package/dist/index.d.ts CHANGED
@@ -58,11 +58,6 @@ declare function isLightTheme(themeId: ThemeId): boolean;
58
58
  /**
59
59
  * Apply a theme to the document by setting CSS custom properties on the root element.
60
60
  *
61
- * IMPORTANT — body background: Portal-based components (Select, Tooltip) render at
62
- * document.body via createPortal. Their backgrounds use --popover which is semi-transparent
63
- * (rgba(0,0,0,0.8)). If <body> has no background-color, the browser default (white) bleeds
64
- * through, making dropdowns/tooltips appear gray instead of dark.
65
- *
66
61
  * Consuming apps MUST set: body { background-color: var(--background); }
67
62
  */
68
63
  declare function applyTheme(themeId: ThemeId, accentHue: number | null, dims?: Record<SurfaceKey, number>, outline?: number, root?: HTMLElement): void;
@@ -400,7 +395,7 @@ declare function Toggle({ checked, onChange, disabled, size, className, accentCo
400
395
  interface InputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'onChange' | 'size' | 'type'> {
401
396
  value: string;
402
397
  onChange: (value: string) => void;
403
- type?: 'text' | 'search' | 'password';
398
+ type?: 'text' | 'search' | 'password' | 'email';
404
399
  debounceMs?: number;
405
400
  error?: boolean | string;
406
401
  variant?: 'filled' | 'outline';
package/dist/index.js CHANGED
@@ -566,6 +566,25 @@ function Tooltip({
566
566
  window.addEventListener("scroll", handleScroll, true);
567
567
  return () => window.removeEventListener("scroll", handleScroll, true);
568
568
  }, [trigger, isVisible, position, align]);
569
+ useEffect2(() => {
570
+ if (trigger !== "hover" || !isVisible) return;
571
+ const dismiss = () => setIsVisible(false);
572
+ window.addEventListener("scroll", dismiss, true);
573
+ window.addEventListener("keydown", dismiss);
574
+ window.addEventListener("pointerdown", dismiss);
575
+ window.addEventListener("blur", dismiss);
576
+ return () => {
577
+ window.removeEventListener("scroll", dismiss, true);
578
+ window.removeEventListener("keydown", dismiss);
579
+ window.removeEventListener("pointerdown", dismiss);
580
+ window.removeEventListener("blur", dismiss);
581
+ };
582
+ }, [trigger, isVisible]);
583
+ useEffect2(() => {
584
+ return () => {
585
+ if (hideTimeoutRef.current) clearTimeout(hideTimeoutRef.current);
586
+ };
587
+ }, []);
569
588
  const resolvedPos = position === "auto" ? actualPosition : position;
570
589
  const arrowClasses = getArrowClasses(resolvedPos, align);
571
590
  const tooltipContent = /* @__PURE__ */ jsxs3(
@@ -24,7 +24,7 @@
24
24
  --dialog-backdrop: rgba(0, 0, 0, 0.95);
25
25
 
26
26
  /* Popover: floating panels, dropdown menus */
27
- --popover: rgba(0, 0, 0, 0.8);
27
+ --popover: rgba(0, 0, 0, 0.9);
28
28
  --popover-foreground: rgba(255, 255, 255, 0.83);
29
29
 
30
30
  /* Muted: subdued elements, disabled states */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@toolr/ui-design",
3
- "version": "0.1.10",
3
+ "version": "0.1.12",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -24,7 +24,7 @@
24
24
  --dialog-backdrop: rgba(0, 0, 0, 0.95);
25
25
 
26
26
  /* Popover: floating panels, dropdown menus */
27
- --popover: rgba(0, 0, 0, 0.8);
27
+ --popover: rgba(0, 0, 0, 0.9);
28
28
  --popover-foreground: rgba(255, 255, 255, 0.83);
29
29
 
30
30
  /* Muted: subdued elements, disabled states */