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-05-14 - [Range Input Clear Action]
**Learning:** Native HTML range inputs cannot represent a `null` or "unset" state once a value has been selected. For user-provided ratings where `null` is a valid "not rated" state, providing a separate localized "Clear" button improves UX by allowing users to undo a rating without choosing an arbitrary low/default value.
**Action:** Always provide a clear/reset action next to range inputs if the underlying data model supports an optional or null state.
11 changes: 11 additions & 0 deletions src/components/Library/GameDetailHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,17 @@ export function GameDetailHeader({ game, onGameUpdated, onPlatformChange, onFilt
<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>
{game.personal_rating !== null && game.personal_rating !== undefined && (
<button
type="button"
onClick={() => onRatingChange?.(null)}
className="text-xs text-red-400 hover:text-red-300 transition-colors focus-visible:ring-2 focus-visible:ring-red-500 rounded px-1 flex items-center gap-1"
aria-label={t('clearRating')}
title={t('clearRating')}
>
<span aria-hidden="true">βœ•</span> {t('clearRating')}
</button>
)}
</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
2 changes: 2 additions & 0 deletions 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 @@ -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