mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-21 18:57:03 +02:00
final layout
This commit is contained in:
1 parent
73de6e3521
commit
9b8d4c4e3c
5 files changed
+240
-167
No files matched your search
@@ -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",
|
||||
|
||||
Reference in new issue
Block a user