Skip to content

Instantly share code, notes, and snippets.

@nsantos16
Created April 1, 2021 04:28
Show Gist options
  • Save nsantos16/e5738da962bb6d31900f414aa23690ab to your computer and use it in GitHub Desktop.
Save nsantos16/e5738da962bb6d31900f414aa23690ab to your computer and use it in GitHub Desktop.
import React, { useState, useEffect, useContext, useRef } from "react";
import ReactDOM from "react-dom";
import { NavLink } from "react-router-dom";
import styled from "styled-components";
import "./styles.css";
const Context = React.createContext();
const useBreadcrumbContext = () => {
const context = useContext(Context);
if (!context) {
throw new Error("Missing BreadcrumbProvider.");
}
return context;
};
const BreadcrumbProvider = ({ children }) => {
const portalNodeState = useState();
return (
<Context.Provider value={portalNodeState}>{children}</Context.Provider>
);
};
const BreadcrumbPortal = ({ children }) => {
const portalNodeRef = useRef();
const [, setPortalNode] = useBreadcrumbContext();
useEffect(() => {
setPortalNode(portalNodeRef.current);
}, []);
return (
<nav aria-label="Breadcrumb">
<Items ref={portalNodeRef} />
</nav>
);
};
const Items = styled.ol`
margin: 0;
padding-left: 0;
list-style: none;
`;
const Breadcrumb = ({ children, to, ...props }) => {
const [portalNode] = useBreadcrumbContext();
return portalNode
? ReactDOM.createPortal(
<Item {...props}>
<ItemLink to={to}>{children}</ItemLink>
</Item>,
portalNode
)
: null;
};
const Item = styled.li`
display: inline;
& + &::before {
content: "";
display: inline-block;
transform: rotate(15deg);
border-right: 1px solid currentColor;
height: 1em;
margin: 0 8px -0.2em;
}
`;
const ItemLink = styled(NavLink).attrs({ exact: true })`
color: #36d;
text-decoration: none;
border-bottom: 1px solid transparent;
&:hover {
border-color: currentColor;
}
&.active {
border: none;
color: inherit;
}
`;
export { BreadcrumbProvider, BreadcrumbPortal, Breadcrumb };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment