From daedfe0ed596afb794fae73c3c552a4e48d45e19 Mon Sep 17 00:00:00 2001 From: river0525 <0525sotaro@gmail.com> Date: Thu, 18 Jun 2026 14:38:09 +0900 Subject: [PATCH 1/9] feat(votes): add showNeutralBadge prop to VotableGrade --- src/features/votes/components/VotableGrade.svelte | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/features/votes/components/VotableGrade.svelte b/src/features/votes/components/VotableGrade.svelte index a9eb2c822..93a4559e9 100644 --- a/src/features/votes/components/VotableGrade.svelte +++ b/src/features/votes/components/VotableGrade.svelte @@ -38,6 +38,7 @@ defaultPadding?: number; defaultWidth?: number; reducedWidth?: number; + showNeutralBadge?: boolean; } let { @@ -48,6 +49,7 @@ defaultPadding = 1, defaultWidth = 10, reducedWidth = 8, + showNeutralBadge = true, }: Props = $props(); // 表示用のグレード(投票後に画面リロードなしで差し替えるためのローカル状態) @@ -191,14 +193,14 @@ onclick={() => onTriggerClick()} > - Voted grade: {getTaskGradeLabel(displayGrade)}{relativeEvaluationLabel + Voted grade: {getTaskGradeLabel(displayGrade)}{relativeEvaluationLabel && (showNeutralBadge || relativeEvaluationLabel !== '±0') ? `, relative evaluation: ${relativeEvaluationLabel}` : ''}{isProvisional ? ', provisional' : ''} - {#if taskResult.grade !== TaskGrade.PENDING && latestMedianGrade} + {#if taskResult.grade !== TaskGrade.PENDING && latestMedianGrade && (showNeutralBadge || relativeEvaluationLabel !== '±0')} Date: Thu, 18 Jun 2026 14:55:21 +0900 Subject: [PATCH 2/9] feat(tasks): pass showNeutralBadge prop through TaskTableBodyCell Co-Authored-By: Claude Sonnet 4.6 --- .../tasks/components/contest-table/TaskTableBodyCell.svelte | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/features/tasks/components/contest-table/TaskTableBodyCell.svelte b/src/features/tasks/components/contest-table/TaskTableBodyCell.svelte index 25afebfd4..daf4ce7ee 100644 --- a/src/features/tasks/components/contest-table/TaskTableBodyCell.svelte +++ b/src/features/tasks/components/contest-table/TaskTableBodyCell.svelte @@ -16,6 +16,7 @@ isShownTaskIndex: boolean; taskLabel?: string; voteResults: VoteStatisticsMap; + showNeutralBadge?: boolean; onupdate?: (updatedTask: TaskResult) => void; // Ensure to update task result in parent component. } @@ -26,6 +27,7 @@ isShownTaskIndex, taskLabel, voteResults, + showNeutralBadge = true, onupdate = () => {}, }: Props = $props(); @@ -60,6 +62,7 @@ {isLoggedIn} {isAtCoderVerified} {estimatedGrade} + {showNeutralBadge} defaultPadding={0.25} defaultWidth={6} reducedWidth={6} From 56afaa0f4204273a1396bc65f813c08c5376ac65 Mon Sep 17 00:00:00 2001 From: river0525 <0525sotaro@gmail.com> Date: Thu, 18 Jun 2026 15:06:19 +0900 Subject: [PATCH 3/9] =?UTF-8?q?feat(tasks):=20add=20toggle=20to=20show/hid?= =?UTF-8?q?e=20=C2=B10=20relative=20evaluation=20badge=20in=20task=20table?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tasks/components/contest-table/TaskTable.svelte | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/features/tasks/components/contest-table/TaskTable.svelte b/src/features/tasks/components/contest-table/TaskTable.svelte index f97c8a922..436297700 100644 --- a/src/features/tasks/components/contest-table/TaskTable.svelte +++ b/src/features/tasks/components/contest-table/TaskTable.svelte @@ -4,6 +4,7 @@ import { Heading, Button, + Toggle, Table, TableBody, TableBodyCell, @@ -44,6 +45,8 @@ let { taskResults, isLoggedIn, isAtCoderVerified, voteResults }: Props = $props(); + let showNeutralBadge = $state(true); + // Prepare contest table provider based on the active contest type. let activeContestType: ContestTableProviderGroups = $derived(activeContestTypeStore.get()); @@ -192,7 +195,7 @@ -
+
{#each Object.entries(contestTableProviderGroups) as [type, config] (type)}
+ + + ±0 を表示 +
@@ -294,6 +301,7 @@ {isLoggedIn} {isAtCoderVerified} {voteResults} + {showNeutralBadge} isShownTaskIndex={contestTable.displayConfig.isShownTaskIndex} {taskLabel} onupdate={(updatedTask: TaskResult) => handleUpdateTaskResult(updatedTask)} From c9101a719b64afb3e1924d58378a6050c9736960 Mon Sep 17 00:00:00 2001 From: river0525 <0525sotaro@gmail.com> Date: Thu, 18 Jun 2026 15:11:44 +0900 Subject: [PATCH 4/9] =?UTF-8?q?fix(tasks):=20add=20aria-label=20to=20?= =?UTF-8?q?=C2=B10=20toggle=20for=20accessibility?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tasks/components/contest-table/TaskTable.svelte | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/features/tasks/components/contest-table/TaskTable.svelte b/src/features/tasks/components/contest-table/TaskTable.svelte index 436297700..15fe84fc5 100644 --- a/src/features/tasks/components/contest-table/TaskTable.svelte +++ b/src/features/tasks/components/contest-table/TaskTable.svelte @@ -214,7 +214,11 @@ {/each}
- + ±0 を表示 From 9236efb668e208d4e6e0ca157192d6e19acf3790 Mon Sep 17 00:00:00 2001 From: river0525 <0525sotaro@gmail.com> Date: Thu, 18 Jun 2026 22:57:10 +0900 Subject: [PATCH 5/9] style(votes): fix prettier formatting in VotableGrade sr-only expression --- src/features/votes/components/VotableGrade.svelte | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/features/votes/components/VotableGrade.svelte b/src/features/votes/components/VotableGrade.svelte index 93a4559e9..c3b405d76 100644 --- a/src/features/votes/components/VotableGrade.svelte +++ b/src/features/votes/components/VotableGrade.svelte @@ -193,7 +193,8 @@ onclick={() => onTriggerClick()} > - Voted grade: {getTaskGradeLabel(displayGrade)}{relativeEvaluationLabel && (showNeutralBadge || relativeEvaluationLabel !== '±0') + Voted grade: {getTaskGradeLabel(displayGrade)}{relativeEvaluationLabel && + (showNeutralBadge || relativeEvaluationLabel !== '±0') ? `, relative evaluation: ${relativeEvaluationLabel}` : ''}{isProvisional ? ', provisional' : ''} From 8a28952fa871cf44c9963c120391c22cffd2a502 Mon Sep 17 00:00:00 2001 From: river0525 <0525sotaro@gmail.com> Date: Thu, 18 Jun 2026 23:19:29 +0900 Subject: [PATCH 6/9] refactor(votes): extract shouldShowRelativeEvaluation derived to remove duplication --- src/features/votes/components/VotableGrade.svelte | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/features/votes/components/VotableGrade.svelte b/src/features/votes/components/VotableGrade.svelte index c3b405d76..303aa2094 100644 --- a/src/features/votes/components/VotableGrade.svelte +++ b/src/features/votes/components/VotableGrade.svelte @@ -85,6 +85,12 @@ return getRelativeEvaluationLabel(calcGradeDiff(taskResult.grade, latestMedianGrade)); }); + // Whether to show the relative evaluation label (badge + sr-only text). + // Hidden only when showNeutralBadge is false and the label is exactly '±0'. + const shouldShowRelativeEvaluation = $derived( + showNeutralBadge || relativeEvaluationLabel !== '±0', + ); + let isOpening = $state(false); let votedGrade = $state(null); let voteAbortController: AbortController | null = null; @@ -194,14 +200,14 @@ > Voted grade: {getTaskGradeLabel(displayGrade)}{relativeEvaluationLabel && - (showNeutralBadge || relativeEvaluationLabel !== '±0') + shouldShowRelativeEvaluation ? `, relative evaluation: ${relativeEvaluationLabel}` : ''}{isProvisional ? ', provisional' : ''} - {#if taskResult.grade !== TaskGrade.PENDING && latestMedianGrade && (showNeutralBadge || relativeEvaluationLabel !== '±0')} + {#if taskResult.grade !== TaskGrade.PENDING && latestMedianGrade && shouldShowRelativeEvaluation} Date: Sat, 20 Jun 2026 00:02:50 +0000 Subject: [PATCH 7/9] =?UTF-8?q?fix(contest-table):=20align=20=C2=B10=20tog?= =?UTF-8?q?gle=20button=20to=20the=20right?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 4.6 --- src/features/tasks/components/contest-table/TaskTable.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/features/tasks/components/contest-table/TaskTable.svelte b/src/features/tasks/components/contest-table/TaskTable.svelte index 15fe84fc5..e351d5204 100644 --- a/src/features/tasks/components/contest-table/TaskTable.svelte +++ b/src/features/tasks/components/contest-table/TaskTable.svelte @@ -216,7 +216,7 @@ ±0 を表示 From 215f6752f478fffe03a573a93e42b689f0b5200d Mon Sep 17 00:00:00 2001 From: "k.hiro1818" Date: Sat, 20 Jun 2026 00:09:55 +0000 Subject: [PATCH 8/9] fix(contest-table): improve toggle label clarity and increase gap between sections Co-Authored-By: Claude Sonnet 4.6 --- src/features/tasks/components/contest-table/TaskTable.svelte | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/features/tasks/components/contest-table/TaskTable.svelte b/src/features/tasks/components/contest-table/TaskTable.svelte index e351d5204..06024327b 100644 --- a/src/features/tasks/components/contest-table/TaskTable.svelte +++ b/src/features/tasks/components/contest-table/TaskTable.svelte @@ -195,7 +195,7 @@ -
+
{#each Object.entries(contestTableProviderGroups) as [type, config] (type)}
From 5b3b2ed736c588672d012f5d33c8316c4a2a1746 Mon Sep 17 00:00:00 2001 From: "k.hiro1818" Date: Sat, 20 Jun 2026 04:26:55 +0000 Subject: [PATCH 9/9] feat(contest-table): persist neutral badge toggle state in localStorage Co-Authored-By: Claude Sonnet 4.6 --- .../tasks/components/contest-table/TaskTable.svelte | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/features/tasks/components/contest-table/TaskTable.svelte b/src/features/tasks/components/contest-table/TaskTable.svelte index 06024327b..a89ee2ed4 100644 --- a/src/features/tasks/components/contest-table/TaskTable.svelte +++ b/src/features/tasks/components/contest-table/TaskTable.svelte @@ -31,6 +31,8 @@ type ContestTableProviderGroups, } from '$features/tasks/utils/contest-table/contest_table_provider'; + import { useLocalStorage } from '$lib/stores/local_storage_helper.svelte'; + import { getBackgroundColorFrom } from '$lib/services/submission_status'; import { areAllTasksAccepted } from '$lib/utils/task'; import { createContestTaskPairKey } from '$lib/utils/contest_task_pair'; @@ -45,8 +47,6 @@ let { taskResults, isLoggedIn, isAtCoderVerified, voteResults }: Props = $props(); - let showNeutralBadge = $state(true); - // Prepare contest table provider based on the active contest type. let activeContestType: ContestTableProviderGroups = $derived(activeContestTypeStore.get()); @@ -191,6 +191,14 @@ taskResults = newTaskResults; } } + + // Note: Persist the state of the neutral badge toggle across page reloads. + const neutralBadgeStorage = useLocalStorage('show_neutral_badge', true); + let showNeutralBadge = $state(neutralBadgeStorage.value); + + $effect(() => { + neutralBadgeStorage.value = showNeutralBadge; + });