ASCIIFont
Large banner text for headers and splash screens.
ASCIIFont
Render large decorative text using ASCII art fonts. ASCIIFont is implemented as a FrameBuffer-backed renderable: the text is rendered into an offscreen buffer and then composed into the main tree.
Use it for splash screens, section headers, welcome banners, and compact “branding” elements in a terminal UI. For dense UIs, prefer plain Text and reserve ASCIIFont for high-impact moments.
Basic Usage
Renderable API
import { ASCIIFontRenderable, RGBA, createCliRenderer } from "@cascadetui/core"
const renderer = await createCliRenderer()
const title = new ASCIIFontRenderable(renderer, {
id: "title",
text: "CASCADE",
font: "tiny",
color: RGBA.fromInts(255, 255, 255, 255),
})
renderer.root.add(title)Construct API
import { ASCIIFont, createCliRenderer } from "@cascadetui/core"
const renderer = await createCliRenderer()
renderer.root.add(
ASCIIFont({
text: "HELLO",
font: "block",
color: "#00FF00",
}),
)React binding
import { createCliRenderer, type ASCIIFontName } from "@cascadetui/core"
import { createRoot } from "@cascadetui/react"
import { useState } from "react"
function App() {
const [font, setFont] = useState<ASCIIFontName>("tiny")
return (
<box style={{ paddingLeft: 1, paddingRight: 1 }}>
<select
focused
onChange={(_, option) => setFont(option?.value)}
options={[
{ name: "Tiny", value: "tiny" },
{ name: "Block", value: "block" },
{ name: "Shade", value: "shade" },
{ name: "Slick", value: "slick" },
{ name: "Huge", value: "huge" },
{ name: "Grid", value: "grid" },
{ name: "Pallet", value: "pallet" },
]}
/>
<ascii-font text="ASCII" font={font} color="#7aa2f7" />
</box>
)
}
const renderer = await createCliRenderer()
createRoot(renderer).render(<App />)Available Fonts
Cascade includes several ASCII art font styles:
// Small, compact font
{
font: "tiny",
}
// Block style font
{
font: "block",
}
// Shaded style font
{
font: "shade",
}
// Slick style font
{
font: "slick",
}
// Large font
{
font: "huge",
}
// Grid style font
{
font: "grid",
}
// Pallet style font
{
font: "pallet",
}In practice, start with tiny for compact UIs and block for hero headers. Use larger fonts sparingly so they don’t dominate the layout.
Schema (ASCIIFontOptions)
ASCIIFont is backed by ASCIIFontRenderable and accepts ASCIIFontOptions. Width/height are computed from the rendered text and font and are not configurable directly.
export interface ASCIIFontOptions extends Omit<RenderableOptions<ASCIIFontRenderable>, "width" | "height"> {
text?: string
font?: ASCIIFontName
color?: ColorInput | ColorInput[]
backgroundColor?: ColorInput
selectionBg?: ColorInput
selectionFg?: ColorInput
selectable?: boolean
}
// Defaults
{
text: "",
font: "tiny",
color: "#FFFFFF",
backgroundColor: "transparent",
selectionBg: undefined,
selectionFg: undefined,
selectable: true,
}Because dimensions depend on text and font, changing either triggers a re-measure and a re-render. If you rely on layout constraints (flex), treat ASCIIFont as a fixed-size child (it sets flexShrink: 0 internally).
Positioning
Position the ASCII text anywhere on screen:
const title = new ASCIIFontRenderable(renderer, {
id: "title",
text: "TITLE",
font: "block",
color: RGBA.fromHex("#FFFF00"),
x: 10,
y: 2,
})If you are using flex layouts heavily, consider wrapping the ASCIIFont inside a container (Box) and let layout place it. Reserve explicit x/y positioning for overlays and splash screens.
Colors and multi-color fonts
color accepts either a single ColorInput or an array of colors. The array form is used by multi-color font definitions (some fonts embed color segments). If the font uses multiple colors, the renderer will pick from the provided color array by index.
import { ASCIIFont, createCliRenderer } from "@cascadetui/core"
const renderer = await createCliRenderer()
renderer.root.add(
ASCIIFont({
text: "GRAD",
font: "block",
// Each segment in the font can refer to a different color index
color: ["#7aa2f7", "#bb9af7", "#7dcfff", "#9ece6a"],
}),
)If you just want a “gradient look” without relying on font segmentation, a common trick is layering two ASCIIFonts with small offsets (shadow) or splitting your text into two nodes.
Selection
ASCIIFont supports mouse-driven selection (when selection is enabled at the renderer level). You can disable selection via selectable: false or style it via selectionBg/selectionFg.
import { ASCIIFontRenderable, createCliRenderer } from "@cascadetui/core"
const renderer = await createCliRenderer({ useMouse: true })
const banner = new ASCIIFontRenderable(renderer, {
id: "banner",
text: "SELECT ME",
font: "block",
selectionBg: "#33467a",
selectionFg: "#c0caf5",
selectable: true,
})
renderer.root.add(banner)
renderer.on("mouse", () => {
if (banner.hasSelection()) {
console.log("Selected:", banner.getSelectedText())
}
})When layering multiple ASCIIFont nodes (e.g. shadows), consider setting selectable: false on decorative layers to avoid confusing selection behavior.
Properties
| Property | Type | Default | Description |
|---|---|---|---|
text | string | "" | Text to display |
font | ASCIIFontName | "tiny" | Font style to use |
color | ColorInput | ColorInput[] | "#FFFFFF" | Text color(s) |
backgroundColor | ColorInput | "transparent" | Background color |
selectable | boolean | true | Whether text is selectable |
selectionBg | ColorInput | - | Selection background color |
selectionFg | ColorInput | - | Selection foreground color |
x | number | - | X position offset |
y | number | - | Y position offset |
Note: width and height are measured from text and font. If you need to “align” the banner visually, prefer putting it in a container and using layout props (alignItems, justifyContent) instead of forcing explicit sizes.
Example: Welcome Screen
import { Box, ASCIIFont, Text, createCliRenderer } from "@cascadetui/core"
const renderer = await createCliRenderer()
const welcomeScreen = Box(
{
width: "100%",
height: "100%",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
},
ASCIIFont({
text: "Cascade",
font: "huge",
color: "#00FFFF",
}),
Text({
content: "Terminal UI Framework",
fg: "#888888",
}),
Text({
content: "Press any key to continue...",
fg: "#444444",
}),
)
renderer.root.add(welcomeScreen)Dynamic Text
Update the text content dynamically:
const counter = new ASCIIFontRenderable(renderer, {
id: "counter",
text: "0",
font: "block",
color: RGBA.fromHex("#FF0000"),
})
let count = 0
setInterval(() => {
count++
counter.text = count.toString()
}, 1000)Color Effects
Create gradient-like effects by positioning multiple ASCII fonts:
import { Box, ASCIIFont } from "@cascadetui/core"
const gradientTitle = Box(
{},
ASCIIFont({
text: "HELLO",
font: "block",
color: "#FF0000",
}),
// Overlay with offset for shadow effect
ASCIIFont({
text: "HELLO",
font: "block",
color: "#880000",
x: 1,
y: 1,
selectable: false,
}),
)When layering, be mindful of selection behaviour (two overlapping selectable nodes) and consider disabling selection for the shadow layer.