Repository navigation
feat(app): reveal search row-selection checkboxes on hover #3164
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| --- | ||
| '@hyperdx/app': patch | ||
| --- | ||
|
|
||
| feat: reveal search row-selection checkboxes on hover | ||
|
|
||
| The multi-select checkbox now fades in when a row is hovered or the checkbox | ||
| takes keyboard focus, instead of sitting on every row all the time, and is a | ||
| little smaller so its column costs less horizontal room. Selecting | ||
| any row reveals every checkbox so shift-click ranges stay aimable, and touch | ||
| devices (no hover) keep them visible. The cell keeps its width in every state, | ||
| so nothing reflows on hover. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,7 +3,12 @@ import { Checkbox } from '@mantine/core'; | |
|
|
||
| import styles from '@styles/LogTable.module.scss'; | ||
|
|
||
| export const ROW_SELECTION_COLUMN_WIDTH = 24; | ||
| // Slimmer than Mantine's xs (16px): the column is pure overhead on a table | ||
| // that is already short of horizontal room. Plus the 4px edge gap the | ||
| // checkbox carries in `.selectCheckbox`. | ||
| const CHECKBOX_SIZE = 14; | ||
|
|
||
| export const ROW_SELECTION_COLUMN_WIDTH = CHECKBOX_SIZE + 4; | ||
|
|
||
| const CELL_WIDTH_STYLE = { | ||
| width: ROW_SELECTION_COLUMN_WIDTH, | ||
|
|
@@ -23,12 +28,17 @@ export const RowSelectionCell = memo( | |
| isSelected: boolean; | ||
| onToggle: (rowId: string, options: { extendRange: boolean }) => void; | ||
| }) => ( | ||
| <td className={styles.selectCell} style={CELL_WIDTH_STYLE}> | ||
| <td | ||
| className={styles.selectCell} | ||
| style={CELL_WIDTH_STYLE} | ||
| data-testid="row-select-cell" | ||
| > | ||
| <Checkbox | ||
| className={styles.selectCheckbox} | ||
| size="xs" | ||
| size={`${CHECKBOX_SIZE}px`} | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔵 minor — Pointer target shrinks to 14×14 while the surrounding cell stays inert Mantine renders the Checkbox root as a plain Advisory. Fix if it is a small defect in code this PR changes; otherwise reply in the thread. Do not widen the PR or touch files it did not already change. How to respond
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ^ I feel as though this one is worth addressing as it seems we've lost 2px in the clickable area of the checkbox. Worth updating: |
||
| checked={isSelected} | ||
| aria-label="Select row" | ||
| title="Select row, shift-click to select a range" | ||
| data-testid="row-select-checkbox" | ||
| // The row body is a single button that opens the side panel. | ||
| onClick={e => e.stopPropagation()} | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,6 +9,62 @@ test.describe('Search row multi-select', { tag: '@search' }, () => { | |
| await searchPage.goto(); | ||
| }); | ||
|
|
||
| test( | ||
| 'reveals a row checkbox only while the row is hovered', | ||
| { tag: ['@local-mode'] }, | ||
| async () => { | ||
| const checkbox = searchPage.table.getRowCheckboxCell(0); | ||
| await expect(checkbox).toHaveCSS('opacity', '0'); | ||
|
|
||
| await searchPage.table.hoverRow(0); | ||
| await expect(checkbox).toHaveCSS('opacity', '1'); | ||
|
|
||
| await searchPage.table.hoverRow(3); | ||
| await expect(checkbox).toHaveCSS('opacity', '0'); | ||
| }, | ||
| ); | ||
|
|
||
| test( | ||
| 'hides the checkbox again once the row is unchecked', | ||
| { tag: ['@local-mode'] }, | ||
| async ({ page }) => { | ||
| const checkbox = searchPage.table.getRowCheckboxCell(0); | ||
|
|
||
| await searchPage.table.selectRows([0]); | ||
| await expect(searchPage.selectionCount).toBeVisible(); | ||
| // Clicking again unchecks it, and leaves focus on the checkbox. | ||
| await searchPage.table.selectRows([0]); | ||
| await expect(searchPage.selectionCount).toBeHidden(); | ||
|
|
||
| await searchPage.table.hoverRow(5); | ||
| await expect(checkbox).toHaveCSS('opacity', '0'); | ||
|
|
||
| // That focus must still reveal the checkbox once it is keyboard focus: | ||
| // shift-tab walks back from the row's expand button to its checkbox. | ||
| await searchPage.table.expandRow(0); | ||
| await searchPage.table.hoverRow(5); | ||
| await page.keyboard.press('Shift+Tab'); | ||
| await expect(checkbox).toHaveCSS('opacity', '1'); | ||
| }, | ||
| ); | ||
|
|
||
| test( | ||
| 'shows every checkbox while a selection exists', | ||
| { tag: ['@local-mode'] }, | ||
| async () => { | ||
| // Row 3 is never hovered here, so it can only be visible because the | ||
| // table is in selection mode — which is what keeps shift-click aimable. | ||
| const unhovered = searchPage.table.getRowCheckboxCell(3); | ||
| await expect(unhovered).toHaveCSS('opacity', '0'); | ||
|
|
||
| await searchPage.table.selectRows([0]); | ||
| await expect(unhovered).toHaveCSS('opacity', '1'); | ||
|
|
||
| await searchPage.clearRowSelection(); | ||
| await expect(unhovered).toHaveCSS('opacity', '0'); | ||
|
Comment on lines
+12
to
+64
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The new tests cover mouse hover and active selection, but not the keyboard Knowledge Base Used: Development and test workflows 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!
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔵 minor — Final assertion in 'shows every checkbox while a selection exists' depends on where the menu leaves the mouse
Advisory. Fix if it is a small defect in code this PR changes; otherwise reply in the thread. Do not widen the PR or touch files it did not already change. How to respond |
||
| }, | ||
| ); | ||
|
|
||
| test( | ||
| 'selects rows and reports the count', | ||
| { tag: ['@local-mode'] }, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔵 minor — Column width hand-syncs a 4px gap that actually lives in SCSS
ROW_SELECTION_COLUMN_WIDTH = CHECKBOX_SIZE + 4encodes in TS thepadding-left: 4pxdeclared on.selectCheckboxinpackages/app/styles/LogTable.module.scss:100-104; editing either one alone clips the glyph or leaves dead space, and nothing pins them together. It also means the 18px cell's content box is exactly 14px, sojustify-content: centerno longer centers anything and the checkbox now sits flush against the expand-chevron cell (previously ~2px of right gap). Drive the gap from one place — drop thepadding-leftand let the flex centering do the work, or expose it as a CSS custom property the TS constant reads.Advisory. Fix if it is a small defect in code this PR changes; otherwise reply in the thread. Do not widen the PR or touch files it did not already change. How to respond