Observed since 20 Oct, 18:26 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
1ch
Terminal UI components for React
Character-grid UI that runs in the browser. One <term-ui> element turns semantic HTML into a fixed-width terminal render -- boxes, tables, charts, progress bars, status lines -- all from standard tags.

Playground · Docs · npm
npm install 1ch
Register once, then forget about it:
import { registerTermUIElement } from "1ch";
import "1ch/style.css";
registerTermUIElement();
Drop it in with your preferred reactivity provider:
function DeployPanel() {
const [build, setBuild] = useState(0);
const { metrics } = useMetrics();
return (
<term-ui width="60" mode="dark">
<section gap="1">
<article title="deploy v2.4.1">
<progress label="build" value={build} max="100"></progress>
<progress label="tests" value="94" max="100"></progress>
</article>
<figure height="4" fill>
{metrics.map(v => <data value={v} />)}
</figure>
<nav>
<button onClick={() => deploy()}>deploy</button>
<button onClick={() => rollback()}>rollback</button>
</nav>
<footer left=" healthy" right="64s ago "></footer>
</section>
</term-ui>
);
}
<article> is a box. <progress> is a bar. <figure> is a chart. <nav> lays out horizontally. <footer> is a status line. No wrapper components, no special syntax -- just HTML that happens to render as a terminal.
Tables draw with │─┼. Progress bars fill with ████░░░░. Buttons are [ deploy ]. Everything snaps to a character grid and it just looks right.
Who needs designs for internal tools when a character grid gives you a clean UI for free? Dashboards, admin panels, monitoring views, CLI-style apps -- just write the HTML and it looks like something you'd actually want to use.
Your CSS still works -- display: grid, gap, grid-template-columns get picked up from getComputedStyle and mapped to the grid. It's a web component, so React, Vue, Svelte, htmx, plain HTML -- whatever. onClick on a <button> fires like you'd expect.
Zero dependencies. Also does markdown and JSON (source-format="markdown" on the element).
| Element | Becomes |
|---|---|
<article title="X"> | box |
<figure> | chart (text content, <data> children, or values) |
<footer left="X" right="Y"> | status bar |
<nav> | horizontal stack |
<progress> | bar |
<hr> / <hr label="X"> | separator / divider |
<pre> | code block |
<table> | table |
<section>, <div> | container (layout from CSS) |
Need custom behavior? Register your own compiler via registerHtmlTagCompiler(). Full details in the docs.
MIT
Download counts and popularity will appear here as the collector receives them.
| Package / target | Requirement | Relationship |
|---|---|---|
react-reconcilerEnvironment{
"local_name": "react-reconciler",
"alias": false,
"peer_metadata": null
} | ^0.33.0 | runtime |
tsupEnvironment{
"local_name": "tsup",
"alias": false,
"peer_metadata": null
} | ^8 | development |
reactEnvironment{
"local_name": "react",
"alias": false,
"peer_metadata": null
} | ^19 | development |
react-domEnvironment{
"local_name": "react-dom",
"alias": false,
"peer_metadata": null
} | ^19 | development |
@types/bunEnvironment{
"local_name": "@types/bun",
"alias": false,
"peer_metadata": null
} | latest | development |
typescriptEnvironment{
"local_name": "typescript",
"alias": false,
"peer_metadata": null
} | ^5 | development |
@types/reactEnvironment{
"local_name": "@types/react",
"alias": false,
"peer_metadata": null
} | ^19 | development |
@types/react-domEnvironment{
"local_name": "@types/react-dom",
"alias": false,
"peer_metadata": null
} | ^19 | development |
@types/react-reconcilerEnvironment{
"local_name": "@types/react-reconciler",
"alias": false,
"peer_metadata": null
} | ^0.33.0 | development |
reactEnvironment{
"local_name": "react",
"alias": false,
"peer_metadata": null
} | ^18 || ^19 | peer |
react-domEnvironment{
"local_name": "react-dom",
"alias": false,
"peer_metadata": null
} | ^18 || ^19 | peer |
Source distribution
{
"shasum": "caad9d6ba64003fa7ed70f39f0b965d07ff47bd4",
"tarball": "https://registry.npmjs.org/1ch/-/1ch-0.2.0.tgz",
"fileCount": 6,
"integrity": "sha512-x/RCBqQM/V0IXANLUUH2t4T4VNOp9ZwLU8jc8yJRPxwWX29p+rNKzknd3dYYAImZ5wFyTo0Gmtf2ujcvLWNNTw==",
"signatures": [
{
"sig": "MEUCIQDtdRgHyKfWnxvH1jrP1EPXb8KKBQ3AsVWGlxmlCn6YCAIgcrJxhwsVH0xVYzW2ysKhPvztNUETrxi3e4mn6ZLocCI=",
"keyid": "SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"
}
],
"unpackedSize": 351099
}Observed since 20 Oct, 18:26 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package_version:9444bb504d91d2fed86d41df14ea34c8c82412e7af48ef82182669fa161c75f3