1.0.1 • Published 11 months ago

roses v1.0.1

Weekly downloads
1
License
ISC
Repository
-
Last release
11 months ago

npm version CircleCI

🌹 Roses 🌹

React component library layered atop emotion and @styled-system/css. Built with Typescript.

Skip to setup

roses is a simple, extendable design system. It's written with typescript and builds upon an opinionated extension of the system-ui interface, so type support is first-class.

It builds on the following libraries, so it's best to be familiar with them as well:

For more context and alternatives, see Related Projects

I already know what this stuff is.

TLDR:

  • Roses keeps all responsive styles in an sx prop using @styled-system/css.
  • Simple components can be styled in the theme directly under the componentStyles and variants keys- use the themed() HOC which will first apply any componentStyles you've defined and add sx and variant props.
  • More complex components can be defined like any other emotion component in the context of a styled-system theme.
  • Good type support.

Motivation

roses began as work on a design system for my own use- an extension of rebass using styled-components to build a library of reusable, themable components. Over time (and having never built a design system on my own) a couple pain points crept in:

Emotion as the css-in-js library: Early on I ran into some wrinkles around the styled-components' @types package. This was part of the motivation for switching to emotion. Additionally, it is smaller and (as of early 2019) rumoured to be more performant than styled-components.

Responsive, theme-aware styles in a single prop: Collaborators were less enthusiastic about the many styled-system props, especially when combined with the need to define Ts interfaces, account for the presence of a theme and know which props you could use where. By electing to restrict themed styles to a single prop, the total surface area of props to maintain and remember is greatly reduced. It is also designed to be more friendly to users who aren't completely sold on css-in-js. Notably this prop is baldly stolen from theme-ui.

Define core component styles and variants on the theme: Because the system-ui theme spec is wide open, different libraries have augmented it with their own keys. This is fine, but I wanted to introduce a bit of stability and the ability to define core component styles like those exported from rebass within the theme itself. @styled-system/css makes this pretty straightforward:

  • I settled on a top-level theme.componentStyles key which includes style rules as well as its nested variants. The result is much less overhead in defining components that are at their hearts the composition of a div and a few style objects.
  • HTML elements follow the theme-ui pattern of using theme.styles, and a base set of these styles is included with the default theme- see baseTheme and defaultTheme which extends it.

Setup

Add the package and any missing peer dependencies:

yarn add roses @styled-system/css @emotion/core @emotion/styled
# if using ts
# yarn add -D @types/styled-system__css @types/styled-system etc ...

Configure ThemeProvider

All of your components must to be wrapped in an emotion ThemeProvider containing a theme object. You can bring your own from the emotion-theming package or import it directly for some extra type hints:

import { RosesTheme, defaultTheme } from "roses"
// import { ThemeProvider } from 'emotion-theming'

const theme = {
  ...defaultTheme,
  colors: {
    ...defaultTheme.colors,
    white: "black",
    black: "white",
  },
}

// RosesTheme is just a rebranded ThemeProvider.
export const App = props => {
  return <RosesTheme theme={theme}>{props.everythingElse}</RosesTheme>
}

The defaultTheme export is an extension of the theme-ui base preset

Usage

Defining components

Basic component styles can be defined under the theme componentStyles key. Rebass apparently uses a similar, undocumented approach but keys are at the top level- this one I didn't know about.

Given a theme:

// extending the default theme..
{
  ...defaultTheme
  breakpoints: ["780px"], // just a single breakpoint.
  radii: [0, "2px", "4px", "8px"],
  componentStyles: {
    Rectangle: {
      color: ["black", "red"] // at 1st breakpoint the text turns red for some reason.
      padding: 1,  // indexed to `space` key
      mx: 3,
      variants: {
        hot: {
          bg: "primary"
        },
        cold: { ... }
      }

    },
    Widget: { ... }
  }

}

We can make a `Rectangle using the full api:

const Rectangle = themed({
  name: "Rectangle",
  component: "div",
})

... Or a string shorthand - with a default base component of styled('div')({boxSizing: 'border-box'}):

const Widget = themed("Widget")

Since this is all just emotion in the context of a system-ui theme under the covers, you can also build more complex components (whose styles probably won't belong in your theme). See the emotion/@styled-system/css docs for more details.

Variants

Component variant styles can be defined via a special variants key, are accessible via the variant prop and applied over the base styles:

theme.componentStyles.Card = {
  p: 2,
  m: 1,
  display: "inline-block",
  borderRadius: 2,
  variants: {
    shadow: {
      boxShadow: "0 0 16px rgba(0, 0, 0, .25)",
    },
  },
}

// later...

<Card variant="shadow">{ /* etc */ } </Card>

The sx prop

heavily inspired by theme-ui's sx prop.

The final styles applied come from the sx prop.

theme-ui introduced the sx prop. It seemed like a good idea, so roses decided to copy it. Similar to a vanilla react component's styles prop, sx accepts a SystemStyleObject. This is a familiar extension of the vanilla styles api with the responsive, theme-aware values and shortcuts that styled-system/css introduced. sx is a functional copy of theme-ui's version: It passes your styles on to the emotion css prop: <Box sx={myStyles} /> == <Box css={{styledCss(myStyles)}}/>.

Related projects

roses is heavily inspired by these projects:

  • rebass brings a layer of additional convention to styled-system with some UI primitives that you would have had to build anyway. It uses styled-components
  • theme-ui builds on the work of rebass, but makes the switch to emotion and includes built-in support for MDX.
  • system-ui is (to my knowledge) the original responsive theme spec from which styled-system, rebass and theme-ui grew.
  • @artsy/palette was my first encounter with a production design system built styled-system. For Web and React Native/iOS.

License

MIT for now.

Contributors

Docs, PRs and Bug reports welcome. Contributors agree that this project may be relicensed in the future.

1.0.1

11 months ago

1.0.0

1 year ago

0.5.0

5 years ago

0.4.1

5 years ago

0.4.0

5 years ago

0.3.1

5 years ago

0.2.6

5 years ago

0.2.5

5 years ago

0.2.4

5 years ago

0.2.3

5 years ago

0.2.2

5 years ago

0.2.1

5 years ago

0.2.0

5 years ago

0.1.4

5 years ago

0.1.3

5 years ago

0.1.2

5 years ago

0.1.1

5 years ago