Skip to content

Board: drag handle is not vertically aligned with BoardItemTitle #71

Open

Description

@ironAiken2

Problem

Board's drag handle does not line up with the item's title. On backend.ai-webui's dashboard, every board item renders a BoardItemTitle as its first row (via BAIBoardItemTitle), and in edit mode the grip glyph sits in the card's top-left corner, above the title text, so the two never share a line.

Reported from the WebUI side as lablup/backend.ai-webui#10365, which stays open until webui adopts a ui-common release with the fix.

Cause

Board draws only the item shell and the handles; the title row is the consumer's, placed inside renderItem. The two are positioned independently:

  • src/components/Board/Board.css: .uic-board-item__handle--drag is absolutely positioned at inset-block-start: var(--spacing-2) from the item's top.
  • src/components/BoardItemTitle/BoardItemTitle.css: .uic-board-item-title pads its row with padding-block: var(--spacing-5).

Measured in Storybook (Components/Board → Editable, Playwright, with the story wrapper's block padding removed so the title row starts at the item's top, as on the webui dashboard): the sm handle (28px) is centered 12px above the title row's center.

Proposal

Make the title the board's, not the consumer's, and drop renderItem: an item is its title and description, both padded by the board, and the drag handle sits in that padding on the title row's first line.

Props

Added on BoardItem:

prop type role
title? ReactNode The header row's content. A string renders as a level-5 heading; a node (a BoardItemTitle with a tooltip and actions, say) renders as is. Without one there is no header row: the description takes the whole item.
description? ReactNode The body. A string renders as text; a node renders as is.

Added on BoardProps:

prop type role
itemPadding? number | string | { top?, right?, bottom?, left? } (a number is px, a string any CSS length) Every item's title-row and description padding, default --spacing-5 top and bottom, --spacing-8 left and right. Written as --board-item-padding-top / -right / -bottom / -left on each item, since style cannot reach the padded elements inside. The handle is not padded; the left padding is what clears it.

Removed: renderItem, BoardItemActions / removeItem, removedItem, liveAnnouncementItemRemoved, the uic.Board.itemRemoved key. Removing an item is the consumer's: pass items without it. BoardItemTitle becomes a plain title node (no own padding, not sticky).

Rendering

item input rendered drag handle
title + description header row + body, drawn and padded by the board absolute, top-start corner, in the inline padding on the header row's first line
description only the body takes the whole item the same spot
.uic-board-item
├─ drag handle                 (absolute; top offset = the top padding, left --spacing-1)
├─ .uic-board-item__header     (only with a title; padding = the item's)
│    [title: heading or node; first line centered on the handle, the rest wrap below]
├─ .uic-board-item__content    (description; padding = the item's, no top padding after a header; scrolls)
└─ resize handle               (absolute, bottom-end, unchanged)

Consumer migration (backend.ai-webui)

  • BAIBoard passes title / description and itemPadding through instead of defaulting renderItem to data.content.
  • Dashboard panels split into a title node (BAIBoardItemTitle with the refresh button and edit controls) and a body, and drop their own inline inset.
  • Start page tiles pass description only.

Status of #68

#68 carries this design.

Activity

  1. added 8 commits that reference this issue on Oct 15, 2026
    f31515e
    1410816
    1e0d7a3
    5ad1635
    58ddcc6
    17ace76
    330044d
    7358900
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions