Skip to content
glyphcss

Text charts in vanilla JavaScript, React, and Vue

2D charts use @glyphcss/charts directly. They do not need React/Vue scene bindings. Install the package, render synchronously, and replace the <pre> text when your data changes.

Terminal window
npm install @glyphcss/charts
<pre id="chart" class="order-chart"></pre>
import { renderGlyphChart } from "@glyphcss/charts";
const host = document.querySelector<HTMLPreElement>("#chart")!;
try {
host.textContent = renderGlyphChart([18, 24, 21, 35, 42, 39, 48, 44, 38, 52, 61, 57], {
target: "web", color: "none", width: 60, height: 12,
}).text;
} catch (error) {
host.textContent = error instanceof Error ? error.message : String(error);
}
import { useMemo } from "react";
import { renderGlyphChart } from "@glyphcss/charts";
const defaultValues = [18, 24, 21, 35, 42, 39, 48, 44, 38, 52, 61, 57];
export function GlyphOrderChart({ values = defaultValues }) {
const text = useMemo(() => {
try {
return renderGlyphChart(values, { target: "web", color: "none", width: 60, height: 12 }).text;
} catch (error) {
return error instanceof Error ? error.message : String(error);
}
}, [values]);
return <pre className="order-chart">{text}</pre>;
}

Replace the values array when data changes so memoization can observe it.

<script setup lang="ts">
import { computed } from "vue";
import { renderGlyphChart } from "@glyphcss/charts";
const props = withDefaults(defineProps<{ values?: number[] }>(), {
values: () => [18, 24, 21, 35, 42, 39, 48, 44, 38, 52, 61, 57],
});
const text = computed(() => {
try {
return renderGlyphChart(props.values, { target: "web", color: "none", width: 60, height: 12 }).text;
} catch (error) {
return error instanceof Error ? error.message : String(error);
}
});
</script>
<template><pre class="order-chart">{{ text }}</pre></template>

Apply this stylesheet in each application. Load Glyph Mono separately, or use another font with complete charset coverage. Keep line-height: 1 so adjacent glyph rows align.

.order-chart {
font-family: "Glyph Mono", ui-monospace, monospace;
font-size: 13px;
line-height: 1;
white-space: pre;
overflow: auto;
}
60 ┤                                                  ⡠⢄⡀   
   │                                               ⢀⠔⠉  ⠈⠉⠒⠤
   │                                             ⡠⠊⠁        
50 ┤                              ⡠⢄⡀          ⢀⠜           
   │                    ⡠⢄⡀    ⢀⠔⠉  ⠈⠉⠒⠤⢄⡀    ⡔⠁            
40 ┤                 ⢀⠔⠉  ⠈⠉⠒⠤⠊⠁         ⠈⠉⠒⠤⠊              
   │               ⡠⠊⠁                                      
30 ┤             ⢀⠜                                         
   │            ⡔⠁                                          
   │    ⣀⠤⠤⠤⠤⠤⠤⠊                                            
20 └⠠⠔⠊⠉──────┬─────────┬─────────┬─────────┬─────────┬─────
    0         2         4         6         8        10     
Code
import { renderGlyphChart } from "@glyphcss/charts";

const { text } = renderGlyphChart([18, 24, 21, 35, 42, 39, 48, 44, 38, 52, 61, 57], {
  target: "web",
  color: "none",
  width: 60,
  height: 12
});
console.log(text);

Use color: "css" for result.html. It is an escaped span fragment; assign it inside a <pre>, not as a whole HTML document.

import { renderGlyphChart } from "@glyphcss/charts";
const host = document.querySelector<HTMLPreElement>("#chart")!;
const result = renderGlyphChart([18, 24, 21, 35, 42, 39, 48, 44, 38, 52, 61, 57], {
target: "web", color: "css", width: 60, height: 12,
});
host.innerHTML = result.html!;

React uses <pre className="order-chart" dangerouslySetInnerHTML={{ __html: html }} />; Vue uses <pre class="order-chart" v-html="html" />. Obtain html from the renderer, and never concatenate unescaped data into its fragment.

For responsive charts, measure available columns and rows, then re-render with those cell budgets. Own and disconnect any ResizeObserver in the component lifecycle. At build time, emit text or HTML without hydration, as these docs do. Use the 3D guide for chart scene objects and diagram framework examples for asynchronous diagram rendering.