@antadesign/anta 0.3.1 → 0.3.2
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.
- package/dist/anta_helpers.d.ts +10 -0
- package/dist/anta_helpers.js +13 -1
- package/dist/components/Button.js +8 -17
- package/dist/components/Checkbox.d.ts +16 -15
- package/dist/components/Checkbox.js +10 -6
- package/dist/components/Input.d.ts +4 -4
- package/dist/components/Input.js +5 -5
- package/dist/components/RadioGroup.d.ts +15 -15
- package/dist/components/RadioGroup.js +8 -8
- package/dist/components/Tab.d.ts +34 -0
- package/dist/components/Tab.js +4 -0
- package/dist/components/TabPanel.d.ts +22 -0
- package/dist/components/TabPanel.js +4 -0
- package/dist/components/Tabs.d.ts +112 -0
- package/dist/components/Tabs.js +174 -0
- package/dist/components/Tabs.module.css +1 -0
- package/dist/components/Tooltip.d.ts +10 -1
- package/dist/components/Tooltip.js +4 -0
- package/dist/elements/a-button.css +1 -1
- package/dist/elements/a-checkbox.css +1 -1
- package/dist/elements/a-expander.js +6 -1
- package/dist/elements/a-input.js +1 -1
- package/dist/elements/a-radio.css +1 -1
- package/dist/elements/a-tab.css +1 -0
- package/dist/elements/a-tab.d.ts +14 -0
- package/dist/elements/a-tab.js +46 -0
- package/dist/elements/a-tabpanel.css +1 -0
- package/dist/elements/a-tabs.css +1 -0
- package/dist/elements/a-tabs.d.ts +31 -0
- package/dist/elements/a-tabs.js +157 -0
- package/dist/elements/a-text.css +1 -1
- package/dist/elements/a-title.css +1 -1
- package/dist/elements/a-tooltip.d.ts +18 -0
- package/dist/elements/a-tooltip.js +45 -0
- package/dist/elements/index.d.ts +3 -0
- package/dist/elements/index.js +7 -0
- package/dist/general_types.d.ts +146 -20
- package/dist/index.d.ts +6 -0
- package/dist/index.js +6 -0
- package/dist/jsx-runtime.d.ts +5 -1
- package/dist/tokens.css +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { HTMLElementBase } from "../anta_helpers";
|
|
2
|
+
import "./a-tabs.css";
|
|
3
|
+
class ATabsElement extends HTMLElementBase {
|
|
4
|
+
static observedAttributes = ["state", "disabled", "orientation"];
|
|
5
|
+
internals;
|
|
6
|
+
uncontrolledValue = null;
|
|
7
|
+
seeded = false;
|
|
8
|
+
observer;
|
|
9
|
+
// The tab last scrolled into view — so scroll-into-view fires only when the SELECTION
|
|
10
|
+
// changes, not on every sync() (orientation / disabled changes call sync() too).
|
|
11
|
+
lastSelected = null;
|
|
12
|
+
// True after the first connect — gates the native `change` event so it never fires
|
|
13
|
+
// for the initial seed, and gates scroll-into-view so mounting doesn't jump the page.
|
|
14
|
+
alive = false;
|
|
15
|
+
/** The selected tab's value, or `null` when nothing is selected. */
|
|
16
|
+
get value() {
|
|
17
|
+
return this.currentValue;
|
|
18
|
+
}
|
|
19
|
+
constructor() {
|
|
20
|
+
super();
|
|
21
|
+
this.internals = this.attachInternals?.();
|
|
22
|
+
}
|
|
23
|
+
connectedCallback() {
|
|
24
|
+
if (!this.seeded) {
|
|
25
|
+
this.uncontrolledValue = this.getAttribute("default-state");
|
|
26
|
+
this.seeded = true;
|
|
27
|
+
}
|
|
28
|
+
this.addEventListener("click", this.onClick);
|
|
29
|
+
this.addEventListener("keydown", this.onKeyDown);
|
|
30
|
+
this.observer ??= new this.view.MutationObserver((records) => {
|
|
31
|
+
const touchedTabs = records.some(
|
|
32
|
+
(rec) => [...rec.addedNodes, ...rec.removedNodes].some(
|
|
33
|
+
(n) => n.nodeName === "A-TAB" || n.querySelector?.("a-tab") != null
|
|
34
|
+
)
|
|
35
|
+
);
|
|
36
|
+
if (touchedTabs) this.sync();
|
|
37
|
+
});
|
|
38
|
+
this.observer.observe(this, { childList: true, subtree: true });
|
|
39
|
+
this.sync();
|
|
40
|
+
this.alive = true;
|
|
41
|
+
}
|
|
42
|
+
disconnectedCallback() {
|
|
43
|
+
this.observer?.disconnect();
|
|
44
|
+
}
|
|
45
|
+
attributeChangedCallback(name, oldValue, newValue) {
|
|
46
|
+
this.sync();
|
|
47
|
+
if (name === "state" && this.alive && newValue !== oldValue) this.emitChange();
|
|
48
|
+
}
|
|
49
|
+
formDisabledCallback(disabled) {
|
|
50
|
+
if (disabled) this.internals?.states.add("disabled");
|
|
51
|
+
else this.internals?.states.delete("disabled");
|
|
52
|
+
this.sync();
|
|
53
|
+
}
|
|
54
|
+
// Controlled when `state` is present; otherwise the in-memory uncontrolled value.
|
|
55
|
+
get currentValue() {
|
|
56
|
+
return this.hasAttribute("state") ? this.getAttribute("state") : this.uncontrolledValue;
|
|
57
|
+
}
|
|
58
|
+
get isDisabled() {
|
|
59
|
+
return this.hasAttribute("disabled") || (this.internals?.states.has("disabled") ?? false);
|
|
60
|
+
}
|
|
61
|
+
get isVertical() {
|
|
62
|
+
return this.getAttribute("orientation") === "vertical";
|
|
63
|
+
}
|
|
64
|
+
get tabs() {
|
|
65
|
+
return Array.from(this.querySelectorAll("a-tab"));
|
|
66
|
+
}
|
|
67
|
+
sync = () => {
|
|
68
|
+
const value = this.currentValue;
|
|
69
|
+
const tabs = this.tabs;
|
|
70
|
+
const selectedEl = tabs.find((t) => t.value === value && value != null) ?? null;
|
|
71
|
+
for (const t of tabs) t.selected = t === selectedEl;
|
|
72
|
+
if (this.internals && "ariaActiveDescendantElement" in this.internals) {
|
|
73
|
+
this.internals.ariaActiveDescendantElement = selectedEl;
|
|
74
|
+
}
|
|
75
|
+
if (this.alive && selectedEl && selectedEl !== this.lastSelected) {
|
|
76
|
+
selectedEl.scrollIntoView({ block: "nearest", inline: "nearest" });
|
|
77
|
+
}
|
|
78
|
+
this.lastSelected = selectedEl;
|
|
79
|
+
};
|
|
80
|
+
// The shared state algorithm: fire the cancelable `statechange` *before* applying.
|
|
81
|
+
// Controlled never self-applies; uncontrolled applies unless vetoed.
|
|
82
|
+
requestSelect(next) {
|
|
83
|
+
const prev = this.currentValue;
|
|
84
|
+
if (next === prev) return;
|
|
85
|
+
const ok = this.emitStateChange(next, prev);
|
|
86
|
+
if (this.hasAttribute("state")) return;
|
|
87
|
+
if (ok) {
|
|
88
|
+
this.uncontrolledValue = next;
|
|
89
|
+
this.sync();
|
|
90
|
+
this.emitChange();
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// Native `change`, fired *after* a selection applies (user pick or a controlled
|
|
94
|
+
// `state` update) — the post-apply counterpart to the cancelable `statechange`.
|
|
95
|
+
emitChange() {
|
|
96
|
+
this.dispatchEvent(new Event("change", { bubbles: true }));
|
|
97
|
+
}
|
|
98
|
+
/** Dispatch the shared cancelable `statechange`. `next`/`prev` are values
|
|
99
|
+
* (`null` when nothing is selected). Returns false if a listener vetoed. */
|
|
100
|
+
emitStateChange(next, prev) {
|
|
101
|
+
return this.dispatchEvent(
|
|
102
|
+
new CustomEvent("statechange", {
|
|
103
|
+
cancelable: true,
|
|
104
|
+
bubbles: true,
|
|
105
|
+
composed: true,
|
|
106
|
+
detail: { next, prev }
|
|
107
|
+
})
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
onClick = (e) => {
|
|
111
|
+
if (this.isDisabled) return;
|
|
112
|
+
const tab = e.target?.closest("a-tab");
|
|
113
|
+
if (!tab || tab.hasAttribute("disabled")) return;
|
|
114
|
+
tab.focus();
|
|
115
|
+
this.requestSelect(tab.value);
|
|
116
|
+
};
|
|
117
|
+
onKeyDown = (e) => {
|
|
118
|
+
if (this.isDisabled) return;
|
|
119
|
+
const enabled = this.tabs.filter((t) => !t.hasAttribute("disabled"));
|
|
120
|
+
if (enabled.length === 0) return;
|
|
121
|
+
const focused = e.target?.closest("a-tab");
|
|
122
|
+
if (e.key === " " || e.key === "Enter") {
|
|
123
|
+
if (focused && enabled.includes(focused)) {
|
|
124
|
+
e.preventDefault();
|
|
125
|
+
this.requestSelect(focused.value);
|
|
126
|
+
}
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
if (e.key === "Home" || e.key === "End") {
|
|
130
|
+
e.preventDefault();
|
|
131
|
+
const target = e.key === "Home" ? enabled[0] : enabled[enabled.length - 1];
|
|
132
|
+
target.focus();
|
|
133
|
+
this.requestSelect(target.value);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
const forward = e.key === (this.isVertical ? "ArrowDown" : "ArrowRight");
|
|
137
|
+
const back = e.key === (this.isVertical ? "ArrowUp" : "ArrowLeft");
|
|
138
|
+
if (!forward && !back) return;
|
|
139
|
+
e.preventDefault();
|
|
140
|
+
let i = focused ? enabled.indexOf(focused) : -1;
|
|
141
|
+
if (i === -1) i = enabled.findIndex((t) => t.value === this.currentValue);
|
|
142
|
+
if (i === -1) i = 0;
|
|
143
|
+
const next = enabled[(i + (forward ? 1 : -1) + enabled.length) % enabled.length];
|
|
144
|
+
next.focus();
|
|
145
|
+
this.requestSelect(next.value);
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
function register_a_tabs() {
|
|
149
|
+
if (typeof customElements === "undefined") return;
|
|
150
|
+
if (!customElements.get("a-tabs"))
|
|
151
|
+
customElements.define("a-tabs", ATabsElement);
|
|
152
|
+
}
|
|
153
|
+
register_a_tabs();
|
|
154
|
+
export {
|
|
155
|
+
ATabsElement,
|
|
156
|
+
register_a_tabs
|
|
157
|
+
};
|
package/dist/elements/a-text.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
@layer anta{a-text{--text-color: var(--text-2);--text-link-color: var(--link-color);--text-link-hover: var(--link-color-hover);display:block;color:var(--text-color);font-size:15px;line-height:20px;text-wrap:pretty;font-feature-settings:"ss02","ss05"}a-text[size=small]{font-size:13px;line-height:16px}a-text[size=medium]{font-size:15px;line-height:20px}a-text[size=large]{font-size:17px;line-height:24px}a-text[inline]{display:inline-block}a-text[truncate]{min-width:0}a-text[priority=primary]{--text-color: var(--text-1)}a-text[priority=tertiary]{--text-color: var(--text-3);--text-link-color: currentColor;--text-link-hover: var(--text-2)}a-text[priority=quaternary]{--text-color: var(--text-4);--text-link-color: currentColor;--text-link-hover: var(--text-3)}a-text[priority=quinary]{--text-color: var(--text-5);--text-link-color: currentColor;--text-link-hover: var(--text-4)}a-text[tone=brand]{--text-color: var(--text-2-brand);--text-link-color: currentColor;--text-link-hover: var(--text-1-brand)}a-text[tone=brand][priority=primary]{--text-color: var(--text-1-brand)}a-text[tone=brand][priority=tertiary]{--text-color: var(--text-3-brand);--text-link-hover: var(--text-2-brand)}a-text[tone=brand][priority=quaternary]{--text-color: var(--text-4-brand);--text-link-hover: var(--text-3-brand)}a-text[tone=brand][priority=quinary]{--text-color: var(--text-5-brand);--text-link-hover: var(--text-4-brand)}a-text[tone=success]{--text-color: var(--text-2-success);--text-link-color: currentColor;--text-link-hover: var(--text-1-success)}a-text[tone=success][priority=primary]{--text-color: var(--text-1-success)}a-text[tone=success][priority=tertiary]{--text-color: var(--text-3-success);--text-link-hover: var(--text-2-success)}a-text[tone=success][priority=quaternary]{--text-color: var(--text-4-success);--text-link-hover: var(--text-3-success)}a-text[tone=success][priority=quinary]{--text-color: var(--text-5-success);--text-link-hover: var(--text-4-success)}a-text[tone=critical]{--text-color: var(--text-2-critical);--text-link-color: currentColor;--text-link-hover: var(--text-1-critical)}a-text[tone=critical][priority=primary]{--text-color: var(--text-1-critical)}a-text[tone=critical][priority=tertiary]{--text-color: var(--text-3-critical);--text-link-hover: var(--text-2-critical)}a-text[tone=critical][priority=quaternary]{--text-color: var(--text-4-critical);--text-link-hover: var(--text-3-critical)}a-text[tone=critical][priority=quinary]{--text-color: var(--text-5-critical);--text-link-hover: var(--text-4-critical)}a-text[tone=warning]{--text-color: var(--text-2-warning);--text-link-color: currentColor;--text-link-hover: var(--text-1-warning)}a-text[tone=warning][priority=primary]{--text-color: var(--text-1-warning)}a-text[tone=warning][priority=tertiary]{--text-color: var(--text-3-warning);--text-link-hover: var(--text-2-warning)}a-text[tone=warning][priority=quaternary]{--text-color: var(--text-4-warning);--text-link-hover: var(--text-3-warning)}a-text[tone=warning][priority=quinary]{--text-color: var(--text-5-warning);--text-link-hover: var(--text-4-warning)}a-text[tone=info]{--text-color: var(--text-2-info);--text-link-color: currentColor;--text-link-hover: var(--text-1-info)}a-text[tone=info][priority=primary]{--text-color: var(--text-1-info)}a-text[tone=info][priority=tertiary]{--text-color: var(--text-3-info);--text-link-hover: var(--text-2-info)}a-text[tone=info][priority=quaternary]{--text-color: var(--text-4-info);--text-link-hover: var(--text-3-info)}a-text[tone=info][priority=quinary]{--text-color: var(--text-5-info);--text-link-hover: var(--text-4-info)}a-text a,a-text a:link,a-text a:visited{color:var(--text-link-color)}@media(hover:hover)and (pointer:fine){a-text a:hover{color:var(--text-link-hover);text-decoration-color:var(--text-link-hover)}}}
|
|
1
|
+
@layer anta{a-text{--text-color: var(--text-2);--text-link-color: var(--link-color);--text-link-hover: var(--link-color-hover);display:block;color:var(--text-color);font-size:15px;line-height:20px;text-wrap:pretty;font-feature-settings:"ss02","ss05","tnum"}a-text[size=small]{font-size:13px;line-height:16px}a-text[size=medium]{font-size:15px;line-height:20px}a-text[size=large]{font-size:17px;line-height:24px}a-text[inline]{display:inline-block}a-text[truncate]{min-width:0}a-text[priority=primary]{--text-color: var(--text-1)}a-text[priority=tertiary]{--text-color: var(--text-3);--text-link-color: currentColor;--text-link-hover: var(--text-2)}a-text[priority=quaternary]{--text-color: var(--text-4);--text-link-color: currentColor;--text-link-hover: var(--text-3)}a-text[priority=quinary]{--text-color: var(--text-5);--text-link-color: currentColor;--text-link-hover: var(--text-4)}a-text[tone=brand]{--text-color: var(--text-2-brand);--text-link-color: currentColor;--text-link-hover: var(--text-1-brand)}a-text[tone=brand][priority=primary]{--text-color: var(--text-1-brand)}a-text[tone=brand][priority=tertiary]{--text-color: var(--text-3-brand);--text-link-hover: var(--text-2-brand)}a-text[tone=brand][priority=quaternary]{--text-color: var(--text-4-brand);--text-link-hover: var(--text-3-brand)}a-text[tone=brand][priority=quinary]{--text-color: var(--text-5-brand);--text-link-hover: var(--text-4-brand)}a-text[tone=success]{--text-color: var(--text-2-success);--text-link-color: currentColor;--text-link-hover: var(--text-1-success)}a-text[tone=success][priority=primary]{--text-color: var(--text-1-success)}a-text[tone=success][priority=tertiary]{--text-color: var(--text-3-success);--text-link-hover: var(--text-2-success)}a-text[tone=success][priority=quaternary]{--text-color: var(--text-4-success);--text-link-hover: var(--text-3-success)}a-text[tone=success][priority=quinary]{--text-color: var(--text-5-success);--text-link-hover: var(--text-4-success)}a-text[tone=critical]{--text-color: var(--text-2-critical);--text-link-color: currentColor;--text-link-hover: var(--text-1-critical)}a-text[tone=critical][priority=primary]{--text-color: var(--text-1-critical)}a-text[tone=critical][priority=tertiary]{--text-color: var(--text-3-critical);--text-link-hover: var(--text-2-critical)}a-text[tone=critical][priority=quaternary]{--text-color: var(--text-4-critical);--text-link-hover: var(--text-3-critical)}a-text[tone=critical][priority=quinary]{--text-color: var(--text-5-critical);--text-link-hover: var(--text-4-critical)}a-text[tone=warning]{--text-color: var(--text-2-warning);--text-link-color: currentColor;--text-link-hover: var(--text-1-warning)}a-text[tone=warning][priority=primary]{--text-color: var(--text-1-warning)}a-text[tone=warning][priority=tertiary]{--text-color: var(--text-3-warning);--text-link-hover: var(--text-2-warning)}a-text[tone=warning][priority=quaternary]{--text-color: var(--text-4-warning);--text-link-hover: var(--text-3-warning)}a-text[tone=warning][priority=quinary]{--text-color: var(--text-5-warning);--text-link-hover: var(--text-4-warning)}a-text[tone=info]{--text-color: var(--text-2-info);--text-link-color: currentColor;--text-link-hover: var(--text-1-info)}a-text[tone=info][priority=primary]{--text-color: var(--text-1-info)}a-text[tone=info][priority=tertiary]{--text-color: var(--text-3-info);--text-link-hover: var(--text-2-info)}a-text[tone=info][priority=quaternary]{--text-color: var(--text-4-info);--text-link-hover: var(--text-3-info)}a-text[tone=info][priority=quinary]{--text-color: var(--text-5-info);--text-link-hover: var(--text-4-info)}a-text a,a-text a:link,a-text a:visited{color:var(--text-link-color)}@media(hover:hover)and (pointer:fine){a-text a:hover{color:var(--text-link-hover);text-decoration-color:var(--text-link-hover)}}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
@layer anta{a-title{display:block;color:var(--text-1);font-weight:584.62;letter-spacing:0;text-wrap:balance;font-feature-settings:"ss02","ss05"}a-title a-icon{transform:translateY(-.05em)}a-title[level="1"]{font-size:28px;line-height:32px;margin-block-start:0;margin-block-end:16px}a-title[level="2"]{font-size:24px;line-height:28px;margin-block-start:32px;margin-block-end:12px}a-title[level="3"]{font-size:20px;line-height:24px;margin-block-start:24px;margin-block-end:12px}a-title[level="4"]{font-size:17px;line-height:20px;margin-block-start:20px;margin-block-end:8px}a-title[level="5"]{font-size:15px;line-height:20px;margin-block-start:16px;margin-block-end:8px}a-title[level="6"]{font-size:13px;line-height:16px;margin-block-start:16px;margin-block-end:4px}a-title[priority=secondary]{color:var(--text-2)}a-title[priority=tertiary]{color:var(--text-3)}a-title[priority=quaternary]{color:var(--text-4)}a-title[priority=quinary]{color:var(--text-5)}a-title[tone=brand]{color:var(--text-1-brand)}a-title[tone=brand][priority=secondary]{color:var(--text-2-brand)}a-title[tone=brand][priority=tertiary]{color:var(--text-3-brand)}a-title[tone=brand][priority=quaternary]{color:var(--text-4-brand)}a-title[tone=brand][priority=quinary]{color:var(--text-5-brand)}a-title[tone=success]{color:var(--text-1-success)}a-title[tone=success][priority=secondary]{color:var(--text-2-success)}a-title[tone=success][priority=tertiary]{color:var(--text-3-success)}a-title[tone=success][priority=quaternary]{color:var(--text-4-success)}a-title[tone=success][priority=quinary]{color:var(--text-5-success)}a-title[tone=critical]{color:var(--text-1-critical)}a-title[tone=critical][priority=secondary]{color:var(--text-2-critical)}a-title[tone=critical][priority=tertiary]{color:var(--text-3-critical)}a-title[tone=critical][priority=quaternary]{color:var(--text-4-critical)}a-title[tone=critical][priority=quinary]{color:var(--text-5-critical)}a-title[tone=warning]{color:var(--text-1-warning)}a-title[tone=warning][priority=secondary]{color:var(--text-2-warning)}a-title[tone=warning][priority=tertiary]{color:var(--text-3-warning)}a-title[tone=warning][priority=quaternary]{color:var(--text-4-warning)}a-title[tone=warning][priority=quinary]{color:var(--text-5-warning)}a-title[tone=info]{color:var(--text-1-info)}a-title[tone=info][priority=secondary]{color:var(--text-2-info)}a-title[tone=info][priority=tertiary]{color:var(--text-3-info)}a-title[tone=info][priority=quaternary]{color:var(--text-4-info)}a-title[tone=info][priority=quinary]{color:var(--text-5-info)}}
|
|
1
|
+
@layer anta{a-title{display:block;color:var(--text-1);font-weight:584.62;letter-spacing:0;text-wrap:balance;font-feature-settings:"ss02","ss05","tnum"}a-title a-icon{transform:translateY(-.05em)}a-title[level="1"]{font-size:28px;line-height:32px;margin-block-start:0;margin-block-end:16px}a-title[level="2"]{font-size:24px;line-height:28px;margin-block-start:32px;margin-block-end:12px}a-title[level="3"]{font-size:20px;line-height:24px;margin-block-start:24px;margin-block-end:12px}a-title[level="4"]{font-size:17px;line-height:20px;margin-block-start:20px;margin-block-end:8px}a-title[level="5"]{font-size:15px;line-height:20px;margin-block-start:16px;margin-block-end:8px}a-title[level="6"]{font-size:13px;line-height:16px;margin-block-start:16px;margin-block-end:4px}a-title[priority=secondary]{color:var(--text-2)}a-title[priority=tertiary]{color:var(--text-3)}a-title[priority=quaternary]{color:var(--text-4)}a-title[priority=quinary]{color:var(--text-5)}a-title[tone=brand]{color:var(--text-1-brand)}a-title[tone=brand][priority=secondary]{color:var(--text-2-brand)}a-title[tone=brand][priority=tertiary]{color:var(--text-3-brand)}a-title[tone=brand][priority=quaternary]{color:var(--text-4-brand)}a-title[tone=brand][priority=quinary]{color:var(--text-5-brand)}a-title[tone=success]{color:var(--text-1-success)}a-title[tone=success][priority=secondary]{color:var(--text-2-success)}a-title[tone=success][priority=tertiary]{color:var(--text-3-success)}a-title[tone=success][priority=quaternary]{color:var(--text-4-success)}a-title[tone=success][priority=quinary]{color:var(--text-5-success)}a-title[tone=critical]{color:var(--text-1-critical)}a-title[tone=critical][priority=secondary]{color:var(--text-2-critical)}a-title[tone=critical][priority=tertiary]{color:var(--text-3-critical)}a-title[tone=critical][priority=quaternary]{color:var(--text-4-critical)}a-title[tone=critical][priority=quinary]{color:var(--text-5-critical)}a-title[tone=warning]{color:var(--text-1-warning)}a-title[tone=warning][priority=secondary]{color:var(--text-2-warning)}a-title[tone=warning][priority=tertiary]{color:var(--text-3-warning)}a-title[tone=warning][priority=quaternary]{color:var(--text-4-warning)}a-title[tone=warning][priority=quinary]{color:var(--text-5-warning)}a-title[tone=info]{color:var(--text-1-info)}a-title[tone=info][priority=secondary]{color:var(--text-2-info)}a-title[tone=info][priority=tertiary]{color:var(--text-3-info)}a-title[tone=info][priority=quaternary]{color:var(--text-4-info)}a-title[tone=info][priority=quinary]{color:var(--text-5-info)}}
|
|
@@ -68,6 +68,24 @@ export declare class ATooltipElement extends HTMLElementBase {
|
|
|
68
68
|
private get isPinned();
|
|
69
69
|
private get prefersTop();
|
|
70
70
|
private get delay();
|
|
71
|
+
/** When set, the tooltip only shows if its resolved target is actually
|
|
72
|
+
* truncated/clipped; a fitting label gets no tooltip. */
|
|
73
|
+
private get truncatedOnly();
|
|
74
|
+
/** The element whose overflow decides whether the tooltip shows: a
|
|
75
|
+
* `truncated-selector` resolved within the anchor wins; else the first of
|
|
76
|
+
* Anta's ellipsizing label parts inside the anchor; else the anchor itself
|
|
77
|
+
* (which may be the clipping box for a hand-authored target). */
|
|
78
|
+
private resolveTruncationTarget;
|
|
79
|
+
/** True when the resolved target overflows its box (horizontal ellipsis or
|
|
80
|
+
* vertical clamp). A 1px threshold absorbs sub-pixel rounding; a zero-size
|
|
81
|
+
* (hidden / detached) target counts as not truncated. Measured fresh on each
|
|
82
|
+
* show attempt, so late fonts / resizes self-correct with no observer. */
|
|
83
|
+
private isTargetTruncated;
|
|
84
|
+
/** True when there's nothing worth showing: no element children (so an
|
|
85
|
+
* icon/image-only bubble still counts as content) and no non-whitespace text
|
|
86
|
+
* (so formatting whitespace / an empty conditional doesn't open a blank bubble).
|
|
87
|
+
* Re-checked on every show(), so a tooltip populated later self-corrects. */
|
|
88
|
+
private isEmpty;
|
|
71
89
|
private positionFrame?;
|
|
72
90
|
private pendingPosition?;
|
|
73
91
|
private schedulePosition;
|
|
@@ -12,6 +12,7 @@ const PROX_NEAR = 10;
|
|
|
12
12
|
const PROX_FAR = 100;
|
|
13
13
|
const PROX_FADE_MS = 60;
|
|
14
14
|
const ENTER_TOUCH_DELAY = 500;
|
|
15
|
+
const TRUNCATING_PARTS = "a-tab-label, a-button-label";
|
|
15
16
|
const LEAVE_TOUCH_DELAY = 1500;
|
|
16
17
|
const TOUCH_SLOP = 10;
|
|
17
18
|
let currentOpen = null;
|
|
@@ -218,6 +219,46 @@ class ATooltipElement extends HTMLElementBase {
|
|
|
218
219
|
const n = parseInt(attr, 10);
|
|
219
220
|
return Number.isFinite(n) ? n : DEFAULT_DELAY;
|
|
220
221
|
}
|
|
222
|
+
// --- truncated-only gating (UI-thread layout READS — no mutation) ---
|
|
223
|
+
/** When set, the tooltip only shows if its resolved target is actually
|
|
224
|
+
* truncated/clipped; a fitting label gets no tooltip. */
|
|
225
|
+
get truncatedOnly() {
|
|
226
|
+
return this.hasAttribute("truncated-only");
|
|
227
|
+
}
|
|
228
|
+
/** The element whose overflow decides whether the tooltip shows: a
|
|
229
|
+
* `truncated-selector` resolved within the anchor wins; else the first of
|
|
230
|
+
* Anta's ellipsizing label parts inside the anchor; else the anchor itself
|
|
231
|
+
* (which may be the clipping box for a hand-authored target). */
|
|
232
|
+
resolveTruncationTarget() {
|
|
233
|
+
const anchor = this.anchor;
|
|
234
|
+
if (!anchor) return null;
|
|
235
|
+
const sel = this.getAttribute("truncated-selector");
|
|
236
|
+
if (sel) {
|
|
237
|
+
try {
|
|
238
|
+
const found = anchor.querySelector(sel);
|
|
239
|
+
if (found) return found;
|
|
240
|
+
} catch {
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
return anchor.querySelector(TRUNCATING_PARTS) ?? anchor;
|
|
244
|
+
}
|
|
245
|
+
/** True when the resolved target overflows its box (horizontal ellipsis or
|
|
246
|
+
* vertical clamp). A 1px threshold absorbs sub-pixel rounding; a zero-size
|
|
247
|
+
* (hidden / detached) target counts as not truncated. Measured fresh on each
|
|
248
|
+
* show attempt, so late fonts / resizes self-correct with no observer. */
|
|
249
|
+
isTargetTruncated() {
|
|
250
|
+
const t = this.resolveTruncationTarget();
|
|
251
|
+
if (!t) return false;
|
|
252
|
+
if (t.clientWidth === 0 && t.clientHeight === 0) return false;
|
|
253
|
+
return t.scrollWidth - t.clientWidth > 1 || t.scrollHeight - t.clientHeight > 1;
|
|
254
|
+
}
|
|
255
|
+
/** True when there's nothing worth showing: no element children (so an
|
|
256
|
+
* icon/image-only bubble still counts as content) and no non-whitespace text
|
|
257
|
+
* (so formatting whitespace / an empty conditional doesn't open a blank bubble).
|
|
258
|
+
* Re-checked on every show(), so a tooltip populated later self-corrects. */
|
|
259
|
+
isEmpty() {
|
|
260
|
+
return this.children.length === 0 && (this.textContent ?? "").trim() === "";
|
|
261
|
+
}
|
|
221
262
|
// --- positioning (sets only the shadow container's own transform) ---
|
|
222
263
|
// Single pending position frame: a burst of mousemoves within one frame
|
|
223
264
|
// coalesces to ONE layout read + transform write, using the LATEST geometry
|
|
@@ -289,6 +330,8 @@ class ATooltipElement extends HTMLElementBase {
|
|
|
289
330
|
// --- show / hide ---
|
|
290
331
|
show = (e) => {
|
|
291
332
|
if (!this.anchor) return;
|
|
333
|
+
if (this.isEmpty()) return;
|
|
334
|
+
if (this.truncatedOnly && !this.isTargetTruncated()) return;
|
|
292
335
|
this.cancelHide();
|
|
293
336
|
if (currentOpen && currentOpen !== this && this.anchor.contains(currentOpen.anchor)) {
|
|
294
337
|
return;
|
|
@@ -400,6 +443,8 @@ class ATooltipElement extends HTMLElementBase {
|
|
|
400
443
|
/** Open now if another tooltip is hot (skip delay), else (re)arm the delayed
|
|
401
444
|
* show with the latest cursor event. */
|
|
402
445
|
trigger(e) {
|
|
446
|
+
if (this.isEmpty()) return;
|
|
447
|
+
if (this.truncatedOnly && !this.isTargetTruncated()) return;
|
|
403
448
|
if (isHot()) {
|
|
404
449
|
this.debouncedShow?.cancel();
|
|
405
450
|
this.show(e);
|
package/dist/elements/index.d.ts
CHANGED
|
@@ -27,5 +27,8 @@ export { AMenuElement, register_a_menu } from './a-menu';
|
|
|
27
27
|
export { AMenuItemElement, register_a_menu_item } from './a-menu-item';
|
|
28
28
|
export { AMenuSeparatorElement, register_a_menu_separator } from './a-menu-separator';
|
|
29
29
|
export { AMenuGroupElement, register_a_menu_group } from './a-menu-group';
|
|
30
|
+
export { ATabElement, register_a_tab } from './a-tab';
|
|
31
|
+
export { ATabsElement, register_a_tabs } from './a-tabs';
|
|
30
32
|
import './a-title.css';
|
|
31
33
|
import './a-tag.css';
|
|
34
|
+
import './a-tabpanel.css';
|
package/dist/elements/index.js
CHANGED
|
@@ -12,8 +12,11 @@ import { AMenuElement, register_a_menu } from "./a-menu";
|
|
|
12
12
|
import { AMenuItemElement, register_a_menu_item } from "./a-menu-item";
|
|
13
13
|
import { AMenuSeparatorElement, register_a_menu_separator } from "./a-menu-separator";
|
|
14
14
|
import { AMenuGroupElement, register_a_menu_group } from "./a-menu-group";
|
|
15
|
+
import { ATabElement, register_a_tab } from "./a-tab";
|
|
16
|
+
import { ATabsElement, register_a_tabs } from "./a-tabs";
|
|
15
17
|
import "./a-title.css";
|
|
16
18
|
import "./a-tag.css";
|
|
19
|
+
import "./a-tabpanel.css";
|
|
17
20
|
export {
|
|
18
21
|
AButtonElement,
|
|
19
22
|
ACheckboxElement,
|
|
@@ -27,6 +30,8 @@ export {
|
|
|
27
30
|
AProgressElement,
|
|
28
31
|
ARadioElement,
|
|
29
32
|
ARadioGroupElement,
|
|
33
|
+
ATabElement,
|
|
34
|
+
ATabsElement,
|
|
30
35
|
ATextElement,
|
|
31
36
|
ATooltipElement,
|
|
32
37
|
register_a_button,
|
|
@@ -41,6 +46,8 @@ export {
|
|
|
41
46
|
register_a_progress,
|
|
42
47
|
register_a_radio,
|
|
43
48
|
register_a_radio_group,
|
|
49
|
+
register_a_tab,
|
|
50
|
+
register_a_tabs,
|
|
44
51
|
register_a_text,
|
|
45
52
|
register_a_tooltip
|
|
46
53
|
};
|
package/dist/general_types.d.ts
CHANGED
|
@@ -321,6 +321,14 @@ export interface ATooltipAttributes extends BaseAttributes {
|
|
|
321
321
|
/** Make the bubble hoverable/clickable (pointer events on, stays open while
|
|
322
322
|
* hovered). Always pinned. Presence-based (`''` on, omit off). */
|
|
323
323
|
interactive?: boolean | '';
|
|
324
|
+
/** Only show when the measured target is actually truncated/clipped (its text
|
|
325
|
+
* overflows). UI-thread layout read, re-measured per show. Defaults to the
|
|
326
|
+
* nearest Anta ellipsizing label part (`a-tab-label` / `a-button-label`) in the
|
|
327
|
+
* anchor, then the anchor itself. Presence-based (`''` on, omit off). */
|
|
328
|
+
'truncated-only'?: boolean | '';
|
|
329
|
+
/** CSS selector (resolved within the anchor) for the element whose overflow a
|
|
330
|
+
* `truncated-only` tooltip measures. */
|
|
331
|
+
'truncated-selector'?: string;
|
|
324
332
|
/** HTML `id`. */
|
|
325
333
|
id?: string;
|
|
326
334
|
}
|
|
@@ -335,16 +343,17 @@ export interface ATooltipAttributes extends BaseAttributes {
|
|
|
335
343
|
* `@antadesign/anta`.
|
|
336
344
|
*/
|
|
337
345
|
export interface ACheckboxAttributes extends BaseAttributes {
|
|
338
|
-
/**
|
|
339
|
-
* Named tones track light/dark mode automatically via
|
|
340
|
-
* tokens. `'neutral'` is the default (same as omitting it).
|
|
346
|
+
/** Mark colour (checked fill + unselected box border), or any literal CSS color
|
|
347
|
+
* for a one-off custom tone. Named tones track light/dark mode automatically via
|
|
348
|
+
* the theme-aware role tokens. `'neutral'` is the default (same as omitting it).
|
|
349
|
+
* The label + hint stay neutral — use `tone-text` for those. */
|
|
341
350
|
tone?: 'brand' | 'neutral' | 'info' | 'success' | 'warning' | 'critical' | (string & {});
|
|
351
|
+
/** Text colour (label + hint), independent of `tone`. A named tone or any literal
|
|
352
|
+
* CSS color; named tones track light/dark via the `--text-*` role tokens. Omit
|
|
353
|
+
* (or `'neutral'`) to leave the text neutral. */
|
|
354
|
+
'tone-text'?: 'brand' | 'neutral' | 'info' | 'success' | 'warning' | 'critical' | (string & {});
|
|
342
355
|
/** Size variant. `small` = 14px, `medium` (default) = 16px, `large` = 18px box. */
|
|
343
356
|
size?: 'small' | 'medium' | 'large';
|
|
344
|
-
/** Visual priority. `primary` (default) fills the checked box with the tone
|
|
345
|
-
* colour and draws a white checkmark; `secondary` keeps the box unfilled and
|
|
346
|
-
* draws the border + checkmark in the tone colour (an outlined look). */
|
|
347
|
-
priority?: 'primary' | 'secondary';
|
|
348
357
|
/** Controlled state — the element reflects changes to this attribute. Use this
|
|
349
358
|
* (driven from your store) for a controlled checkbox; use `default-state` for
|
|
350
359
|
* an uncontrolled one. */
|
|
@@ -565,16 +574,17 @@ export interface AButtonAttributes extends BaseAttributes {
|
|
|
565
574
|
export interface ARadioAttributes extends BaseAttributes {
|
|
566
575
|
/** This option's identity / submitted value. */
|
|
567
576
|
value?: string;
|
|
568
|
-
/**
|
|
569
|
-
* Named tones track light/dark mode
|
|
570
|
-
* tokens. `'neutral'` is the default
|
|
577
|
+
/** Mark colour (selected ring fill + dot, unselected ring border), or any literal
|
|
578
|
+
* CSS color for a one-off custom tone. Named tones track light/dark mode via the
|
|
579
|
+
* theme-aware role tokens. `'neutral'` is the default. The label + hint stay
|
|
580
|
+
* neutral — use `tone-text` for those. */
|
|
571
581
|
tone?: 'brand' | 'neutral' | 'info' | 'success' | 'warning' | 'critical' | (string & {});
|
|
582
|
+
/** Text colour (label + hint), independent of `tone`. A named tone or any literal
|
|
583
|
+
* CSS color; named tones track light/dark via the `--text-*` role tokens. Omit
|
|
584
|
+
* (or `'neutral'`) to leave the text neutral. */
|
|
585
|
+
'tone-text'?: 'brand' | 'neutral' | 'info' | 'success' | 'warning' | 'critical' | (string & {});
|
|
572
586
|
/** Size variant. small=14px, medium=16px, large=18px control. */
|
|
573
587
|
size?: 'small' | 'medium' | 'large';
|
|
574
|
-
/** Visual priority. `primary` (default) fills the selected ring with the tone
|
|
575
|
-
* colour and draws a white dot; `secondary` keeps the ring unfilled and draws
|
|
576
|
-
* the border + dot in the tone colour (an outlined look). */
|
|
577
|
-
priority?: 'primary' | 'secondary';
|
|
578
588
|
/** Disabled state. Presence-based (`''` on, omit off). */
|
|
579
589
|
disabled?: boolean | '';
|
|
580
590
|
/** Selected state — connect-time seed for the standalone render path (no
|
|
@@ -614,16 +624,16 @@ export interface ARadioGroupAttributes extends BaseAttributes {
|
|
|
614
624
|
'default-state'?: string;
|
|
615
625
|
/** Form field name — the group submits `name=value`. */
|
|
616
626
|
name?: string;
|
|
617
|
-
/**
|
|
627
|
+
/** Mark tone cascaded to children that don't set their own, or any literal CSS
|
|
618
628
|
* color for a one-off custom tone. Inherits through CSS so every child
|
|
619
|
-
* `<a-radio>` picks up the same fill curve.
|
|
629
|
+
* `<a-radio>` picks up the same fill curve. The option text stays neutral —
|
|
630
|
+
* use `tone-text`. */
|
|
620
631
|
tone?: 'brand' | 'neutral' | 'info' | 'success' | 'warning' | 'critical' | (string & {});
|
|
632
|
+
/** Text tone cascaded to children's label + hint, independent of `tone`. A named
|
|
633
|
+
* tone or any literal CSS color. Omit (or `'neutral'`) to leave the text neutral. */
|
|
634
|
+
'tone-text'?: 'brand' | 'neutral' | 'info' | 'success' | 'warning' | 'critical' | (string & {});
|
|
621
635
|
/** Size cascaded to children that don't set their own. */
|
|
622
636
|
size?: 'small' | 'medium' | 'large';
|
|
623
|
-
/** Visual priority cascaded to children that don't set their own. `primary`
|
|
624
|
-
* (default) fills the selected ring with the tone colour; `secondary` keeps it
|
|
625
|
-
* unfilled and draws the border + dot in the tone colour (an outlined look). */
|
|
626
|
-
priority?: 'primary' | 'secondary';
|
|
627
637
|
/** Validation/feedback tone for the group hint — same set as `<a-input>`'s
|
|
628
638
|
* `status`. Recolours `<a-radio-group-hint>`; omit for the neutral default. */
|
|
629
639
|
status?: 'neutral' | 'brand' | 'info' | 'success' | 'warning' | 'critical';
|
|
@@ -656,3 +666,119 @@ export interface ARadioGroupAttributes extends BaseAttributes {
|
|
|
656
666
|
'aria-label'?: string;
|
|
657
667
|
'aria-labelledby'?: string;
|
|
658
668
|
}
|
|
669
|
+
/**
|
|
670
|
+
* Attributes for the `<a-tab>` custom element — one tab in a tablist. Presentational,
|
|
671
|
+
* the sibling of `<a-radio>`: the parent `<a-tabs>` owns selection, keyboard, and
|
|
672
|
+
* scrolling. The selected look comes from the element's `:state(selected)` (set by the
|
|
673
|
+
* tablist via the `selected` property), not a host attribute. There is no `Tab` web
|
|
674
|
+
* component to render directly — `Tabs` renders these from its `<Tab>` children, and
|
|
675
|
+
* hand-authors write `<a-tab>` directly inside an `<a-tabs>`. Wrap the visible label in
|
|
676
|
+
* `<a-tab-label>` (as `Tabs` does) so it carries the optical baseline nudge, truncates
|
|
677
|
+
* with an ellipsis when constrained, and keeps a sibling `<a-icon>` centered — exactly
|
|
678
|
+
* like `<a-button-label>`.
|
|
679
|
+
*/
|
|
680
|
+
export interface ATabAttributes extends BaseAttributes {
|
|
681
|
+
/** This tab's identity / the value reported when it's selected. */
|
|
682
|
+
value?: string;
|
|
683
|
+
/** Per-tab tone override (same vocabulary as `<a-tabs tone>`): colours this tab's
|
|
684
|
+
* label + icons and, when selected, its indicator. Named tones tone the sliding
|
|
685
|
+
* indicator too; a custom literal colour tones the indicator only in `noslide`.
|
|
686
|
+
* Custom tones also set `--tabs-tone-source` on the tab (via the wrapper's style). */
|
|
687
|
+
tone?: 'neutral' | 'brand' | 'info' | 'success' | 'warning' | 'critical' | (string & {});
|
|
688
|
+
/** Selected state — connect-time seed for the standalone render path (no tablist).
|
|
689
|
+
* In an `<a-tabs>`, the tablist drives `:state(selected)` directly and this
|
|
690
|
+
* attribute is ignored. Presence-based (`''` on, omit off). */
|
|
691
|
+
selected?: boolean | '';
|
|
692
|
+
/** Disabled state. Presence-based (`''` on, omit off). */
|
|
693
|
+
disabled?: boolean | '';
|
|
694
|
+
/** ARIA — `role="tab"` is set by the consumer (`Tabs` on each tab, or a hand-author),
|
|
695
|
+
* and `aria-controls` points at the paired panel. `aria-selected` is published by
|
|
696
|
+
* the element through `ElementInternals` (off the DOM), driven by the `selected`
|
|
697
|
+
* property the tablist sets — not a DOM attribute. `tabindex` (inherited from
|
|
698
|
+
* `BaseAttributes`) is set by `Tabs` — every enabled tab is its own tab stop
|
|
699
|
+
* (`tabindex="0"`) — not by the element. */
|
|
700
|
+
role?: 'tab';
|
|
701
|
+
'aria-controls'?: string;
|
|
702
|
+
'aria-disabled'?: 'true' | 'false';
|
|
703
|
+
}
|
|
704
|
+
/**
|
|
705
|
+
* Attributes for the `<a-tabs>` custom element — the tablist + single-select
|
|
706
|
+
* coordinator. No shadow DOM: `<a-tab>` children are plain light-DOM, laid out by
|
|
707
|
+
* `a-tabs.css`, so the strip is restylable with ordinary CSS and usable hand-assembled.
|
|
708
|
+
* Unlike `<a-radio-group>` it is NOT form-associated (a tablist submits nothing), and
|
|
709
|
+
* the panels live outside it (siblings the `Tabs` wrapper shows/hides). The element
|
|
710
|
+
* coordinates **off-DOM only** — selection via each tab's `selected` property, focus via
|
|
711
|
+
* `internals.ariaActiveDescendantElement`, scroll via `scrollIntoView`. Roving
|
|
712
|
+
* `tabindex` (the JSX path) is rendered by the `Tabs` wrapper, not the element. For the
|
|
713
|
+
* typed JSX wrapper use `Tabs` from `@antadesign/anta`.
|
|
714
|
+
*/
|
|
715
|
+
export interface ATabsAttributes extends BaseAttributes {
|
|
716
|
+
/** Controlled selected value (the active tab's `value`). Present → controlled: the
|
|
717
|
+
* element reflects changes to this attribute and a pick only dispatches
|
|
718
|
+
* `statechange`. Absent → uncontrolled (seed with `default-state`). */
|
|
719
|
+
state?: string;
|
|
720
|
+
/** Uncontrolled initial selected value — read once on connect. */
|
|
721
|
+
'default-state'?: string;
|
|
722
|
+
/** Visual priority. `primary` (default) is the raised pill on a recessed track; `secondary`
|
|
723
|
+
* keeps that sizing but drops the track (selected = subtle active background fill, no
|
|
724
|
+
* border); `tertiary` is a bottom-underline under the selected tab only (no track, no rest
|
|
725
|
+
* line). `tone` tints secondary + tertiary; primary stays neutral. */
|
|
726
|
+
priority?: 'primary' | 'secondary' | 'tertiary';
|
|
727
|
+
/** Tone applied to the selected indicator/label, or any literal CSS color for a
|
|
728
|
+
* one-off custom tone (derived in oklch). `'neutral'` is the default. */
|
|
729
|
+
tone?: 'neutral' | 'brand' | 'info' | 'success' | 'warning' | 'critical' | (string & {});
|
|
730
|
+
/** Size variant. small=24px, medium (default)=28px, large=32px tall — matching Button's
|
|
731
|
+
* scale (the label leading runs a touch tighter, offset by 1px more block padding per side). */
|
|
732
|
+
size?: 'small' | 'medium' | 'large';
|
|
733
|
+
/** Layout + arrow-key axis. `'horizontal'` (default) ellipsizes labels when tabs
|
|
734
|
+
* overflow (scrolling is opt-in via CSS); `'vertical'` stacks them. */
|
|
735
|
+
orientation?: 'horizontal' | 'vertical';
|
|
736
|
+
/** Disable the sliding indicator. By default the selected-tab indicator is a single
|
|
737
|
+
* rectangle that animates between tabs via CSS anchor positioning; with `noslide` the
|
|
738
|
+
* highlight is painted on each tab and snaps with no movement (also the automatic
|
|
739
|
+
* fallback where anchor positioning isn't supported). Presence-based (`''` on, omit off). */
|
|
740
|
+
noslide?: boolean | '';
|
|
741
|
+
/** Disable the whole strip. Presence-based (`''` on, omit off). */
|
|
742
|
+
disabled?: boolean | '';
|
|
743
|
+
/** Fires whenever the active tab changes. `detail` carries `{ next, prev }` (values;
|
|
744
|
+
* `null` = none). Cancelable: a synchronous `preventDefault()` vetoes the pick in
|
|
745
|
+
* uncontrolled mode. All-lowercase to bind across both renderers (like
|
|
746
|
+
* `<a-radio-group>`). */
|
|
747
|
+
onstatechange?: (e: CustomEvent<{
|
|
748
|
+
next: string | null;
|
|
749
|
+
prev: string | null;
|
|
750
|
+
}>) => void;
|
|
751
|
+
/** Native `change`, fired *after* a selection applies (post-apply counterpart to
|
|
752
|
+
* `onstatechange`). Lowercase so both renderers bind the native event. */
|
|
753
|
+
onchange?: (e: Event) => void;
|
|
754
|
+
/** Strip focus enter / leave — wired from the bubbling `focusin` / `focusout` (focus
|
|
755
|
+
* lands on a tab, not the tablist). The `Tabs` wrapper maps its `onFocus`/`onBlur`. */
|
|
756
|
+
onfocusin?: (e: FocusEvent) => void;
|
|
757
|
+
onfocusout?: (e: FocusEvent) => void;
|
|
758
|
+
/** ARIA — set by the `Tabs` wrapper (the element never touches these). */
|
|
759
|
+
role?: 'tablist';
|
|
760
|
+
'aria-orientation'?: 'horizontal' | 'vertical';
|
|
761
|
+
'aria-disabled'?: 'true' | 'false';
|
|
762
|
+
'aria-label'?: string;
|
|
763
|
+
}
|
|
764
|
+
/**
|
|
765
|
+
* Attributes for the `<a-tabpanel>` styled tag.
|
|
766
|
+
*
|
|
767
|
+
* `<a-tabpanel>` has no JS — it's a CSS-only styled element. The `Tabs` wrapper renders
|
|
768
|
+
* it, pairs it to its tab via id, and toggles visibility declaratively: `hidden`
|
|
769
|
+
* (display:none) or `data-hide="visibility"` (keeps the layout box), plus `inert` while
|
|
770
|
+
* hidden. Low-level attributes; for the typed JSX wrapper use `TabPanel` (inside `Tabs`)
|
|
771
|
+
* from `@antadesign/anta`.
|
|
772
|
+
*/
|
|
773
|
+
export interface ATabpanelAttributes extends BaseAttributes {
|
|
774
|
+
/** Hidden via `display:none`. Presence-based (`''` on, omit off). */
|
|
775
|
+
hidden?: boolean | '';
|
|
776
|
+
/** Hidden via `visibility:hidden` (keeps the layout box). The `Tabs` wrapper sets
|
|
777
|
+
* this for `mounting="visibility"`. */
|
|
778
|
+
'data-hide'?: 'visibility';
|
|
779
|
+
/** Removes the hidden panel from focus + the a11y tree. Presence-based. */
|
|
780
|
+
inert?: boolean | '';
|
|
781
|
+
/** ARIA — set by the `Tabs` wrapper. */
|
|
782
|
+
role?: 'tabpanel';
|
|
783
|
+
'aria-labelledby'?: string;
|
|
784
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -47,6 +47,12 @@ export { Input } from './components/Input';
|
|
|
47
47
|
export type { InputProps, InputChangeAttrs } from './components/Input';
|
|
48
48
|
export { RadioGroup } from './components/RadioGroup';
|
|
49
49
|
export type { RadioGroupProps, RadioOption } from './components/RadioGroup';
|
|
50
|
+
export { Tabs } from './components/Tabs';
|
|
51
|
+
export type { TabsProps, TabsMounting, TabsChangeAttrs } from './components/Tabs';
|
|
52
|
+
export { Tab } from './components/Tab';
|
|
53
|
+
export type { TabProps } from './components/Tab';
|
|
54
|
+
export { TabPanel } from './components/TabPanel';
|
|
55
|
+
export type { TabPanelProps } from './components/TabPanel';
|
|
50
56
|
export type { BaseProps, BaseAttributes } from './general_types';
|
|
51
57
|
export { configure } from './jsx-runtime';
|
|
52
58
|
export type { AntaIntrinsicElements } from './jsx-runtime';
|
package/dist/index.js
CHANGED
|
@@ -14,6 +14,9 @@ import { MenuGroup } from "./components/MenuGroup";
|
|
|
14
14
|
import { Expander } from "./components/Expander";
|
|
15
15
|
import { Input } from "./components/Input";
|
|
16
16
|
import { RadioGroup } from "./components/RadioGroup";
|
|
17
|
+
import { Tabs } from "./components/Tabs";
|
|
18
|
+
import { Tab } from "./components/Tab";
|
|
19
|
+
import { TabPanel } from "./components/TabPanel";
|
|
17
20
|
import { configure } from "./jsx-runtime";
|
|
18
21
|
export {
|
|
19
22
|
Button,
|
|
@@ -29,6 +32,9 @@ export {
|
|
|
29
32
|
MenuSeparator,
|
|
30
33
|
Progress,
|
|
31
34
|
RadioGroup,
|
|
35
|
+
Tab,
|
|
36
|
+
TabPanel,
|
|
37
|
+
Tabs,
|
|
32
38
|
Tag,
|
|
33
39
|
Text,
|
|
34
40
|
Title,
|
package/dist/jsx-runtime.d.ts
CHANGED
|
@@ -37,7 +37,7 @@ export declare function useId(): string;
|
|
|
37
37
|
export declare function jsx(type: ComponentType, props: Record<string, unknown> | null, key?: string | number): unknown;
|
|
38
38
|
export declare function jsxs(type: ComponentType, props: Record<string, unknown> | null, key?: string | number): unknown;
|
|
39
39
|
export { _Fragment as Fragment };
|
|
40
|
-
import type { AProgressAttributes, ATextAttributes, ATitleAttributes, ATagAttributes, AExpanderAttributes, AIconAttributes, AButtonAttributes, ACheckboxAttributes, ATooltipAttributes, AInputAttributes, ARadioAttributes, ARadioGroupAttributes, AMenuAttributes, AMenuItemAttributes, AMenuGroupAttributes, BaseAttributes } from './general_types';
|
|
40
|
+
import type { AProgressAttributes, ATextAttributes, ATitleAttributes, ATagAttributes, AExpanderAttributes, AIconAttributes, AButtonAttributes, ACheckboxAttributes, ATooltipAttributes, AInputAttributes, ARadioAttributes, ARadioGroupAttributes, AMenuAttributes, AMenuItemAttributes, AMenuGroupAttributes, ATabsAttributes, ATabAttributes, ATabpanelAttributes, BaseAttributes } from './general_types';
|
|
41
41
|
export declare namespace JSX {
|
|
42
42
|
interface IntrinsicElements extends React.JSX.IntrinsicElements, AntaIntrinsicElements {
|
|
43
43
|
}
|
|
@@ -77,4 +77,8 @@ export interface AntaIntrinsicElements {
|
|
|
77
77
|
'a-menu-separator': BaseAttributes;
|
|
78
78
|
'a-menu-group': AMenuGroupAttributes;
|
|
79
79
|
'a-menu-group-label': BaseAttributes;
|
|
80
|
+
'a-tabs': ATabsAttributes;
|
|
81
|
+
'a-tab': ATabAttributes;
|
|
82
|
+
'a-tab-label': BaseAttributes;
|
|
83
|
+
'a-tabpanel': ATabpanelAttributes;
|
|
80
84
|
}
|
package/dist/tokens.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
@layer base,anta,components,utilities;:root,.light{--sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;--monospace: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Monaco, Consolas, "Liberation Mono", monospace;font-size:15px;font-weight:400;font-feature-settings:"ss02" on,"ss05" on;--bg-1: #ffffff;--bg-2: #fbfafb;--bg-3: #f6f4f6;--bg-4: #f1eff1;--bg-5: #ece9ec;--bg-2-brand: #fcfcfe;--bg-3-brand: #f7f6fd;--bg-4-brand: #efeefc;--bg-5-brand: #e9e5fa;--bg-2-success: #f7fcf9;--bg-3-success: #ecf9f0;--bg-4-success: #e2f5e8;--bg-5-success: #d9f2e0;--bg-2-critical: #fefbfb;--bg-3-critical: #fdf2f2;--bg-4-critical: #fcebeb;--bg-5-critical: #fae5e5;--bg-2-warning: #fefbf6;--bg-3-warning: #fcf4e8;--bg-4-warning: #fbeeda;--bg-5-warning: #f9e7cd;--bg-2-info: #fbfcfe;--bg-3-info: #f2f7fd;--bg-4-info: #e9f3fb;--bg-5-info: #e1eefa;--text-1: #050306;--text-2: #302b31;--text-3: #635b65;--text-4: #878089;--text-5: #9f99a1;--text-1-brand: #2e1e7b;--text-2-brand: #483493;--text-3-brand: #483493cc;--text-4-brand: #48349399;--text-5-brand: #48349366;--text-1-success: #004618;--text-2-success: #1f5c31;--text-3-success: #1f5c31cc;--text-4-success: #1f5c3199;--text-5-success: #1f5c3166;--text-1-critical: #8f1014;--text-2-critical: #a01c1c;--text-3-critical: #a01c1ccc;--text-4-critical: #a01c1c99;--text-5-critical: #a01c1c66;--text-1-warning: #7f410b;--text-2-warning: #995200;--text-3-warning: #995200cc;--text-4-warning: #99520099;--text-5-warning: #99520066;--text-1-info: #003969;--text-2-info: #175082;--text-3-info: #175082cc;--text-4-info: #175082b2;--text-5-info: #17508280;--border-1: #938d96;--border-2: #c1b9c1;--border-3: #d4ced4;--border-4: #e0dce0;--border-5: #ece9ec;--border-1-brand: #9081df;--border-2-brand: #bcb1f1;--border-3-brand: #d2cbf6;--border-4-brand: #ddd8f8;--border-5-brand: #e9e5fa;--border-1-success: #44c169;--border-2-success: #88d7a0;--border-3-success: #b3e5c2;--border-4-success: #c6ecd1;--border-5-success: #d9f2e0;--border-1-critical: #e56c6c;--border-2-critical: #efa4a4;--border-3-critical: #f4c2c2;--border-4-critical: #f7d4d4;--border-5-critical: #fae5e5;--border-1-warning: #d88118;--border-2-warning: #edb25a;--border-3-warning: #f3cc91;--border-4-warning: #f6dbb1;--border-5-warning: #f9e7cd;--border-1-info: #56a1e1;--border-2-info: #93c5ec;--border-3-info: #bad6f3;--border-4-info: #cfe3f7;--border-5-info: #e1eefa;--link-color: #1466d4;--link-color-hover: #2674e6;--focus-ring: oklch(.55 .2 284.15)}.dark{font-weight:400;--bg-1: #000000;--bg-2: #0e0d0f;--bg-3: #121014;--bg-4: #161316;--bg-5: #1a171b;--bg-2-brand: #08060e;--bg-3-brand: #0f0c1d;--bg-4-brand: #130f24;--bg-5-brand: #16132b;--bg-2-success: #030b06;--bg-3-success: #051209;--bg-4-success: #06160b;--bg-5-success: #081b0e;--bg-2-critical: #120303;--bg-3-critical: #210606;--bg-4-critical: #260808;--bg-5-critical: #2e0a0b;--bg-2-warning: #110a03;--bg-3-warning: #1c1105;--bg-4-warning: #231406;--bg-5-warning: #2b1a08;--bg-2-info: #020a12;--bg-3-info: #05131f;--bg-4-info: #071725;--bg-5-info: #0c2337;--text-1: #ece9ec;--text-2: #c1b9c1;--text-3: #9f99a1;--text-4: #776e77;--text-5: #635b65;--text-1-brand: #c5baff;--text-2-brand: #ada0ee;--text-3-brand: #ada0eecc;--text-4-brand: #ada0ee99;--text-5-brand: #ada0ee66;--text-1-success: #9ddeb1;--text-2-success: #74cd8e;--text-3-success: #74cd8ecc;--text-4-success: #74cd8e99;--text-5-success: #74cd8e66;--text-1-critical: #ffabac;--text-2-critical: #e78e90;--text-3-critical: #e78e90cc;--text-4-critical: #e78e9099;--text-5-critical: #e78e9066;--text-1-warning: #f0bf75;--text-2-warning: #e1a452;--text-3-warning: #e1a452cc;--text-4-warning: #e1a45299;--text-5-warning: #e1a45266;--text-1-info: #9ed2ff;--text-2-info: #7db6e8;--text-3-info: #7db6e8cc;--text-4-info: #7db6e899;--text-5-info: #7db6e866;--border-1: hsl(288deg 5.21% 42%);--border-2: hsl(282deg 7.04% 28%);--border-3: hsl(277.5deg 6.56% 20%);--border-4: hsl(290deg 6.52% 13%);--border-5: hsl(285deg 7.14% 10%);--border-1-brand: hsl(250.08deg 59.8% 58%);--border-2-brand: hsl(250deg 50% 42%);--border-3-brand: hsl(252.63deg 47.74% 30%);--border-4-brand: hsl(249.8deg 39.84% 19%);--border-5-brand: hsl(249deg 39.22% 14%);--border-1-success: hsl(138.18deg 49.75% 29%);--border-2-success: hsl(138.26deg 50.36% 20%);--border-3-success: hsl(137.7deg 49.59% 16%);--border-4-success: hsl(138.46deg 52% 10%);--border-5-success: hsl(138.86deg 53.85% 7.5%);--border-1-critical: hsl(0deg 56% 46%);--border-2-critical: hsl(.42deg 63% 30%);--border-3-critical: hsl(0deg 62.21% 23%);--border-4-critical: hsl(359.13deg 59% 15%);--border-5-critical: hsl(359.06deg 63% 11%);--border-1-warning: hsl(32.13deg 80.31% 34%);--border-2-warning: hsl(27.93deg 84.06% 24%);--border-3-warning: hsl(30deg 79.66% 17%);--border-4-warning: hsl(28.75deg 63.16% 12%);--border-5-warning: hsl(28.64deg 66.67% 9%);--border-1-info: hsl(207.82deg 70.2% 40%);--border-2-info: hsl(207.77deg 69.94% 29%);--border-3-info: hsl(208.04deg 69.93% 21%);--border-4-info: hsl(208.52deg 62.89% 14%);--border-5-info: hsl(207.78deg 65.85% 10.5%);--link-color: #7baee9;--link-color-hover: #90bdee;--focus-ring: #a897fc}
|
|
1
|
+
@layer base,anta,components,utilities;:root,.light{--sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;--monospace: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Monaco, Consolas, "Liberation Mono", monospace;font-size:15px;font-weight:400;font-feature-settings:"ss02" on,"ss05" on,"tnum" on;--bg-1: #ffffff;--bg-2: #fbfafb;--bg-3: #f6f4f6;--bg-4: #f1eff1;--bg-5: #ece9ec;--bg-2-brand: #fcfcfe;--bg-3-brand: #f7f6fd;--bg-4-brand: #efeefc;--bg-5-brand: #e9e5fa;--bg-2-success: #f7fcf9;--bg-3-success: #ecf9f0;--bg-4-success: #e2f5e8;--bg-5-success: #d9f2e0;--bg-2-critical: #fefbfb;--bg-3-critical: #fdf2f2;--bg-4-critical: #fcebeb;--bg-5-critical: #fae5e5;--bg-2-warning: #fefbf6;--bg-3-warning: #fcf4e8;--bg-4-warning: #fbeeda;--bg-5-warning: #f9e7cd;--bg-2-info: #fbfcfe;--bg-3-info: #f2f7fd;--bg-4-info: #e9f3fb;--bg-5-info: #e1eefa;--text-1: #050306;--text-2: #302b31;--text-3: #635b65;--text-4: #878089;--text-5: #9f99a1;--text-1-brand: #2e1e7b;--text-2-brand: #483493;--text-3-brand: #483493cc;--text-4-brand: #48349399;--text-5-brand: #48349366;--text-1-success: #004618;--text-2-success: #1f5c31;--text-3-success: #1f5c31cc;--text-4-success: #1f5c3199;--text-5-success: #1f5c3166;--text-1-critical: #8f1014;--text-2-critical: #a01c1c;--text-3-critical: #a01c1ccc;--text-4-critical: #a01c1c99;--text-5-critical: #a01c1c66;--text-1-warning: #7f410b;--text-2-warning: #995200;--text-3-warning: #995200cc;--text-4-warning: #99520099;--text-5-warning: #99520066;--text-1-info: #003969;--text-2-info: #175082;--text-3-info: #175082cc;--text-4-info: #175082b2;--text-5-info: #17508280;--border-1: #938d96;--border-2: #c1b9c1;--border-3: #d4ced4;--border-4: #e0dce0;--border-5: #ece9ec;--border-1-brand: #9081df;--border-2-brand: #bcb1f1;--border-3-brand: #d2cbf6;--border-4-brand: #ddd8f8;--border-5-brand: #e9e5fa;--border-1-success: #44c169;--border-2-success: #88d7a0;--border-3-success: #b3e5c2;--border-4-success: #c6ecd1;--border-5-success: #d9f2e0;--border-1-critical: #e56c6c;--border-2-critical: #efa4a4;--border-3-critical: #f4c2c2;--border-4-critical: #f7d4d4;--border-5-critical: #fae5e5;--border-1-warning: #d88118;--border-2-warning: #edb25a;--border-3-warning: #f3cc91;--border-4-warning: #f6dbb1;--border-5-warning: #f9e7cd;--border-1-info: #56a1e1;--border-2-info: #93c5ec;--border-3-info: #bad6f3;--border-4-info: #cfe3f7;--border-5-info: #e1eefa;--link-color: #1466d4;--link-color-hover: #2674e6;--focus-ring: oklch(.55 .2 284.15)}.dark{font-weight:400;--bg-1: #000000;--bg-2: #0e0d0f;--bg-3: #121014;--bg-4: #161316;--bg-5: #1a171b;--bg-2-brand: #08060e;--bg-3-brand: #0f0c1d;--bg-4-brand: #130f24;--bg-5-brand: #16132b;--bg-2-success: #030b06;--bg-3-success: #051209;--bg-4-success: #06160b;--bg-5-success: #081b0e;--bg-2-critical: #120303;--bg-3-critical: #210606;--bg-4-critical: #260808;--bg-5-critical: #2e0a0b;--bg-2-warning: #110a03;--bg-3-warning: #1c1105;--bg-4-warning: #231406;--bg-5-warning: #2b1a08;--bg-2-info: #020a12;--bg-3-info: #05131f;--bg-4-info: #071725;--bg-5-info: #0c2337;--text-1: #ece9ec;--text-2: #c1b9c1;--text-3: #9f99a1;--text-4: #776e77;--text-5: #635b65;--text-1-brand: #c5baff;--text-2-brand: #ada0ee;--text-3-brand: #ada0eecc;--text-4-brand: #ada0ee99;--text-5-brand: #ada0ee66;--text-1-success: #9ddeb1;--text-2-success: #74cd8e;--text-3-success: #74cd8ecc;--text-4-success: #74cd8e99;--text-5-success: #74cd8e66;--text-1-critical: #ffabac;--text-2-critical: #e78e90;--text-3-critical: #e78e90cc;--text-4-critical: #e78e9099;--text-5-critical: #e78e9066;--text-1-warning: #f0bf75;--text-2-warning: #e1a452;--text-3-warning: #e1a452cc;--text-4-warning: #e1a45299;--text-5-warning: #e1a45266;--text-1-info: #9ed2ff;--text-2-info: #7db6e8;--text-3-info: #7db6e8cc;--text-4-info: #7db6e899;--text-5-info: #7db6e866;--border-1: hsl(288deg 5.21% 42%);--border-2: hsl(282deg 7.04% 28%);--border-3: hsl(277.5deg 6.56% 20%);--border-4: hsl(290deg 6.52% 13%);--border-5: hsl(285deg 7.14% 10%);--border-1-brand: hsl(250.08deg 59.8% 58%);--border-2-brand: hsl(250deg 50% 42%);--border-3-brand: hsl(252.63deg 47.74% 30%);--border-4-brand: hsl(249.8deg 39.84% 19%);--border-5-brand: hsl(249deg 39.22% 14%);--border-1-success: hsl(138.18deg 49.75% 29%);--border-2-success: hsl(138.26deg 50.36% 20%);--border-3-success: hsl(137.7deg 49.59% 16%);--border-4-success: hsl(138.46deg 52% 10%);--border-5-success: hsl(138.86deg 53.85% 7.5%);--border-1-critical: hsl(0deg 56% 46%);--border-2-critical: hsl(.42deg 63% 30%);--border-3-critical: hsl(0deg 62.21% 23%);--border-4-critical: hsl(359.13deg 59% 15%);--border-5-critical: hsl(359.06deg 63% 11%);--border-1-warning: hsl(32.13deg 80.31% 34%);--border-2-warning: hsl(27.93deg 84.06% 24%);--border-3-warning: hsl(30deg 79.66% 17%);--border-4-warning: hsl(28.75deg 63.16% 12%);--border-5-warning: hsl(28.64deg 66.67% 9%);--border-1-info: hsl(207.82deg 70.2% 40%);--border-2-info: hsl(207.77deg 69.94% 29%);--border-3-info: hsl(208.04deg 69.93% 21%);--border-4-info: hsl(208.52deg 62.89% 14%);--border-5-info: hsl(207.78deg 65.85% 10.5%);--link-color: #7baee9;--link-color-hover: #90bdee;--focus-ring: #a897fc}
|