Skip to content

Commit

Permalink
Add TabList component (#298)
Browse files Browse the repository at this point in the history
* Add TabList component
* Use TabList component in test panel
  • Loading branch information
netalondon authored May 9, 2024
1 parent acdf7ba commit 0635b9e
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 76 deletions.
66 changes: 66 additions & 0 deletions web/src/shell/tabs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import {
CSSProperties,
Children,
PropsWithChildren,
ReactNode,
cloneElement,
useId,
useState,
} from "react";

export const Tab = (
props: PropsWithChildren<{
title: ReactNode;
style?: CSSProperties;
parent?: string;
checked?: boolean;
onSelect?: () => void;
}>
) => {
const id = useId();
const tab = `tab-${id}`;
const panel = `panel-${id}`;
return (
<>
<div role="tab" id={tab} aria-controls={panel} style={props.style}>
<label>
{props.title}
<input
type="radio"
name={props.parent}
aria-controls={panel}
value={tab}
checked={props.checked}
onChange={(e) => e.target.checked == true && props.onSelect?.()}
/>
</label>
</div>
<div role="tabpanel" id={panel} aria-labelledby={tab}>
{props.children}
</div>
</>
);
};

export const TabList = (props: { children: ReturnType<typeof Tab>[] }) => {
const id = useId();
const [selectedIndex, setSelectedIndex] = useState(0);
return (
<section
role="tablist"
style={{ "--tab-count": props.children.length } as React.CSSProperties}
>
{Children.map(props.children, (child, index) =>
cloneElement(child, {
checked: index === selectedIndex,
parent: id,
idx: index,
onSelect: () => {
setSelectedIndex(index);
child.props?.onSelect?.();
},
})
)}
</section>
);
};
85 changes: 9 additions & 76 deletions web/src/shell/test_panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { CMP } from "@nand2tetris/simulator/languages/cmp.js";
import { TST } from "@nand2tetris/simulator/languages/tst.js";
import { Timer } from "@nand2tetris/simulator/timer.js";
import {
CSSProperties,
Dispatch,
ReactNode,
RefObject,
Expand All @@ -24,6 +23,7 @@ import { AppContext } from "../App.context";
import { useDialog } from "./dialog";
import { Editor } from "./editor";
import { Panel } from "./panel";
import { Tab, TabList } from "./tabs";

const WARNING_KEY = "skipTestEditWarning";

Expand Down Expand Up @@ -246,30 +246,8 @@ export const TestPanel = ({
</>
}
>
<div role="tablist" style={{ "--tab-count": "3" } as CSSProperties}>
<div
role="tab"
id="test-tab-tst"
aria-controls="test-tabpanel-tst"
aria-selected={selectedTestTab === "tst"}
>
<label>
<input
type="radio"
name="test-tabs"
aria-controls="test-tabpanel-tst"
value="tst"
checked={selectedTestTab === "tst"}
onChange={() => setSelectedTestTab("tst")}
/>
Test Script
</label>
</div>
<div
role="tabpanel"
aria-labelledby="test-tab-tst"
id="test-tabpanel-tst"
>
<TabList>
<Tab title="Test Script" onSelect={() => setSelectedTestTab("tst")}>
<Editor
value={tst}
onChange={onChange}
Expand All @@ -278,31 +256,8 @@ export const TestPanel = ({
disabled={!editMode}
highlight={showHighlight ? tstHighlight : undefined}
/>
</div>
<div
role="tab"
id="test-tab-cmp"
aria-controls="test-tablpanel-cmp"
aria-selected={selectedTestTab === "cmp"}
>
<label>
<input
type="radio"
name="test-tabs"
aria-controls="test-tabpanel-cmp"
value="cmp"
checked={selectedTestTab === "cmp"}
onChange={() => setSelectedTestTab("cmp")}
/>
Compare File
</label>
</div>
<div
role="tabpanel"
aria-labelledby="test-tab-cmp"
id="test-tabpanel-cmp"
style={{ position: "relative" }}
>
</Tab>
<Tab title="Compare File" onSelect={() => setSelectedTestTab("cmp")}>
<Editor
value={cmp}
onChange={setCmp}
Expand All @@ -311,30 +266,8 @@ export const TestPanel = ({
lineNumberTransform={(_) => ""}
disabled={!editMode}
/>
</div>
<div
role="tab"
id="test-tab-out"
aria-controls="test-tabpanel-out"
aria-selected={selectedTestTab === "out"}
>
<label>
<input
type="radio"
name="test-tabs"
aria-controls="test-tabpanel-out"
value="out"
checked={selectedTestTab === "out"}
onChange={() => setSelectedTestTab("out")}
/>
Output File
</label>
</div>
<div
role="tabpanel"
id="test-tabpanel-out"
aria-labelledby="test-tab-out"
>
</Tab>
<Tab title="Output File" onSelect={() => setSelectedTestTab("out")}>
{out == "" && <p>Execute test script to compare output.</p>}
{(diffDisplay?.failureNum ?? 0) > 0 && (
<p>
Expand All @@ -361,8 +294,8 @@ export const TestPanel = ({
})
)}
/>
</div>
</div>
</Tab>
</TabList>
</Panel>
);
};

0 comments on commit 0635b9e

Please sign in to comment.