got working toggle tabs! I don't like HeadlessUI's Tabs, they don't appear to support programmatic opening

This commit is contained in:
Frank Johnson
2021-09-11 04:34:13 -04:00
parent 206ec7fdab
commit 9812db5cd6
4 changed files with 110 additions and 50 deletions

View File

@@ -65,8 +65,13 @@ const IdeHeader = ({
return (
<div className="h-16 w-full bg-ch-gray-900 flex justify-between items-center text-lg">
{_projectId ? (
<div className="h-full text-gray-300 flex items-center">
<div className="h-full text-gray-300 flex items-center">
<div className="w-14 h-16 flex items-center justify-center bg-ch-gray-900">
<Link to={routes.home()}>
<Svg className="w-12 p-0.5" name="favicon" />
</Link>
</div>
{_projectId && <>
<span className="bg-ch-gray-700 h-full grid grid-flow-col-dense items-center gap-2 px-4">
<Gravatar
image={project?.user?.image || projectOwnerImage}
@@ -87,10 +92,8 @@ const IdeHeader = ({
canEdit={canEdit}
shouldRouteToIde={!projectTitle}
/>
</div>
) : (
<div />
)}
</>}
</div>
<div className="text-gray-200 grid grid-flow-col-dense gap-4 mr-4 items-center">
{canEdit && !projectTitle && (
<CaptureButton

View File

@@ -1,7 +1,7 @@
import { ReactNode, useState } from 'react'
import { Link, routes } from '@redwoodjs/router'
import { Tab } from '@headlessui/react'
import Svg, { SvgNames } from 'src/components/Svg/Svg'
import { ReactNode } from 'react'
interface SidebarConfigType {
name: string,
@@ -15,13 +15,13 @@ const sidebarTopConfig : SidebarConfigType[] = [
name: 'Files',
icon: 'files',
disabled: false,
panel: () => { <h2>Some Files!</h2> },
panel: <h2>Some Files!</h2>,
},
{
name: 'GitHub',
icon: 'github',
disabled: false,
panel: () => { <h2>Le GitHub Integration</h2> },
panel: <h2>Le GitHub Integration</h2>,
},
{
name: 'Visibility',
@@ -40,42 +40,74 @@ const sidebarBottomConfig : SidebarConfigType[] = [
},
]
const IdeSideBar = () => {
const combinedConfig = [
...sidebarTopConfig,
...sidebarBottomConfig,
]
function TabToggle({ item, className = "", active, onChange, onClick }) {
return (
<div className="h-full flex flex-col justify-between">
<div className="w-14 h-16 flex items-center justify-center bg-ch-gray-900">
<Link to={routes.home()}>
<Svg className="w-12 p-0.5" name="favicon" />
</Link>
</div>
<Tab.Group vertical>
<Tab.List className="h-full flex flex-col justify-between">
<div>
{ sidebarTopConfig.map(topItem => (
<Tab disabled={topItem.disabled}
key={'tab-'+topItem.name}
className="text-gray-300 p-3 pb-6 flex justify-center">
<Svg name={topItem.icon} className="w-8 mx-auto"/>
</Tab>
<label
key={'tab-'+item.name}
className={`tabToggle${item.disabled ? ' disabled' : ''}${active ? ' active' : ''} ${className}`}>
<input name="sidebar-tabs"
type="radio"
disabled={item.disabled}
value={ item.name }
onChange={ onChange }
onClick={ onClick }
className="visually-hidden"
/>
<Svg name={item.icon} className="w-8 mx-auto"/>
</label>
)
}
const IdeSideBar = () => {
const [selectedTab, setSelectedTab] = useState("")
const [lastOpen, setLastOpen] = useState("")
function onTabClick(name) {
return function() {
if (selectedTab === name) {
setLastOpen(selectedTab)
setSelectedTab("")
} else if (selectedTab === "" && lastOpen === name) {
setSelectedTab(name)
}
}
}
return (
<section className="flex h-full bg-ch-gray-700">
<fieldset className="h-full flex flex-col justify-between border-r-2 border-ch-gray-900">
<div>
{ sidebarTopConfig.map((topItem, i) => (
<TabToggle
item={topItem}
active={ selectedTab === topItem.name }
onChange={ () => setSelectedTab(topItem.name) }
onClick={ onTabClick(topItem.name) }
/>
))}
</div>
<div>
{ sidebarBottomConfig.map(bottomItem => (
<Tab disabled={bottomItem.disabled}
key={'tab-'+bottomItem.name}
className="text-gray-300 p-3 pb-6 flex justify-center">
<Svg name={bottomItem.icon} className="w-8 mx-auto" />
</Tab>
</div>
<div>
{ sidebarBottomConfig.map((bottomItem, i) => (
<TabToggle
item={bottomItem}
active={ selectedTab === bottomItem.name }
onChange={ () => setSelectedTab(bottomItem.name) }
onClick={ onTabClick(bottomItem.name) }
/>
))}
</div>
</Tab.List>
<Tab.Panels>
{ ([...sidebarTopConfig, ...sidebarBottomConfig]).map(item => item.panel && (
<Tab.Panel key={'panel-'+item.name}>{ item.panel }</Tab.Panel>
)) }
</Tab.Panels>
</Tab.Group>
</div>
</div>
</fieldset>
{ combinedConfig.find(item => item.name === selectedTab)?.panel && (
<div className="w-56 h-full bg-ch-gray-700 py-4 px-2 text-ch-gray-300 border-t-2 border-ch-gray-900">
{ combinedConfig.find(item => item.name === selectedTab).panel }
</div>
) }
</section>
)
}

View File

@@ -24,15 +24,17 @@ const IdeWrapper = ({ cadPackage }: Props) => {
useIdeInit(cadPackage, project?.code || state?.code)
return (
<div className="h-full flex">
<div className="w-14 bg-ch-gray-700 flex-shrink-0">
<IdeSideBar />
</div>
<div className="h-full flex flex-grow flex-col">
<nav className="flex">
<div className="h-full flex flex-col">
<nav className="flex">
<IdeHeader handleRender={onRender} />
</nav>
<IdeContainer />
</nav>
<div className="h-full flex flex-grow bg-ch-gray-900">
<div className="flex-shrink-0">
<IdeSideBar />
</div>
<div className="h-full flex flex-grow">
<IdeContainer />
</div>
</div>
</div>
)

View File

@@ -17,6 +17,29 @@
body {
font-family: 'Fira Sans', ui-sans-serif, system-ui, -apple-system, system-ui, "Segoe UI", "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
}
/* https://www.a11yproject.com/posts/2013-01-11-how-to-hide-content/ */
.visually-hidden {
clip: rect(0 0 0 0);
clip-path: inset(50%);
height: 1px;
overflow: hidden;
position: absolute;
white-space: nowrap;
width: 1px;
}
}
@layer components {
.tabToggle {
@apply text-ch-gray-300 p-3 mb-3 flex justify-center;
}
.tabToggle.active {
@apply bg-ch-pink-800 text-ch-pink-300 bg-opacity-30;
}
.tabToggle.disabled {
@apply text-ch-gray-550 cursor-not-allowed;
}
}