From d52c9766ece7fb33d6a8f5c39b150802a285a043 Mon Sep 17 00:00:00 2001 From: Nathan Wang Date: Tue, 14 Jul 2020 21:47:51 -0700 Subject: [PATCH] update sidebar styling, closes #48 --- .../ModuleLayout/SidebarNav/Accordion.tsx | 60 +++++++++++++++++++ .../ModuleLayout/SidebarNav/ItemLink.tsx | 13 ++-- .../ModuleLayout/SidebarNav/SidebarNav.tsx | 24 +++++--- .../ModuleLayout/SidebarNav/StyledLink.tsx | 52 ++++++++++++++++ src/components/markdown/LanguageSection.tsx | 4 +- 5 files changed, 135 insertions(+), 18 deletions(-) create mode 100644 src/components/ModuleLayout/SidebarNav/Accordion.tsx create mode 100644 src/components/ModuleLayout/SidebarNav/StyledLink.tsx diff --git a/src/components/ModuleLayout/SidebarNav/Accordion.tsx b/src/components/ModuleLayout/SidebarNav/Accordion.tsx new file mode 100644 index 0000000..b41b9c0 --- /dev/null +++ b/src/components/ModuleLayout/SidebarNav/Accordion.tsx @@ -0,0 +1,60 @@ +import * as React from 'react'; +import { useEffect, useState } from 'react'; +import styled from 'styled-components'; +import tw from 'twin.macro'; +import useStickyState from '../../../hooks/useStickyState'; + +const Container = styled.div` + &:last-of-type { + ${tw`border-b`} + } +`; + +const Label = styled.div` + &:hover { + background-color: #f7faff; + } +`; + +export default function Accordion({ label, isActive, children }) { + const [expanded, setExpanded] = useStickyState( + true, + 'guide:sidebarnav:isexpanded:' + label + ); + useEffect(() => { + if (isActive) setExpanded(true); + }, [isActive]); + return ( + + + {expanded && children} + + ); +} diff --git a/src/components/ModuleLayout/SidebarNav/ItemLink.tsx b/src/components/ModuleLayout/SidebarNav/ItemLink.tsx index c7e3287..75749d7 100644 --- a/src/components/ModuleLayout/SidebarNav/ItemLink.tsx +++ b/src/components/ModuleLayout/SidebarNav/ItemLink.tsx @@ -1,6 +1,7 @@ import * as React from 'react'; import { Link } from 'gatsby'; import { ModuleLinkInfo } from '../../../module'; +import StyledLink from './StyledLink'; const ItemLink = ({ link, @@ -13,19 +14,15 @@ const ItemLink = ({ React.useEffect(() => { if (isActive) { - console.log(itemRef); itemRef.current.scrollIntoView({ block: `center` }); } }, [isActive]); return ( - - {link.title} + + + {link.title} + ); }; diff --git a/src/components/ModuleLayout/SidebarNav/SidebarNav.tsx b/src/components/ModuleLayout/SidebarNav/SidebarNav.tsx index 2789e1e..bb190cd 100644 --- a/src/components/ModuleLayout/SidebarNav/SidebarNav.tsx +++ b/src/components/ModuleLayout/SidebarNav/SidebarNav.tsx @@ -2,6 +2,7 @@ import * as React from 'react'; import { ModuleLinkInfo } from '../../../module'; import { Link } from 'gatsby'; import ItemLink from './ItemLink'; +import Accordion from './Accordion'; export interface NavLinkGroup { label: string; @@ -23,18 +24,25 @@ export const SidebarNav = ({ const renderLink = (link: NavLinkItem) => { if (link instanceof ModuleLinkInfo) { return ( - + ); } return ( -
-
- {link.label} -
+ x instanceof ModuleLinkInfo && x.id === activeLink.id + ) !== -1 + } + > {link.children.map(renderLink)} -
+ ); }; return <>{links.map(renderLink)}; diff --git a/src/components/ModuleLayout/SidebarNav/StyledLink.tsx b/src/components/ModuleLayout/SidebarNav/StyledLink.tsx new file mode 100644 index 0000000..8b8db8f --- /dev/null +++ b/src/components/ModuleLayout/SidebarNav/StyledLink.tsx @@ -0,0 +1,52 @@ +import styled, { css } from 'styled-components'; +import tw from 'twin.macro'; +import { Link } from 'gatsby'; + +// Almost entirely copy pasted from https://gatsbyjs.org/ oops + +const StyledLink = styled.span` + ${tw`focus:outline-none transition ease-in-out duration-150 hover:text-blue-700 focus:bg-blue-100 relative flex items-center px-6 py-3 text-sm leading-5`} + + ${({ isActive }) => + isActive + ? tw`text-blue-700 font-semibold` + : tw`text-gray-600`} + + + &::before, + &::after { + content: ''; + left: 0.5rem; + top: 1.3em; + height: 8px; + width: 8px; + position: absolute; + transition: all 250ms cubic-bezier(0.4, 0, 0.2, 1) 0s; + } + + ${props => + props.isActive && + css` + &::after { + transform: ${props => + props.isActive ? 'translateX(-92px)' : 'translateX(-100px)'}; + width: 100px; + border-radius: 4px; + ${tw`bg-blue-600`} + } + `} + + &::before { + transform: scale(0.1); + border-radius: 100%; + } + + &:hover { + &::before { + transform: scale(1); + ${tw`bg-blue-600`} + } + } +`; + +export default StyledLink; diff --git a/src/components/markdown/LanguageSection.tsx b/src/components/markdown/LanguageSection.tsx index 8b3afd7..f889d6d 100644 --- a/src/components/markdown/LanguageSection.tsx +++ b/src/components/markdown/LanguageSection.tsx @@ -29,10 +29,10 @@ export const LanguageSection = props => { return ( <> {Object.keys(sections).map(lang => ( - <> +

{languages[lang]}

{sections[lang]} - +
))} );