import { Meta, Source } from "@storybook/blocks";
import Button from "../components/Button/Button"; import Link from "../components/Link/Link"; import Text from "../components/Text/Text";
- {Why Chakra UI?}
- {DSProvider}
- {Components}
- {Styling}
- {Style Props}
- {Hooks}
- {Testing}
The Reservoir Design System (DS) project was influenced by other design systems but ultimately we decided to initially build DS components from scratch rather than use another design system as its foundation. To better help all the projects at NYPL and to better scale with all the components we have built and still need to build, we decided to integrate Chakra UI into the DS.
Chakra UI is an open source component library that is opinionated and uses design and development patterns that various projects at NYPL use. Since the DS will be the foundation for all NYPL projects moving forward, using Chakra will help us align all projects so similar patterns are used throughout various teams and projects.
Chakra follows WAI-ARIA and WCAG 2.1 standards and guidelines which aligns with the standards that NYPL follows for its own components and applications.
With design and development consistency, the ability to customize components if necessary, and accessibility standards in place, developers at NYPL using the Design System will be able to build out applications faster.
We recommend to read Chakra's own documentation to get up to speed on it. This file will provide information on how it is used in the DS but we rely on Chakra's documentation.
If you need help updating to a newer version of the DS, check out our Chakra Migration Guide.
In order to use DS components in a consuming application, there is a necessary step that must be done for component styles to properly render. Consuming applications need to wrap all the DS components with a simple provider component. Fortunately, this only needs to be done once at the top level of the consuming application.
Once the following is completed, DS components that internally use Chakra UI
will render styles properly. Internally, the DSProvider
is built on top of
Chakra's ChakraProvider
component with NYPL's custom theme as input. This sets
up the style context to propogate through all the children nodes in the DOM tree.
Although Chakra is integrated into the DS repo, we are still working to compose
DS components with Chakra components or patterns. For example, both the DS and
Chakra have a Button
component so we will use Chakra's Button
component to
compose the DS Button
component. However, the DS has a Hero
component that
is not already built by Chakra. In this case, the DS Hero
component will
internally use Chakra
components such as Box
.
While we can directly use Chakra components that align with DS components, we want to compose DS components using the Chakra component as a base instead. This pattern allows the Design System to have control over props and standard styles.
These components composed from Chakra, therefore, do not have all styled props
available. For example, whereas m
(margin
), me
(marginEnd
), and similar
props can be used in Chakra components, those props are not available for DS
components that internally are composed with Chakra components.
Components built from Chakra rename the component with the Chakra
name prefix.
In this example, the ChakraTabs
component is returned with NYPL specific
functionality, styles, and other requirements.
We are writing CSS style object rules into Javascript objects that work with Chakra's theme. Instead of creating a variant for a component with a class name, now different props or internal logic are used to get the appropriate variant. Internally, the right variant will be mapped to a Chakra theme variant that will provide all the necessary styles.
For the Button
component, for example, we would convert a SCSS class rule such
as .button-outline
to a Javascript object (more on this in the Anatomy of a
Component Styling Object section).
Some components are directly exported from Chakra. These components can be found
in the /src/index.ts
file. Note that not all Chakra components are re-exported
because we want to limit what developers should use in consuming applications.
They include:
Box
, Center
, Circle
, Grid
, GridItem
, HStack
, Square
, Stack
, VStack
Note: These components are harder to have snapshot tests for because, internally, these components autogenerate ids and class names on every new render. We can't override them so snapshot tests will fail.
Update: Newer Chakra UI versions have mostly fixed this issue. Still, since Chakra components have already been tested, we don't necessarily want or need to test them ourselves.
The NYPL DS' theme file can be found at src/theme/index.ts
. This creates a new
theme that extends Chakra's theme and is set in the DSProvider
component. Note
that the example below is the general structure of the theme
object but the DS
theme
object has values already set so it may look different. You would generally
only work and add new object values in the components
obejct key for new
components and their theme or variants.
Note: There are some SCSS files used to style third party plugins and to generate SCSS mixins.
For in-depth information, read Chakra's Component Style documentation.
Component theme files can be found in the src/theme/components/
directory.
Here is an example using the Button
component.
A current variant class rule can be converted to a Javascript object and go in
the variants
object as in the following example.
Now this variant can be rendered:
There are currently five (5) breakpoint values used in the DS:
Key Name | EM/PX value |
---|---|
sm | 20em/320px |
md | 38em/600px |
lg | 60em/960px |
xl | 80em/1280px |
2xl | 96em/1536px |
There are two ways to set breakpoint values for a style rule: the array method
and the object method. We prefer the object method and recommend to use the
object method since it is easier to read and readily know what values take
effect at defined breakpoint values. Note that the Chakra "base"
key value is
the same as "sm"
.
We recommend and follow this pattern in the DS. As an example, let's say we want
to increase the width of the Button
component as the device width increases.
We start at value "100px" and increase by "50px" at every breakpoint. In the
button.ts
style file, we can define it as in the example below:
You do not have to define every breakpoint. If you only want to change the width
of the Button
at the lg
breakpoint, it can be defined as:
We do not recommend this pattern because it is harder to read and implicit on
breakpoint values. Following the same example as the one above, the width of the
Button
component can be updated wiht all five values in an array:
All available colors can be found in src/theme/foundations/colors.ts
. Chakra
autogenerates the colors
object into CSS variables. We will rely on these
variables rather than creating our own.
In the shorten object example above, the following will be generated by Chakra:
Theme object value | CSS variable |
---|---|
colors.ui.focus |
--nypl-colors-ui-focus |
colors.ui.link.primary |
--nypl-colors-ui-link-primary |
colors.ui.link.secondary |
--nypl-colors-ui-link-secondary |
colors.section["whats-on"].primary |
--nypl-colors-section-whats-on-primary |
colors.section["whats-on"].secondary |
--nypl-colors-section-whats-on-secondary |
Note: while each Chakra color has number range values from 50 to 900 (such as
red.400
, blue.600
, etc) and each one is based on the color coming from
DS' Figma documentation, we recommend NOT to use them.
All the spacing values can be found in the src/theme/foundations/spacing.ts
file. While Chakra provides many values, only use the eight DS defined values.
NYPL name Value | Chakra Value | DS Variable |
---|---|---|
xxs | 1 | --nypl-space-xxs |
xs | 2 | --nypl-space-xs |
s | 4 | --nypl-space-s |
m | 6 | --nypl-space-m |
l | 8 | --nypl-space-l |
xl | 12 | --nypl-space-xl |
xxl | 16 | --nypl-space-xxl |
xxxl | 24 | --nypl-space-xxxl |
For example, to make all button
s have a padding: 8px 16px
value:
All typography values can be found in the src/theme/foundations/typography.ts
file. These values declare the font family, font sizes, and font weights to use
for all text.
NYPL Reservoir components are built around the Chakra UI library. While Reservoir components may use the corresponding Chakra UI component, that is not always the case. Every Reservoir component, however, does make use of the Chakra UI "style props" pattern. This means that it is possible to pass in CSS rules to a component, including the shorthand versions. These style props will target the wrapper element of the component; this means if you want to target a specific element or component in a Reservoir component, you won't be able to with style props.
{
While this is available to use, it is not recommended. If you see a need to override styles, please reach out to the NYPL Reservoir team for assistance. }In the following example, the Button
component has been passed p
and maxW
props which are shorthand for "padding" and "max-width", respectively.
{
Button }Find more information and a full list of all the available props, check the Chakra UI Style Props page.
The following hooks are available to use and can be imported from
@nypl/design-system-react-components
.
If your application does not use CSS or SCSS files and you want to write
CSS-in-JS styles in your React components, the useNYPLTheme
hook will provide
you with NYPL-specific style values. This hook depends on the DSProvider
component and if the function is used outside of this wrapper component, then
the theme object will be empty.
After importing and rendering the DSProvider
wrapper component, as explained
in the DSProvider section, your
children components can use this hook function.
The theme
variable will be a JS object with style values discussed in the
sections above. This will allow you to use NYPL-specific styles in your
components through CSS-in-JS.
Note: more patterns will be added.
- NYPL DS Components
All DS components should be used with their current styles. If a DS component needs an updated style, first contact the Design System and UX teams about this update. If you really need to update a style and there is no available variant, then you can add styles directly as style prop.
For example, if the Heading
component should render the text in NYPL's green
color used for "success primary" and add a bold font weight, then you can do
the following:
{/* Other components */}
Of course, you can destructure the theme
object to only get the object keys
you need for your component (this is a general example). Log the object to the
console to see all the available styles.
- HTML Components
Use the style
attribute in HTML components to add inline styles.
Do not re-test Chakra components that are re-exported since they are already
tested in the @chakra-ui/react
package. We expect all new components composed
with Chakra components to have tests for functionality and styling, including
snapshot tests.