Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .jules/palette.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## 2025-02-05 - Disabled Tooltip Best Practices
**Learning:** Native disabled buttons swallow mouse events, preventing tooltips (like the `title` attribute) from displaying. Wrapping the disabled element in a span and setting `disabled:pointer-events-none` on the element along with `cursor-not-allowed` on the parent span restores both hover tooltips and correct cursor behavior without breaking accessibility or layout.
**Action:** Use this span-wrapper pattern combined with Tailwind's `disabled:pointer-events-none` and `cursor-not-allowed` for all disabled buttons that require explanatory tooltips.
19 changes: 12 additions & 7 deletions src/features/library/components/UnresolvedFilesSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -165,14 +165,19 @@ export function UnresolvedFilesSection({
</button>
) : null}
</div>
<button
className="flex items-center gap-2 rounded-lg bg-accent-600 px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-accent-700 disabled:opacity-50"
disabled={isAttemptMatchPending || isAttemptMatchAllPending || discoveredItems.length === 0}
onClick={onAttemptMatchAll}
<span
className={cx('inline-flex', (isAttemptMatchPending || isAttemptMatchAllPending || discoveredItems.length === 0) && 'cursor-not-allowed')}
title={isAttemptMatchAllPending || isAttemptMatchPending ? 'Matching in progress' : discoveredItems.length === 0 ? 'No unresolved files to match' : undefined}
>
<RefreshCw size={14} className={cx(isAttemptMatchAllPending && 'animate-spin')} />
{isAttemptMatchAllPending ? 'Matching All...' : 'Match All'}
</button>
<button
className="flex items-center gap-2 rounded-lg bg-accent-600 px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-accent-700 disabled:pointer-events-none disabled:opacity-50"
disabled={isAttemptMatchPending || isAttemptMatchAllPending || discoveredItems.length === 0}
onClick={onAttemptMatchAll}
>
<RefreshCw size={14} className={cx(isAttemptMatchAllPending && 'animate-spin')} />
{isAttemptMatchAllPending ? 'Matching All...' : 'Match All'}
</button>
</span>
</div>
</div>

Expand Down