# quark-sheet

Drop a Quark sheet next to your markup — bind, render, and react without a component runtime.


```html
<section>
  <quark-sheet>
    details[open] summary {
      content: "Panel Open";
    }
    details:not([open]) summary {
      content: "Panel Closed";
    }
  </quark-sheet>
  <details>
    <summary></summary>
    <p>This is the panel content.</p>
  </details>
</section>
```


## Features

- **Sibling scope** Sheet + targets share a parent — Quark watches that host
- **Global sheets** `is-global` runs top-level rules document-wide
- **Inline or remote** Paste Quark in the element, or load `src-url`
- **Lifecycle state** `is-loading` / `is-success` / `is-error` + matching events (from [loadable-element](/packages/loadable-element))
- **Reload** The `--reload` command drops the shared cache entry for `src-url` and fetches again
- **Auto (un)register** Connect registers; disconnect tears down cleanly

## Installation


`@excom/quark-sheet` v0.2.1

```bash
pnpm add @excom/quark-sheet
```

```bash
npm install @excom/quark-sheet
```

```bash
yarn add @excom/quark-sheet
```

### Import

```ts
import "@excom/quark-sheet";
```



## Usage

Place `<quark-sheet>` under the same parent as the elements it should orchestrate.
Inline Quark text is enough for most apps. An inline sheet reads its text when it connects, so load the scripts with `defer`, as a module script, or after the markup (end of `<body>`); a plain `<script src>` in `<head>` leaves it dead. A `src-url` sheet is not affected.

```html
<section>
  <quark-sheet>
    details[open] summary { content: "Panel Open"; }
    details:not([open]) summary { content: "Panel Closed"; }
  </quark-sheet>
  <details>
    <summary></summary>
    <p>This is the panel content.</p>
  </details>
</section>
```

By default the sheet is scoped to its parent. Add `is-global` to run
top-level rules in the root context (e.g. reading a provider above the
host); rules inside an explicit `@scope { }` block stay host-scoped either
way. Language details live in the [`quark`](/packages/quark) docs.

An inline sheet is HTML content: a browser reads `<` followed by a letter, `/`, `!` or `?` as markup, in a sheet comment or string too, and a `<title>` or `<textarea>` there takes the rest of the page as its text (the sheet fails with a parse error far from the cause). Keep such text out of an inline sheet, or load the sheet with `src-url`.

For [prerendering](/docs/prerendering), `@excom/quark-sheet/server` exports `settle`, the hook that holds a page until its sheets are quiet. `@excom/nucleus-kit/server` already has it.

### API Reference


#### Attributes

| Name | Surface | Type | Default | Values | Description | Inherited from |
| --- | --- | --- | --- | --- | --- | --- |
| `src-url` | option | `string` |  | `<URL>` | URL of a remote `.quark` / text sheet. When set, contents are fetched into the live sheet (replacing inline text). |  |
| `is-global` | option | `boolean` |  |  | Run top-level rules in the root context (the whole document) instead of implicitly wrapping the sheet in `@scope { }`. Rules nested inside an explicit `@scope { }` block remain scoped to the host either way. |  |
| `is-loading` | state | `boolean` |  |  | Fetch in progress. |  |
| `is-success` | state | `boolean` |  |  | Sheet parsed and registered on the host. |  |
| `is-error` | state | `boolean` |  |  | Fetch or Quark parse/register failed. |  |
| `quark-instance` | state | `Quark` |  |  | Live `Quark` instance while registered. |  |
| `did-load` | state | `boolean` |  |  | Work has succeeded and no failure followed. Stays set while a refresh loads, so content can stay on screen (stale-while-revalidate): gate it on `[did-load]` rather than `[is-success]`. Cleared on error. | `@excom/loadable-element` |

#### Provision

| Name | Type | Description | Inherited from |
| --- | --- | --- | --- |
| `provision` | `unknown` | The result of the most recent work on success, or the error payload on failure. Shape is defined by the composing element. Not reflected as an attribute. | `@excom/loadable-element` |

#### Fires

| Name | Type | Description | Inherited from |
| --- | --- | --- | --- |
| `quark-sheet-loading` | `QuarkSheetLoadingEvent` (`CustomEvent & { type: "quark-sheet-loading"; detail: void; bubbles: true; cancelable: true; composed: true }`) | After `is-loading` becomes true (fetch in flight). |  |
| `quark-sheet-success` | `QuarkSheetSuccessEvent` (`CustomEvent & { type: "quark-sheet-success"; detail: void; bubbles: true; cancelable: true; composed: true }`) | After the sheet parses and registers successfully (`is-success`). |  |
| `quark-sheet-error` | `QuarkSheetErrorEvent` (`CustomEvent & { type: "quark-sheet-error"; detail: unknown; bubbles: true; cancelable: true; composed: true }`) | After parse / fetch failure (`is-error`). `event.detail` is the error. |  |
| `quark-sheet-loading` | `LoadableLoadingEvent` (`CustomEvent & { type: "{tag}-loading"; detail: void; bubbles: true; cancelable: true; composed: true }`) | After `is-loading` is set (work started). | `@excom/loadable-element` |
| `quark-sheet-success` | `LoadableSuccessEvent` | After `is-success` is set. `event.detail` is the new `provision`. | `@excom/loadable-element` |
| `quark-sheet-error` | `LoadableErrorEvent` | After `is-error` is set. `event.detail` is the error payload (also stored as `provision`). | `@excom/loadable-element` |

#### Commands

| Command | Action |
| --- | --- |
| `--reload` | Drops the shared text cache entry for `src-url` and fetches the sheet again (the cache is page-wide: every element loading the same URL shares it). No-op without `src-url`. |

#### CSS Aliases

| Alias | Kind | Matches | Description |
| --- | --- | --- | --- |
| `:--quark-sheet` | element | `quark-sheet`, `.tag-quark-sheet` |  |



### Examples

#### Provider data

`prop("provision")` reads a `<provider-fetch>` provision on success and fills a title.


```html
<section>
  <provider-fetch api-url="/api/todos/1">
    <p>Title: <span bind-title></span></p>
  </provider-fetch>
  <quark-sheet>
    provider-fetch[is-success] {
      $todo: prop("provision").body;
      [bind-title] {
        content: $todo.title;
      }
    }
  </quark-sheet>
</section>
```

## Release notes

### 0.2.0 (2026-10-08)

- Add `@excom/quark-sheet/server`, which exports `settle`: the prerender hook that holds a page until its sheets are quiet, without the 1 s limit of `Quark.whenSettled()`

### 0.1.1 (2026-09-23)

- Ship only dist (and declared extras) in the npm tarball; drop build logs, tests and sources
