Home >Web Front-end >JS Tutorial >How To Build Beautiful Terminal UIs (TUIs) in JavaScript!

How To Build Beautiful Terminal UIs (TUIs) in JavaScript!

Linda Hamilton
Linda HamiltonOriginal
2024-11-25 00:04:17998browse

If you're like me and completely obsessed with CLIs and Terminal UIs, this post is for you!

Unfortunately, there isn’t a native way to build beautiful Terminal UIs in JavaScript—at least none that I know of! This was a problem I ran into myself, which eventually led me to port one of the most stunning TUI libraries out there: Lipgloss, created by the folks at Charm.

Don’t believe me? Check this out:

How To Build Beautiful Terminal UIs (TUIs) in JavaScript!

Gorgeous, right?

Here’s the catch: Lipgloss is written in Go. While I usually work in Go, I recently needed to write a web monitoring tool in Node.js. I wasn’t willing to give up my sleek, beautiful UIs, so I found myself in a classic developer challenge mode.

You know those magical moments when you’re deep in code, and something unexpected just clicks? That’s how I ended up porting parts of Lipgloss to WebAssembly (Wasm). And that’s how charsm was born.

What is charsm?

Charsm is short for Charm CLI Wasm. Cool, right? Let’s dive into how you can use it to build stunning TUIs in JavaScript.


Getting Started

Install charsm with a simple npm command:

npm install charsm

Create a Simple Table

To get started, import charsm and initialize it in your script:

import { initLip, Lipgloss } from "charsm";

(async function () {
  const ini = await initLip();
})();

The initLip function loads the Wasm file, prepping everything for rendering. Let’s try printing a table:

const rows = [
  ["Chinese", "您好", "你好"],
  ["Japanese", "こんにちは", "やあ"],
  ["Arabic", "أهلين", "أهلا"],
  ["Russian", "Здравствуйте", "Привет"],
  ["Spanish", "Hola", "¿Qué tal?"],
];

const tabledata = { 
  headers: ["LANGUAGE", "FORMAL", "INFORMAL"], 
  rows: rows 
};

(async function () {
  const ini = await initLip();
  const lip = new Lipgloss();

  const table = lip.newTable({
    data: tabledata,
    table: { border: "rounded", color: "99", width: 100 },
    header: { color: "212", bold: true },
    rows: { even: { color: "246" } },
  });

  console.log(table);
})();

We can also use hex code for colors(check the link to a full example in the outro)

Result:

How To Build Beautiful Terminal UIs (TUIs) in JavaScript!

Simple, right? Now, let’s move on to rendering a list.


Rendering a List

Currently, we can render a simple list. Here’s how it works:

const subtle = { Light: "#D9DCCF", Dark: "#383838" };
const special = { Light: "#43BF6D", Dark: "#73F59F" };

const list = lip.List({
  data: ["Grapefruit", "Yuzu", "Citron", "Pomelo", "Kumquat"],
  selected: [],
  listStyle: "alphabet",
  styles: {
    numeratorColor: special.Dark,
    itemColor: subtle.Dark,
    marginRight: 1,
  },
});
const combined = table + "\n\n" + list
console.log(combined);

How To Build Beautiful Terminal UIs (TUIs) in JavaScript!

Customizing Selected Items

Let’s make it fancier by using a custom enumerator icon (e.g., ✅) for selected items:

const customList = lip.List({
  data: ["Grapefruit", "Yuzu", "Citron", "Pomelo", "Kumquat"],
  selected: ["Grapefruit", "Yuzu"],
  listStyle: "custom",
  customEnum: "✅",
  styles: {
    numeratorColor: special.Dark,
    itemColor: subtle.Dark,
    marginRight: 1,
  },
});

console.log(customList);

The selected items will display the ✅ icon.

How To Build Beautiful Terminal UIs (TUIs) in JavaScript!


Rendering Markdown

Charsm wraps the Glamour library from Charm to handle markdown rendering:

npm install charsm

Custom Styles

Think of styles in charsm as CSS for terminals. Here’s how you can create your own style:

import { initLip, Lipgloss } from "charsm";

(async function () {
  const ini = await initLip();
})();

To apply this style to text:

const rows = [
  ["Chinese", "您好", "你好"],
  ["Japanese", "こんにちは", "やあ"],
  ["Arabic", "أهلين", "أهلا"],
  ["Russian", "Здравствуйте", "Привет"],
  ["Spanish", "Hola", "¿Qué tal?"],
];

const tabledata = { 
  headers: ["LANGUAGE", "FORMAL", "INFORMAL"], 
  rows: rows 
};

(async function () {
  const ini = await initLip();
  const lip = new Lipgloss();

  const table = lip.newTable({
    data: tabledata,
    table: { border: "rounded", color: "99", width: 100 },
    header: { color: "212", bold: true },
    rows: { even: { color: "246" } },
  });

  console.log(table);
})();

consult the readme on github for more options or better yet here is a "full" example

Want a layout? Charsm supports simple flex-like layout:

const subtle = { Light: "#D9DCCF", Dark: "#383838" };
const special = { Light: "#43BF6D", Dark: "#73F59F" };

const list = lip.List({
  data: ["Grapefruit", "Yuzu", "Citron", "Pomelo", "Kumquat"],
  selected: [],
  listStyle: "alphabet",
  styles: {
    numeratorColor: special.Dark,
    itemColor: subtle.Dark,
    marginRight: 1,
  },
});
const combined = table + "\n\n" + list
console.log(combined);

Wrapping Up

And there you have it! With charsm, you can render tables, lists, markdown, and even create custom styles—all within the terminal which by the way you can wrap around the list or markdown since it is text

const customList = lip.List({
  data: ["Grapefruit", "Yuzu", "Citron", "Pomelo", "Kumquat"],
  selected: ["Grapefruit", "Yuzu"],
  listStyle: "custom",
  customEnum: "✅",
  styles: {
    numeratorColor: special.Dark,
    itemColor: subtle.Dark,
    marginRight: 1,
  },
});

console.log(customList);

The table and list will be wrapped in a border, with padding and margins!

How To Build Beautiful Terminal UIs (TUIs) in JavaScript!

This is just the beginning. I’ll be adding interactive components (like forms) soon, so stay tuned. Have fun experimenting and building your own beautiful Terminal UIs in JavaScript!

Cheers!

The above is the detailed content of How To Build Beautiful Terminal UIs (TUIs) in JavaScript!. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn