Skip to content

Commit 953f7fc

Browse files
committed
Address review comments
1 parent 50c47c9 commit 953f7fc

3 files changed

Lines changed: 75 additions & 37 deletions

File tree

packages/code-studio/src/styleguide/Navigations.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ function NavTabListExample({
4444
setTabs(t => t.filter(tab => tab.key !== key));
4545
}, []);
4646

47-
const makeContextItems = useCallback(
47+
const makeContextActions = useCallback(
4848
(tab: NavTabItem) => [
4949
{
5050
title: 'Select Tab to the Left',
@@ -81,8 +81,7 @@ function NavTabListExample({
8181
onSelect={handleSelect}
8282
onReorder={handleReorder}
8383
onClose={handleClose}
84-
isReorderAllowed
85-
makeContextItems={makeContextItems}
84+
makeContextActions={makeContextActions}
8685
/>
8786
);
8887
}

packages/components/src/navigation/NavTab.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ interface NavTabProps {
1515
activeRef: React.RefObject<HTMLDivElement>;
1616
index: number;
1717
isDraggable: boolean;
18-
contextActions?: ResolvableContextAction[];
18+
contextActions?: ResolvableContextAction | ResolvableContextAction[];
1919
}
2020

2121
const NavTab = memo(
@@ -29,7 +29,7 @@ const NavTab = memo(
2929
isDraggable,
3030
contextActions,
3131
}: NavTabProps) => {
32-
const { key, isClosable = false, title } = tab;
32+
const { key, isClosable = onClose != null, title } = tab;
3333

3434
return (
3535
<Draggable

packages/components/src/navigation/NavTabList.tsx

Lines changed: 71 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import DragUtils from '../DragUtils';
1919
import Button from '../Button';
2020
import NavTab from './NavTab';
2121
import './NavTabList.scss';
22-
import { ResolvableContextAction } from '../context-actions';
22+
import { ContextAction, ResolvableContextAction } from '../context-actions';
2323

2424
// mouse hold timeout to act as hold instead of click
2525
const CLICK_TIMEOUT = 500;
@@ -29,28 +29,70 @@ const START_SPEED = 0.01;
2929
const ACCELERATION = 0.0005;
3030

3131
export interface NavTabItem {
32+
/**
33+
* Unique key for the tab.
34+
*/
3235
key: string;
36+
37+
/**
38+
* Title to display on the tab.
39+
*/
3340
title: string;
41+
42+
/**
43+
* Whether the tab is closable.
44+
* If omitted, the tab will be closeable if onClose exists.
45+
*/
3446
isClosable?: boolean;
3547
}
3648

3749
type NavTabListProps<T extends NavTabItem = NavTabItem> = {
50+
/**
51+
* The key of the active tab.
52+
* If this does not match a tab key, no tab will be active.
53+
*/
3854
activeKey: string;
55+
56+
/**
57+
* Array of tabs to display.
58+
* @see {@link NavTabItem} for the minimum required properties.
59+
*/
3960
tabs: T[];
61+
62+
/**
63+
* Function called when a tab is selected.
64+
*
65+
* @param key The key of the tab to select
66+
*/
4067
onSelect: (key: string) => void;
68+
69+
/**
70+
* Function called when a tab is closed.
71+
* If the function is provided, all tabs will be closeable by default.
72+
* Tabs may set their own closeable property to override this behavior.
73+
*
74+
* @param key The key of the tab to close
75+
*/
4176
onClose?: (key: string) => void;
42-
onReorder: (sourceIndex: number, destinationIndex: number) => void;
43-
isReorderAllowed: boolean;
4477

4578
/**
46-
* Context items to add to the tab in addition to the default items.
47-
* The default items are Close, Close to the Right, and Close All.
48-
* The default items have a group value of 20.
79+
* Function called when a tab is reordered.
80+
* If the function is omitted, the tab list will not be reorderable.
81+
*
82+
* @param sourceIndex Index in the tab list the drag started from
83+
* @param destinationIndex Index in the tab list the drag ended at
84+
*/
85+
onReorder?: (sourceIndex: number, destinationIndex: number) => void;
86+
87+
/**
88+
* Context actions to add to the tab in addition to the default actions.
89+
* The default actions are Close, Close to the Right, and Close All.
90+
* The default actions have a group value of 20.
4991
*
5092
* @param tab The tab to make context items for
5193
* @returns Additional context items for the tab
5294
*/
53-
makeContextItems?: (tab: T) => ResolvableContextAction[];
95+
makeContextActions?: (tab: T) => ContextAction | ContextAction[];
5496
};
5597

5698
function isScrolledLeft(element: HTMLElement): boolean {
@@ -64,13 +106,13 @@ function isScrolledRight(element: HTMLElement): boolean {
64106
);
65107
}
66108

67-
function makeBaseContextItems(
109+
function makeBaseContextActions(
68110
tab: NavTabItem,
69111
tabs: NavTabItem[],
70112
onClose: ((key: string) => void) | undefined
71-
): ResolvableContextAction[] {
113+
): ContextAction[] {
72114
const { isClosable = false, key } = tab;
73-
const contextActions: ResolvableContextAction[] = [];
115+
const contextActions: ContextAction[] = [];
74116
if (isClosable && onClose != null) {
75117
contextActions.push({
76118
title: 'Close',
@@ -81,7 +123,16 @@ function makeBaseContextItems(
81123
},
82124
});
83125

84-
contextActions.push(() => ({
126+
let disabled = true;
127+
for (let i = tabs.length - 1; i > 0; i -= 1) {
128+
if (tabs[i].key === tab.key) break;
129+
if (tabs[i].isClosable === true) {
130+
disabled = false;
131+
break;
132+
}
133+
}
134+
135+
contextActions.push({
85136
title: 'Close to the Right',
86137
order: 20,
87138
group: 20,
@@ -91,19 +142,8 @@ function makeBaseContextItems(
91142
if (tabs[i].isClosable === true) onClose(tabs[i].key);
92143
}
93144
},
94-
// IIFE to run when called
95-
disabled: (() => {
96-
let disable = true;
97-
for (let i = tabs.length - 1; i > 0; i -= 1) {
98-
if (tabs[i].key === tab.key) break;
99-
if (tabs[i].isClosable === true) {
100-
disable = false;
101-
break;
102-
}
103-
}
104-
return disable;
105-
})(),
106-
}));
145+
disabled,
146+
});
107147

108148
contextActions.push({
109149
title: 'Close All',
@@ -126,8 +166,7 @@ function NavTabList({
126166
onSelect,
127167
onReorder,
128168
onClose,
129-
isReorderAllowed,
130-
makeContextItems,
169+
makeContextActions,
131170
}: NavTabListProps): React.ReactElement {
132171
const containerRef = useRef<HTMLDivElement>();
133172
const [isOverflowing, setIsOverflowing] = useState(true);
@@ -161,7 +200,7 @@ function NavTabList({
161200
return;
162201
}
163202

164-
onReorder(result.source.index, result.destination.index);
203+
onReorder?.(result.source.index, result.destination.index);
165204
},
166205
[onReorder]
167206
);
@@ -351,16 +390,16 @@ function NavTabList({
351390
tabs.forEach(tab => {
352391
const { key } = tab;
353392
const contextActions = [
354-
...makeBaseContextItems(tab, tabs, onClose),
355-
...(makeContextItems?.(tab) ?? []),
393+
() => makeBaseContextActions(tab, tabs, onClose),
394+
() => makeContextActions?.(tab) ?? [],
356395
];
357396
tabContextActions.set(key, contextActions);
358397
});
359398
return tabContextActions;
360-
}, [makeContextItems, tabs, onClose]);
399+
}, [makeContextActions, tabs, onClose]);
361400

362401
const activeTabRef = useRef<HTMLDivElement>(null);
363-
const activeTab = tabs.find(tab => tab.key === activeKey) ?? tabs[0];
402+
const activeTab = tabs.find(tab => tab.key === activeKey);
364403
const navTabs = tabs.map((tab, index) => {
365404
const { key } = tab;
366405
const isActive = tab === activeTab;
@@ -374,7 +413,7 @@ function NavTabList({
374413
activeRef={activeTabRef}
375414
onSelect={onSelect}
376415
onClose={onClose}
377-
isDraggable={isReorderAllowed}
416+
isDraggable={onReorder != null}
378417
contextActions={tabContextActionMap.get(key)}
379418
/>
380419
);

0 commit comments

Comments
 (0)