npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

react-styled-factory

v0.0.9

Published

Abstract utility for creating typesafe styled [React](https://reactjs.org/) components without having to do the type and props wiring. Intended (but not limited) to be used together with a css compiler like [vanilla-extract](https://vanilla-extract.style)

Downloads

53

Readme

react-styled-factory

Abstract utility for creating typesafe styled React components without having to do the type and props wiring. Intended (but not limited) to be used together with a css compiler like vanilla-extract.

Try it on StackBlitz

Heads up: This package does not follow semantic versioning. Changes of all types are released to the patch portion of the version string.

Defining components

Use the provided factory to create a styled function that you will use to create react components.

import { createStyledFactory } from "react-styled-factory";

export const styled = createStyledFactory();

Use the styled function to produce a React component:

import { styled } from "./styled";

const Component = styled("div");

<Component style={{ color: "red" }} data-foo="123">
  Hello World
</Component>; // <div style="color: red;" data-foo="123">Hello World</div>

Custom components can be used as well:

import { HTMLAttributes } from "react";

function Impl(props: HTMLAttributes<HTMLSpanElement>) {
  return <span {...props} />;
}

const Component = styled(Impl);

<Component>Foo</Component>; // <span>Foo</span>

(Optional) Provide an sx compiler (i.e. @vanilla-extract/sprinkles) to the factory if you want to enable the sx prop on all components:

// styled.ts
import { createStyledFactory } from "react-styled-factory";
import { sprinkles } from "./styles.css.ts";

export const styled = createStyledFactory(sprinkles);

// Component.tsx
import { styled } from "./styled";

const Component = styled("div");

<Component sx={{ color: "primary", pt: "large" }} />;
// <div class="color-red padding-top-large"></div>

(Optional) When using an sx compiler you can also specify the sx value as the default style:

// styled.ts
import { createStyledFactory } from "react-styled-factory";
import { sprinkles } from "./styles.css.ts";

export const styled = createStyledFactory(sprinkles);

// Component.tsx
import { styled } from "./styled";

const Component = styled("div", { color: "primary", pt: "large" });

<Component />; // <div class="color-red padding-top-large"></div>

Styling components

Provide a variants compiler (i.e. @vanilla-extract/recipes) to automatically convert variant props to class names:

// styles.css.ts
import { recipe } from "@vanilla-extract/recipes";

export const myRecipe = recipe({
  variants: {
    size: {
      small: { fontSize: "10px" },
      large: { fontSize: "20px" },
    },
    color: {
      primary: { color: "blue" },
      secondary: { color: "red" },
    },
  },
});

// Component.tsx
import { myRecipe } from "./styles.css.ts";

const Component = styled("div", myRecipe);

<Component size="large" color="primary" />;
// <div class="size-large color-primary"></div>

You can also pass in plain class names for simpler components:

const Component = styled("div", "my-css-class");

<Component />; // <div class="my-css-class"></div>

Which integrates well with i.e. @vanilla-extract/css:

// styles.css.ts
import { style } from "@vanilla-extract/css";

export const myClass = style({ color: "red" });

// Component.tsx
import { myClass } from "./styles.css.ts";

const Component = styled("div", myClass);

Composing components

Styled components support merging with the immediate child:

const Component = styled("div", "my-css-class");

<Component asChild>
  <span>Hello World</span>
</Component>; // <span class="my-css-class">Hello World</span>

You can also produce a new component, identical but with the inner component changed:

// Component.tsx
export const Component = styled("div", "my-css-class");

// NewComponent.tsx
import { Component } from "./Component";

const NewComponent = Component.as("span");

<NewComponent />; // <span class="my-css-class"></span>

You can embed default props by using the attrs function:

const Component = styled("div").attrs({ role: "button" });

<Component />; //  <div role="button"></span>
<Component role="alert" />; // <div role="alert"></span>

By default, variant props will be filtered and not passed to the inner component. You can override this behavior by using shouldForwardProp:

// Dialog.css.ts
import { recipe } from "@vanilla-extract/recipes";

export const dialogRecipe = recipe({
  base: {
    transition: "opacity 0.3s",
  },
  variants: {
    open: {
      true: { opacity: 1 },
      false: { opacity: 0 },
    },
  },
});

// Dialog.tsx
import { dialogRecipe } from "./Dialog.css.ts";

const Dialog1 = styled("dialog", dialogRecipe);

// "open" will be interpreted and generate a class,
// but will not be passed to the inner component
<Dialog1 open />; // <dialog class="open-true"></dialog>

const Dialog2 = styled("dialog", dialogRecipe).shouldForwardProp(
  ({ name, isVariant }) => !isVariant || name == "open",
);

// Here "open" will be both used to generate a class
// and be passed to the inner component
<Dialog2 open />; // <dialog class="open-true" open></dialog>