Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/lukejacksonn/oceanwind
Compiles tailwind shorthand into css at runtime. Succeeded by Twind.
https://github.com/lukejacksonn/oceanwind
css css-in-js otion shorthand-syntax tailwind-compiler
Last synced: 18 days ago
JSON representation
Compiles tailwind shorthand into css at runtime. Succeeded by Twind.
- Host: GitHub
- URL: https://github.com/lukejacksonn/oceanwind
- Owner: lukejacksonn
- Created: 2020-09-01T19:34:49.000Z (about 4 years ago)
- Default Branch: master
- Last Pushed: 2021-08-05T11:46:01.000Z (over 3 years ago)
- Last Synced: 2024-05-17T17:20:22.442Z (6 months ago)
- Topics: css, css-in-js, otion, shorthand-syntax, tailwind-compiler
- Language: JavaScript
- Homepage: https://twind.dev
- Size: 381 KB
- Stars: 264
- Watchers: 8
- Forks: 12
- Open Issues: 9
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Oceanwind
> compiles tailwind like shorthand syntax into css at runtime
This library takes inspiration from [Tailwind](https://github.com/tailwindlabs/tailwindcss) and utilizes [Otion](https://github.com/kripod/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](https://esm.codes/#Ly8gT2NlYW53aW5kIGRlbW8gYnkgQGx1a2VqYWNrc29ubgovLyAtLS0tLS0tLS0tLS0tLS0tCiAgICAKaW1wb3J0IHsgcmVuZGVyLCBodG1sIH0gZnJvbSAnaHR0cHM6Ly9ucG0ucmV2ZXJzZWh0dHAuY29tL3ByZWFjdCxwcmVhY3QvaG9va3MsaHRtL3ByZWFjdCc7CmltcG9ydCB7IHRoZW1lZCB9IGZyb20gJ2h0dHBzOi8vdW5wa2cuY29tL29jZWFud2luZCc7Cgpjb25zdCBvdyA9IHRoZW1lZCh7CiAgLy8gRXhhbXBsZSBvZiBleHRlbmRpbmcgdGhlIGRlZmF1bHQgdGhlbWUKICByb3RhdGU6IHsgNTogJzVkZWcnIH0KfSkKCmNvbnN0IHN0eWxlID0gewogIC8vIEV4YW1wbGUgb2YgYWJzdHJhY3RlZCBzdHlsZQogIGNvbnRhaW5lcjogb3dgCiAgICBoLWZ1bGwKICAgIGJnLXB1cnBsZS01MDAKICAgIGZsZXgKICAgIGl0ZW1zLWNlbnRlcgogICAganVzdGlmeS1jZW50ZXIKICBgCn0KCnJlbmRlcigKICBodG1sYAogICAgPGRpdiBjbGFzc05hbWU9JHtzdHlsZS5jb250YWluZXJ9PgogICAgICA8aDEgY2xhc3NOYW1lPSR7CiAgICAgICAgLy8gRXhhbXBsZSBvZiBhbiBpbmxpbmUgc3R5bGUKICAgICAgICBvd2AKICAgICAgICAgIHRleHQtd2hpdGUKICAgICAgICAgIGZvbnQtYm9sZAogICAgICAgICAgZm9udC1zYW5zCiAgICAgICAgICBob3ZlcjooCiAgICAgICAgICAgIHJvdGF0ZS01CiAgICAgICAgICAgIHNjYWxlLTE1MAogICAgICAgICAgICBjdXJzb3ItcG9pbnRlcgogICAgICAgICAgKQogICAgICAgIGAKICAgICAgfT5IZWxsbyBXb3JsZDwvaDE+CiAgICA8L2Rpdj4KICBgLAogIGRvY3VtZW50LmJvZHkKKTs=)
The aim here was to create a compiler that:
- 📖 Supports all existing Tailwind shorthand syntax outlined [in the docs](https://tailwindcss.com/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 usedThe 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:
```js
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 createdIt is recommended to import the following css files which help normalize styles across browsers:
- The Tailwind reset [available here](https://unpkg.com/tailwindcss/dist/base.min.css)
- The Tailwind prose helper [available here](https://unpkg.com/@tailwindcss/typography/dist/typography.min.css)### Extending the default theme
Importing and invoking oceanwind directly will cause it to use [default theme](https://github.com/lukejacksonn/oceanwind/blob/master/core/theme.js) 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.
```js
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:
```js
// 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
```js
ow`
sm:hover:(
bg-black
text-white
)
md:(bg-white hover:text-black)
`;
```It is possible to nest groupings too, for example:
```js
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](https://user-images.githubusercontent.com/1457604/95141411-04e4dc00-0769-11eb-9245-d4cc37c8b58f.png)
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:
```js
themed({ strict: true });
```![image](https://user-images.githubusercontent.com/1457604/95245344-e9caa880-080a-11eb-9741-576f7b2ff6b0.png)
## 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](https://esm.codes/#Ly8gT2NlYW53aW5kIGRlbW8gYnkgQGx1a2VqYWNrc29ubgovLyAtLS0tLS0tLS0tLS0tLS0tCiAgICAKaW1wb3J0IHsgcmVuZGVyLCBodG1sIH0gZnJvbSAnaHR0cHM6Ly9ucG0ucmV2ZXJzZWh0dHAuY29tL3ByZWFjdCxwcmVhY3QvaG9va3MsaHRtL3ByZWFjdCc7CmltcG9ydCB7IHRoZW1lZCB9IGZyb20gJ2h0dHBzOi8vdW5wa2cuY29tL29jZWFud2luZCc7Cgpjb25zdCBvdyA9IHRoZW1lZCh7CiAgLy8gRXhhbXBsZSBvZiBleHRlbmRpbmcgdGhlIGRlZmF1bHQgdGhlbWUKICByb3RhdGU6IHsgNTogJzVkZWcnIH0KfSkKCmNvbnN0IHN0eWxlID0gewogIC8vIEV4YW1wbGUgb2YgYWJzdHJhY3RlZCBzdHlsZQogIGNvbnRhaW5lcjogb3dgCiAgICBoLWZ1bGwKICAgIGJnLXB1cnBsZS01MDAKICAgIGZsZXgKICAgIGl0ZW1zLWNlbnRlcgogICAganVzdGlmeS1jZW50ZXIKICBgCn0KCnJlbmRlcigKICBodG1sYAogICAgPGRpdiBjbGFzc05hbWU9JHtzdHlsZS5jb250YWluZXJ9PgogICAgICA8aDEgY2xhc3NOYW1lPSR7CiAgICAgICAgLy8gRXhhbXBsZSBvZiBhbiBpbmxpbmUgc3R5bGUKICAgICAgICBvd2AKICAgICAgICAgIHRleHQtd2hpdGUKICAgICAgICAgIGZvbnQtYm9sZAogICAgICAgICAgZm9udC1zYW5zCiAgICAgICAgICBob3ZlcjooCiAgICAgICAgICAgIHJvdGF0ZS01CiAgICAgICAgICAgIHNjYWxlLTE1MAogICAgICAgICAgICBjdXJzb3ItcG9pbnRlcgogICAgICAgICAgKQogICAgICAgIGAKICAgICAgfT5IZWxsbyBXb3JsZDwvaDE+CiAgICA8L2Rpdj4KICBgLAogIGRvY3VtZW50LmJvZHkKKTs=)
```js
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`
Hello World
`,
document.body
);
```## Server-side rendering (SSR)
Oceanwind supports SSR through Otion. Consider the following example:
```js
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`hello oceanwind`;
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](https://www.npmjs.com/package/otion#server-side-rendering) for further configuration options and usage instructions.
## Acknowledgements
I'd like to thank both [Adam Wathan](https://github.com/adamwathan) and [Kristóf Poduszló](https://github.com/kripod) for their amazing work with Tailwind and Otion respectively, which made making this library somewhat a breeze. Also [Phil Pluckthun](https://github.com/kitten) who helped me deduce the initial grammar.