Skip to content

feat: currentcolor and inherited open() color - #158

Draft
natemoo-re wants to merge 2 commits into
feat/ansi16-system-colorsfrom
feat/currentcolor
Draft

natemoo-re wants to merge 2 commits into
feat/ansi16-system-colorsfrom
feat/currentcolor

Conversation

@natemoo-re

Copy link
Copy Markdown
Member
  • Stacked on feat: CSS system colors map to the ANSI 16-color palette #157.
  • open() gets a color field. Nested open()s and text()s inherit it unless they set their own, like CSS color.
  • currentcolor works in every color field and means "this element's color". As color itself, it means inherit.
  • border.color is now optional and defaults to currentcolor, so borders match the text color by default.
  • currentcolor never throws. If the color it points at is the terminal default and it's used as a background, it paints the theme foreground the terminal reported, or falls back to the default background.
  • Inheritance is resolved while packing each frame. Nothing new goes over the wire, and no state carries between frames.
  • Spec commit is separate from the implementation commit.

Replaces the "currentcolor is reserved" wording. open() gains a color
field, inherited by descendants unless overridden; currentcolor means
"inherit" in a color field and "this directive's own resolved color,
field-resolved like any other color" everywhere else. border.color
becomes optional, defaulting to currentcolor. Inheritance is a
pack()-time stack scoped to one frame's directive array.
open() gains a color field: the element's own foreground, inherited
by descendants via a pack()-time stack pushed on open and popped on
close. currentcolor means "inherit" in a color field and "this
directive's own resolved color" everywhere else, going through the
same field resolution (resolveForField) as any other color.
border.color is now optional and defaults to currentcolor.

resolveColor() returns a CURRENT_COLOR sentinel for the keyword;
ops.ts substitutes the inherited/own color before field resolution
via resolveOwn()/colorValue(), both newly threading a `current`
parameter through colorWord/sideFg/sideBg. No wire-format change:
open()'s own color has no direct rendering, only TS-side inheritance.
@bombshell-cooper

Copy link
Copy Markdown
Contributor

Changeset suggestion

The current changeset no longer matches this PR. This review contains a corrected replacement.

Why: Changeset should start with an approved active present-tense verb. Changeset package scope does not match the affected packages confidently.

View the proposed changeset
---
'@bomb.sh/tty': minor
---

Adds `color` to `open()`: the element's own foreground color, inherited by every descendant that does not set its own.

`currentcolor` is now a valid color string at every color field. In `open({ color })` and `text({ color })` it means "inherit" (same as omitting the field); in any other field — `bg`, `border.color`, `border.bg`, or a structured border side's `color`/`bg` — it resolves to the directive's own resolved foreground, then follows normal field resolution (terminal-themed for same-field defaults, theme-probed for cross-field defaults, pass-through for sRGB).

`border.color` is now optional and defaults to `currentcolor`, matching CSS; a border with no `color` set anywhere inherits the element's foreground as before.

Foreground inheritance is resolved by `pack()` with a stack scoped to a single call: pushed on each `open()`, popped on the matching `close()`. No state carries across frames.

#### Migration

`border.color` was previously required. It is now optional.

```diff
- open("box", { border: { color: "red", top: 1 } })
+ open("box", { border: { top: 1 } })  // inherits element color via currentcolor
```

Existing code that sets `border.color` explicitly is unaffected.

The string `"currentcolor"` was previously rejected as an invalid color string. Code that tested for that rejection will need to be updated.

```diff
- expect(validate([open("a", { bg: "currentcolor" }), close()])).toBe(false)
+ expect(validate([open("a", { bg: "currentcolor" }), close()])).toBe(true)
```

Review this changeset manually

If this draft is correct, react with 🚀 and Cooper will commit it to this branch.

@@ -0,0 +1,16 @@
---

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changeset needs revision.

Changeset should start with an approved active present-tense verb. Changeset package scope does not match the affected packages confidently.

View the proposed replacement
---
'@bomb.sh/tty': minor
---

Adds `color` to `open()`: the element's own foreground color, inherited by every descendant that does not set its own.

`currentcolor` is now a valid color string at every color field. In `open({ color })` and `text({ color })` it means "inherit" (same as omitting the field); in any other field — `bg`, `border.color`, `border.bg`, or a structured border side's `color`/`bg` — it resolves to the directive's own resolved foreground, then follows normal field resolution (terminal-themed for same-field defaults, theme-probed for cross-field defaults, pass-through for sRGB).

`border.color` is now optional and defaults to `currentcolor`, matching CSS; a border with no `color` set anywhere inherits the element's foreground as before.

Foreground inheritance is resolved by `pack()` with a stack scoped to a single call: pushed on each `open()`, popped on the matching `close()`. No state carries across frames.

#### Migration

`border.color` was previously required. It is now optional.

```diff
- open("box", { border: { color: "red", top: 1 } })
+ open("box", { border: { top: 1 } })  // inherits element color via currentcolor
```

Existing code that sets `border.color` explicitly is unaffected.

The string `"currentcolor"` was previously rejected as an invalid color string. Code that tested for that rejection will need to be updated.

```diff
- expect(validate([open("a", { bg: "currentcolor" }), close()])).toBe(false)
+ expect(validate([open("a", { bg: "currentcolor" }), close()])).toBe(true)
```

@github-actions

Copy link
Copy Markdown

Size Increased — +3.2 KB

141.4 KB unpacked

@pkg-pr-new

pkg-pr-new Bot commented Oct 20, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@bomb.sh/tty@158

commit: 735cb31

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant