Opinionated design system for React, based on Chakra UI + Next.js.
- Default theme with semantic tokens
- 100% TypeScript, transpiled to ESM (requires Next.js 12+)
- Components:
In your Next.js app:
$ npm install @47ng/chakra-next
To resolve theme tokens across color modes, use useColorModeToken:
import { useColorModeToken } from '@47ng/chakra-next' const fill = useColorModeToken('red.500', 'blue.500') const shadow = useColorModeToken('md', 'dark-lg', 'shadows')
The following semantic tokens are provided:
- colors:
body(follows the html/body/__next background color)text.dimtext.dimmertext.dimmestcard.bg
- shadows:
card.shadow(make card shadow darker in dark mode to stand out)
import { RouteLink, OutgoingLink, ButtonRouteLink } from '@47ng/chakra-next' export default () => ( <> {/* Integrate Next.js routes with Chakra styles */} <RouteLink to="/login">Login</RouteLink> {/* Use `as` for dynamic routes */} <RouteLink to="/posts/[slug]" as="/posts/foo">Login</RouteLink> {/* Make external links stand out */} <OutgoingLink href="https://github.com" showExternalIcon> GitHub </RouteLink> {/* For when a button looks better, still outputs an <a> tag */} <ButtonRouteLink to="/logout">Logout</ButtonRouteLink> </> )
Use NavLink when you want a link to have special styling depending on
the current page.
By default, NavLinks:
- Underline their text when active
- Are active when the current path starts with the link path
Example:
import { NavLink } from '@47ng/chakra-next' export default () => ( <> <NavLink to="/blog">Blog</NavLink> </> )
The link will be active for the following paths:
| Path | Active |
|---|---|
/home |
false |
/blog |
true |
/blog/ |
true |
/blog/foo |
true |
import { NavLink } from '@47ng/chakra-next' export default () => ( <> <NavLink to="/blog" borderBottomWidth="3px" borderBottomColor="transparent" active={{ color: 'blue.500', borderBottomColor: 'blue.500' }} > Blog </NavLink> </> )
Sometimes, you want the NavLink to be active only on exact route matches:
import { NavLink, navLinkMatch } from '@47ng/chakra-next' export default () => ( <> <NavLink to="/home" shouldBeActive={navLinkMatch.exact}> Home </NavLink> </> )
You can also have custom logic to determine whether a NavLink should be active:
import { NavLink, navLinkMatch } from '@47ng/chakra-next' export default () => ( <> <NavLink to="/blog/[post]" as="/blog/another-blog-post?active=true" shouldBeActive={({ to, as, router }) => navLinkMatch.exact({ to, as, router }) && router?.query.active === 'true' } > Another Blog Post </NavLink> </> )
Redirect will change the current URL to the one given, when mounted.
import { Redirect } from '@47ng/chakra-next' export default ({ loggedIn }) => ( <>{loggedIn ? <Text>Hello !</Text> : <Redirect to="/login" />}</> )
By default, the redirection will be pushed onto the navigation history stack.
You can replace the history stack instead with the replace prop:
import { Redirect } from '@47ng/chakra-next' export default () => ( <> <Redirect to="/home" replace /> </> )
Next.js dynamic paths are also supported:
import { Redirect } from '@47ng/chakra-next' export default () => ( <> <Redirect to="/blog/[slug]" as="/blog/foo-bar" /> </> )
If you want to redirect to an external link
(not an internal route), you will have to set the external prop:
import { Redirect } from '@47ng/chakra-next' export default () => ( <> <Redirect to="https://example.com" external /> {/* You can also have the history replaced with external URLs: */} <Redirect to="https://example.com" external replace /> </> )
You can also pass transition options:
<Redirect to="/home" shallow scroll={false} />
import { Card, cardProps } from '@47ng/chakra-next' export default () => ( <> {/* Card as Box */} <Card>I'm in a card</Card> {/* Apply Card styles to a custom component */} <MyChakraComponent {...cardProps} /> </> )
Extends chakra.svg with with:
- SVG namespace pre-filled
role="img"
import { Svg } from '@47ng/chakra-next' export default () => ( <Svg aria-labelledby="svg-demo-title svg-demo-desc" viewBox="0 0 24 24" display="block" my={4} mx="auto" > <title id="svg-demo-title">A red circle</title> <desc id="svg-demo-desc"> Svg lets you style SVG container tags with Chakra UI style props. </desc> <circle fill="red" cx="12" cy="12" r="10"> </Svg> )
Note: to use theme tokens for fills, strokes and other SVG properties, you must resolve them first:
import { useToken } from '@chakra-ui/react' export default () => ( <Svg aria-labelledby="svg-demo-title svg-demo-desc" viewBox="0 0 24 24" display="block" my={4} mx="auto" fill={useToken('colors', 'red.500')} // Resolve theme tokens with `useToken` > <title id="svg-demo-title">A red circle</title> <desc id="svg-demo-desc"> Svg lets you style SVG container tags with Chakra UI style props. </desc> <circle // You can also use the CSS prop names directly: fill="var(--chakra-colors-red.500)" cx="12" cy="12" r="10" > </Svg> )
Sometimes you want to render a component only on the client, and have a skeleton or fallback component rendered on the server, whether for SSR or static output.
import { NoSSR } from '@47ng/chakra-next' export default () => ( <> <NoSSR>This is only rendered on the client</NoSSR> {/* Skeleton is rendered on SSR/SSG, TheRealThing is rendered on the client.*/} <NoSSR fallback={<Skeleton />}> <TheRealThing /> </NoSSR> </> )
Header with navigation links:
import { Box, Stack } from '@chakra-ui/core' import { NavLink } from '@47ng/chakra-next' export default () => ( <Box as="header"> <Stack as="nav" isInline> <NavLink to="/features">Features</NavLink> <NavLink to="/pricing">Pricing</NavLink> <NavLink to="/docs">Documentation</NavLink> </Stack> </Box> )
MIT - Made with ❤️ by François Best.