GithubHelp home page GithubHelp logo

system-props / system-props Goto Github PK

View Code? Open in Web Editor NEW
81.0 5.0 9.0 64.26 MB

Responsive, theme-based style props for building design systems with React. Written in TypeScript.

Home Page: https://system-props.com

License: MIT License

TypeScript 98.74% JavaScript 0.93% HTML 0.33%
styled-system css-in-js design-system style-props tokens theming design-tokens styled-components emotion css

system-props's Introduction

System Props

Responsive, theme-based style props for building design systems with React. https://system-props.com

Version size MIT License

yarn add system-props

Features

Functions almost identically to styled-system, but adds the following features:

  • Written in TypeScript
  • Chakra's PseudoBox inspired pseudo selector props
  • Access the theme object at any time by using the function syntax
  • Supports common themed shorthand properties, like border, margin, padding, and box-shadow
  • Strict mode: allow only values that are present in the theme
  • Visually distinguish theme values by prefixing system prop values with $

Quick Start

See the example project in this repo for a more complete example.

import { createSystem, color, space } from 'system-props';
import styled, { ThemeProvider } from 'styled-components';

const theme = {
  space: ['0px', '4px', '8px', '16px', '32px'],
  colors: {
    blue100: 'lightblue',
    blue200: 'blue',
    //...etc
  },
};

const system = createSystem({
  strict, // default: false
  pseudoSelectors, // default: { _hover: '&:hover', ...etc }
});

const Box = styled.div(system({ ...color, ...space }));

const App = () => {
  return (
    <ThemeProvider theme={theme}>
      <Box
        bg="$blue500"
        margin="$1 $2 $3 $4"
        border="1px solid $blue200"
        borderBottom={(theme) => `3px dotted ${theme.colors.blue200}`}
        _hover={{
          bg: '$blue700',
        }}
      />
    </ThemeProvider>
  );
};

Credits

Many of the concepts here come from so many great, existing open-source projects, and they deserve a shout-out!

system-props's People

Contributors

dependabot[bot] avatar hamlim avatar kbondanza avatar kerumen avatar roginfarrer avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

system-props's Issues

Variants

Is there a way to define variants like in styled-system?

export const Text = styled.p<Props>(
	{
		boxSizing: 'border-box',
	},
	variant({
		scale: 'textStyles',
		prop: 'variant',
		// Trigger the new styled-system variants API
		// Actual variant to be defined in site-specific themes
		variants: { _: {} },
	}),
	space,
	layout,
	typography,
	color,
	border,
	shadow
);

So you could define multiple props in the theme file:

const theme = {
	textStyles: {
		base: {
			color: 'base',
			fontFamily: 'base',
			fontWeight: 'base',
			lineHeight: 'base',
			letterSpacing: 'base',
			fontSize: 'm',
		},
		large: {
			color: 'base',
			fontFamily: 'base',
			fontWeight: 'base',
			lineHeight: 'base',
			letterSpacing: 'base',
			fontSize: 'l',
		},
	},
}

And use the component like this:

<Text variant="large">Hello</Text>

Bug with PropConfig types

  Property 'fontSmoothing' is incompatible with index signature.
    Type '{ readonly property: "-webkit-font-smoothing"; }' is not assignable to type 'true | PropertyConfig'.

re-creation:

const system = createSystem();

system({
  fontSmoothing: {
    property: '-webkit-font-smoothing'
  }
})

Skip undefined values for props

First of all, thanks for the fork! I enjoy using it instead of styled-system.

I have an issue when I want to display my component in Storybook because it sets all props of the component to undefined (I guess it's needed for the UI, to display the controls? I'm not sure).

Anyway, I want to render a Box (<Box paddingX={2} />) but Storybook sets paddingLeft, paddingRight, etc to undefined which overwrites the paddingX. Is it possible to ignore undefined values when parsing the props?

A fix was proposed to styled-system (PR here) but I don't have enough time to dig into your code and propose the same fix.

πŸ—ΊοΈ Roadmap to 1.0

  • Fix TypeScript types for system props usage on components
  • Complete documentation website
    • Comparison to styled-system
    • When, why, and how to use $ syntax
    • Theme specification

Export css function

Add support to do something like:

<Box
  css={{
    '&:hover': {
      backgroundColor: '$blue400'
    }
  }}
/>

Types aren't allowing nested styles

When trying to use nested selectors, I get a type error.

Example CSS:

const styles: CSSFunctionArgs<"prefix"> = {
  backgroundColor: "tomato",
  padding: "1rem",
  "&:hover": {
    backgroundColor: "crimson"
  },
  "&[role='button']": {
    "&:hover": {
      backgroundColor: "rebeccapurple"
    }
  }
};

Type error:

Type '{ backgroundColor: "tomato"; padding: "1rem"; "&:hover": { backgroundColor: "crimson"; }; "&[role='button']": { "&:hover": { backgroundColor: "rebeccapurple"; }; }; }' is not assignable to type 'CSSFunctionArgs<"prefix">'.
  Type '{ backgroundColor: "tomato"; padding: "1rem"; "&:hover": { backgroundColor: "crimson"; }; "&[role='button']": { "&:hover": { backgroundColor: "rebeccapurple"; }; }; }' is not assignable to type 'CSSObject<"prefix", Theme>'.
    Type '{ backgroundColor: "tomato"; padding: "1rem"; "&:hover": { backgroundColor: "crimson"; }; "&[role='button']": { "&:hover": { backgroundColor: "rebeccapurple"; }; }; }' is not assignable to type '{ [k: string]: string | number | InternalCss<"prefix", Theme> | undefined; }'.
      Property '"&[role='button']"' is incompatible with index signature.
        Type '{ "&:hover": { backgroundColor: "rebeccapurple"; }; }' is not assignable to type 'string | number | InternalCss<"prefix", Theme> | undefined'.
          Type '{ "&:hover": { backgroundColor: "rebeccapurple"; }; }' has no properties in common with type 'InternalCss<"prefix", Theme>'.ts(2322)

The type error disappear if a property is added to the nested selector

const styles: CSSFunctionArgs<"prefix"> = {
  backgroundColor: "tomato",
  padding: "1rem",
  "&:hover": {
    backgroundColor: "crimson"
  },
  "&[role='button']": {
     backgroundColor: "limegreen"
    "&:hover": {
      backgroundColor: "rebeccapurple"
    }
  }
};

And if a other property is nested, I still got a type error

const nestedStyles: CSSFunctionArgs<"prefix"> = {
  backgroundColor: "tomato",
  padding: "1rem",
  "&[role='button']": {
    backgroundColor: "limegreen",
    "&:hover": {
      backgroundColor: "slateblue",
      "&::after": {
        content: '"content"',
        paddingInline: "1rem"
      }
    }
  }
};
Type '{ backgroundColor: "slateblue"; "&::after": { content: string; paddingInline: string; }; }' is not assignable to type 'string | number | InternalCss<"prefix", Theme> | undefined'.
  Object literal may only specify known properties, and '"&::after"' does not exist in type 'InternalCss<"prefix", Theme>'.ts(2322)

Here's a codesandbox with some tests
https://codesandbox.io/s/system-props-nested-css-9dxigb

Strict Mode Types

That's a good idea! On that subject, would it be possible to validate strict mode with TypeScript?

I mean, if I don't have a red color in my theme and I'm passing color="red", TS should raise an error.

Originally posted by @Kerumen in #53 (comment)

TypeScript error for number props since v0.19

Since latest release v0.19 it's not possible to write marginLeft={2} anymore. We get a TS error:

Type '2' is not assignable to type 'SystemProp<MarginLeft<0 | (string & {})>> | undefined'.

Discussion: Supporting CSS variables / custom properties

Opening this issue as a discussion on how the system-props package could support generating CSS variables / custom properties - I haven't given this much thought yet but wanted to jot down a few initial ideas!

My first concept was around aligning on defining a theme object that uses the var(--X) references as theme values, e.g.:

let theme = {
  colors: {
    primary: `var(--primary)`
  }
};

(essentially what the early versions of this package was doing [has since been updated however]).

However this could be less than ideal for a few reasons:

  • It's clunky / non-standard currently
  • If you need to read the underlying value of the var (e.g. to compute contrast), you need to do some weird logic
    • This is even worse than less than ideal because it won't work in non-browser environments!

The benefits however here being that it should _just work_ℒ️ out of the box!

My second idea (and something I'm tinkering with a bit) is to enable dependency injection and allow consumers to provide their own get function to createSystem which can be used in place of memoizedGet across the codebase. This is kind of clunky however, as developers may need to replicate a decent amount of logic possibly. Plus I'm sure there will be some edge cases that need to be accounted for (e.g. get used in places that you don't want to return a CSS variable for).

Maybe get is the wrong "unit" to expose and allow for this change however, maybe a new transform codepath can get introduced that gets called with:

  • value (the result of resolving the prop value against theme, e.g. after get(...)
  • theme
  • path
  • prop name (maybe?)
  • scale
  • ... more?

and is expected to return the raw css value generated. This could default to essentially a pass through:

function defaultTransform(
  value: string,
/*
  theme: any,
  path: string,
  propName: string,
  scale: string,
  ...
*/
): string {
  return value;
}

Again, this is all sort of top of mind, thinking out loud on supporting CSS variables within system-props, curious if anyone else has other interesting ideas!

`_disabled` attribute is not working

In its current form, the _disabled pseudo selector is not working. It generates a class .hash [disabled] targeting the descendant element and not the disabled one.

To fix it, we should change it to

_disabled: '&[disabled], &[disabled]:hover, &[disabled]:focus, &[aria-disabled], &[aria-disabled]:hover, &[aria-disabled]:focus',

I don't know if you want me to open the PR? I can do it, and we should also add a test to ensure everything is working as intended.

Access theme tokens from 'complex' background values

Add support for accessing theme tokens when using more complex background values (gradients, multiple backgrounds, etc). It works fine for simple background colors.

// βœ…
background="$color1"
// ❌
background="linear-gradient(direction, $color1, $color2 75%, $color3)"

Currently the raw string will be output as invalid CSS, but it should output the transformed token values. Note: This behavior can be accomplished with the function syntax, but it would be great to support both!

background={theme => `linear-gradient(direction, ${theme.colors.color1}, ${theme.colors.color2} 75%, ${theme.colors.color3})`}

See https://codesandbox.io/s/system-props-gradient-y3mou?file=/index.tsx for example case.

Add transition + animation prop group

Add prop group that supports animation and transition CSS properties, and ties to the theme.

animation and transition should have shorthand parsers.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.