@oscarpalmer/oui 0.17.0 → 0.18.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 (58) hide show
  1. package/dist/css/badge.css +3 -3
  2. package/dist/css/content.css +9 -11
  3. package/dist/css/form.css +36 -22
  4. package/dist/css/message.css +4 -0
  5. package/dist/css/reset.css +176 -56
  6. package/dist/css/tooltip.css +8 -0
  7. package/dist/js/attributable.full.js +48 -0
  8. package/dist/js/attributable.js +30 -45
  9. package/dist/js/floatable.full.js +413 -0
  10. package/dist/js/floatable.js +254 -169
  11. package/dist/js/focus-trap/embedded.full.js +351 -0
  12. package/dist/js/focus-trap/embedded.js +131 -131
  13. package/dist/js/focus-trap/standalone.full.js +402 -0
  14. package/dist/js/focus-trap/standalone.js +4 -4
  15. package/dist/js/index.js +4 -5
  16. package/dist/js/oui.full.js +1596 -0
  17. package/dist/js/popover.full.js +822 -0
  18. package/dist/js/popover.js +83 -162
  19. package/dist/js/splitter.full.js +605 -0
  20. package/dist/js/splitter.js +263 -245
  21. package/dist/js/tooltip.full.js +679 -0
  22. package/dist/js/tooltip.js +159 -150
  23. package/package.json +31 -59
  24. package/src/css/content.scss +1 -2
  25. package/src/css/form.scss +12 -4
  26. package/src/css/message.scss +3 -0
  27. package/src/css/mixins.scss +7 -0
  28. package/src/css/reset.scss +180 -54
  29. package/src/css/tooltip.scss +8 -0
  30. package/src/js/floatable.ts +380 -133
  31. package/src/js/focus-trap/embedded.ts +149 -64
  32. package/src/js/focus-trap/standalone.ts +4 -4
  33. package/src/js/index.ts +1 -0
  34. package/src/js/popover.ts +50 -120
  35. package/src/js/splitter.ts +250 -103
  36. package/src/js/tooltip.ts +155 -68
  37. package/types/floatable.d.ts +17 -10
  38. package/types/focus-trap/embedded.d.ts +18 -5
  39. package/types/index.d.ts +1 -0
  40. package/types/popover.d.ts +2 -0
  41. package/types/splitter.d.ts +13 -1
  42. package/types/tooltip.d.ts +2 -1
  43. package/dist/js/attributable.cjs +0 -51
  44. package/dist/js/floatable.cjs +0 -176
  45. package/dist/js/focus-trap/embedded.cjs +0 -150
  46. package/dist/js/focus-trap/standalone.cjs +0 -8
  47. package/dist/js/index.cjs +0 -6
  48. package/dist/js/popover.cjs +0 -166
  49. package/dist/js/splitter.cjs +0 -272
  50. package/dist/js/tooltip.cjs +0 -166
  51. package/types/attributable.d.cts +0 -5
  52. package/types/floatable.d.cts +0 -20
  53. package/types/focus-trap/embedded.d.cts +0 -15
  54. package/types/focus-trap/standalone.d.cts +0 -3
  55. package/types/index.d.cts +0 -14
  56. package/types/popover.d.cts +0 -14
  57. package/types/splitter.d.cts +0 -10
  58. package/types/tooltip.d.cts +0 -3
@@ -1,165 +1,174 @@
1
+ import { attributable } from "./attributable.js";
2
+ import { Floatable } from "./floatable.js";
1
3
  import { isNullableOrWhitespace } from "@oscarpalmer/atoms/is";
2
4
  import { on } from "@oscarpalmer/toretto/event";
3
- import { attributable } from "./attributable.js";
4
- import { deactivate, Floatable, activate } from "./floatable.js";
5
- class Tooltip {
6
- abortController = new AbortController();
7
- attributes;
8
- floatable;
9
- constructor(anchor, content) {
10
- this.attributes = content.attributes;
11
- this.floatable = new Floatable(
12
- anchor,
13
- content.element,
14
- `${selector}-position`,
15
- "vertical",
16
- true
17
- );
18
- initialize(this);
19
- }
20
- destroy() {
21
- deactivate(this.floatable, active);
22
- reset(this.floatable.anchor, this.attributes);
23
- this.abortController.abort();
24
- this.floatable.content.remove();
25
- this.floatable.destroy();
26
- this.abortController = void 0;
27
- this.attributes = void 0;
28
- this.floatable = void 0;
29
- }
30
- }
5
+ import { findAncestor } from "@oscarpalmer/toretto/find";
6
+ var Tooltip = class {
7
+ attributes;
8
+ floatable;
9
+ timer;
10
+ constructor(anchor, content) {
11
+ this.attributes = content.attributes;
12
+ this.floatable = new Floatable({
13
+ anchor,
14
+ content: content.element,
15
+ defaultPosition: "vertical",
16
+ interactive: false,
17
+ preferAbove: true,
18
+ positionAttribute: ATTRIBUTE_POSITION
19
+ });
20
+ anchor.insertAdjacentElement("afterend", content.element);
21
+ TOOLTIPS_ALL.set(content.element, this);
22
+ }
23
+ destroy() {
24
+ const { attributes, floatable } = this;
25
+ TOOLTIPS_ACTIVE.delete(this);
26
+ TOOLTIPS_ALL.delete(floatable.options.anchor);
27
+ TOOLTIPS_ALL.delete(floatable.options.content);
28
+ reset(floatable.options.anchor, attributes);
29
+ floatable.options.content.remove();
30
+ floatable.destroy();
31
+ this.attributes = void 0;
32
+ this.floatable = void 0;
33
+ }
34
+ };
31
35
  function addTooltip(anchor) {
32
- if (tooltips.has(anchor)) {
33
- return;
34
- }
35
- const content = getContent(anchor);
36
- if (content != null) {
37
- tooltips.set(anchor, new Tooltip(anchor, content));
38
- }
36
+ if (TOOLTIPS_ALL.has(anchor)) return;
37
+ const content = getContent(anchor);
38
+ if (content != null) TOOLTIPS_ALL.set(anchor, new Tooltip(anchor, content));
39
+ }
40
+ function closeTooltips(next) {
41
+ const tooltips = [...TOOLTIPS_ACTIVE];
42
+ for (const active of tooltips) {
43
+ if (active === next) continue;
44
+ if (active.timer != null) clearTimeout(active.timer);
45
+ active.floatable.options.content.removeAttribute("oui-tooltip-content-active");
46
+ requestAnimationFrame(() => {
47
+ active.timer = setTimeout(() => {
48
+ TOOLTIPS_ACTIVE.delete(active);
49
+ active.floatable.toggle(false);
50
+ }, delay);
51
+ });
52
+ }
39
53
  }
40
54
  function getContent(anchor) {
41
- const attributes = {
42
- ariaDescribedby: anchor.getAttribute("aria-describedby"),
43
- ariaLabelledBy: anchor.getAttribute("aria-labelledby")
44
- };
45
- const wrapper = getWrapper(anchor);
46
- const labelledElements = getElements(attributes.ariaLabelledBy);
47
- if (labelledElements.length > 0) {
48
- anchor.setAttribute("aria-labelledby", wrapper.id);
49
- for (const element of labelledElements) {
50
- wrapper.append(element);
51
- }
52
- return {
53
- attributes,
54
- element: wrapper
55
- };
56
- }
57
- const describedElements = getElements(attributes.ariaDescribedby);
58
- if (describedElements.length > 0) {
59
- anchor.setAttribute("aria-describedby", wrapper.id);
60
- for (const element of describedElements) {
61
- wrapper.append(element);
62
- }
63
- return {
64
- attributes,
65
- element: wrapper
66
- };
67
- }
68
- let content = anchor.getAttribute("aria-label");
69
- if (isNullableOrWhitespace(content)) {
70
- content = anchor.getAttribute("aria-description");
71
- }
72
- if (isNullableOrWhitespace(content)) {
73
- return;
74
- }
75
- const paragraph = document.createElement("p");
76
- paragraph.textContent = content;
77
- wrapper.append(paragraph);
78
- return {
79
- attributes,
80
- element: wrapper
81
- };
55
+ const attributes = {
56
+ ariaDescribedby: anchor.getAttribute("aria-describedby"),
57
+ ariaLabelledBy: anchor.getAttribute("aria-labelledby")
58
+ };
59
+ const wrapper = getWrapper(anchor);
60
+ const labelledElements = getElements(attributes.ariaLabelledBy);
61
+ if (labelledElements.length > 0) {
62
+ anchor.setAttribute("aria-labelledby", wrapper.id);
63
+ for (const element of labelledElements) wrapper.append(element);
64
+ return {
65
+ attributes,
66
+ element: wrapper
67
+ };
68
+ }
69
+ const describedElements = getElements(attributes.ariaDescribedby);
70
+ if (describedElements.length > 0) {
71
+ anchor.setAttribute("aria-describedby", wrapper.id);
72
+ for (const element of describedElements) wrapper.append(element);
73
+ return {
74
+ attributes,
75
+ element: wrapper
76
+ };
77
+ }
78
+ let content = anchor.getAttribute("aria-label");
79
+ if (isNullableOrWhitespace(content)) content = anchor.getAttribute("aria-description");
80
+ if (isNullableOrWhitespace(content)) return;
81
+ const paragraph = document.createElement("p");
82
+ paragraph.textContent = content;
83
+ wrapper.append(paragraph);
84
+ return {
85
+ attributes,
86
+ element: wrapper
87
+ };
82
88
  }
83
89
  function getElements(attribute) {
84
- const ids = attribute?.split(/\s+/) ?? [];
85
- const elements = [];
86
- for (const id of ids) {
87
- if (isNullableOrWhitespace(id)) {
88
- continue;
89
- }
90
- const element = document.querySelector(`#${id}`);
91
- if (element instanceof HTMLElement) {
92
- const cloned = element.cloneNode(true);
93
- cloned.hidden = false;
94
- elements.push(cloned);
95
- }
96
- }
97
- return elements;
90
+ const ids = attribute?.split(EXPRESSION_WHITESPACE) ?? [];
91
+ const elements = [];
92
+ for (const id of ids) {
93
+ if (isNullableOrWhitespace(id)) continue;
94
+ const element = document.querySelector(`#${id}`);
95
+ if (element instanceof HTMLElement) {
96
+ const cloned = element.cloneNode(true);
97
+ cloned.hidden = false;
98
+ elements.push(cloned);
99
+ }
100
+ }
101
+ return elements;
98
102
  }
99
103
  function getWrapper(anchor) {
100
- const wrapper = document.createElement("div");
101
- wrapper.setAttribute(`${selector}-content`, "");
102
- wrapper.className = anchor.getAttribute(`${selector}-class`) ?? "";
103
- wrapper.hidden = true;
104
- wrapper.id = `${selector}-${++index}`;
105
- wrapper.role = "tooltip";
106
- wrapper.tabIndex = -1;
107
- return wrapper;
104
+ const wrapper = document.createElement("div");
105
+ wrapper.setAttribute(ATTRIBUTE_CONTENT, "");
106
+ wrapper.className = anchor.getAttribute(ATTRIBUTE_CLASS) ?? "";
107
+ wrapper.hidden = true;
108
+ wrapper.id = `${SELECTOR}-${++index}`;
109
+ wrapper.role = "tooltip";
110
+ wrapper.tabIndex = -1;
111
+ return wrapper;
108
112
  }
109
- function initialize(tooltip) {
110
- const { abortController, floatable } = tooltip;
111
- const { anchor, content } = floatable;
112
- anchor.insertAdjacentElement("afterend", content);
113
- const elements = [anchor, content];
114
- for (const element of elements) {
115
- for (const event of activateEvents) {
116
- on(
117
- element,
118
- event,
119
- () => {
120
- activate(floatable, active, void 0, 250);
121
- },
122
- {
123
- signal: abortController.signal
124
- }
125
- );
126
- }
127
- for (const event of deactivateEvents) {
128
- on(
129
- element,
130
- event,
131
- () => {
132
- deactivate(floatable, active, void 0, 250);
133
- },
134
- {
135
- signal: abortController.signal
136
- }
137
- );
138
- }
139
- }
113
+ function onActivate(event) {
114
+ onToggle(event, true);
115
+ }
116
+ function onClick(event) {
117
+ if (findAncestor(event.target, SELECTOR_CONTENT) != null) event.stopPropagation();
118
+ }
119
+ function onDeactivate(event) {
120
+ onToggle(event, false);
121
+ }
122
+ function onToggle(event, activate) {
123
+ if (toggle != null) cancelAnimationFrame(toggle);
124
+ toggle = requestAnimationFrame(() => {
125
+ toggle = void 0;
126
+ const element = findAncestor(event.target, SELECTOR_FULL);
127
+ const tooltip = TOOLTIPS_ALL.get(element);
128
+ if (TOOLTIPS_ACTIVE.size > 0) closeTooltips(tooltip);
129
+ if (tooltip == null || tooltip.floatable.options.content.hasAttribute("oui-tooltip-content-active") === activate) return;
130
+ if (activate) {
131
+ if (tooltip.timer != null) clearTimeout(tooltip.timer);
132
+ TOOLTIPS_ACTIVE.add(tooltip);
133
+ tooltip.floatable.toggle(true);
134
+ requestAnimationFrame(() => {
135
+ tooltip.floatable.options.content.setAttribute("oui-tooltip-content-active", "");
136
+ });
137
+ return;
138
+ }
139
+ tooltip.floatable.options.content.removeAttribute("oui-tooltip-content-active");
140
+ tooltip.timer ??= setTimeout(() => {
141
+ TOOLTIPS_ACTIVE.delete(tooltip);
142
+ tooltip.floatable.toggle(false);
143
+ }, delay);
144
+ });
140
145
  }
141
146
  function removeTooltip(element) {
142
- tooltips.get(element)?.destroy();
143
- tooltips.delete(element);
147
+ if (!element.hasAttribute(ATTRIBUTE_CONTENT)) TOOLTIPS_ALL.get(element)?.destroy();
144
148
  }
145
149
  function reset(anchor, attributes) {
146
- if (attributes.ariaDescribedby == null) {
147
- anchor.removeAttribute("aria-describedby");
148
- } else {
149
- anchor.setAttribute("aria-describedby", attributes.ariaDescribedby);
150
- }
150
+ if (attributes.ariaDescribedby == null) anchor.removeAttribute("aria-describedby");
151
+ else anchor.setAttribute("aria-describedby", attributes.ariaDescribedby);
152
+ }
153
+ function setDelay(value) {
154
+ delay = typeof value === "number" && value >= 0 ? value : delay;
151
155
  }
152
- const active = /* @__PURE__ */ new Set();
153
- const activateEvents = ["focus", "mouseenter", "touchstart"];
154
- const deactivateEvents = ["blur", "mouseleave"];
155
- const selector = "oui-tooltip";
156
- const tooltips = /* @__PURE__ */ new WeakMap();
157
- let index = 0;
158
- attributable(selector, addTooltip, removeTooltip);
159
- on(document, "keydown", (event) => {
160
- if (event.key === "Escape") {
161
- for (const floatable of active) {
162
- deactivate(floatable, active);
163
- }
164
- }
165
- });
156
+ var SELECTOR = "oui-tooltip";
157
+ var ATTRIBUTE_CLASS = `${SELECTOR}-class`;
158
+ var ATTRIBUTE_CONTENT = `${SELECTOR}-content`;
159
+ var ATTRIBUTE_POSITION = `${SELECTOR}-position`;
160
+ var SELECTOR_CONTENT = `[${ATTRIBUTE_CONTENT}]`;
161
+ var SELECTOR_FULL = `[${SELECTOR}], [${ATTRIBUTE_CONTENT}]`;
162
+ var EXPRESSION_WHITESPACE = /\s+/;
163
+ var TOOLTIPS_ACTIVE = /* @__PURE__ */ new Set();
164
+ var TOOLTIPS_ALL = /* @__PURE__ */ new WeakMap();
165
+ var delay = 250;
166
+ var index = 0;
167
+ var toggle;
168
+ attributable(SELECTOR, addTooltip, removeTooltip);
169
+ on(document, "click", onClick, { capture: true });
170
+ on(document, "focusin", onActivate);
171
+ on(document, "focusout", onDeactivate);
172
+ on(document, "mousemove", onActivate);
173
+ on(document, "touchstart", onActivate);
174
+ export { setDelay };
package/package.json CHANGED
@@ -4,83 +4,56 @@
4
4
  "url": "https://oscarpalmer.se"
5
5
  },
6
6
  "dependencies": {
7
- "@oscarpalmer/atoms": "^0.104",
8
- "@oscarpalmer/toretto": "^0.20"
7
+ "@oscarpalmer/atoms": "^0.112",
8
+ "@oscarpalmer/toretto": "^0.24"
9
9
  },
10
10
  "description": "Styles, components, and utilities for building websites and applications.",
11
11
  "devDependencies": {
12
- "@biomejs/biome": "^2.1",
12
+ "@biomejs/biome": "^2.2",
13
13
  "@rollup/plugin-node-resolve": "^16",
14
14
  "@rollup/plugin-typescript": "^12.1",
15
- "@types/node": "^24.1",
15
+ "@types/node": "^24.7",
16
16
  "@vitest/coverage-istanbul": "^3.2",
17
17
  "autoprefixer": "^10.4",
18
- "dts-bundle-generator": "^9.5",
19
- "glob": "^11",
20
- "jsdom": "^26.1",
18
+ "jsdom": "^27",
21
19
  "postcss-cli": "^11",
22
20
  "postcss-input-range": "^6",
23
21
  "postcss-scss": "^4",
24
- "sass": "^1.89",
25
- "stylelint": "^16.22",
22
+ "rollup": "^4.52",
23
+ "sass": "^1.93",
24
+ "stylelint": "^16.25",
26
25
  "tslib": "^2.8",
27
- "typescript": "^5.8",
28
- "vite": "^7",
26
+ "typescript": "^5.9",
27
+ "vite": "npm:rolldown-vite@latest",
29
28
  "vitest": "^3.2"
30
29
  },
31
30
  "exports": {
32
31
  ".": {
33
- "import": {
34
- "types": "./types/index.d.ts",
35
- "default": "./dist/js/index.js"
36
- },
37
- "require": {
38
- "types": "./types/index.d.cts",
39
- "default": "./dist/js/index.cjs"
40
- }
32
+ "types": "./types/index.d.ts",
33
+ "default": "./dist/js/index.js"
41
34
  },
42
35
  "./focus-trap": {
43
- "import": {
44
- "types": "./types/focus-trap/standalone.d.ts",
45
- "default": "./dist/js/focus-trap/standalone.js"
46
- },
47
- "require": {
48
- "types": "./types/focus-trap/standalone.d.cts",
49
- "default": "./dist/js/focus-trap/standalone.cjs"
50
- }
36
+ "types": "./types/focus-trap/standalone.d.ts",
37
+ "default": "./dist/js/focus-trap/standalone.js"
51
38
  },
52
39
  "./popover": {
53
- "import": {
54
- "types": "./types/popover.d.ts",
55
- "default": "./dist/js/popover.js"
56
- },
57
- "require": {
58
- "types": "./types/popover.d.cts",
59
- "default": "./dist/js/popover.cjs"
60
- }
40
+ "types": "./types/popover.d.ts",
41
+ "default": "./dist/js/popover.js"
61
42
  },
62
43
  "./splitter": {
63
- "import": {
64
- "types": "./types/splitter.d.ts",
65
- "default": "./dist/js/splitter.js"
66
- },
67
- "require": {
68
- "types": "./types/splitter.d.cts",
69
- "default": "./dist/js/splitter.cjs"
70
- }
44
+ "types": "./types/splitter.d.ts",
45
+ "default": "./dist/js/splitter.js"
71
46
  },
72
47
  "./tooltip": {
73
- "import": {
74
- "types": "./types/tooltip.d.ts",
75
- "default": "./dist/js/tooltip.js"
76
- },
77
- "require": {
78
- "types": "./types/tooltip.d.cts",
79
- "default": "./dist/js/tooltip.cjs"
80
- }
48
+ "types": "./types/tooltip.d.ts",
49
+ "default": "./dist/js/tooltip.js"
81
50
  }
82
51
  },
83
- "files": ["dist", "src", "types"],
52
+ "files": [
53
+ "dist",
54
+ "src",
55
+ "types"
56
+ ],
84
57
  "keywords": [
85
58
  "css",
86
59
  "scss",
@@ -92,7 +65,6 @@
92
65
  "utility"
93
66
  ],
94
67
  "license": "MIT",
95
- "main": "dist/js/index.cjs",
96
68
  "module": "dist/js/index.js",
97
69
  "name": "@oscarpalmer/oui",
98
70
  "repository": {
@@ -103,16 +75,16 @@
103
75
  "build": "npm run clean && npm run build:css && npm run build:js",
104
76
  "build:css": "npm run build:postcss && npx sass ./postcss:./dist/css --no-source-map",
105
77
  "build:postcss": "npx postcss ./src/css/*.scss -d ./postcss -u autoprefixer postcss-input-range --parser postcss-scss",
106
- "build:js": "npx vite build && npm run types",
78
+ "build:js": "npx vite build && npm run rollup:build && npx tsc",
107
79
  "clean": "rm -rf ./dist && rm -rf ./types && rm -f ./tsconfig.tsbuildinfo",
108
- "rollup": "npx rollup -c --watch",
80
+ "rollup:build": "npx rollup -c",
81
+ "rollup:watch": "npx rollup -c --watch",
109
82
  "test": "npx vitest --coverage",
110
- "types": "npx tsc && npx dts-bundle-generator --config ./dts.config.cts --silent",
111
83
  "watch:css": "npx sass ./postcss:./dist/css --no-source-map --watch",
112
84
  "watch:postcss": "npx postcss ./src/css/*.scss -d ./postcss -u autoprefixer postcss-input-range --parser postcss-scss --watch",
113
85
  "watch:js": "npx vite build --watch"
114
86
  },
115
87
  "type": "module",
116
- "types": "types/index.d.cts",
117
- "version": "0.17.0"
118
- }
88
+ "types": "types/index.d.ts",
89
+ "version": "0.18.0"
90
+ }
@@ -3,7 +3,7 @@
3
3
  @use './mixins' as mixins;
4
4
 
5
5
  @mixin thumb($background, $shadow) {
6
- @include mixins.shadow(
6
+ @include mixins.shadowSmall(
7
7
  color-mix(in oklab, $shadow, transparent 33%),
8
8
  color-mix(in oklab, white, transparent 82.5%)
9
9
  );
@@ -24,7 +24,6 @@
24
24
  background-image: none;
25
25
  border: 1px solid var(--oui-gray-3);
26
26
  border-radius: 0.375em;
27
- box-shadow: inset 0 1px 2px 0 var(--oui-gray-3);
28
27
  }
29
28
 
30
29
  .oui-card {
package/src/css/form.scss CHANGED
@@ -77,9 +77,11 @@
77
77
  }
78
78
 
79
79
  .oui-input {
80
- :where(&:not([type='range' i])) {
80
+ :where(&) {
81
81
  --oui-background-value: var(--oui-absolute);
82
+ }
82
83
 
84
+ :where(&:not([type='range' i])) {
83
85
  @include input;
84
86
 
85
87
  padding: 0.5em 0.75em;
@@ -160,7 +162,7 @@
160
162
  var(--oui-background-value),
161
163
  transparent var(--oui-background-percentage)
162
164
  );
163
- border: 2px solid var(--oui-absolute);
165
+ border: 1px solid var(--oui-absolute);
164
166
  border-radius: 1.25em;
165
167
  box-shadow: 0 1px 2px 2px rgba(0, 0, 0, 0.125);
166
168
  cursor: pointer;
@@ -174,7 +176,7 @@
174
176
  }
175
177
 
176
178
  :where(
177
- &.oui-validatable:not(
179
+ &.oui-validate:not(
178
180
  [disabled],
179
181
  [readonly],
180
182
  [aria-disabled='true' i]
@@ -206,7 +208,7 @@
206
208
  }
207
209
 
208
210
  :where(
209
- &.oui-validatable:not(
211
+ &.oui-validate:not(
210
212
  [disabled],
211
213
  [readonly],
212
214
  [aria-disabled='true' i]
@@ -310,6 +312,12 @@
310
312
 
311
313
  cursor: default;
312
314
  }
315
+
316
+ &::range-thumb {
317
+ --oui-background-value: var(--oui-gray-2);
318
+
319
+ cursor: default;
320
+ }
313
321
  }
314
322
 
315
323
  :where(&:is([disabled], [readonly], [aria-disabled='true' i]):focus) {
@@ -19,6 +19,7 @@
19
19
  var(--oui-shadow-mixed),
20
20
  );
21
21
 
22
+ max-width: fit-content;
22
23
  display: inline-flex;
23
24
  flex-flow: column nowrap;
24
25
  gap: 1em;
@@ -39,6 +40,8 @@
39
40
  }
40
41
 
41
42
  :where(& p) {
43
+ max-width: 32rem;
44
+ max-width: 64ch;
42
45
  display: inline-flex;
43
46
  flex-flow: row wrap;
44
47
  gap: 1em;
@@ -73,6 +73,13 @@
73
73
  0 64px 128px -32px $color;
74
74
  }
75
75
 
76
+ @mixin shadowSmall($color: rgba(0, 0, 0, 0.05), $inset: transparent) {
77
+ box-shadow:
78
+ inset 0 1px 0 0 $inset,
79
+ 0 0 0 1px $color,
80
+ 0 1px 2px -.5px $color;
81
+ }
82
+
76
83
  @mixin visuallyHidden() {
77
84
  width: 1px !important;
78
85
  height: 1px !important;