|
129 | 129 | .on("@click", ({ state }) => state.count(state.count() + 1)) // host click |
130 | 130 | .on("button.inc@click", ({ state }) => state.count(state.count() + 1)) // child click |
131 | 131 | .on("input@input:debounce", ({ state, event }) => { |
132 | | - // with modifier |
133 | 132 | state.query((event.target as HTMLInputElement).value); |
134 | 133 | }) |
135 | 134 | .render(({ state }) => html`<div><button class="inc">+</button></div>`); |
@@ -223,6 +222,63 @@ You can also bind to an external signal created with `context()`: |
223 | 222 |
|
224 | 223 | --- |
225 | 224 |
|
| 225 | +### `.css(strings, ...values)` |
| 226 | + |
| 227 | +Attaches scoped styles to the island. Accepts a tagged template literal or a plain string. The CSS is automatically wrapped in a `@scope` rule bounded to the island host, so styles are contained within the island and do not leak into child islands. |
| 228 | + |
| 229 | +```ts |
| 230 | +import { css } from "ilha"; |
| 231 | + |
| 232 | +const Card = ilha.state("active", false).css` |
| 233 | + .title { font-weight: 700; } |
| 234 | + button { background: teal; color: white; } |
| 235 | + `.render( |
| 236 | + ({ state }) => html` |
| 237 | + <div> |
| 238 | + <p class="title">Hello</p> |
| 239 | + <button>Toggle</button> |
| 240 | + </div> |
| 241 | + `, |
| 242 | +); |
| 243 | +``` |
| 244 | + |
| 245 | +Interpolations are supported: |
| 246 | + |
| 247 | +```ts |
| 248 | +const accent = "teal"; |
| 249 | + |
| 250 | +ilha.css`button { background: ${accent}; }`.render(() => `<button>Go</button>`); |
| 251 | +``` |
| 252 | + |
| 253 | +You can also pass a plain string (e.g. from an external `.css` file): |
| 254 | + |
| 255 | +```ts |
| 256 | +import styles from "./card.css?raw"; |
| 257 | + |
| 258 | +ilha.css(styles).render(() => `<div class="card">…</div>`); |
| 259 | +``` |
| 260 | + |
| 261 | +**SSR output** — a `<style data-ilha-css>` tag is prepended as the first child of the island's rendered HTML: |
| 262 | + |
| 263 | +```html |
| 264 | +<style data-ilha-css> |
| 265 | + @scope (:scope) to ([data-ilha]) { |
| 266 | + .title { |
| 267 | + font-weight: 700; |
| 268 | + } |
| 269 | + } |
| 270 | +</style> |
| 271 | +<div>…</div> |
| 272 | +``` |
| 273 | + |
| 274 | +**Client mount** — the style element is injected once as the first child of the host and preserved across re-renders (morph never replaces it). During hydration, the SSR-emitted `<style>` node is reused and not duplicated. |
| 275 | + |
| 276 | +**`.hydratable()` integration** — the style tag is included inside the `data-ilha` wrapper regardless of the `snapshot` option. |
| 277 | + |
| 278 | +> **Note:** Calling `.css()` more than once on the same builder chain is not supported. In dev mode a warning is logged and only the last stylesheet is used. Compose all your styles into a single `.css()` call. |
| 279 | +
|
| 280 | +--- |
| 281 | + |
226 | 282 | ### `.slot(name, island)` |
227 | 283 |
|
228 | 284 | Embeds a child island as a named slot. The child island is mounted and managed independently. During SSR the slot renders the child's HTML inline; during client mount the child island is activated for interactivity. |
@@ -430,6 +486,41 @@ raw("<strong>bold</strong>"); // → passes through unescaped |
430 | 486 |
|
431 | 487 | --- |
432 | 488 |
|
| 489 | +### `css\`\`` tagged template |
| 490 | + |
| 491 | +A passthrough tagged template for CSS strings. Functionally identical to a plain template literal — no runtime transformation occurs. Its purpose is purely to enable editor tooling (LSP syntax highlighting, Prettier formatting) to recognise the contents as CSS. |
| 492 | + |
| 493 | +```ts |
| 494 | +import { css } from "ilha"; |
| 495 | + |
| 496 | +const styles = css` |
| 497 | + button { |
| 498 | + background: teal; |
| 499 | + color: white; |
| 500 | + } |
| 501 | + .label { |
| 502 | + font-weight: 700; |
| 503 | + } |
| 504 | +`; |
| 505 | + |
| 506 | +ilha.css(styles).render(() => `<button class="label">Go</button>`); |
| 507 | +``` |
| 508 | + |
| 509 | +Interpolations work as normal string concatenation: |
| 510 | + |
| 511 | +```ts |
| 512 | +const accent = "coral"; |
| 513 | +const styles = css` |
| 514 | + button { |
| 515 | + background: ${accent}; |
| 516 | + } |
| 517 | +`; |
| 518 | +``` |
| 519 | + |
| 520 | +> **Note:** `css` (the named export) is the plain passthrough tag for tooling. `ilha.css` is the builder chain method that attaches styles to an island. They are intentionally separate. |
| 521 | +
|
| 522 | +--- |
| 523 | + |
433 | 524 | ### `type(coerce?)` |
434 | 525 |
|
435 | 526 | Creates a lightweight Standard Schema validator for use with `.input()` — useful when you don't want a full validation library. |
|
0 commit comments