Update tabs for mobile

This commit is contained in:
Robert Long
2022-01-21 15:43:03 -08:00
parent d6fb0e836d
commit 48f3f430da
5 changed files with 86 additions and 7 deletions

53
src/tabs/Tabs.jsx Normal file
View File

@@ -0,0 +1,53 @@
import React, { useRef } from "react";
import { useTabList, useTab, useTabPanel } from "@react-aria/tabs";
import { Item } from "@react-stately/collections";
import { useTabListState } from "@react-stately/tabs";
import styles from "./Tabs.module.css";
import classNames from "classnames";
export function TabContainer(props) {
const state = useTabListState(props);
const ref = useRef();
const { tabListProps } = useTabList(props, state, ref);
return (
<div className={classNames(styles.tabContainer, props.className)}>
<ul {...tabListProps} ref={ref} className={styles.tabList}>
{[...state.collection].map((item) => (
<Tab key={item.key} item={item} state={state} />
))}
</ul>
<TabPanel key={state.selectedItem?.key} state={state} />
</div>
);
}
function Tab({ item, state }) {
const { key, rendered } = item;
const ref = useRef();
const { tabProps } = useTab({ key }, state, ref);
return (
<li
{...tabProps}
ref={ref}
className={classNames(styles.tab, {
[styles.selected]: state.selectedKey === key,
[styles.disabled]: state.disabledKeys.has(key),
})}
>
{rendered}
</li>
);
}
function TabPanel({ state, ...props }) {
const ref = useRef();
const { tabPanelProps } = useTabPanel(props, state, ref);
return (
<div {...tabPanelProps} ref={ref} className={styles.tabPanel}>
{state.selectedItem?.props.children}
</div>
);
}
export const TabItem = Item;

86
src/tabs/Tabs.module.css Normal file
View File

@@ -0,0 +1,86 @@
.tabContainer {
display: flex;
flex: 1;
flex-direction: column;
}
.tabList {
display: flex;
list-style: none;
padding: 0;
margin: 0 auto 24px auto;
}
.tab {
max-width: 190px;
min-width: fit-content;
height: 32px;
border-radius: 8px;
background-color: transparent;
display: flex;
align-items: center;
padding: 0 8px;
border: none;
cursor: pointer;
}
.tab > * {
color: var(--textColor4);
margin: 0 8px 0 0;
}
.tab svg * {
fill: var(--textColor4);
}
.tab > :last-child {
margin-right: 0;
}
.tab.selected {
background-color: #0dbd8b;
}
.tab.selected * {
color: #ffffff;
}
.tab.selected svg * {
fill: #ffffff;
}
.tab.disabled {
}
.tabPanel {
display: flex;
flex-direction: column;
flex: 1;
padding: 0;
overflow-y: auto;
}
@media (min-width: 800px) {
.tab {
padding: 0 16px;
}
.tab > * {
margin: 0 16px 0 0;
}
.tabContainer {
width: 100%;
flex-direction: row;
margin: 0 0 44px 0;
}
.tabList {
flex-direction: column;
margin-bottom: 0;
}
.tabPanel {
padding: 0 40px;
}
}

49
src/tabs/Tabs.stories.jsx Normal file
View File

@@ -0,0 +1,49 @@
import React from "react";
import { TabContainer, TabItem } from "./Tabs";
import { ReactComponent as AudioIcon } from "../icons/Audio.svg";
import { ReactComponent as VideoIcon } from "../icons/Video.svg";
import { ReactComponent as DeveloperIcon } from "../icons/Developer.svg";
import { Body } from "../typography/Typography";
export default {
title: "Tabs",
component: TabContainer,
parameters: {
layout: "fullscreen",
},
};
export const Tabs = () => (
<TabContainer>
<TabItem
title={
<>
<AudioIcon width={16} height={16} />
<Body>Audio</Body>
</>
}
>
Audio Tab Content
</TabItem>
<TabItem
title={
<>
<VideoIcon width={16} height={16} />
<Body>Video</Body>
</>
}
>
Video Tab Content
</TabItem>
<TabItem
title={
<>
<DeveloperIcon width={16} height={16} />
<Body>Developer</Body>
</>
}
>
Developer Tab Content
</TabItem>
</TabContainer>
);