From b1b49729c8cea91b30a9c2d8d4658feb377cbda7 Mon Sep 17 00:00:00 2001 From: "Kalle (Sendou)" <38327916+Sendouc@users.noreply.github.com> Date: Sat, 30 Oct 2021 16:33:38 +0300 Subject: [PATCH] Tab component from Headless UI --- frontend/components/common/Tab.tsx | 81 +++++++++++++++++++ frontend/components/common/Tabs.tsx | 67 --------------- frontend/components/layout.tsx | 6 +- frontend/package-lock.json | 19 +++++ frontend/package.json | 1 + frontend/pages/_document.tsx | 1 + .../pages/o/[organization]/[tournament].tsx | 32 ++++---- 7 files changed, 122 insertions(+), 85 deletions(-) create mode 100644 frontend/components/common/Tab.tsx delete mode 100644 frontend/components/common/Tabs.tsx diff --git a/frontend/components/common/Tab.tsx b/frontend/components/common/Tab.tsx new file mode 100644 index 000000000..71a0d9240 --- /dev/null +++ b/frontend/components/common/Tab.tsx @@ -0,0 +1,81 @@ +import { Tab as HeadlessTab } from "@headlessui/react"; +import { ComponentProps } from "react"; +import { css } from "stitches.config"; + +export function Tab(props: any) { + return ( + (selected ? tab({ type: "active" }) : tab())} + /> + ); +} + +function Group(props: ComponentProps) { + return ; +} + +function List({ + tabsCount, + ...props +}: ComponentProps & { tabsCount: number }) { + return ( + + ); +} + +function Panels(props: ComponentProps) { + return ; +} + +function Panel(props: ComponentProps) { + return ; +} + +Tab.Group = Group; +Tab.List = List; +Tab.Panels = Panels; +Tab.Panel = Panel; + +const container = css({ + display: "grid", + justifyContent: "center", + placeItems: "center", + gap: "$10", + gridTemplateColumns: "repeat(var(--tabs-count), 85px)", +}); + +const tab = css({ + all: "unset", + fontSize: "$sm", + cursor: "pointer", + + "&::after": { + display: "block", + width: "1.25rem", + height: "3px", + borderBottom: "3px solid", + content: '""', + borderColor: "transparent", + }, + + "&:hover::after": { + borderColor: "$themeTransparent", + }, + + variants: { + type: { + active: { + fontWeight: "$bold", + + "&::after": { + borderColor: "$theme !important", + }, + }, + }, + }, +}); diff --git a/frontend/components/common/Tabs.tsx b/frontend/components/common/Tabs.tsx deleted file mode 100644 index 064d212d5..000000000 --- a/frontend/components/common/Tabs.tsx +++ /dev/null @@ -1,67 +0,0 @@ -import styled from "@emotion/styled"; -import { ReactNode } from "react"; - -const Container = ({ - children, - tabsCount, -}: { - children: ReactNode; - tabsCount: number; -}) => { - return {children}; -}; - -const Tab = ({ - children, - active, - onClick, -}: { - children: ReactNode; - active?: boolean; - onClick?: () => void; -}) => { - return ( - - {children} - - ); -}; - -const S = { - Container: styled.div<{ tabsCount: number }>` - display: grid; - grid-template-columns: repeat(${(props) => props.tabsCount}, 85px); - justify-content: center; - place-items: center; - gap: 2.5rem; - `, - TabButton: styled.button<{ active?: boolean }>` - all: unset; - font-weight: ${(props) => (props.active ? "bold" : 500)}; - font-size: 0.9rem; - cursor: pointer; - - ::after { - display: block; - width: 1.25rem; - height: 3px; - border-bottom: 3px solid - ${(props) => - props.active ? "var(--colors-theme) !important" : "transparent"}; - content: ""; - } - - :hover::after { - border-color: var(--colors-theme-transparent); - } - - :focus-visible::after { - border-color: var(--colors-theme-transparent); - } - `, -}; - -export default { - Container, - Tab, -}; diff --git a/frontend/components/layout.tsx b/frontend/components/layout.tsx index e456dcaa3..bc46d6cec 100644 --- a/frontend/components/layout.tsx +++ b/frontend/components/layout.tsx @@ -46,7 +46,7 @@ export function Layout({ children }: { children: ReactNode }) { {navItems.map((navItem) => ( - + {navItem.title} {navItem.items.map((item) => ( @@ -123,7 +123,7 @@ const S_NavLink = stitchesStyled("a", { textTransform: "capitalize", transition: "0.2s transform", - ":hover": { + "&:hover": { transform: "translateX(2px)", }, }); @@ -131,7 +131,7 @@ const S_NavLink = stitchesStyled("a", { // TODO: figure out whether to server items from asset or public and migrate all images there // + if not using next image do some adjusting of the image size, format etc. const S_NavLinkImage = stitchesStyled("img", { - width: "$7", + width: "1.75rem", marginRight: "$2", }); diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 35b03f9b7..790ee2f5e 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -7,6 +7,7 @@ "name": "@sendou.ink/frontend", "dependencies": { "@emotion/styled": "^11.3.0", + "@headlessui/react": "^1.4.1", "@mantine/core": "^3.0.5", "@mantine/hooks": "^3.0.5", "@mantine/next": "^3.0.5", @@ -865,6 +866,18 @@ "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.1.tgz", "integrity": "sha512-gfta+H8aziZsm8pZa0vj04KO6biEiisppNgA1kbJvFrrWu9Vm7eaUEy76DIxsuTaWvti5fkJVhllWc6ZTE+Mdw==" }, + "node_modules/@headlessui/react": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.4.1.tgz", + "integrity": "sha512-gL6Ns5xQM57cZBzX6IVv6L7nsam8rDEpRhs5fg28SN64ikfmuuMgunc+Rw5C1cMScnvFM+cz32ueVrlSFEVlSg==", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": "^16 || ^17 || ^18", + "react-dom": "^16 || ^17 || ^18" + } + }, "node_modules/@mantine/core": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/@mantine/core/-/core-3.0.5.tgz", @@ -8413,6 +8426,12 @@ "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.1.tgz", "integrity": "sha512-gfta+H8aziZsm8pZa0vj04KO6biEiisppNgA1kbJvFrrWu9Vm7eaUEy76DIxsuTaWvti5fkJVhllWc6ZTE+Mdw==" }, + "@headlessui/react": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.4.1.tgz", + "integrity": "sha512-gL6Ns5xQM57cZBzX6IVv6L7nsam8rDEpRhs5fg28SN64ikfmuuMgunc+Rw5C1cMScnvFM+cz32ueVrlSFEVlSg==", + "requires": {} + }, "@mantine/core": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/@mantine/core/-/core-3.0.5.tgz", diff --git a/frontend/package.json b/frontend/package.json index e84fe9149..4542535e2 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -8,6 +8,7 @@ }, "dependencies": { "@emotion/styled": "^11.3.0", + "@headlessui/react": "^1.4.1", "@mantine/core": "^3.0.5", "@mantine/hooks": "^3.0.5", "@mantine/next": "^3.0.5", diff --git a/frontend/pages/_document.tsx b/frontend/pages/_document.tsx index 91deeeaf1..d0d63d9db 100644 --- a/frontend/pages/_document.tsx +++ b/frontend/pages/_document.tsx @@ -3,6 +3,7 @@ import { createGetInitialProps } from "@mantine/next"; const getInitialProps = createGetInitialProps(); +// TODO: https://stitches.dev/blog/using-nextjs-with-stitches export default class _Document extends Document { static getInitialProps = getInitialProps; } diff --git a/frontend/pages/o/[organization]/[tournament].tsx b/frontend/pages/o/[organization]/[tournament].tsx index d229ba0c5..51eb88247 100644 --- a/frontend/pages/o/[organization]/[tournament].tsx +++ b/frontend/pages/o/[organization]/[tournament].tsx @@ -1,7 +1,6 @@ import styled from "@emotion/styled"; -import { useState } from "react"; -import { InfoBanner } from "../../../components/tournament/InfoBanner"; -import Tabs from "../../../components/common/Tabs"; +import { InfoBanner } from "components/tournament/InfoBanner"; +import { Tab } from "components/common/Tab"; const tabs = [ { name: "Overview", id: "info" }, @@ -13,21 +12,24 @@ const tabs = [ ]; export default function TournamentPage() { - const [activeTab, setActiveTab] = useState("info"); return ( - - {tabs.map((tab) => ( - setActiveTab(tab.id)} - > - {tab.name} - - ))} - + + + {tabs.map((tab) => ( + {tab.name} + ))} + + + Content 1 + Content 2 + Content 3 + Content 4 + Content 5 + Content 6 + + ); }