Skip to content

Conversation

@galligan
Copy link
Contributor

  • Add Tokens interface with semantic color string values
  • Add TokenOptions for color level configuration
  • Add createTokens() factory for static color tokens
  • Support NO_COLOR, FORCE_COLOR environment variables
  • Provide success/warning/error/info/muted/accent/primary/secondary tokens

Fixes #51

Co-Authored-By: Claude Opus 4.5 noreply@anthropic.com

Copy link
Contributor Author

galligan commented Jan 23, 2026

Warning

This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
Learn more

This stack of pull requests is managed by Graphite. Learn more about stacking.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d8d284fde0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@greptile-apps
Copy link

greptile-apps bot commented Jan 23, 2026

Greptile Summary

  • Adds semantic color tokens system to @outfitter/ui package with raw ANSI escape code strings for template string usage alongside existing theme functions
  • Implements comprehensive environment variable handling for NO_COLOR and FORCE_COLOR standards with configurable color level detection (0-3)
  • Introduces extensive shape-based rendering system with auto-selection logic and unified render() function to support various CLI data structures

Important Files Changed

Filename Overview
packages/ui/src/index.ts Major expansion adding Tokens interface, createTokens() factory, comprehensive shape types, and unified rendering system with complex color detection logic
packages/ui/src/tests/tokens.test.ts New comprehensive test file covering token structure, environment variables, configuration options, and integration with existing theme functionality

Confidence score: 4/5

  • This PR introduces significant new functionality with comprehensive test coverage and follows the project's TDD principles
  • Score reflects the complexity of the color detection logic and extensive new type definitions that require careful review for edge cases
  • Pay close attention to the color detection logic in createTokens() function and the complex shape type system in packages/ui/src/index.ts

Sequence Diagram

sequenceDiagram
    participant User
    participant createTokens as "createTokens()"
    participant Environment as "process.env"
    participant Tokens as "Tokens"

    User->>createTokens: "Call createTokens(options?)"
    createTokens->>Environment: "Check NO_COLOR env var"
    Environment-->>createTokens: "NO_COLOR value"
    createTokens->>Environment: "Check FORCE_COLOR env var"
    Environment-->>createTokens: "FORCE_COLOR value"
    createTokens->>createTokens: "Determine colorEnabled flag"
    alt colorEnabled is false
        createTokens->>Tokens: "Create tokens with empty strings"
    else colorEnabled is true
        createTokens->>Tokens: "Create tokens with ANSI codes"
    end
    createTokens-->>User: "Return Tokens object"
Loading

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

3 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

Comment on lines 616 to 687
export function createTokens(options?: TokenOptions): Tokens {
// Determine if colors should be enabled
let colorEnabled: boolean;

// colorLevel: 0 always disables colors
if (options?.colorLevel === 0) {
colorEnabled = false;
}
// forceColor option takes precedence over environment
else if (options?.forceColor === true) {
colorEnabled = true;
}
// FORCE_COLOR env takes precedence over NO_COLOR
// Supports FORCE_COLOR=1, FORCE_COLOR=2, FORCE_COLOR=3 (common for color levels)
else if (process.env["FORCE_COLOR"] !== undefined && process.env["FORCE_COLOR"] !== "") {
colorEnabled = true;
}
// NO_COLOR env disables colors
// Per no-color.org spec, ANY non-empty value disables colors
else if (process.env["NO_COLOR"] !== undefined && process.env["NO_COLOR"] !== "") {
colorEnabled = false;
}
// colorLevel 1-3 enables colors
else if (options?.colorLevel !== undefined && options.colorLevel > 0) {
colorEnabled = true;
}
// Fall back to TTY detection
else {
colorEnabled = process.stdout.isTTY ?? false;
}

// Return empty strings when colors are disabled
if (!colorEnabled) {
return {
success: "",
warning: "",
error: "",
info: "",
muted: "",
accent: "",
primary: "",
secondary: "",
};
}

// Return ANSI codes when colors are enabled
return {
// Semantic colors
success: ANSI.green,
warning: ANSI.yellow,
error: ANSI.red,
info: ANSI.blue,
// Text colors
muted: ANSI.dim,
accent: ANSI.cyan,
primary: "", // Primary uses default terminal color
secondary: ANSI.gray,
};
}
Copy link

Choose a reason for hiding this comment

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

style: Color detection logic duplicates some patterns from supportsColor() function - consider extracting shared logic to avoid inconsistencies

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/ui/src/index.ts
Line: 616:674

Comment:
**style:** Color detection logic duplicates some patterns from `supportsColor()` function - consider extracting shared logic to avoid inconsistencies

<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>

How can I resolve this? If you propose a fix, please make it concise.

// Auto-selection based on shape type
if (isCollection(shape)) {
// Check if items are objects (use table) or primitives (use list)
const hasObjectItems = shape.items.length > 0 && shape.items.every(isPlainObject);
Copy link

Choose a reason for hiding this comment

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

logic: Edge case: empty arrays with hasObjectItems will be false due to short-circuit evaluation, defaulting to list rendering which may not be intended. Should empty collections have a specific default rendering behavior, or is list rendering the intended fallback?

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/ui/src/index.ts
Line: 1666:1666

Comment:
**logic:** Edge case: empty arrays with `hasObjectItems` will be false due to short-circuit evaluation, defaulting to list rendering which may not be intended. Should empty collections have a specific default rendering behavior, or is list rendering the intended fallback?

How can I resolve this? If you propose a fix, please make it concise.

@galligan galligan changed the base branch from p3-12/state/pagination-helpers to graphite-base/75 January 23, 2026 21:27
@galligan galligan force-pushed the p3-13/ui/create-tokens branch from 555109e to d3dd7f8 Compare January 23, 2026 21:30
@galligan galligan changed the base branch from graphite-base/75 to p3-12/state/pagination-helpers January 23, 2026 21:30
@galligan
Copy link
Contributor Author

Updated createTokens env handling to treat NO_COLOR as a hard disable and honor FORCE_COLOR numeric levels (0 disables, 1+ enables).

galligan and others added 2 commits January 23, 2026 18:06
- Add Tokens interface with semantic color string values
- Add TokenOptions for color level configuration
- Add createTokens() factory for static color tokens
- Support NO_COLOR, FORCE_COLOR environment variables
- Provide success/warning/error/info/muted/accent/primary/secondary tokens

Fixes #51

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@galligan galligan force-pushed the p3-13/ui/create-tokens branch from d3dd7f8 to ce4b35b Compare January 23, 2026 23:09
@galligan galligan force-pushed the p3-12/state/pagination-helpers branch from 1a27fc3 to 6c1bed2 Compare January 23, 2026 23:09
@galligan
Copy link
Contributor Author

Restacked after downstack update (formatRelative test stabilization); no additional changes in this PR.

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

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants