Skip to content

Commit

Permalink
add new web components integration
Browse files Browse the repository at this point in the history
  • Loading branch information
sastan committed Dec 15, 2022
1 parent 2057fc5 commit f43f5bf
Show file tree
Hide file tree
Showing 21 changed files with 639 additions and 242 deletions.
8 changes: 8 additions & 0 deletions .changeset/eight-fireants-trade.md
@@ -0,0 +1,8 @@
---
'@example/with-lit': patch
'@example/with-web-components': patch
'@twind/core': patch
'@twind/with-web-components': patch
---

add new web components integration
7 changes: 5 additions & 2 deletions .codesandbox/ci.json
Expand Up @@ -26,7 +26,8 @@
"gatsby-plugin-twind": "packages/with-gatsby/dist",
"@twind/with-next": "packages/with-next/dist",
"@twind/with-remix": "packages/with-remix/dist",
"@twind/with-sveltekit": "packages/with-sveltekit/dist"
"@twind/with-sveltekit": "packages/with-sveltekit/dist",
"@twind/with-web-components": "packages/with-web-components/dist"
},
// A list of sandboxes that you want generated for a PR, if this list
// is not set we will default to `vanilla`. The built library will automatically
Expand All @@ -39,9 +40,11 @@
"/examples/basic",
"/examples/playground",
"/examples/with-gatsby",
"/examples/with-lit",
"/examples/with-next",
"/examples/with-remix",
"/examples/with-sveltekit"
"/examples/with-sveltekit",
"/examples/with-web-components"
],
// Node.js version to use for building the PR.
// Supported versions are '10' (10.24.1, default), '12' (12.22.7), '14' (14.18.1) and '16' (16.13.0).
Expand Down
3 changes: 2 additions & 1 deletion .stackblitz/codeflow.json
Expand Up @@ -15,7 +15,8 @@
"gatsby-plugin-twind": "./packages/with-gatsby",
"@twind/with-next": "./packages/with-next",
"@twind/with-remix": "./packages/with-remix",
"@twind/with-sveltekit": "./packages/with-sveltekit"
"@twind/with-sveltekit": "./packages/with-sveltekit",
"@twind/with-web-components": "./packages/with-web-components"
}
}
}
3 changes: 2 additions & 1 deletion CHANGELOG.md
Expand Up @@ -17,7 +17,8 @@

## Integrations

- [gatsby-plugin-twind](./packages/with-gatsby/CHANGELOG.md)
- [@twind/with-next](./packages/with-next/CHANGELOG.md)
- [@twind/with-remix](./packages/with-remix/CHANGELOG.md)
- [@twind/with-sveltekit](./packages/with-sveltekit/CHANGELOG.md)
- [gatsby-plugin-twind](./packages/with-gatsby/CHANGELOG.md)
- [@twind/with-web-components](./packages/with-web-components/CHANGELOG.md)
31 changes: 16 additions & 15 deletions documentation/examples.md

Large diffs are not rendered by default.

223 changes: 148 additions & 75 deletions documentation/with-lit.md
@@ -1,6 +1,7 @@
---
section: Use With
title: Lit
package: '@twind/with-web-components'
example: with-lit
excerpt: |
Using Twind with [Lit](https://lit.dev)
Expand All @@ -9,78 +10,150 @@ next: ./with-next.md

This guide shows how to use [Lit](https://lit.dev) with Twind.

> **Caution**
> This example is using [Constructable Stylesheet Objects](https://wicg.github.io/construct-stylesheets/) and `DocumentOrShadowRoot.adoptedStyleSheets` which have [limited browser support](https://caniuse.com/mdn-api_document_adoptedstylesheets) at the moment (December 2022). The [Constructible style sheets polyfill](https://github.com/calebdwilliams/construct-style-sheets) offers a solution for all modern browsers and IE 11.
```js
import { LitElement, html } from 'lit'

import { twind, cssom, observe } from '@twind/core'
import config from './twind.config'

// 1. Create separate CSSStyleSheet
const sheet = cssom(new CSSStyleSheet())

// 2. Use that to create an own twind instance
const tw = twind(config, sheet)

export class TwindElement extends LitElement {
// 3. Apply the same style to each instance of this element
static override styles = [sheet.target]

// 4a. Observe using "own" tw function
override firstUpdated(): void {
observe(tw, this.renderRoot)
}

override render() {
return html`
<main class="h-screen bg-purple-400 flex items-center justify-center">
<h1 class="font-bold text(center 5xl white sm:gray-800 md:pink-700)">This is Twind!</h1>
</main>
`

// 4b. Use "own" tw function directly
// return html`
// <main class="${tw('h-screen bg-purple-400 flex items-center justify-center')}">
// <h1 class="${tw('font-bold text(center 5xl white sm:gray-800 md:pink-700')}">
// This is Twind!
// </h1>
// </main>
// `
}
}

customElements.define('twind-element', TwindElement);
```

> **Tip**
> The [Library Mode guide](./library-mode) might be helpful for advanced use cases like creating a dedicated `twind` module.
```js title="twind.js"
import {
twind,
cssom,
tx as tx$,
injectGlobal as injectGlobal$,
keyframes as keyframes$,
} from '@twind/core'

import config from './twind.config'

// 1. Create separate CSSStyleSheet
export const sheet = /* #__PURE__ */ cssom(new CSSStyleSheet())

// 2. Use that to create an own twind instance
export const tw = /* #__PURE__ */ twind(config, sheet)

// tx allow tagged template usage like: tx`text(center 5xl white sm:gray-800 md:pink-700)`
export const tx = /* #__PURE__ */ tx$.bind(tw)

// bind some helper function
export const injectGlobal = /* #__PURE__ */ injectGlobal$.bind(tw)
export const keyframes = /* #__PURE__ */ keyframes$.bind(tw)

// export additional useful functions
export { observe, cx } from from '@twind/core'
```
> **Note**
> In [modern browsers](https://caniuse.com/mdn-api_document_adoptedstylesheets) this integration uses [Constructable Stylesheet Objects](https://wicg.github.io/construct-stylesheets/) and [`adoptedStyleSheets`](https://developer.mozilla.org/en-US/docs/Web/API/ShadowRoot/adoptedStyleSheets) for optimal performance. In legacy browsers, it falls back to using separate style elements (one per element instance) that are all kept in sync.
## 🤝 Compatibility

| @twind/with-web-components | lit |
| -------------------------- | ------------ |
| `>=1.0.0 <1.1.0` | `>=2.0.0 <3` |

## 📦 Installation

1. :::cols-12{.gap-4}

::col-span-4
**Install from npm**

`@twind/core` and `@twind/with-web-components` are available on npm and need to be installed together.

::col-span-8

```sh
npm install @twind/core @twind/with-web-components
```

:::

1. :::cols-12{.gap-4}

::col-span-4
**Define the configuration**

Using an extra file, `twind.config.js`, allows some tools like [IntelliSense](./installation) to find your configuration.

::col-span-8

```js title="twind.config.js"
import { defineConfig } from '@twind/core'

export default defineConfig({
/* @twind/with-web-components will use
* hashed class names in production by default
* If you don't want this, uncomment the next line
*/
// hash: false,
})
```

:::

1. :::cols-12{.gap-4}

::col-span-4
**Create a Custom Element**

`install` creates a mixin that can be used to enhance elements with a shared stylesheet, generates styles for all used CSS classes and adds `this.tw` (the twind instance) to the element instance.

The mixin function can be used with several elements — they all will share the same twind instance.

::col-span-8

```js
import { LitElement, html } from 'lit'

import install from '@twind/with-web-components'
import config from './twind.config'

const withTwind = install(config)

export class TwindElement extends withTwind(LitElement) {
override render() {
return html`<h1 class="text-3xl font-bold underline">Hello world!</h1>`
}
}

customElements.define('twind-element', TwindElement);
```

::col-span-4
**Using typescript and decorators**

The mixin function can also be used as a decorator.

> **Important**
> Please be aware that typescript will not be able to infer the additional properties (like `this.tw`) added to the element class.
::col-span-8

```ts
import { LitElement, html } from 'lit'
import { customElement } from 'lit/decorators.js'

import install from '@twind/with-web-components'
import config from './twind.config'

const withTwind = install(config)

@customElement('twind-element')
@withTwind
export class TwindElement extends LitElement {
override render() {
return html`<h1 class="text-3xl font-bold underline">Hello world!</h1>`
}
}
```

:::

1. <details>
<summary><strong>Optional</strong>: Install and configure the recommended presets <a href="./preset-autoprefix"><code>@twind/preset-autoprefix</code></a> and <a href="./preset-tailwind"><code>@twind/preset-tailwind</code></a>.</summary>

:::cols-12{.gap-4}

::col-span-4
**Install the presets**

All presets are [available on npm](https://www.npmjs.com/search?q=keywords:twind-preset).

::col-span-8

```sh
npm install @twind/preset-autoprefix @twind/preset-tailwind
```

:::

:::cols-12{.gap-4}

::col-span-4
**Configure the presets**

Each preset must be added to the `presets` array in the configuration.

::col-span-8

```js title="twind.config.js" [2-3,6]
import { defineConfig } from '@twind/core'
import presetAutoprefix from '@twind/preset-autoprefix'
import presetTailwind from '@twind/preset-tailwind'

export default defineConfig({
presets: [presetAutoprefix(), presetTailwind()],
})
```

:::

</details>

0 comments on commit f43f5bf

Please sign in to comment.