Skip to content

Commit a3dd005

Browse files
committed
Experimental Tabs
1 parent c3df8d8 commit a3dd005

File tree

6 files changed

+138
-145
lines changed

6 files changed

+138
-145
lines changed

packages/lab/src/tabs-next/TabListNext.css

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
/* Component class applied to the root element */
22
.saltTabListNext {
3+
max-width: 100%;
4+
width: 100%;
5+
min-width: 0;
6+
}
7+
8+
.saltTabListNext [role="tablist"] {
39
display: flex;
410
flex-wrap: nowrap;
511
justify-content: flex-start;

packages/lab/src/tabs-next/TabListNext.tsx

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -81,13 +81,13 @@ export const TabListNext = forwardRef<HTMLDivElement, TabListNextProps>(
8181
const handleKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {
8282
onKeyDown?.(event);
8383

84+
if (menuOpen) return;
85+
8486
const actionMap = {
8587
ArrowRight: getNext,
8688
ArrowLeft: getPrevious,
8789
Home: getFirst,
8890
End: getLast,
89-
ArrowUp: menuOpen ? getPrevious : undefined,
90-
ArrowDown: menuOpen ? getNext : undefined,
9191
};
9292

9393
const action = actionMap[event.key as keyof typeof actionMap];
@@ -111,7 +111,6 @@ export const TabListNext = forwardRef<HTMLDivElement, TabListNextProps>(
111111

112112
return (
113113
<div
114-
role="tablist"
115114
className={clsx(
116115
withBaseName(),
117116
withBaseName(appearance),
@@ -120,7 +119,6 @@ export const TabListNext = forwardRef<HTMLDivElement, TabListNextProps>(
120119
className,
121120
)}
122121
data-ismeasuring={isMeasuring ? true : undefined}
123-
ref={handleRef}
124122
onKeyDown={handleKeyDown}
125123
aria-describedby={clsx(ariaDescribedBy, warningId)}
126124
{...rest}
@@ -131,16 +129,17 @@ export const TabListNext = forwardRef<HTMLDivElement, TabListNextProps>(
131129
inaccurate or change when a tab is selected
132130
</span>
133131
)}
134-
{visible}
135-
<TabOverflowList
136-
isMeasuring={isMeasuring}
137-
buttonRef={overflowButtonRef}
138-
tabstripRef={tabstripRef}
139-
open={menuOpen}
140-
setOpen={setMenuOpen}
141-
>
142-
{hidden}
143-
</TabOverflowList>
132+
<div role="tablist" ref={handleRef}>
133+
{visible}
134+
<TabOverflowList
135+
isMeasuring={isMeasuring}
136+
buttonRef={overflowButtonRef}
137+
open={menuOpen}
138+
setOpen={setMenuOpen}
139+
>
140+
{hidden}
141+
</TabOverflowList>
142+
</div>
144143
</div>
145144
);
146145
},

packages/lab/src/tabs-next/TabNextTrigger.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { useListItem } from "@floating-ui/react";
12
import {
23
makePrefixer,
34
useForkRef,
@@ -15,6 +16,7 @@ import {
1516
} from "react";
1617
import { useTabNext } from "./TabNextContext";
1718
import tabTriggerCss from "./TabNextTrigger.css";
19+
import { useTabOverflow } from "./TabOverflowContext";
1820
import { useTabsNext } from "./TabsNextContext";
1921

2022
export interface TabNextTriggerProps
@@ -52,6 +54,8 @@ export const TabNextTrigger = forwardRef<
5254

5355
const { setSelected, registerTab, getPanelId } = useTabsNext();
5456
const { selected, value, focused, disabled, tabId, actions } = useTabNext();
57+
const overflowContext = useTabOverflow();
58+
const item = useListItem();
5559

5660
const tabRef = useRef<HTMLButtonElement>(null);
5761

@@ -77,7 +81,8 @@ export const TabNextTrigger = forwardRef<
7781
}
7882
};
7983

80-
const handleRef = useForkRef<HTMLButtonElement>(tabRef, ref);
84+
const handleTabRef = useForkRef<HTMLButtonElement>(item.ref, tabRef);
85+
const handleRef = useForkRef<HTMLButtonElement>(handleTabRef, ref);
8186
const panelId = getPanelId(value);
8287

8388
// Applying aria-actions this way avoid React warnings about unknown props
@@ -87,14 +92,17 @@ export const TabNextTrigger = forwardRef<
8792
}
8893
: {};
8994

95+
const active = overflowContext && item.index === overflowContext?.activeIndex;
96+
console.log("TabNextTrigger", { overflowContext, item });
97+
9098
return (
9199
<button
92100
aria-selected={selected}
93101
aria-disabled={disabled}
94102
aria-controls={panelId}
95103
{...ariaActionsProps}
96104
aria-description={getAriaDescription(actions.length)}
97-
tabIndex={focused || selected ? undefined : -1}
105+
tabIndex={focused || selected || active ? undefined : -1}
98106
role="tab"
99107
type="button"
100108
onClick={!disabled ? handleClick : undefined}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { createContext } from "@salt-ds/core";
2+
import { useContext } from "react";
3+
4+
export interface TabOverflowContextValue {
5+
activeIndex: number | null;
6+
getItemProps: (props: any) => Record<string, unknown>;
7+
}
8+
9+
export const TabOverflowContext = createContext<TabOverflowContextValue | null>(
10+
"TabOverflowContext",
11+
null,
12+
);
13+
14+
export function useTabOverflow() {
15+
return useContext(TabOverflowContext);
16+
}

0 commit comments

Comments
 (0)