final layout

This commit is contained in:
tresabhi committed 2026-06-02 12:27:32 -05:00
1 parent 73de6e3521
commit 9b8d4c4e3c
5 files changed
+240 -167

No files matched your search

+7 -3
View File
@@ -204,10 +204,14 @@
"tanks": {
"characteristics": {
"titles": {
"meta": "Meta",
"firepower": "Firepower",
"gun": "Gun",
"clip": "Clip",
"shell": "Shell",
"accuracy": "Accuracy",
"flexibility": "Flexibility",
"maneuverability": "Maneuverability",
"survivability": "Survivability"
"survivability": "Survivability",
"concealment": "Concealment"
},
"items": {
@@ -1,105 +1,133 @@
.characteristics {
--cell-width: 2.5rem;
.characteristics-wrapper {
margin: 0 var(--space-4);
--base-cell-width: 20rem;
--group-span: 7;
--inner-padding: var(--space-4);
display: grid;
grid-auto-rows: var(--cell-width);
grid-template-columns: repeat(auto-fill, minmax(var(--cell-width), 1fr));
grid-auto-flow: dense;
container-type: inline-size;
padding: var(--space-5);
gap: var(--space-4);
.characteristics {
--N: round(down, 100cqw / var(--base-cell-width));
--cell-width: calc(100cqw / var(--N));
--cell-height: calc(var(--cell-width) / var(--group-span));
box-sizing: border-box;
.group {
display: grid;
grid-template-columns: 1fr;
grid-template-columns: repeat(
auto-fill,
minmax(var(--base-cell-width), 1fr)
);
grid-auto-rows: var(--cell-height);
grid-auto-flow: dense;
grid-column: span var(--group-span);
gap: inherit;
gap: var(--cell-gap);
.title-wrapper {
background-color: var(--amber-a3);
grid-row: span 1;
box-sizing: border-box;
padding: 0 var(--inner-padding);
.group {
--gradient-size: min(100%, var(--space-8));
display: flex;
align-items: center;
gap: var(--space-3);
grid-column: span 1;
display: grid;
grid-template-columns: inherit;
grid-auto-rows: inherit;
.title {
.content {
display: flex;
align-items: center;
gap: var(--space-2);
grid-row: span 1;
cursor: pointer;
svg {
width: 1em;
height: 1em;
}
}
}
}
.item {
padding: 0 var(--inner-padding);
grid-row: span 1;
display: flex;
flex-direction: column;
justify-content: center;
gap: var(--space-2);
.value {
display: flex;
justify-content: space-between;
}
.ranking {
display: flex;
align-items: center;
gap: var(--space-3);
margin: 0 calc(var(--space-4));
.bar-wrapper {
.center {
flex: 1;
height: var(--space-1);
padding: var(--space-3);
background-color: var(--gray-3);
border-radius: var(--radius-max);
overflow: hidden;
.text {
.align {
display: flex;
align-items: center;
gap: var(--space-2);
.bar {
background-color: var(--jade-9);
width: 75%;
height: 100%;
svg {
width: 1em;
height: 1em;
}
}
}
}
}
}
.toy {
grid-row: span var(--group-span);
padding: var(--inner-padding);
.content {
background-color: green;
width: 100%;
margin: 0 var(--space-4);
padding: var(--space-0);
gap: inherit;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
background-color: var(--gray-2);
outline: var(--gray-5) solid var(--space-1);
.item {
padding: 0 var(--space-3);
border-radius: var(--space-3);
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
gap: var(--space-2);
.value {
display: flex;
justify-content: space-between;
}
.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 {
flex: 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;
}
}
}
@@ -1,4 +1,3 @@
import { GearIcon } from "@radix-ui/react-icons";
import { useCharacteristicRenderer } from "../../hooks/useCharacteristicRenderer";
import { useStrings } from "../../hooks/useStrings";
import type { CharacteristicOutput } from "../../tankopedia/characteristics";
@@ -8,6 +7,7 @@ import {
type CharacteristicsGroup,
} from "../../tankopedia/characteristicsOrder";
import type { ComputedCharacteristics } from "../../tankopedia/computeCharacteristics";
import { Heading } from "../Heading";
import { Text } from "../Text";
import styles from "./index.module.css";
@@ -19,10 +19,12 @@ export function TankopediaCharacteristics({
characteristics,
}: TankopediaCharacteristicsProps) {
return (
<div className={styles.characteristics}>
{characteristicsOrder.map((group) => (
<Group group={group} characteristics={characteristics} />
))}
<div className={styles["characteristics-wrapper"]}>
<div className={styles.characteristics}>
{characteristicsOrder.map((group) => (
<Group group={group} characteristics={characteristics} />
))}
</div>
</div>
);
}
@@ -36,32 +38,48 @@ 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).length;
const span = `calc(${toys} * var(--group-span) + ${items} + 1)`;
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 ${span}`,
gridTemplateRows: `repeat(${span}, 1fr)`,
gridRow: `span ${groupSpan}`,
gridTemplateRows: `repeat(${groupSpan}, 1fr)`,
}}
>
<div className={styles["title-wrapper"]}>
<Text className={styles.title}>
<div className={styles.content}>
{group.group}
<GearIcon />
</div>
</Text>
<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.group]
}
{/*<GearIcon />*/}
</div>
</Heading>
</div>
</div>
{group.order.map((item) =>
"toy" in item ? (
<Toy {...item} />
) : (
<Item config={item} value={characteristics[item.name]} />
),
)}
<div
className={styles.content}
style={{
gridRow: `span ${contentSpan}`,
}}
>
{group.order.map((item) =>
"toy" in item ? (
<Toy {...item} />
) : (
<Item config={item} value={characteristics[item.name]} />
),
)}
<div className={styles.dead} />
</div>
</div>
);
}
@@ -83,9 +101,7 @@ function Item({ config, value }: ItemProps) {
</div>
<div className={styles.ranking}>
<div className={styles["bar-wrapper"]}>
<div className={styles.bar} />
</div>
<Bar value={Math.random()} />
<Text lowContrast size="minor" className={styles.number}>
1 / 132
@@ -95,6 +111,35 @@ function Item({ config, value }: ItemProps) {
);
}
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;
}
@@ -102,7 +147,7 @@ interface ToyProps {
function Toy({ toy }: ToyProps) {
return (
<div className={styles.toy}>
<div className={styles.content}>
<div className={styles.sandbox}>
<Text lowContrast>{toy} toy</Text>
</div>
</div>
@@ -20,10 +20,12 @@ const { id, locale } = Astro.props;
---
<BaseLayout {locale} accent="violet">
<ColorScale color="red" />
<ColorScale color="jade" />
<ColorScale color="amber" />
<ColorScale color="amber" alpha />
<ColorScale color="red" />
<ColorScale color="orange" />
<ColorScale color="amber" />
<ColorScale color="jade" />
<Page {locale} {id} client:load />
</BaseLayout>
@@ -1,11 +1,5 @@
import type { Strings } from "@blitzkit/i18n";
import {
Nation,
TankClass,
TankType,
} from "@protos/blitz_static_tank_component";
import type { ReactNode } from "react";
import { VintageIcon } from "../icons/Vintage";
import {
GunType,
type CharacteristicName,
@@ -45,65 +39,65 @@ export enum CharacteristicsGroupRender {
}
export const characteristicsOrder: CharacteristicsGroup[] = [
{
group: "meta",
render: CharacteristicsGroupRender.Flashy,
order: [
{
name: "name",
strings: "TankEntity",
render({ output, gameStrings }) {
return gameStrings[output as string];
},
},
{
name: "class",
render({ output, strings }) {
return strings.classes.full[output as TankClass];
},
},
{
name: "type",
render({ output, strings }) {
return strings.types[output as TankType];
},
},
{
name: "nation",
render({ output, strings }) {
return strings.nations[output as Nation];
},
},
{
name: "tier",
render({ output, strings }) {
const name = output as string;
// {
// group: "meta",
// render: CharacteristicsGroupRender.Flashy,
// order: [
// {
// name: "name",
// strings: "TankEntity",
// render({ output, gameStrings }) {
// return gameStrings[output as string];
// },
// },
// {
// name: "class",
// render({ output, strings }) {
// return strings.classes.full[output as TankClass];
// },
// },
// {
// name: "type",
// render({ output, strings }) {
// return strings.types[output as TankType];
// },
// },
// {
// name: "nation",
// render({ output, strings }) {
// return strings.nations[output as Nation];
// },
// },
// {
// name: "tier",
// render({ output, strings }) {
// const name = output as string;
if (name == "vintage") {
return <VintageIcon />;
}
// if (name == "vintage") {
// return <VintageIcon />;
// }
return strings.tiers[name as keyof typeof strings.tiers];
},
},
{ name: "id" },
{ name: "slug" },
],
},
// return strings.tiers[name as keyof typeof strings.tiers];
// },
// },
// { name: "id" },
// { name: "slug" },
// ],
// },
{
group: "economics",
render: CharacteristicsGroupRender.Statistical,
order: [
{ name: "purchase_price" },
{ name: "compensation" },
{ name: "upgrade_price" },
{ name: "research_level" },
{ name: "crew_xp_multiplier" },
// {
// group: "economics",
// render: CharacteristicsGroupRender.Statistical,
// order: [
// { name: "purchase_price" },
// { name: "compensation" },
// { name: "upgrade_price" },
// { name: "research_level" },
// { name: "crew_xp_multiplier" },
// TODO: investigate ATTRIBUTE_NAME_CREW_XP_MULTIPLIER
],
},
// // TODO: investigate ATTRIBUTE_NAME_CREW_XP_MULTIPLIER
// ],
// },
{
group: "gun",