mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
a4ead704ba
Builds on top of the existing Playwright tests to plug in the test selector API: https://gist.github.com/bvaughn/d3c8b8842faf2ac2439bb11773a19cec My goals in doing this are to... 1. Experiment with the new API to see what works and what doesn't. 2. Add some test selector attributes (and remove DOM-structure based selectors). 3. Focus the tests on DevTools itself (rather than the test app). I also took this opportunity to add a few new test cases– like named hooks, editable props, component search, and profiling- just to play around more with the Playwright API. Relates to issue #22646
141 lines
3.4 KiB
JavaScript
141 lines
3.4 KiB
JavaScript
/**
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*
|
|
* @flow
|
|
*/
|
|
|
|
import * as React from 'react';
|
|
import {Fragment, useCallback} from 'react';
|
|
import Icon from './Icon';
|
|
|
|
import styles from './TabBar.css';
|
|
import Tooltip from './Components/reach-ui/tooltip';
|
|
|
|
import type {IconType} from './Icon';
|
|
|
|
type TabInfo = {|
|
|
icon: IconType,
|
|
id: string,
|
|
label: string,
|
|
title?: string,
|
|
|};
|
|
|
|
export type Props = {|
|
|
currentTab: any,
|
|
disabled?: boolean,
|
|
id: string,
|
|
selectTab: (tabID: any) => void,
|
|
tabs: Array<TabInfo | null>,
|
|
type: 'navigation' | 'profiler' | 'settings',
|
|
|};
|
|
|
|
export default function TabBar({
|
|
currentTab,
|
|
disabled = false,
|
|
id: groupName,
|
|
selectTab,
|
|
tabs,
|
|
type,
|
|
}: Props) {
|
|
if (!tabs.some(tab => tab !== null && tab.id === currentTab)) {
|
|
const firstTab = ((tabs.find(tab => tab !== null): any): TabInfo);
|
|
selectTab(firstTab.id);
|
|
}
|
|
|
|
const onChange = useCallback(
|
|
({currentTarget}) => selectTab(currentTarget.value),
|
|
[selectTab],
|
|
);
|
|
|
|
const handleKeyDown = useCallback(event => {
|
|
switch (event.key) {
|
|
case 'ArrowDown':
|
|
case 'ArrowLeft':
|
|
case 'ArrowRight':
|
|
case 'ArrowUp':
|
|
event.stopPropagation();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}, []);
|
|
|
|
let iconSizeClassName;
|
|
let tabLabelClassName;
|
|
let tabSizeClassName;
|
|
switch (type) {
|
|
case 'navigation':
|
|
iconSizeClassName = styles.IconSizeNavigation;
|
|
tabLabelClassName = styles.TabLabelNavigation;
|
|
tabSizeClassName = styles.TabSizeNavigation;
|
|
break;
|
|
case 'profiler':
|
|
iconSizeClassName = styles.IconSizeProfiler;
|
|
tabLabelClassName = styles.TabLabelProfiler;
|
|
tabSizeClassName = styles.TabSizeProfiler;
|
|
break;
|
|
case 'settings':
|
|
iconSizeClassName = styles.IconSizeSettings;
|
|
tabLabelClassName = styles.TabLabelSettings;
|
|
tabSizeClassName = styles.TabSizeSettings;
|
|
break;
|
|
default:
|
|
throw Error(`Unsupported type "${type}"`);
|
|
}
|
|
|
|
return (
|
|
<Fragment>
|
|
{tabs.map(tab => {
|
|
if (tab === null) {
|
|
return <div key="VRule" className={styles.VRule} />;
|
|
}
|
|
|
|
const {icon, id, label, title} = tab;
|
|
|
|
let button = (
|
|
<label
|
|
className={[
|
|
tabSizeClassName,
|
|
disabled ? styles.TabDisabled : styles.Tab,
|
|
!disabled && currentTab === id ? styles.TabCurrent : '',
|
|
].join(' ')}
|
|
data-testname={`TabBarButton-${id}`}
|
|
key={id}
|
|
onKeyDown={handleKeyDown}
|
|
onMouseDown={() => selectTab(id)}>
|
|
<input
|
|
type="radio"
|
|
className={styles.Input}
|
|
checked={currentTab === id}
|
|
disabled={disabled}
|
|
name={groupName}
|
|
value={id}
|
|
onChange={onChange}
|
|
/>
|
|
<Icon
|
|
className={`${
|
|
disabled ? styles.IconDisabled : ''
|
|
} ${iconSizeClassName}`}
|
|
type={icon}
|
|
/>
|
|
<span className={tabLabelClassName}>{label}</span>
|
|
</label>
|
|
);
|
|
|
|
if (title) {
|
|
button = (
|
|
<Tooltip key={id} label={title}>
|
|
{button}
|
|
</Tooltip>
|
|
);
|
|
}
|
|
|
|
return button;
|
|
})}
|
|
</Fragment>
|
|
);
|
|
}
|