Extract out Tabs component
This commit is contained in:
parent
75e48204ef
commit
a2282f5442
43
web/components/layout/tabs.tsx
Normal file
43
web/components/layout/tabs.tsx
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
import clsx from 'clsx'
|
||||||
|
import { useState } from 'react'
|
||||||
|
|
||||||
|
type Tab = {
|
||||||
|
title: string
|
||||||
|
tabIcon?: JSX.Element
|
||||||
|
content: JSX.Element
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Tabs(props: { tabs: Tab[]; defaultIndex?: number }) {
|
||||||
|
const { tabs, defaultIndex } = props
|
||||||
|
const [activeIndex, setActiveIndex] = useState(defaultIndex ?? 0)
|
||||||
|
const activeTab = tabs[activeIndex]
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<nav className="flex space-x-4" aria-label="Tabs">
|
||||||
|
{tabs.map((tab, i) => (
|
||||||
|
<a
|
||||||
|
key={tab.title}
|
||||||
|
href="#"
|
||||||
|
className={clsx(
|
||||||
|
tab.title === activeTab.title
|
||||||
|
? 'bg-gray-200 text-gray-700'
|
||||||
|
: 'text-gray-500 hover:bg-gray-100 hover:text-gray-700',
|
||||||
|
'rounded-md px-3 py-2 text-sm font-medium'
|
||||||
|
)}
|
||||||
|
aria-current={tab.title === activeTab.title ? 'page' : undefined}
|
||||||
|
onClick={(e) => {
|
||||||
|
e.preventDefault()
|
||||||
|
setActiveIndex(i)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{tab.tabIcon ? <span className="mr-2">{tab.tabIcon}</span> : null}
|
||||||
|
{tab.title}
|
||||||
|
</a>
|
||||||
|
))}
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<div className="mt-4">{activeTab.content}</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
|
@ -9,6 +9,7 @@ import {
|
||||||
} from '../components/analytics/charts'
|
} from '../components/analytics/charts'
|
||||||
import { Col } from '../components/layout/col'
|
import { Col } from '../components/layout/col'
|
||||||
import { Spacer } from '../components/layout/spacer'
|
import { Spacer } from '../components/layout/spacer'
|
||||||
|
import { Tabs } from '../components/layout/tabs'
|
||||||
import { Page } from '../components/page'
|
import { Page } from '../components/page'
|
||||||
import { Title } from '../components/title'
|
import { Title } from '../components/title'
|
||||||
import { fromPropz, usePropz } from '../hooks/use-propz'
|
import { fromPropz, usePropz } from '../hooks/use-propz'
|
||||||
|
@ -250,45 +251,6 @@ export function CustomAnalytics(props: {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Tab = {
|
|
||||||
title: string
|
|
||||||
content: JSX.Element
|
|
||||||
}
|
|
||||||
|
|
||||||
function Tabs(props: { tabs: Tab[]; defaultIndex: number }) {
|
|
||||||
const { tabs, defaultIndex } = props
|
|
||||||
const [activeTab, setActiveTab] = useState(tabs[defaultIndex])
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<nav className="flex space-x-4" aria-label="Tabs">
|
|
||||||
{tabs.map((tab) => (
|
|
||||||
<a
|
|
||||||
key={tab.title}
|
|
||||||
href="#"
|
|
||||||
className={clsx(
|
|
||||||
tab.title === activeTab.title
|
|
||||||
? 'bg-gray-100 text-gray-700'
|
|
||||||
: 'text-gray-500 hover:text-gray-700',
|
|
||||||
'rounded-md px-3 py-2 text-sm font-medium'
|
|
||||||
)}
|
|
||||||
aria-current={tab.title === activeTab.title ? 'page' : undefined}
|
|
||||||
onClick={(e) => {
|
|
||||||
console.log('clicked')
|
|
||||||
e.preventDefault()
|
|
||||||
setActiveTab(tab)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{tab.title}
|
|
||||||
</a>
|
|
||||||
))}
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
<div className="mt-4">{activeTab.content}</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function FirebaseAnalytics() {
|
export function FirebaseAnalytics() {
|
||||||
// Edit dashboard at https://datastudio.google.com/u/0/reporting/faeaf3a4-c8da-4275-b157-98dad017d305/page/Gg3/edit
|
// Edit dashboard at https://datastudio.google.com/u/0/reporting/faeaf3a4-c8da-4275-b157-98dad017d305/page/Gg3/edit
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user