Resizable two-pane workbench splitter with controlled ratio support and keyboard-accessible divider semantics.
Install @wyrd-company/react or the Flutter package and use it directly —
your DESIGN.md does the styling.
catalog/contracts/split.ymlsource of truth · verbatim
$schema: https://thewyrdingway.dev/schemas/component-contract.schema.ymlcontractVersion: 0.1.0identity:name: Splittag: wyrd-splitpackage: wyrd.component.splittitle: Splitsummary: Resizable two-pane workbench splitter with controlled ratio support and keyboard-accessible divider semantics.relationships:related-to: - quality-parity-and-gatesclassification:category: layoutcomposition: multi-slotinteractive: truetarget-strategy:react: requiredflutter: requiredsurface:properties: - name: directiontype:kind: enumvalues: - row - columnrequired: falsedefault: rowreflects: trueserializable: truesummary: Split axis; row places panes side-by-side, column stacks panes vertically. - name: ratiotype:kind: integerminimum: 10maximum: 90required: falsecontrolled: trueserializable: truesummary: Controlled first-pane share as a percentage. - name: default-ratiotype:kind: integerminimum: 10maximum: 90required: falsedefault: 50serializable: truesummary: Initial uncontrolled first-pane share as a percentage. - name: min-ratiotype:kind: integerminimum: 5maximum: 45required: falsedefault: 20serializable: truesummary: Minimum first-pane share enforced by implementations. - name: max-ratiotype:kind: integerminimum: 55maximum: 95required: falsedefault: 80serializable: truesummary: Maximum first-pane share enforced by implementations.slots: - name: startrequired: truecardinality: exactly-oneaccepts: - componentsummary: First pane content sized by the ratio. - name: endrequired: truecardinality: exactly-oneaccepts: - componentsummary: Second pane content sized to the remaining share.events: - name: ratio-changepayload:ratio:kind: integerbubbles: truecomposed: truecancelable: falsesummary: Emitted from drag and keyboard resizing with the clamped first-pane ratio.states: - name: defaultsource: platformsummary: Enabled row splitter. - name: columnsource: propertysummary: Column direction derived from direction. - name: focus-visiblesource: platformsummary: Keyboard-visible focus on the divider. - name: draggingsource: platformsummary: Pointer drag is actively resizing panes.parts: - name: rootsummary: Split flex container.slots: - start - end - name: startsummary: First pane.slots: - start - name: dividersummary: Focusable ARIA separator used to resize panes. - name: endsummary: Second pane.slots: - endtokens:divider:color: color.outlinehover-color: color.primarythickness: 1pxhit-area: spacing.mdmessages: []obligations:accessibility:role: separatorkeyboard: - Tab moves focus to the divider. - ArrowLeft and ArrowRight adjust row splits by 1 following visual direction, so RTL reverses the physical-key effect. - ArrowUp and ArrowDown adjust column splits by 1. - Home moves the ratio to min-ratio. - End moves the ratio to max-ratio.semantics: - Divider is focusable with tabindex=0. - Divider exposes aria-orientation vertical for row direction and horizontal for column direction. - Divider exposes aria-valuenow from the clamped ratio and aria-valuemin/aria-valuemax from min-ratio/max-ratio. - The splitter is unnamed in v1; surrounding workbench chrome owns contextual labeling.behavior:model: inputinteractions: - Dragging the divider computes ratio from pointer position inside the split container. - Keyboard resizing emits ratio-change using the same clamp behavior as dragging. - Controlled ratio wins over default-ratio; uncontrolled implementations track the latest emitted ratio locally. - Implementations clamp ratio into the resolved min-ratio/max-ratio range.hostEffects: - Dispatch ratio-change event.conditions: - rtl - density-compact - text-expansionsdui:status: blockedserializableProperties: []serializableSlots: []eventBindings: []notes: Split is workbench chrome, not a Layout DSL node. Static SDUI splits are served by Grid and Stack; revisit if authored UIs need resizable split panes.examples: - name: row-defaultstate: defaultproperties:default-ratio: 50slots:start: Navigationend: Editor - name: columnstate: columnproperties:direction: columndefault-ratio: 35slots:start: Editorend: Console - name: constrainedstate: defaultproperties:default-ratio: 60min-ratio: 20max-ratio: 80slots:start: Outlineend: Preview
01
Examples
Generated from the contract's examples block.
Previews are the published @wyrd-company/react component, themed by the
brand's role tokens — flip the site's light/dark toggle and they follow.
Initial uncontrolled first-pane share as a percentage.
min-ratio
integer
20
Minimum first-pane share enforced by implementations.
max-ratio
integer
80
Maximum first-pane share enforced by implementations.
03
Slots & events
Slot
Cardinality
Accepts
Summary
start
exactly-one
component
First pane content sized by the ratio.
end
exactly-one
component
Second pane content sized to the remaining share.
Event
Payload
Summary
ratio-change
ratio
Emitted from drag and keyboard resizing with the clamped first-pane ratio.
04
Tokens
The contract's token bindings. Open the shared contextual sidebar from any example;
primary swatches reflect the color you pick there. Error swatches show the active
preset's values; editing any knob switches to custom and resets error to TWW · Ink.
Binding
Token
divider.color
color.outline
divider.hover-color
color.primary
divider.thickness
1px
divider.hit-area
spacing.md
05
States
State
Source
Summary
default
platform
Enabled row splitter.
column
property
Column direction derived from direction.
focus-visible
platform
Keyboard-visible focus on the divider.
dragging
platform
Pointer drag is actively resizing panes.
06
Accessibility
From the contract's accessibility obligations. Role separator
Tab moves focus to the divider.
ArrowLeft and ArrowRight adjust row splits by 1 following visual direction, so RTL reverses the physical-key effect.
ArrowUp and ArrowDown adjust column splits by 1.
Home moves the ratio to min-ratio.
End moves the ratio to max-ratio.
Divider is focusable with tabindex=0.
Divider exposes aria-orientation vertical for row direction and horizontal for column direction.
Divider exposes aria-valuenow from the clamped ratio and aria-valuemin/aria-valuemax from min-ratio/max-ratio.
The splitter is unnamed in v1; surrounding workbench chrome owns contextual labeling.
Status: blocked. Split is workbench chrome, not a Layout DSL node. Static SDUI splits are served by Grid and Stack; revisit if authored UIs need resizable split panes.