Skip to content

fix(sidebar): align category counts and show actions on hover without layout shift#77

Merged
AmintaCCCP merged 1 commit intomainfrom
fix-category-sidebar-layout
Apr 10, 2026
Merged

fix(sidebar): align category counts and show actions on hover without layout shift#77
AmintaCCCP merged 1 commit intomainfrom
fix-category-sidebar-layout

Conversation

@AmintaCCCP
Copy link
Copy Markdown
Owner

@AmintaCCCP AmintaCCCP commented Apr 10, 2026

Summary

  • align category count badges without leaving extra whitespace
  • hide the count badge on hover and show action buttons instead
  • action buttons are now absolutely positioned, so they do not take up space when hidden
  • no layout shift when hovering over categories

Before

  • count badge and action buttons shared a flex container
  • buttons used opacity-0 but still reserved space
  • counts appeared misaligned

After

  • count badge displays normally, aligns consistently
  • on hover, badge fades out and action buttons fade in at the same position
  • no hidden elements taking up space when not visible

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 10, 2026

📝 Walkthrough

Walkthrough

Updates the CategorySidebar component's category row UI layout by replacing quote styles and refactoring the badge and action button rendering. The count badge now hides on hover via opacity, while edit/delete/hide buttons are repositioned absolutely and revealed on hover, reducing layout impact.

Changes

Cohort / File(s) Summary
CategorySidebar UI Refactoring
src/components/CategorySidebar.tsx
Updated quote characters in confirmation prompts, adjusted category row button positioning to relative, and refactored badge/action button layout: badge now hides on hover (group-hover:opacity-0), action buttons use absolute positioning with hover visibility control (group-hover:opacity-100), and icon sizing increased from w-3 h-3 to w-3.5 h-3.5.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 A humble rabbit hops with glee,
To see the badges dance so free,
With buttons hiding, then revealed,
The hover states are now sealed,
A cleaner layout, oh so neat!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: fixing sidebar category layout by aligning counts and implementing hover-triggered action buttons without layout shifts.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix-category-sidebar-layout

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/components/CategorySidebar.tsx (1)

166-244: ⚠️ Potential issue | 🟠 Major

Avoid nested <button> elements in the category row.

Line 166 wraps the row with a <button>, and Lines 209-241 add child <button>s inside it. This is invalid interactive nesting and can break click/focus behavior across browsers.

Possible structure fix
- <button
+ <div
    onDragOver={...}
    onDragLeave={...}
    onDrop={(event) => handleDropOnCategory(event, category)}
    className="group shrink-0 lg:shrink relative"
- >
+ >
+   <button
+     type="button"
+     onClick={() => onCategorySelect(category.id)}
+     className="relative flex min-w-[140px] items-center justify-between px-3 py-2.5 rounded-lg text-left transition-colors lg:w-full"
+   >
      ...
-     {category.id !== 'all' && (
-       <div className="absolute ...">
+   </button>
+   {category.id !== 'all' && (
+     <div className="absolute ...">
        <button type="button" ... />
        <button type="button" ... />
      </div>
    )}
- </button>
+ </div>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/CategorySidebar.tsx` around lines 166 - 244, The category row
currently nests interactive <button> children inside an outer <button> (in
CategorySidebar), which is invalid; change the outer clickable container used
where onClick calls onCategorySelect and onDrop calls handleDropOnCategory from
a <button> to a non-interactive element (e.g., <div> or <li> with role="button"
and appropriate keyboard handlers) so inner buttons (calling handleEditCategory,
handleDeleteCategory, handleHideDefaultCategory) remain real <button>s; ensure
the outer element preserves accessibility by forwarding onClick, onKeyDown
(Enter/Space) and drag handlers (onDragOver/onDragLeave/onDrop) and retains the
same className/title logic so styling and behavior are unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/CategorySidebar.tsx`:
- Around line 201-208: The action-controls div inside CategorySidebar currently
uses only group-hover classes (e.g., "group-hover:opacity-100" and
"group-hover:pointer-events-auto") so keyboard users can't reveal them; update
the visibility/pointer-event utility classes to also respond to keyboard focus
by using focus/focus-within variants (e.g., replace or add
"group-focus-within:opacity-100" and "group-focus-within:pointer-events-auto"
alongside the existing group-hover variants) and ensure the interactive children
(buttons/links) are focusable so they become reachable when the group receives
focus; target the div with the class string containing "absolute right-3 ...
opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none
group-hover:pointer-events-auto" in CategorySidebar and add the corresponding
focus/focus-within class variants.
- Around line 193-204: The count badge is hidden on hover via the CSS token
"group-hover:opacity-0" which causes the `all` category (which has no action
buttons) to lose its count; change the span's class generation so
"group-hover:opacity-0" is only applied for non‑all rows. Add a boolean (e.g.
isAll = category.id === 'all' or whichever identifier you use for the all
category) and update the span's className that currently composes
isSelected/isDragTarget to conditionally include `group-hover:opacity-0` only
when !isAll (e.g. `${!isAll ? 'group-hover:opacity-0' : ''}`) so the badge
remains visible for the all category.

---

Outside diff comments:
In `@src/components/CategorySidebar.tsx`:
- Around line 166-244: The category row currently nests interactive <button>
children inside an outer <button> (in CategorySidebar), which is invalid; change
the outer clickable container used where onClick calls onCategorySelect and
onDrop calls handleDropOnCategory from a <button> to a non-interactive element
(e.g., <div> or <li> with role="button" and appropriate keyboard handlers) so
inner buttons (calling handleEditCategory, handleDeleteCategory,
handleHideDefaultCategory) remain real <button>s; ensure the outer element
preserves accessibility by forwarding onClick, onKeyDown (Enter/Space) and drag
handlers (onDragOver/onDragLeave/onDrop) and retains the same className/title
logic so styling and behavior are unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 23c82f89-777b-4185-a181-d9461ab397ee

📥 Commits

Reviewing files that changed from the base of the PR and between 616a0c8 and 1fae8bc.

📒 Files selected for processing (1)
  • src/components/CategorySidebar.tsx

Comment on lines +193 to +204
{/* 数字 badge - 正常状态显示,hover 时隐藏 */}
<span
className={`text-xs px-2 py-1 rounded-full shrink-0 transition-opacity ${
isSelected
? 'bg-blue-200 text-blue-800 dark:bg-blue-800 dark:text-blue-200'
: isDragTarget
? 'bg-green-200 text-green-800 dark:bg-green-800 dark:text-green-200'
: 'bg-gray-200 text-gray-600 dark:bg-gray-600 dark:text-gray-400'
}`}>
<span>{count}</span>
</div>
} group-hover:opacity-0`}
>
{count}
</span>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Keep the count visible for the all category.

Line 201 hides the badge on hover for every row, but all has no action buttons (Lines 207-243). Hovering all currently removes the count with nothing replacing it.

Conditional badge hide
- } group-hover:opacity-0`}
+ } ${category.id !== 'all' ? 'group-hover:opacity-0 group-focus-within:opacity-0' : ''}`}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{/* 数字 badge - 正常状态显示,hover 时隐藏 */}
<span
className={`text-xs px-2 py-1 rounded-full shrink-0 transition-opacity ${
isSelected
? 'bg-blue-200 text-blue-800 dark:bg-blue-800 dark:text-blue-200'
: isDragTarget
? 'bg-green-200 text-green-800 dark:bg-green-800 dark:text-green-200'
: 'bg-gray-200 text-gray-600 dark:bg-gray-600 dark:text-gray-400'
}`}>
<span>{count}</span>
</div>
} group-hover:opacity-0`}
>
{count}
</span>
{/* 数字 badge - 正常状态显示,hover 时隐藏 */}
<span
className={`text-xs px-2 py-1 rounded-full shrink-0 transition-opacity ${
isSelected
? 'bg-blue-200 text-blue-800 dark:bg-blue-800 dark:text-blue-200'
: isDragTarget
? 'bg-green-200 text-green-800 dark:bg-green-800 dark:text-green-200'
: 'bg-gray-200 text-gray-600 dark:bg-gray-600 dark:text-gray-400'
} ${category.id !== 'all' ? 'group-hover:opacity-0 group-focus-within:opacity-0' : ''}`}
>
{count}
</span>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/CategorySidebar.tsx` around lines 193 - 204, The count badge
is hidden on hover via the CSS token "group-hover:opacity-0" which causes the
`all` category (which has no action buttons) to lose its count; change the
span's class generation so "group-hover:opacity-0" is only applied for non‑all
rows. Add a boolean (e.g. isAll = category.id === 'all' or whichever identifier
you use for the all category) and update the span's className that currently
composes isSelected/isDragTarget to conditionally include
`group-hover:opacity-0` only when !isAll (e.g. `${!isAll ?
'group-hover:opacity-0' : ''}`) so the badge remains visible for the all
category.

Comment on lines +201 to +208
} group-hover:opacity-0`}
>
{count}
</span>

{category.id !== 'all' && (
{/* 操作按钮 - 绝对定位,hover 时显示,不占位 */}
{category.id !== 'all' && (
<div className="absolute right-3 top-1/2 -translate-y-1/2 flex items-center gap-1 opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none group-hover:pointer-events-auto">
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Show action controls on keyboard focus, not hover only.

Line 208 uses group-hover only. Keyboard users won’t reliably discover/reach these controls without a focus-based visibility path.

Accessibility-focused class update
- } group-hover:opacity-0`}
+ } group-hover:opacity-0 group-focus-within:opacity-0`}

- <div className="absolute right-3 top-1/2 -translate-y-1/2 flex items-center gap-1 opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none group-hover:pointer-events-auto">
+ <div className="absolute right-3 top-1/2 -translate-y-1/2 flex items-center gap-1 opacity-0 group-hover:opacity-100 group-focus-within:opacity-100 transition-opacity pointer-events-none group-hover:pointer-events-auto group-focus-within:pointer-events-auto">
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/CategorySidebar.tsx` around lines 201 - 208, The
action-controls div inside CategorySidebar currently uses only group-hover
classes (e.g., "group-hover:opacity-100" and "group-hover:pointer-events-auto")
so keyboard users can't reveal them; update the visibility/pointer-event utility
classes to also respond to keyboard focus by using focus/focus-within variants
(e.g., replace or add "group-focus-within:opacity-100" and
"group-focus-within:pointer-events-auto" alongside the existing group-hover
variants) and ensure the interactive children (buttons/links) are focusable so
they become reachable when the group receives focus; target the div with the
class string containing "absolute right-3 ... opacity-0 group-hover:opacity-100
transition-opacity pointer-events-none group-hover:pointer-events-auto" in
CategorySidebar and add the corresponding focus/focus-within class variants.

@AmintaCCCP AmintaCCCP merged commit 05aea16 into main Apr 10, 2026
5 checks passed
@AmintaCCCP AmintaCCCP deleted the fix-category-sidebar-layout branch April 10, 2026 10:06
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