New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

vite-plugin-toad

Package Overview
Dependencies
Maintainers
1
Versions
58
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

vite-plugin-toad

Zero runtime CSS-in-JS powered by Vite

latest
npmnpm
Version
0.3.4
Version published
Maintainers
1
Created
Source

🌺🐸☘️

Zero-runtime CSS-in-JS tool inspired by Linaria.

Try on StackBlitz or check out example.

⚠ Work in progress.

pnpm i -D vite-plugin-toad

/*@toad-ext .scss*/ // This sets extension for corresponding output file.
// You can set in plugin config globally or for each file.
import { render } from 'solid-js/web';
import { modularScale, hiDPI } from 'polished';
import { css } from 'vite-plugin-toad/css';
import Constants from './constants';
import logo from './logo.svg';

css`/*global*/ /* mark style as global */
   body {background-color: ${Constants.BACKGROUND_COLOR};} /* Use some static variables. Works when 'ssr.evaluate = true' */
   @keyframes logo-spin {
      from {transform: rotate(0deg);}
      to {transform: rotate(360deg);}
   }
`;
const App = () => (
   <div
      class={css`
         /*@toad-debug wrapper*/ // <- this adds "wrapper" to output class
         max-width: 800px;
         background-color: #dadada;
         font-size: ${modularScale(2)};
         ${hiDPI(1.5)} {
            font-size: ${modularScale(2.5)};
         }
      `}
   >
      <img
         src={logo}
         class={css`
            animation: logo-spin infinite 10s linear;
            height: 40vmin;
            pointer-events: none;
            & ~ p {
               $variable: blue;
               color: #{$variable}; // This code will work as we set .scss extension
            }
        `}
      />
      <p>Edit <code>app.tsx</code> and save to reload</p>
      <a href="https://github.com/solidjs/solid" target="_blank" > Learn solid </a>
   </div>
);
if (!import.meta.env.SSR) {
   render(App, document.body);
}

All CSS transforms are handled by Vite, so it will work with SASS, LightningCSS, PostCSS and other tools.
There is also way to write your CSS-in-JS separately by using babel-plugin-css-attribute. Here it is an example from my project with UnoCSS, preset attributify and vite-plugin-toad:

<a
   m-b-8
   m-t-16px
   class="block cursor-pointer text-center c-blue-500"
   css={css`@container (height < 400px) { margin-bottom: 0; }`}
>
   My link
</a>

⬇️vite-plguin-toad⬇️

<a class={"block cursor-pointer text-center c-blue-500 m-b-8 m-t-16px" + "login_page-1okjy9f"}
>
   My link
</a>

To use this feature, set transformCssAttribute: true or use Babel plugin, example with vite-plugin-solid:

import ViteSolid from "@foxpro/vite-plugin-solid"
import BabelPluginCssAttrs from "vite-plugin-toad/babel-plugin-css-attribute"

// ...vite configurations and plugins... 
ViteSolid({
   hot: dev,
   dev: dev,
   typescript: {
      onlyRemoveTypeImports: true
   },
   babel: {
      plugins: [[BabelPluginCssAttrs, {}]]
   }
})

⚠️ To achieve better better performance, use babel-plugin-css-attribute directly if possible, because Toad will use additionally:
@babel/preset-typescript
@babel/plugin-syntax-jsx
This can slightly affect build performance.
You can customize babel options by using babel option.

For more advanced documentation, please refer to typescript JSDoc comments.

Motivation

I found following way of writing components can be convinient:

<TextField.Input
   ref={numberInputRef}
   inputmode="decimal"
   css="
      background-color: var(--grey-000);
      border: 1px solid blue; border-radius: 8px;
      &:focus {
         outline-offset: -5px; outline-color: var(--grey-000);
      }
      color: var(--black-900); line-height: 3.5rem; font-weight: 500;
   "
   h-12 w-full p-l-10px
/>

CSS-in-JS for creating component styles, and Atomic CSS with attributify for positioning component in layout.
I found this way keeps code more clean and readable. It avoids mess of long atomic classes with ?#[]@ symbols and decoupling of styles as it used to with BEM or CSS modules.

I'm planning to add handling of css="" attribute.

Known tradeoffs

Make sure you modules with CSS-in-JS don't use top-level DOM API if you are using ssr: { eval: true }. You can wrap it like in the example:

if (!import.meta.env.SSR) {
   render(App, document.body)
}

Some plugins don't respect Vite ssr: true option when using ssrLoadModule, so they need to be processed separately if you're want to use variables in template literals.
You can process it in customSSRTransformer. Make sure to output SSR-ready code.

ViteToad({
   outputExtension: '.scss',
   exclude: [/node_modules/, /\.s?css/], // better to exclude all styles
   ssr: {
      eval: true,
      async customSSRTransformer(code, ctx, server, _c, url) {
         solidOptions.solid.generate = 'ssr'
         const result = await server.transformRequest(skipToadForUrl(url), { ssr: true })
         // Or, if you know what you're doing: 
         // const solidPlugin = server.config.plugins.find(p => p.name === 'solid')
         // const result = await solidPlugin.transform(code, skipToadForUrl(url), { ssr: true })
         return {
            result,
            // this will be called when we will transform all dependencies
            cb: () => {
               solidOptions.solid.generate = 'dom'
            }
         } 
      },
   },
})

Currently, it may not work if styles are co-located with some legacy dependencies / or dependencies that are not intended to be used in SSR environment. What you can do about it:

  • Split your code so your component with styles are not in the same module with bad dependency
  • Wrap your dependency in lazy import() inside your component near usage place, or in if(!import.meta.env.SSR).
  • Try another SSR-friendly library instead
  • Make a simple Vite plugin just in your configuration to skip dependency: return empty string in Vite load() hook.
  • Play with Vite ssr.external configuration. It's possible that I will implement some kind of tree-shaking through SWC, so all unused in styling deps will be omitted, as Linaria do with their shaker.

Typescript

You can avoid using import { css } from 'vite-plugin-toad/css by adding "vite-plugin-toad/css" entry to tsconfig.json compilerOptions.types array.

Keywords

vite

FAQs

Package last updated on 22 Aug 2023

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts