mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-23 11:39:50 +02:00
TankopediaCharacteristics
This commit is contained in:
1 parent
5cae5d1583
commit
74fbd15c5f
9 files changed
+521
-68
No files matched your search
@@ -0,0 +1,138 @@
|
||||
.characteristics-wrapper {
|
||||
margin: var(--space-4);
|
||||
|
||||
--base-cell-width: 20rem;
|
||||
--group-span: 7;
|
||||
|
||||
container-type: inline-size;
|
||||
|
||||
.characteristics {
|
||||
--N: round(down, 100cqw / var(--base-cell-width));
|
||||
--cell-width: calc(100cqw / var(--N));
|
||||
--cell-height: calc(var(--cell-width) / var(--group-span));
|
||||
|
||||
display: grid;
|
||||
grid-template-columns: repeat(
|
||||
auto-fill,
|
||||
minmax(var(--base-cell-width), 1fr)
|
||||
);
|
||||
grid-auto-rows: var(--cell-height);
|
||||
grid-auto-flow: dense;
|
||||
|
||||
box-sizing: border-box;
|
||||
|
||||
.group {
|
||||
--gradient-size: min(100%, var(--space-8));
|
||||
|
||||
grid-column: span 1;
|
||||
|
||||
display: grid;
|
||||
grid-template-columns: inherit;
|
||||
grid-auto-rows: inherit;
|
||||
|
||||
.title {
|
||||
grid-row: span 1;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 0 calc(var(--space-4));
|
||||
|
||||
.center {
|
||||
flex: 1;
|
||||
padding: var(--space-3);
|
||||
|
||||
.text {
|
||||
.align {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-3);
|
||||
|
||||
img {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
margin: 0 var(--space-4);
|
||||
|
||||
gap: inherit;
|
||||
height: 100%;
|
||||
|
||||
display: grid;
|
||||
grid-template-columns: inherit;
|
||||
grid-auto-rows: inherit;
|
||||
|
||||
.item {
|
||||
padding: 0 var(--space-3);
|
||||
|
||||
grid-row: span 1;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
gap: var(--space-2);
|
||||
|
||||
.value {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.units {
|
||||
display: flex;
|
||||
align-items: end;
|
||||
gap: var(--space-2);
|
||||
}
|
||||
}
|
||||
|
||||
.ranking {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-3);
|
||||
|
||||
.bar-wrapper {
|
||||
flex: 1;
|
||||
height: var(--space-1);
|
||||
|
||||
background-color: var(--gray-3);
|
||||
border-radius: var(--radius-max);
|
||||
overflow: hidden;
|
||||
|
||||
.bar {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.toy {
|
||||
grid-row: span var(--group-span);
|
||||
padding: var(--space-4) 0;
|
||||
|
||||
.sandbox {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
background-color: var(--gray-2);
|
||||
outline: var(--gray-5) solid var(--space-1);
|
||||
border-radius: var(--space-3);
|
||||
}
|
||||
}
|
||||
|
||||
.dead {
|
||||
grid-row: span 1;
|
||||
}
|
||||
}
|
||||
|
||||
.dead {
|
||||
grid-row: span 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
import { characteristicsGroups } from "../../config/characteristicsGroups";
|
||||
import { useCharacteristicRenderer } from "../../hooks/useCharacteristicRenderer";
|
||||
import { useStrings } from "../../hooks/useStrings";
|
||||
import type {
|
||||
CharacteristicRenderConfig,
|
||||
CharacteristicReturnType,
|
||||
CharacteristicsGroup,
|
||||
ComputedCharacteristics,
|
||||
} from "../../types/characteristics";
|
||||
import { Heading } from "../Heading";
|
||||
import { Text } from "../Text";
|
||||
import styles from "./index.module.css";
|
||||
|
||||
interface TankopediaCharacteristicsProps {
|
||||
characteristics: ComputedCharacteristics;
|
||||
}
|
||||
|
||||
export function TankopediaCharacteristics({
|
||||
characteristics,
|
||||
}: TankopediaCharacteristicsProps) {
|
||||
return (
|
||||
<div className={styles["characteristics-wrapper"]}>
|
||||
<div className={styles.characteristics}>
|
||||
{characteristicsGroups.map((group) => {
|
||||
const items = group.order.filter(
|
||||
(item) => "name" in item && characteristics[item.name] !== null,
|
||||
).length;
|
||||
const shouldRender = items > 0;
|
||||
|
||||
if (!shouldRender) return null;
|
||||
|
||||
return (
|
||||
<Group
|
||||
key={group.name}
|
||||
group={group}
|
||||
characteristics={characteristics}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
interface GroupProps {
|
||||
group: CharacteristicsGroup;
|
||||
characteristics: ComputedCharacteristics;
|
||||
}
|
||||
|
||||
function Group({ group, characteristics }: GroupProps) {
|
||||
const strings = useStrings();
|
||||
const toys = group.order.filter((item) => "toy" in item).length;
|
||||
const items = group.order.filter(
|
||||
(item) => "name" in item && characteristics[item.name] !== null,
|
||||
).length;
|
||||
const groupSpan = `calc(${toys} * var(--group-span) + ${items} + 2)`;
|
||||
const contentSpan = `calc(${toys} * var(--group-span) + ${items})`;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={styles.group}
|
||||
style={{
|
||||
gridRow: `span ${groupSpan}`,
|
||||
gridTemplateRows: `repeat(${groupSpan}, 1fr)`,
|
||||
}}
|
||||
>
|
||||
<div className={styles.title}>
|
||||
<div className={styles.center}>
|
||||
<Heading size="3" className={styles.text}>
|
||||
<div className={styles.align}>
|
||||
{
|
||||
(
|
||||
strings.tanks.characteristics.titles as Record<string, string>
|
||||
)[group.name]
|
||||
}
|
||||
<img src={`/media/groups/${group.name}.png`} />
|
||||
</div>
|
||||
</Heading>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className={styles.content}
|
||||
style={{
|
||||
gridRow: `span ${contentSpan}`,
|
||||
}}
|
||||
>
|
||||
{group.order.map((item) => (
|
||||
<>
|
||||
{"toy" in item && <Toy {...item} />}
|
||||
{"name" in item && characteristics[item.name] !== null && (
|
||||
<Item config={item} value={characteristics[item.name]!} />
|
||||
)}
|
||||
</>
|
||||
))}
|
||||
|
||||
<div className={styles.dead} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
interface ItemProps {
|
||||
config: CharacteristicRenderConfig;
|
||||
value: CharacteristicReturnType;
|
||||
}
|
||||
|
||||
function Item({ config, value }: ItemProps) {
|
||||
const strings = useStrings();
|
||||
const renderCharacteristic = useCharacteristicRenderer();
|
||||
const hasUnits = config.units !== undefined;
|
||||
|
||||
return (
|
||||
<span className={styles.item}>
|
||||
<div className={styles.value}>
|
||||
<Text lowContrast>
|
||||
{
|
||||
(strings.tanks.characteristics.items as Record<string, string>)[
|
||||
config.name
|
||||
]
|
||||
}
|
||||
</Text>
|
||||
|
||||
<Text lowContrast={hasUnits} size={hasUnits ? "minor" : undefined}>
|
||||
<div className={styles.units}>
|
||||
{renderCharacteristic(value, config)}
|
||||
</div>
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
<div className={styles.ranking}>
|
||||
<Bar value={0.5} />
|
||||
|
||||
<Text lowContrast size="minor" className={styles.number}>
|
||||
1 / 132
|
||||
</Text>
|
||||
</div>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
interface BarProps {
|
||||
value: number;
|
||||
}
|
||||
|
||||
const barColors = ["red", "orange", "amber", "jade"];
|
||||
|
||||
function Bar({ value }: BarProps) {
|
||||
const index = (barColors.length - 1) * value;
|
||||
const iA = Math.floor(index);
|
||||
const iB = Math.ceil(index);
|
||||
const A = barColors[iA];
|
||||
const B = barColors[iB];
|
||||
const x = index % 1;
|
||||
const p = (1 - x) * 100;
|
||||
const v = 7;
|
||||
|
||||
return (
|
||||
<div className={styles["bar-wrapper"]}>
|
||||
<div
|
||||
className={styles.bar}
|
||||
style={{
|
||||
backgroundColor: `color-mix(in srgb, var(--${A}-${v}) ${p}%, var(--${B}-${v}))`,
|
||||
width: `${value * 100}%`,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
interface ToyProps {
|
||||
toy: string;
|
||||
}
|
||||
|
||||
function Toy({ toy }: ToyProps) {
|
||||
return (
|
||||
<div className={styles.toy}>
|
||||
<div className={styles.sandbox}>
|
||||
<Text lowContrast>{toy} toy</Text>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user