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

@phntms/css-components

v0.4.0

Published

At its core, css-components is a simple wrapper around standard CSS. It allows you to write your CSS how you wish then compose them into a component ready to be used in React.

Downloads

196

Readme

@phntms/css-components

NPM version Actions Status PR Welcome

A simple, lightweight, and customizable CSS components library that lets you wrap your css styles in a component-like structure. Inspired by css-in-js libraries like styled-components and stitches.

Introduction

At its core, css-components is a simple wrapper around standard CSS. It allows you to write your CSS how you wish then compose them into a component ready to be used in React.

Here is a minimal example of a button component with an optional variant:

import { styled } from "@phntms/css-components";
import css from "./styles.module.css";

export const Button = styled("button", {
  css: css.root,
  variants: {
    primary: {
      true: css.primary,
    },
  },
});

This outputs a nice clean component that can be used in React:

import { Button } from "./Button";

export const App = () => (
  <div>
    <Button>Default</Button>
    <Button primary>Primary</Button>
  </div>
);

Installation

Install this package with npm.

npm i @phntms/css-components

Usage

Here is a full example of a button component with an optional variant called primary:

components/Button/styles.module.css

.root {
  background-color: grey;
  border-radius: 4px;
}

.primary {
  background-color: black;
}

components/Button/styles.ts

import { styled } from "@phntms/css-components";
import css from "./styles.module.css";

export const StyledButton = styled("button", {
  css: css.root,
  variants: {
    primary: {
      true: css.primary,
    },
  },
});

components/Button/index.tsx

import { StyledButton } from "./styles.ts";

interface Props {
  title: string;
  onClick: () => void;
  primary?: boolean;
}

export const Button = ({ title, onClick, primary }: Props) => (
  <StyledButton onClick={onClick} primary={primary}>
    {title}
  </StyledButton>
);

The variants config object

The variants config object is a simple object that allows you to define the variants that your component supports. Each variant is a key in the object and the value is an object that defines the possible values(css classes) for that variant.

const StyledButton = styled("button", {
  css: css.root,
  variants: {
    big: {
      // Boolean values are supported
      true: css.big,
    },
    color: {
      // String values are supported
      primary: css.primary,
      secondary: css.secondary,
    },
    size: {
      // Number values are supported
      1: css.size1,
      2: css.size2,
    },
  },
});

Default Variants

You can use the defaultVariants feature to set a variant by default:

const StyledButton = styled("button", {
  css: css.root,
  variants: {
    big: {
      // Boolean values are supported
      true: css.big,
    },
  },
  defaultVariants: {
    big: true,
  },
});

Compound Variants

For more complex variant setups you can use the compound variants argument to define what styles should be applied when multiple variants are used.

const StyledButton = styled("button", {
  css: css.root,
  variants: {
    border: {
      true: css.bordered,
    },
    color: {
      primary: css.primary,
      secondary: css.secondary,
    },
  },
  compoundVariants: [
    {
      border: true,
      color: "primary",
      css: css.blueBorder,
    },
    {
      border: true,
      color: "secondary",
      css: css.greyBorder,
    },
  ],
});

Other

Array of Classes

Wherever you specify a css selector, you can also pass in an array of classes to help composing and reusing styles.

import { styled } from "@phntms/css-components";
import shared from "../sharedstyles.module.css";
import css from "./styles.module.css";

const Link = styled("a", {
  css: [shared.link, shared.fontNormal, css.root],
  variants: {
    big: {
      true: [css.big, shared.fontBold],
    },
  },
});

Other Components

You can also style other components from other ecosystems. As long as the component has a className prop, styling should propagate.

Example extending the standard Next.js Link component:

import { styled } from "@phntms/css-components";
import NextLink from "next/link";
import css from "./styles.module.css";

const Link = styled(NextLink, {
  css: css.link,
  variants: {
    big: {
      true: css.big,
    },
  },
});

Passthrough

By default variant values do not end up propagating to the element it is extending and is exclusively used for styling the current component. This is to stop React specific runtime errors from occurring with regards to the DOM. If you do indeed want to pass a variant value to the element you are extending, you can use the passthrough option.

In the following example, readOnly is an intrinsic HTML attribute that we both want to style, but also continue to pass through to the DOM element.

import { styled } from "@phntms/css-components";
import css from "./styles.module.css";

const Input = styled("input", {
  css: css.root,
  variants: {
    readOnly: {
      true: css.disabledStyle,
    },
  },
  passthrough: ["readOnly"],
});

Type Helper

We have included a helper that allows you to access the types of the variants you have defined.

import { VariantProps } from "@phntms/css-components";
import css from "./styles.module.css";

const Button = styled("button", {
  css: css.baseButton,
  variants: {
    primary: { true: css.primary },
  },
});

type ButtonVariants = VariantProps<typeof Button>;
type PrimaryType = ButtonVariants["primary"];

CLI Tool (Experimental)

We have included a CLI tool that allows you to generate components from CSS and SCSS files which confirm to a specific naming convention. This is highly experimental and is subject to change.

Consider this CSS file:

/* styles.module.css */
nav.topBar {
  background-color: #aaa;
  padding: 32px;
}

nav.topBar_fixed_true {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
}

Or using SCSS (Sassy CSS):

// styles.module.scss
nav.topBar {
  background-color: #aaa;
  padding: 32px;

  &_fixed_true {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
  }
}

You can generate a component from this files with the following command:

# For CSS
npx @phntms/css-components --css styles.module.css

# For SCSS
npx @phntms/css-components --css styles.module.scss

# or if you have the package installed
npx css-components --css styles.module.css
npx css-components --css styles.module.scss

This will output a file called styles.ts that looks like this:

import { styled } from "@phntms/css-components";

import css from "./test.css";

export const TopBar = styled("nav", {
  css: css.topBar,
  variants: {
    fixed: {
      true: css.topBar_fixed_true,
    },
  },
});

Possible CSS definitions:

  • a.link Allowing you to define a base style for the component. This means it will be an anchor tag with the css class link.
  • a.link_big_true Lets you set the styling for a variant called big with the value true.
  • a.link_theme_light_default Same as above but also sets the variant as the default value.
  • a.link_big_true_theme_light Gives you the ability to define compound variants styles.

CLI Options

  • --css The path to the CSS or SCSS file you want to generate a component from. This can also be a recursive glob pattern allowing you to scan your entire components directory.
  • --output The filename for the output file. Defaults to styles.ts which will be saved in the same directory as the CSS file.
  • --overwrite If the output file already exists, this will overwrite it. Defaults to false.

Example to generate components from all CSS and SCSS files in the components directory:

# From CSS
npx @phntms/css-components --css ./src/components/**/*.css --output styles.ts

# Or from SCSS
npx @phntms/css-components --css ./src/components/**/*.scss --output styles.ts

# Or from both CSS and SCSS
npx @phntms/css-components --css ./src/components/**/*.{css,scss} --output styles.ts