@stainless-api/ui-primitives 0.1.0-beta.5 → 0.1.0-beta.51

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 (51) hide show
  1. package/dist/DropdownMenu-H_J8MxM7.d.ts +54 -0
  2. package/dist/components/Accordion.d.ts +26 -0
  3. package/dist/components/Accordion.js +29 -0
  4. package/dist/components/Badge.d.ts +40 -0
  5. package/dist/components/Badge.js +63 -0
  6. package/dist/components/Button.d.ts +45 -0
  7. package/dist/components/Button.js +50 -0
  8. package/dist/components/Callout.d.ts +18 -0
  9. package/dist/components/Callout.js +26 -0
  10. package/dist/components/Steps.d.ts +17 -0
  11. package/dist/components/Steps.js +22 -0
  12. package/dist/components/dropdown/Dropdown.d.ts +63 -0
  13. package/dist/components/dropdown/Dropdown.js +52 -0
  14. package/dist/components/dropdown/DropdownButton.d.ts +61 -0
  15. package/dist/components/dropdown/DropdownButton.js +54 -0
  16. package/dist/components/dropdown/DropdownMenu.d.ts +2 -0
  17. package/dist/components/dropdown/DropdownMenu.js +76 -0
  18. package/dist/components/icons/Function.d.ts +9 -0
  19. package/dist/components/icons/Function.js +6 -0
  20. package/dist/components/icons/index.d.ts +2 -0
  21. package/dist/components/icons/index.js +2 -0
  22. package/dist/index.d.ts +8 -0
  23. package/dist/index.js +8 -0
  24. package/dist/scripts/index.d.ts +23 -0
  25. package/dist/scripts/index.js +162 -0
  26. package/dist/styles/starlight-compat.css +131 -0
  27. package/dist/styles/theme.css +183 -0
  28. package/dist/styles.css +1186 -0
  29. package/package.json +43 -24
  30. package/.env +0 -1
  31. package/CHANGELOG.md +0 -33
  32. package/eslint.config.js +0 -2
  33. package/src/components/Button.tsx +0 -94
  34. package/src/components/Callout.tsx +0 -31
  35. package/src/components/DetailsGroup.tsx +0 -17
  36. package/src/components/DropdownButton.tsx +0 -98
  37. package/src/components/button.css +0 -157
  38. package/src/components/callout.css +0 -72
  39. package/src/components/details.css +0 -126
  40. package/src/components/dropdown-button.css +0 -162
  41. package/src/index.ts +0 -4
  42. package/src/scripts/dropdown-button.ts +0 -55
  43. package/src/scripts/index.ts +0 -1
  44. package/src/styles/layout.css +0 -11
  45. package/src/styles/scales.css +0 -129
  46. package/src/styles/starlight-compat.css +0 -125
  47. package/src/styles/swatches.css +0 -87
  48. package/src/styles/theme.css +0 -49
  49. package/src/styles/typography.css +0 -199
  50. package/src/styles.css +0 -11
  51. package/tsconfig.json +0 -15
@@ -0,0 +1,76 @@
1
+ import clsx from "clsx";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import { CheckIcon, ExternalLink } from "lucide-react";
4
+ //#region src/components/dropdown/DropdownMenu.tsx
5
+ function Menu({ className, ...props }) {
6
+ return /* @__PURE__ */ jsx("div", {
7
+ ...props,
8
+ role: "menu",
9
+ "data-state": "closed",
10
+ "data-part": "menu",
11
+ className: clsx("stl-ui-dropdown-menu", className)
12
+ });
13
+ }
14
+ function MenuItemText({ className, subtle, ...props }) {
15
+ return /* @__PURE__ */ jsx("span", {
16
+ ...props,
17
+ "data-part": "item-text",
18
+ className: clsx(`stl-ui-dropdown-menu__item-text`, { "stl-ui-dropdown-menu__item-text--subtle": subtle }, className)
19
+ });
20
+ }
21
+ function MenuItem({ children, value, href, isExternalLink, isSelected, ...props }) {
22
+ const inner = /* @__PURE__ */ jsxs(Fragment, { children: [
23
+ /* @__PURE__ */ jsx("div", {
24
+ className: "stl-ui-dropdown-menu__item-content",
25
+ children
26
+ }),
27
+ isSelected && /* @__PURE__ */ jsx("div", {
28
+ className: "stl-ui-dropdown-menu__item-icon",
29
+ "data-part": "item-selected-icon",
30
+ children: /* @__PURE__ */ jsx(CheckIcon, { size: 16 })
31
+ }),
32
+ isExternalLink && /* @__PURE__ */ jsx("div", {
33
+ className: "stl-ui-dropdown-menu__item-subtle-icon",
34
+ "data-part": "item-external-link-icon",
35
+ children: /* @__PURE__ */ jsx(ExternalLink, { size: 16 })
36
+ })
37
+ ] });
38
+ if (href) return /* @__PURE__ */ jsx("a", {
39
+ role: "menuitem",
40
+ "data-part": "item",
41
+ "data-value": value,
42
+ "aria-selected": isSelected,
43
+ href,
44
+ ...props,
45
+ className: clsx("stl-ui-dropdown-menu__item", "stl-ui-dropdown-menu__item-link", props.className),
46
+ children: inner
47
+ });
48
+ return /* @__PURE__ */ jsx("button", {
49
+ ...props,
50
+ role: "menuitem",
51
+ "data-part": "item",
52
+ "data-value": value,
53
+ "aria-selected": isSelected,
54
+ className: clsx("stl-ui-dropdown-menu__item", props.className),
55
+ children: inner
56
+ });
57
+ }
58
+ /**
59
+ * A template component that defines the content to be displayed in the dropdown trigger
60
+ * when a menu item is selected. This template is used to customize the appearance of
61
+ * the selected item in the trigger button.
62
+ *
63
+ * @param props - Standard HTML template element props
64
+ * @returns A template element marked with the "selected-template" data part
65
+ */
66
+ function MenuItemTemplate({ ...props }) {
67
+ return /* @__PURE__ */ jsx("template", {
68
+ "data-part": "selected-template",
69
+ ...props
70
+ });
71
+ }
72
+ Menu.Item = MenuItem;
73
+ Menu.ItemText = MenuItemText;
74
+ Menu.ItemTemplate = MenuItemTemplate;
75
+ //#endregion
76
+ export { Menu };
@@ -0,0 +1,9 @@
1
+ import * as react from "react";
2
+ import * as lucide_react0 from "lucide-react";
3
+ import { IconNode } from "lucide-react";
4
+
5
+ //#region src/components/icons/Function.d.ts
6
+ declare const __iconNode: IconNode;
7
+ declare const FunctionIcon: react.ForwardRefExoticComponent<Omit<lucide_react0.LucideProps, "ref"> & react.RefAttributes<SVGSVGElement>>;
8
+ //#endregion
9
+ export { FunctionIcon, __iconNode };
@@ -0,0 +1,6 @@
1
+ import { createLucideIcon } from "lucide-react";
2
+ //#region src/components/icons/Function.tsx
3
+ const __iconNode = [["path", { d: "m 7.5982756,10.85526 h 8.3632754 m -8.3632756,8.509999 c 2.9344826,0 4.1082756,-1.467241 4.1082756,-4.108276 V 9.0945701 c 0,-2.9344826 1.467243,-4.8418966 4.695174,-4.4017241" }]];
4
+ const FunctionIcon = createLucideIcon("function", __iconNode);
5
+ //#endregion
6
+ export { FunctionIcon, __iconNode };
@@ -0,0 +1,2 @@
1
+ import { FunctionIcon } from "./Function.js";
2
+ export { FunctionIcon };
@@ -0,0 +1,2 @@
1
+ import { FunctionIcon } from "./Function.js";
2
+ export { FunctionIcon };
@@ -0,0 +1,8 @@
1
+ import { Accordion, AccordionProps } from "./components/Accordion.js";
2
+ import { Badge, BadgeIntent, HTTPMethod, getHttpMethod } from "./components/Badge.js";
3
+ import { Button, ButtonProps, ButtonVariant } from "./components/Button.js";
4
+ import { Callout, CalloutProps, CalloutVariant } from "./components/Callout.js";
5
+ import { Step, Steps } from "./components/Steps.js";
6
+ import { Dropdown } from "./components/dropdown/Dropdown.js";
7
+ import { DropdownButton } from "./components/dropdown/DropdownButton.js";
8
+ export { Accordion, AccordionProps, Badge, BadgeIntent, Button, ButtonProps, ButtonVariant, Callout, CalloutProps, CalloutVariant, Dropdown, DropdownButton, HTTPMethod, Step, Steps, getHttpMethod };
package/dist/index.js ADDED
@@ -0,0 +1,8 @@
1
+ import { Button } from "./components/Button.js";
2
+ import { Dropdown } from "./components/dropdown/Dropdown.js";
3
+ import { DropdownButton } from "./components/dropdown/DropdownButton.js";
4
+ import { Callout } from "./components/Callout.js";
5
+ import { Accordion } from "./components/Accordion.js";
6
+ import { Step, Steps } from "./components/Steps.js";
7
+ import { Badge, getHttpMethod } from "./components/Badge.js";
8
+ export { Accordion, Badge, Button, Callout, Dropdown, DropdownButton, Step, Steps, getHttpMethod };
@@ -0,0 +1,23 @@
1
+ //#region src/scripts/dropdown-button.d.ts
2
+ declare function initDropdownButton({
3
+ dropdown,
4
+ onSelect,
5
+ onPrimaryAction
6
+ }: {
7
+ dropdown: Element;
8
+ onSelect: (value: string) => void;
9
+ onPrimaryAction: (primaryActionElement: Element) => void;
10
+ }): void;
11
+ //#endregion
12
+ //#region src/scripts/dropdown.d.ts
13
+ declare function initDropdown({
14
+ root,
15
+ onSelect,
16
+ initialValue
17
+ }: {
18
+ root?: Element | null;
19
+ onSelect?: (value: string) => void;
20
+ initialValue?: string;
21
+ }): void;
22
+ //#endregion
23
+ export { initDropdown, initDropdownButton };
@@ -0,0 +1,162 @@
1
+ //#region src/scripts/dropdown.ts
2
+ const initialized = /* @__PURE__ */ new WeakSet();
3
+ function initDropdown({ root, onSelect, initialValue }) {
4
+ if (!root) {
5
+ console.error("Dropdown root element not found");
6
+ return;
7
+ }
8
+ if (initialized.has(root)) return;
9
+ const trigger = root.querySelector("[data-part=\"trigger\"]");
10
+ const menu = root.querySelector("[data-part=\"menu\"]");
11
+ if (!trigger) {
12
+ console.error("Dropdown trigger not found");
13
+ return;
14
+ }
15
+ if (!menu) {
16
+ console.error("Dropdown menu not found");
17
+ return;
18
+ }
19
+ const selectedSlot = trigger.querySelector("[data-part=\"trigger-selected\"]");
20
+ const items = Array.from(menu.querySelectorAll("[data-part=\"item\"]"));
21
+ function open() {
22
+ if (!trigger || !menu || !root) return;
23
+ trigger.setAttribute("aria-expanded", "true");
24
+ menu.dataset.state = "open";
25
+ menu.removeAttribute("aria-hidden");
26
+ const triggerRect = trigger.getBoundingClientRect();
27
+ const menuHeight = menu.offsetHeight;
28
+ const spaceBelow = window.innerHeight - triggerRect.bottom;
29
+ const spaceAbove = triggerRect.top;
30
+ menu.classList.remove("stl-ui-dropdown-menu--above", "stl-ui-dropdown-menu--below");
31
+ if (spaceBelow < menuHeight && spaceAbove > spaceBelow) menu.classList.add("stl-ui-dropdown-menu--above");
32
+ else menu.classList.add("stl-ui-dropdown-menu--below");
33
+ }
34
+ function close() {
35
+ if (!trigger || !menu || !root) return;
36
+ trigger.setAttribute("aria-expanded", "false");
37
+ menu.dataset.state = "closed";
38
+ menu.setAttribute("aria-hidden", "true");
39
+ }
40
+ function renderSelectedFromItem(item) {
41
+ if (!selectedSlot) return;
42
+ const tmpl = item.querySelector("template[data-part=\"selected-template\"]");
43
+ if (!tmpl) {
44
+ console.error("Dropdown item template not found");
45
+ return;
46
+ }
47
+ selectedSlot.innerHTML = "";
48
+ selectedSlot.appendChild(tmpl.content.cloneNode(true));
49
+ selectedSlot.removeAttribute("data-placeholder");
50
+ }
51
+ function selectItem(item) {
52
+ if (!trigger) {
53
+ console.error("Dropdown trigger not found");
54
+ return;
55
+ }
56
+ items.forEach((i) => i.setAttribute("aria-selected", String(i === item)));
57
+ trigger.dataset.value = item.getAttribute("data-value") || "";
58
+ renderSelectedFromItem(item);
59
+ }
60
+ function handleItemSelection(e) {
61
+ const item = e.target.closest("[data-part=\"item\"]");
62
+ if (!item) {
63
+ console.error("Dropdown item not found");
64
+ return;
65
+ }
66
+ if (!trigger) {
67
+ console.error("Dropdown trigger not found");
68
+ return;
69
+ }
70
+ selectItem(item);
71
+ onSelect?.(item.getAttribute("data-value") || "");
72
+ close();
73
+ trigger.focus();
74
+ }
75
+ function handleTriggerClick() {
76
+ if (!trigger) return false;
77
+ if (trigger.getAttribute("aria-expanded") === "true") {
78
+ close();
79
+ return false;
80
+ } else {
81
+ open();
82
+ return true;
83
+ }
84
+ }
85
+ const initial = (initialValue ? items.find((i) => i.getAttribute("data-value") === initialValue) : items.find((i) => i.getAttribute("aria-selected") === "true")) ?? items[0];
86
+ if (initial) selectItem(initial);
87
+ trigger.addEventListener("click", () => {
88
+ handleTriggerClick();
89
+ });
90
+ trigger.addEventListener("keydown", (e) => {
91
+ if (e.key !== "Enter" && e.key !== " ") return;
92
+ e.preventDefault();
93
+ if (handleTriggerClick()) items[0]?.focus();
94
+ });
95
+ menu.addEventListener("click", (e) => {
96
+ handleItemSelection(e);
97
+ });
98
+ document.addEventListener("keydown", (e) => {
99
+ if (!(trigger.getAttribute("aria-expanded") === "true")) return;
100
+ if (e.key === "Escape") {
101
+ close();
102
+ trigger.focus();
103
+ return;
104
+ }
105
+ if (e.key === "ArrowDown") {
106
+ e.preventDefault();
107
+ const activeElement = document.activeElement;
108
+ if (activeElement === trigger) {
109
+ items[0]?.focus();
110
+ return;
111
+ }
112
+ let nextSibling = activeElement?.nextElementSibling;
113
+ while (nextSibling && nextSibling.tagName.toLowerCase() === "hr") nextSibling = nextSibling.nextElementSibling;
114
+ if (nextSibling instanceof HTMLElement && items.includes(nextSibling)) nextSibling.focus();
115
+ return;
116
+ }
117
+ if (e.key === "ArrowUp") {
118
+ e.preventDefault();
119
+ const activeElement = document.activeElement;
120
+ if (activeElement === trigger) {
121
+ items[items.length - 1]?.focus();
122
+ return;
123
+ }
124
+ let prevSibling = activeElement?.previousElementSibling;
125
+ while (prevSibling && prevSibling.tagName.toLowerCase() === "hr") prevSibling = prevSibling.previousElementSibling;
126
+ if (prevSibling instanceof HTMLElement && items.includes(prevSibling)) prevSibling.focus();
127
+ return;
128
+ }
129
+ });
130
+ document.addEventListener("click", (e) => {
131
+ if (!root.contains(e.target)) close();
132
+ });
133
+ initialized.add(root);
134
+ }
135
+ //#endregion
136
+ //#region src/scripts/dropdown-button.ts
137
+ function initDropdownButton({ dropdown, onSelect, onPrimaryAction }) {
138
+ const trigger = dropdown.querySelector("[data-part=\"trigger\"]");
139
+ const menu = dropdown.querySelector("[data-part=\"menu\"]");
140
+ const primaryAction = dropdown.querySelector("[data-part=\"primary-action\"]");
141
+ if (!trigger) {
142
+ console.error("Dropdown trigger not found");
143
+ return;
144
+ }
145
+ if (!menu) {
146
+ console.error("Dropdown menu not found");
147
+ return;
148
+ }
149
+ if (!primaryAction) {
150
+ console.error("Dropdown primary action not found");
151
+ return;
152
+ }
153
+ primaryAction.addEventListener("click", () => {
154
+ onPrimaryAction(primaryAction);
155
+ });
156
+ initDropdown({
157
+ root: dropdown,
158
+ onSelect
159
+ });
160
+ }
161
+ //#endregion
162
+ export { initDropdown, initDropdownButton };
@@ -0,0 +1,131 @@
1
+ :root {
2
+ --sl-font: var(--stl-typography-font);
3
+ --sl-font-mono: var(--stl-typography-font-mono);
4
+ --sl-line-height: var(--stl-typography-line-height);
5
+ --sl-text-h1: var(--stl-typography-text-h1);
6
+ --sl-text-h2: var(--stl-typography-text-h2);
7
+ --sl-text-h3: var(--stl-typography-text-h3);
8
+ --sl-text-h4: var(--stl-typography-text-h4);
9
+ --sl-text-h5: var(--stl-typography-text-h5);
10
+ --sl-text-body: var(--stl-typography-scale-base);
11
+ --sl-text-sm: var(--stl-typography-scale-sm);
12
+ --sl-text-body-sm: var(--stl-typography-scale-sm);
13
+ --sl-text-code: var(--stl-typography-scale-sm);
14
+ --sl-text-code-sm: var(--stl-typography-scale-xs);
15
+ --sl-color-bg: var(--stl-color-background);
16
+ --sl-color-bg-sidebar: var(--stl-color-background);
17
+ --sl-color-bg-ui: var(--stl-color-ui-background);
18
+ --sl-color-bg-nav: var(--stl-color-background);
19
+ --sl-color-bg-inline-code: var(--stl-color-muted-background);
20
+ --sl-color-bg-accent: var(--stl-color-accent-inverse-background);
21
+ --sl-color-text: var(--stl-color-foreground);
22
+ --sl-color-text-secondary: var(--stl-color-foreground-reduced);
23
+ --sl-color-text-tertiary: var(--stl-color-foreground-muted);
24
+ --sl-color-text-accent: var(--stl-color-accent-foreground);
25
+ --sl-color-hairline: var(--stl-color-border);
26
+ --sl-color-hairline-light: var(--stl-color-border-faint);
27
+ --sl-color-hairline-shade: var(--stl-color-border-strong);
28
+ --sl-color-text-invert: var(--stl-color-inverse-foreground);
29
+ --sl-color-accent-low: var(--stl-color-accent-muted-background);
30
+ --sl-color-accent: var(--stl-color-accent);
31
+ --sl-color-accent-high: var(--stl-color-accent);
32
+ --sl-color-red-low: var(--stl-color-red-muted-background);
33
+ --sl-color-red: var(--stl-color-red);
34
+ --sl-color-red-high: var(--stl-color-red);
35
+ --sl-color-green-low: var(--stl-color-green-muted-background);
36
+ --sl-color-green: var(--stl-color-green);
37
+ --sl-color-green-high: var(--stl-color-green);
38
+ --sl-color-blue-low: var(--stl-color-blue-muted-background);
39
+ --sl-color-blue: var(--stl-color-blue);
40
+ --sl-color-blue-high: var(--stl-color-blue);
41
+ --sl-color-orange-low: var(--stl-color-orange-muted-background);
42
+ --sl-color-orange: var(--stl-color-orange);
43
+ --sl-color-orange-high: var(--stl-color-orange);
44
+ --sl-color-purple-low: var(--stl-color-purple-muted-background);
45
+ --sl-color-purple: var(--stl-color-purple);
46
+ --sl-color-purple-high: var(--stl-color-purple);
47
+ --sl-color-teal-low: var(--stl-color-cyan-muted-background);
48
+ --sl-color-teal: var(--stl-color-cyan);
49
+ --sl-color-teal-high: var(--stl-color-cyan);
50
+ --sl-color-magenta-low: var(--stl-color-pink-muted-background);
51
+ --sl-color-magenta: var(--stl-color-pink);
52
+ --sl-color-magenta-high: var(--stl-color-pink);
53
+ --sl-color-yellow-low: var(--stl-color-yellow-muted-background);
54
+ --sl-color-yellow: var(--stl-color-yellow);
55
+ --sl-color-yellow-high: var(--stl-color-yellow);
56
+ }
57
+
58
+ .stl-ui-prose {
59
+ & .sl-heading-wrapper {
60
+ line-height: var(--stl-typography-line-height-heading);
61
+ font-family: var(--stl-typography-font-heading);
62
+ --sl-anchor-icon-size: .8em;
63
+
64
+ & :is(h1, h2, h3, h4, h5) {
65
+ font-size: inherit;
66
+ }
67
+ }
68
+
69
+ & .sl-heading-wrapper.level-h1 {
70
+ font-size: var(--stl-typography-text-h1);
71
+ letter-spacing: -.03em;
72
+ margin-top: 64px;
73
+ }
74
+
75
+ & .sl-heading-wrapper.level-h2 {
76
+ font-size: var(--stl-typography-text-h2);
77
+ letter-spacing: -.03em;
78
+ margin-top: 48px;
79
+ }
80
+
81
+ & .sl-heading-wrapper.level-h3 {
82
+ font-size: var(--stl-typography-text-h3);
83
+ letter-spacing: -.02em;
84
+ margin-top: 40px;
85
+ }
86
+
87
+ & .sl-heading-wrapper.level-h4 {
88
+ font-size: var(--stl-typography-text-h4);
89
+ letter-spacing: -.02em;
90
+ margin-top: 32px;
91
+ }
92
+
93
+ & .sl-heading-wrapper.level-h5 {
94
+ font-size: var(--stl-typography-text-h5);
95
+ letter-spacing: -.02em;
96
+ margin-top: 24px;
97
+ }
98
+
99
+ & .sl-anchor-link svg {
100
+ margin-top: 0;
101
+ }
102
+ }
103
+
104
+ .stl-ui-prose starlight-tabs {
105
+ & a[role="tab"] {
106
+ line-height: unset;
107
+ color: var(--stl-color-foreground);
108
+ text-decoration: none;
109
+
110
+ &[aria-selected="true"] {
111
+ color: var(--stl-color-accent-foreground);
112
+ font-weight: normal;
113
+ }
114
+ }
115
+
116
+ & [role="tablist"]:is(ol, ul) {
117
+ padding-left: 0;
118
+ }
119
+
120
+ & li.tab:not(.stl-ui-not-prose *) {
121
+ margin-bottom: 0;
122
+
123
+ & > a:first-child {
124
+ display: flex;
125
+ }
126
+ }
127
+ }
128
+
129
+ ol.sl-steps {
130
+ padding-left: 0;
131
+ }
@@ -0,0 +1,183 @@
1
+ @charset "UTF-8";
2
+ /* 1. Base colors */
3
+ @layer stl-ui.tokens {
4
+ :root {
5
+ --stl-opacity-level-080: 0.80;
6
+ --stl-opacity-level-040: 0.40;
7
+ --stl-opacity-level-016: 0.16;
8
+ --stl-opacity-level-008: 0.08;
9
+ --stl-opacity-level-004: 0.04;
10
+ /* background */
11
+ --stl-color-background: light-dark(rgb(255 255 255), rgb(10 10 10));
12
+ --stl-color-background-hover: light-dark(rgb(from var(--stl-color-foreground) r g b/calc(alpha * var(--stl-opacity-level-004))), rgb(from var(--stl-color-foreground) r g b/calc(alpha * var(--stl-opacity-level-008))));
13
+ /* background shades */
14
+ /* muted background */
15
+ --stl-color-muted-background: light-dark(rgb(from var(--stl-color-foreground) r g b/calc(alpha * var(--stl-opacity-level-008))), rgb(from var(--stl-color-foreground) r g b/calc(alpha * var(--stl-opacity-level-016))));
16
+ --stl-color-muted-background-hover: rgb(from var(--stl-color-muted-background) r g b/calc(alpha * 2));
17
+ /* faint background */
18
+ --stl-color-faint-background: rgb(from var(--stl-color-foreground) r g b/calc(alpha * var(--stl-opacity-level-004)));
19
+ --stl-color-faint-background-hover: rgb(from var(--stl-color-faint-background) r g b/calc(alpha * 2));
20
+ /* ui elements like cards and buttons match --stl-color-background in light mode, but have a slight tint in dark mode */
21
+ --stl-color-ui-background: light-dark(
22
+ var(--stl-color-background),
23
+ rgb(from var(--stl-color-foreground) r g b/calc(alpha * var(--stl-opacity-level-004)))
24
+ );
25
+ --stl-color-ui-background-hover: light-dark(
26
+ var(--stl-color-background-hover),
27
+ rgb(from var(--stl-color-ui-background) r g b/calc(alpha * 2))
28
+ );
29
+ /* foreground */
30
+ --stl-color-foreground: light-dark(rgb(38 38 38), rgb(245 245 245));
31
+ --stl-color-foreground-reduced: rgb(from var(--stl-color-foreground) r g b/calc(alpha * var(--stl-opacity-level-080)));
32
+ --stl-color-foreground-muted: rgb(from var(--stl-color-foreground) r g b/calc(alpha * var(--stl-opacity-level-040)));
33
+ /* inverse */
34
+ --stl-color-inverse-background: var(--stl-color-foreground);
35
+ --stl-color-inverse-background-hover: rgb(from var(--stl-color-inverse-background) r g b/calc(alpha * 0.9));
36
+ --stl-color-inverse-foreground: var(--stl-color-background);
37
+ /* default border (“foreground border”) */
38
+ --stl-color-border: rgb(from var(--stl-color-foreground) r g b/calc(alpha * var(--stl-opacity-level-016)));
39
+ --stl-color-border-faint: rgb(from var(--stl-color-border) r g b/calc(alpha * 0.5));
40
+ --stl-color-border-strong: rgb(from var(--stl-color-border) r g b/calc(alpha * 2.5));
41
+ }
42
+ }
43
+ /* 2. Color palettes (accent, red, green, etc) */
44
+ @layer stl-ui.tokens {
45
+ :root {
46
+ /* accent */
47
+ --stl-color-accent: light-dark(#155dfc, #2b7fff);
48
+ --stl-color-accent-foreground: var(--stl-color-accent);
49
+ --stl-color-accent-foreground-reduced: rgb(from var(--stl-color-accent-foreground) r g b/calc(alpha * var(--stl-opacity-level-080)));
50
+ --stl-color-accent-foreground-muted: rgb(from var(--stl-color-accent-foreground) r g b/calc(alpha * var(--stl-opacity-level-040)));
51
+ --stl-color-accent-muted-background: light-dark(rgb(from var(--stl-color-accent-foreground) r g b/calc(alpha * var(--stl-opacity-level-008))), rgb(from var(--stl-color-accent-foreground) r g b/calc(alpha * var(--stl-opacity-level-016))));
52
+ --stl-color-accent-muted-background-hover: rgb(from var(--stl-color-accent-muted-background) r g b/calc(alpha * 2));
53
+ --stl-color-accent-border: light-dark(rgb(from var(--stl-color-accent) r g b/calc(alpha * var(--stl-opacity-level-016))), rgb(from var(--stl-color-accent) r g b/calc(alpha * calc(var(--stl-opacity-level-016) * 1.5))));
54
+ --stl-color-accent-border-faint: rgb(from var(--stl-color-accent-border) r g b/calc(alpha * 0.5));
55
+ --stl-color-accent-border-strong: var(--stl-color-accent);
56
+ --stl-color-accent-inverse-background: var(--stl-color-accent);
57
+ --stl-color-accent-inverse-background-hover: rgb(from var(--stl-color-accent-inverse-background) r g b/calc(alpha * var(--stl-opacity-level-080)));
58
+ --stl-color-accent-inverse-foreground: rgb(255, 255, 255);
59
+ /* red */
60
+ --stl-color-red: light-dark(#d01e22, #e34041);
61
+ --stl-color-red-foreground: var(--stl-color-red);
62
+ --stl-color-red-foreground-reduced: rgb(from var(--stl-color-red-foreground) r g b/calc(alpha * var(--stl-opacity-level-080)));
63
+ --stl-color-red-foreground-muted: rgb(from var(--stl-color-red-foreground) r g b/calc(alpha * var(--stl-opacity-level-040)));
64
+ --stl-color-red-muted-background: light-dark(rgb(from var(--stl-color-red-foreground) r g b/calc(alpha * var(--stl-opacity-level-008))), rgb(from var(--stl-color-red-foreground) r g b/calc(alpha * var(--stl-opacity-level-016))));
65
+ --stl-color-red-muted-background-hover: rgb(from var(--stl-color-red-muted-background) r g b/calc(alpha * 2));
66
+ --stl-color-red-border: light-dark(rgb(from var(--stl-color-red) r g b/calc(alpha * var(--stl-opacity-level-016))), rgb(from var(--stl-color-red) r g b/calc(alpha * calc(var(--stl-opacity-level-016) * 1.5))));
67
+ --stl-color-red-border-faint: rgb(from var(--stl-color-red-border) r g b/calc(alpha * 0.5));
68
+ --stl-color-red-border-strong: var(--stl-color-red);
69
+ --stl-color-red-inverse-background: var(--stl-color-red);
70
+ --stl-color-red-inverse-background-hover: rgb(from var(--stl-color-red-inverse-background) r g b/calc(alpha * var(--stl-opacity-level-080)));
71
+ --stl-color-red-inverse-foreground: rgb(255, 255, 255);
72
+ /* green */
73
+ --stl-color-green: light-dark(#16a34a, #22c55e);
74
+ --stl-color-green-foreground: var(--stl-color-green);
75
+ --stl-color-green-foreground-reduced: rgb(from var(--stl-color-green-foreground) r g b/calc(alpha * var(--stl-opacity-level-080)));
76
+ --stl-color-green-foreground-muted: rgb(from var(--stl-color-green-foreground) r g b/calc(alpha * var(--stl-opacity-level-040)));
77
+ --stl-color-green-muted-background: light-dark(rgb(from var(--stl-color-green-foreground) r g b/calc(alpha * var(--stl-opacity-level-008))), rgb(from var(--stl-color-green-foreground) r g b/calc(alpha * var(--stl-opacity-level-016))));
78
+ --stl-color-green-muted-background-hover: rgb(from var(--stl-color-green-muted-background) r g b/calc(alpha * 2));
79
+ --stl-color-green-border: light-dark(rgb(from var(--stl-color-green) r g b/calc(alpha * var(--stl-opacity-level-016))), rgb(from var(--stl-color-green) r g b/calc(alpha * calc(var(--stl-opacity-level-016) * 1.5))));
80
+ --stl-color-green-border-faint: rgb(from var(--stl-color-green-border) r g b/calc(alpha * 0.5));
81
+ --stl-color-green-border-strong: var(--stl-color-green);
82
+ --stl-color-green-inverse-background: var(--stl-color-green);
83
+ --stl-color-green-inverse-background-hover: rgb(from var(--stl-color-green-inverse-background) r g b/calc(alpha * var(--stl-opacity-level-080)));
84
+ --stl-color-green-inverse-foreground: rgb(255, 255, 255);
85
+ /* blue */
86
+ --stl-color-blue: light-dark(#155dfc, #2b7fff);
87
+ --stl-color-blue-foreground: var(--stl-color-blue);
88
+ --stl-color-blue-foreground-reduced: rgb(from var(--stl-color-blue-foreground) r g b/calc(alpha * var(--stl-opacity-level-080)));
89
+ --stl-color-blue-foreground-muted: rgb(from var(--stl-color-blue-foreground) r g b/calc(alpha * var(--stl-opacity-level-040)));
90
+ --stl-color-blue-muted-background: light-dark(rgb(from var(--stl-color-blue-foreground) r g b/calc(alpha * var(--stl-opacity-level-008))), rgb(from var(--stl-color-blue-foreground) r g b/calc(alpha * var(--stl-opacity-level-016))));
91
+ --stl-color-blue-muted-background-hover: rgb(from var(--stl-color-blue-muted-background) r g b/calc(alpha * 2));
92
+ --stl-color-blue-border: light-dark(rgb(from var(--stl-color-blue) r g b/calc(alpha * var(--stl-opacity-level-016))), rgb(from var(--stl-color-blue) r g b/calc(alpha * calc(var(--stl-opacity-level-016) * 1.5))));
93
+ --stl-color-blue-border-faint: rgb(from var(--stl-color-blue-border) r g b/calc(alpha * 0.5));
94
+ --stl-color-blue-border-strong: var(--stl-color-blue);
95
+ --stl-color-blue-inverse-background: var(--stl-color-blue);
96
+ --stl-color-blue-inverse-background-hover: rgb(from var(--stl-color-blue-inverse-background) r g b/calc(alpha * var(--stl-opacity-level-080)));
97
+ --stl-color-blue-inverse-foreground: rgb(255, 255, 255);
98
+ /* yellow */
99
+ --stl-color-yellow: light-dark(#ca8a04, #eab308);
100
+ --stl-color-yellow-foreground: var(--stl-color-yellow);
101
+ --stl-color-yellow-foreground-reduced: rgb(from var(--stl-color-yellow-foreground) r g b/calc(alpha * var(--stl-opacity-level-080)));
102
+ --stl-color-yellow-foreground-muted: rgb(from var(--stl-color-yellow-foreground) r g b/calc(alpha * var(--stl-opacity-level-040)));
103
+ --stl-color-yellow-muted-background: light-dark(rgb(from var(--stl-color-yellow-foreground) r g b/calc(alpha * var(--stl-opacity-level-008))), rgb(from var(--stl-color-yellow-foreground) r g b/calc(alpha * var(--stl-opacity-level-016))));
104
+ --stl-color-yellow-muted-background-hover: rgb(from var(--stl-color-yellow-muted-background) r g b/calc(alpha * 2));
105
+ --stl-color-yellow-border: light-dark(rgb(from var(--stl-color-yellow) r g b/calc(alpha * var(--stl-opacity-level-016))), rgb(from var(--stl-color-yellow) r g b/calc(alpha * calc(var(--stl-opacity-level-016) * 1.5))));
106
+ --stl-color-yellow-border-faint: rgb(from var(--stl-color-yellow-border) r g b/calc(alpha * 0.5));
107
+ --stl-color-yellow-border-strong: var(--stl-color-yellow);
108
+ --stl-color-yellow-inverse-background: var(--stl-color-yellow);
109
+ --stl-color-yellow-inverse-background-hover: rgb(from var(--stl-color-yellow-inverse-background) r g b/calc(alpha * var(--stl-opacity-level-080)));
110
+ --stl-color-yellow-inverse-foreground: rgb(255, 255, 255);
111
+ /* orange */
112
+ --stl-color-orange: light-dark(#ea580c, #f97316);
113
+ --stl-color-orange-foreground: var(--stl-color-orange);
114
+ --stl-color-orange-foreground-reduced: rgb(from var(--stl-color-orange-foreground) r g b/calc(alpha * var(--stl-opacity-level-080)));
115
+ --stl-color-orange-foreground-muted: rgb(from var(--stl-color-orange-foreground) r g b/calc(alpha * var(--stl-opacity-level-040)));
116
+ --stl-color-orange-muted-background: light-dark(rgb(from var(--stl-color-orange-foreground) r g b/calc(alpha * var(--stl-opacity-level-008))), rgb(from var(--stl-color-orange-foreground) r g b/calc(alpha * var(--stl-opacity-level-016))));
117
+ --stl-color-orange-muted-background-hover: rgb(from var(--stl-color-orange-muted-background) r g b/calc(alpha * 2));
118
+ --stl-color-orange-border: light-dark(rgb(from var(--stl-color-orange) r g b/calc(alpha * var(--stl-opacity-level-016))), rgb(from var(--stl-color-orange) r g b/calc(alpha * calc(var(--stl-opacity-level-016) * 1.5))));
119
+ --stl-color-orange-border-faint: rgb(from var(--stl-color-orange-border) r g b/calc(alpha * 0.5));
120
+ --stl-color-orange-border-strong: var(--stl-color-orange);
121
+ --stl-color-orange-inverse-background: var(--stl-color-orange);
122
+ --stl-color-orange-inverse-background-hover: rgb(from var(--stl-color-orange-inverse-background) r g b/calc(alpha * var(--stl-opacity-level-080)));
123
+ --stl-color-orange-inverse-foreground: rgb(255, 255, 255);
124
+ /* purple */
125
+ --stl-color-purple: light-dark(#9333ea, #a855f7);
126
+ --stl-color-purple-foreground: var(--stl-color-purple);
127
+ --stl-color-purple-foreground-reduced: rgb(from var(--stl-color-purple-foreground) r g b/calc(alpha * var(--stl-opacity-level-080)));
128
+ --stl-color-purple-foreground-muted: rgb(from var(--stl-color-purple-foreground) r g b/calc(alpha * var(--stl-opacity-level-040)));
129
+ --stl-color-purple-muted-background: light-dark(rgb(from var(--stl-color-purple-foreground) r g b/calc(alpha * var(--stl-opacity-level-008))), rgb(from var(--stl-color-purple-foreground) r g b/calc(alpha * var(--stl-opacity-level-016))));
130
+ --stl-color-purple-muted-background-hover: rgb(from var(--stl-color-purple-muted-background) r g b/calc(alpha * 2));
131
+ --stl-color-purple-border: light-dark(rgb(from var(--stl-color-purple) r g b/calc(alpha * var(--stl-opacity-level-016))), rgb(from var(--stl-color-purple) r g b/calc(alpha * calc(var(--stl-opacity-level-016) * 1.5))));
132
+ --stl-color-purple-border-faint: rgb(from var(--stl-color-purple-border) r g b/calc(alpha * 0.5));
133
+ --stl-color-purple-border-strong: var(--stl-color-purple);
134
+ --stl-color-purple-inverse-background: var(--stl-color-purple);
135
+ --stl-color-purple-inverse-background-hover: rgb(from var(--stl-color-purple-inverse-background) r g b/calc(alpha * var(--stl-opacity-level-080)));
136
+ --stl-color-purple-inverse-foreground: rgb(255, 255, 255);
137
+ /* cyan */
138
+ --stl-color-cyan: light-dark(#0891b2, #06b6d4);
139
+ --stl-color-cyan-foreground: var(--stl-color-cyan);
140
+ --stl-color-cyan-foreground-reduced: rgb(from var(--stl-color-cyan-foreground) r g b/calc(alpha * var(--stl-opacity-level-080)));
141
+ --stl-color-cyan-foreground-muted: rgb(from var(--stl-color-cyan-foreground) r g b/calc(alpha * var(--stl-opacity-level-040)));
142
+ --stl-color-cyan-muted-background: light-dark(rgb(from var(--stl-color-cyan-foreground) r g b/calc(alpha * var(--stl-opacity-level-008))), rgb(from var(--stl-color-cyan-foreground) r g b/calc(alpha * var(--stl-opacity-level-016))));
143
+ --stl-color-cyan-muted-background-hover: rgb(from var(--stl-color-cyan-muted-background) r g b/calc(alpha * 2));
144
+ --stl-color-cyan-border: light-dark(rgb(from var(--stl-color-cyan) r g b/calc(alpha * var(--stl-opacity-level-016))), rgb(from var(--stl-color-cyan) r g b/calc(alpha * calc(var(--stl-opacity-level-016) * 1.5))));
145
+ --stl-color-cyan-border-faint: rgb(from var(--stl-color-cyan-border) r g b/calc(alpha * 0.5));
146
+ --stl-color-cyan-border-strong: var(--stl-color-cyan);
147
+ --stl-color-cyan-inverse-background: var(--stl-color-cyan);
148
+ --stl-color-cyan-inverse-background-hover: rgb(from var(--stl-color-cyan-inverse-background) r g b/calc(alpha * var(--stl-opacity-level-080)));
149
+ --stl-color-cyan-inverse-foreground: rgb(255, 255, 255);
150
+ /* pink */
151
+ --stl-color-pink: light-dark(#ec4899, #ec4899);
152
+ --stl-color-pink-foreground: var(--stl-color-pink);
153
+ --stl-color-pink-foreground-reduced: rgb(from var(--stl-color-pink-foreground) r g b/calc(alpha * var(--stl-opacity-level-080)));
154
+ --stl-color-pink-foreground-muted: rgb(from var(--stl-color-pink-foreground) r g b/calc(alpha * var(--stl-opacity-level-040)));
155
+ --stl-color-pink-muted-background: light-dark(rgb(from var(--stl-color-pink-foreground) r g b/calc(alpha * var(--stl-opacity-level-008))), rgb(from var(--stl-color-pink-foreground) r g b/calc(alpha * var(--stl-opacity-level-016))));
156
+ --stl-color-pink-muted-background-hover: rgb(from var(--stl-color-pink-muted-background) r g b/calc(alpha * 2));
157
+ --stl-color-pink-border: light-dark(rgb(from var(--stl-color-pink) r g b/calc(alpha * var(--stl-opacity-level-016))), rgb(from var(--stl-color-pink) r g b/calc(alpha * calc(var(--stl-opacity-level-016) * 1.5))));
158
+ --stl-color-pink-border-faint: rgb(from var(--stl-color-pink-border) r g b/calc(alpha * 0.5));
159
+ --stl-color-pink-border-strong: var(--stl-color-pink);
160
+ --stl-color-pink-inverse-background: var(--stl-color-pink);
161
+ --stl-color-pink-inverse-background-hover: rgb(from var(--stl-color-pink-inverse-background) r g b/calc(alpha * var(--stl-opacity-level-080)));
162
+ --stl-color-pink-inverse-foreground: rgb(255, 255, 255);
163
+ }
164
+ :root[data-theme=dark],
165
+ .stl-theme-dark {
166
+ color-scheme: dark;
167
+ background: var(--stl-color-background);
168
+ color: var(--stl-color-foreground);
169
+ }
170
+ :root[data-theme=light],
171
+ .stl-theme-light {
172
+ color-scheme: light;
173
+ background: var(--stl-color-background);
174
+ color: var(--stl-color-foreground);
175
+ }
176
+ }
177
+ /* Semantic color roles */
178
+ @layer stl-ui.tokens {
179
+ :root {
180
+ --stl-color-link-foreground: var(--stl-color-accent-foreground);
181
+ --stl-color-text-selection: var(--stl-color-accent-inverse-background);
182
+ }
183
+ }