@blockle/blocks-react 3.1.0 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/display/Divider/divider.css.js +3 -3
- package/dist/components/display/Tag/Tag.d.ts +28 -0
- package/dist/components/display/Tag/Tag.d.ts.map +1 -0
- package/dist/components/display/Tag/Tag.js +46 -0
- package/dist/components/feedback/Alert/Alert.d.ts +15 -6
- package/dist/components/feedback/Alert/Alert.d.ts.map +1 -1
- package/dist/components/feedback/Alert/Alert.js +8 -37
- package/dist/components/feedback/Toast/ToastContext.d.ts +6 -0
- package/dist/components/feedback/Toast/ToastContext.d.ts.map +1 -1
- package/dist/components/feedback/Toast/ToastProvider.d.ts +6 -0
- package/dist/components/feedback/Toast/ToastProvider.d.ts.map +1 -1
- package/dist/components/feedback/Toast/ToastProvider.js +90 -29
- package/dist/components/feedback/Toast/useCountdowns.d.ts +14 -0
- package/dist/components/feedback/Toast/useCountdowns.d.ts.map +1 -0
- package/dist/components/feedback/Toast/useCountdowns.js +74 -0
- package/dist/components/form/Button/Button.d.ts +11 -3
- package/dist/components/form/Button/Button.d.ts.map +1 -1
- package/dist/components/form/Checkbox/Checkbox.d.ts.map +1 -1
- package/dist/components/form/Checkbox/Checkbox.js +7 -25
- package/dist/components/form/IconButton/IconButton.d.ts +29 -0
- package/dist/components/form/IconButton/IconButton.d.ts.map +1 -0
- package/dist/components/form/IconButton/IconButton.js +61 -0
- package/dist/components/form/Label/Label.d.ts +1 -1
- package/dist/components/form/Label/Label.d.ts.map +1 -1
- package/dist/components/form/NumericInput/NumericInput.d.ts +11 -1
- package/dist/components/form/NumericInput/NumericInput.d.ts.map +1 -1
- package/dist/components/form/NumericInput/NumericInput.js +52 -24
- package/dist/components/form/Select/Select.d.ts.map +1 -1
- package/dist/components/form/Select/Select.js +2 -23
- package/dist/components/form/Select/select.css.js +1 -1
- package/dist/components/form/Textarea/Textarea.css.d.ts +2 -0
- package/dist/components/form/Textarea/Textarea.css.d.ts.map +1 -1
- package/dist/components/form/Textarea/Textarea.css.js +17 -1
- package/dist/components/form/Textarea/Textarea.d.ts +11 -0
- package/dist/components/form/Textarea/Textarea.d.ts.map +1 -1
- package/dist/components/form/Textarea/Textarea.js +8 -2
- package/dist/components/layout/Inline/Inline.d.ts +11 -3
- package/dist/components/layout/Inline/Inline.d.ts.map +1 -1
- package/dist/components/layout/Inline/Inline.js +5 -3
- package/dist/components/layout/Stack/Stack.d.ts +12 -8
- package/dist/components/layout/Stack/Stack.d.ts.map +1 -1
- package/dist/components/layout/Stack/Stack.js +8 -4
- package/dist/components/navigation/Link/Link.d.ts +1 -1
- package/dist/components/navigation/Link/Link.d.ts.map +1 -1
- package/dist/components/navigation/Link/Link.js +2 -2
- package/dist/components/navigation/Tabs/Tab.d.ts +21 -0
- package/dist/components/navigation/Tabs/Tab.d.ts.map +1 -0
- package/dist/components/navigation/Tabs/Tab.js +138 -0
- package/dist/components/navigation/Tabs/TabIndicator.d.ts +6 -0
- package/dist/components/navigation/Tabs/TabIndicator.d.ts.map +1 -0
- package/dist/components/navigation/Tabs/TabIndicator.js +19 -0
- package/dist/components/navigation/Tabs/TabList.d.ts +10 -0
- package/dist/components/navigation/Tabs/TabList.d.ts.map +1 -0
- package/dist/components/navigation/Tabs/TabList.js +101 -0
- package/dist/components/navigation/Tabs/TabListContext.d.ts +13 -0
- package/dist/components/navigation/Tabs/TabListContext.d.ts.map +1 -0
- package/dist/components/navigation/Tabs/TabListContext.js +6 -0
- package/dist/components/navigation/Tabs/TabNav.d.ts +15 -0
- package/dist/components/navigation/Tabs/TabNav.d.ts.map +1 -0
- package/dist/components/navigation/Tabs/TabNav.js +44 -0
- package/dist/components/navigation/Tabs/TabPanel.d.ts +14 -0
- package/dist/components/navigation/Tabs/TabPanel.d.ts.map +1 -0
- package/dist/components/navigation/Tabs/TabPanel.js +31 -0
- package/dist/components/navigation/Tabs/Tabs.d.ts +13 -0
- package/dist/components/navigation/Tabs/Tabs.d.ts.map +1 -0
- package/dist/components/navigation/Tabs/Tabs.js +33 -0
- package/dist/components/navigation/Tabs/TabsContext.d.ts +13 -0
- package/dist/components/navigation/Tabs/TabsContext.d.ts.map +1 -0
- package/dist/components/navigation/Tabs/TabsContext.js +27 -0
- package/dist/components/navigation/Tabs/tabs.css.d.ts +7 -0
- package/dist/components/navigation/Tabs/tabs.css.d.ts.map +1 -0
- package/dist/components/navigation/Tabs/tabs.css.js +122 -0
- package/dist/components/overlay/Dialog/Dialog.d.ts +1 -1
- package/dist/components/overlay/Dialog/Dialog.d.ts.map +1 -1
- package/dist/components/overlay/Dialog/Dialog.js +9 -7
- package/dist/components/overlay/Drawer/Drawer.d.ts +1 -1
- package/dist/components/overlay/Drawer/Drawer.d.ts.map +1 -1
- package/dist/components/overlay/Drawer/Drawer.js +9 -7
- package/dist/components/overlay/Menu/Menu.d.ts +52 -0
- package/dist/components/overlay/Menu/Menu.d.ts.map +1 -0
- package/dist/components/overlay/Menu/Menu.js +273 -0
- package/dist/components/overlay/Menu/menu-utils.d.ts +33 -0
- package/dist/components/overlay/Menu/menu-utils.d.ts.map +1 -0
- package/dist/components/overlay/Menu/menu-utils.js +54 -0
- package/dist/components/overlay/Popover/Popover.d.ts +9 -0
- package/dist/components/overlay/Popover/Popover.d.ts.map +1 -1
- package/dist/components/overlay/Popover/Popover.js +70 -31
- package/dist/components/overlay/Popover/popover-utils.d.ts +32 -1
- package/dist/components/overlay/Popover/popover-utils.d.ts.map +1 -1
- package/dist/components/overlay/Popover/popover-utils.js +77 -22
- package/dist/components/overlay/modalOverlayStack.d.ts +8 -0
- package/dist/components/overlay/modalOverlayStack.d.ts.map +1 -0
- package/dist/components/overlay/modalOverlayStack.js +37 -0
- package/dist/components/overlay/useModalOverlay.d.ts +6 -14
- package/dist/components/overlay/useModalOverlay.d.ts.map +1 -1
- package/dist/components/overlay/useModalOverlay.js +8 -31
- package/dist/components/typography/Heading/Heading.d.ts +2 -1
- package/dist/components/typography/Heading/Heading.d.ts.map +1 -1
- package/dist/components/typography/Heading/Heading.js +9 -1
- package/dist/components/typography/Text/Text.d.ts +3 -2
- package/dist/components/typography/Text/Text.d.ts.map +1 -1
- package/dist/components/typography/Text/Text.js +9 -1
- package/dist/components/typography/textOverflow.css.d.ts +3 -0
- package/dist/components/typography/textOverflow.css.d.ts.map +1 -0
- package/dist/components/typography/textOverflow.css.js +32 -0
- package/dist/components/typography/textOverflow.d.ts +9 -0
- package/dist/components/typography/textOverflow.d.ts.map +1 -0
- package/dist/components/typography/textOverflow.js +10 -0
- package/dist/hooks/useModalDialog/useModalDialog.d.ts +5 -0
- package/dist/hooks/useModalDialog/useModalDialog.d.ts.map +1 -1
- package/dist/hooks/useModalDialog/useModalDialog.js +3 -2
- package/dist/hooks/usePreventBodyScroll/usePreventBodyScroll.d.ts +5 -0
- package/dist/hooks/usePreventBodyScroll/usePreventBodyScroll.d.ts.map +1 -1
- package/dist/hooks/usePreventBodyScroll/usePreventBodyScroll.js +31 -16
- package/dist/icons/icons.d.ts +8 -0
- package/dist/icons/icons.d.ts.map +1 -0
- package/dist/icons/icons.js +39 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -0
- package/dist/testUtils/browser/consumerStyles.css.d.ts +2 -0
- package/dist/testUtils/browser/consumerStyles.css.d.ts.map +1 -0
- package/dist/testUtils/browser/contrast.d.ts +6 -2
- package/dist/testUtils/browser/contrast.d.ts.map +1 -1
- package/dist/testUtils/browser/emulateNoAnchorPositioning.d.ts +8 -0
- package/dist/testUtils/browser/emulateNoAnchorPositioning.d.ts.map +1 -0
- package/dist/testUtils/browser/render.d.ts +6 -2
- package/dist/testUtils/browser/render.d.ts.map +1 -1
- package/dist/testUtils/browser/screenshot.d.ts +2 -0
- package/dist/testUtils/browser/screenshot.d.ts.map +1 -0
- package/dist/testUtils/testTheme.css.d.ts.map +1 -1
- package/package.json +2 -2
- package/dist/components/feedback/Alert/Alert.css.d.ts +0 -2
- package/dist/components/feedback/Alert/Alert.css.d.ts.map +0 -1
- package/dist/components/feedback/Alert/Alert.css.js +0 -15
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { classnames } from "@blockle/blocks-core";
|
|
4
|
+
import { createSlottable } from "@blockle/blocks-react-slot";
|
|
5
|
+
import { useContext, useRef, useEffect } from "react";
|
|
6
|
+
import { useComponentStyles } from "../../../hooks/useComponentStyles/useComponentStyles.js";
|
|
7
|
+
import { TabListContext } from "./TabListContext.js";
|
|
8
|
+
import { useTabsContext, getPanelId, getTabId } from "./TabsContext.js";
|
|
9
|
+
import { trigger, slot, tab } from "./tabs.css.js";
|
|
10
|
+
function hasContent(node) {
|
|
11
|
+
return node !== null && node !== void 0 && node !== false;
|
|
12
|
+
}
|
|
13
|
+
function revealInline(tab2, list) {
|
|
14
|
+
const tabBox = tab2.getBoundingClientRect();
|
|
15
|
+
const listBox = list.getBoundingClientRect();
|
|
16
|
+
if (tabBox.left < listBox.left) {
|
|
17
|
+
list.scrollLeft -= listBox.left - tabBox.left;
|
|
18
|
+
} else if (tabBox.right > listBox.right) {
|
|
19
|
+
list.scrollLeft += tabBox.right - listBox.right;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
const TabFrame = ({
|
|
23
|
+
active,
|
|
24
|
+
as: Wrapper,
|
|
25
|
+
children,
|
|
26
|
+
endSlot,
|
|
27
|
+
scrollRef,
|
|
28
|
+
startSlot
|
|
29
|
+
}) => {
|
|
30
|
+
const wrapperRef = useRef(null);
|
|
31
|
+
const tabClassName = useComponentStyles("tabs", { tab: true });
|
|
32
|
+
const startSlotClassName = useComponentStyles(
|
|
33
|
+
"tabs",
|
|
34
|
+
{ startSlot: true },
|
|
35
|
+
false
|
|
36
|
+
);
|
|
37
|
+
const endSlotClassName = useComponentStyles("tabs", { endSlot: true }, false);
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
if (active && wrapperRef.current && scrollRef?.current) {
|
|
40
|
+
revealInline(wrapperRef.current, scrollRef.current);
|
|
41
|
+
}
|
|
42
|
+
}, [active, scrollRef]);
|
|
43
|
+
return /* @__PURE__ */ jsxs(Wrapper, { ref: wrapperRef, className: classnames(tab, tabClassName), children: [
|
|
44
|
+
hasContent(startSlot) && /* @__PURE__ */ jsx("span", { className: classnames(slot, startSlotClassName), children: startSlot }),
|
|
45
|
+
children,
|
|
46
|
+
hasContent(endSlot) && /* @__PURE__ */ jsx("span", { className: classnames(slot, endSlotClassName), children: endSlot })
|
|
47
|
+
] });
|
|
48
|
+
};
|
|
49
|
+
const [LinkTemplate, LinkSlot] = createSlottable("a");
|
|
50
|
+
const TabsTab = ({
|
|
51
|
+
asChild: _asChild,
|
|
52
|
+
children,
|
|
53
|
+
className,
|
|
54
|
+
current: _current,
|
|
55
|
+
endSlot,
|
|
56
|
+
onClick,
|
|
57
|
+
startSlot,
|
|
58
|
+
value,
|
|
59
|
+
...restProps
|
|
60
|
+
}) => {
|
|
61
|
+
const { baseId, setValue, value: selectedValue } = useTabsContext("Tab");
|
|
62
|
+
const list = useContext(TabListContext);
|
|
63
|
+
const triggerClassName = useComponentStyles("tabs", { trigger: true });
|
|
64
|
+
if (value === void 0) {
|
|
65
|
+
throw new Error("Tab needs a value inside Tabs");
|
|
66
|
+
}
|
|
67
|
+
const selected = selectedValue === value;
|
|
68
|
+
return /* @__PURE__ */ jsx(
|
|
69
|
+
TabFrame,
|
|
70
|
+
{
|
|
71
|
+
as: "div",
|
|
72
|
+
active: selected,
|
|
73
|
+
scrollRef: list?.scrollRef,
|
|
74
|
+
startSlot,
|
|
75
|
+
endSlot,
|
|
76
|
+
children: /* @__PURE__ */ jsx(
|
|
77
|
+
"button",
|
|
78
|
+
{
|
|
79
|
+
...restProps,
|
|
80
|
+
type: "button",
|
|
81
|
+
role: "tab",
|
|
82
|
+
id: getTabId(baseId, value),
|
|
83
|
+
"aria-selected": selected,
|
|
84
|
+
"aria-controls": getPanelId(baseId, value),
|
|
85
|
+
tabIndex: selected || list?.fallbackValue === value ? 0 : -1,
|
|
86
|
+
className: classnames(trigger, triggerClassName, className),
|
|
87
|
+
onClick: (event) => {
|
|
88
|
+
onClick?.(event);
|
|
89
|
+
if (!event.defaultPrevented) {
|
|
90
|
+
setValue(value);
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
children
|
|
94
|
+
}
|
|
95
|
+
)
|
|
96
|
+
}
|
|
97
|
+
);
|
|
98
|
+
};
|
|
99
|
+
const TabNavTab = ({
|
|
100
|
+
asChild,
|
|
101
|
+
children,
|
|
102
|
+
className,
|
|
103
|
+
current,
|
|
104
|
+
endSlot,
|
|
105
|
+
startSlot,
|
|
106
|
+
value: _value,
|
|
107
|
+
...restProps
|
|
108
|
+
}) => {
|
|
109
|
+
const list = useContext(TabListContext);
|
|
110
|
+
const triggerClassName = useComponentStyles("tabs", { trigger: true });
|
|
111
|
+
return /* @__PURE__ */ jsx(
|
|
112
|
+
TabFrame,
|
|
113
|
+
{
|
|
114
|
+
as: "li",
|
|
115
|
+
active: Boolean(current),
|
|
116
|
+
scrollRef: list?.scrollRef,
|
|
117
|
+
startSlot,
|
|
118
|
+
endSlot,
|
|
119
|
+
children: /* @__PURE__ */ jsx(
|
|
120
|
+
LinkTemplate,
|
|
121
|
+
{
|
|
122
|
+
...restProps,
|
|
123
|
+
asChild,
|
|
124
|
+
"aria-current": current ? "page" : void 0,
|
|
125
|
+
className: classnames(trigger, triggerClassName, className),
|
|
126
|
+
children: /* @__PURE__ */ jsx(LinkSlot, { children })
|
|
127
|
+
}
|
|
128
|
+
)
|
|
129
|
+
}
|
|
130
|
+
);
|
|
131
|
+
};
|
|
132
|
+
const Tab = (props) => {
|
|
133
|
+
const inNav = useContext(TabListContext)?.nav ?? false;
|
|
134
|
+
return inNav ? /* @__PURE__ */ jsx(TabNavTab, { ...props }) : /* @__PURE__ */ jsx(TabsTab, { ...props });
|
|
135
|
+
};
|
|
136
|
+
export {
|
|
137
|
+
Tab
|
|
138
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Tab indicator: one decorative bar per list, positioned by the base styles
|
|
3
|
+
* against the selected tab and styled by the theme. Shared by `TabList` and `TabNav`.
|
|
4
|
+
*/
|
|
5
|
+
export declare const TabIndicator: React.FC;
|
|
6
|
+
//# sourceMappingURL=TabIndicator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TabIndicator.d.ts","sourceRoot":"","sources":["../../../../src/components/navigation/Tabs/TabIndicator.tsx"],"names":[],"mappings":"AAOA;;;GAGG;AACH,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAUhC,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { classnames } from "@blockle/blocks-core";
|
|
4
|
+
import { useComponentStyles } from "../../../hooks/useComponentStyles/useComponentStyles.js";
|
|
5
|
+
import { indicator } from "./tabs.css.js";
|
|
6
|
+
const TabIndicator = () => {
|
|
7
|
+
const className = useComponentStyles("tabs", { indicator: true });
|
|
8
|
+
return /* @__PURE__ */ jsx(
|
|
9
|
+
"span",
|
|
10
|
+
{
|
|
11
|
+
"aria-hidden": "true",
|
|
12
|
+
"data-tab-indicator": "",
|
|
13
|
+
className: classnames(indicator, className)
|
|
14
|
+
}
|
|
15
|
+
);
|
|
16
|
+
};
|
|
17
|
+
export {
|
|
18
|
+
TabIndicator
|
|
19
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { HTMLElementProps } from '@blockle/blocks-core';
|
|
2
|
+
export type TabListProps = {
|
|
3
|
+
/** Names the tab list; use it or `aria-labelledby` when a page has several */
|
|
4
|
+
'aria-label'?: string;
|
|
5
|
+
'aria-labelledby'?: string;
|
|
6
|
+
children?: React.ReactNode;
|
|
7
|
+
ref?: React.Ref<HTMLDivElement>;
|
|
8
|
+
} & Omit<HTMLElementProps<HTMLDivElement>, 'children' | 'ref'>;
|
|
9
|
+
export declare const TabList: React.FC<TabListProps>;
|
|
10
|
+
//# sourceMappingURL=TabList.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TabList.d.ts","sourceRoot":"","sources":["../../../../src/components/navigation/Tabs/TabList.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAc,KAAK,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AASzE,MAAM,MAAM,YAAY,GAAG;IACzB,8EAA8E;IAC9E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;CACjC,GAAG,IAAI,CAAC,gBAAgB,CAAC,cAAc,CAAC,EAAE,UAAU,GAAG,KAAK,CAAC,CAAC;AAE/D,eAAO,MAAM,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,YAAY,CAuG1C,CAAC"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { classnames } from "@blockle/blocks-core";
|
|
4
|
+
import { useRef, useState, useLayoutEffect, useMemo } from "react";
|
|
5
|
+
import { useComponentStyles } from "../../../hooks/useComponentStyles/useComponentStyles.js";
|
|
6
|
+
import { TabIndicator } from "./TabIndicator.js";
|
|
7
|
+
import { TabListContext } from "./TabListContext.js";
|
|
8
|
+
import { useTabsContext, getTabValue } from "./TabsContext.js";
|
|
9
|
+
import { list } from "./tabs.css.js";
|
|
10
|
+
const TabList = ({
|
|
11
|
+
children,
|
|
12
|
+
className,
|
|
13
|
+
onKeyDown,
|
|
14
|
+
ref,
|
|
15
|
+
...restProps
|
|
16
|
+
}) => {
|
|
17
|
+
const { baseId, setValue } = useTabsContext("TabList");
|
|
18
|
+
const listRef = useRef(null);
|
|
19
|
+
const listClassName = useComponentStyles("tabs", { list: true });
|
|
20
|
+
const [fallbackValue, setFallbackValue] = useState();
|
|
21
|
+
useLayoutEffect(() => {
|
|
22
|
+
const tabs = Array.from(
|
|
23
|
+
listRef.current?.querySelectorAll('[role="tab"]') ?? []
|
|
24
|
+
);
|
|
25
|
+
const hasSelected = tabs.some(
|
|
26
|
+
(tab) => tab.getAttribute("aria-selected") === "true"
|
|
27
|
+
);
|
|
28
|
+
const first = tabs[0];
|
|
29
|
+
setFallbackValue(
|
|
30
|
+
hasSelected || !first ? void 0 : getTabValue(baseId, first.id)
|
|
31
|
+
);
|
|
32
|
+
});
|
|
33
|
+
const context = useMemo(
|
|
34
|
+
() => ({ fallbackValue, nav: false, scrollRef: listRef }),
|
|
35
|
+
[fallbackValue]
|
|
36
|
+
);
|
|
37
|
+
return /* @__PURE__ */ jsx(TabListContext.Provider, { value: context, children: /* @__PURE__ */ jsxs(
|
|
38
|
+
"div",
|
|
39
|
+
{
|
|
40
|
+
...restProps,
|
|
41
|
+
role: "tablist",
|
|
42
|
+
ref: (node) => {
|
|
43
|
+
listRef.current = node;
|
|
44
|
+
if (typeof ref === "function") {
|
|
45
|
+
ref(node);
|
|
46
|
+
} else if (ref) {
|
|
47
|
+
ref.current = node;
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
className: classnames(list, listClassName, className),
|
|
51
|
+
onKeyDown: (event) => {
|
|
52
|
+
onKeyDown?.(event);
|
|
53
|
+
if (event.defaultPrevented || event.altKey || event.ctrlKey || event.metaKey || !listRef.current) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const tabs = Array.from(
|
|
57
|
+
listRef.current.querySelectorAll('[role="tab"]')
|
|
58
|
+
);
|
|
59
|
+
const index = tabs.indexOf(event.target);
|
|
60
|
+
if (index === -1) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const nextIndex = getNextIndex(event.key, index, tabs.length);
|
|
64
|
+
if (nextIndex === void 0) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
event.preventDefault();
|
|
68
|
+
const next = tabs[nextIndex];
|
|
69
|
+
if (!next) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const nextValue = getTabValue(baseId, next.id);
|
|
73
|
+
next.focus();
|
|
74
|
+
if (nextValue !== void 0) {
|
|
75
|
+
setValue(nextValue);
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
children: [
|
|
79
|
+
children,
|
|
80
|
+
/* @__PURE__ */ jsx(TabIndicator, {})
|
|
81
|
+
]
|
|
82
|
+
}
|
|
83
|
+
) });
|
|
84
|
+
};
|
|
85
|
+
function getNextIndex(key, index, count) {
|
|
86
|
+
switch (key) {
|
|
87
|
+
case "ArrowRight":
|
|
88
|
+
return (index + 1) % count;
|
|
89
|
+
case "ArrowLeft":
|
|
90
|
+
return (index - 1 + count) % count;
|
|
91
|
+
case "Home":
|
|
92
|
+
return 0;
|
|
93
|
+
case "End":
|
|
94
|
+
return count - 1;
|
|
95
|
+
default:
|
|
96
|
+
return void 0;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
export {
|
|
100
|
+
TabList
|
|
101
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type TabListContextValue = {
|
|
2
|
+
/**
|
|
3
|
+
* The value of the tab that takes the tab stop when no tab is selected, so
|
|
4
|
+
* the list stays reachable by keyboard. Undefined in a `TabNav`.
|
|
5
|
+
*/
|
|
6
|
+
fallbackValue: string | undefined;
|
|
7
|
+
/** True inside a `TabNav`, so a Tab renders a link */
|
|
8
|
+
nav: boolean;
|
|
9
|
+
/** The element that scrolls sideways when the tabs overflow */
|
|
10
|
+
scrollRef: React.RefObject<HTMLElement | null>;
|
|
11
|
+
};
|
|
12
|
+
export declare const TabListContext: import('react').Context<TabListContextValue | null>;
|
|
13
|
+
//# sourceMappingURL=TabListContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TabListContext.d.ts","sourceRoot":"","sources":["../../../../src/components/navigation/Tabs/TabListContext.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,mBAAmB,GAAG;IAChC;;;OAGG;IACH,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,sDAAsD;IACtD,GAAG,EAAE,OAAO,CAAC;IACb,+DAA+D;IAC/D,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;CAChD,CAAC;AAEF,eAAO,MAAM,cAAc,qDAAkD,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { HTMLElementProps } from '@blockle/blocks-core';
|
|
2
|
+
export type TabNavProps = {
|
|
3
|
+
/** Names the navigation; use it or `aria-labelledby` when a page has several */
|
|
4
|
+
'aria-label'?: string;
|
|
5
|
+
'aria-labelledby'?: string;
|
|
6
|
+
/** `Tab`s, each a link; mark the current page's with `current` */
|
|
7
|
+
children?: React.ReactNode;
|
|
8
|
+
ref?: React.Ref<HTMLElement>;
|
|
9
|
+
} & Omit<HTMLElementProps<HTMLElement>, 'children' | 'ref'>;
|
|
10
|
+
/**
|
|
11
|
+
* Route tabs: a `nav` around a list of links that looks like `Tabs`. It has no
|
|
12
|
+
* tab roles or arrow-key handling; the links are plain links in the tab order.
|
|
13
|
+
*/
|
|
14
|
+
export declare const TabNav: React.FC<TabNavProps>;
|
|
15
|
+
//# sourceMappingURL=TabNav.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TabNav.d.ts","sourceRoot":"","sources":["../../../../src/components/navigation/Tabs/TabNav.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAc,KAAK,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAQzE,MAAM,MAAM,WAAW,GAAG;IACxB,gFAAgF;IAChF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,kEAAkE;IAClE,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;CAC9B,GAAG,IAAI,CAAC,gBAAgB,CAAC,WAAW,CAAC,EAAE,UAAU,GAAG,KAAK,CAAC,CAAC;AAE5D;;;GAGG;AACH,eAAO,MAAM,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,CAqCxC,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { classnames } from "@blockle/blocks-core";
|
|
4
|
+
import { useRef, useMemo } from "react";
|
|
5
|
+
import { useComponentStyles } from "../../../hooks/useComponentStyles/useComponentStyles.js";
|
|
6
|
+
import { TabIndicator } from "./TabIndicator.js";
|
|
7
|
+
import { TabListContext } from "./TabListContext.js";
|
|
8
|
+
import { navList, list } from "./tabs.css.js";
|
|
9
|
+
const TabNav = ({
|
|
10
|
+
children,
|
|
11
|
+
className,
|
|
12
|
+
ref,
|
|
13
|
+
...restProps
|
|
14
|
+
}) => {
|
|
15
|
+
const navRef = useRef(null);
|
|
16
|
+
const listClassName = useComponentStyles("tabs", { list: true });
|
|
17
|
+
const navListClassName = useComponentStyles("tabs", { navList: true });
|
|
18
|
+
const context = useMemo(
|
|
19
|
+
() => ({ fallbackValue: void 0, nav: true, scrollRef: navRef }),
|
|
20
|
+
[]
|
|
21
|
+
);
|
|
22
|
+
return /* @__PURE__ */ jsx(TabListContext.Provider, { value: context, children: /* @__PURE__ */ jsxs(
|
|
23
|
+
"nav",
|
|
24
|
+
{
|
|
25
|
+
ref: (node) => {
|
|
26
|
+
navRef.current = node;
|
|
27
|
+
if (typeof ref === "function") {
|
|
28
|
+
ref(node);
|
|
29
|
+
} else if (ref) {
|
|
30
|
+
ref.current = node;
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
className: classnames(list, listClassName, className),
|
|
34
|
+
...restProps,
|
|
35
|
+
children: [
|
|
36
|
+
/* @__PURE__ */ jsx("ul", { className: classnames(navList, navListClassName), children }),
|
|
37
|
+
/* @__PURE__ */ jsx(TabIndicator, {})
|
|
38
|
+
]
|
|
39
|
+
}
|
|
40
|
+
) });
|
|
41
|
+
};
|
|
42
|
+
export {
|
|
43
|
+
TabNav
|
|
44
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { HTMLElementProps } from '@blockle/blocks-core';
|
|
2
|
+
export type TabPanelProps = {
|
|
3
|
+
children?: React.ReactNode;
|
|
4
|
+
ref?: React.Ref<HTMLDivElement>;
|
|
5
|
+
/** Matches the `value` of the Tab that shows this panel */
|
|
6
|
+
value: string;
|
|
7
|
+
} & Omit<HTMLElementProps<HTMLDivElement>, 'children' | 'ref' | 'value'>;
|
|
8
|
+
/**
|
|
9
|
+
* Stays mounted while inactive, hidden with the `hidden` attribute, so its
|
|
10
|
+
* state (such as a typed draft) survives switching tabs. Render its children
|
|
11
|
+
* conditionally to mount them only while selected.
|
|
12
|
+
*/
|
|
13
|
+
export declare const TabPanel: React.FC<TabPanelProps>;
|
|
14
|
+
//# sourceMappingURL=TabPanel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TabPanel.d.ts","sourceRoot":"","sources":["../../../../src/components/navigation/Tabs/TabPanel.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAc,KAAK,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAKzE,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC,2DAA2D;IAC3D,KAAK,EAAE,MAAM,CAAC;CACf,GAAG,IAAI,CAAC,gBAAgB,CAAC,cAAc,CAAC,EAAE,UAAU,GAAG,KAAK,GAAG,OAAO,CAAC,CAAC;AAEzE;;;;GAIG;AACH,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,aAAa,CAuB5C,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { classnames } from "@blockle/blocks-core";
|
|
4
|
+
import { useComponentStyles } from "../../../hooks/useComponentStyles/useComponentStyles.js";
|
|
5
|
+
import { useTabsContext, getTabId, getPanelId } from "./TabsContext.js";
|
|
6
|
+
const TabPanel = ({
|
|
7
|
+
children,
|
|
8
|
+
className,
|
|
9
|
+
value,
|
|
10
|
+
...restProps
|
|
11
|
+
}) => {
|
|
12
|
+
const { baseId, value: selectedValue } = useTabsContext("TabPanel");
|
|
13
|
+
const selected = selectedValue === value;
|
|
14
|
+
const panelClassName = useComponentStyles("tabs", { panel: true });
|
|
15
|
+
return /* @__PURE__ */ jsx(
|
|
16
|
+
"div",
|
|
17
|
+
{
|
|
18
|
+
role: "tabpanel",
|
|
19
|
+
id: getPanelId(baseId, value),
|
|
20
|
+
"aria-labelledby": getTabId(baseId, value),
|
|
21
|
+
hidden: !selected,
|
|
22
|
+
tabIndex: selected ? 0 : void 0,
|
|
23
|
+
className: classnames(panelClassName, className),
|
|
24
|
+
...restProps,
|
|
25
|
+
children
|
|
26
|
+
}
|
|
27
|
+
);
|
|
28
|
+
};
|
|
29
|
+
export {
|
|
30
|
+
TabPanel
|
|
31
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { HTMLElementProps } from '@blockle/blocks-core';
|
|
2
|
+
export type TabsProps = {
|
|
3
|
+
children?: React.ReactNode;
|
|
4
|
+
/** The initially selected tab when the selection is uncontrolled */
|
|
5
|
+
defaultValue?: string;
|
|
6
|
+
/** Called with the value of the tab that is selected */
|
|
7
|
+
onValueChange?: (value: string) => void;
|
|
8
|
+
ref?: React.Ref<HTMLDivElement>;
|
|
9
|
+
/** The selected tab, for a controlled selection */
|
|
10
|
+
value?: string;
|
|
11
|
+
} & Omit<HTMLElementProps<HTMLDivElement>, 'children' | 'defaultValue' | 'ref' | 'value'>;
|
|
12
|
+
export declare const Tabs: React.FC<TabsProps>;
|
|
13
|
+
//# sourceMappingURL=Tabs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Tabs.d.ts","sourceRoot":"","sources":["../../../../src/components/navigation/Tabs/Tabs.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAK7D,MAAM,MAAM,SAAS,GAAG;IACtB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,oEAAoE;IACpE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,wDAAwD;IACxD,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC,mDAAmD;IACnD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,IAAI,CACN,gBAAgB,CAAC,cAAc,CAAC,EAChC,UAAU,GAAG,cAAc,GAAG,KAAK,GAAG,OAAO,CAC9C,CAAC;AAEF,eAAO,MAAM,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,SAAS,CAiCpC,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useId, useState, useCallback, useMemo } from "react";
|
|
4
|
+
import { TabsContext } from "./TabsContext.js";
|
|
5
|
+
const Tabs = ({
|
|
6
|
+
children,
|
|
7
|
+
defaultValue,
|
|
8
|
+
onValueChange,
|
|
9
|
+
value: controlledValue,
|
|
10
|
+
...restProps
|
|
11
|
+
}) => {
|
|
12
|
+
const baseId = useId();
|
|
13
|
+
const [internalValue, setInternalValue] = useState(defaultValue);
|
|
14
|
+
const isControlled = controlledValue !== void 0;
|
|
15
|
+
const value = isControlled ? controlledValue : internalValue;
|
|
16
|
+
const setValue = useCallback(
|
|
17
|
+
(nextValue) => {
|
|
18
|
+
if (!isControlled) {
|
|
19
|
+
setInternalValue(nextValue);
|
|
20
|
+
}
|
|
21
|
+
onValueChange?.(nextValue);
|
|
22
|
+
},
|
|
23
|
+
[isControlled, onValueChange]
|
|
24
|
+
);
|
|
25
|
+
const context = useMemo(
|
|
26
|
+
() => ({ value, setValue, baseId }),
|
|
27
|
+
[value, setValue, baseId]
|
|
28
|
+
);
|
|
29
|
+
return /* @__PURE__ */ jsx(TabsContext.Provider, { value: context, children: /* @__PURE__ */ jsx("div", { ...restProps, children }) });
|
|
30
|
+
};
|
|
31
|
+
export {
|
|
32
|
+
Tabs
|
|
33
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type TabsContextValue = {
|
|
2
|
+
/** The selected tab's value, or undefined when nothing is selected */
|
|
3
|
+
value: string | undefined;
|
|
4
|
+
setValue: (value: string) => void;
|
|
5
|
+
/** Prefix for the ids generated from each Tab's and TabPanel's value */
|
|
6
|
+
baseId: string;
|
|
7
|
+
};
|
|
8
|
+
export declare const TabsContext: import('react').Context<TabsContextValue | null>;
|
|
9
|
+
export declare function useTabsContext(part: string): TabsContextValue;
|
|
10
|
+
export declare function getTabId(baseId: string, value: string): string;
|
|
11
|
+
export declare function getTabValue(baseId: string, id: string): string | undefined;
|
|
12
|
+
export declare function getPanelId(baseId: string, value: string): string;
|
|
13
|
+
//# sourceMappingURL=TabsContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TabsContext.d.ts","sourceRoot":"","sources":["../../../../src/components/navigation/Tabs/TabsContext.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,gBAAgB,GAAG;IAC7B,sEAAsE;IACtE,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,wEAAwE;IACxE,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,eAAO,MAAM,WAAW,kDAA+C,CAAC;AAExE,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,CAQ7D;AAGD,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,UAErD;AAGD,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,sBAMrD;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,UAEvD"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useContext, createContext } from "react";
|
|
3
|
+
const TabsContext = createContext(null);
|
|
4
|
+
function useTabsContext(part) {
|
|
5
|
+
const context = useContext(TabsContext);
|
|
6
|
+
if (!context) {
|
|
7
|
+
throw new Error(`${part} must be rendered inside Tabs`);
|
|
8
|
+
}
|
|
9
|
+
return context;
|
|
10
|
+
}
|
|
11
|
+
function getTabId(baseId, value) {
|
|
12
|
+
return `${baseId}-tab-${encodeURIComponent(value)}`;
|
|
13
|
+
}
|
|
14
|
+
function getTabValue(baseId, id) {
|
|
15
|
+
const prefix = `${baseId}-tab-`;
|
|
16
|
+
return id.startsWith(prefix) ? decodeURIComponent(id.slice(prefix.length)) : void 0;
|
|
17
|
+
}
|
|
18
|
+
function getPanelId(baseId, value) {
|
|
19
|
+
return `${baseId}-panel-${encodeURIComponent(value)}`;
|
|
20
|
+
}
|
|
21
|
+
export {
|
|
22
|
+
TabsContext,
|
|
23
|
+
getPanelId,
|
|
24
|
+
getTabId,
|
|
25
|
+
getTabValue,
|
|
26
|
+
useTabsContext
|
|
27
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const list: string;
|
|
2
|
+
export declare const navList: string;
|
|
3
|
+
export declare const indicator: string;
|
|
4
|
+
export declare const tab: string;
|
|
5
|
+
export declare const trigger: string;
|
|
6
|
+
export declare const slot: string;
|
|
7
|
+
//# sourceMappingURL=tabs.css.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tabs.css.d.ts","sourceRoot":"","sources":["../../../../src/components/navigation/Tabs/tabs.css.ts"],"names":[],"mappings":"AA4BA,eAAO,MAAM,IAAI,QAgBf,CAAC;AAIH,eAAO,MAAM,OAAO,QAUlB,CAAC;AAMH,eAAO,MAAM,SAAS,QAiCpB,CAAC;AAEH,eAAO,MAAM,GAAG,QA2Bd,CAAC;AAQH,eAAO,MAAM,OAAO,QAMlB,CAAC;AAIH,eAAO,MAAM,IAAI,QAAY,CAAC"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { setFileScope, endFileScope } from "@vanilla-extract/css/fileScope";
|
|
2
|
+
import { layers, tabIndicatorVars } from "@blockle/blocks-core";
|
|
3
|
+
import { style, globalStyle } from "@vanilla-extract/css";
|
|
4
|
+
setFileScope("src/components/navigation/Tabs/tabs.css.ts", "@blockle/blocks-react");
|
|
5
|
+
const selectedTrigger = '[aria-selected="true"], [aria-current="page"]';
|
|
6
|
+
const selected = '> :is([aria-selected="true"], [aria-current="page"])';
|
|
7
|
+
const anchorName = "--blockle-tab";
|
|
8
|
+
const anchorPositioning = "(anchor-name: --a) and (anchor-scope: --a)";
|
|
9
|
+
const anchorCss = (properties) => properties;
|
|
10
|
+
const list = style({
|
|
11
|
+
"@layer": {
|
|
12
|
+
[layers.molecule]: {
|
|
13
|
+
// The Tab indicator is positioned against this box
|
|
14
|
+
position: "relative",
|
|
15
|
+
display: "flex",
|
|
16
|
+
// One row that scrolls sideways, never wraps. The Tab indicator is a
|
|
17
|
+
// child, so it scrolls with the tabs.
|
|
18
|
+
overflowX: "auto",
|
|
19
|
+
"@supports": {
|
|
20
|
+
// Keeps another tab list's selected tab from anchoring this list's
|
|
21
|
+
// Tab indicator
|
|
22
|
+
[anchorPositioning]: anchorCss({ anchorScope: anchorName })
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
const navList = style({
|
|
28
|
+
"@layer": {
|
|
29
|
+
[layers.molecule]: {
|
|
30
|
+
display: "flex",
|
|
31
|
+
flexShrink: 0,
|
|
32
|
+
listStyle: "none",
|
|
33
|
+
margin: 0,
|
|
34
|
+
padding: 0
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
const indicator = style({
|
|
39
|
+
"@layer": {
|
|
40
|
+
[layers.molecule]: {
|
|
41
|
+
display: "none",
|
|
42
|
+
"@supports": {
|
|
43
|
+
[anchorPositioning]: anchorCss({
|
|
44
|
+
display: "block",
|
|
45
|
+
position: "absolute",
|
|
46
|
+
positionAnchor: anchorName,
|
|
47
|
+
left: `anchor(${anchorName} left)`,
|
|
48
|
+
width: `anchor-size(${anchorName} width)`,
|
|
49
|
+
bottom: 0,
|
|
50
|
+
height: tabIndicatorVars.thickness,
|
|
51
|
+
backgroundColor: tabIndicatorVars.color,
|
|
52
|
+
pointerEvents: "none"
|
|
53
|
+
})
|
|
54
|
+
},
|
|
55
|
+
// Moves only for users who haven't asked for less motion
|
|
56
|
+
"@media": {
|
|
57
|
+
"(prefers-reduced-motion: no-preference)": {
|
|
58
|
+
transitionProperty: "left, width",
|
|
59
|
+
transitionDuration: tabIndicatorVars.duration,
|
|
60
|
+
transitionTimingFunction: tabIndicatorVars.easing
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
selectors: {
|
|
64
|
+
// Nothing selected, nothing to point at
|
|
65
|
+
[`${list}:not(:has(${selectedTrigger})) > &`]: {
|
|
66
|
+
display: "none"
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
const tab = style({
|
|
73
|
+
"@layer": {
|
|
74
|
+
[layers.molecule]: {
|
|
75
|
+
position: "relative",
|
|
76
|
+
flexShrink: 0,
|
|
77
|
+
selectors: {
|
|
78
|
+
// Static bar under the selected tab. Without anchor positioning it is
|
|
79
|
+
// the only mark; the moving Tab indicator replaces it everywhere else.
|
|
80
|
+
[`&:has(${selected})::after`]: {
|
|
81
|
+
content: '""',
|
|
82
|
+
position: "absolute",
|
|
83
|
+
insetInline: 0,
|
|
84
|
+
insetBlockEnd: 0,
|
|
85
|
+
blockSize: tabIndicatorVars.thickness,
|
|
86
|
+
backgroundColor: tabIndicatorVars.color
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
"@supports": {
|
|
90
|
+
[anchorPositioning]: {
|
|
91
|
+
selectors: {
|
|
92
|
+
[`&:has(${selected})`]: anchorCss({ anchorName }),
|
|
93
|
+
[`&:has(${selected})::after`]: { content: "none" }
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
const insetRing = { outlineOffset: "-2px !important" };
|
|
101
|
+
const trigger = style({
|
|
102
|
+
"@layer": {
|
|
103
|
+
[layers.molecule]: {
|
|
104
|
+
":focus-visible": insetRing
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
const slot = style({});
|
|
109
|
+
globalStyle(`${slot} :is(button, a, [tabindex]):focus-visible`, {
|
|
110
|
+
"@layer": {
|
|
111
|
+
[layers.molecule]: insetRing
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
endFileScope();
|
|
115
|
+
export {
|
|
116
|
+
indicator,
|
|
117
|
+
list,
|
|
118
|
+
navList,
|
|
119
|
+
slot,
|
|
120
|
+
tab,
|
|
121
|
+
trigger
|
|
122
|
+
};
|