module wrapping

This commit is contained in:
tresabhi committed 2026-05-19 13:20:54 -05:00
1 parent 402d054b30
commit d66d25a261
7 files changed
+87 -43

No files matched your search

@@ -1,5 +1,6 @@
.link {
text-decoration-color: currentColor;
cursor: pointer;
display: inline;
align-items: center;
@@ -1,11 +1,14 @@
.price {
font-size: var(--font-size-minor);
display: flex;
gap: var(--space-3);
height: 1em;
.entry {
display: block;
line-height: 1;
font-size: inherit;
.wrapper {
display: flex;
@@ -17,6 +17,12 @@ export function Price({ price, className, ...props }: PriceProps) {
{price.price_list.map((entry, index) => (
<PriceEntry key={index} entry={entry} />
))}
{price.price_list.length === 0 && (
<Text className={styles.entry} lowContrast>
Free
</Text>
)}
</div>
);
}
@@ -27,8 +33,6 @@ interface PriceEntryProps {
function PriceEntry({ entry }: PriceEntryProps) {
if (entry.premium_time_price !== undefined) {
console.log(entry);
throw new Error("Unsupported price type");
}
@@ -60,7 +64,7 @@ function PriceInternal({ icon, value }: PriceInternalProps) {
const locale = useLocale();
return (
<Text weight="light" size="minor" lowContrast className={styles.entry}>
<Text weight="light" lowContrast className={styles.entry}>
<div className={styles.wrapper}>
<img className={styles.icon} src={icon} />
{formatCompact(locale, value)}
@@ -60,40 +60,57 @@
.line {
display: flex;
flex-direction: column;
gap: var(--space-3);
.wrapper {
.line-wrap {
display: flex;
flex-direction: column;
align-items: center;
gap: var(--space-2);
.stage {
position: relative;
gap: var(--space-3);
padding: var(--space-3);
.wrap-marker {
padding-bottom: var(--font-size-minor);
font-size: 2em;
.icon {
svg {
width: 1em;
height: 1em;
transform: translate(var(--space-1), var(--space-1));
}
}
.tier {
position: absolute;
left: var(--space-2);
top: var(--space-2);
}
.wrapper {
display: flex;
flex-direction: column;
align-items: center;
gap: var(--space-2);
.price {
position: absolute;
left: 50%;
bottom: var(--space-2);
transform: translateX(-50%);
.stage {
position: relative;
padding: var(--space-3);
font-size: 2em;
.icon {
width: 1em;
height: 1em;
transform: translate(var(--space-1), var(--space-1));
}
.tier {
position: absolute;
left: var(--space-2);
top: var(--space-2);
}
.price {
position: absolute;
left: 50%;
bottom: var(--space-2);
transform: translateX(-50%);
}
}
}
}
@@ -1,10 +1,14 @@
import { romanize } from "@blitzkit/core";
import type { BlitzStaticEquipmentPresetComponent_EquipmentSlot } from "@protos/blitz_static_equipment_preset_component";
import { Grade } from "@protos/blitz_static_standard_grades_enum";
import type { StandardPrice } from "@protos/blitz_static_standard_price";
import { StandardPrice } from "@protos/blitz_static_standard_price";
import type { UpgradeLine } from "@protos/blitz_static_tank_upgrade_line";
import type { StageParameters } from "@protos/blitz_static_tank_upgrade_single_stage";
import { DoubleArrowDownIcon, DoubleArrowUpIcon } from "@radix-ui/react-icons";
import {
CornerBottomLeftIcon,
DoubleArrowLeftIcon,
DoubleArrowRightIcon,
} from "@radix-ui/react-icons";
import { chunk } from "lodash-es";
import { useMemo } from "react";
import { equipmentColumns } from "../../config/equipment";
@@ -12,6 +16,7 @@ import { catImages } from "../../config/images";
import {
alternativeLines,
isAlternativeLine,
maxModulesPerRow,
originalLineName,
} from "../../config/modules";
import { useEquipment } from "../../hooks/useEquipment";
@@ -21,7 +26,7 @@ import { useUpgradePreset } from "../../hooks/useUpgradePreset";
import { Tankopedia } from "../../stores/tankopedia";
import { Button } from "../Button";
import { Heading } from "../Heading";
import { IconButton } from "../IconButton";
import { Link } from "../Link";
import { Price } from "../Price";
import { Section } from "../Section";
import { Text } from "../Text";
@@ -167,7 +172,7 @@ function Modules() {
<div className={styles.header}>
<Heading size="4">{strings.tanks.loadout.modules}</Heading>
<IconButton
<Link
onClick={() => {
Tankopedia.mutate((draft) => {
for (const line of tank.tank!.upgrade_lines) {
@@ -178,13 +183,12 @@ function Modules() {
}
});
}}
color="tomato"
variant="ghost"
color="gray"
>
<DoubleArrowDownIcon />
</IconButton>
<DoubleArrowLeftIcon />
</Link>
<IconButton
<Link
onClick={() => {
Tankopedia.mutate((draft) => {
for (const line of tank.tank!.upgrade_lines) {
@@ -197,11 +201,10 @@ function Modules() {
}
});
}}
color="jade"
variant="ghost"
color="gray"
>
<DoubleArrowUpIcon />
</IconButton>
<DoubleArrowRightIcon />
</Link>
</div>
<div className={styles.lines}>
@@ -254,8 +257,23 @@ function Line({ name, lines }: LineProps) {
function LineInner({ name, lines }: LineProps) {
const line = lines.find((line) => line.name === name)!;
return line.stages.map((stage, index) => (
<LineElement key={index} index={index} lineName={name} stage={stage} />
return chunk(line.stages, maxModulesPerRow).map((chunk, wrapIndex) => (
<div className={styles["line-wrap"]}>
{wrapIndex > 0 && (
<Text size="minor" className={styles["wrap-marker"]} lowContrast>
<CornerBottomLeftIcon />
</Text>
)}
{chunk.map((stage, elementIndex) => (
<LineElement
key={elementIndex}
index={wrapIndex * maxModulesPerRow + elementIndex}
lineName={name}
stage={stage}
/>
))}
</div>
));
}
@@ -297,6 +315,8 @@ function LineElement({ index, lineName, stage }: LineElementProps) {
price = override.price;
}
price ??= StandardPrice.create();
let isSelected: boolean;
if (isAlternativeLine(lineName)) {
@@ -395,7 +415,7 @@ function LineElement({ index, lineName, stage }: LineElementProps) {
</Text>
</Button>
{price && <Price className={styles.price} price={price} />}
{<Price className={styles.price} price={price} />}
</div>
);
}
@@ -1,3 +1,5 @@
export const maxModulesPerRow = 5;
export const alternativeLines: Record<string, string> = {
guns: "alternative_guns",
};
@@ -2,7 +2,6 @@
import "@radix-ui/colors/violet-dark.css";
import { api } from "../../../../api/dynamic";
import { mixStaticPaths } from "../../../../astro/mixStaticPaths";
import ColorScale from "../../../../components/ColorScale.astro";
import BaseLayout from "../../../../layouts/BaseLayout.astro";
import { getStaticPaths as _getStaticPaths } from "../index.astro";
import { Page } from "./_index";
@@ -20,8 +19,6 @@ const { id, locale } = Astro.props;
---
<BaseLayout {locale} accent="violet">
<ColorScale color="tomato" />
<ColorScale color="jade" />
<Page {locale} {id} client:load />
</BaseLayout>