noph-ui 0.8.13 → 0.8.15

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.
@@ -74,8 +74,8 @@
74
74
  </a>
75
75
  {/if}
76
76
 
77
- {#if title && element}
78
- <Tooltip anchor={element} id={tooltipId}>{title}</Tooltip>
77
+ {#if title}
78
+ <Tooltip id={tooltipId}>{title}</Tooltip>
79
79
  {/if}
80
80
 
81
81
  <style>
@@ -85,8 +85,8 @@
85
85
  </a>
86
86
  {/if}
87
87
 
88
- {#if title && element}
89
- <Tooltip anchor={element} id={tooltipId}>{title}</Tooltip>
88
+ {#if title}
89
+ <Tooltip id={tooltipId}>{title}</Tooltip>
90
90
  {/if}
91
91
 
92
92
  <style>
@@ -1,5 +1,8 @@
1
1
  <script lang="ts">
2
- let { children } = $props()
2
+ import type { Snippet } from 'svelte'
3
+
4
+ let { children, element = $bindable() }: { children: Snippet; element?: HTMLSpanElement } =
5
+ $props()
3
6
  </script>
4
7
 
5
8
  <svelte:head>
@@ -40,4 +43,4 @@
40
43
  </style>
41
44
  </svelte:head>
42
45
 
43
- <span class="np-icon">{@render children()}</span>
46
+ <span class="np-icon" bind:this={element}>{@render children()}</span>
@@ -1,5 +1,7 @@
1
+ import type { Snippet } from 'svelte';
1
2
  declare const Icon: import("svelte").Component<{
2
- children: any;
3
- }, {}, "">;
3
+ children: Snippet;
4
+ element?: HTMLSpanElement;
5
+ }, {}, "element">;
4
6
  type Icon = ReturnType<typeof Icon>;
5
7
  export default Icon;
@@ -87,7 +87,6 @@
87
87
  : '') + style}
88
88
  class={['text-field', attributes.class]}
89
89
  bind:this={element}
90
- bind:clientWidth
91
90
  >
92
91
  <div
93
92
  class="field"
@@ -102,8 +101,9 @@
102
101
  tabindex={attributes.disabled ? -1 : tabindex}
103
102
  aria-controls="listbox"
104
103
  aria-expanded={menuOpen}
105
- aria-label={label}
104
+ aria-label={attributes['aria-label'] || label}
106
105
  bind:this={field}
106
+ bind:clientWidth
107
107
  onclick={(event) => {
108
108
  event.preventDefault()
109
109
  menuElement?.showPopover()
@@ -161,6 +161,7 @@
161
161
  tabindex="-1"
162
162
  aria-label={label}
163
163
  {...attributes}
164
+ class={[]}
164
165
  bind:value
165
166
  bind:this={selectElement}
166
167
  >
@@ -1,17 +1,15 @@
1
1
  <script lang="ts">
2
2
  import type { TooltipProps } from './types.ts'
3
3
 
4
- let { children, anchor, ...attributes }: TooltipProps = $props()
4
+ let { children, element = $bindable(), id, ...attributes }: TooltipProps = $props()
5
5
  let clientWidth = $state(0)
6
6
  let clientHeight = $state(0)
7
7
  let innerHeight = $state(0)
8
8
  let innerWidth = $state(0)
9
- let anchorRect: DOMRect | undefined = $state(anchor.getBoundingClientRect())
9
+ let anchor: HTMLElement | undefined = $state()
10
+ let anchorRect: DOMRect | undefined = $state()
10
11
 
11
12
  const distanceToBorder = 8
12
- const refreshValues = () => {
13
- anchorRect = anchor?.getBoundingClientRect()
14
- }
15
13
 
16
14
  let calculateLeftPos = $derived.by(() => {
17
15
  if (!anchor || !anchorRect) {
@@ -37,18 +35,34 @@
37
35
  }
38
36
  return top
39
37
  })
40
- anchor.addEventListener('mouseenter', () => {
41
- refreshValues()
38
+ let setAnchor = (document: Document) => {
39
+ anchor = (document.querySelector(`[aria-describedby="${id}"]`) as HTMLElement) ?? undefined
40
+ }
41
+
42
+ $effect(() => {
43
+ if (anchor) {
44
+ anchor.addEventListener('pointerenter', () => {
45
+ anchorRect = anchor?.getBoundingClientRect() ?? undefined
46
+ element?.showPopover()
47
+ })
48
+ anchor.addEventListener('pointerleave', () => {
49
+ element?.hidePopover()
50
+ })
51
+ }
42
52
  })
43
53
  </script>
44
54
 
45
- <svelte:window bind:innerHeight bind:innerWidth onresize={refreshValues} onscroll={refreshValues} />
55
+ <svelte:document use:setAnchor />
56
+ <svelte:window bind:innerHeight bind:innerWidth />
46
57
 
47
58
  <div
48
59
  {...attributes}
49
- class={['tooltip', attributes.class]}
60
+ {id}
61
+ class={['np-tooltip', attributes.class]}
50
62
  style="top:{calculateTopPos}px;left:{calculateLeftPos}px;{attributes.style}"
51
63
  role="tooltip"
64
+ popover="manual"
65
+ bind:this={element}
52
66
  bind:clientWidth
53
67
  bind:clientHeight
54
68
  >
@@ -56,23 +70,31 @@
56
70
  </div>
57
71
 
58
72
  <style>
59
- .tooltip {
60
- visibility: hidden;
73
+ .np-tooltip {
61
74
  width: max-content;
62
- position: fixed;
75
+ margin: 0;
63
76
  background: var(--np-color-inverse-surface);
64
77
  color: var(--np-color-inverse-on-surface);
65
- scale: 0;
66
- z-index: 1;
67
78
  padding: 0.25rem 0.5rem;
68
79
  border-radius: 0.25rem;
69
80
  line-height: 1rem;
70
81
  font-size: 0.75rem;
71
- transition: scale 0.3s ease;
82
+ opacity: 0;
83
+ transition:
84
+ overlay 0.3s allow-discrete,
85
+ display 0.3s allow-discrete,
86
+ opacity 0.3s ease;
72
87
  }
73
- @media (hover: hover) {
74
- :global([aria-describedby]:hover + [role='tooltip']) {
75
- visibility: visible;
88
+ .np-tooltip:popover-open {
89
+ opacity: 1;
90
+ animation: scaleIn 0.3s ease;
91
+ }
92
+
93
+ @keyframes scaleIn {
94
+ from {
95
+ scale: 0;
96
+ }
97
+ to {
76
98
  scale: 1;
77
99
  }
78
100
  }
@@ -1,4 +1,4 @@
1
1
  import type { TooltipProps } from './types.ts';
2
- declare const Tooltip: import("svelte").Component<TooltipProps, {}, "">;
2
+ declare const Tooltip: import("svelte").Component<TooltipProps, {}, "element">;
3
3
  type Tooltip = ReturnType<typeof Tooltip>;
4
4
  export default Tooltip;
@@ -1,4 +1,4 @@
1
1
  import type { HTMLAttributes } from 'svelte/elements';
2
2
  export interface TooltipProps extends Omit<HTMLAttributes<HTMLDivElement>, 'role'> {
3
- anchor: HTMLElement;
3
+ element?: HTMLDivElement;
4
4
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "noph-ui",
3
- "version": "0.8.13",
3
+ "version": "0.8.15",
4
4
  "license": "MIT",
5
5
  "homepage": "https://noph.dev",
6
6
  "repository": {