From 59e8d971e7ef96a34c92336f6bc95ef36f1098cb Mon Sep 17 00:00:00 2001 From: leeliu103 Date: Tue, 18 Nov 2025 22:53:18 +0000 Subject: [PATCH] Remove sidebar cell info panels and simplify UI to use tooltips MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Streamlines the interface by removing redundant cell info sidebars from both Block Layout and WMMA Layout tabs. Hover information is now displayed exclusively through tooltips, providing a cleaner UI. Additional improvements: - Remove unused WMMA submit button and implement auto-update on select changes - Add Playwright test coverage for tooltip hover functionality - Clean up related CSS and DOM setup code 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- index.html | 10 ---------- src/main.tabs.test.ts | 16 ---------------- src/styles.css | 17 ----------------- src/tabs/BlockLayoutTab.ts | 19 +++---------------- src/tabs/CanvasTab.ts | 33 ++------------------------------- src/tabs/WMMALayoutTab.ts | 36 ++++++++++++------------------------ tests/visualization.spec.ts | 30 ++++++++++++++++-------------- 7 files changed, 33 insertions(+), 128 deletions(-) diff --git a/index.html b/index.html index d82c412..4e15dce 100644 --- a/index.html +++ b/index.html @@ -103,10 +103,6 @@

Tensor Shape

-
-

Cell Info

-
-
@@ -164,16 +160,10 @@

Operand

- -
-
-

Cell Info

-
-
diff --git a/src/main.tabs.test.ts b/src/main.tabs.test.ts index 59c9454..5be77af 100644 --- a/src/main.tabs.test.ts +++ b/src/main.tabs.test.ts @@ -182,14 +182,6 @@ const setupDom = () => { controls.setAttribute('data-controls', '') sidebar.appendChild(controls) - const cellInfo = document.createElement('div') - cellInfo.id = 'cell-info' - const cellInfoContent = document.createElement('div') - cellInfoContent.id = 'cell-info-content' - cellInfoContent.innerHTML = '

Hover over a cell to see details

' - cellInfo.appendChild(cellInfoContent) - sidebar.appendChild(cellInfo) - contentWrapper.appendChild(sidebar) contentWrapper.appendChild(createVisualizationSection('canvas')) @@ -239,14 +231,6 @@ const setupDom = () => { controls.setAttribute('data-controls', '') sidebar.appendChild(controls) - const cellInfo = document.createElement('div') - cellInfo.id = 'wmma-cell-info' - const cellInfoContent = document.createElement('div') - cellInfoContent.id = 'wmma-cell-info-content' - cellInfoContent.innerHTML = '

Hover over a cell to see details

' - cellInfo.appendChild(cellInfoContent) - sidebar.appendChild(cellInfo) - contentWrapper.appendChild(sidebar) contentWrapper.appendChild(createVisualizationSection('wmma-canvas')) diff --git a/src/styles.css b/src/styles.css index 02d56ba..7173acf 100644 --- a/src/styles.css +++ b/src/styles.css @@ -146,23 +146,6 @@ button:active { padding: 0.25rem 0; } -.cell-info { - margin-top: 1.5rem; - padding-top: 1.5rem; - border-top: 1px solid #eee; -} - -#cell-info-content { - padding: 1rem; - background-color: #f8f9fa; - border-radius: 4px; - font-size: 0.85rem; -} - -#cell-info-content p { - margin: 0.25rem 0; -} - .validation-errors, .validation-warnings { margin-bottom: 1rem; diff --git a/src/tabs/BlockLayoutTab.ts b/src/tabs/BlockLayoutTab.ts index 5e3bf4e..9ade2c3 100644 --- a/src/tabs/BlockLayoutTab.ts +++ b/src/tabs/BlockLayoutTab.ts @@ -34,17 +34,11 @@ export class BlockLayoutTab extends CanvasTab { } const resetButton = renderSharedControls(controlsContainer, { resetButtonId: 'reset' }) - const cellInfoContent = tabContent.querySelector('#cell-info-content') - if (!(cellInfoContent instanceof HTMLElement)) { - throw new Error('BlockLayoutTab cell info content not found') - } - const elements: CanvasTabElements = { root: tabContent, canvas, visualizationContainer, resetButton, - cellInfoContent, } super(elements) @@ -89,7 +83,7 @@ export class BlockLayoutTab extends CanvasTab { protected handleHover(event: MouseEvent): void { const renderer = this.getRenderer() if (!renderer) { - this.resetCellInfoContent() + this.hideTooltip() return } @@ -101,18 +95,11 @@ export class BlockLayoutTab extends CanvasTab { const cellInfo = renderer.getCellInfo(gridPos.row, gridPos.col) if (!cellInfo) { - this.resetCellInfoContent() this.hideTooltip() return } const warpColor = renderer.getWarpColor(cellInfo.warpId) - this.setCellInfoContent(` -

Position: (${cellInfo.position[0]}, ${cellInfo.position[1]})

-

Thread ID: ${cellInfo.threadId}

-

Register ID: ${cellInfo.registerId}

-

Warp ID: ${cellInfo.warpId}

- `) const tooltipContent = `
Logical Index: (${cellInfo.position[0]}, ${cellInfo.position[1]})
@@ -127,9 +114,9 @@ export class BlockLayoutTab extends CanvasTab { } /** - * Reset hover state to the default cell info message. + * Reset hover state when the pointer leaves the canvas. */ protected resetHover(): void { - this.resetCellInfoContent() + this.hideTooltip() } } diff --git a/src/tabs/CanvasTab.ts b/src/tabs/CanvasTab.ts index 0922d05..0d8797f 100644 --- a/src/tabs/CanvasTab.ts +++ b/src/tabs/CanvasTab.ts @@ -6,8 +6,6 @@ export interface CanvasTabElements { canvas: HTMLCanvasElement visualizationContainer: HTMLElement resetButton: HTMLButtonElement - cellInfoContent: HTMLElement - defaultCellInfoMessage?: string } /** @@ -19,19 +17,16 @@ export abstract class CanvasTab { protected readonly tooltip = new Tooltip() private readonly elements: CanvasTabElements - private readonly cellInfoDefaultMessage: string private isDragging = false private isActive = false private keyboardListener: ((event: KeyboardEvent) => void) | null = null protected constructor(elements: CanvasTabElements) { this.elements = elements - this.cellInfoDefaultMessage = elements.defaultCellInfoMessage ?? 'Hover over a cell to see details' this.validateElements() this.setupResetButton() this.setupCanvasInteractions() - this.resetCellInfoContent() } /** @@ -86,13 +81,6 @@ export abstract class CanvasTab { return this.elements.canvas } - /** - * Provide subclasses with access to the cell info container element. - */ - protected get cellInfoContent(): HTMLElement { - return this.elements.cellInfoContent - } - /** * Replace the current renderer instance. */ @@ -113,7 +101,7 @@ export abstract class CanvasTab { protected abstract handleHover(event: MouseEvent): void /** - * Reset hover state, clearing cell info/tooltips as needed. + * Reset hover state when the pointer leaves the canvas. */ protected abstract resetHover(): void @@ -158,20 +146,6 @@ export abstract class CanvasTab { this.canvas.height = height } - /** - * Update the cell info pane with new HTML content. - */ - protected setCellInfoContent(content: string): void { - this.cellInfoContent.innerHTML = content - } - - /** - * Reset the cell info pane to the default message. - */ - protected resetCellInfoContent(): void { - this.cellInfoContent.innerHTML = `

${this.cellInfoDefaultMessage}

` - } - /** * Hide the shared tooltip. */ @@ -180,7 +154,7 @@ export abstract class CanvasTab { } private validateElements(): void { - const { root, canvas, visualizationContainer, resetButton, cellInfoContent } = this.elements + const { root, canvas, visualizationContainer, resetButton } = this.elements if (!root) { throw new Error('CanvasTab root element not provided') } @@ -193,9 +167,6 @@ export abstract class CanvasTab { if (!resetButton) { throw new Error('CanvasTab reset button not provided') } - if (!cellInfoContent) { - throw new Error('CanvasTab cell info container not provided') - } } private setupResetButton(): void { diff --git a/src/tabs/WMMALayoutTab.ts b/src/tabs/WMMALayoutTab.ts index b8e6d76..e533015 100644 --- a/src/tabs/WMMALayoutTab.ts +++ b/src/tabs/WMMALayoutTab.ts @@ -23,7 +23,6 @@ import { CanvasTab, type CanvasTabElements } from './CanvasTab' * managing WMMA-specific form inputs and metadata. */ export class WMMALayoutTab extends CanvasTab { - private readonly form: HTMLFormElement private readonly architectureSelect: HTMLSelectElement private readonly instructionSelect: HTMLSelectElement private readonly operandSelect: HTMLSelectElement @@ -58,11 +57,6 @@ export class WMMALayoutTab extends CanvasTab { } const resetButton = renderSharedControls(controlsContainer, { resetButtonId: 'wmma-reset' }) - const cellInfoContent = tabContent.querySelector('#wmma-cell-info-content') - if (!(cellInfoContent instanceof HTMLElement)) { - throw new Error('WMMALayoutTab cell info content not found') - } - const form = tabContent.querySelector('#wmmaForm') if (!(form instanceof HTMLFormElement)) { throw new Error('WMMALayoutTab form element not found') @@ -88,18 +82,17 @@ export class WMMALayoutTab extends CanvasTab { canvas, visualizationContainer, resetButton, - cellInfoContent, } super(elements) - this.form = form this.architectureSelect = architectureSelect this.instructionSelect = instructionSelect this.operandSelect = operandSelect this.setupEventListeners() this.populateInstructionOptions() + this.updateVisualization() } /** @@ -107,10 +100,10 @@ export class WMMALayoutTab extends CanvasTab { */ /** - * Ensure hover state resets to the default message on exit. + * Ensure hover state resets when the pointer leaves the canvas. */ protected resetHover(): void { - this.resetCellInfoContent() + this.hideTooltip() } /** @@ -119,7 +112,7 @@ export class WMMALayoutTab extends CanvasTab { protected handleHover(event: MouseEvent): void { const renderer = this.getRenderer() if (!renderer) { - this.resetCellInfoContent() + this.hideTooltip() return } @@ -131,7 +124,6 @@ export class WMMALayoutTab extends CanvasTab { const cellInfo = renderer.getCellInfo(gridPos.row, gridPos.col) if (!cellInfo) { - this.resetCellInfoContent() this.hideTooltip() return } @@ -152,14 +144,6 @@ export class WMMALayoutTab extends CanvasTab { elementLabel = elementIndex.toString() } - const infoLines = [ - `

Logical Index: ${logicalIndex}

`, - `

Thread: ${cellInfo.threadId}

`, - `

Register: ${registerLabel}

`, - `

Bit Range: ${bitRangeLabel}

`, - `

Element: ${elementLabel}

`, - ] - const tooltipLines = [ `
Logical Index: ${logicalIndex}
`, `
Thread: ${cellInfo.threadId}
`, @@ -168,19 +152,23 @@ export class WMMALayoutTab extends CanvasTab { `
Element: ${elementLabel}
`, ] - this.setCellInfoContent(infoLines.join('')) this.tooltip.show(tooltipLines.join(''), event.clientX, event.clientY) } private setupEventListeners(): void { this.architectureSelect.addEventListener('change', () => { this.populateInstructionOptions() + this.updateVisualization() + }) + + this.instructionSelect.addEventListener('change', () => { + this.updateVisualization() }) - this.form.addEventListener('submit', (event) => { - event.preventDefault() + this.operandSelect.addEventListener('change', () => { this.updateVisualization() }) + } private populateInstructionOptions(): void { @@ -199,7 +187,7 @@ export class WMMALayoutTab extends CanvasTab { this.instructionSelect.appendChild(option) }) - this.updateVisualization() + this.instructionSelect.selectedIndex = 0 } private getParams(): WMMALayoutParams { diff --git a/tests/visualization.spec.ts b/tests/visualization.spec.ts index a1b48f3..b28a9c8 100644 --- a/tests/visualization.spec.ts +++ b/tests/visualization.spec.ts @@ -112,25 +112,27 @@ test.describe('Triton Layout Visualizer', () => { await page.locator('#reset').click() }) - test('should display cell info on hover', async ({ page }) => { + test('should show tooltip when hovering WMMA cells', async ({ page }) => { await page.goto('/') - const canvas = page.locator('#canvas') - const cellInfo = page.locator('#cell-info-content') + // Switch to the WMMA layout tab + await page.locator('#tab-wmma-layout').click() + + const canvas = page.locator('#wmma-canvas') + await expect(canvas).toBeVisible() - // Initially should show placeholder - await expect(cellInfo).toContainText('Hover over a cell') + // Allow the WMMA visualization to render before hovering + await page.waitForTimeout(200) - // Hover over canvas + // Hover near the center of the canvas to trigger the tooltip const box = await canvas.boundingBox() - if (box) { - await page.mouse.move(box.x + box.width / 2, box.y + box.height / 2) - await page.waitForTimeout(100) - - // Cell info should update - const text = await cellInfo.textContent() - expect(text).toBeTruthy() - } + expect(box).not.toBeNull() + await page.mouse.move(box!.x + box!.width / 2, box!.y + box!.height / 2) + + // Tooltip should appear with WMMA metadata content + const tooltip = page.locator('.layout-tooltip').filter({ hasText: 'Logical Index:' }) + await expect(tooltip).toBeVisible() + await expect(tooltip).toContainText('Thread:') }) test('should take visual snapshot', async ({ page }) => {