Use generics to better type TabbedView (#10726)
This commit is contained in:
parent
fcf2fe2c1d
commit
a629ce3a53
12 changed files with 56 additions and 52 deletions
|
@ -29,7 +29,7 @@ import { RovingAccessibleButton, RovingTabIndexProvider } from "../../accessibil
|
|||
/**
|
||||
* Represents a tab for the TabbedView.
|
||||
*/
|
||||
export class Tab {
|
||||
export class Tab<T extends string> {
|
||||
/**
|
||||
* Creates a new tab.
|
||||
* @param {string} id The tab's ID.
|
||||
|
@ -39,7 +39,7 @@ export class Tab {
|
|||
* @param {string} screenName The screen name to report to Posthog.
|
||||
*/
|
||||
public constructor(
|
||||
public readonly id: string,
|
||||
public readonly id: T,
|
||||
public readonly label: string,
|
||||
public readonly icon: string | null,
|
||||
public readonly body: React.ReactNode,
|
||||
|
@ -52,20 +52,20 @@ export enum TabLocation {
|
|||
TOP = "top",
|
||||
}
|
||||
|
||||
interface IProps {
|
||||
tabs: NonEmptyArray<Tab>;
|
||||
initialTabId?: string;
|
||||
interface IProps<T extends string> {
|
||||
tabs: NonEmptyArray<Tab<T>>;
|
||||
initialTabId?: T;
|
||||
tabLocation: TabLocation;
|
||||
onChange?: (tabId: string) => void;
|
||||
onChange?: (tabId: T) => void;
|
||||
screenName?: ScreenName;
|
||||
}
|
||||
|
||||
interface IState {
|
||||
activeTabId: string;
|
||||
interface IState<T extends string> {
|
||||
activeTabId: T;
|
||||
}
|
||||
|
||||
export default class TabbedView extends React.Component<IProps, IState> {
|
||||
public constructor(props: IProps) {
|
||||
export default class TabbedView<T extends string> extends React.Component<IProps<T>, IState<T>> {
|
||||
public constructor(props: IProps<T>) {
|
||||
super(props);
|
||||
|
||||
const initialTabIdIsValid = props.tabs.find((tab) => tab.id === props.initialTabId);
|
||||
|
@ -78,7 +78,7 @@ export default class TabbedView extends React.Component<IProps, IState> {
|
|||
tabLocation: TabLocation.LEFT,
|
||||
};
|
||||
|
||||
private getTabById(id: string): Tab | undefined {
|
||||
private getTabById(id: T): Tab<T> | undefined {
|
||||
return this.props.tabs.find((tab) => tab.id === id);
|
||||
}
|
||||
|
||||
|
@ -87,7 +87,7 @@ export default class TabbedView extends React.Component<IProps, IState> {
|
|||
* @param {Tab} tab the tab to show
|
||||
* @private
|
||||
*/
|
||||
private setActiveTab(tab: Tab): void {
|
||||
private setActiveTab(tab: Tab<T>): void {
|
||||
// make sure this tab is still in available tabs
|
||||
if (!!this.getTabById(tab.id)) {
|
||||
if (this.props.onChange) this.props.onChange(tab.id);
|
||||
|
@ -97,7 +97,7 @@ export default class TabbedView extends React.Component<IProps, IState> {
|
|||
}
|
||||
}
|
||||
|
||||
private renderTabLabel(tab: Tab): JSX.Element {
|
||||
private renderTabLabel(tab: Tab<T>): JSX.Element {
|
||||
const isActive = this.state.activeTabId === tab.id;
|
||||
const classes = classNames("mx_TabbedView_tabLabel", {
|
||||
mx_TabbedView_tabLabel_active: isActive,
|
||||
|
@ -130,11 +130,11 @@ export default class TabbedView extends React.Component<IProps, IState> {
|
|||
);
|
||||
}
|
||||
|
||||
private getTabId(tab: Tab): string {
|
||||
private getTabId(tab: Tab<T>): string {
|
||||
return `mx_tabpanel_${tab.id}`;
|
||||
}
|
||||
|
||||
private renderTabPanel(tab: Tab): React.ReactNode {
|
||||
private renderTabPanel(tab: Tab<T>): React.ReactNode {
|
||||
const id = this.getTabId(tab);
|
||||
return (
|
||||
<div className="mx_TabbedView_tabPanel" key={id} id={id} aria-labelledby={`${id}_label`}>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue