• Stars
    star
    264
  • Rank 155,103 (Top 4 %)
  • Language
    JavaScript
  • Created about 4 years ago
  • Updated over 3 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Compiles tailwind shorthand into css at runtime. Succeeded by Twind.

Oceanwind

compiles tailwind like shorthand syntax into css at runtime

This library takes inspiration from Tailwind and utilizes Otion to provide means of efficiently generating atomic styles from shorthand syntax and appending them to the DOM at runtime.

Server side rendering and static extraction is also supported.

⚡️ Check out the live and interactive demo


The aim here was to create a compiler that:

  • 📖 Supports all existing Tailwind shorthand syntax outlined in the docs
  • 💡 Generates only the styles required without building or purging
  • 🗜 Is smaller than the average purged css file output from the Tailwind compiler
  • Has desirable perf characteristics at runtime
  • ⚠️ Warns the developer when unrecognized or duplicate shorthand is used

The library currently weighs under 10kb and supports the vast majority of Tailwind directives and variants.

Usage

To use the library, first import the module then invoke the default export using tagged template syntax:

import ow from 'https://unpkg.com/oceanwind';
document.body.className = ow`h-full bg-purple-500 rotate-3 scale-95`;

Running the above code will result in the following happening:

  1. Shorthand syntax will be translated into CSS (e.g. h-screen -> { height: 100vh }).
  2. All resultant CSS will be merged into a single CSS-in-JS object
  3. Each style will be assigned a unique class and appended to a stylesheet
  4. A string is returned representing all the classes that were created

It is recommended to import the following css files which help normalize styles across browsers:

Extending the default theme

Importing and invoking oceanwind directly will cause it to use default theme for directives that require themed values (like bg-red-500 for example). To customize the theme, use the themed export instead of the default export.

import { themed } from 'https://unpkg.com/oceanwind';

const ow = themed({
  colors: {
    red: {
      500: 'hotpink',
    },
  },
});

ow`bg-red-500`; // will result in a hotpink background-color

Any custom theme provided to the themed function will be deep merged with the default theme.

Function Signature

It is possible to invoke oceanwind in a multitude of different ways. For example:

// Function call passing a string
ow('bg-red-500 rounded');

// Tag Template Literal (falsey interpolations will be omitted)
ow`bg-red-500 rounded`;
ow`bg-red-500 ${false && 'rounded'}`;

// Function call passing an array (falsey items will be omitted)
ow(['bg-red-500', 'rounded']);
ow(['bg-red-500', false && 'rounded']);

// Function call passing an object (keys with falsey values will be omitted)
ow({ 'bg-red-500': true, rounded: true });
ow({ 'bg-red-500': true, rounded: false });

Variant Grouping

Directives with the same variants can be grouped using parenthesis. Oceanwind will expand the nested directives; applying the variant to each directive in the group before translation. For example:

Notice any directives within tagged template literals can span multiple lines

ow`
  sm:hover:(
    bg-black
    text-white
  )
  md:(bg-white hover:text-black)
`;

It is possible to nest groupings too, for example:

ow`
  sm:(
    bg-black
    text-white
    hover:(bg-white text-black)
  )
`;

Two things to note here is that the outermost variant should always be a responsive variant (just like in tailwind hover:sm: is not supported) and that nesting responsive variants doesn't make sense either, for example sm:md: is not supported.

Catching Errors

By default warnings about missing or duplicate translations will be written to the console:

image

Clicking on the file path in dev tools will jump to the line in the file in the sources panel.

It is possible to make oceanwind throw an error rather just warning by opting into strict mode:

themed({ strict: true });

image

Example

Most of the time developers will be using a front end framework to render DOM elements. Oceanwind is framework agnostic but here is an example of how you might use it with preact and no build step.

⚡️ Check out the live and interactive demo

import { render, h } from 'https://unpkg.com/preact?module';

import htm from 'https://unpkg.com/htm?module';
import ow from 'https://unpkg.com/oceanwind';

const html = htm.bind(h);

render(
  html`
    <div className=${ow`h-full bg-purple-500`}>
      <h1 className=${ow`text-white font-bold`}>Hello World</h1>
    </div>
  `,
  document.body
);

Server-side rendering (SSR)

Oceanwind supports SSR through Otion. Consider the following example:

import { h } from 'preact';
import render from 'preact-render-to-string';
import htm from 'htm';
import { getStyleTag, VirtualInjector } from 'otion/server';
import { setup, themed } from 'oceanwind';

const injector = VirtualInjector();
setup({ injector });

const html = htm.bind(h);
const ow = themed({});
const style = {
  main: ow`clearfix`,
};

const app = html`<main className=${style.main}>hello oceanwind</main>`;
const appHtml = render(app);
const styleTag = getStyleTag(injector);

// Inject styleTag to your HTML now.

Oceanwind also exposes hydrate from Otion for client-side hydration. See Otion documentation for further configuration options and usage instructions.

Acknowledgements

I'd like to thank both Adam Wathan and Kristóf Poduszló for their amazing work with Tailwind and Otion respectively, which made making this library somewhat a breeze. Also Phil Pluckthun who helped me deduce the initial grammar.

More Repositories

1

react-slack-clone

Complete chat application, built with Chatkit | by @lukejacksonn
JavaScript
1,347
star
2

perflink

Low friction JavaScript benchmarks that you can share via URL
JavaScript
1,208
star
3

servor

Dependency free file server for single page app development
JavaScript
1,042
star
4

ijk

Transforms arrays into virtual dom trees; a terse alternative to JSX and h
JavaScript
467
star
5

GreedyNav

A responsive navigation menu that stacks items into a dropdown menu when they overflow
JavaScript
231
star
6

es-react

ES6 module exposing the latest version of react and react-dom
JavaScript
231
star
7

csz

Runtime CSS modules with SASS like preprocessing
JavaScript
218
star
8

monacode

An es-module wrapper around the monaco editor and prettier
JavaScript
167
star
9

create-es-react-app

A create-react-app like template using only es-modules (no build step).
JavaScript
103
star
10

hyperapp-pwa

A minimalist, progressive web app compliant template for hyperapp projects
JavaScript
72
star
11

domz

A proxy function to help build virtual DOM trees from functions
JavaScript
62
star
12

hyperapp-electron

A minimal electron app starter with hyperapp, livereload and redux devtools
JavaScript
51
star
13

Actuate

One line easy actuation of CSS animation sequences
JavaScript
41
star
14

chattery

A GitHub action that creates chatrooms for pull requests
Ruby
29
star
15

esm

A single file es module prototyping tool
JavaScript
29
star
16

blub

[POC] resolving es module dependency graphs on the server
JavaScript
27
star
17

deployable

A ready-to-deploy static web app template and tutorial
HTML
25
star
18

hyperapp-firebase-auth

🔥 Drop in authentication for hyperapps using firebase
JavaScript
19
star
19

Lorem

Generates random lorem ipsum snippets
JavaScript
19
star
20

Malette

A color picker tool for the google material design palette
JavaScript
18
star
21

cube

Rubik's Cube simulator with F2L/OLL/PLL algorithms
JavaScript
17
star
22

hyperapp-wiki

Example of how hyperapp could be used to serve its on wiki with gh-pages
HTML
13
star
23

blog

A forkable personal blog that runs on GitHub pages. Demo 👉
JavaScript
12
star
24

hyperapp-hn

First attempt at a community hacker news PWA built with HyperApp
JavaScript
10
star
25

vuid

❄️ Very unique identifiers in the browser using web cryptography (144b)
JavaScript
10
star
26

hyperapp-fetch

A component to fetch and cache data before rendering a view
JavaScript
10
star
27

tetris

The classic NES Tetris built with hyperapp
JavaScript
9
star
28

ipsums

Generate random amounts of lorem ipsum text
JavaScript
8
star
29

framer

Easily apply a frame overlay to an avatar photo
JavaScript
8
star
30

hyperapp-starter

A minimalist starter for hyperapp projects
JavaScript
6
star
31

Protohype

A set of aliases for commonly used CSS properties and values
CSS
5
star
32

hyperapp-router

A frontend router for hyperapp view switching
JavaScript
4
star
33

preroll

An opinionated web project builder with dev server
JavaScript
3
star
34

dankon

🗺 Learn to express your gratitude in 140+ different languages
JavaScript
3
star
35

streamer

🚰 Streams of reasonably interesting data published reasonably stochastically
JavaScript
2
star
36

fb-sdk

Load and queue calls to the facebook sdk
JavaScript
2
star
37

huy

useful h function ui elements
JavaScript
2
star
38

plural

picture-in-picture interface for youtube videos
JavaScript
2
star
39

hyperapp-two

A multi-page and multi-component boilerplate hyperapp project
JavaScript
2
star
40

xs

An extra small, stand alone web application template
HTML
1
star
41

youtube-eco

A chrome extension that optimizes youtube streaming quality
JavaScript
1
star
42

hyperapp-unite

A utility function for merging reducers, effects and routes with safe namespacing
JavaScript
1
star
43

Stash

A jQuery plugin that can instigate application/octet-stream downloads of local content
JavaScript
1
star
44

Browver

A JavaScript plugin that detects if a browser is too and points to the latest browser downloads..
JavaScript
1
star
45

lukejacksonn.github.io

My personal homepage to be hosted at http://lukejacksonn.com
HTML
1
star
46

gitinit

Create a new git repo based on an already existing repository
JavaScript
1
star
47

feeder

My awesome pusher feeds app (test)
JavaScript
1
star
48

loginn

A set of lambda functions and frontend components to aid authentication
JavaScript
1
star
49

create-pusher-app

An experiment with yeoman, hyperapp and the Pusher Feeds API
JavaScript
1
star
50

lukejacksonn

1
star