Skip to content
DesignOSby h4rithd
Components/Synchronized Workbench
block / developer-tools

Synchronized Workbench

Paired text workspaces that resize together through pointer and keyboard controls.

PREVIEW READY
LIVE PREVIEWDARK / LIGHT COMPATIBLE
component.tsx
import { Button } from "@/components/designos/button"

export function Interface() {
  return <Button>Initialize</Button>
}
INSTALL / SOURCE REGISTRY

Add Synchronized Workbench to your project

The command adds the component source and its DesignOS base dependency.

$pnpm dlx shadcn@latest add https://designos.h4rithd.com/r/synchronized-workbench.json
registry/default/blocks/synchronized-workbench.tsx
"use client"

import * as React from "react"
import "@/components/designos/designos.css"

export function SynchronizedWorkbench({ input, output, onInputChange, minHeight = 240, maxHeight = 760 }: { input: string; output: string; onInputChange: (value: string) => void; minHeight?: number; maxHeight?: number }) {
  const [height, setHeight] = React.useState(360)
  const start = React.useRef({ y: 0, height: 360 })
  const clamp = React.useCallback((value: number) => Math.min(maxHeight, Math.max(minHeight, value)), [maxHeight, minHeight])
  const begin = (event: React.PointerEvent<HTMLButtonElement>) => {
    event.currentTarget.setPointerCapture(event.pointerId)
    start.current = { y: event.clientY, height }
  }
  return <div className="dos-workbench" style={{ "--dos-workbench-height": `${height}px` } as React.CSSProperties}>
    <section className="dos-workbench__pane"><header className="dos-workbench__head"><span>Input</span><span>{input.length} chars</span></header><textarea aria-label="Input" value={input} onChange={(event) => onInputChange(event.target.value)} placeholder="Enter text…" /><footer className="dos-workbench__meta">Resizable · synchronized</footer></section>
    <section className="dos-workbench__pane"><header className="dos-workbench__head"><span>Output</span><span>{output.length} chars</span></header><textarea aria-label="Output" value={output} readOnly /><footer className="dos-workbench__meta">Read only</footer></section>
    <button type="button" className="dos-workbench__resize" role="separator" aria-label="Resize both workbench panes" aria-orientation="horizontal" aria-valuemin={minHeight} aria-valuemax={maxHeight} aria-valuenow={height} onPointerDown={begin} onPointerMove={(event) => { if (event.currentTarget.hasPointerCapture(event.pointerId)) setHeight(clamp(start.current.height + event.clientY - start.current.y)) }} onKeyDown={(event) => { const amount = event.shiftKey ? 48 : 16; if (event.key === "ArrowUp") { event.preventDefault(); setHeight((value) => clamp(value - amount)) } if (event.key === "ArrowDown") { event.preventDefault(); setHeight((value) => clamp(value + amount)) } if (event.key === "Home") { event.preventDefault(); setHeight(minHeight) } if (event.key === "End") { event.preventDefault(); setHeight(maxHeight) } }} />
  </div>
}

Component contract

  • Source-owned after installation
  • Dark and light theme variables
  • Keyboard and visible-focus behavior
  • Reduced-motion fallback
  • Responsive from 320px upward
  • IBM Plex Sans + JetBrains Mono hierarchy