React visual primitives with first-class TypeScript support and a tiny footprint.

Last update: Apr 7, 2022

tsstyled

homepage bundle size github stars npm version build status coverage status

React visual primitives with first-class TypeScript support and a tiny footprint.

TL;DR: This library is a styled-components rewrite that is smaller, simpler, with stronger TypeScript types.

Getting Started

Installation

Install the tsstyled package and its react peer dependency.

# With NPM
npm i tsstyled react

# With Yarn
yarn add tsstyled react

This library uses semantic versioning. Breaking changes will only be introduced in major version updates.

Compatibility

  • React >= 16.14.0
  • TypeScript >= 4.2.4
  • IE >= 11

Community

Do you have questions, suggestions, or issues? Join the Discord server!

Motivation

The styled-components library is incredibly popular. The "visual primitives" pattern (ie. atomic components with styles included as code), combined with tagged templates, make it powerful and an easy transition from CSS/SCSS.

However, it was created many years ago, well before TypeScript had gained the popularity it has now. Types have now been added by the community. But, the API wasn't designed with types in mind, and some of the design choices are just not compatible with strong typing.

This library is a rewrite which keeps the key features, cleans up the design for TypeScript, and removes some unnecessary and counter productive "features". It also completely removes any dependence on third party libraries, and is about 1/3rd the size.

The problem(s) with styled-components

There are many relatively small but definite problems with the styled-components types, which are not fixable given the current design.
  • Type errors are surfaced late, when you try to use the component, not when you using the styled function, attrs method, or the tagged template.
  • It is possible to set the generics in ways that allow prop values to be assign without type errors, that will result in runtime errors.
  • You can only add new props to a component's props type (not remove them).
  • The types are messy, hard to parse, and break some type utilities (React.ComponentProps)
  • Setting generic types explicitly is hard to get right, because some orders of operation are reversed, and the type intersections are not the best solution for combining them.
  • Theme typing is fragile, because it relies on declaration merging which doesn't always seem to work as intended. More importantly, using declaration merging locks all components into sharing a common theme type.
  • See also the DefinitlyTyped bugs for styled-components.
Philosophically, the styled-components "re-styling" capability is too powerful. It can invalidate assumptions made by the originally styled component.
  • The as property is allowed to change the base component to anything. This is lazy and incompatible with good design. If you want to implement your own component with an as property, that’s completely fine, because you designed it that way. But having it automatically added to every styled component opens up too many uncertainties, and paves the way for a fragile component hierarchy.
  • The order of applying attrs is reversed. This is the opposite of standard component design. In vanilla React, if you wrap a component with another component, the outer component now controls what reaches the inner component, which is a good thing. If you restyle (wrap) an already styled component, the restyle gets to reach around the inner styled component and apply properties directly to the base component. This is fragile because you are modifying internal behaviors that you don't have visibility on or control over.

All of this means that when styling a component, you can’t assume you’re styling the component you think you are, you don’t really know what props will be passed to you, and your props might not be passed to the base component.

Moving from styled-components

Most styled-components capabilities (basic and advanced) are supported, with some notable differences and omissions.
  • The styled.div syntax is not supported (only styled('div')).
  • The attrs method is replaced by props, which can only be used once as the first chained method call after styled, and it is applied in the intuitive (ie. functional) order when restyling (instead of the reverse order used by attrs).
  • The template function returned by the styled function is not generic, because the props method is the only way to set the styled component's properties.
  • The use, set, and map functions have been added to support stronger typing when manipulating property values, and they are also applied in the intuitive order like props (instead of the reverse order used by attrs).
  • The style object syntax is not supported, to keep the library size down, and because tagged templates provide a better developer experience overall.
  • The as polymorphic prop is not supported, because it does not fit the philosophy of this library.
  • The attributes passed through to simple HTML elements (eg. div) are not filtered based on known HTML attributes, but instead are filtered based on the following rules:
    1. Props that start with $ are always filtered out.
    2. The style, children, and ref props are never filtered out.
    3. Function props are filtered out unless the prop name starts with on.
    4. All other non-primitive (string, number, boolean) props are filtered out.
  • The component selector pattern only works when a component is given an explicit display name, because making every component selectable adds transfer size to the SSR output, and requiring a name can mitigate some potential SSR vs client rendering order gotchas.
  • The API is similar enough to the styled-components API for the vscode-styled-components plugin to provide syntax support.
  • No theme is automatically injected into styled component props, because custom themes can be manually injected by using a theme hook with the use method.
  • No keyframes utility is included, because the @keyframes at-rule can be used in any styled template string, and the getId utility can be used if animation name collisions are a concern.
  • No createGlobalStyle utility is included, because global styles can be created by calling styled('style') which produces a global style component.
  • No automatic vendor prefixing is performed, to keep library size and complexity down, and because it's unnecessary for most common styling scenarios.

The Basics

Style HTML elements

Use string tag names to create simple HTML elements with styling. The styled component supports all of the same props (included refs) that the HTML element supports.

import { styled } from 'tsstyled';

const StyledDiv = styled('div')`
  color: red;
`;

Style React components

Any component which accepts a className prop can be styled, just like an HTML tag. The styled component supports all of the same props (including refs) that the base component supports.

const Base = (props: { className?: string }): ReactElement => {
  return <div className={props.className}>Foo</div>;
};
const StyledBase = styled(Base)`
  color: red;
`;

Override component props type

When you style an HTML element or a React component, the new styled component has the exact same props as the original component by default. You can override that default by using the generic props method to set a custom props type.

NOTE: The props method must always be the first styled method called, and it can only be used once per styled component.

The simplest case is a props type which extends the base props type. New props can be added, prop values can be narrowed, and optional props can be removed.

const StyledDiv = styled('div').props<{
    // Add a new prop.
    $color?: string;
    // Narrow the value type of a prop.
    className?: 'foo' | 'bar';
    // Remove an optional prop by narrowing the type to undefined.
    style: undefined;
  }>()`
    color: ${(props) => props.$color};
  `;

The styled component above accepts all of the intrinsic div props, except style which has been removed, and the className only accepts the values foo or bar. It also accepts an extra non-standard $color prop. Be sure to include the $ prefix if you want keep a property from being passed to the base HTML element as an attribute.

If you don't want to extend the base props, you can set the extend option to false.

interface IStyledDivExtraProps {
  color?: string;
}

const StyledDiv = styled('div').props<{ $color?: string }>({ extend: false })`
  color: ${(props) => props.$color};
`;

Now the styled component only accepts the $color prop, and no other props.

If your custom props type is not "compatible" with the base component, then a mapping function to create props compatible with the base component is required. Compatible means that the new styled component props can be passed directly to the base component without modification. Changing a prop value type (eg. string to string[]), and removing a required prop, are examples of incompatible changes.

interface IStyledDivProps {
  // The standard className can only be a string. Allowing a string
  // array makes this incompatible with the base component (div)
  // props.
  className?: string | string[];
}

const StyledDiv = styled('div').props((props: IStyleDivProps) => ({
  // This mapping function is required to convert an incompatible
  // array class name back to a string which is compatible with the
  // div.
  className: props.className instanceof Array ? props.join(' ') : props.className
}))``;

Using the props with a callback does not extend the base props. So, the above styled component now only supports the className prop, and no other props. To keep any of the base component props, include them manually in your custom props type. The InferProps type utility can be used to access the properties of any HTML element or React component.

import { InferProps } from 'tsstyled';

interface IStyledDivProps extends Omit<InferProps<'div'>, 'className'> {
  className?: string | string[];
}

Provide default prop values

Default prop values can be provided for undefined props with the use method. Props returned by the callback will only be set if the current prop value is undefined. This method is an alternative to using the map method with Object.assign({}, defaultProps, props) or { ...defaultProps, ...props }, which allows explicitly undefined props to overwrite and hide default props.

const StyledDiv = styled('div').use((props) => ({
  // Use the component ID as the default class name.
  className: props.id,
}))`
  color: red;
`;

Add or update prop values

Prop values can be added and modified (but not removed or set to undefined) with the set method. Props returned by the callback will be set as long as the new value is defined. This method is an alternative to using the map method with Object.assign({}, props, newProps) or { ...props, ...newProps }, which can allow explicitly undefined new prop values to overwrite and hide defined prop values.

const StyledDiv = styled('div').set((props) => ({
  // Add a prefix to the existing class name.
  className: props.className && `prefix-${props.className}`,
}))`
  color: red;
`;

Map prop values

Prop values can be completely rewritten using the map method. Props returned by the callback replace the current props without condition.

NOTE: Please give preference to the use and set methods. They provide better type support for their respective scenarios. Only use map when you need to remove properties from the current props object.

const StyledDiv = styled('div').map((props) => ({
  id: props.id,
  className: props.className,
  children: props.children,
  // Props that are not returned, are removed.
}))`
  color: red;
`;

Global styles

A global stylesheet can be added by styling a style component.

const GlobalStyle = styled('style')`
  body, html {
    margin: 0;
    padding: 0;
  }
`;

render(
  <>
    <GlobalStyle />
    <div>Page content</div>
  </>
);

Keyframes and fonts

Defining keyframes or font-faces is the same as defining any other style. Since they are not scoped to any particular component, you may want to limit them to global styles, but they will work in any style. If you are concerned about names colliding, you can use the getId utility to generate unique names.

import { styled, getId } from 'tsstyled';

const openSans = getId('Open Sans');
const slideIn = getId('slideIn');

const GlobalStyle = styled('style')`
  @font-face {
    font-family: ${openSans};
    src: url("/fonts/OpenSans-Regular-webfont.woff2") format("woff2"),
         url("/fonts/OpenSans-Regular-webfont.woff") format("woff");
  }

  @keyframes ${slideIn} {
    from {
      transform: translateX(0%);
    }

    to {
      transform: translateX(100%);
    }
  }
`;

const StyledDiv = styled('div')`
  font-family: ${openSans};
  animation-name: ${slideIn};
`;

Theming

Styled components created with tsstyled are not theme aware by default, and there is no default theme type or values. However, theming is trivial to setup, and requiring the extra setup makes it easier to support third party theme integration.

Create a theme

Themes are just values made available via a React context, and preferably using a React hook. The createTheme utility is provided to make that a one step process. It accepts the default theme value, and returns a theme hook function and provider component.

import { createTheme } from 'tsstyled';

const [useTheme, ThemeProvider] = createTheme({
  foregroundColor: black;
  backgroundColor: white;
});

// The theme type can be inferred from the hook's return type.
type Theme = ReturnType<typeof useTheme>;

Use a theme

Themes can be integrated via React hooks in the props, use, set, or map method callbacks. Actually, any hook can be used in these callbacks (not just theme hooks) as long as hooks are not called conditionally. The recommended approach is to have hooks provide default values by calling them in a use method callback.

const ThemedDiv = styled('div').use(() => ({
  theme: useTheme(),
}))`
  color: ${(props) => props.theme.foregroundColor};
  background: ${(props) => props.theme.backgroundColor};
`;

Override theme values

The provider returned by the createTheme utility allows the theme to be overridden for part of your React tree. It's not necessary to use the provider unless you want to override theme values.

const ThemeInvertedProvider = (props: { children?: ReactNode }) => {
  return (
    <ThemeProvider
      value={(current) => ({
        foregroundColor: current.backgroundColor,
        backgroundColor: current.foregroundColor,
      })}
    >
      {children}
    </ThemeProvider>
  );
};

render(
  <ThemeInvertedProvider>
    <ThemedDiv>Greetings from the dark side.</ThemedDiv>
  </ThemeInvertedProvider>
);

Style syntax

Style syntax is CSS-like, and all CSS properties, selectors, and at-rules are supported. In addition, SCSS-like nesting is supported with parent selector references (&).

Simple CSS

If you just want to style one element, use CSS properties at the top-level (no surrounding block).

const StyledDiv = styled('div')`
  color: red;
`;

These CSS properties will be wrapped in a block with a selector for the styled dynamic class.

._s7y13d {
  color: red;
}

Child selectors

You can use CSS selectors and blocks to style children of the styled component.

const StyledDiv = styled('div')`
  color: red;
  .child {
    color: blue;
  }
`

The styled dynamic class will be automatically prepended to all selectors to make them "scoped".

._s7y13d {
  color: red;
}
._s7y13d .child {
  color: blue;
}

Nesting

You can nest blocks to create more complex selectors.

const StyledDiv = styled('div')`
  color: red;
  .child {
    color: blue;
    .grandchild {
      color: green;
    }
  }
`;

Just like the styled dynamic class is prepended to top-level selectors, so too are parent selectors prepended to child selectors.

._s7y13d {
  color: red;
}
._s7y13d .child {
  color: blue;
}
._s7y13d .child .grandchild {
  color: green;
}

Parent selector references

As noted above, the parent selector is automatically prepended to child selectors. This behavior can be overridden by using a parent selector reference (&) to inject the parent selector anywhere in your child selector. This includes injecting the parent selector multiple times to increase specificity, and is necessary when using pseudo selectors like :hover which you will probably want to apply directly to the styled component instead of to its children.

const StyledDiv = styled('div')`
  && {
    color: red;
  }
  &:hover {
    color: blue;
  }
  .parent & {
    color: green;
  }
`

For any selector that contains an &, the parent selector will replace the & characters, and the parent selector will not be automatically prepended.

._s7y13d._s7y13d {
  color: red;
}
._s7y13d:hover {
  color: blue;
}
.parent ._s7y13d {
  color: green;
}

At-rules

All CSS at-rules are supported (except @charset which isn't allowed inside <style> tags). Conditional group rules (ie. @media and @supports) which can have nested selector blocks, can themselves be nested, and can have deeply nested child selectors which use parent selector references.

const StyledDiv = styled('div')`
  @media screen and (min-width: 900px) {
    color: red
  }
  .child {
    @media screen and (min-width: 600px) {
      .grandchild {
        color: blue;
        .adopted & {
          color: green;
        }
      }
    }
  }
`;

The at-rules will be hoisted as necessary, and parent selectors will be handled the same way they would be without the intervening at-rule.

@media screen and (min-width: 900px) {
  ._s7y13d {
    color: red;
  }
}
@media screen and (min-width: 600px) {
  ._s7y13d .child .grandchild {
    color: blue;
  }
  .adopted ._s7y13d .child .grandchild {
    color: green;
  }
}

Comments

Styles can contain both block (/* */) and line comments (//). Comments are never included in stylesheets.

const StyledDiv = styled('div')`
  // This is a comment.
  /* And so is...
     this. */
`;

Empty values

If a CSS property value is an empty string or null-ish (null, undefined), then the whole property will be omitted from the style.

const StyledDiv = styled('div')`
  color: ${null};
  background: red;
`;

The color property is not included because it has no value.

._s7y13d {
  background: red;
}

Style helpers

The css utility provides syntax support when defining independent styles which are not immediately applied to a component.

Static helpers

Static helpers are simple style strings. As long as the template doesn't include any function values, the css utility returns a string.

import { css, styled } from 'tsstyled';

const font: string = css`
  font-family: Arial, sans-serif;
  font-weight: 400;
  font-size: 1rem;
`;
// typeof font === 'string'

const StyledDiv = styled('div')`
  ${font}
  color: red;
`;

Dynamic helpers

Dynamic helpers are functions that return style strings. If the template includes any function values, the css utility returns a function instead of a string. The generic type defines the properties that your helper will accept.

const font = css<{ scale?: number }>`
  font-family: Arial, sans-serif;
  font-weight: 400;
  font-size: ${(props) => props.scale ?? 1}rem;
`;
// typeof font === 'function'

const StyledDiv = styled('div')`
  ${font({ scale: 2 })}
  color: red;
`;

Themed helpers

If you're using theming, you'll almost certainly need some of your helpers to use the theme. Themed helpers are just a specialized form of dynamic helper which accepts the theme as a prop. However, it's a good idea not to depend on the entire theme, only the values you need. This makes it easier to use the helper in the case where you don't have the theme, and just want to manually fill in the required theme values.

const font = css<{ theme: Pick<Theme, 'fontSize'> }>`
  font-family: Arial, sans-serif;
  font-weight: 400;
  font-size: ${(props) => props.theme.fontSize};
`;

const ThemedDiv = styled('div').use(() => ({ theme: useTheme() }))`
  ${font}
  color: red;
`;

// Or, if you can't use the theme for some reason.
const StyledDiv = styled('div')`
  ${font({ theme: { fontSize: '1rem' } })}
  color: red;
`;

Utilities

Detecting styled components

The isStyled and isStyledSelector functions can be used to detect components that have been styled. The isStyled method detects any styled component, while the isStyledSelector function only returns true for styled components that can be used as selectors.

import { isStyled, isStyledSelector } from 'tsstyled';

const StyledComp = styled('div')``;
const StyledCompAndSelector = styled('div', 'DisplayName')``;

isStyled(StyledComp); // true
isStyled(StyledCompAndSelector); // true
isStyledSelector(StyledComp); // false
isStyledSelector(StyledCompAndSelector); // true

Building a class name string

Joining multiple class names into a single string is a common problem. The classNames function takes possibly falsy class names, or maps of class names, and returns a clean class names string.

import { isStyled, isStyledSelector } from 'tsstyled';

const className = classNames('a', { b: true, c: false }, null); // "a b"

Server Side Rendering (SSR)

No configuration is required to make SSR work. When rendered without a browser context (ie. a document global), styles are rendered inline, before the first element that uses a style. On the client, tsstyled will pull the inlined styles into the document <head> before React rehydration occurs.

If the default SSR support using inlined styles doesn't work for your scenario, you can use the ServerStyleManager and the StyleConfig component to capture styles rendered during SSR.

import { ServerStyleManager, StyleConfig } from 'tsstyled';

const manager = new ServerStyleManager();
const html = renderToString(
  <StyleConfig serverManager={manager}>
    <App />
  </StyleConfig>
);
const styles = manager.getStyleTag();

The getStyleTag method returns an HTML string containing a single <style> tag. There is also a getStyleElement method that returns the same style as a React element, and a getStyleData method that returns an array of raw style data ({ key: string, cssText: string }).

Ecosystem

A list of some of the cool stuff built with tsstyled. If you have something to share, please create a GitHub PR to add it to this README file.

Websites

  • Your website here!

Packages

  • Your package here!

GitHub

https://github.com/Shakeskeyboarde/tsstyled
You might also like...

Imersão React.js 3º edição. Project using ReactJS, Next JS, and Styled Components for the week challenge by Alura. We created a social network inspired by Orkut.

Example app with styled-components This example features how you use a different styling solution than styled-jsx that also supports universal styles.

Jul 19, 2021

Dynamic Styles for React Native and Expo Web

Dynamic Styles for React Native and Expo Web

react-native-swag-styles Dynamic Styles for React Native and Expo Web Highlights Dynamic. Based on React Hook. It automatically re-renders when necess

May 17, 2022

CSS Maid 🧹 A tool made for React.js to clean up CSS default styling! Give your CSS a nice reset and style with less hassle!

CSS Maid 🧹 A tool made for React.js to clean up CSS default styling! Give your CSS a nice reset and style with less hassle!

CSS Maid 🧹 What is it? CSS Maid is a tool for React.js that helps clean up & reset default css! It resets default padding, remove text-decoration on

Sep 1, 2021

🏠 Airbnb website using React, Next.js and Tailwind CSS

🏠 Airbnb website using React, Next.js and Tailwind CSS

This example shows how to use Tailwind CSS (v2.2) with Next.js. It follows the steps outlined in the official Tailwind docs.

May 2, 2022

Minimal and performant React component library built on styled-components

Minimal and performant React component library built on styled-components

Jan 3, 2022

This repository allows you to create a React template component folder. It optionally includes scss and css files

Generate-React-Components - grc grc let you generate react components in typescript in a folder you specify and it will include .tsx, .scss, .css file

Nov 26, 2021

The simplest solution for content loading in React and styled-components.

styled-content-loader The simplest solution for content loading in React and styled-components. Getting Started npm install styled-components styled-c

Jul 13, 2021

A Simple Spinner and Loader Library for React

A Simple Spinner and Loader Library for React

React-Spinner A Simple Spinner and Loader Library Have a look How to use? The NPM package is not released yet. You can clone the project and try out t

May 21, 2022

Typograpy components for react and styled-components

Typograpy components for react and styled-components

styled-typography Typograpy components for react and styled-components styled-typography is a small set of components, using styled-components, to bet

May 1, 2022
Comments
  • 1. Use of the useTheme hook in the callback provided to use() breaks the rules of hooks according to eslint

    Pretty much the title. Calling the useTheme() hook from the callback provided to use() causes eslint to error, citing the Rules of Hooks.

    Additionally, creating a variable for the theme and referencing that variable in the use() function does not successfully update the theme when changed using the <ThemeProvider> component.

    Reviewed by AnthonyUtt at 2021-08-15 14:35
  • 2. Transitions not working

    I'm trying to set up a dark mode toggle in my project, but the transitions don't work when updating styles. If I manually go into DevTools and add/remove the relevant classes, the transitions work, but not when tsstyled is updating the classes. I've also tried implementing this using ThemeProvider and a "dark theme" but it seems tsstyled removes the classes before adding the new ones when the theme updates. Doesn't work when manually defining element styles for the component in use() either.

    After playing around in DevTools for a bit, it seems like all styles are being cleared from the component (including element styles) before the new styles are applied. Any thoughts on this would be greatly appreciated.

    Code below:

    Layout.tsx

    import React, { useState } from 'react';
    import { styled, classNames } from 'tsstyled';
    import './fonts.css';
    
    // Theme
    import { useTheme, useDarkTheme, ThemeProvider, GlobalStyles } from './theme';
    
    // Components
    import Head from './head';
    import DarkModeSwitch from './darkModeSwitch';
    
    interface LayoutProps {
        title: string;
        children?: React.ReactNode;
    }
    
    const Layout: React.FC<LayoutProps> = ({ title, children }) => {
        const [darkMode, setDarkMode] = useState(false);
        const darkTheme = useDarkTheme();
    
        const darkClass = classNames({ dark: darkMode });
    
        const LayoutContainer = styled('div').use(() => ({
            theme: useTheme(), // eslint-disable-line
        }))`
            position: relative;
            width: 100%;
            min-height: 100vh;
            background-color: ${props => props.theme.white};
            color: ${props => props.theme.charcoal};
            transition: background 1s ease-in-out, color 1s ease-in-out;
        `;
    
        const SwitchContainer = styled('div')`
            position: absolute;
            right: 0.5rem;
            top: 0.5rem;
            display: flex;
            justify-content: flex-end;
            align-items: center;
        `;
    
        const SwitchText = styled('p').use(() => ({
            theme: useTheme(), // eslint-disable-line
        }))`
            color: ${props => props.theme.lightFontColor};
            font-size: 1rem;
            margin: 0;
            padding: 0;
            margin-right: 0.5rem;
        `;
    
        return (
            <>
            <Head title={title} />
            <ThemeProvider
                value={current => {
                    if (!darkMode) {
                        return current;
                    }
                    return darkTheme;
                }}
            >
                <GlobalStyles />
                <LayoutContainer className={darkClass}>
                    <SwitchContainer>
                        <SwitchText>Dark Mode</SwitchText>
                        <DarkModeSwitch
                            initialState={darkMode}
                            stateChangeCallback={setDarkMode}
                        />
                    </SwitchContainer>
                    {children}
                </LayoutContainer>
            </ThemeProvider>
            </>
        );
    };
    
    export { useTheme };
    export default Layout;
    

    theme.ts

    import { createTheme, styled, css } from 'tsstyled';
    
    const colors = {
        darkBlue: '#173042',
        medBlue: '#236477',
        paleBlue: '#CFDFDA',
        medGreen: '#7CAD3E',
        darkGreen: '#4A6C2F',
        charcoal: '#333',
        paleGray: '#999',
        white: '#FFF',
        offWhite: '#E1E1E1',
    };
    
    const fonts = {
        copyFontFamily: `'Poppins', sans-serif`,
        accentFontFamily: `'Conthrax', sans-serif`,
    };
    
    const accentColor = colors.medBlue;
    
    const [useTheme, ThemeProvider] = createTheme({
        // Colors
        darkBlue: colors.darkBlue,
        medBlue: colors.medBlue,
        paleBlue: colors.paleBlue,
        medGreen: colors.medGreen,
        darkGreen: colors.darkGreen,
        charcoal: colors.charcoal,
        paleGray: colors.paleGray,
        white: colors.white,
        offWhite: colors.offWhite,
    
        accentColor,
    
        // Fonts
        accentFontFamily: fonts.accentFontFamily,
        accentFontWeight: 500,
        accentFontColor: accentColor,
    
        copyFontFamily: fonts.copyFontFamily,
        copyFontWeight: 300,
        copyFontColor: colors.charcoal,
    
        lightFontColor: colors.paleGray,
    });
    
    const [useDarkTheme] = createTheme({
        // Colors
        darkBlue: colors.darkBlue,
        medBlue: colors.medBlue,
        paleBlue: colors.paleBlue,
        medGreen: colors.medGreen,
        darkGreen: colors.darkGreen,
        charcoal: colors.charcoal,
        paleGray: colors.paleGray,
        white: colors.white,
        offWhite: colors.offWhite,
    
        accentColor,
    
        // Fonts
        accentFontFamily: fonts.accentFontFamily,
        accentFontWeight: 500,
        accentFontColor: accentColor,
    
        copyFontFamily: fonts.copyFontFamily,
        copyFontWeight: 300,
        copyFontColor: colors.white,
    
        lightFontColor: colors.paleGray,
    });
    
    const cssReset = css`
        /* http://meyerweb.com/eric/tools/css/reset/ 
        v2.0 | 20110126
        License: none (public domain)
        */
    
        html,
        body,
        div,
        span,
        applet,
        object,
        iframe,
        h1,
        h2,
        h3,
        h4,
        h5,
        h6,
        p,
        blockquote,
        pre,
        a,
        abbr,
        acronym,
        address,
        big,
        cite,
        code,
        del,
        dfn,
        em,
        img,
        ins,
        kbd,
        q,
        s,
        samp,
        small,
        strike,
        strong,
        sub,
        sup,
        tt,
        var,
        b,
        u,
        i,
        center,
        dl,
        dt,
        dd,
        ol,
        ul,
        li,
        fieldset,
        form,
        label,
        legend,
        table,
        caption,
        tbody,
        tfoot,
        thead,
        tr,
        th,
        td,
        article,
        aside,
        canvas,
        details,
        embed,
        figure,
        figcaption,
        footer,
        header,
        hgroup,
        menu,
        nav,
        output,
        ruby,
        section,
        summary,
        time,
        mark,
        audio,
        video {
            margin: 0;
            padding: 0;
            border: 0;
            font-size: 100%;
            font: inherit;
            vertical-align: baseline;
        }
        /* HTML5 display-role reset for older browsers */
        article,
        aside,
        details,
        figcaption,
        figure,
        footer,
        header,
        hgroup,
        menu,
        nav,
        section {
            display: block;
        }
        body {
            line-height: 1;
        }
        ol,
        ul {
            list-style: none;
        }
        blockquote,
        q {
            quotes: none;
        }
        blockquote:before,
        blockquote:after,
        q:before,
        q:after {
            content: '';
            content: none;
        }
        table {
            border-collapse: collapse;
            border-spacing: 0;
        }
    `;
    
    const GlobalStyles = styled('style').use(() => ({
        theme: useTheme(),
    }))`
        ${cssReset}
        :root {
            font-family: ${props => props.theme.copyFontFamily};
            font-weight: ${props => props.theme.copyFontWeight};
            color: ${props => props.theme.copyFontColor};
        }
    
        :root .dark {
            background-color: ${props => props.theme.charcoal};
            color: ${props => props.theme.white};
        }
    `;
    
    export { useTheme, useDarkTheme, ThemeProvider, GlobalStyles };
    
    Reviewed by AnthonyUtt at 2021-08-15 14:25
Seamless mapping of class names to CSS modules inside of React components.
Seamless mapping of class names to CSS modules inside of React components.

React CSS Modules React CSS Modules implement automatic mapping of CSS modules. Every CSS class is assigned a local-scoped identifier with a global un

Jun 19, 2022
Whirlwind is a utility-first styling framework specifically designed for React Native. It is heavily inspired by Tachyons and Tailwind CSS and uses low-level building blocks for rapidly building custom designs.

React Native Whirlwind ??️ A utility-first CSS framework designed for React Native. Whirlwind is a utility-first CSS framework specifically designed f

May 6, 2022
♞ JavaScript mobile-first chess.

♞ JavaScript mobile-first chess client. Play Documentation Changelog How does it work? The game state and the game view are separated. The view re-ren

May 23, 2022
Framework-agnostic CSS-in-JS with support for server-side rendering, browser prefixing, and minimum CSS generation

Aphrodite Framework-agnostic CSS-in-JS with support for server-side rendering, browser prefixing, and minimum CSS generation. Support for colocating y

Jun 19, 2022
A react component available on npm to easily link to your project on github and is made using React, TypeScript and styled-components.

fork-me-corner is a react component available on npm to easily link to your project on github and is made using React, TypeScript and styled-components.

Feb 27, 2022
💻 A Disney+ interface with React, TypeScript and consumption of a fake API with json-server
💻 A Disney+ interface with React, TypeScript and consumption of a fake API with json-server

?? A Disney+ interface with React, TypeScript and consumption of a fake API with json-server

May 18, 2022
TailwindCss plugin to export Typescript typings, helpers and const from your config.
TailwindCss plugin to export Typescript typings, helpers and const from your config.

Tailwind TS Generator ⚡️ Generate Tailwind type from your own configuration! This package is a Tailwindcss plugin that generates code out of your tail

Jun 14, 2022
Repositório utilizado na criação de um setup para facilitar o inicio do desenvolvimento de apps com React, Next e TypeScript. Só "clonar" e "codar"! hahaha

Template para desenvolvimento de projetos utilizando REACT e NEXT com TypeScript Como executar Clone o projeto e acesse a pasta do mesmo. $ git clone

Jan 7, 2022
Starter template for NextJs with TypeScript. Supports Tailwind with CSS-Modules
Starter template for NextJs with TypeScript. Supports Tailwind with CSS-Modules

Starter template for NextJs with TypeScript. Supports Tailwind with CSS-Modules. Jest and @react/testing-library configured and ready to go. Also ESLint, Prettier, Husky, Commit-lint and Atomic Design for components.

Jun 9, 2022
CSS media queries in react - for responsive design, and more.

react-responsive Information Package react-responsive Description Media queries in react for responsive design Browser Version >= IE6* Demo The best s

Jun 21, 2022