Skip to content

Conversation

@sinelaw
Copy link
Owner

@sinelaw sinelaw commented Jan 30, 2026

Summary

Introduces a comprehensive TypeScript UI Controls Library (controls.ts) that provides reusable components for building plugin interfaces. This eliminates manual text construction and byte offset calculation when creating plugin UIs, mirroring the Rust control patterns used in the editor's Settings UI.

Key Changes

  • New Controls Library (controls.ts): Added 1135 lines of TypeScript controls including:

    • ButtonControl - Buttons with focus indicators (brackets when focused)
    • ToggleButton - Toggle buttons with ON/OFF state
    • ListControl<T> - Selectable lists with scrolling and selection management
    • GroupedListControl<T> - Lists with grouped sections (e.g., "Installed" vs "Available")
    • TextInputControl - Text input fields with cursor management
    • FocusManager<T> - Focus cycling through UI elements (mirrors Rust FocusManager)
    • SplitView - Side-by-side panel rendering with dividers
    • FilterBar - Toggle filter buttons
    • HelpBar - Key binding help display
    • Separator & Label - Simple layout components
  • Type Definitions: Added StyleRange, ControlOutput, ItemRenderer, and related types for consistent styling and rendering

  • Export Updates (index.ts):

    • Reorganized exports with better grouping
    • Added all new controls to public API
    • Added VirtualBufferBuilder export (from vbuffer.ts)
  • Code Formatting: Applied consistent formatting across finder.ts, navigation-controller.ts, panel-manager.ts, and search-utils.ts (trailing commas, line breaks for readability)

Implementation Details

  • All controls implement a render() method returning ControlOutput with text and style ranges
  • Style ranges use character offsets (not bytes) - UTF-8 conversion handled automatically by VirtualBufferBuilder
  • Focus states (FocusState enum) support Normal, Focused, Hovered, and Disabled states
  • List controls handle selection, scrolling, and automatic visibility management
  • Colors support both theme keys (strings like "ui.menu_active_bg") and RGB tuples
  • Comprehensive JSDoc documentation with usage examples for each control

Benefits

  • Eliminates manual text construction and offset calculation
  • Provides consistent UI patterns across plugins
  • Reduces boilerplate code for common UI patterns
  • Type-safe control composition
  • Automatic style range management

https://claude.ai/code/session_01Kt49PHNWUZjs4TNk8zxZZ1

Add a UI controls library that mirrors the Rust control patterns,
eliminating manual text construction and byte offset calculation
when building plugin interfaces.

New files:
- controls.ts: ButtonControl, ListControl, GroupedListControl,
  FocusManager, TextInputControl, ToggleButton, Separator, Label
- vbuffer.ts: VirtualBufferBuilder for automatic UTF-8 handling

The VirtualBufferBuilder handles character-to-byte conversion
automatically, so plugins can work with character offsets instead
of manually tracking UTF-8 byte positions.

This is Part 2 of the Unified UI Framework plan - the TypeScript
equivalent of the Rust layout utilities (point_in_rect, FocusManager,
MenuLayout, TabLayout) that were already implemented.

Next step: Migrate pkg.ts to use the new controls library.

https://claude.ai/code/session_01Kt49PHNWUZjs4TNk8zxZZ1
Refactor the package manager UI to use the new controls library:
- Use VirtualBufferBuilder for automatic UTF-8 byte offset handling
- Use ButtonControl for buttons (filter, sync, action buttons)
- Remove manual utf8ByteLength() function
- Remove buildListViewEntries() and applyPkgManagerHighlighting()
- Add new renderPkgManagerUI() function using VirtualBufferBuilder
- Extract buildLeftPanel() and buildRightPanel() helper functions

This reduces the UI code by ~100 lines while improving maintainability.
The VirtualBufferBuilder handles character-to-byte conversion automatically,
eliminating a common source of bugs in UTF-8 offset calculations.

https://claude.ai/code/session_01Kt49PHNWUZjs4TNk8zxZZ1
All 11 implementation steps are now complete:
1-7: Rust layout utilities (point_in_rect, FocusManager, MenuLayout, TabLayout)
8-10: TypeScript controls library (controls.ts, vbuffer.ts, exports)
11: pkg.ts migration to use the controls library

https://claude.ai/code/session_01Kt49PHNWUZjs4TNk8zxZZ1
Add themeColor(), themeFg(), and themeBg() helpers to simplify the
verbose pattern of `pkgTheme.xxx.fg?.theme ?? pkgTheme.xxx.fg?.rgb`.

This reduces the UI rendering code by ~74 lines while maintaining
the same visual behavior.

https://claude.ai/code/session_01Kt49PHNWUZjs4TNk8zxZZ1
Replace if-else chain with object lookup for help text action labels.
Reduces code by 12 lines.

https://claude.ai/code/session_01Kt49PHNWUZjs4TNk8zxZZ1
- Add renderLines() method to GroupedListControl for split-view layouts
- Add customizable colors (titleFg, selectedFg, selectedBg, itemFg)
- Replace manual list building in pkg.ts with GroupedListControl
- Extract formatPackageItem() function for item rendering

This demonstrates proper usage of the controls library, with
GroupedListControl handling selection state and rendering while
supporting the split-view layout pattern.

https://claude.ai/code/session_01Kt49PHNWUZjs4TNk8zxZZ1
Add reusable layout controls to lib/controls.ts:
- SplitView: Side-by-side panel rendering with divider
- FilterBar: Row of toggle filter buttons with active/focused states
- HelpBar: Help text bar with key bindings
- PanelLine: Interface for styled lines in panels

Refactor pkg.ts to use these new controls, reducing manual
rendering code and improving maintainability.

Also apply deno fmt formatting fixes across plugin lib files.

https://claude.ai/code/session_01Kt49PHNWUZjs4TNk8zxZZ1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants