All Projects → ricokahler → flair

ricokahler / flair

Licence: MIT license
a lean, component-centric style system for React components

Programming Languages

javascript
184084 projects - #8 most used programming language
typescript
32286 projects
CSS
56736 projects
HTML
75241 projects

Projects that are alternatives of or similar to flair

Styled System
⬢ Style props for rapid UI development
Stars: ✭ 7,126 (+37405.26%)
Mutual labels:  css-in-js, theming
Style9
CSS-in-JS compiler inspired by Facebook's stylex
Stars: ✭ 314 (+1552.63%)
Mutual labels:  babel-plugin, css-in-js
adonis
Adonis ❤️ Aphrodite
Stars: ✭ 44 (+131.58%)
Mutual labels:  css-in-js, theming
Babel Plugin Tailwind Components
Use Tailwind with any CSS-in-JS library
Stars: ✭ 320 (+1584.21%)
Mutual labels:  babel-plugin, css-in-js
Compiled
A familiar and performant compile time CSS-in-JS library for React.
Stars: ✭ 1,235 (+6400%)
Mutual labels:  babel-plugin, css-in-js
Xwind
Tailwind CSS as a templating language in JS and CSS-in-JS
Stars: ✭ 249 (+1210.53%)
Mutual labels:  babel-plugin, css-in-js
Styled Theming
Create themes for your app using styled-components
Stars: ✭ 1,067 (+5515.79%)
Mutual labels:  css-in-js, theming
Postjss
Use the power of PostCSS in compiling with JSS
Stars: ✭ 40 (+110.53%)
Mutual labels:  babel-plugin, css-in-js
Snackui
SnackUI 🍑 - the final React style library. With an *optimizing compiler* that lets you write views naturally, with easier DX, working on native and web at once, all while being faster than hand-rolling your own CSS.
Stars: ✭ 55 (+189.47%)
Mutual labels:  babel-plugin, css-in-js
Emotion
👩‍🎤 CSS-in-JS library designed for high performance style composition
Stars: ✭ 14,177 (+74515.79%)
Mutual labels:  babel-plugin, css-in-js
tsstyled
A small, fast, and simple CSS-in-JS solution for React.
Stars: ✭ 52 (+173.68%)
Mutual labels:  css-in-js, theming
visage
Visage design system
Stars: ✭ 12 (-36.84%)
Mutual labels:  css-in-js
babel-plugin-inline-svg
Babel plugin to optimise and inline svg
Stars: ✭ 50 (+163.16%)
Mutual labels:  babel-plugin
babel-plugin-transform-hoist-nested-functions
Babel plugin to move nested functions to outer scopes
Stars: ✭ 32 (+68.42%)
Mutual labels:  babel-plugin
sprockets-bumble d
Sprockets plugin to transpile modern javascript using Babel, useful while migrating to ES6 modules
Stars: ✭ 32 (+68.42%)
Mutual labels:  babel-plugin
boss-lite
Boss Lite - React Redux Material Admin Template
Stars: ✭ 148 (+678.95%)
Mutual labels:  css-in-js
css-render
Generating CSS using JS with considerable flexibility and extensibility, at both server side and client side.
Stars: ✭ 137 (+621.05%)
Mutual labels:  css-in-js
Theming-Android
Examples and tips on how to support multiple themes within your app
Stars: ✭ 40 (+110.53%)
Mutual labels:  theming
Holi
Holi is a lightweight Jetpack Compose library of colors, gradients and cool utility functions for all your palette needs!
Stars: ✭ 160 (+742.11%)
Mutual labels:  theming
system-ui.com
Standards for creating consistent, interoperable user interfaces
Stars: ✭ 64 (+236.84%)
Mutual labels:  css-in-js

Flair

a lean, component-centric style system for React components

⚠️ This library is still in heavy development with the best features coming soon (development on hiatus)

Watch releases to be notified for new features.

Features

  • 🎣 hooks API
  • 👩‍🎨 theming
  • 🎨 advanced color context features including dark mode
  • 🧩 composable styles by default
  • 📦 small size, 7.3kB
  • 👩‍🎨 full color manipulation library included (colork2k) (no need for chroma-js or polished)
  • full TypeScript support and enhanced DX

Experimental features

The best features of this library are still in development:

  • static and extracted CSS similar to Linaria via a Babel Plugin (this will become the preferred way to use the library when stable)
  • SSR support
  • much smaller bundle 2.5kB
  • performance improvements

Requirements

  • React >16.8.0 (requires hooks)
  • No IE 11 support

Table of contents

Why another CSS-in-JS lib?

Glad you asked! See here for more info.

Installation

Install

npm i --save flair

Create your theme

flair's theming works by providing an object to all your components. This theme object should contain values to keep your app's styles consistent.

See theming usage for more info

// /src/theme.ts (or /src/theme.js)

const theme = {
  // see theming usage for more info
  colors: {
    brand: 'palevioletred',
    accent: 'peachpuff',
    surface: 'white',
  },
};

export default theme;

Provider installation

// index.ts (or index.js)
import React from 'react';
import { ThemeProvider, ColorContextProvider } from 'flair';
import { render } from 'react-dom';
import theme from './theme';
import App from './App';

const container = document.querySelector('#root');

render(
  <ThemeProvider theme={theme}>
    <ColorContextProvider
      color={theme.colors.accent}
      surface={theme.colors.surface}
    >
      <App />
    </ColorContextProvider>
  </ThemeProvider>,
  container,
);

Add type augments

If you're using typescript or an editor that supports the typescript language service (VS Code), you'll need to add one more file to configure the types and intellisense.

Place this file at the root of your project.

// /arguments.d.ts
import {
  StyleFnArgs,
  ReactComponent,
  StyleProps,
  GetComponentProps,
} from 'flair';

declare module 'flair' {
  // this should import your theme
  type Theme = typeof import('./src/theme').default;

  // provides an override type that includes the type for your theme
  export function useTheme(): Theme;

  // provides an override type that includes the type for your theme
  export function createStyles<Styles, ComponentType extends ReactComponent>(
    stylesFn: (args: StyleFnArgs<Theme>) => Styles,
  ): <Props extends StyleProps<Styles>>(
    props: Props,
    component?: ComponentType,
  ) => {
    Root: React.ComponentType<GetComponentProps<ComponentType>>;
    styles: { [P in keyof Styles]: string } & {
      cssVariableObject: { [key: string]: string };
    };
  } & Omit<Props, keyof StyleProps<any>>;
}

VS Code extension

If you're using VSCode, we recommend installing the vscode-styled-components by the styled-components team. This will add syntax highlighting for our style of CSS-in-JS.

Usage

Basic usage

// Card.tsx
import React from 'react';
import { createStyles, PropsFromStyles } from 'flair';

// `flair` works by creating a hook that intercepts your props
const useStyles = createStyles(({ css, theme }) => ({
  // here you return an object of styles
  root: css`
    padding: 1rem;
    background-color: peachpuff;
    /* you can pull in your theme like so */
    border-right: 5px solid ${theme.colors.brand};
  `,
  title: css`
    font-weight: bold;
    font-weight: 3rem;
    margin-bottom: 1rem;
  `,
  description: css`
    line-height: 1.5;
  `,
}));

// write your props like normal, just add the `extends…` like so:
interface Props extends PropsFromStyles<typeof useStyles> {
  title: React.ReactNode;
  description: React.ReactNode;
}

function Card(props: Props) {
  // `useStyles` intercepts your props
  const {
    // `Root` and `styles` are props added via `useStyles`
    Root,
    styles,
    // `title` and `description` are the props you defined
    title,
    description,
  } = useStyles(props, 'div' /* 👈 `div` is the default if you omit this */);

  return (
    // the `root` class is automatically applied to the `Root` component
    <Root
      onClick={() => {
        // you can supply any props you would send to the root component
        // (which is a `div` in this case)
      }}
    >
      {/* the styles that come back are class names */}
      <h2 className={styles.title}>{title}</h2>
      <p className={styles.description}>{description}</p>
    </Root>
  );
}

export default Card;

Composability

flair's styles are composable by default. This means that every style you write can be augmented because the style props className, style, and styles are automatically propagated to the subject Root component.

Building from the example above:

// Grid.tsx
import React from 'react';
import { createStyles, PropsFromStyles } from 'flair';
import Cart from './Card';

const useStyles = createStyles(({ css }) => ({
  root: css`
    display: grid;
    gap: 1rem;
    grid-template-columns: repeat(3, 1fr);
  `,
  card: css`
    box-shadow: 0 0 45px 0 rgba(0, 0, 0, 0.2);
  `,
  titleUnderlined: css`
    text-decoration: underlined;
  `,
}));

interface Props extends PropsFromStyles<typeof useStyles> {}

function Grid(props: Props) {
  const { Root, styles } = useStyles(props);

  return (
    <Root>
      <Card
        // augments the `root` class in the Card
        className={styles.card}
        styles={{
          // augments the `title` class in `Card`
          title: styles.titleUnderlined,
        }}
        title="flair"
        description={
          <>a lean, component-centric style system for React components</>
        }
      />

      <Card
        className={styles.card}
        title="emotion"
        description={
          <>CSS-in-JS library designed for high performance style composition</>
        }
      />

      <Card
        className={styles.card}
        title="styled-components"
        description={
          <>
            Visual primitives for the component age. Use the best bits of ES6
            and CSS to style your apps without stress
          </>
        }
      />
    </Root>
  );
}

Dynamic coloring

Every component styled with flair supports dynamic coloring. This means you can pass the prop color to it and use that color when defining styles.

// passing the color prop
<Button color="red">My Red Button</Button>
// using the color prop to define styles
import React from 'react';
import { createStyles, PropsFromStyles } from 'flair';

// the `color` prop comes through here  👇
const useStyles = createStyles(({ css, color, surface }) => ({
  //                                           👆
  // additionally, there is another prop `surface` that hold the color of the
  // surface this component is on currently. this is usually black for dark mode
  // and white for non-dark modes
  root: css`
    border: 1px solid ${color.decorative};
    background-color: ${surface};
    color: ${color.readable};
  `,
}));

interface Props extends PropsFromStyles<typeof useStyles> {
  children: React.ReactNode;
  onClick: () => void;
}

function Button(props: Props) {
  const { Root, children, onClick } = useStyles(props, 'children');
  return <Root onClick={onClick}>{children}</Root>;
}

export default Button;

See this demo in CodeSandbox

Color system usage

flair ships with a simple yet robust color system. You can wrap your components in ColorContextProviders to give your components context for what color they should expect to be on top of. This works well when supporting dark mode.

See here for a full demo of color context.

Theming usage

Theming in flair is implemented as one object that will be available to all your components in the app. You can use this object to store values to make your app's styles consistent. We recommend referring to material-ui's theme object for idea on how to define your own theme's shape.

Wrap your App in a ThemeProvider and give that ThemeProvider a theme object.

After your wrap in a theme provider, you can access the theme via the args in createStyles:

//                                     👇👇👇
const useStyles = createStyles(({ css, theme }) => ({
  root: css`
    color: ${theme.colors.brand};
  `,
}));

And inside your component. You can access the theme via useTheme()

function Component(props: Props) {
  const theme = useTheme();

  // ...
}

Implementations

This repo has two implementations that are better suited for different environments/setups.

Both implementations share the exact same API and even use the same import (the SSR version rewrites the imports via the babel plugin).

In general, the standalone implementation is easier to get started with, works in more environments, and is currently much more stable than the SSR counterpart.

With the existence of both versions, you can get started using the standalone version and optimize later with the SSR version.

Feature @flair/standalone @flair/ssr
Works standalone without any babel plugins or webpack loaders (for create-react-app support) 🔴
Zero config 🔴
Faster, static CSS 🚀 🔴
Extracts CSS from JS bundle 🔴
Stability 👍 beta 🤔 experimental
Bundle size 7.3kB 🤷‍♀️ 2.5kB 😎
Theming
Dynamic coloring
Same lean API 😎 😎

How does this all work?

See the architecture docs for more info.

Enabling the experimental SSR mode (@flair/ssr)

⚠️ In order to get this to work, you need to be able to freely configure babel and webpack. This is currently not possible with create-react-app.

Configure babel

Create or modify your .babelrc configuration file at the root of your folder.

{
  "presets": [
    // ...rest of your presets
  ],
  "plugins": [
    // ...rest of your plugins
    [
      "@flair/plugin",
      {
        // this is the theme file. refer to here:
        // https://github.com/ricokahler/flair#create-your-theme
        "themePath": "./src/styles/theme.js"
      }
    ]
  ]
}

Note: You do not need to change your imports. The babel plugin @flair/plugin will re-write your imports to use the @flair/ssr package

Configure Webpack

In your webpack config, create a new rule for .rss-css files and include the @flair/loader in the chain.

module.exports = {
  // ...
  module: {
    // ...
    rules: [
      // ...
      {
        test: /\.rss-css$/,
        use: [
          'style-loader', // you can use the mini-css-extract-plugin instead too
          {
            loader: 'css-loader',
            options: { importLoaders: 2 },
          },
          // flair loader must be last
          '@flair/loader',
        ],
        include: [
          require.resolve('@flair/loader/load.rss-css'),
          // ...
        ],
      },
    ],
  },
};

Credits

Big thanks to @lepture for the name flair ❤️

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].