2.3 KB89 lines
Blame
1/**
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8import type {ReactNode} from 'react';
9import type {ColumnAlignmentProps} from './Flex';
10
11import * as stylex from '@stylexjs/stylex';
12import {Column, Row} from './Flex';
13import {spacing} from './theme/tokens.stylex';
14
15const styles = stylex.create({
16 tabList: {
17 padding: '4px',
18 paddingBottom: spacing.pad,
19 gap: '32px',
20 },
21 tab: {
22 color: {
23 default: 'var(--panel-tab-foreground)',
24 ':hover': 'var(--panel-tab-active-foreground)',
25 },
26 padding: '4px 0',
27 backgroundColor: 'transparent',
28 border: 'none',
29 cursor: 'pointer',
30 borderBottom: '1px solid transparent',
31 },
32 activeTab: {
33 borderBottom: '1px solid var(--panel-tab-active-foreground)',
34 color: 'var(--panel-tab-active-foreground)',
35 },
36 tabpanel: {
37 padding: '0 6px 10px 6px',
38 },
39 spaceBetween: {
40 justifyContent: 'space-between',
41 },
42});
43
44export type PanelInfo = {render: () => ReactNode; label: ReactNode};
45export function Panels<T extends string>({
46 panels,
47 xstyle,
48 tabXstyle,
49 tabListXstyle,
50 alignmentProps,
51 active,
52 onSelect,
53 tabListOptionalComponent,
54}: {
55 panels: Record<T, PanelInfo>;
56 xstyle?: stylex.StyleXStyles;
57 tabXstyle?: stylex.StyleXStyles;
58 tabListXstyle?: stylex.StyleXStyles;
59 alignmentProps?: ColumnAlignmentProps;
60 active: T;
61 onSelect: (item: T) => void;
62 tabListOptionalComponent?: ReactNode;
63}) {
64 return (
65 <Column xstyle={xstyle} {...(alignmentProps ?? {alignStart: true})}>
66 <Row xstyle={[styles.tabList, styles.spaceBetween, tabListXstyle]} role="tablist">
67 <Row>
68 {(Object.entries(panels) as Array<[T, PanelInfo]>).map(([name, value]) => {
69 return (
70 <button
71 role="tab"
72 aria-selected={active === name}
73 key={name}
74 onClick={() => onSelect(name)}
75 {...stylex.props(styles.tab, active === name && styles.activeTab, tabXstyle)}>
76 {value.label}
77 </button>
78 );
79 })}
80 </Row>
81 {tabListOptionalComponent}
82 </Row>
83 <div role="tabpanel" {...stylex.props(styles.tabpanel)}>
84 {panels[active]?.render()}
85 </div>
86 </Column>
87 );
88}
89