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
7 changes: 7 additions & 0 deletions .Jules/palette.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
## 2025-05-15 - [UX Pattern: Range Input Null State]
**Learning:** Native HTML range inputs (`<input type="range">`) cannot represent a `null` or "unset" state as they always default to a value (usually the minimum).
**Action:** Provide a separate "Clear" or "Reset" button next to numeric range controls to allow users to explicitly unset the value.

## 2025-05-15 - [Accessibility: Icon-only Buttons]
**Learning:** Icon-only buttons containing text emojis (e.g., βœ•) can be confusing for screen readers if the emoji is not hidden and a proper label is not provided.
**Action:** Wrap text emojis in `<span aria-hidden="true">` and provide both `aria-label` and `title` attributes on the parent button.
15 changes: 14 additions & 1 deletion src/components/Library/GameDetailHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,20 @@ export function GameDetailHeader({ game, onGameUpdated, onPlatformChange, onFilt
{/* Personal Rating */}
<div className="space-y-2">
<div className="flex items-center justify-between">
<span className="theme-text-muted text-sm">{t('personalRating')} (0-100): <span className="text-purple-500 font-semibold">{game.personal_rating !== null && game.personal_rating !== undefined ? `${game.personal_rating}/100` : '-'}</span></span>
<div className="flex items-center gap-2">
<span className="theme-text-muted text-sm">{t('personalRating')} (0-100): <span className="text-purple-500 font-semibold">{game.personal_rating !== null && game.personal_rating !== undefined ? `${game.personal_rating}/100` : '-'}</span></span>
{game.personal_rating !== null && game.personal_rating !== undefined && (
<button
type="button"
onClick={() => onRatingChange?.(null)}
className="theme-text-muted hover:text-red-400 transition-colors focus-visible:ring-1 focus-visible:ring-red-400 rounded p-0.5"
aria-label={t('clearRating')}
title={t('clearRating')}
>
<span aria-hidden="true">βœ•</span>
</button>
)}
</div>
</div>
<div className="flex items-center gap-3">
<span className="text-xs theme-text-muted">0</span>
Expand Down
2 changes: 0 additions & 2 deletions src/components/Library/GameScreenshotsCarousel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ export function GameScreenshotsCarousel({ gameId }: GameScreenshotsCarouselProps
const [igdbScreenshots, setIgdbScreenshots] = useState<string[]>([]);
const [currentIndex, setCurrentIndex] = useState(0);
const [loading, setLoading] = useState(true);
const [hasIgdbId, setHasIgdbId] = useState(false);

useEffect(() => {
const loadScreenshots = async () => {
Expand All @@ -29,7 +28,6 @@ export function GameScreenshotsCarousel({ gameId }: GameScreenshotsCarouselProps
// Load game data to check IGDB ID
try {
const game = await invoke<{ igdb_id: number | null }>("get_game_by_id", { id: gameId });
setHasIgdbId(!!game?.igdb_id);

// Load IGDB screenshots if available
if (game?.igdb_id) {
Expand Down
4 changes: 3 additions & 1 deletion src/i18n/translations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export const translations = {

// Game Detail
personalRating: 'Personal Rating',
clearRating: 'Clear Rating',
notes: 'Notes',
saveNotes: 'Save Notes',
deleteGame: 'Delete Game',
Expand Down Expand Up @@ -291,7 +292,7 @@ export const translations = {
playTime: 'Play Time',
hours: 'hours',
platform: 'Platform',
platforms: 'Plateformes',
platforms: 'Platforms',
selectPlatform: 'Select platform...',
noPlatform: 'No platform',
availableOnIGDB: 'Available on',
Expand Down Expand Up @@ -435,6 +436,7 @@ export const translations = {

// Game Detail
personalRating: 'Note personnelle',
clearRating: 'Effacer la note',
notes: 'Notes',
saveNotes: 'Sauvegarder les notes',
deleteGame: 'Supprimer le jeu',
Expand Down