frontend: add <hive-btn> component, use it for dialog buttons
mara: 'wait the common styles is literally just the button stuff? pls make a button component now as part of this pr and replace the usage in the modal. replacing all usages and finally removing the btn styles from common css is a follow up then.' <hive-btn> (hive-btn.js) is a customized built-in <button is="hive-btn"> with its own shadow root -- extending HTMLButtonElement keeps every native button behaviour (click/keyboard activation, :disabled, form participation) instead of re-implementing it on a generic wrapper. Shadow root holds only an adopted stylesheet + a <slot>, so the button's light-DOM content (label, or asyncBtn's swapped-in spinner span) renders through unchanged -- slotted content stays styled by the light-DOM cascade, so the global .spinner class still applies. Variants (cancel/confirm/danger) are a 'variant' attribute, not a CSS class, since they're a semantic prop of the component. Customized built-ins aren't supported in Safari/WebKit -- fine here, the project targets recent Firefox only (same reasoning as the original custom-elements pilot). Wired into modal.js: HiveDialog's buttons now render as <button is="hive-btn" variant="...">, replacing the old component-common.css .btn copy -- deleted that file + component- styles.js entirely (their sole purpose was giving dialog buttons a .btn look, which hive-btn now owns properly). dom.js's el() gained support so it can create customized built-ins the same way it creates everything else. hive-dialog.css dropped the now-dead .cancel/.confirm/.confirm.danger rules. Per mara's scoping: NOT touching the other .btn consumers across the app (dashboard/agent submit buttons, form() helper, etc.) or removing .btn from dashboard/common.css / agent/agent.css in this PR -- that migration + cleanup is an explicit follow-up. Verified with a full frontend build (grepped bundled JS for hive-btn/ variant to confirm it inlines); nix fmt clean.
This commit is contained in:
parent
bce666a9b2
commit
a588ed42ce
9 changed files with 123 additions and 122 deletions
40
frontend/packages/shared/src/hive-btn.js
Normal file
40
frontend/packages/shared/src/hive-btn.js
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
// hive-btn.js — <hive-btn>, a customized built-in `<button>` (`<button
|
||||
// is="hive-btn">`) with a shadow root for style encapsulation, replacing
|
||||
// the light-DOM `.btn` class as the button primitive for shadow-DOM
|
||||
// consumers (starting with modal.js's dialog buttons — see the frontend
|
||||
// components-split discussion on the forge issue tracker).
|
||||
//
|
||||
// Extending `HTMLButtonElement` (a "customized built-in element", not an
|
||||
// autonomous one) keeps every native `<button>` behaviour for free —
|
||||
// click/keyboard activation, `:disabled`, form participation/submission —
|
||||
// instead of re-implementing them on a generic wrapper. The shadow root
|
||||
// holds only a `<style>`-equivalent (adopted stylesheet) plus a `<slot>`
|
||||
// so the button's light-DOM content (its label, or asyncBtn's swapped-in
|
||||
// spinner span) renders through unchanged — slotted content stays styled
|
||||
// by the light-DOM cascade (global `.spinner` etc. still apply), only the
|
||||
// host element's own box/text styling is shadow-scoped.
|
||||
//
|
||||
// Customized built-ins aren't supported in Safari/WebKit (a deliberate
|
||||
// WebKit-team stance, unlikely to change) — fine here since the project
|
||||
// targets recent Firefox only.
|
||||
//
|
||||
// Usage: `el('button', { type: 'button', is: 'hive-btn', variant: 'danger' }, 'label')`
|
||||
// (dom.js's `el()` passes `is` to `document.createElement` so custom-
|
||||
// element upgrade happens at creation, not after). `variant` is one of
|
||||
// 'cancel' | 'confirm' | 'danger' | (unset, for the neutral/default look)
|
||||
// — a plain attribute, not a class, since it's a semantic prop of the
|
||||
// component rather than an arbitrary styling hook.
|
||||
|
||||
import hiveBtnCss from './hive-btn.css';
|
||||
|
||||
class HiveBtn extends HTMLButtonElement {
|
||||
connectedCallback() {
|
||||
if (this.shadowRoot) return; // guard: connectedCallback can re-fire (e.g. re-parenting)
|
||||
const root = this.attachShadow({ mode: 'open' });
|
||||
const sheet = new CSSStyleSheet();
|
||||
sheet.replaceSync(hiveBtnCss);
|
||||
root.adoptedStyleSheets = [sheet];
|
||||
root.append(document.createElement('slot'));
|
||||
}
|
||||
}
|
||||
customElements.define('hive-btn', HiveBtn, { extends: 'button' });
|
||||
Loading…
Reference in a new issue