// @flow import { observer } from "mobx-react"; import { CollapsedIcon } from "outline-icons"; import * as React from "react"; import { withRouter, NavLink } from "react-router-dom"; import styled, { withTheme } from "styled-components"; import Flex from "components/Flex"; type Props = { to?: string | Object, href?: string | Object, onClick?: (SyntheticEvent<>) => void, children?: React.Node, icon?: React.Node, expanded?: boolean, label?: React.Node, menu?: React.Node, menuOpen?: boolean, hideDisclosure?: boolean, iconColor?: string, active?: boolean, theme: Object, exact?: boolean, depth?: number, }; function SidebarLink({ icon, children, onClick, to, label, active, menu, menuOpen, hideDisclosure, theme, exact, href, depth, ...rest }: Props) { const [expanded, setExpanded] = React.useState(rest.expanded); const style = React.useMemo(() => { return { paddingLeft: `${(depth || 0) * 16 + 16}px`, }; }, [depth]); React.useEffect(() => { if (rest.expanded) { setExpanded(rest.expanded); } }, [rest.expanded]); const handleClick = React.useCallback( (ev: SyntheticEvent<>) => { ev.preventDefault(); ev.stopPropagation(); setExpanded(!expanded); }, [expanded] ); const handleExpand = React.useCallback(() => { setExpanded(true); }, []); const showDisclosure = !!children && !hideDisclosure; const activeStyle = { color: theme.text, background: theme.sidebarItemBackground, fontWeight: 600, ...style, }; return ( {icon && {icon}} {menu && {menu}} {expanded && children} ); } // accounts for whitespace around icon const IconWrapper = styled.span` margin-left: -4px; margin-right: 4px; height: 24px; `; const Action = styled.span` display: ${(props) => (props.menuOpen ? "inline" : "none")}; position: absolute; top: 4px; right: 4px; color: ${(props) => props.theme.textTertiary}; svg { opacity: 0.75; } &:hover { svg { opacity: 1; } } `; const StyledNavLink = styled(NavLink)` display: flex; position: relative; overflow: hidden; text-overflow: ellipsis; padding: 4px 16px; border-radius: 4px; color: ${(props) => props.theme.sidebarText}; font-size: 15px; cursor: pointer; &:hover { color: ${(props) => props.theme.text}; } &:focus { color: ${(props) => props.theme.text}; background: ${(props) => props.theme.black05}; outline: none; } &:hover { > ${Action} { display: inline; } } `; const Wrapper = styled(Flex)` position: relative; `; const Label = styled.div` position: relative; width: 100%; max-height: 4.8em; line-height: 1.6; `; const Disclosure = styled(CollapsedIcon)` position: absolute; left: -24px; ${({ expanded }) => !expanded && "transform: rotate(-90deg);"}; `; export default withRouter(withTheme(observer(SidebarLink)));