feat: generalize colored delta cells

This commit is contained in:
TrèsAbhi committed 2025-10-26 22:01:42 -05:00
1 parent f8ee2b64a6
commit aecc2adb07
4 files changed
+74 -47

No files matched your search

@@ -3,6 +3,7 @@ import { Flex, Heading, IconButton, Table } from "@radix-ui/themes";
import type { TankCharacteristics } from "../../core/blitzkit/tankCharacteristics"; import type { TankCharacteristics } from "../../core/blitzkit/tankCharacteristics";
import { useLocale } from "../../hooks/useLocale"; import { useLocale } from "../../hooks/useLocale";
import { CompareEphemeral } from "../../stores/compareEphemeral"; import { CompareEphemeral } from "../../stores/compareEphemeral";
import { CompareCellDirection } from "../CompareCell";
import { StickyColumnHeaderCell } from "../StickyColumnHeaderCell"; import { StickyColumnHeaderCell } from "../StickyColumnHeaderCell";
import { CompareRow } from "./CompareRow"; import { CompareRow } from "./CompareRow";
import { CompareSectionTitle } from "./CompareSectionTitle"; import { CompareSectionTitle } from "./CompareSectionTitle";
@@ -79,7 +80,7 @@ export function Body({ stats }: BodyProps) {
<CompareRow <CompareRow
stats={stats} stats={stats}
name={strings.website.tools.tankopedia.characteristics.values.reload} name={strings.website.tools.tankopedia.characteristics.values.reload}
deltaType="lowerIsBetter" deltaType={CompareCellDirection.LOWER_IS_BETTER}
value={(stats) => value={(stats) =>
stats.shellReload ?? stats.shellReload ??
stats.shellReloads!.reduce((a, b) => a + b, 0) / stats.shellReloads!.reduce((a, b) => a + b, 0) /
@@ -95,7 +96,7 @@ export function Body({ stats }: BodyProps) {
<> <>
<CompareRow <CompareRow
stats={stats} stats={stats}
deltaType="lowerIsBetter" deltaType={CompareCellDirection.LOWER_IS_BETTER}
value="intraClip" value="intraClip"
decimals={2} decimals={2}
/> />
@@ -107,7 +108,7 @@ export function Body({ stats }: BodyProps) {
<CompareRow <CompareRow
stats={stats} stats={stats}
value="shellRicochet" value="shellRicochet"
deltaType="lowerIsBetter" deltaType={CompareCellDirection.LOWER_IS_BETTER}
decimals={0} decimals={0}
/> />
<CompareRow stats={stats} value="shellVelocity" decimals={0} /> <CompareRow stats={stats} value="shellVelocity" decimals={0} />
@@ -116,48 +117,48 @@ export function Body({ stats }: BodyProps) {
<CompareRow <CompareRow
stats={stats} stats={stats}
value="aimTime" value="aimTime"
deltaType="lowerIsBetter" deltaType={CompareCellDirection.LOWER_IS_BETTER}
decimals={2} decimals={2}
/> />
<CompareRow <CompareRow
stats={stats} stats={stats}
value="dispersion" value="dispersion"
deltaType="lowerIsBetter" deltaType={CompareCellDirection.LOWER_IS_BETTER}
decimals={3} decimals={3}
/> />
<CompareRow <CompareRow
stats={stats} stats={stats}
indent indent
value="dispersionMoving" value="dispersionMoving"
deltaType="lowerIsBetter" deltaType={CompareCellDirection.LOWER_IS_BETTER}
decimals={3} decimals={3}
/> />
<CompareRow <CompareRow
stats={stats} stats={stats}
indent indent
value="dispersionHullTraversing" value="dispersionHullTraversing"
deltaType="lowerIsBetter" deltaType={CompareCellDirection.LOWER_IS_BETTER}
decimals={3} decimals={3}
/> />
<CompareRow <CompareRow
stats={stats} stats={stats}
indent indent
value="dispersionTurretTraversing" value="dispersionTurretTraversing"
deltaType="lowerIsBetter" deltaType={CompareCellDirection.LOWER_IS_BETTER}
decimals={3} decimals={3}
/> />
<CompareRow <CompareRow
stats={stats} stats={stats}
indent indent
value="dispersionShooting" value="dispersionShooting"
deltaType="lowerIsBetter" deltaType={CompareCellDirection.LOWER_IS_BETTER}
decimals={3} decimals={3}
/> />
<CompareRow <CompareRow
stats={stats} stats={stats}
indent indent
value="dispersionGunDamaged" value="dispersionGunDamaged"
deltaType="lowerIsBetter" deltaType={CompareCellDirection.LOWER_IS_BETTER}
decimals={3} decimals={3}
/> />
<CompareRow stats={stats} value="gunDepression" decimals={1} /> <CompareRow stats={stats} value="gunDepression" decimals={1} />
@@ -186,21 +187,21 @@ export function Body({ stats }: BodyProps) {
<CompareRow <CompareRow
stats={stats} stats={stats}
value="hardTerrainCoefficientRaw" value="hardTerrainCoefficientRaw"
deltaType="lowerIsBetter" deltaType={CompareCellDirection.LOWER_IS_BETTER}
decimals={2} decimals={2}
/> />
<CompareRow <CompareRow
stats={stats} stats={stats}
indent indent
value="mediumTerrainCoefficientRaw" value="mediumTerrainCoefficientRaw"
deltaType="lowerIsBetter" deltaType={CompareCellDirection.LOWER_IS_BETTER}
decimals={2} decimals={2}
/> />
<CompareRow <CompareRow
stats={stats} stats={stats}
indent indent
value="softTerrainCoefficientRaw" value="softTerrainCoefficientRaw"
deltaType="lowerIsBetter" deltaType={CompareCellDirection.LOWER_IS_BETTER}
decimals={2} decimals={2}
/> />
<CompareRow <CompareRow
@@ -246,7 +247,7 @@ export function Body({ stats }: BodyProps) {
<CompareRow <CompareRow
stats={stats} stats={stats}
value="fireChance" value="fireChance"
deltaType="lowerIsBetter" deltaType={CompareCellDirection.LOWER_IS_BETTER}
display={(stats) => (stats.fireChance * 100).toFixed(0)} display={(stats) => (stats.fireChance * 100).toFixed(0)}
deltaNominalDisplay={(delta) => (delta * 100).toFixed(0)} deltaNominalDisplay={(delta) => (delta * 100).toFixed(0)}
/> />
@@ -288,28 +289,28 @@ export function Body({ stats }: BodyProps) {
<CompareRow <CompareRow
stats={stats} stats={stats}
value="volume" value="volume"
deltaType="lowerIsBetter" deltaType={CompareCellDirection.LOWER_IS_BETTER}
decimals={1} decimals={1}
/> />
<CompareRow <CompareRow
stats={stats} stats={stats}
indent indent
value="width" value="width"
deltaType="lowerIsBetter" deltaType={CompareCellDirection.LOWER_IS_BETTER}
decimals={1} decimals={1}
/> />
<CompareRow <CompareRow
stats={stats} stats={stats}
indent indent
value="height" value="height"
deltaType="lowerIsBetter" deltaType={CompareCellDirection.LOWER_IS_BETTER}
decimals={1} decimals={1}
/> />
<CompareRow <CompareRow
stats={stats} stats={stats}
indent indent
value="length" value="length"
deltaType="lowerIsBetter" deltaType={CompareCellDirection.LOWER_IS_BETTER}
decimals={1} decimals={1}
/> />
</Table.Body> </Table.Body>
@@ -6,17 +6,17 @@ import {
import { Flex, IconButton, Table, Text } from "@radix-ui/themes"; import { Flex, IconButton, Table, Text } from "@radix-ui/themes";
import { useRef } from "react"; import { useRef } from "react";
import type { TankCharacteristics } from "../../core/blitzkit/tankCharacteristics"; import type { TankCharacteristics } from "../../core/blitzkit/tankCharacteristics";
import { Var } from "../../core/radix/var";
import { useLocale } from "../../hooks/useLocale"; import { useLocale } from "../../hooks/useLocale";
import { CompareEphemeral } from "../../stores/compareEphemeral"; import { CompareEphemeral } from "../../stores/compareEphemeral";
import { ComparePersistent } from "../../stores/comparePersistent"; import { ComparePersistent } from "../../stores/comparePersistent";
import { CompareCell, CompareCellDirection } from "../CompareCell";
import { StickyRowHeaderCell } from "../StickyRowHeaderCell"; import { StickyRowHeaderCell } from "../StickyRowHeaderCell";
type CompareRowProps = { type CompareRowProps = {
display?: ( display?: (
member: Awaited<TankCharacteristics> member: Awaited<TankCharacteristics>
) => number | string | undefined; ) => number | string | undefined;
deltaType?: "higherIsBetter" | "lowerIsBetter"; deltaType?: CompareCellDirection;
decimals?: number; decimals?: number;
deltaNominalDisplay?: (delta: number) => string | number; deltaNominalDisplay?: (delta: number) => string | number;
indent?: boolean; indent?: boolean;
@@ -33,7 +33,7 @@ type CompareRowProps = {
export function CompareRow({ export function CompareRow({
display, display,
deltaType = "higherIsBetter", deltaType = CompareCellDirection.HIGHER_IS_BETTER,
decimals, decimals,
deltaNominalDisplay, deltaNominalDisplay,
indent, indent,
@@ -108,33 +108,18 @@ export function CompareRow({
{values.map((value, index) => { {values.map((value, index) => {
const delta = value - values[0]; const delta = value - values[0];
const deltaPercentage = value / values[0] - 1; const deltaPercentage = value / values[0] - 1;
const normalizedDeltaPercentage = Math.round(
Math.min(100, Math.abs(deltaPercentage) * 2 * 100 + 25)
);
const resolvedDisplayValue = display const resolvedDisplayValue = display
? display(stats[index]) ? display(stats[index])
: decimals === undefined : decimals === undefined
? value ? value
: value?.toFixed(decimals); : value?.toFixed(decimals);
return ( return (
<Table.Cell <CompareCell
key={index} key={index}
style={{ truth={values[0]}
backgroundColor: value={value}
index === 0 || direction={deltaType}
value === undefined ||
values[0] === undefined ||
value === values[0]
? undefined
: (
deltaType === "higherIsBetter"
? value > values[0]
: value < values[0]
)
? `color-mix(in srgb, ${Var("green-7")} ${normalizedDeltaPercentage}%, ${Var("green-3")})`
: `color-mix(in srgb, ${Var("red-7")} ${normalizedDeltaPercentage}%, ${Var("red-3")})`,
}}
> >
<Flex <Flex
align="center" align="center"
@@ -160,8 +145,8 @@ export function CompareRow({
deltaNominalDisplay deltaNominalDisplay
? deltaNominalDisplay(delta) ? deltaNominalDisplay(delta)
: decimals === undefined : decimals === undefined
? delta ? delta
: delta.toFixed(decimals) : delta.toFixed(decimals)
}`} }`}
) )
</Text> </Text>
@@ -179,7 +164,7 @@ export function CompareRow({
</> </>
)} )}
</Flex> </Flex>
</Table.Cell> </CompareCell>
); );
})} })}
</Table.Row> </Table.Row>
@@ -107,8 +107,8 @@ export function CompareTable({ stats }: CompareTableProps) {
crewSkills[skill] === 0 crewSkills[skill] === 0
? Var("gray-11") ? Var("gray-11")
: permanentSkills.includes(skill) : permanentSkills.includes(skill)
? Var("crimson-11") ? Var("crimson-11")
: Var("amber-11"), : Var("amber-11"),
}} }}
/> />
))} ))}
@@ -0,0 +1,41 @@
import { Table } from "@radix-ui/themes";
import type { CellProps } from "@radix-ui/themes/components/table";
export enum CompareCellDirection {
HIGHER_IS_BETTER,
LOWER_IS_BETTER,
}
interface CompareCellProps extends CellProps {
value: number;
truth: number;
direction?: CompareCellDirection;
}
export function CompareCell({
value,
truth,
style,
direction,
...props
}: CompareCellProps) {
const percentage = value / truth - 1;
const shiftedPercentage = Math.round(
Math.min(100, Math.abs(percentage) * 2 * 100 + 25)
);
return (
<Table.Cell
style={{
backgroundColor:
value === truth
? undefined
: (direction === CompareCellDirection.HIGHER_IS_BETTER) ===
value > truth
? `color-mix(in srgb, var(--green-7) ${shiftedPercentage}%, var(--green-3))`
: `color-mix(in srgb, var(--red-7) ${shiftedPercentage}%, var(--red-3))`,
}}
{...props}
/>
);
}