Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
d30102f
wp theme: sync with lms wp-editor-kit; theming playground story
juliacanzani Aug 15, 2026
98937ac
elementor theme: TUI token remapping (starting point)
juliacanzani Aug 15, 2026
469a153
elementor theme: magenta primary scale
juliacanzani Aug 15, 2026
9152666
elementor theme: fg-active on segmented items must follow the neutral…
juliacanzani Aug 15, 2026
d6c7437
elementor theme: neutral focus for text-like fields, accent for selec…
juliacanzani Aug 15, 2026
2b9174d
themes: dark fills + nested-interface cascade; elementor label spec
juliacanzani Aug 15, 2026
fe38793
elementor theme: notice styling per control-notice; segmented at 12px
juliacanzani Aug 15, 2026
6705bb3
elementor theme: combobox chevron matches the 12px control font
juliacanzani Aug 15, 2026
53dfb6b
elementor theme: token-field chips size fractionally from their control
juliacanzani Aug 15, 2026
f0359c9
elementor theme: notices follow the panel-alert recipe (3px stripe)
juliacanzani Aug 15, 2026
5f84070
elementor theme: semantic palette mapping, popover scaling, option hover
juliacanzani Aug 15, 2026
f8dcbf7
elementor theme: notice inner gaps per Elementor (8px/6px)
juliacanzani Aug 15, 2026
e3be56b
beaver-builder theme: TUI token remapping (starting point)
juliacanzani Aug 15, 2026
9edfaed
beaver-builder theme: fallbacks from the core bundle's own definitions
juliacanzani Aug 15, 2026
354808d
TangibleUI: bump to ^0.2.6 - default-context dark mode now works
juliacanzani Aug 15, 2026
cbbf952
storybook:fresh script - dev server with a clean Vite dep cache
juliacanzani Aug 15, 2026
e1aa9a7
TangibleUI: bump to ^0.2.7 - notice gap tokens now structural
juliacanzani Aug 15, 2026
5a548d3
TangibleUI: bump to ^0.2.8 - drop context workarounds now fixed at so…
juliacanzani Aug 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion assets/build/all.unlayered.min.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion assets/build/beaver-builder/index.min.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion assets/build/elementor/index.min.css

Large diffs are not rendered by default.

52 changes: 26 additions & 26 deletions assets/build/example.min.js

Large diffs are not rendered by default.

52 changes: 26 additions & 26 deletions assets/build/index.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion assets/build/wp/index.min.css

Large diffs are not rendered by default.

96 changes: 96 additions & 0 deletions assets/src/components/Playground.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import type { Meta, StoryObj } from '@storybook/react-vite'

import { Field } from '../index'
import { Notice } from '@tangible/ui'

/**
* A theming playground: one page with a broad spread of controls, for
* eyeballing context themes (default / wp / elementor / beaver-builder — use
* the toolbar) and light/dark modes side by side while editing theme files
* like `assets/src/themes/wp.scss`.
*/

const choices = {
one: 'Option one',
two: 'Option two',
three: 'Option three'
}

const column: React.CSSProperties = {
display: 'flex',
flexDirection: 'column',
gap: '20px',
minWidth: 0
}

/**
* `context` must thread into every Field: portaled content (select listboxes,
* popovers) re-applies its wrapper from the field's own context prop — without
* it, dropdowns render in the default context regardless of the toolbar.
*/
const Playground = ({ context }: { context?: string }) => (
<div
style={{
display: 'grid',
gridTemplateColumns: 'repeat(auto-fit, minmax(280px, 1fr))',
gap: '24px 32px',
maxWidth: 960
}}
>
<div style={column}>
<Field context={context} type="text" name="pg-text" label="Text" description="A helper description" />
<Field context={context} type="textarea" name="pg-textarea" label="Textarea" />
<Field context={context} type="number" name="pg-number" label="Number" value="42" />
<Field context={context} type="date-picker" name="pg-date" label="Date" />
<Field context={context} type="time-picker" name="pg-time" label="Time" />
<Field context={context} type="color-picker" name="pg-color" label="Color" value="#6366F1" />
<Field context={context} type="gradient" name="pg-gradient" label="Gradient" />
</div>

<div style={column}>
<Field context={context} type="select" name="pg-select" label="Select" choices={choices} />
<Field
context={context}
type="select"
name="pg-select-multi"
label="Select (multiple)"
multiple={true}
choices={choices}
value={['one', 'two']}
/>
<Field context={context} type="combo-box" name="pg-combo" label="Combo box" choices={choices} />
<Field context={context} type="button-group" name="pg-buttons" label="Button group" choices={choices} value="one" />
<Field context={context} type="radio" name="pg-radio" label="Radio" choices={choices} value="one" />
<Field context={context} type="checkbox" name="pg-checkbox" label="Checkbox" value={true} />
<Field context={context} type="switch" name="pg-switch" label="Switch" value="on" />
<Field context={context} type="switch" name="pg-switch-off" label="Switch (off)" value="off" />
</div>

<div style={{ ...column, gridColumn: '1 / -1' }}>
{(['info', 'success', 'warning', 'danger'] as const).map(theme => (
<Notice key={theme} theme={theme}>
<Notice.Head title={`Notice (${theme})`} />
<Notice.Body>A theme-coloured notice for context theming.</Notice.Body>
</Notice>
))}
<Field context={context} type="dimensions" name="pg-dimensions" label="Dimensions" />
<Field context={context} type="simple-dimension" name="pg-simple-dimension" label="Simple dimension" />
<Field context={context} type="alignment-matrix" name="pg-alignment" label="Alignment matrix" />
<Field context={context} type="border" name="pg-border" label="Border" />
</div>
</div>
)

const meta = {
title: 'Theming/Playground',
component: Playground,
parameters: {
layout: 'padded'
}
} satisfies Meta<typeof Playground>

export default meta

type Story = StoryObj<typeof meta>

export const AllControls: Story = {}
2 changes: 2 additions & 0 deletions assets/src/contexts/beaver-builder/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,5 @@
}

@import '../../lib/prose-mirror/index.scss';

@import '../../themes/beaver-builder.scss';
2 changes: 2 additions & 0 deletions assets/src/contexts/elementor/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,5 @@ body.elementor-editor-active:has(#e-theme-ui-dark-css[media="(prefers-color-sche
}

@import '../../lib/prose-mirror/index.scss';

@import '../../themes/elementor.scss';
163 changes: 163 additions & 0 deletions assets/src/themes/beaver-builder.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
/*
* Beaver Builder context theme overrides (TUI token remapping).
* Keep context-specific styling centralized here instead of per-component files.
*
* BB's design system runs on --fl-builder-* custom properties (radius 6px,
* target-size 36px, input/panel/platter/heading bgs, accent
* hsl(194,100%,41%), hue-210 grey ladders, font-family) — every value here
* references the BB var first so the live builder drives it, with fallbacks
* taken from builder-css.bundle.min.css's own skin definitions (both modes).
*
* Unlike Elementor, BB focuses text fields with the accent blue, so no
* neutral-focus split here. Aside for later: BB marks DYNAMIC values purple
* (--fl-builder-dynamic-accent-color: #6221a2) and global values orange
* (#ff9600) — relevant to the fields dynamic-value treatment someday.
*
* The legacy per-component overrides in contexts/beaver-builder/components/
* still apply to the not-yet-migrated react-aria fields; this file themes the
* TUI-based ones.
*/

@mixin bb-tokens-light {
/* BB accent ladder from their own definitions: accent hsl(194,100%,41%),
hover 37%, selected 34%. */
--tui-theme-primary-subtlest: #e6f6fb;
--tui-theme-primary-subtler: #c2e8f4;
--tui-theme-primary-subtle: #8fd4ea;
--tui-theme-primary-base: var(--fl-builder-accent-color, #00a3d1);
--tui-theme-primary-strong: var(--fl-builder-accent-color-hover, #0093bd);
--tui-theme-primary-stronger: #0087ad;
--tui-theme-primary-strongest: #005c77;

--tui-color-bg: var(--fl-builder-panel-bg-color, #fbfcfd);
--tui-color-bg-surface: var(--fl-builder-input-bg-color, #ffffff);
--tui-color-bg-elevated: #ffffff;
--tui-color-bg-muted: var(--fl-builder-platter-bg-color, #eff2f5);
--tui-color-fg: var(--fl-builder-input-color, #000000);
--tui-color-fg-secondary: #525961;
--tui-color-fg-muted: var(--fl-builder-dim-color, #7e8b98);
--tui-color-border: var(--fl-builder-outline-color, #d2dae3);
--tui-color-divider: var(--fl-builder-divider-color, #bfcbd8);

--tui-color-fill-subtle: #eff2f5;
--tui-color-fill: #e4e9ee;
--tui-color-fill-strong: #d2dae3;

--tui-focus-ring-color: var(--fl-builder-selected-color, #0087ad);

/* Dropdown option hover wash */
--tf-option-hover: #eff2f5;
}

@mixin bb-tokens-dark {
/* Dark fallbacks from BB's own skin definitions: panel #23282e, inputs
RECESSED darker (#181b20), heading #101216, outline hsl(210,11%,25%).
The accent is shared across skins. */
--tui-theme-primary-subtlest: #062e3a;
--tui-theme-primary-subtler: #0a4254;
--tui-theme-primary-subtle: #0e566e;
--tui-theme-primary-base: var(--fl-builder-accent-color, #00a3d1);
--tui-theme-primary-strong: #33b5da;
--tui-theme-primary-stronger: #66c8e4;
--tui-theme-primary-strongest: #b3e4f2;

--tui-color-bg: var(--fl-builder-panel-bg-color, #23282e);
--tui-color-bg-surface: var(--fl-builder-input-bg-color, #181b20);
--tui-color-bg-elevated: var(--fl-builder-box-background, #23282e);
--tui-color-bg-muted: var(--fl-builder-heading-bg-color, #101216);
--tui-color-fg: var(--fl-builder-input-color, #ffffff);
--tui-color-fg-secondary: #c3c8cd;
--tui-color-fg-muted: var(--fl-builder-dim-color, #7e8b98);
--tui-color-border: var(--fl-builder-outline-color, #393f47);
--tui-color-divider: var(--fl-builder-divider-color, #343a41);

/* Control fills — see the nested-wrapper gotcha in wp.scss/elementor.scss */
--tui-color-fill-subtle: #262c33;
--tui-color-fill: #2e353d;
--tui-color-fill-strong: #393f47;

--tui-focus-ring-color: var(--fl-builder-selected-color, #33b5da);

--tf-option-hover: #393f47;
}

@mixin bb-control-remaps {
--tui-focus-ring-offset: 0px;
--tui-focus-ring-width: 1.5px;

/* BB's panel runs 36px controls (their target-size) at ~14px type */
--tui-control-height-sm: 28px;
--tui-control-height-md: var(--fl-builder-target-size, 36px);
--tui-control-height-lg: 44px;
--tui-control-font-size-sm: calc(13 * var(--tui-typography-size-multiplier, calc(1rem / 16)));
--tui-control-font-size-md: calc(14 * var(--tui-typography-size-multiplier, calc(1rem / 16)));
--tui-control-font-size-lg: calc(15 * var(--tui-typography-size-multiplier, calc(1rem / 16)));
--tui-button-font-size-sm: calc(13 * var(--tui-typography-size-multiplier, calc(1rem / 16)));
--tui-button-font-size: calc(14 * var(--tui-typography-size-multiplier, calc(1rem / 16)));
--tui-button-font-size-lg: calc(15 * var(--tui-typography-size-multiplier, calc(1rem / 16)));
--tui-button-font-weight: 500;
--tui-button-radius: var(--fl-builder-radius, 6px);
--tui-icon-button-radius: var(--fl-builder-radius, 6px);
--tui-input-radius: var(--fl-builder-radius, 6px);
--tui-select-trigger-radius: var(--fl-builder-radius, 6px);
--tui-select-content-radius: var(--fl-builder-radius, 6px);
--tui-multiselect-trigger-radius: var(--fl-builder-radius, 6px);
--tui-multiselect-content-radius: var(--fl-builder-radius, 6px);
--tui-accordion-radius: var(--fl-builder-radius, 6px);
--tui-card-radius: var(--fl-builder-radius, 6px);
--tui-notice-radius: var(--fl-builder-radius, 6px);
--tui-input-fg: var(--tui-color-fg);
--tui-input-bg: var(--tui-color-bg-surface);
--tui-select-trigger-bg: var(--tui-color-bg-surface);

/* Option hover follows the per-mode wash (combobox falls back through
select's token; multicombobox has its own). */
--tui-select-option-bg-hover: var(--tf-option-hover);
--tui-multiselect-option-bg-hover: var(--tf-option-hover);
--tui-multicombobox-option-bg-hover: var(--tf-option-hover);

/* Segmented groups (Align / Transform): grey group, the active segment
lifted to the surface colour (white in light). */
.tui-segmented.is-variant-pill {
--tui-segmented-radius: var(--tui-input-radius);
--tui-segmented-border: var(--tui-color-border);
--tui-segmented-bg: var(--tui-color-bg-muted);
--tui-segmented-padding: 0;
--tui-segmented-gap: 0;
--tui-segmented-item-radius: var(--fl-builder-radius, 6px);
--tui-segmented-item-padding: var(--tui-spacing-xxs) var(--tui-spacing-sm);
--tui-segmented-item-bg-active: var(--tui-color-bg-elevated);
--tui-segmented-item-fg-active: var(--tui-color-fg);
}
}

/* Panel labels: sentence case at panel ink, BB's font stack on the root. */
@mixin bb-labels {
font-family: var(--fl-builder-font-family, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif);

:is(label, .tui-label, .tui-field__label) {
font-weight: 400;
font-size: calc(14 * var(--tui-typography-size-multiplier, calc(1rem / 16)));
text-transform: none;
color: var(--tui-color-fg);
}
}

.tf-context-beaver-builder.tui-interface,
.tf-context-beaver-builder .tui-interface {
@include bb-tokens-light;
@include bb-control-remaps;
@include bb-labels;
}

/* Dark: via data-theme (storybook toolbar, host-controlled interfaces), via
BB's own skin class, and cascaded into nested interfaces (portaled-content
wrappers carry no data-theme — see the gotcha in wp.scss). */
.tf-context-beaver-builder.tui-interface[data-theme='dark'],
.tf-context-beaver-builder .tui-interface[data-theme='dark'],
.tf-context-beaver-builder.tui-interface[data-theme='dark'] .tui-interface,
.tui-interface[data-theme='dark'] .tf-context-beaver-builder.tui-interface,
.fl-builder-ui-skin--dark .tf-context-beaver-builder.tui-interface,
.fl-builder-ui-skin--dark .tf-context-beaver-builder .tui-interface {
@include bb-tokens-dark;
}
Loading
Loading