npm package: @skirbi/semtic
Description: HTML for humans and CSS
Author: Wesley Schwengle
Latest version: 0.0.6

<!--
SPDX-FileCopyrightText: 2025, 2026 Wesley Schwengle <wesleys@opperschaap.net>

SPDX-License-Identifier: MIT
-->

# @skirbi/semtic

Semantic HTML authoring components built on top of `@skirbi/sugar`.

This package provides composable, framework‑agnostic Web Components
that:

-   Stay in the light DOM
-   Generate real semantic HTML
-   Avoid class-based utility noise
-   Unify form behavior
-   Separate layout from styling
-   Integrate with `@skirbi/pinta` for theming


# Installation

``` bash
npm install @skirbi/semtic
```

Register everything:

``` js
import '@skirbi/semtic/all.mjs';
```

Or register selectively:

``` js
import { SemticForm, SemticInput } from '@skirbi/semtic';
SemticForm.register();
SemticInput.register();
```


# File Overview

## index.mjs

Exports public components without registering them automatically.

## register-semtic.mjs

Registers all exported semtic components via `customElements.register()`.


# Structural Components

## semtic-page.mjs

Wraps content in `<main>`.

## semtic-panel.mjs

Semantic container built on `<section>`. Supports `labelledby` → maps to
`aria-labelledby`.

## semtic-section.mjs

Section with optional header generation. Attributes: `title`,
`subtitle`.

## semtic-header.mjs

Generates semantic header structure with `<h1>` and `<h2>`.

## semtic-actions.mjs

Footer-style container for grouped actions.

## semtic-article.mjs

Structured `<article>` with header + body. Attributes: `title`,
`subtitle`, `content-id`.

## semtic-article-meta.mjs

Auto-generates semantic metadata. Attributes: `date`, `readingtime`,
`author`, `tags`.


# Forms

All form controls share a unified contract:

-   Real HTML controls
-   Label support
-   Required indicator
-   Error slot
-   Attribute forwarding
-   Light DOM only

## semtic-form.mjs

Wraps `<form>`. Optional `legend` generates `<fieldset>`.

## semtic-fieldset.mjs

Semantic grouping for form controls with description + error handling.

## semtic-input.mjs

Unified input control. Attributes: `label`, `type`, `required-label`,
`id`, `name`, `placeholder`, `value`.

## semtic-textarea.mjs

Textarea equivalent of semtic-input.

## semtic-checkbox.mjs

Checkbox with unified behavior.

## semtic-radio.mjs

Radio button with unified behavior.

## semtic-tooltip.mjs

Composable tooltip. Supports long-form nested usage or short
attribute-based usage.


# Layout Primitives

Structural only. Styling is CSS responsibility.

## semtic-grid

2D layout helper. Attributes: - `semtic-columns` - `semtic-columns-sm` -
`semtic-columns-md` - `semtic-columns-lg` - `semtic-gap`

## semtic-flex

1D alignment helper. Attributes: - `semtic-direction` -
`semtic-justify` - `semtic-align` - `semtic-gap`

## semtic-stack

Vertical rhythm helper. Attribute: `semtic-gap`.

## semtic-select

`semtic-select` is the semantic form shell around
`HTMLElementSugarSelect`.

It adds:

-   label support (`label=""`)
-   required marker (`required` + `required-label=""`)
-   error slot (`slot="error"`)

It **keeps** all SugarSelect behavior:

-   static options via `options` (JSON array)
-   optional compatibility alias `data-options`
-   remote fetching via `endpoint`
-   local/remote search (`searchable`, `min-chars`, `debounce`,
    `search-min`)
-   mapping via `jpath`, `jpath-label`, `jpath-value`
-   templates via `jpath-label-template`, `jpath-value-template`\
    (templates win; no fail-fast)

Example (static):

``` html
<semtic-select
  label="Division"
  name="division_id"
  required
  options='[{"id":1,"name":"A"},{"id":2,"name":"B"}]'
  jpath-label="name"
  jpath-value="id"
></semtic-select>
```

Example (remote):

``` html
<semtic-select
  label="User"
  name="user_id"
  searchable
  endpoint="/api/users"
  param="q"
  jpath="data"
  jpath-label-template="{name} ({email})"
  jpath-value-template="user:{id}"
  search-min="10"
></semtic-select>
```

Error slot:

``` html
<semtic-select label="Division" required>
  <span slot="error">Please pick a division</span>
</semtic-select>
```

## semtic-nav

Minimal structural wrapper that produces a real `<nav>`.

``` html
<semtic-nav>
  <a href="/">Home</a>
  <a href="/events">Events</a>
</semtic-nav>
```

## semtic-breadcrumb

A semantic breadcrumb primitive:

-   outputs `<nav aria-label="Breadcrumb">`
-   wraps items into `<ol><li>...`
-   optional separator injection via `semtic-separator=">"` (opt-in)

Example:

``` html
<semtic-breadcrumb semtic-separator=">">
  <a href="/">Home</a>
  <a href="/events">Events</a>
  <span>Competition</span>
</semtic-breadcrumb>
```

## Layout primitives

These are structural helpers. No styling is shipped.

### semtic-grid

``` html
<semtic-grid semtic-columns="1" semtic-columns-md="2"
             semtic-columns-lg="3" semtic-gap="4">
  <semtic-panel>One</semtic-panel>
  <semtic-panel>Two</semtic-panel>
  <semtic-panel>Three</semtic-panel>
</semtic-grid>
```

### semtic-flex

``` html
<semtic-flex semtic-justify="end" semtic-gap="2">
  <button type="button">Cancel</button>
  <button type="submit">Save</button>
</semtic-flex>
```

### semtic-stack

``` html
<semtic-stack semtic-gap="4">
  <h2>Title</h2>
  <p>Text</p>
</semtic-stack>
```

# Reference examples

## 1) Login page

``` html
<html semtic-theme="client1">
  <body>
    <semtic-grid semtic-columns="1">
      <semtic-panel semtic-theme-tone="primary" semtic-theme-variant="solid">
        <semtic-stack semtic-gap="4">
          <semtic-header
            title="Welcome back"
            subtitle="Sign in to continue"
          ></semtic-header>

          <semtic-form>
            <semtic-stack semtic-gap="3">
              <semtic-input
                label="Email"
                type="email"
                name="email"
                autocomplete="email"
                required
              ></semtic-input>

              <semtic-input
                label="Password"
                type="password"
                name="password"
                autocomplete="current-password"
                required
              ></semtic-input>

              <semtic-flex semtic-justify="end" semtic-gap="2">
                <button type="submit" semtic-theme-tone="primary">Login</button>
              </semtic-flex>
            </semtic-stack>
          </semtic-form>
        </semtic-stack>
      </semtic-panel>
    </semtic-grid>
  </body>
</html>
```

## 2) Nav + breadcrumbs + 3-column article (responsive)

``` html
<html semtic-theme="client1">
  <body>
    <semtic-stack semtic-gap="4">

      <semtic-nav>
        <a href="/">Home</a>
        <a href="/blog">Blog</a>
        <a href="/about">About</a>
      </semtic-nav>

      <semtic-breadcrumb semtic-separator=">">
        <a href="/">Home</a>
        <a href="/blog">Blog</a>
        <span>Article</span>
      </semtic-breadcrumb>

      <semtic-article title="Three column layout" subtitle="Responsive via CSS breakpoints">
        <semtic-grid
          semtic-columns="1"
          semtic-columns-md="2"
          semtic-columns-lg="3"
          semtic-gap="4"
        >
          <semtic-panel>
            <semtic-header title="Column 1"></semtic-header>
            <p>Intro / lead-in content.</p>
          </semtic-panel>

          <semtic-panel>
            <semtic-header title="Column 2"></semtic-header>
            <p>Main content.</p>
          </semtic-panel>

          <semtic-panel>
            <semtic-header title="Column 3"></semtic-header>
            <p>Related links or aside.</p>
          </semtic-panel>
        </semtic-grid>
      </semtic-article>

    </semtic-stack>
  </body>
</html>
```

Notes:

-   Responsiveness is defined in your CSS (`semtic-columns-md`,
    `semtic-columns-lg`).
-   Style and tokens come from `@skirbi/pinta`.


# Theming

Semtic does not ship styling. Use `@skirbi/pinta` for themes, tones,
variants, and layout tokens.

See: `@skirbi/pinta`

Use theme attributes:

``` html
<html semtic-theme="client">
  <semtic-panel semtic-theme-tone="primary" semtic-theme-variant="solid">
    ...
  </semtic-panel>
</html>
```

See:

# Philosophy

Semtic is:

-   An authoring layer
-   Semantic-first
-   Minimal
-   Framework-independent
-   Layout-clean
-   Accessibility-aware

Semtic is not:

-   A CSS framework
-   A UI kit
-   A design system

# Status

Stable for real-world usage. Designed to evolve slowly. YAGNI by
default.