A collection of UI components build to create a production grade front-end experience with react & Next.js
component | description |
---|---|
Accordion | Vertically stacked list of items that can be collapsed/expanded individually |
Box | The base for all components |
Breadcrumb | Shows the current path with the ability to navigate to each sub-path individually |
Button | Simple button component (see storybook for the most up to date variants) |
Checkbox | Checkbox with label and an optional statusmessage (optimized for usage with react-hook-form) |
DatePicker | Datepicker that utilizes 'react-flatpickr' |
Flex | Mimics a flexbox implementation |
Grid | Mimics a grid implementation using flexbox for compatibility reasons (with few limitations in comparison to the actual grid spec) |
Heading | Semantically correct headings (see storybook for all default variants) |
Icon | Allows for svgs to be used as icon. We also provide some default icons you can choose to import and use with the icon component (see storybook for a complete overview). *Note: please consider using something like SVGR when using your own icons |
Input | Input box with label and an optional statusmessage (optimized for usage with react-hook-form) |
Modal | Modal build with reach-dialog which uses framer-motion to ensure smooth state transition animations |
Radio | Radio group with labels and an optional statusmessage (optimized for usage with react-hook-form) |
Select | Select (created with react-select ) input with label and an optional statusmessage (optimized for usage with react-hook-form) |
Spinner | Indicator to display a loading state |
Stack | Automagically creates a (horizontal or vertical) stack of items with evenly spaced |
StatusMessage | Displays a message in a certain colour based on the type of status (default, warning, error, success) |
Tag | Tag component used to create a list of toggleable tags with an optional statusmessage (optimized for usage with react-hook-form) |
Text | Semantically correct text blocks (see storybook for all default variants) |
TextArea | Text area with label and an optional statusmessage (optimized for usage with react-hook-form) |
Toggle | Toggle with label and an optional statusmessage (optimized for usage with react-hook-form) |
- Note: If a component does not satisfies your needs you can easily copy the contents of the components into your own project to extend / modify to fit your use-case (for other, less dramatic, customization options keep on reading 😉)
When the thought about creating (yet another) ui-library for react, the obvious questions were unavoidable:
- Why?
- Aren't there already many ui-libraries out there? What are we solving that others don't?
Yes there are already a bunch of ui-libraries but none specifically tailored to our setup which in the end resulted in a lot of repetitive work and/or tweaking or customizing the already existing libraries to the point where "building your own" becomes a viable option.
Our focus was to redo as less as possible and utilize as much as possible with battled tested libraries (preferably backed by an open source community). So we took some time to stitch everthing together to come up with a setup that enables us to get up and running quickly.
During development of this library certain choices have been made which enforce certain constraints on the developer 🔒
This done in order make the experience between projects as similar as possible. Most of these constraints are considered 'best-practices' anyway so they shouldn't be surprising to deal with 🤓
Using typescript is highly recommended
Quickest way to get started is by running the following command:
yarn install @storyofams/react-ui
The library requires the following dependencies to be already installed:
- React (^17.0.0)
- Next.js (^10.0.0)
- styled-system (^5.1.0)
- @styled-system/css (^5.1.0)
- @styled-system/props (^5.1.0)
- styled-components (^5.2.0)
- @reach/alert (^0.13.0)
- @reach/checkbox (^0.13.0)
- @reach/dialog (^0.13.0)
- flatpickr (^4.6.9)
- react-flatpickr (^3.10.7)
- framer-motion (^3.10.0)
- react-id-generator (^3.0.0)
- react-select (^4.1.0)
You can get started right away by importing whichever component you fancy into your project, however to get the most optimal developer experience keep on reading!
Add the following file to your project as styled.d.ts
import 'styled-components';
export interface Breakpoints extends Array<string> {
sm?: string;
md?: string;
lg?: string;
xl?: string;
}
declare module 'styled-components' {
type Theme = typeof import('./path/to/theme-default-export.ts').default;
export interface DefaultTheme extends Theme {
breakpoints: Breakpoints;
}
}
Setting up requires adding a theme that should comply with the theme definition specified here with a slight adjustment to the breakpoints. If you want to get started quickly just copy and paste the theme from the library (for the Breakpoints import see the above Types
step).
We export a list of commonly used icons to get started quickly which you can view here. Besides the icons we provide you can also supply your own svg to the Icon component as a React component. This recommended way of adding icons to load them into your application is by using svgr.
Have a look at the latest storybook deployment to view all the components. Most likely you'll find what you need there and won't even have to look further.
This library is made to get up and running fast which means we're providing variants we think that are useful that work for most use-cases. There will however always be projects that require new
variants or slight adjustments on the already existing variants. To allow for this we're exporting a function called styled
. This function is a wrapper on top of styled-components that pretty much works like the styled function created by stitches.
example:
import { Button, styled } from '@storyofams/react-ui';
// Button has the following variants by default:
// - variant (primary, secondary, link, underline)
// - buttonSize (small, medium, large)
const ExtendedButton = styled(Button, {
variants: {
newVariant: {
primary: {
fontSize: 21,
'&:hover': {
backgroundColor: 'primary100',
},
},
},
buttonSize: {
'medium-screen-xl': {
fontSize: 2.2,
lineHeight: 'medium',
},
},
variant: {
icon: {
fontSize: 14,
borderRadius: 9999,
},
},
},
});
export const Extended = () => (
<>
<ExtendedButton variant="primary">button</ExtendedButton>
<ExtendedButton variant="icon" newVariant="primary">
button
</ExtendedButton>
<ExtendedButton
variant="icon"
buttonSize={['large', 'medium', 'medium-screen-xl']}
>
button
</ExtendedButton>
</>
);
Thanks to styled-system we get access to a css
function. This css function can be used when you don't quite want to wrap a whole new styled-component, but you do need some specific css selectors to make it look pretty 🥰
To utilize the full potential of typescript we've re-exported the css function for you but added some autocomplete for values that live in your theme.
comparison:
import { css } from '@styled-system/css'
<Component
css={css({
backgroundColor: 'red' // autocompleted
backgroundColor: 'primary500' // not-autocompleted
})}
/>
VS
import { css } from '@storyofams/react-ui'
<Component
css={css({
backgroundColor: 'red' // autocompleted
backgroundColor: 'primary500' // autocompleted
})}
/>
For those components that just require extra customization or that really can't do without those few extra lines of css you can extend systemprops
.
example:
import styled from 'styled-components';
import { Box, SystemProps } from '@storyofams/react-ui';
type CustomBoxProps = SystemProps & {
/** add any CustomBoxProps here */
customProp: string;
}
const CustomBox = styled(Box)<CustomBoxProps>`
// very specific styling that cannot be applied through either;
// * props
// * cssProp
`;
export const CustomComponent = (({ customProp, ...rest}): CustomBoxProps) => {
return (
<CustomBox {...rest}>
{/** ... */}
</CustomBox>
)
};
Following are some things to take note of when using the library.
I'm not using next.js, why do I need to install next.js?
Every project is different, we've found that next.js offers us a rich environment to get up and running fast for small to huge applications. Having that said, using react-ui is not completely depended on Next.js, with the only exception being the button component. This component can act as a link between content for your application and uses the next link since that's what we use most. We are looking into the possibilities to allow to provide a custom Link component to the button.
I'm seeing a lot of properties on the dom but no actual styling is applied?
This is a know issue when using a component that uses a forwardingRef. Our current setup requires the as
prop to enable autocomplete on certain HTML properties, since that components accepts an as
property but is also forwarding a ref to another styled-component (which again accepts as
) you'll need to forward the as
. We're looking into the misconfiguration that is happening between those properties and why it's causing the properties to be passed to the dom rather than being used for styling.
Some things do not have color am I going colourblind?
Most likely a theme variable we're using isn't covered in your theme. Don't worry you can style those all individually as component props. If you do find a color that's playing nice please let us know by filing an issue
Props are not autocompleting with values from my theme
Make sure to go through the setup section of this readme. If the problem persists check if your implementation differs from the one in the /example
folder. If all of the above fails let us know by filing an issue
When creating this library we couldn't have done it without the following pioneers.
This library has really been on the forefront of developing react applications that are easily styled since the early days. It has served us very well over the course of the years and it will be hard to part ways if there ever comes a time where on of the other solutions in this space takes over.
You're probably already familiar with styled-component but be sure to give them some love 💜
This library, but more specifically Brent Jackson has really shaped up how we look to design systems. The foundation he has created with styled-system is really the dream of every developer.
Not sure what happened but the repo's have stayed unmaintained / unchanged for a while now. So we are using styled-system and the complimentary packages props and css to create the best DX we could come up with.
Huge shout out to this library and it's author for paving the way that enabled us to do this 💯
This library is a more recent addition to the stack, but caught our eye because the shared philosophy that builds on styled-system and even includes some extensive pseudo elements as props (based on the chakra-ui implementation).
Another library that has been there for a while is reach-ui. This library gives you the building blocks to build, the hard to get right, react components with a great attention to accessibility 🕵️♂️
This has been our go to when it comes to implementing those impossible components, with great success and most importantly ease of use.
If you are not aware of these guys already I highly recommend checking out both radix and modulz. They have been a great source of inspiration for some aspects of this UI-library. We feel like they are the breath of fresh air this section of industry is really urging for. Stitches is highly innovative taking modern css capabilities to the css-in-js that we've all gotten to love. Radix is just a work of love, a product of hard work and dedication, to make the web more accessible to everyone 🥰
Having that said we also feel like it is still too early to convert our entire codebase. We are however keeping a close eye on what they are up to and will most likely jump on the wagon as soon as we feel it's matured enough to be steadily used in production grade font-end applications.