Skip to content

Releases: zweiundeins/starbase

v0.7.0

Choose a tag to compare

@github-actions github-actions released this 07 Oct 20:30

Ten new components, seven of them drag-and-drop and editing surfaces from derekr's PD rockets; TypeScript in the playground, with a type check on every run, and components written in TypeScript; and a licence on every component page.

Added

  • Seven surfaces from derekr's PD rockets, under its Beer-Ware licence: sb-sortable-list, sb-drag-group, sb-kanban-board, sb-sortable-tree, sb-context-menu, sb-bento-workspace (experimental) and sb-inline-edit. They work over server-rendered markup and emit what the user did (a move, a rename, a menu action) for the server to apply. go run ./cmd/vendorpd vendors a release with the fixes in patches/pd-rockets applied, each ready to offer upstream, and their docs' demos are answered by the stateless GET /demo/arrange/{kind}. sb-kanban-board also moves lanes, by a grip, Alt and the arrows, or step buttons (sb-kanban-lane-move, with lane ids, so a server can refuse a stale move).
  • Three components that replace zweiundeins.gmbh's Lit components: sb-image-compare, two pictures of the same size with a divider the reader drags, taps or moves with the keys, and an optional full screen view; sb-toc, a table of contents that marks the section being read, with reading progress and a compact bar for narrow screens; and sb-typewriter, text typed behind a blinking cursor, or a cycle of phrases, without moving anything around it.
  • A component can name its licence with license: front matter; its page and its JSON-LD show it.
  • TypeScript in the playground: a switch turns component.js into component.ts, which runs with its types stripped on the server, its errors reported at the lines written. TypeScript, and JavaScript that starts with // @ts-check, is checked by TypeScript on the server on every run, against the types of the patched Datastar build, and its problems are underlined in the editor. TypeScript snippets can't be submitted as components yet. The compiler, TypeScript's native port, is embedded in the binary; release archives and the container image carry its licence and notices.
  • Components can be written in TypeScript: go tool task ts type-checks <slug>.ts strictly, with helper modules and .d.ts declarations from its folder, and writes the committed .js that the site, the install snippets and the pinned versions serve. sb-code-editor, sb-data-table, sb-date-picker, sb-dropdown, sb-select, sb-tree and sb-virtual-scroll are TypeScript now (their modules are the compiler's output, so they get new versions that behave the same), and the playground opens them as TypeScript.
  • A pull request's preview of a component written in TypeScript opens its .ts source with the TypeScript switch on, and the type check reads the modules it imports at that commit.
  • sb-code-editor: highlights TypeScript (language="ts"), and diagnostics underlines problems sent by the page or the server, the line under the code shows the one at the caret, and F8 and Shift+F8 move between them. A problem whose word has changed disappears, so an older list doesn't point at the wrong place. sb-code-playground hands its own diagnostics to its editors, per file.

Fixed

  • sb-code-playground: setting files while the console had output threw, and an error thrown while the code loads now shows its line.
  • The playground's size line read "undefined" until the first edit when its modules came from the browser's cache.
  • sb-pixel-board: a palette bound to a signal (data-attr) on an element added after load overflowed the stack. It, sb-code-editor, sb-count-up, sb-gauge, sb-qr-code and sb-relative-time no longer make such a binding depend on their own state.
  • sb-tree: selected rows and the open arrows stay visible in forced colours.
  • The gallery's "live demo" hint sits on the preview's top edge instead of covering the first item of a demo, and screen readers skip it.

v0.6.0

Choose a tag to compare

@github-actions github-actions released this 01 Oct 22:22

Time of day and time zones in the date picker; rich cells, a column picker and exports in the data table; keyboard focus that survives the virtual scroll's windows; copying without the Clipboard API; a shadow token for every overlay; and four more Rocket fixes, filed upstream.

Added

  • sb-relative-time takes time-zone, an IANA name for the date on hover, the threshold date and the day count, so a page that shows its times in the server's zone says "yesterday" by the server's calendar. The date on hover follows title-lang (auto is the browser's language), and title-style="numeric" shows it as numbers with seconds, like toLocaleString().
  • Every overlay's drop shadow comes from --sb-shadow-overlay, so a theme can soften or drop them all: sb-popover, sb-select's list, sb-dropdown's menu, sb-date-picker's calendar, sb-data-table's column picker, sb-modal, sb-drawer, sb-tooltip, sb-toast and sb-theme-switch's menu. Its value is one shadow without spread (some of them draw it with drop-shadow()), or none; each keeps its own shadow when the token is unset.
  • sb-date-picker takes time: a time row under the calendar, in steps (minutes by default, down to seconds), and an Apply button that commits the date and the time together; a form gets the value like a datetime-local field. With time-zone, it shows and reads the wall clock in an IANA zone and the value is an RFC 3339 instant with that zone's offset. Daylight saving gaps and overlaps resolve the way Temporal does.
  • sb-data-table cells can be rich: a link, a value with a muted suffix, or a badge ({value, text, suffix, href, tone}). Their text is never markup, and only http, https and mailto links are kept; sb-cell-activate reports a link's click. hidden-columns hides columns, which the server owns, and column-picker lets the user choose them (sb-columns, never pending). requestExport() emits sb-export with the order, the shown columns and the selection; the docs' star catalog answers it with a CSV or JSON download (GET /demo/data/rows/export, rate limited).

Changed

  • The patched Rocket build has four more fixes, twelve in all (patches/rocket). Each is filed upstream, with its repro page in docs/repro/.
    • #1224: a light component renders inside a data-ignore-morph ancestor instead of drawing nothing.
    • #1225: a removed element's mount root leaves the observed roots, so removed elements can be collected.
    • #1226: a definition that arrives after Datastar's first pass still applies the shadow host's light children.
    • #1227: the pending-host observer scans a parent once per batch, not once per moved child, so reordering 1,000 rows no longer takes seconds.
  • docs/repro/rocket-morph-ids/ shows a quiet case of #1209: a Rocket element inserted ahead of keyed moves breaks them without throwing, and only 0008's restored id maps fix it. A comment for #1209 is drafted in docs/upstream/08, not posted.

Fixed

  • sb-copy-button copies where the Clipboard API is missing or refuses (plain HTTP, a permissions policy): through a hidden textarea in its own shadow root, and as a last resort it selects the text in a panel and says which keys copy it. sb-copy tells which way it went (method), and sb-copy-error is cancelable; cancelling it keeps the old "failed" state.
  • Pages work over plain HTTP: the tab id comes from crypto.getRandomValues, which non-secure contexts have, instead of crypto.randomUUID.
  • sb-relative-time: where a daylight saving gap skips midnight (America/Santiago, America/Havana, Africa/Cairo), the day count turns at the jump instead of an hour before it.
  • sb-virtual-scroll keeps the keyboard focus on the same item when a window arrives. The morph patches the items by position, so the focused element showed another item afterwards, or the focus fell to the page when the morph removed it; now Tab and Shift+Tab walk the items one at a time across windows, also when pressed the moment a window lands, and over links in rows that have a tabindex and over controls inside components (an sb-checkbox). An item scrolled out of the window leaves the focus on the scroller until a window brings it back, a new list that ends before the focused item gives the focus to its last item (an empty one to the scroller), and a control in the header slot takes the focus without scrolling the list.

v0.5.0

Choose a tag to compare

@github-actions github-actions released this 29 Sep 20:34

Seven new components (a drawer, a popover, checkboxes, a date picker, a virtual scroll and a data table), docs that show the real server code behind their demos, and Starbase's pages on a patched Rocket until its fixes land upstream.

Added

  • sb-drawer: a <dialog> panel that slides in from the start, end, top or bottom edge, modal or not (modal="false"), with a header slot, a scrolling body and a fixed footer. The server owns open as on sb-modal; show(), hide() and sb-open / sb-close {reason, value} are the page's.
  • sb-popover: a panel anchored to a trigger, as a click dialog or a hover card (WCAG 1.4.13), in the top layer. It has 12 logical placements that flip and shift to stay on screen (CSS anchor positioning, with a JS fallback), an optional pixel arrow, and a server-owned open.
  • sb-checkbox, a pixel checkbox with a label and a mixed state (indeterminate), and sb-checkbox-group, several choices as one JSON array value from options or <sb-check> children, with an optional select-all. Both follow the command contract and submit like native checkboxes.
  • sb-date-picker: a date field with a calendar in a popover (or inline), for one ISO date or a {start, end} range committed as one value. It shows and reads dates in the page's language, starts the week on the locale's first day, takes min, max and disabled-dates from the server, and emits sb-month, so a page can send each month's disabled dates when they are needed.
  • sb-virtual-scroll: a list of any length that holds only the rows in view. The server renders each window as plain HTML (sb-window {offset, count}), and the list has a sticky header slot, columns for grids and scrollToIndex(). A server that answers fewer rows than asked for (a page-size cap) still fills the view.
  • sb-data-table: a table that scrolls in sb-virtual-scroll, with a sticky header, sorting, row selection as a command value (selected, confirm, revert()), sb-row-activate and the WAI-ARIA grid keyboard. A table that holds every row sorts it itself on a header click; one that holds a window asks the server (sb-sort).
  • The new layers close innermost first on Escape, nested in each other or in sb-modal, sb-dropdown and sb-select.
  • Docs show the real server code behind their demos. A fenced block named by its source (go source=internal/web/demo.go#Server.demoTelemetry) holds those declarations, go tool task listings fills it, and a test fails when it no longer matches the code; on the site it links to the file. The docs of sb-tree, sb-select, sb-gauge, sb-meter, sb-sparkline, sb-pixel-board, sb-virtual-scroll and sb-data-table, and "Commands and components" on the contribute page, have one.
  • Demo data for long lists: a million-star catalog computed from each star's index (GET /demo/data/list renders windows of it for sb-virtual-scroll), and its first 100,000 stars in SQLite, sortable by every column (GET /demo/data/rows for sb-data-table; migration 009, seeded once at startup).
  • Every component pull request gets a playground link for each revision, not only the ones the submission bot opens.

Changed

  • Starbase's pages run a patched build of Rocket: the v1.0.4 release with eight fixes, each filed upstream (patches/rocket, built into static/vendor/datastar-rocket.js by go tool task vendor). Install snippets load it too, pinned at /c/datastar@<build>/datastar-rocket.js and kept for good like component versions, so a page gets the same fixes; every component keeps working on the official release, and a patch goes once a Datastar release has its fix.
    • #1217: an effect that throws during disconnect no longer leaves the element dead.
    • #1218: moving an element keeps its state instead of running its setup again.
    • #1219: bool props follow HTML boolean attributes: checked="checked" reads as true, and false removes the attribute instead of writing "false".
    • #1220: components can be form-associated.
    • #1221: data-on:*__window inside a shadow root goes with its element.
    • #1222: instances share one stylesheet per CSS text instead of parsing their own.
    • #1223: observeProps hears an attribute write that decodes to the current value.
    • #1209: a morph that starts inside another (a Rocket element rendering while the morph connects it) no longer breaks the outer one, so elements with Rocket components inside can have ids. Upstream fixed it for its next release without a public commit, so this one is Starbase's own fix.
  • Gallery cards have ids again: a sort or a search moves them with their live previews instead of morphing one card into another.
  • Go modules updated, among them SQLite (modernc 1.60.1) and brotli 1.2.5.
  • The README shows a screenshot of the site instead of a mockup.

Fixed

  • sb-modal: a data-sb-close button in an sb-drawer nested in the modal closes only the drawer.
  • Long dashes are gone from the components' docs.

Known issues

  • On the official v1.0.4, ids on repeated or reordered elements that contain Rocket components still break Datastar's morph (#1209). The build the install snippets load has the fix; with the official release, leave the ids off until a release has it.
  • The form-like components are not form-associated yet (#1220): validity and required, <fieldset disabled>, <label for> and the form attribute don't reach them. The patched build can declare form association, but the components keep joining forms with listeners until a release can, so they behave the same on the official release.

v0.4.0

Choose a tag to compare

@github-actions github-actions released this 25 Sep 04:48

A review of all 35 components: smaller downloads (the bundle every page loads is 22% smaller), about a hundred bugs fixed, form participation for the form-like components, and browser tests for the value contract, forms and shrinking.

Changed

  • Component modules are shrunk before they are minified: the .docs() text, the manifest: block passed to rocket(), and comments and needless whitespace in CSS and HTML templates no longer ship. Modules are 18% smaller and the bundle 16%. Every component gets a new version once (the shrinking is part of the version hash), so pinned URLs keep working and the new files replace nothing. manifest.json is now published from the readable modules.
  • sb-code-editor loads Prism only when an editor highlights, so the bundle every page loads is 7.2 kB smaller; code shows uncoloured until it arrives. Prism is rebuilt from its language components (0.9 kB less, identical highlighting).
  • Size tables and the playground's size line no longer count a component as its own dependency (sb-dropdown showed 15.8 kB "with deps" for a 7.9 kB module) or a file only the docs' examples load (sb-autoloader's demo-badge.js).
  • Altogether, /c/bundle.js shrinks from 67.1 kB to 52.7 kB (brotli) and the catalog's modules from 86.2 kB to 75.1 kB, while fixing everything below and adding form participation.
  • The server can clear a value it never set: value="" (or value="0", checked="false", open="false") sent to an element rendered without that attribute now wins in sb-code-editor, sb-dropdown, sb-input, sb-radio-group, sb-rating, sb-select, sb-slider, sb-toggle and sb-tree; Rocket used to ignore it, since the decoded value didn't change. A removed attribute is still ignored, and a browser test checks both for every value component.
  • Forced colours (Windows High Contrast): focus rings, carets, checks, tracks, icons, status lights and the chosen item stay visible in sb-alert, sb-busy, sb-button, sb-card, sb-code-playground, sb-copy-button, sb-details, sb-dropdown, sb-input, sb-meter, sb-pixel-board, sb-radio-group, sb-select, sb-slider, sb-tabs, sb-theme-switch and sb-toggle. Some of them used to vanish.
  • The hidden attribute hides every component, also on pages without a [hidden] reset: most set their own display, which beat the browser's rule.
  • disabled="false" (what el.disabled = false writes) no longer dims a component or blocks its clicks: sb-button (and loading="false"), sb-dropdown, sb-radio-group, sb-rating, sb-select, sb-slider and sb-toggle.
  • Right-to-left pages: fills, carets, focus bars, close buttons, tips and arrow keys follow the reading direction in sb-alert, sb-busy, sb-copy-button, sb-details, sb-dropdown, sb-input, sb-odometer, sb-radio-group, sb-range, sb-rating, sb-select, sb-slider, sb-tabs, sb-theme-switch, sb-toast, sb-toggle and sb-tooltip. For example, sb-rating fills half units from the start side, sb-tooltip centres top and bottom tips on the trigger, and sb-odometer keeps its digits in left-to-right order.
  • Canvas components follow every theme change: sb-gauge and sb-sparkline repaint whenever a colour token changes, from any cause (a theme scoped to a container, a class, light-dark(), forced colours), not only on a theme-switch pick. A still sb-nebula or sb-starfield (speed 0 or reduced motion) repaints on a theme change or when the system turns light or dark, and sb-echarts' pie and funnel labels follow the theme too.
  • A removed sb-echarts, sb-gauge or sb-sparkline no longer throws on every later theme change: their window listeners outlived the element.
  • An invalid lang (en_US, de_DE, a stray space) no longer blanks sb-count-up, sb-echarts, sb-odometer or sb-relative-time: an underscore is read as a hyphen (de_DE is German), and other invalid tags fall back to the browser's locale. The first three also find the page's lang from inside another component's shadow root, and sb-echarts follows a changed lang.
  • A token's fallback (what a component uses on a page without Starbase's tokens) is the same in every component, and a test keeps it so: --sb-surface-raised in sb-dropdown and sb-toast, --sb-surface-hover in sb-button, --sb-danger in sb-copy-button and --sb-radius-sm (6px) in sb-tree had their own.
  • Form-like components take part in the <form> they sit in: sb-code-editor, sb-input, sb-radio-group, sb-range, sb-rating, sb-select, sb-slider and sb-toggle submit their value under their name the way their native counterparts do (a toggle sends name=on only when on, a multiple select one entry per pick, a radio group nothing until a choice is picked, a range its {start, end} JSON), so native submits, new FormData(form) and Datastar's contentType: 'form' include them, and a form reset brings back the server's value (a reset the page cancels leaves them alone). They are not form-associated elements yet, because Rocket can't declare one, so validity, <fieldset disabled>, <label for> and the form attribute don't reach them; each README's Forms section says what works. sb-input and sb-code-editor get a disabled prop. sb-tree stays commands-only, and sb-button neither submits nor resets a form.
  • sb-tabs emits input on every move, and change, sb-change and sb-tab-change only on commit (the last two fired on every arrow key). sb-change's detail now carries the tab's label. A click commits at once, the arrow keys, Home and End after a 250 ms pause, so running through the tabs sends one command instead of one per tab.
  • sb-input takes rev: when it changes, the server's value wins even if it is the same, so a command the server normalises back to the stored value (or ignores) no longer leaves the field pending. The Showcase call sign uses it.
  • sb-busy no longer sets aria-busy on itself: on an ancestor of its status region it could hold the announcement back, and a morph stripped it. Set it on the content that is loading; :state(busy) stays the styling hook.
  • sb-modal ignores a removed open attribute, like the other server-driven attributes: to close, the server sends open="false". Inline panels no longer show a close button that did nothing, the close button is part close, and the corners follow the theme's --sb-radius.
  • sb-meter's default warn and danger thresholds are 70% and 90% of its min–max range instead of the absolute values 70 and 90 (the same on 0–100). Its tone is :state(ok|warn|danger), and its blocks are part segment, lit ones also lit.
  • sb-dropdown's menu part (with role="menu") is now the panel inside each level's popover, which casts the drop shadow. Its Styling docs set tokens on the element, since a token set on ::part(menu) never reached the panel.
  • sb-toast identifies a toast without an id by its message (#2, #3… for repeats), which is the id sb-dismiss reports, so dismissing the first plain-string toast no longer hides the next one. sb-dismiss fires after the toast is hidden locally.
  • New hooks: sb-alert has an icon slot (in place of the status light) and :state(closed), and host.open reads and sets whether it shows; sb-qr-code's "Too much data" is an error slot in an error part, to translate and restyle it; sb-sparkline and sb-starfield take a label for their accessible name (label="" makes a starfield decoration); sb-range's thumbs follow --sb-slider-thumb and --sb-slider-thumb-edge, like sb-slider's; sb-tooltip stacks at --sb-z-tooltip (default 70).

Fixed

  • sb-alert comes back when the server changes its open attribute after a dismissal (unchanged markup keeps the dismissal), and a closed alert no longer leaves an empty gap in a grid or flex stack. Headings meet WCAG AA contrast on light themes, and long URLs wrap instead of pushing the close button out of the box.
  • sb-autoloader's sb-ready and el.ready wait until every component on the page at startup has loaded or failed (they fired at the timeout, with a wrong loaded count; timeout now only lifts the cloak), once per loader, also after a morph moves it. A module that doesn't define its tag is reported (sb-load-error) instead of blocking that tag for good, a failed module is fetched again when its tag reappears, and el.load(tag) and el.discover(root) return promises.
  • sb-busy no longer stays up forever when the element that fired a request is replaced or removed before the response (a Delete button whose row the response removes). Its label is announced when a wait starts, and one removed while up emits a last sb-busy-change { busy: false }.
  • sb-button no longer traps the keyboard while loading (Tab, Escape and page shortcuts work; clicks, Enter and Space stay blocked). A disabled button ignores clicks, el.click() included, and they no longer reach the element behind it. aria-label reaches the inner button or link, so icon-only buttons have a name, and slotted icons no longer shrink to nothing.
  • sb-card has a width of its own in flex rows, auto grid columns and fit-content layouts (it collapsed to 0 px), keeps inline markup in the flow of the text (block children now flow like a <div>, with their own margins), and collapses an empty body. It no longer clips tooltips that reach outside it or makes photos jagged, and in a linked card, footer actions and body links and buttons get their own clicks, and keyboard focus rings the whole card.
  • sb-code-editor: Shift+Tab without a selection no longer selects the start of the line (the next keystroke deleted it), and Enter or Tab that confirm IME input are left to the IME. Code from a child <script type="text/plain"> is the server's value (confirm is no longer pending on load, and revert() no longer empties the editor), edits survive a move, and the gutter ...
Read more

v0.3.0

Choose a tag to compare

@github-actions github-actions released this 24 Sep 15:32

Nine new components (35 in total), leaner delivery (minified modules, one precompressed bundle, brotli -11 everywhere), installation as tabs with pinned integrity, a Styling section for every component, and live sizes in the playground.

Added

  • 9 new components (26 → 35; 34 in the gallery, since sb-code-playground is now unlisted):
    • sb-dropdown: an actions menu whose items are commands (sb-select {name, value}), with submenus up to five levels, and radio groups for a menu that shows a current choice, also in its trigger. A native popover in the top layer, placed with CSS anchor positioning.
    • sb-radio-group: one choice out of a handful, with pixel radios, under the command contract. Choices come from sb-radio children or from the server's options, and the keyboard stays put when the server drops the focused choice.
    • sb-details: a disclosure that animates to its content's height, alone or as an exclusive accordion (group), built on a native <details>. open is view state the server may own.
    • sb-toast: a toast region the server fills. It stacks, announces and dismisses the server's list, while closing, countdowns and pausing stay with the viewer, so a morph never brings back a closed toast.
    • sb-busy: a spinner, bar or skeleton that shows itself while the Datastar requests it watches are in flight (no signal needed), or while the server says busy.
    • sb-odometer: a number that rolls its digit wheels to each new value. Only the digits that change turn, each the way the number moves (over the top when it climbs), separators follow the locale, and drum draws the wheels as 3D cylinders. Screen readers get the value once, as text. From Libretto's live-drive readout.
    • sb-echarts: Apache ECharts driven by an option the server sends as JSON. Colours come from the --sb-* tokens and follow a theme change without restarting, numbers and dates follow the page's language, and a slotted table is the fallback for readers without the chart. ECharts 6.1.0 is vendored unmodified from npm and loaded only when a chart comes near the screen. From Libretto, where it draws every chart.
    • sb-count-up: counts a number up the first time it is on screen, and on from where it stands when the server sends a new one. The server's text inside is what search engines and people without JavaScript see. From libretto.ch.
    • sb-autoloader: the site's autoloader as a component, for any web components: a tag map and/or a URL pattern, loading each tag the first time it appears (morphs included), with dependencies and an optional un-cloak.
  • The playground shows what your component weighs while you type: its component.js minified and compressed at brotli -11 (what a page downloads), with the components it renders and the files it imports, plus the minified and raw sizes. The server measures each edit with the same esbuild and brotli settings as the catalog, so the numbers match the component pages' size tables. When the code doesn't parse, the last good numbers stay, dimmed. On a narrow screen the line keeps only the downloaded size. sb-code-playground takes extra content for its top bar (slot="bar").
  • Every component's docs have a Styling section, like sb-gauge's: size, fonts, colour tokens and parts, reachable from the page's CSS (no shadow mode changes or @imports), with a live example. A test checks that every ::part() and --sb-… property a section names exists in the component's source. sb-echarts' Theming section is folded into it.
  • More styling hooks, each documented in its Styling section and unchanged by default: sb-card has a heading part, sb-alert heading and message; the selected tab (sb-tabs) and row (sb-tree) are also part selected, following the selection; sb-theme-switch's options are part option (option selected when chosen); --sb-code-editor-font-size, --sb-slider-thumb / --sb-slider-thumb-edge, --sb-toggle-knob and --sb-pixel-board-grid; sb-copy-button's icon scales with the button.
  • sb-button takes loading: an inline pixel spinner (the same one sb-busy draws), clicks and Enter blocked against double submits, aria-busy, and focus kept. It costs no space until it is loading; bind it to data-indicator.
  • sb-theme-switch takes a domain, so one theme choice can cover every subdomain. A domain the browser refuses falls back to this host instead of dropping the choice silently.
  • sb-theme-change carries scheme ("light" or "dark"): what the page now paints in, worked out from the theme's own color-scheme, so code that draws needs no list of theme names. The theme switch's docs gain a section on following the theme from a canvas.

Changed

  • Components follow your page's font. Where one uses a font token (sb-gauge's value, sb-button variant="pixel", sb-echarts), it now falls back to the page's font instead of a hard-coded monospace, so outside Starbase they match the page without any configuration. sb-gauge's value and label now scale with --sb-gauge-size, and its docs have a Styling section.
  • Pages load every component as one file (/c/bundle.js, 66 kB) instead of one module per component. Measured on production over slow 4G, a visit that includes the homepage is 250–450 ms faster, at the cost of about 265 ms for a visitor who only sees one component page. Once the bundle grows past 100 kB (brotli), pages go back to the autoloader on their own.
  • The Themes page remembers the previewed theme and the 8-bit switch for the session: they carry across pages and browser tabs, and render from the first paint. The gallery's sort is a session default too: a sort in the URL still wins (shared links show what was shared); without one, the gallery uses the last sort you chose. Search and category keep the sort and never change the default.
  • Installation snippets end with a copyable usage: instead of the gallery card's preview:. It is a new optional front-matter field: the smallest markup that shows how you'd use the component in your own page (no card sizing, demo signals or timers, forced open, or images that only exist on Starbase), with preview: as the fallback. 30 components have one; a copied sb-theme-switch, for one, now themes the page instead of a demo attribute. A test keeps demo wiring and Starbase-only paths out of every component's installation markup.
  • Assets are served precompressed at brotli -11 (gzip -9 as the fallback) instead of being compressed per request at level 5: every component module, the autoloader, the CSS bundles, the vendored Datastar build and the art. The size tables now show exactly the bytes a browser receives.
  • Installation on component pages is four tabs instead of one long block: Autoloader (the default), This component (its minified module pinned with its frozen integrity, plus every component it renders), Pinned (today's catalog snapshot with an integrity import map) and Self-host (each file's minified and readable link with its size, and an import map at your own Datastar). Each tab has one sentence and a snippet that is exactly what to paste, with its own copy button. The chosen tab is remembered for the session, across component pages and browser tabs, through a new kind of state: session preferences (session_prefs), for choices that should outlive a page.
  • Component modules are minified (esbuild) next to the readable source: every x.js has an x.min.js, and the autoloader and the site load those — about 23% less over the wire across the catalog. The readable file stays the default URL for the docs and the playground. Minified bytes are frozen per version, so an esbuild upgrade can never change a pinned URL. Size tables add a minified column, and gallery cards show the minified size.
  • sb-code-playground is no longer listed in the gallery: it is the machinery behind /playground rather than a community component. It stays served, versioned and documented, through a new unlisted: front-matter flag.
  • The main domain is now starbase.zweiundeins.gmbh; rocket.libretto.ch redirects there.
  • Live demos stand on a pixel grid: in the gallery the preview panel is visibly the component itself (and says "live demo" on hover), which is why it is the one part of a card that isn't the link to the component page. Demo stages in the docs use the same grid.

Fixed

  • sb-code-editor's highlighted text no longer drifts away from the caret and the line numbers: the <code> inside it had the browser's own monospace font, a second font that made every line 1 px taller (two rows off after 40 lines). It takes the editor's font, size and line height now, and a browser test (TestCodeEditorLinesAlign) measures the first and the last line against the caret and the gutter at two sizes. sb-theme-switch's select arrow follows the theme (it was a fixed light grey, faint on light themes), and sb-pixel-board's grid lines follow the blank cell colour, so they show on a light board.
  • sb-gauge, sb-sparkline and sb-echarts no longer pull in sb-theme-switch: a comment mentioning it was read as a dependency, so the autoloader loaded it, the size tables counted it and the install tab added a script for it. Dependencies are now found in the minified module, where comments are gone.
  • Installation tabs: "This component" now pins everything it loads through the import map's integrity (a script tag covers only its own file, so code-editor's Prism was unchecked), and already-minified vendored files are no longer renamed to a non-existent .min.min.js — which had dropped ECharts from the Pinned tab's integrity and broken its Self-host link.
  • sb-echarts wrote a missing value as “undefined” in tooltips and labels (its number formatter stringified whatever it was given); it now writes “-”, as ECharts does. Axis tooltips also leave out the series that have no value at the hovered point – a projection before...
Read more

v0.2.0

Choose a tag to compare

@github-actions github-actions released this 22 Sep 15:08

Eight new components (26 in total), a command contract that makes every value component CQRS-ready, continuous deployment, and a security, performance and SEO pass.

Added

  • 8 new components (18 → 26):
    • sb-nebula: a drifting WebGL nebula in dithered pixels. The first component that came in through the submission bot.
    • sb-theme-switch: auto, dark or light (or any themes), as radio buttons, a select or a header menu. It remembers the choice in a cookie, so the server renders the theme before the first paint (no flash). The Starbase header uses it for the site's own themes, with "auto" following the system (Deep Space or Daylight).
    • sb-rating: pixel hearts or stars for a score, with half steps, hover preview and keys.
    • sb-relative-time: "3 minutes ago" that stays current, in any language, with a server fallback.
    • sb-qr-code: pixel QR codes for any text or URL, with optional brand-coloured corners (uqr, vendored and verified).
    • sb-tree: a keyboard-friendly tree whose branches load lazily from the server; expanded and loaded are props the server can morph.
    • sb-select: filter, pick several, or autocomplete from the server through a results prop.
    • sb-range: a two-thumb slider whose {start, end} is one value, committed as one command.
  • Command contract for value components (input, slider, toggle, code editor, tabs, rating, tree, select, range): a name prop and sb-change {name, value} on commit, ready to post as a command. With confirm, :state(pending) marks an edit the server hasn't confirmed, and revert() returns to the server's value after a rejected command. The Showcase demonstrates the loop (pending, a server-normalized value, a rejected command).
  • Example dataset (a seeded universe of galaxies, systems, planets and moons) with generic demo endpoints, /demo/data/children and /demo/data/search, for docs and playground demos (into= names the signal, delay= simulates latency).
  • Component sizes: gallery cards show the download size (brotli, including the components it renders), and component pages have a Size table with original, gzip and brotli sizes for each file and each rendered component, plus a total. Datastar and Rocket are not counted.
  • Continuous deployment: after CI passes on main, the Deploy workflow ships the binary over a single-purpose SSH key to starbase-deploy, which verifies it, checks /healthz and rolls back if the new version isn't healthy. The unit, env and Caddy files are in deploy/.
  • Vendored libraries: a submission from a repository brings along every file the component imports relatively (up to 2 MB each), listed with its license banner in the PR. Imports are checked strictly: 'datastar' or files in the component's folder, never URLs or bare packages.
  • Submission pull requests get a playground preview link for every revision (/playground?preview=<commit>/<slug>) and a list of similar existing components, to spot duplicates before merging. When the pull request step fails, the bot tells the author on the issue.
  • Opt out of the 8-bit look: --sb-notch and data-sb-style="smooth" turn off pixel corners, notched frames and the pixel display font. The Themes page has a switch.
  • SEO: robots.txt, a sitemap, canonical URLs, Open Graph and Twitter cards, JSON-LD (WebSite with search, SoftwareSourceCode per component) and PNG icons rendered from the pixel art.
  • Contribute guidelines for component authors: the command contract, components with several values (one structured value per decision, view state and server data as separate props, sb-<verb> operations), and no optimistic updates (server results only come from the server's render; the user's own input stays, marked pending).

Changed

  • The server can set every component's value: a value/checked attribute the server changes wins over local edits, while re-sent identical markup leaves edits alone. Removed attributes are ignored (morphs also strip reflected ones), so to clear, send value="" / checked="false". The manual pre-upgrade property adoption and the dirty flags are gone (Rocket replays those writes itself).
  • sb-alert has an open prop, so the server can hide and re-show it. sb-theme-switch draws its icons as CSS masks.
  • The logo and the hero scene follow the site theme: they are inlined as SVG, and their themeable colours are --sb-art-* tokens. As standalone files (favicon) they keep the original colours.
  • Performance: brotli, zstd or gzip for pages and text assets; one minified, hashed CSS bundle; hashed, preloaded fonts; immutable static files; pixel art drawn as one path per colour; lazy playground preview frames, and no layout shift on /playground.
  • GitHub Actions updated to their Node 24 (LTS) majors.

Fixed

  • sb-copy-button: a refused clipboard write (no secure context, no permission, unfocused document) was silently ignored; it now shows "Copy failed" (failed-label) and emits sb-copy-error {value, error}. The result is announced through a role="status" region outside the button, and the tip is readable on light themes and no longer cut off on code blocks.
  • Demo endpoints answer CORS preflights, so components in the playground sandbox (opaque origin) can load demo data with @get, e.g. the lazy tree.
  • Playground: the preview theme picker applied the previous choice.
  • The playground can run components that import their own files (e.g. sb-code-editor and its vendored Prism): relative imports resolve against the component's folder.
  • Submissions from a playground link failed validation: the link was recorded as the component's source:, which must be a GitHub repository.
  • The hero scene keeps its proportions at every width; sb-theme-switch icons line up with their labels; light-theme contrast fixes.

Security

  • Versioned, immutable component URLs (/c/<slug>@<hash>/…) and catalog snapshots (/c/@<catalog>/autoloader.js), with SHA-384 integrity for every file (/c/@<catalog>/importmap.json). Sites can pin exactly what they reviewed; browsers refuse any file that changed. Old versions keep working after later deploys.
  • Vendored libraries are verified: vendor.json names each file's npm release, and the bot checks it byte for byte against the registry-verified tarball. Minified code that can't be verified is refused.
  • The Starbase service listens on a Unix socket and is denied all of localhost (other services on a shared host), with a fully hardened systemd unit. starbase-deploy asks a new binary its version inside a network-less sandbox with a timeout.
  • Pull request previews are limited to the repository's own submission branches; script-src is limited to /static/ and /c/.
  • Rate limits for snippet saves and painting (per session and per IP), and a cap on total snippet storage.
  • CI: actions pinned to commit SHAs (Dependabot keeps them current), job timeouts, Chrome's sandbox kept on for submitted code, the bot's write-capable job re-validates what the build job produced, CODEOWNERS for vendored code, CI/CD and deploy files, and tests that keep the production environment to deploy.yml.

Known issues

  • Datastar's morph is not re-entrant with Rocket components that are reordered by id: reported upstream as starfederation/datastar#1209, with a minimal reproduction and a fix in docs/repro/rocket-morph-reentrancy/. Starbase avoids the pattern.

v0.1.0

Choose a tag to compare

@github-actions github-actions released this 22 Sep 03:42

The first release: a community gallery of Rocket web components for Datastar.

Added

  • Gallery. Categories with counts, realtime full-text search (SQLite FTS5), sorting, and live previews. Per-tab filter state is kept on the server and mirrored in the URL.
  • Component pages. Rendered docs with live html preview examples and copyable source, API tables generated from Rocket manifests, an auto-generated props Playground, installation snippets and "Edit on GitHub".
  • 18 components: button, input, slider, toggle, alert, modal, tooltip, meter, card, tabs, copy-button, code-editor (Prism with Rocket-aware highlighting), code-playground, voxel (a software 3D renderer), starfield, gauge, sparkline and pixel-board.
  • Code playground. Edit a component's JavaScript and HTML with a sandboxed live preview (opaque-origin iframe), a console, theme switching, share links, and "Submit as component".
  • Showcase. Mission Control, a dashboard driven by server-pushed signals (/demo/telemetry), and a multiplayer pixel board with live presence.
  • Themes. An Open-Props-style token system (--sb-*), with four themes that restyle every component through shadow DOM.
  • Submitting components without tools. A GitHub issue form (paste code, link a repository, or paste a playground link) and a bot that validates the component, generates its manifest in headless Chrome, and opens a pull request.
  • Autoloader. /c/autoloader.js loads <sb-*> components on first use, follows morphs, knows dependencies between components, and offers ready and sb-cloak against the flash of undefined elements.
  • Architecture. CQRS throughout: commands answered with 204, a single SQLite writer that batches commands, one render stream per tab that re-renders the whole page, and Brotli across frames. GitHub sign-in for stars.
  • Tooling. Live reload (air), task manifests, a component scaffolder, CI (tests, templ check, manifest freshness, govulncheck, cross-platform builds, container image) and a release workflow.

Known issues

  • Datastar's morph is not re-entrant with Rocket components that are reordered by id. See docs/repro/rocket-morph-reentrancy/ for a minimal reproduction and a proposed upstream fix. Starbase avoids the pattern.