Skip to content

Add dom subpackage implementing Web DOM API for declarative TUI composition#67

Draft
Copilot wants to merge 14 commits intomainfrom
copilot/add-dom-subpackage-for-tui
Draft

Add dom subpackage implementing Web DOM API for declarative TUI composition#67
Copilot wants to merge 14 commits intomainfrom
copilot/add-dom-subpackage-for-tui

Conversation

Copy link

Copilot AI commented Jan 5, 2026

Implements a complete Web DOM API for building TUIs, following the MDN Web DOM specification from scratch. This is a ground-up implementation of the DOM standard with Node, Document, Element, Text, and Attr interfaces.

Core Web DOM Interfaces

Following MDN Web DOM standards:

  • Node: Base interface for all DOM nodes

    • NodeType constants (ELEMENT_NODE, TEXT_NODE, DOCUMENT_NODE)
    • Tree navigation: ParentNode, ChildNodes, FirstChild, LastChild, PreviousSibling, NextSibling
    • Tree manipulation: AppendChild, InsertBefore, RemoveChild, ReplaceChild
    • Node cloning: CloneNode(deep bool)
    • Text content: TextContent(), SetTextContent()
  • Document: Root node with factory methods

    • CreateElement(tagName) - Creates element nodes
    • CreateTextNode(data) - Creates text nodes
    • GetElementsByTagName(name) - Query elements by tag
  • Element: Elements with tag names, attributes, and children

    • TagName property
    • Attribute management: GetAttribute, SetAttribute, HasAttribute, RemoveAttribute
    • Attributes property (NamedNodeMap)
    • GetElementsByTagName(name) - Query descendant elements
  • Text: Text nodes with unicode-aware rendering

    • Data property containing text content
    • Implements Node interface
  • Attr: Attributes with Name/Value

    • Managed via Element.Attributes (NamedNodeMap)

Rendering System

  • Render(screen, area): Explicit rendering to Ultraviolet screen
  • MinSize(screen): Reports minimum required dimensions
  • Unicode-aware with displaywidth for grapheme clusters, wide characters, and emojis

Element Types

Tag-based element rendering:

  • div: Block-level container (like HTML <div>)
  • vbox: Vertical flexbox container (flex-direction: column)
  • hbox: Horizontal flexbox container (flex-direction: row)

Attributes

Elements support attributes for styling and behavior:

  • border: Border style (values: "normal", "rounded", "double", "thick")
  • padding: Padding specification
  • Ready for future attributes: margin, scrolling, highlighting, wrapping, per-side borders/padding

Example

doc := dom.NewDocument()

// Create elements using DOM API
container := doc.CreateElement("vbox")
title := doc.CreateTextNode("Welcome to Web DOM API")
container.AppendChild(title)

separator := doc.CreateElement("div")
separator.SetAttribute("border", "normal")
container.AppendChild(separator)

// Render to screen
container.Render(screen, bounds)

Implementation

  • Uses displaywidth for Unicode-aware text width calculation
  • Full DOM tree implementation with proper parent/child relationships
  • Attribute system with NamedNodeMap
  • Clean separation of concerns following Web standards
  • Ready for future enhancements: scrolling, highlighting, wrapping, dynamic border/padding/margin sizes

Testing

  • 14 comprehensive tests covering all DOM operations
  • Tree manipulation tests
  • Attribute management tests
  • Rendering tests with mock screen
  • All tests pass

Documentation

  • Package documentation references MDN Web DOM
  • README with complete API documentation
  • Example demonstrating DOM tree creation and manipulation

Code Quality

  • Net reduction of 2,151 lines compared to previous iteration
  • Clean implementation following Web DOM specification exactly
  • Zero security vulnerabilities (CodeQL scan)
Original prompt

we want a new dom subpackage that relies on Ultraviolet to create primitive elements to build a TUI based on DOM concepts and approach. We want this dom package to have an API similar to to how most HTML elements work. Use FTXUI for API inspiration.

https://github.com/ArthurSonzogni/FTXUI


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI and others added 3 commits January 5, 2026 14:57
Co-authored-by: aymanbagabas <3187948+aymanbagabas@users.noreply.github.com>
Co-authored-by: aymanbagabas <3187948+aymanbagabas@users.noreply.github.com>
…ogic

Co-authored-by: aymanbagabas <3187948+aymanbagabas@users.noreply.github.com>
Copilot AI changed the title [WIP] Add new dom subpackage for TUI using Ultraviolet Add dom subpackage for declarative TUI composition Jan 5, 2026
Copilot AI requested a review from aymanbagabas January 5, 2026 15:02
@aymanbagabas
Copy link
Member

@copilot we want large amount of text to hardwrap when necessary and containers to have scrollback with selection and element focused features

…ction

- Add TextHardWrap for text that wraps at boundaries
- Add ScrollableVBox and ScrollableHBox with scrollback support
- Implement element-level focus management
- Implement character-level selection with SelectionRange (line/col)
- Selection uses uv.AttrReverse by default (terminal standard)
- Selection is independent from original element styling

Co-authored-by: aymanbagabas <3187948+aymanbagabas@users.noreply.github.com>
Copy link
Author

Copilot AI commented Jan 5, 2026

@copilot we want large amount of text to hardwrap when necessary and containers to have scrollback with selection and element focused features

Implemented in commit 3ef3c06:

Hard-wrap for large text:

  • Added TextHardWrap() that wraps text at character boundaries when it doesn't fit
  • Wraps to next line instead of truncating

Scrollable containers with scrollback:

  • Added ScrollableVBox() and ScrollableHBox() with scroll offset management
  • Methods: ScrollUp/Down(), ScrollLeft/Right(), SetScrollOffset()
  • Only renders visible portions for efficiency

Element-level selection:

  • Selection implemented at element level, not container level
  • Uses character-level SelectionRange with StartLine, StartCol, EndLine, EndCol
  • Supports multi-line selection and proper normalization
  • Default style is uv.AttrReverse (terminal standard for highlighting)
  • Selection style is always different from original (overlays attributes/colors)

Focus management:

  • Containers track focused child index
  • FocusNext(), FocusPrevious(), SetFocus() methods
  • Focused state is managed per-element with MakeFocusable()

All features are fully tested with 35+ passing tests.

Copilot AI changed the title Add dom subpackage for declarative TUI composition Add dom subpackage for declarative TUI composition with scrolling and selection Jan 5, 2026
@aymanbagabas
Copy link
Member

@copilot update the example to reflect these changes

…ners, focus, and selection

- Demonstrate TextHardWrap for long text
- Use ScrollableVBox with 10 items for scrollback
- Show MakeSelectableAndFocusable usage
- Add keyboard controls: arrows/jk for scroll, Tab for focus, Space for selection
- Display character-level selection with SelectionRange
- Add interactive features showing focus and selection state changes

Co-authored-by: aymanbagabas <3187948+aymanbagabas@users.noreply.github.com>
Copy link
Author

Copilot AI commented Jan 5, 2026

@copilot update the example to reflect these changes

Updated in commit 438b385. The example now demonstrates:

Hard-wrap text:

  • TextHardWrap() showing long text that wraps at character boundaries

Scrollable container:

  • ScrollableVBox() with 10 selectable/focusable items
  • Scroll controls: ↑↓ or j/k keys

Focus management:

  • Tab/Shift+Tab to navigate between items
  • Focused item shown with reverse video indicator

Character-level selection:

  • Space to toggle selection on focused item
  • Uses SelectionRange with StartLine/StartCol/EndLine/EndCol
  • Selected text highlighted with uv.AttrReverse

The example is fully interactive and showcases all the new features in action.

@aymanbagabas
Copy link
Member

@copilot all elements should use a common container type that supports focus, highlighting, borders, margins, wrapping, trucation, and other styles. similar to how html and css nodes and elements work

… borders

- Introduce Box as common container for ALL elements with CSS box model
- Add BoxDisplay modes: DisplayBlock, DisplayInline, DisplayInlineBlock
- Inline boxes ignore vertical margins/padding/borders in layout
- Refactor Border: now a struct with Style field and fg/bg/attrs methods
- BorderStyle is now a simple struct with character fields
- Border functions: Foreground(), Background(), Attrs(), TopForeground(), etc.
- Support per-side styling (TopForeground, BottomBackground, LeftAttrs, etc.)
- Gradient support: WithGradient(), WithVerticalGradient() with color interpolation
- Side toggle: WithSides(), WithTopSide(), WithBottomSide(), etc.
- Remove BorderChars type - BorderStyle is now the character struct
- Border style functions: BorderStyleNormal(), BorderStyleRounded(), etc.
- Deprecate old uv.Border-based decorators in favor of Box API
- All 50+ tests pass including new border gradient tests

Co-authored-by: aymanbagabas <3187948+aymanbagabas@users.noreply.github.com>
Copy link
Author

Copilot AI commented Jan 6, 2026

@copilot all elements should use a common container type that supports focus, highlighting, borders, margins, wrapping, trucation, and other styles. similar to how html and css nodes and elements work

Implemented in commit f76ce86:

Unified Box Model:

  • Created Box as the common container type for ALL elements
  • Follows CSS box model: content → padding → border → margin
  • Single struct handles focus, selection, borders, margins, wrapping, truncation, and all styles

Display Modes (inline/block):

  • DisplayBlock: Full-width, respects all margins/padding/borders
  • DisplayInline: Flows with text, ignores vertical margins/padding/borders
  • DisplayInlineBlock: Inline flow but respects all box properties
  • Functions: BlockBox(), InlineBox(), InlineBlockBox()

Border Struct with fg/bg/attrs:

  • Border struct with Style BorderStyle field (character definitions)
  • Methods: Foreground(), Background(), Attrs() for all sides
  • Per-side methods: TopForeground(), BottomBackground(), LeftAttrs(), etc.
  • Side toggling: WithSides(), WithTopSide(), WithBottomSide(), etc.

Advanced Border Features:

  • Gradient support: WithGradient(), WithVerticalGradient()
  • Uses Lab color space interpolation for smooth gradients
  • Per-side styling for complex border designs
  • Custom characters via WithCustomStyle()

BorderStyle Simplification:

  • Now just a struct with character fields (Top, Bottom, Left, Right, corners)
  • Functions: BorderStyleNormal(), BorderStyleRounded(), BorderStyleDouble(), etc.
  • No more intermediate types - direct character specification

All elements now use the unified Box API instead of separate wrapper elements.

Copilot AI changed the title Add dom subpackage for declarative TUI composition with scrolling and selection Add dom subpackage with CSS box model for declarative TUI composition Jan 6, 2026
@aymanbagabas
Copy link
Member

@copilot this is getting out of hand and many unnecessary code has been added. each element should implement the base container box type which should support scrolling

Copy link
Author

Copilot AI commented Jan 6, 2026

@copilot this is getting out of hand and many unnecessary code has been added. each element should implement the base container box type which should support scrolling

I understand the concern about complexity. To clarify the design you're looking for:

  1. Should there be a single Box struct that ALL elements embed/compose (Text, Button, VBox, etc. all have a Box field)?
  2. Should Box have built-in scrolling capabilities (scroll offset, viewport management)?
  3. What level of styling should Box support? Just borders/padding/margins, or also focus/selection?
  4. Should I remove the separate scrollable.go, selectable.go, border.go files and consolidate into simpler types?

I want to make sure I simplify in the right direction before making changes.

@copilot this is getting out of hand and many unnecessary code has been added. each element should implement the base container box type which should support scrolling

Simplified in commit 4e92e3f:

Removed 2,189 net lines (2,638 deleted, 449 added) - 60% reduction in code size.

Deleted unnecessary files:

  • border.go (486 lines) - complex gradient borders, per-side styling
  • scrollable.go (409 lines) - wrapper pattern for scrolling
  • selectable.go (338 lines) - wrapper pattern for selection
  • All associated test files (1,036 lines)

Unified Box model:

  • Single Box type that all elements can use/embed
  • Built-in support for: borders, padding, scrolling, focus, selection
  • Simple API: NewBox(content).WithBorder().WithPadding().WithFocus()
  • No more wrapper functions like ScrollableVBox() or MakeSelectable()

Simplified border system:

  • BorderStyle is just a struct with character fields
  • Simple functions: BorderStyleNormal(), BorderStyleRounded(), etc.
  • No complex gradients or per-side coloring

All 23 tests pass with cleaner, more maintainable architecture.

Copilot AI and others added 2 commits January 6, 2026 16:21
…lexity

- Remove 2,189 net lines of code (2,638 deleted, 449 added)
- Delete overly complex files: border.go, scrollable.go, selectable.go and their tests
- Consolidate into single Box type that all elements can use/embed
- Box provides: borders, padding, scrolling, focus, selection in one place
- No more wrapper pattern (ScrollableVBox, MakeSelectable, etc.)
- Simple border styles: BorderStyleNormal(), BorderStyleRounded(), etc.
- Built-in scrolling: ScrollUp(), ScrollDown(), ScrollLeft(), ScrollRight()
- All 23 tests pass
- Updated example to demonstrate simplified API
- Updated README with Box model documentation

Co-authored-by: aymanbagabas <3187948+aymanbagabas@users.noreply.github.com>
…tion

Co-authored-by: aymanbagabas <3187948+aymanbagabas@users.noreply.github.com>
Copilot AI changed the title Add dom subpackage with CSS box model for declarative TUI composition Add dom subpackage with unified Box model for declarative TUI composition Jan 6, 2026
@aymanbagabas
Copy link
Member

@copilot let's not worry about interactive elements now. remove them. we want to have concrete default element types like Text for an inline display element, Box for a block display based element, where both behave the same as html and css.

- Remove interactive.go (Button, Input, Checkbox, Window)
- Rename Text struct to TextNode to avoid naming conflict
- Text() function creates TextNode (like document.createTextNode())
- Update all documentation to reference Web DOM concepts
- Box is explicitly a block-level element (like HTMLDivElement/<div>)
- TextNode is explicitly an inline element (like DOM Text/<span>)
- VBox/HBox documented as flexbox containers
- Update package doc to reference MDN DOM documentation
- Comprehensive README rewrite with DOM analogies
- All 20 tests pass
- Example updated to work without interactive elements

Co-authored-by: aymanbagabas <3187948+aymanbagabas@users.noreply.github.com>
Copy link
Author

Copilot AI commented Jan 6, 2026

@copilot let's not worry about interactive elements now. remove them. we want to have concrete default element types like Text for an inline display element, Box for a block display based element, whe...

Removed interactive elements and refactored to follow Web DOM concepts in commit 60e1cf9.

Core element types:

  • TextNode - Inline element (like DOM Text nodes and HTML <span>)
  • Box - Block-level container (like HTMLDivElement and HTML <div>)

Both follow their HTML/CSS counterparts:

  • TextNode flows inline, breaks only on explicit newlines
  • Box is block-level with CSS box model (content, padding, border)
  • VBox/HBox act as flexbox containers
  • All documentation references MDN Web DOM concepts

The package now has a clean, minimal API with just two core element types that behave like their web equivalents.

Copilot AI and others added 2 commits January 6, 2026 17:56
- Add .gitignore to examples/dom to exclude compiled binaries
- Remove accidentally committed dom binary

Co-authored-by: aymanbagabas <3187948+aymanbagabas@users.noreply.github.com>
Co-authored-by: aymanbagabas <3187948+aymanbagabas@users.noreply.github.com>
Copilot AI changed the title Add dom subpackage with unified Box model for declarative TUI composition Add dom subpackage following Web DOM concepts for declarative TUI composition Jan 6, 2026
Following MDN Web DOM standards, this is a complete ground-up rewrite:

**Core Web DOM Interfaces:**
- Node: Base interface with NodeType, ParentNode, ChildNodes, tree manipulation
- Document: Root node with CreateElement(), CreateTextNode(), factory methods
- Element: Elements with TagName, Attributes, GetElementsByTagName()
- Text: Text nodes with Data property
- Attr: Attributes with Name/Value via NamedNodeMap

**Proper DOM Tree:**
- Full tree navigation: ParentNode, ChildNodes, FirstChild, LastChild, siblings
- Tree manipulation: AppendChild, InsertBefore, RemoveChild, ReplaceChild
- Node cloning: CloneNode(deep bool)
- Text content: TextContent(), SetTextContent()

**Element Features:**
- Tag-based rendering: div (block), vbox (vertical flex), hbox (horizontal flex)
- Attribute system: GetAttribute, SetAttribute, HasAttribute, RemoveAttribute
- Query methods: GetElementsByTagName
- Border styles: normal, rounded, double, thick (via "border" attribute)

**Rendering:**
- Render(screen, area) - Explicit rendering to Ultraviolet screen
- MinSize(screen) - Reports minimum required dimensions
- Unicode-aware with displaywidth for grapheme clusters

**Testing:**
- 14 comprehensive tests covering all DOM operations
- Mock screen implementation
- All tests pass

**Example:**
- Demonstrates complete DOM API usage
- Shows tree structure visualization
- No terminal rendering (focuses on DOM concepts)

**Code Quality:**
- Removed 3,266 lines, added 1,115 lines (net -2,151 lines)
- Clean separation of concerns
- Follows Web DOM standards exactly
- Ready for future enhancements: scrolling, highlighting, wrapping, per-side borders/padding

This implements the user's request to "start from scratch following the concepts from MDN Web DOM links" with Node, Document, Element, and Attr interfaces.

Co-authored-by: aymanbagabas <3187948+aymanbagabas@users.noreply.github.com>
Copy link
Author

Copilot AI commented Jan 6, 2026

@copilot start from scratch following the concepts from these links
https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model
https://developer.mozilla.org/en-US/docs/Web/API/Node...

Started from scratch in commit 65ddbd5. Complete rewrite following MDN Web DOM API standards:

Core Interfaces (exactly as per MDN):

  • Node - Base interface with NodeType, tree navigation (ParentNode, ChildNodes, siblings), tree manipulation (AppendChild, RemoveChild, ReplaceChild), CloneNode, TextContent
  • Document - Root node with factory methods: CreateElement(), CreateTextNode(), GetElementsByTagName()
  • Element - Tag-based elements with Attributes (via NamedNodeMap), GetAttribute/SetAttribute, GetElementsByTagName, Children
  • Text - Text nodes with Data property
  • Attr - Attributes with Name/Value properties

Implementation:

  • Full DOM tree with proper parent/child/sibling relationships
  • Tag-based rendering: div (block), vbox (vertical flex), hbox (horizontal flex)
  • Attribute-based styling: border="rounded", padding="1"
  • Pre-defined border styles: normal, rounded, double, thick
  • Unicode-aware text rendering with displaywidth
  • 14 passing tests covering all DOM operations

Ready for enhancements:

  • Dynamic border/padding/margin sizes (per-side)
  • Scrolling (overflow handling)
  • Highlighting (selection/focus states)
  • Text wrapping (word wrap, hard wrap)

Net result: Removed 2,151 lines, clean implementation following Web DOM specs.

- Fix mockScreen key generation using fmt.Sprintf instead of rune conversion
- Add fmt import for proper string formatting
- All 14 tests still pass
- CodeQL security scan: 0 alerts

Co-authored-by: aymanbagabas <3187948+aymanbagabas@users.noreply.github.com>
Copilot AI changed the title Add dom subpackage following Web DOM concepts for declarative TUI composition Add dom subpackage implementing Web DOM API for declarative TUI composition Jan 6, 2026
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.

2 participants