From e7fe053877492be71badb4881fc980f494358e98 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Wed, 27 May 2026 06:32:48 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=A8=20Palette:=20UX=20and=20Accessibil?= =?UTF-8?q?ity=20Improvements?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Added confirmation dialog for game deletion. - Added "Clear Rating" button to allow unsetting personal ratings. - Improved accessibility with aria-labels for icon-only buttons. - Fixed build error by removing unused state. - Added missing i18n keys for new features. Co-authored-by: Gamepulse <8333979+Gamepulse@users.noreply.github.com> --- .Jules/palette.md | 7 +++++++ src/components/Library/GameCard.tsx | 9 ++++++--- src/components/Library/GameDetail.tsx | 9 +++++++-- src/components/Library/GameDetailHeader.tsx | 12 ++++++++++++ src/components/Library/GameScreenshotsCarousel.tsx | 2 -- src/i18n/translations.ts | 4 ++++ 6 files changed, 36 insertions(+), 7 deletions(-) create mode 100644 .Jules/palette.md diff --git a/.Jules/palette.md b/.Jules/palette.md new file mode 100644 index 0000000..21ecc9b --- /dev/null +++ b/.Jules/palette.md @@ -0,0 +1,7 @@ +## 2026-05-27 - [Personal Rating Nullability] +**Learning:** HTML5 range inputs cannot natively represent a `null` or "unset" state once a value is assigned. This makes it impossible for users to "un-rate" a game once they've touched the slider. +**Action:** Always provide a clear, accessible "Clear" or "Reset" button (e.g., a small ✕) next to range inputs that correspond to nullable database fields to ensure full user control over their data. + +## 2026-05-27 - [Strict Build Constraints] +**Learning:** This project uses strict TypeScript linting in its production build (`pnpm build`), where unused variables or state declarations (e.g., `hasIgdbId`) cause build failures. +**Action:** Always run `pnpm build` before submitting to identify and remove unused code that might have been left over during development. diff --git a/src/components/Library/GameCard.tsx b/src/components/Library/GameCard.tsx index f628ab4..f94031f 100644 --- a/src/components/Library/GameCard.tsx +++ b/src/components/Library/GameCard.tsx @@ -196,7 +196,8 @@ const GameCard: React.FC = ({ game, onClick, viewMode, onFilter, onQuickAssign?.(); }} className="ml-auto text-xs px-2 py-1 bg-orange-500 hover:bg-orange-600 text-white rounded transition-colors" - title="Quick assign platform" + title={t('quickAssignPlatform')} + aria-label={t('quickAssignPlatform')} > 🎮 @@ -296,7 +297,8 @@ const GameCard: React.FC = ({ game, onClick, viewMode, onFilter, onQuickAssign?.(); }} className="absolute bottom-1 left-1 w-5 h-5 flex items-center justify-center text-[10px] bg-orange-500 hover:bg-orange-600 text-white rounded transition-colors z-10" - title="Quick assign platform" + title={t('quickAssignPlatform')} + aria-label={t('quickAssignPlatform')} > 🎮 @@ -379,7 +381,8 @@ const GameCard: React.FC = ({ game, onClick, viewMode, onFilter, onQuickAssign?.(); }} className="ml-2 text-xs px-2 py-1 bg-orange-500 hover:bg-orange-600 text-white rounded transition-colors" - title="Quick assign platform" + title={t('quickAssignPlatform')} + aria-label={t('quickAssignPlatform')} > 🎮 diff --git a/src/components/Library/GameDetail.tsx b/src/components/Library/GameDetail.tsx index 6e12f43..0a83daf 100644 --- a/src/components/Library/GameDetail.tsx +++ b/src/components/Library/GameDetail.tsx @@ -64,7 +64,11 @@ export function GameDetail({ gameId, onBack, onFilter }: GameDetailProps) { setGame({ ...game, notes: notesValue }); }; - const handleDelete = async () => { if (await deleteGame(game.id)) onBack(); }; + const handleDelete = async () => { + if (window.confirm(t('confirmDelete'))) { + if (await deleteGame(game.id)) onBack(); + } + }; const handlePlayTimeChange = async (hours: number) => { if (await updatePlayTime(game.id, hours)) { @@ -179,7 +183,8 @@ export function GameDetail({ gameId, onBack, onFilter }: GameDetailProps) { type="button" onClick={handleClearExecutable} className="px-3 py-2 bg-red-600 text-white rounded-lg hover:bg-red-700 transition-colors text-sm" - title="Clear executable path" + title={t('remove') || "Remove"} + aria-label={t('remove') || "Remove"} > ✕ diff --git a/src/components/Library/GameDetailHeader.tsx b/src/components/Library/GameDetailHeader.tsx index aa3d128..0f5cc26 100644 --- a/src/components/Library/GameDetailHeader.tsx +++ b/src/components/Library/GameDetailHeader.tsx @@ -148,6 +148,7 @@ export function GameDetailHeader({ game, onGameUpdated, onPlatformChange, onFilt onClick={(e) => { e.stopPropagation(); onFavoriteToggle(); }} className="absolute -top-2 -right-2 w-10 h-10 flex items-center justify-center text-3xl transition-transform hover:scale-110" title={game.is_favorite ? t('removeFromFavorites') : t('addToFavorites')} + aria-label={game.is_favorite ? t('removeFromFavorites') : t('addToFavorites')} > {game.is_favorite ? ( @@ -365,6 +366,17 @@ export function GameDetailHeader({ game, onGameUpdated, onPlatformChange, onFilt
{t('personalRating')} (0-100): {game.personal_rating !== null && game.personal_rating !== undefined ? `${game.personal_rating}/100` : '-'} + {game.personal_rating !== null && game.personal_rating !== undefined && ( + + )}
0 diff --git a/src/components/Library/GameScreenshotsCarousel.tsx b/src/components/Library/GameScreenshotsCarousel.tsx index 6a4e37c..bfae3b8 100644 --- a/src/components/Library/GameScreenshotsCarousel.tsx +++ b/src/components/Library/GameScreenshotsCarousel.tsx @@ -20,7 +20,6 @@ export function GameScreenshotsCarousel({ gameId }: GameScreenshotsCarouselProps const [igdbScreenshots, setIgdbScreenshots] = useState([]); const [currentIndex, setCurrentIndex] = useState(0); const [loading, setLoading] = useState(true); - const [hasIgdbId, setHasIgdbId] = useState(false); useEffect(() => { const loadScreenshots = async () => { @@ -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) { diff --git a/src/i18n/translations.ts b/src/i18n/translations.ts index 1664377..c73753b 100644 --- a/src/i18n/translations.ts +++ b/src/i18n/translations.ts @@ -343,6 +343,8 @@ export const translations = { more: 'more', clearAll: 'Clear All', tryAdjustingFilters: 'Try adjusting your filters', + clearRating: 'Clear Rating', + quickAssignPlatform: 'Quick Assign Platform', // Screenshot Background screenshotBackground: 'Game Detail Background', @@ -729,6 +731,8 @@ export const translations = { more: 'de plus', clearAll: 'Tout effacer', tryAdjustingFilters: 'Essayez d\'ajuster vos filtres', + clearRating: 'Effacer la note', + quickAssignPlatform: 'Assignation rapide de plateforme', // Screenshot Background screenshotBackground: 'Arrière-plan de la fiche jeu',