wx-svelte-core 2.5.3 → 2.6.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.
Files changed (44) hide show
  1. package/package.json +3 -3
  2. package/readme.md +1 -3
  3. package/src/components/Avatar.svelte +2 -2
  4. package/src/components/Button.svelte +2 -0
  5. package/src/components/Calendar.svelte +2 -1
  6. package/src/components/Checkbox.svelte +7 -2
  7. package/src/components/CheckboxGroup.svelte +8 -2
  8. package/src/components/ColorBoard.svelte +7 -2
  9. package/src/components/ColorPicker.svelte +7 -1
  10. package/src/components/ColorSelect.svelte +7 -1
  11. package/src/components/Combo.svelte +9 -1
  12. package/src/components/Counter.svelte +4 -1
  13. package/src/components/DatePicker.svelte +3 -2
  14. package/src/components/DateRangePicker.svelte +3 -2
  15. package/src/components/Field.svelte +2 -1
  16. package/src/components/Icon.svelte +9 -3
  17. package/src/components/Modal.svelte +2 -1
  18. package/src/components/MultiCombo.svelte +6 -1
  19. package/src/components/Pager.svelte +2 -1
  20. package/src/components/Popup.svelte +7 -1
  21. package/src/components/RadioButton.svelte +2 -1
  22. package/src/components/RadioButtonGroup.svelte +2 -1
  23. package/src/components/RangeCalendar.svelte +3 -1
  24. package/src/components/RichSelect.svelte +4 -1
  25. package/src/components/Segmented.svelte +1 -0
  26. package/src/components/Select.svelte +3 -1
  27. package/src/components/SideArea.svelte +2 -2
  28. package/src/components/Slider.svelte +8 -1
  29. package/src/components/Switch.svelte +8 -2
  30. package/src/components/Tabs.svelte +3 -1
  31. package/src/components/Text.svelte +9 -4
  32. package/src/components/TextArea.svelte +4 -1
  33. package/src/components/TimePicker.svelte +3 -2
  34. package/src/components/Tooltip.svelte +382 -0
  35. package/src/components/TwoState.svelte +4 -0
  36. package/src/components/calendar/Month.svelte +2 -1
  37. package/src/components/calendar/Panel.svelte +4 -1
  38. package/src/components/helpers/SuggestDropdown.svelte +6 -1
  39. package/src/index.js +1 -0
  40. package/src/themes/Material.svelte +14 -1
  41. package/src/themes/Willow.svelte +14 -1
  42. package/src/themes/WillowDark.svelte +14 -1
  43. package/types/index.d.ts +70 -6
  44. package/whatsnew.md +17 -0
@@ -12,8 +12,8 @@
12
12
  placeholder = "",
13
13
  disabled = false,
14
14
  error = false,
15
- inputStyle = "",
16
15
  title = "",
16
+ tooltip,
17
17
  css = "",
18
18
  icon = "",
19
19
  clear = false,
@@ -54,6 +54,7 @@
54
54
  class:wx-error={error}
55
55
  class:wx-disabled={disabled}
56
56
  class:wx-clear={clear}
57
+ data-tooltip-text={tooltip}
57
58
  >
58
59
  {#if type == "password"}
59
60
  <input
@@ -64,7 +65,6 @@
64
65
  {disabled}
65
66
  {placeholder}
66
67
  type="password"
67
- style={inputStyle}
68
68
  {title}
69
69
  {oninput}
70
70
  onchange={change}
@@ -78,7 +78,6 @@
78
78
  {disabled}
79
79
  {placeholder}
80
80
  type="number"
81
- style={inputStyle}
82
81
  {title}
83
82
  {oninput}
84
83
  onchange={change}
@@ -92,7 +91,6 @@
92
91
  {disabled}
93
92
  {placeholder}
94
93
  {title}
95
- style={inputStyle}
96
94
  {oninput}
97
95
  onchange={change}
98
96
  />
@@ -204,4 +202,11 @@
204
202
  border-color: var(--wx-color-danger);
205
203
  color: var(--wx-color-danger);
206
204
  }
205
+ .wx-date-input input {
206
+ cursor: pointer;
207
+ width: 100%;
208
+ padding-right: calc(
209
+ var(--wx-input-icon-size) + var(--wx-input-icon-indent) * 2
210
+ );
211
+ }
207
212
  </style>
@@ -6,9 +6,11 @@
6
6
  id,
7
7
  placeholder = "",
8
8
  title = "",
9
+ tooltip,
9
10
  disabled = false,
10
11
  error = false,
11
12
  readonly = false,
13
+ css = "",
12
14
  onchange,
13
15
  } = $props();
14
16
 
@@ -16,7 +18,7 @@
16
18
  </script>
17
19
 
18
20
  <textarea
19
- class="wx-textarea"
21
+ class="wx-textarea {css}"
20
22
  class:wx-error={error}
21
23
  bind:value
22
24
  id={inputId}
@@ -26,6 +28,7 @@
26
28
  {title}
27
29
  oninput={() => onchange && onchange({ value, input: true })}
28
30
  onchange={() => onchange && onchange({ value })}
31
+ data-tooltip-text={tooltip}
29
32
  ></textarea>
30
33
 
31
34
  <style>
@@ -17,6 +17,7 @@
17
17
  value = $bindable(defValue),
18
18
  id,
19
19
  title = "",
20
+ tooltip,
20
21
  css = "",
21
22
  disabled = false,
22
23
  error = false,
@@ -129,14 +130,14 @@
129
130
  >
130
131
  <Text
131
132
  id={inputId}
132
- {css}
133
+ css={`wx-date-input ${css}`}
133
134
  {title}
135
+ {tooltip}
134
136
  value={textValue}
135
137
  readonly={true}
136
138
  {disabled}
137
139
  {error}
138
140
  icon="wxi-clock"
139
- inputStyle="cursor: pointer; width: 100%; padding-right: calc(var(--wx-input-icon-size) + var(--wx-input-icon-indent) * 2);"
140
141
  />
141
142
 
142
143
  {#if popup && !disabled}
@@ -0,0 +1,382 @@
1
+ <script>
2
+ import { calculatePosition, getAbsParent } from "@svar-ui/lib-dom";
3
+ import Portal from "./Portal.svelte";
4
+
5
+ const {
6
+ at = "top-center",
7
+ arrow = false,
8
+ touch = false,
9
+ overflow = false,
10
+ delay = 300,
11
+ content: Content = null,
12
+ resolver = defaultResolver,
13
+ children,
14
+ css = "",
15
+ } = $props();
16
+
17
+ const side = $derived.by(() => getSide(at));
18
+ const align = $derived.by(() => getAlign(at));
19
+ const resolvedAt = $derived.by(() => {
20
+ if (at === "point") return "point";
21
+ return `${side}-${align}`;
22
+ });
23
+
24
+ let areaNode;
25
+ let isHovered = false;
26
+ let tooltipNode = $state(null);
27
+ let match = $state(null); // { result, anchor, mouseX, mouseY }
28
+ let position = $state(null); // { x, y, z, side, arrowOffset }
29
+ let firstAnchor = $state(false);
30
+
31
+ // render only when there is displayable content
32
+ const shouldRender = $derived(
33
+ match !== null && (!!match.result || Content != null)
34
+ );
35
+
36
+ function getSide(at) {
37
+ if (at === "point") return "point";
38
+ const split = at.split("-");
39
+ return split[0];
40
+ }
41
+
42
+ function getAlign(at) {
43
+ if (at === "point") return "center";
44
+ const split = at.split("-");
45
+ return split.length === 1 ? "center" : split[1];
46
+ }
47
+
48
+ function readCSSPropertyInt(node, property, defaultValue) {
49
+ const value = getComputedStyle(node).getPropertyValue(property);
50
+ return parseInt(value) || defaultValue;
51
+ }
52
+
53
+ function getPointOffset() {
54
+ return readCSSPropertyInt(tooltipNode, "--wx-tooltip-point-offset", 14);
55
+ }
56
+
57
+ function getArrowSize() {
58
+ return readCSSPropertyInt(tooltipNode, "--wx-tooltip-arrow-size", 6);
59
+ }
60
+
61
+ // Compute the CSS arrow offset relative to the anchor
62
+ function getArrowOffset(arrowSize, result, rect, body) {
63
+ if (side === "point") return "50%";
64
+ const bodyRect = body?.getBoundingClientRect() ?? { top: 0, left: 0 };
65
+ const h = arrowSize / 2;
66
+
67
+ let anchorPoint;
68
+ let tooltipEdge;
69
+ if (side === "top" || side === "bottom") {
70
+ tooltipEdge = result.x - (body?.scrollLeft ?? 0) + bodyRect.left;
71
+ if (align === "start") anchorPoint = rect.left + arrowSize + h;
72
+ else if (align === "end") anchorPoint = rect.right - arrowSize - h;
73
+ else anchorPoint = rect.left + rect.width / 2;
74
+ } else {
75
+ tooltipEdge = result.y - (body?.scrollTop ?? 0) + bodyRect.top;
76
+ if (align === "start") anchorPoint = rect.top + arrowSize + h;
77
+ else if (align === "end") anchorPoint = rect.bottom - arrowSize - h;
78
+ else anchorPoint = rect.top + rect.height / 2;
79
+ }
80
+
81
+ return `${anchorPoint - tooltipEdge}px`;
82
+ }
83
+
84
+ // Positioning of the tooltip
85
+ $effect(() => {
86
+ if (!tooltipNode || !match) return void (position = null);
87
+
88
+ // Offset from the mouse cursor when at="point"
89
+ const offset = at === "point" ? getPointOffset() : 0;
90
+
91
+ // Calculate the position of the tooltip
92
+ const result = calculatePosition(
93
+ tooltipNode,
94
+ match.anchor,
95
+ resolvedAt,
96
+ match.mouseX + offset,
97
+ match.mouseY + offset
98
+ );
99
+
100
+ if (result === null) return void (position = null);
101
+
102
+ // Detect if calculatePosition flipped to the opposite side
103
+ const anchorRect = match.anchor.getBoundingClientRect();
104
+ const body = getAbsParent(tooltipNode);
105
+ const realSide = getSide(result.at);
106
+
107
+ // Add gap for the arrow if needed, using realSide for direction
108
+ let arrowOffset = "50%";
109
+ if (result && arrow && at !== "point") {
110
+ const arrowSize = getArrowSize();
111
+ if (realSide === "top") result.y -= arrowSize;
112
+ else if (realSide === "bottom") result.y += arrowSize;
113
+ else if (realSide === "left") result.x -= arrowSize;
114
+ else if (realSide === "right") result.x += arrowSize;
115
+ arrowOffset = getArrowOffset(arrowSize, result, anchorRect, body);
116
+ }
117
+
118
+ // Submit the result to the position state
119
+ const minZ = readCSSPropertyInt(
120
+ tooltipNode,
121
+ "--wx-tooltip-z-index",
122
+ 1002
123
+ );
124
+
125
+ position = {
126
+ x: Math.round(result.x),
127
+ y: Math.round(result.y),
128
+ z: Math.max(result.z, minZ),
129
+ side: realSide,
130
+ arrowOffset,
131
+ };
132
+ });
133
+
134
+ function defaultResolver(element) {
135
+ if (overflow && element.scrollWidth <= element.clientWidth) return null;
136
+ const text = element.getAttribute?.("data-tooltip-text");
137
+ return text ? text : null;
138
+ }
139
+
140
+ function walk(node, ev) {
141
+ if (!isHovered) return null;
142
+
143
+ // Disable tooltip on touch devices if prop touch == false
144
+ const touchD = "ontouchstart" in window || navigator.maxTouchPoints > 0;
145
+ if (touchD && !touch) return null;
146
+
147
+ for (; node && node !== areaNode; node = node.parentNode) {
148
+ if (node.nodeType !== Node.ELEMENT_NODE) continue;
149
+
150
+ const result = resolver(node, ev);
151
+ if (result == null) continue;
152
+
153
+ return {
154
+ result,
155
+ anchor: node,
156
+ mouseX: ev.clientX,
157
+ mouseY: ev.clientY,
158
+ };
159
+ }
160
+
161
+ return null;
162
+ }
163
+
164
+ let timer;
165
+ let hiding = false;
166
+ function debounce(fn, ...args) {
167
+ clearTimeout(timer);
168
+ timer = setTimeout(fn, delay, ...args);
169
+ }
170
+
171
+ function onmousemove(ev) {
172
+ // (1) Ignore if the most closely hovered tooltip area is not this one (in case of nested tooltips)
173
+ if (ev.target.closest(".wx-tooltip-area") !== areaNode) {
174
+ isHovered = false;
175
+ match = null;
176
+ clearTimeout(timer);
177
+ return;
178
+ }
179
+ isHovered = true;
180
+
181
+ // (2) If the cursor is still within the anchor element
182
+ if (match?.anchor?.contains(ev.target)) {
183
+ clearTimeout(timer);
184
+ hiding = false;
185
+ const result = resolver(ev.target, ev);
186
+ if (result != null) {
187
+ match = {
188
+ result,
189
+ anchor: ev.target,
190
+ mouseX: ev.clientX,
191
+ mouseY: ev.clientY,
192
+ };
193
+ return;
194
+ }
195
+ }
196
+
197
+ // (3) Cursor left the anchor - walk for a new anchor
198
+ if (match !== null) {
199
+ const result = walk(ev.target, ev);
200
+ if (!result) {
201
+ if (!hiding) {
202
+ hiding = true;
203
+ debounce(() => {
204
+ hiding = false;
205
+ match = null;
206
+ });
207
+ }
208
+ } else {
209
+ clearTimeout(timer);
210
+ hiding = false;
211
+ match = result;
212
+ firstAnchor = false;
213
+ }
214
+ } else {
215
+ debounce(() => {
216
+ match = walk(ev.target, ev);
217
+ firstAnchor = true;
218
+ });
219
+ }
220
+ }
221
+
222
+ function onmouseleave() {
223
+ debounce(() => {
224
+ hiding = false;
225
+ isHovered = false;
226
+ match = null;
227
+ });
228
+ }
229
+
230
+ function onscroll() {
231
+ clearTimeout(timer);
232
+ match = null;
233
+ }
234
+
235
+ $effect(() => {
236
+ window.addEventListener("scroll", onscroll, {
237
+ capture: true,
238
+ passive: true,
239
+ });
240
+
241
+ return () => {
242
+ clearTimeout(timer);
243
+ window.removeEventListener("scroll", onscroll, { capture: true });
244
+ };
245
+ });
246
+ </script>
247
+
248
+ <div
249
+ bind:this={areaNode}
250
+ class="wx-tooltip-area"
251
+ role="none"
252
+ {onmousemove}
253
+ {onmouseleave}
254
+ >
255
+ {#if shouldRender}
256
+ <Portal>
257
+ <div
258
+ class={`wx-tooltip ${css}`}
259
+ class:wx-arrow-top={arrow && position?.side === "top"}
260
+ class:wx-arrow-bottom={arrow && position?.side === "bottom"}
261
+ class:wx-arrow-left={arrow && position?.side === "left"}
262
+ class:wx-arrow-right={arrow && position?.side === "right"}
263
+ class:wx-tooltip-transition={!firstAnchor}
264
+ role="tooltip"
265
+ bind:this={tooltipNode}
266
+ style="
267
+ translate:{position?.x ?? 0}px {position?.y ?? 0}px;
268
+ z-index:{position?.z ?? 20};
269
+ {!position ? 'visibility:hidden;' : ''}
270
+ --wx-arrow-offset:{position?.arrowOffset ?? '50%'};
271
+ "
272
+ >
273
+ <div class="wx-tooltip-wrapper">
274
+ <div class="wx-tooltip-inner">
275
+ {#if typeof match.result === "string"}
276
+ {#if Content}
277
+ <Content data={match.result} />
278
+ {:else}
279
+ <div class="wx-tooltip-text">
280
+ {match.result}
281
+ </div>
282
+ {/if}
283
+ {:else if Content}
284
+ <Content {...match.result} />
285
+ {:else}
286
+ <div class="wx-tooltip-text">
287
+ {match.result?.data}
288
+ </div>
289
+ {/if}
290
+ </div>
291
+ </div>
292
+ </div>
293
+ </Portal>
294
+ {/if}
295
+
296
+ {@render children()}
297
+ </div>
298
+
299
+ <style>
300
+ .wx-tooltip-area {
301
+ position: relative;
302
+ height: 100%;
303
+ width: 100%;
304
+ }
305
+
306
+ .wx-tooltip {
307
+ pointer-events: none;
308
+ position: absolute;
309
+ top: 0;
310
+ left: 0;
311
+ border: 1px solid var(--wx-tooltip-border, transparent);
312
+ border-radius: var(--wx-border-radius);
313
+ background-color: var(--wx-tooltip-background);
314
+ color: var(--wx-tooltip-font-color);
315
+ animation: wx-tooltip-appear 100ms ease-out;
316
+ }
317
+
318
+ .wx-tooltip-transition {
319
+ transition: translate 50ms ease;
320
+ }
321
+
322
+ @keyframes wx-tooltip-appear {
323
+ from {
324
+ opacity: 0;
325
+ }
326
+ to {
327
+ opacity: 1;
328
+ }
329
+ }
330
+
331
+ .wx-tooltip-inner {
332
+ border-radius: var(--wx-border-radius);
333
+ overflow: hidden;
334
+ }
335
+
336
+ .wx-tooltip-text {
337
+ padding: var(--wx-tooltip-padding);
338
+ font: var(--wx-tooltip-font);
339
+ color: var(--wx-tooltip-font-color);
340
+ }
341
+
342
+ .wx-tooltip.wx-arrow-top::before,
343
+ .wx-tooltip.wx-arrow-bottom::before,
344
+ .wx-tooltip.wx-arrow-left::before,
345
+ .wx-tooltip.wx-arrow-right::before {
346
+ content: "";
347
+ position: absolute;
348
+ border: var(--wx-tooltip-arrow-size, 6px) solid transparent;
349
+ }
350
+
351
+ .wx-tooltip.wx-arrow-top::before {
352
+ top: 100%;
353
+ left: var(--wx-arrow-offset, 50%);
354
+ transform: translateX(-50%);
355
+ border-top-color: var(--wx-tooltip-background);
356
+ filter: drop-shadow(0 1px 0 var(--wx-tooltip-border, transparent));
357
+ }
358
+
359
+ .wx-tooltip.wx-arrow-bottom::before {
360
+ bottom: 100%;
361
+ left: var(--wx-arrow-offset, 50%);
362
+ transform: translateX(-50%);
363
+ border-bottom-color: var(--wx-tooltip-background);
364
+ filter: drop-shadow(0 -1px 0 var(--wx-tooltip-border, transparent));
365
+ }
366
+
367
+ .wx-tooltip.wx-arrow-left::before {
368
+ top: var(--wx-arrow-offset, 50%);
369
+ left: 100%;
370
+ transform: translateY(-50%);
371
+ border-left-color: var(--wx-tooltip-background);
372
+ filter: drop-shadow(1px 0 0 var(--wx-tooltip-border, transparent));
373
+ }
374
+
375
+ .wx-tooltip.wx-arrow-right::before {
376
+ top: var(--wx-arrow-offset, 50%);
377
+ right: 100%;
378
+ transform: translateY(-50%);
379
+ border-right-color: var(--wx-tooltip-background);
380
+ filter: drop-shadow(-1px 0 0 var(--wx-tooltip-border, transparent));
381
+ }
382
+ </style>
@@ -9,6 +9,7 @@
9
9
  iconActive = "",
10
10
  onclick,
11
11
  title = "",
12
+ tooltip,
12
13
  css = "",
13
14
  text = "",
14
15
  textActive = "",
@@ -32,6 +33,7 @@
32
33
  {#if value && active}
33
34
  <Button
34
35
  {title}
36
+ {tooltip}
35
37
  text={(value && textActive) || text}
36
38
  {css}
37
39
  type={typeStr}
@@ -44,6 +46,7 @@
44
46
  {:else if children}
45
47
  <Button
46
48
  {title}
49
+ {tooltip}
47
50
  text={(value && textActive) || text}
48
51
  {css}
49
52
  type={typeStr}
@@ -56,6 +59,7 @@
56
59
  {:else}
57
60
  <Button
58
61
  {title}
62
+ {tooltip}
59
63
  text={(value && textActive) || text}
60
64
  {css}
61
65
  type={typeStr}
@@ -8,6 +8,7 @@
8
8
  current = $bindable(),
9
9
  part = "",
10
10
  markers = null,
11
+ css = "",
11
12
  oncancel,
12
13
  onchange,
13
14
  } = $props();
@@ -103,7 +104,7 @@
103
104
  });
104
105
  </script>
105
106
 
106
- <div>
107
+ <div class="wx-month {css}">
107
108
  <div class="wx-weekdays">
108
109
  {#each weekdays as day}
109
110
  <div class="wx-weekday">{day}</div>
@@ -12,6 +12,7 @@
12
12
  part = "normal",
13
13
  markers = null,
14
14
  buttons = ["clear", "today"],
15
+ css = "",
15
16
  onshift: shift,
16
17
  onchange: change,
17
18
  } = $props();
@@ -63,7 +64,9 @@
63
64
  </script>
64
65
 
65
66
  <div
66
- class="wx-calendar {part !== 'normal' && part !== 'both' ? 'wx-part' : ''}"
67
+ class="wx-calendar {part !== 'normal' && part !== 'both'
68
+ ? 'wx-part'
69
+ : ''} {css}"
67
70
  >
68
71
  <div class="wx-wrap">
69
72
  <Header date={current} {part} {type} {onshift} />
@@ -152,6 +152,11 @@
152
152
  );
153
153
  });
154
154
 
155
+ $effect(() => {
156
+ items;
157
+ if (virtualized) scrollTop = 0;
158
+ });
159
+
155
160
  onMount(() => {
156
161
  onready &&
157
162
  onready({
@@ -165,7 +170,7 @@
165
170
  {#snippet itemContent({ data })}
166
171
  {#if checkboxes}
167
172
  <Checkbox
168
- style="margin-right: 8px; pointer-events: none;"
173
+ css="wx-list-checkbox"
169
174
  name={data.id}
170
175
  value={value && value.includes(data.id)}
171
176
  />
package/src/index.js CHANGED
@@ -31,6 +31,7 @@ export { default as Calendar } from "./components/Calendar.svelte";
31
31
  export { default as Month } from "./components/calendar/Month.svelte";
32
32
  export { default as RangeCalendar } from "./components/RangeCalendar.svelte";
33
33
  export { default as TimePicker } from "./components/TimePicker.svelte";
34
+ export { default as Tooltip } from "./components/Tooltip.svelte";
34
35
  export { default as TwoState } from "./components/TwoState.svelte";
35
36
  export { default as Modal } from "./components/Modal.svelte";
36
37
  export { default as ModalArea } from "./components/ModalArea.svelte";
@@ -78,7 +78,8 @@
78
78
  /* end icons */
79
79
 
80
80
  /* other */
81
- --wx-border: 1px solid #dfdfdf;
81
+ --wx-border-color: #dfdfdf;
82
+ --wx-border: 1px solid var(--wx-border-color);
82
83
  --wx-border-radius: 2px;
83
84
  --wx-radius-medium: var(--wx-border-radius);
84
85
 
@@ -312,6 +313,18 @@
312
313
  --wx-calendar-controls-font-weight: var(--wx-button-font-weight);
313
314
  --wx-calendar-controls-font-color: var(--wx-color-link);
314
315
  /* end calendar */
316
+
317
+ /* tooltip */
318
+ --wx-tooltip-font: var(--wx-font-weight) var(--wx-font-size)
319
+ var(--wx-font-family);
320
+ --wx-tooltip-font-color: #ffffff;
321
+ --wx-tooltip-background: #000000b2;
322
+ --wx-tooltip-border: transparent;
323
+ --wx-tooltip-padding: 4px 8px;
324
+ --wx-tooltip-point-offset: 14px;
325
+ --wx-tooltip-arrow-size: 6px;
326
+ --wx-tooltip-z-index: 1002;
327
+ /* end tooltip */
315
328
  }
316
329
 
317
330
  :global(.wx-material-theme) {
@@ -75,7 +75,8 @@
75
75
  /* end icons */
76
76
 
77
77
  /* other */
78
- --wx-border: 1px solid #e6e6e6;
78
+ --wx-border-color: #e6e6e6;
79
+ --wx-border: 1px solid var(--wx-border-color);
79
80
  --wx-border-radius: 3px;
80
81
  --wx-radius-major: 6px;
81
82
 
@@ -314,6 +315,18 @@
314
315
  --wx-calendar-controls-font-weight: var(--wx-font-weight);
315
316
  --wx-calendar-controls-font-color: var(--wx-color-font);
316
317
  /* end calendar */
318
+
319
+ /* tooltip */
320
+ --wx-tooltip-font: var(--wx-font-weight) var(--wx-font-size)
321
+ var(--wx-font-family);
322
+ --wx-tooltip-font-color: #ffffff;
323
+ --wx-tooltip-background: #2c2f3c;
324
+ --wx-tooltip-border: transparent;
325
+ --wx-tooltip-padding: 4px 8px;
326
+ --wx-tooltip-point-offset: 14px;
327
+ --wx-tooltip-arrow-size: 6px;
328
+ --wx-tooltip-z-index: 1002;
329
+ /* end tooltip */
317
330
  }
318
331
 
319
332
  :global(.wx-willow-theme) {
@@ -75,7 +75,8 @@
75
75
  /* end icons */
76
76
 
77
77
  /* other */
78
- --wx-border: 1px solid #384047;
78
+ --wx-border-color: #384047;
79
+ --wx-border: 1px solid var(--wx-border-color);
79
80
  --wx-border-radius: 3px;
80
81
  --wx-radius-major: 6px;
81
82
 
@@ -310,6 +311,18 @@
310
311
  --wx-calendar-controls-font-weight: var(--wx-font-weight);
311
312
  --wx-calendar-controls-font-color: var(--wx-color-font);
312
313
  /* end calendar */
314
+
315
+ /* tooltip */
316
+ --wx-tooltip-font: var(--wx-font-weight) var(--wx-font-size)
317
+ var(--wx-font-family);
318
+ --wx-tooltip-font-color: #ffffff;
319
+ --wx-tooltip-background: #2c2f3c;
320
+ --wx-tooltip-border: var(--wx-border-color);
321
+ --wx-tooltip-padding: 4px 8px;
322
+ --wx-tooltip-point-offset: 14px;
323
+ --wx-tooltip-arrow-size: 6px;
324
+ --wx-tooltip-z-index: 1002;
325
+ /* end tooltip */
313
326
  }
314
327
 
315
328
  :global(.wx-willow-dark-theme) {