@oscarpalmer/oui 0.23.1 → 0.25.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 (40) hide show
  1. package/dist/css/{tooltip.css → floatable.css} +59 -24
  2. package/dist/css/reset.css +17 -0
  3. package/dist/js/dialog.d.mts +38 -0
  4. package/dist/js/dialog.mjs +92 -0
  5. package/dist/js/embedded-84gxpReS.d.mts +64 -0
  6. package/dist/js/embedded-BpwzMSEF.d.mts +26 -0
  7. package/dist/js/floatable/embedded.d.mts +2 -0
  8. package/dist/js/floatable/embedded.mjs +146 -0
  9. package/dist/js/floatable/standalone.d.mts +2 -0
  10. package/dist/js/floatable/standalone.mjs +2 -0
  11. package/dist/js/focus-trap/embedded.d.mts +1 -25
  12. package/dist/js/focus-trap/embedded.mjs +1 -1
  13. package/dist/js/index.d.mts +5 -2
  14. package/dist/js/index.mjs +7 -4
  15. package/dist/js/internal/attributable.mjs +4 -3
  16. package/dist/js/internal/draggable.mjs +1 -1
  17. package/dist/js/popover.d.mts +38 -1
  18. package/dist/js/popover.mjs +81 -38
  19. package/dist/js/sortable.mjs +7 -5
  20. package/dist/js/splitter.mjs +18 -14
  21. package/dist/js/tooltip.d.mts +33 -1
  22. package/dist/js/tooltip.mjs +91 -48
  23. package/package.json +2 -2
  24. package/src/css/{tooltip.scss → floatable.scss} +47 -5
  25. package/src/css/mixins.scss +0 -2
  26. package/src/css/reset.scss +17 -0
  27. package/src/js/dialog.ts +188 -0
  28. package/src/js/floatable/embedded.ts +302 -0
  29. package/src/js/floatable/standalone.ts +1 -0
  30. package/src/js/index.ts +4 -2
  31. package/src/js/internal/attributable.ts +5 -3
  32. package/src/js/popover.ts +146 -48
  33. package/src/js/sortable.ts +8 -5
  34. package/src/js/splitter.ts +26 -9
  35. package/src/js/tooltip.ts +138 -51
  36. package/dist/css/popover.css +0 -30
  37. package/dist/js/internal/floatable.d.mts +0 -18
  38. package/dist/js/internal/floatable.mjs +0 -67
  39. package/src/css/popover.scss +0 -10
  40. package/src/js/internal/floatable.ts +0 -118
@@ -1,60 +1,103 @@
1
+ import { createFloatable, getOnBeforeToggleListener } from "./floatable/embedded.mjs";
1
2
  import { attributable } from "./internal/attributable.mjs";
2
- import { createFocusTrap, removeFocusTrap } from "./focus-trap/embedded.mjs";
3
- import { createFloatable, removeFloatable } from "./internal/floatable.mjs";
3
+ import { createFocusTrap } from "./focus-trap/embedded.mjs";
4
4
  import { on } from "@oscarpalmer/toretto/event";
5
+ import { isHTMLOrSVGElement } from "@oscarpalmer/toretto/is";
5
6
  //#region src/js/popover.ts
6
- var Popover = class {
7
- element;
8
- anchor;
9
- floatable;
10
- focusTrap;
11
- listener;
12
- constructor(element) {
13
- this.element = element;
14
- this.anchor = element.ownerDocument.querySelector(`[popovertarget="${element.id}"]`);
15
- this.floatable = createFloatable(this.anchor, element, options);
16
- this.focusTrap = createFocusTrap(element, { noescape: true });
17
- this.listener = on(element, EVENT_TOGGLE, (event) => {
18
- if (event.newState === STATE_OPEN) {
19
- ignoreFocus = false;
20
- this.floatable?.update();
21
- element.focus();
22
- } else if (!ignoreFocus) this.anchor?.focus();
23
- });
24
- this.element.setAttribute(ATTRIBUTE_CONTENT, "");
25
- this.floatable?.update();
7
+ var OuiPopover = class {
8
+ #state;
9
+ /**
10
+ * Is the popover open?
11
+ */
12
+ get open() {
13
+ return this.#state.content.checkVisibility();
14
+ }
15
+ constructor(state) {
16
+ this.#state = state;
17
+ this.#state.floatable.update();
26
18
  }
27
- destroy() {
28
- this.focusTrap?.destroy();
29
- removeFloatable(this.element);
30
- removeFocusTrap(this.element);
31
- this.element.removeAttribute(ATTRIBUTE_CONTENT);
32
- this.anchor = null;
33
- this.element = null;
19
+ /**
20
+ * Closes the popover
21
+ */
22
+ hide() {
23
+ this.#state.floatable.hide();
24
+ }
25
+ /**
26
+ * Opens the popover
27
+ */
28
+ show() {
29
+ this.#state.floatable.show();
34
30
  }
35
31
  };
32
+ function destroyPopover(state) {
33
+ state.floatable.destroy();
34
+ state.focusTrap?.destroy();
35
+ for (const listener of state.listeners) listener();
36
+ state.anchor = void 0;
37
+ state.content = void 0;
38
+ state.floatable = void 0;
39
+ state.focusTrap = void 0;
40
+ state.listeners = void 0;
41
+ state.popover = void 0;
42
+ }
43
+ /**
44
+ * Get the _OuiPopover_ for an element
45
+ *
46
+ * @param element Element to get _OuiPopover_ for
47
+ * @returns _OuiPopover_ instance
48
+ */
49
+ function getPopover(element) {
50
+ return states.get(element)?.popover;
51
+ }
52
+ function getState(anchor, content) {
53
+ const state = {
54
+ anchor,
55
+ content,
56
+ floatable: createFloatable(anchor, content, options, false),
57
+ focusTrap: content.getAttribute(ARIA_MODAL) === TRUE ? createFocusTrap(content, { noescape: true }) : void 0,
58
+ listeners: [getOnBeforeToggleListener(content), on(content, EVENT_TOGGLE, (event) => {
59
+ if (event.newState === STATE_OPEN) {
60
+ ignoreFocus = false;
61
+ state.floatable?.update();
62
+ content.setAttribute(ATTRIBUTE_OPEN, "");
63
+ content.focus();
64
+ } else {
65
+ content.removeAttribute(ATTRIBUTE_OPEN);
66
+ if (!ignoreFocus) anchor?.focus();
67
+ }
68
+ })],
69
+ popover: void 0
70
+ };
71
+ state.popover = new OuiPopover(state);
72
+ return state;
73
+ }
36
74
  function onAdd(element) {
37
- if (!instances.has(element) && element.getAttribute(ATTRIBUTE) !== POPOVER_HINT) instances.set(element, new Popover(element));
75
+ if (states.has(element) || element.hasAttribute("oui-floatable")) return;
76
+ const anchor = element.ownerDocument.querySelector(`[popovertarget="${element.id}"]`);
77
+ if (isHTMLOrSVGElement(anchor)) states.set(element, getState(anchor, element));
38
78
  }
39
79
  function onPointerdown() {
40
80
  ignoreFocus = true;
41
81
  }
42
82
  function onRemove(element) {
43
- instances.get(element)?.destroy();
44
- instances.delete(element);
83
+ const state = states.get(element);
84
+ if (state == null) return;
85
+ destroyPopover(state);
86
+ states.delete(element);
45
87
  }
46
- const ATTRIBUTE = "popover";
47
- const ATTRIBUTE_CONTENT = "oui-popover-content";
88
+ const ATTRIBUTE = "oui-popover";
89
+ const ARIA_MODAL = "aria-modal";
90
+ const ATTRIBUTE_OPEN = `${ATTRIBUTE}-open`;
48
91
  const EVENT_TOGGLE = "toggle";
49
- const POPOVER_HINT = "hint";
50
92
  const STATE_OPEN = "open";
51
- const instances = /* @__PURE__ */ new WeakMap();
93
+ const TRUE = "true";
52
94
  const options = {
53
- attribute: "position",
95
+ attribute: `${ATTRIBUTE}position`,
54
96
  position: "below-start"
55
97
  };
98
+ const states = /* @__PURE__ */ new WeakMap();
56
99
  let ignoreFocus = false;
57
100
  on(document, "pointerdown", onPointerdown, { capture: true });
58
101
  attributable(ATTRIBUTE, onAdd, onRemove);
59
102
  //#endregion
60
- export {};
103
+ export { getPopover };
@@ -1,6 +1,7 @@
1
1
  import { attributable } from "./internal/attributable.mjs";
2
2
  import { Draggable, addDraggable, removeDraggable } from "./internal/draggable.mjs";
3
3
  import { getPosition } from "@oscarpalmer/toretto/event";
4
+ import { isHTMLOrSVGElement } from "@oscarpalmer/toretto/is";
4
5
  import { findAncestor, getElementFromPosition } from "@oscarpalmer/toretto/find";
5
6
  import { createElement } from "@oscarpalmer/toretto/create";
6
7
  //#region src/js/sortable.ts
@@ -177,12 +178,13 @@ function setPlaceholder(state, sortable, origin) {
177
178
  parent: sortable.element,
178
179
  placeholder: element,
179
180
  create: (value) => {
180
- if (!(value instanceof HTMLElement)) return;
181
- placeholder.drag.custom = value;
182
- updatePlaceholder(sortable, value);
181
+ if (!isHTMLOrSVGElement(value)) return;
182
+ const element = value;
183
+ placeholder.drag.custom = element;
184
+ updatePlaceholder(sortable, element);
183
185
  state.element = {
184
- rectangle: value.getBoundingClientRect(),
185
- node: value
186
+ rectangle: element.getBoundingClientRect(),
187
+ node: element
186
188
  };
187
189
  }
188
190
  }
@@ -1,24 +1,28 @@
1
- import { clamp } from "@oscarpalmer/atoms/number";
2
1
  import { getPosition, on } from "@oscarpalmer/toretto/event";
2
+ import { isNullableOrWhitespace } from "@oscarpalmer/atoms/is";
3
+ import { clamp } from "@oscarpalmer/atoms/number";
3
4
  import { findAncestor } from "@oscarpalmer/toretto/find";
4
5
  import { toggleStyles } from "@oscarpalmer/toretto/style";
5
6
  import supportsTouch from "@oscarpalmer/toretto/touch";
6
- import { isNullableOrWhitespace } from "@oscarpalmer/atoms/is";
7
7
  import { round } from "@oscarpalmer/atoms/math";
8
8
  //#region src/js/splitter.ts
9
+ const ATTRIBUTE_MAX = "max";
10
+ const ATTRIBUTE_MIN = "min";
11
+ const ATTRIBUTE_SIZE = "size";
12
+ const ATTRIBUTE_TYPE = "type";
9
13
  var OuiSplitterElement = class extends HTMLElement {
10
14
  static observedAttributes = [
11
- "max",
12
- "min",
13
- "size",
14
- "type"
15
+ ATTRIBUTE_MAX,
16
+ ATTRIBUTE_MIN,
17
+ ATTRIBUTE_SIZE,
18
+ ATTRIBUTE_TYPE
15
19
  ];
16
20
  #splitter;
17
21
  get max() {
18
22
  return this.#splitter.values.max;
19
23
  }
20
24
  set max(value) {
21
- this.setAttribute("max", String(value));
25
+ this.setAttribute(ATTRIBUTE_MAX, String(value));
22
26
  }
23
27
  get min() {
24
28
  return this.#splitter.values.min;
@@ -52,12 +56,12 @@ var OuiSplitterElement = class extends HTMLElement {
52
56
  }
53
57
  attributeChangedCallback(name) {
54
58
  switch (name) {
55
- case "max":
56
- case "min":
57
- case "size":
59
+ case ATTRIBUTE_MAX:
60
+ case ATTRIBUTE_MIN:
61
+ case ATTRIBUTE_SIZE:
58
62
  this.#splitter.updateValues();
59
63
  break;
60
- case "type":
64
+ case ATTRIBUTE_TYPE:
61
65
  this.#splitter.updateOrientation();
62
66
  break;
63
67
  default: break;
@@ -157,14 +161,14 @@ function getValue(element, name, defaultValue) {
157
161
  }
158
162
  function getValues(element) {
159
163
  const values = {
160
- max: getValue(element, "max", NAVIGATION_MAXIMUM_PERCENTAGE),
161
- min: getValue(element, "min", NAVIGATION_MINIMUM_PERCENTAGE),
164
+ max: getValue(element, ATTRIBUTE_MAX, NAVIGATION_MAXIMUM_PERCENTAGE),
165
+ min: getValue(element, ATTRIBUTE_MIN, NAVIGATION_MINIMUM_PERCENTAGE),
162
166
  now: {
163
167
  current: .5,
164
168
  previous: .5
165
169
  }
166
170
  };
167
- const value = getContained(values.min, getValue(element, "size", values.now.current), values.max);
171
+ const value = getContained(values.min, getValue(element, ATTRIBUTE_SIZE, values.now.current), values.max);
168
172
  values.now.current = value;
169
173
  values.now.previous = value;
170
174
  return values;
@@ -1,4 +1,36 @@
1
+ import { n as OuiFloatable } from "./embedded-84gxpReS.mjs";
2
+
1
3
  //#region src/js/tooltip.d.ts
4
+ declare class OuiTooltip {
5
+ #private;
6
+ /**
7
+ * Is the tooltip open?
8
+ */
9
+ get open(): boolean;
10
+ constructor(state: OuiTooltipState);
11
+ /**
12
+ * Closes the tooltip
13
+ */
14
+ hide(): void;
15
+ /**
16
+ * Opens the tooltip
17
+ */
18
+ show(): void;
19
+ }
20
+ type OuiTooltipState = {
21
+ anchor: HTMLElement;
22
+ content: HTMLElement;
23
+ floatable: OuiFloatable;
24
+ timer?: number;
25
+ tooltip: OuiTooltip;
26
+ };
27
+ declare function getTooltip(element: HTMLElement): OuiTooltip | undefined;
28
+ /**
29
+ * Set the delay before showing the tooltip, in milliseconds
30
+ *
31
+ * _(Default delay is half a second, or 500 milliseconds)_
32
+ * @param value Delay in milliseconds
33
+ */
2
34
  declare function setTooltipDelay(value: number): void;
3
35
  //#endregion
4
- export { setTooltipDelay };
36
+ export { type OuiTooltip, getTooltip, setTooltipDelay };
@@ -1,27 +1,34 @@
1
+ import { createFloatable } from "./floatable/embedded.mjs";
1
2
  import { attributable } from "./internal/attributable.mjs";
2
- import { Floatable } from "./internal/floatable.mjs";
3
3
  import { on } from "@oscarpalmer/toretto/event";
4
+ import { isNullableOrWhitespace } from "@oscarpalmer/atoms/is";
5
+ import { isHTMLOrSVGElement } from "@oscarpalmer/toretto/is";
4
6
  import { findAncestor } from "@oscarpalmer/toretto/find";
5
7
  import { createElement } from "@oscarpalmer/toretto/create";
6
- import { isNullableOrWhitespace } from "@oscarpalmer/atoms/is";
7
8
  //#region src/js/tooltip.ts
8
- var Tooltip = class {
9
- anchor;
10
- content;
11
- floatable;
12
- timer;
13
- constructor(anchor, content) {
14
- this.anchor = anchor;
15
- this.content = content;
16
- instances.set(content, this);
17
- anchor.insertAdjacentElement("afterend", content);
18
- this.floatable = new Floatable(anchor, content, options);
19
- this.floatable.update();
9
+ var OuiTooltip = class {
10
+ #state;
11
+ /**
12
+ * Is the tooltip open?
13
+ */
14
+ get open() {
15
+ return this.#state.content.checkVisibility();
16
+ }
17
+ constructor(state) {
18
+ this.#state = state;
19
+ state.floatable.update();
20
+ }
21
+ /**
22
+ * Closes the tooltip
23
+ */
24
+ hide() {
25
+ this.#state.floatable.hide();
20
26
  }
21
- destroy() {
22
- instances.delete(this.content);
23
- this.anchor = null;
24
- this.content = null;
27
+ /**
28
+ * Opens the tooltip
29
+ */
30
+ show() {
31
+ this.#state.floatable.show();
25
32
  }
26
33
  };
27
34
  function activate(event, focus) {
@@ -29,34 +36,47 @@ function activate(event, focus) {
29
36
  const content = findAncestor(event, SELECTOR_CONTENT);
30
37
  if (anchor == null && content == null) {
31
38
  if (!focused) {
32
- closeTooltip(active);
33
- active = void 0;
39
+ closeTooltip(activeState);
40
+ activeState = void 0;
41
+ activeTooltip = void 0;
34
42
  }
35
43
  return;
36
44
  }
37
- const instance = instances.get(anchor ?? content);
38
- if (instance == null || instance === active) return;
39
- const shouldDelay = active == null;
40
- closeTooltip(active);
41
- active = instance;
45
+ const state = states.get(anchor ?? content);
46
+ if (state == null || state.tooltip === activeTooltip) return;
47
+ const shouldDelay = activeTooltip == null;
48
+ closeTooltip(activeState);
49
+ activeState = state;
50
+ activeTooltip = state.tooltip;
42
51
  focused = focus;
43
- instance.timer = setTimeout(() => {
44
- instance.content.showPopover({ source: instance.anchor });
52
+ state.timer = setTimeout(() => {
53
+ state.content.showPopover({ source: state.anchor });
45
54
  setTimeout(() => {
46
- instance.floatable.update();
47
- instance.content.setAttribute(ATTRIBUTE_CONTENT_ACTIVE, "");
55
+ state.floatable.update();
56
+ state.content.setAttribute(ATTRIBUTE_CONTENT_OPEN, "");
48
57
  });
49
58
  }, shouldDelay ? delay : 0);
50
59
  }
51
- function closeTooltip(instance) {
52
- if (instance == null) return;
53
- if (instance.timer != null) clearTimeout(instance.timer);
54
- instance.content?.hidePopover();
55
- instance.content?.removeAttribute(ATTRIBUTE_CONTENT_ACTIVE);
60
+ function closeTooltip(state) {
61
+ if (state == null) return;
62
+ if (state.timer != null) clearTimeout(state.timer);
63
+ state.content?.hidePopover();
64
+ state.content?.removeAttribute(ATTRIBUTE_CONTENT_OPEN);
56
65
  }
57
66
  function createTooltip(anchor) {
58
67
  const content = getContent(anchor);
59
- if (content != null) instances.set(anchor, new Tooltip(anchor, content));
68
+ if (content == null) return;
69
+ anchor.insertAdjacentElement("afterend", content);
70
+ states.set(anchor, getState(anchor, content));
71
+ }
72
+ function destroyTooltip(state) {
73
+ clearTimeout(state.timer);
74
+ state.content.remove();
75
+ state.floatable.destroy();
76
+ state.anchor = void 0;
77
+ state.content = void 0;
78
+ state.floatable = void 0;
79
+ state.tooltip = void 0;
60
80
  }
61
81
  function findElements(attribute) {
62
82
  const ids = attribute?.split(EXPRESSION_WHITESPACE) ?? [];
@@ -64,7 +84,7 @@ function findElements(attribute) {
64
84
  for (const id of ids) {
65
85
  if (isNullableOrWhitespace(id)) continue;
66
86
  const element = document.querySelector(`#${id}`);
67
- if (element instanceof HTMLElement) {
87
+ if (isHTMLOrSVGElement(element)) {
68
88
  const cloned = element.cloneNode(true);
69
89
  cloned.hidden = false;
70
90
  elements.push(cloned);
@@ -96,28 +116,50 @@ function getElements(anchor) {
96
116
  paragraph.textContent = content;
97
117
  return [paragraph];
98
118
  }
119
+ function getState(anchor, content) {
120
+ const state = {
121
+ anchor,
122
+ content,
123
+ floatable: createFloatable(anchor, content, options, false),
124
+ tooltip: null
125
+ };
126
+ state.tooltip = new OuiTooltip(state);
127
+ return state;
128
+ }
129
+ function getTooltip(element) {
130
+ return states.get(element)?.tooltip;
131
+ }
99
132
  function onAdd(element) {
100
- if (!instances.has(element)) createTooltip(element);
133
+ if (!states.has(element)) createTooltip(element);
101
134
  }
102
135
  function onFocusin(event) {
103
136
  activate(event, true);
104
137
  }
105
138
  function onFocusout() {
106
- if (active == null) return;
139
+ if (activeTooltip == null) return;
107
140
  if (focusTimer != null) clearTimeout(focusTimer);
108
141
  focusTimer = setTimeout(() => {
109
- if (active == null || document.activeElement == null || findAncestor(document.activeElement, SELECTOR) != null) return;
110
- closeTooltip(active);
111
- active = void 0;
142
+ if (activeTooltip == null || document.activeElement == null || findAncestor(document.activeElement, SELECTOR) != null) return;
143
+ closeTooltip(activeState);
144
+ activeState = void 0;
145
+ activeTooltip = void 0;
112
146
  });
113
147
  }
114
148
  function onPointermove(event) {
115
149
  activate(event, false);
116
150
  }
117
151
  function onRemove(element) {
118
- instances.get(element)?.destroy();
119
- instances.delete(element);
152
+ const state = states.get(element);
153
+ if (state == null) return;
154
+ destroyTooltip(state);
155
+ states.delete(element);
120
156
  }
157
+ /**
158
+ * Set the delay before showing the tooltip, in milliseconds
159
+ *
160
+ * _(Default delay is half a second, or 500 milliseconds)_
161
+ * @param value Delay in milliseconds
162
+ */
121
163
  function setTooltipDelay(value) {
122
164
  if (typeof value === "number" && !Number.isNaN(value) && value >= 0) delay = value;
123
165
  }
@@ -129,21 +171,22 @@ const CONTENT_TAGNAME = "div";
129
171
  const EXPRESSION_WHITESPACE = /\s+/;
130
172
  const ATTRIBUTE = "oui-tooltip";
131
173
  const ATTRIBUTE_CONTENT = `${ATTRIBUTE}-content`;
132
- const ATTRIBUTE_CONTENT_ACTIVE = `${ATTRIBUTE_CONTENT}-active`;
174
+ const ATTRIBUTE_CONTENT_OPEN = `${ATTRIBUTE_CONTENT}-open`;
133
175
  const SELECTOR = `[${ATTRIBUTE}]`;
134
176
  const SELECTOR_CONTENT = `[${ATTRIBUTE_CONTENT}]`;
135
- const instances = /* @__PURE__ */ new WeakMap();
177
+ const states = /* @__PURE__ */ new WeakMap();
136
178
  const options = {
137
- attribute: "oui-tooltip-position",
179
+ attribute: `${ATTRIBUTE}-position`,
138
180
  position: "above"
139
181
  };
140
182
  let delay = 500;
141
183
  let focused = false;
142
- let active;
184
+ let activeState;
185
+ let activeTooltip;
143
186
  let focusTimer;
144
187
  on(document, "focusin", onFocusin);
145
188
  on(document, "focusout", onFocusout);
146
189
  on(document, "pointermove", onPointermove);
147
190
  attributable(ATTRIBUTE, onAdd, onRemove);
148
191
  //#endregion
149
- export { setTooltipDelay };
192
+ export { getTooltip, setTooltipDelay };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oscarpalmer/oui",
3
- "version": "0.23.1",
3
+ "version": "0.25.0",
4
4
  "description": "Styles, components, and utilities for building websites and applications.",
5
5
  "keywords": [
6
6
  "css",
@@ -74,7 +74,7 @@
74
74
  "@oscarpalmer/toretto": "^0.46"
75
75
  },
76
76
  "devDependencies": {
77
- "@oxlint/plugins": "^1.69",
77
+ "@oxlint/plugins": "^1.70",
78
78
  "@vitest/coverage-istanbul": "^4.1",
79
79
  "autoprefixer": "^10.5",
80
80
  "concurrently": "^10",
@@ -1,5 +1,51 @@
1
1
  @use 'mixins.scss' as mixins;
2
2
 
3
+ :where([oui-dialog], [oui-popover], [oui-tooltip-content]),
4
+ :where([oui-dialog])::backdrop {
5
+ opacity: 0;
6
+ transition: 0.125s ease-in-out;
7
+ transition-property: opacity, scale;
8
+ }
9
+
10
+ :where([oui-dialog], [oui-popover], [oui-tooltip-content]) {
11
+ @include mixins.shadow-overlay;
12
+
13
+ background-color: var(--oui-absolute);
14
+ scale: 0.9;
15
+ }
16
+
17
+ :where([oui-dialog]:focus, [oui-popover]:focus, [oui-tooltip-content]:focus) {
18
+ outline: none;
19
+ }
20
+
21
+ :where(
22
+ [oui-dialog][oui-dialog-open],
23
+ [oui-popover][oui-popover-open],
24
+ [oui-tooltip-content][oui-tooltip-content-open]
25
+ ),
26
+ :where([oui-dialog][oui-dialog-open])::backdrop {
27
+ opacity: 1;
28
+ }
29
+
30
+ :where(
31
+ [oui-dialog][oui-dialog-open],
32
+ [oui-popover][oui-popover-open],
33
+ [oui-tooltip-content][oui-tooltip-content-open]
34
+ ) {
35
+ scale: 1;
36
+ transition-delay: 0.125s;
37
+ }
38
+
39
+ :where([oui-popover], [oui-tooltip-content]) {
40
+ @include mixins.floatable;
41
+ }
42
+
43
+ :where([oui-popover]) {
44
+ padding: 1rem;
45
+ background-color: var(--oui-absolute);
46
+ border-radius: 0.25rem;
47
+ }
48
+
3
49
  :where(
4
50
  [oui-tooltip]:is(
5
51
  abbr,
@@ -29,8 +75,6 @@
29
75
  }
30
76
 
31
77
  :where([oui-tooltip-content]) {
32
- @include mixins.floatable;
33
-
34
78
  max-width: 48ch;
35
79
  padding: 0.75em 1em;
36
80
  overflow: visible;
@@ -39,8 +83,6 @@
39
83
  border-radius: 0.25rem;
40
84
  font-size: 0.875rem;
41
85
  pointer-events: none;
42
- transition: opacity 0.125s ease-in-out 0s;
43
- transition-behavior: allow-discrete;
44
86
 
45
87
  &::after {
46
88
  content: '';
@@ -97,7 +139,7 @@
97
139
  }
98
140
  }
99
141
 
100
- :where([oui-tooltip-content][oui-tooltip-content-active]) {
142
+ :where([oui-tooltip-content][oui-tooltip-content-open]) {
101
143
  opacity: 1;
102
144
  pointer-events: all;
103
145
  }
@@ -52,8 +52,6 @@
52
52
  }
53
53
 
54
54
  @mixin floatable() {
55
- @include shadow-overlay;
56
-
57
55
  --margin-bottom: 0.5em;
58
56
  --margin-left: 0.5em;
59
57
  --margin-right: 0.5em;
@@ -121,6 +121,23 @@
121
121
  display: list-item;
122
122
  }
123
123
 
124
+ :where(dialog) {
125
+ display: none !important;
126
+ overscroll-behavior: contain;
127
+ border: none;
128
+ color: currentcolor;
129
+ }
130
+
131
+ :where([oui-dialog][aria-modal='true' i]) {
132
+ position: fixed;
133
+ inset: 50% auto auto 50%;
134
+ transform: translate3d(-50%, -50%, 0);
135
+ }
136
+
137
+ :where(dialog[open]) {
138
+ display: inherit !important;
139
+ }
140
+
124
141
  :where(dl, ol, ul) :where(dl, ol, ul) {
125
142
  /** Remove the margin on nested lists in Chrome, Edge, and Safari [SE] */
126
143
  margin: 0;