Git Product home page Git Product logo

syfxlin / reve Goto Github PK

View Code? Open in Web Editor NEW
0.0 1.0 1.0 156 KB

@syfxlin/reve is a library of enhancements to vanilla-extract to improve the experience of using vanilla-extract and reduce unnecessary time consumption due to specific programming paradigms.

License: MIT License

HTML 3.83% TypeScript 94.30% JavaScript 1.86%
css-in-js css-prop styled-components vanilla-extract theme-system

reve's Introduction

Reve

vanilla-extract is a CSS-in-JS compiler that writes styles in TypeScript (or JavaScript) using locale-scoped class names and CSS variables, then generates static CSS files at build time.

@syfxlin/reve is a library of enhancements to vanilla-extract to improve the experience of using vanilla-extract and reduce unnecessary time consumption due to specific programming paradigms.

Motivation

vanilla-extract use object style to define styles, which makes good use of the type mechanism for auto-completion and error checking. But this style is not convenient compared to vanilla style. For example, string values need more quotes, CSS functions can't be auto-complete and error-checked, Emmet abbreviation syntax is not supported, and so on.

vanilla-extract each style block can only target a single element, which makes it a pain when we need to define complex nested styles, wasting a lot of time writing global styles or adding classNames to child elements, most typically adding typography styles. The most typical scenario is to add typography styles. For example, here's a comparison of two snippets:

// Bad
export const typography = style({
  // ...
});

globalStyle(`${typography} h1, ${typography} h2, ${typography} h3`, {
  // ...
});

globalStyle(`${typography} h1::before, ${typography} h2::before, ${typography} h3::before`, {
  // ...
});

// Good
export const typography = styled.css`
  // ... typography style
  
  h1, h2, h3 {
    // ... heading style
    
    &::after {
      // ... heading ::after pseudo style
    }
  }
`

vanilla-extract developers added this limitation for maintainability, so I don't think they'll remove it, so I use the stylis library to parse the vanilla style css into object style css and chunking the styles to ensure that a style chunk targets only and chunking the styles to make sure that a style block is only for one element, styles is finally exported via vanilla-extract globalStyle.

vanilla-extract writes styles based on TypeScript/JavaScript, so it has the ability to execute code, and we can take advantage of this by creating a theme system that calculates values at build time and hardcodes them directly into the CSS, defining only the values that need to be able to change dynamically in theme variables. This way we don't need to define a very large number of theme variables, resulting in a very large CSS file (vanilla-extract generates all defined theme variables into the final CSS file, even if it doesn't use them). For example:

// Bad
export const theme = createThemeContract({
  color: {
    background: null
  },
  size: {
    // ... x1 - x31
    x32: null
  }
});

createGlobalTheme(".light-theme", theme, {
  color: {
    background: "lightblue"
  },
  size: {
    // ... x1 - x31
    x32: "32px"
  }
});

createGlobalTheme(".dark-theme", theme, {
  color: {
    background: "lightpink"
  },
  size: {
    // ... x1 - x31
    x32: "32px"
  }
});

export const container = styled.css`
  font-size: ${theme.size.x32};
  background-color: ${theme.color.background};
`;
// Output:
// .light-theme { --def456: lightblue; /* x1-x31 */; --x32: 32px; }
// .dark-theme { --def456: lightpink; /* x1-x31 */; --x32: 32px; }
// .abc123 { font-size: var(--x32); background-color: var(--def456); }

// Good
export const theme = createReveTheme({
  static: {
    size: (value: number) => `${value}px`,
  },
  dynamic: {
    ".light-theme": {
      color: { background: "lightblue" },
    },
    ".dark-theme": {
      color: { background: "lightpink" },
    },
  },
});

export const container = styled.css`
  font-size: ${theme.size(32)};
  background-color: ${theme.color.background};
`;
// Output:
// .light-theme { --def456: lightblue; }
// .dark-theme { --def456: lightpink; }
// .abc123 { font-size: 32px; background-color: var(--def456); }

I started this project as a proof-of-concept to see if I could fix a few of the bad implementations mentioned above, improve my coding efficiency, and save time for other things I want to do.

Installation

# NPM
npm i @syfxlin/reve @vanilla-extract/css
# Yarn
yarn add @syfxlin/reve @vanilla-extract/css
# PNPM
pnpm add @syfxlin/reve @vanilla-extract/css

Usage

import { styled, createReveTheme } from "@syfxlin/reve";

// vanilla css api
styled.global`
  box-sizing: border-box;
`

export const container = styled.css`
  font-size: ${theme.size(32)};
  background-color: ${theme.color.background};

  /* Supports nested syntax for styled-componets styles */
  div {
    display: flex;

    &::before {
    }
  }

  div & {
  }

  & div {
  }

  & > div {
  }

  /* Support media query syntax */
  @media (max-width: 1250px) {
    /* ... */
  }
`;

// theme system
export const theme = createReveTheme({
  static: {
    size: (value: number) => `${value}px`,
  },
  dynamic: {
    ".light-theme": {
      color: { background: "lightblue" },
    },
    ".dark-theme": {
      color: { background: "lightpink" },
    },
  },
});

Maintainer

@syfxlin/reve is written and maintained with the help of Otstar Lin and the following contributors.

License

Released under the MIT License.

reve's People

Contributors

renovate[bot] avatar syfxlin avatar

Watchers

 avatar

Forkers

kaberasim85

reve's Issues

Atomic CSS generation proof of concept

The stylis library can convert CSS into AST, so you can create a CSS Store to dynamically store each style definition. When the field name and field value are the same, use the same class. An example is as follows:

export const container = styled.css`
  font-size: 32px;
  background-color: lightblue;
`;

<div className={container} />

Output:

<div class="fs-32 bc-lightblue"></div>
.fs-32 {
  font-size: 32px;
}

.bc-lightblue {
  background-color: lightblue;
}

CSS Store:

{
  "font-size: 32px": "fs-32",
  "background-color: lightblue": "bc-lightblue",
}

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Rate-Limited

These updates are currently rate-limited. Click on a checkbox below to force their creation now.

  • fix(deps): update dependency @vanilla-extract/css-utils to v0.1.4
  • fix(deps): update dependency @vanilla-extract/dynamic to v2.1.1
  • chore(deps): update dependency @vitejs/plugin-react to v4.3.1
  • ๐Ÿ” Create all rate-limited PRs at once ๐Ÿ”

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Detected dependencies

github-actions
.github/workflows/release.yml
  • actions/checkout v4
  • pnpm/action-setup v3.0.0
  • actions/setup-node v4
npm
package.json
  • @vanilla-extract/css-utils ^0.1.3
  • @vanilla-extract/dynamic ^2.1.0
  • clsx ^2.1.0
  • stylis ^4.3.1
  • @syfxlin/eslint-config ^1.0.4
  • @types/react ^18.2.63
  • @types/react-dom ^18.2.20
  • @types/stylis ^4.2.5
  • @vanilla-extract/vite-plugin ^4.0.4
  • @vitejs/plugin-react ^4.2.1
  • bunchee ^4.4.8
  • eslint ^8.57.0
  • react ^18.2.0
  • react-dom ^18.2.0
  • typescript ^5.3.3
  • vite ^5.1.5
  • @vanilla-extract/css ^1.12.0

  • Check this box to trigger a request for Renovate to run again on this repository

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.