import { CollapsedIcon } from "outline-icons"; import * as React from "react"; import styled, { keyframes } from "styled-components"; import usePersistedState from "~/hooks/usePersistedState"; import { undraggableOnDesktop } from "~/styles"; type Props = { /** Unique header id – if passed the header will become toggleable */ id?: string; title: React.ReactNode; }; /** * Toggleable sidebar header */ export const Header: React.FC = ({ id, title, children }) => { const [firstRender, setFirstRender] = React.useState(true); const [expanded, setExpanded] = usePersistedState( `sidebar-header-${id}`, true ); React.useEffect(() => { if (!expanded) { setFirstRender(false); } }, [expanded]); const handleClick = React.useCallback(() => { setExpanded(!expanded); }, [expanded, setExpanded]); return ( <>

{expanded && (firstRender ? children : {children})} ); }; export const fadeAndSlideDown = keyframes` from { opacity: 0; transform: translateY(-8px); } to { opacity: 1; transform: translateY(0px); } `; const Fade = styled.span` animation: ${fadeAndSlideDown} 100ms ease-in-out; `; const Button = styled.button` display: inline-flex; align-items: center; font-size: 13px; font-weight: 600; user-select: none; color: ${(props) => props.theme.textTertiary}; letter-spacing: 0.03em; margin: 0; padding: 4px 2px 4px 12px; height: 22px; border: 0; background: none; border-radius: 4px; -webkit-appearance: none; transition: all 100ms ease; ${undraggableOnDesktop()} &:not(:disabled):hover, &:not(:disabled):active { color: ${(props) => props.theme.textSecondary}; cursor: var(--pointer); } `; const Disclosure = styled(CollapsedIcon)<{ expanded?: boolean }>` transition: opacity 100ms ease, transform 100ms ease, fill 50ms !important; ${({ expanded }) => !expanded && "transform: rotate(-90deg);"}; opacity: 0; `; const H3 = styled.h3` margin: 0; &:hover { ${Disclosure} { opacity: 1; } } `; export default Header;