mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-21 10:47:04 +02:00
some more tankoepdia layout
This commit is contained in:
1 parent
d2b4cc3e7d
commit
0a186399b6
12 files changed
+234
-8
No files matched your search
+2
-1
@@ -6,6 +6,7 @@
|
||||
"uasset",
|
||||
"oodle",
|
||||
"blitzkit",
|
||||
"webp"
|
||||
"webp",
|
||||
"hocs"
|
||||
]
|
||||
}
|
||||
@@ -202,6 +202,20 @@
|
||||
},
|
||||
|
||||
"tanks": {
|
||||
"characteristics": {
|
||||
"titles": {
|
||||
"meta": "Meta",
|
||||
"firepower": "Firepower",
|
||||
"maneuverability": "Maneuverability",
|
||||
"survivability": "Survivability"
|
||||
}
|
||||
},
|
||||
|
||||
"navigation": {
|
||||
"tank": "Tank",
|
||||
"characteristics": "Characteristics"
|
||||
},
|
||||
|
||||
"loadout": {
|
||||
"consumables": "Consumables",
|
||||
"modules": "Modules",
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
.characteristics {
|
||||
padding: var(--space-5);
|
||||
padding-top: var(--space-6);
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--space-5);
|
||||
box-sizing: border-box;
|
||||
|
||||
max-height: 100%;
|
||||
overflow-y: auto;
|
||||
|
||||
&[data-visible="false"] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
gap: var(--space-4);
|
||||
|
||||
.title-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-4);
|
||||
|
||||
.title {
|
||||
.title-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-2);
|
||||
|
||||
cursor: pointer;
|
||||
|
||||
svg {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.separator {
|
||||
height: var(--space-1);
|
||||
flex: 1;
|
||||
|
||||
background-color: var(--gray-5);
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
import { CaretDownIcon, CaretRightIcon } from "@radix-ui/react-icons";
|
||||
import {
|
||||
characteristicsOrder,
|
||||
type CharacteristicRenderConfig,
|
||||
type CharacteristicsGroup,
|
||||
} from "../../tankopedia/characteristicsOrder";
|
||||
import styles from "./index.module.css";
|
||||
import { Heading } from "../Heading";
|
||||
import { Tankopedia, TankopediaTab } from "../../stores/tankopedia";
|
||||
import { useStrings } from "../../hooks/useStrings";
|
||||
|
||||
export function TankopediaCharacteristics() {
|
||||
const isVisible = Tankopedia.use(
|
||||
(state) => state.tab === TankopediaTab.Characteristics,
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={styles.characteristics} data-visible={isVisible}>
|
||||
{characteristicsOrder.map((group) => (
|
||||
<Group {...group} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function Group({ group, order }: CharacteristicsGroup) {
|
||||
const isOpen = Tankopedia.use((state) => state.groups[group]);
|
||||
const strings = useStrings();
|
||||
|
||||
return (
|
||||
<div className={styles.group}>
|
||||
<div className={styles["title-wrapper"]}>
|
||||
<Heading className={styles.title} size="3">
|
||||
<div className={styles["title-content"]}>
|
||||
{isOpen ? <CaretDownIcon /> : <CaretRightIcon />}
|
||||
{strings.tanks.characteristics.titles[group]}
|
||||
</div>
|
||||
</Heading>
|
||||
|
||||
<div className={styles.separator} />
|
||||
</div>
|
||||
|
||||
<div className={styles.content}>
|
||||
{order.map((item) =>
|
||||
"toy" in item ? <Toy {...item} /> : <Item {...item} />,
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
interface ToyProps {
|
||||
toy: string;
|
||||
}
|
||||
|
||||
function Toy({ toy }: ToyProps) {
|
||||
return <span>{toy}</span>;
|
||||
}
|
||||
|
||||
function Item({ name }: CharacteristicRenderConfig) {
|
||||
return <span>{name}</span>;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
.tabs {
|
||||
display: flex;
|
||||
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
|
||||
.tab {
|
||||
padding: var(--space-3) var(--space-5);
|
||||
border-top: var(--space-2) solid transparent;
|
||||
|
||||
cursor: pointer;
|
||||
|
||||
&[data-selected="true"] {
|
||||
background: linear-gradient(var(--accent-a4), transparent);
|
||||
border-top: var(--space-2) solid var(--accent-9);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import { useStrings } from "../../hooks/useStrings";
|
||||
import { Tankopedia, TankopediaTab } from "../../stores/tankopedia";
|
||||
import { Text } from "../Text";
|
||||
import styles from "./index.module.css";
|
||||
|
||||
export function TankopediaNavigation() {
|
||||
const strings = useStrings();
|
||||
const tab = Tankopedia.use((state) => state.tab);
|
||||
|
||||
return (
|
||||
<div className={styles.tabs}>
|
||||
<div
|
||||
className={styles.tab}
|
||||
data-selected={tab === TankopediaTab.Tank}
|
||||
onClick={() => {
|
||||
Tankopedia.mutate((draft) => {
|
||||
draft.tab = TankopediaTab.Tank;
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Text>{strings.tanks.navigation.tank}</Text>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className={styles.tab}
|
||||
data-selected={tab === TankopediaTab.Characteristics}
|
||||
onClick={() => {
|
||||
Tankopedia.mutate((draft) => {
|
||||
draft.tab = TankopediaTab.Characteristics;
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Text>{strings.tanks.navigation.characteristics}</Text>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,7 +1,11 @@
|
||||
.sandbox {
|
||||
position: relative;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
.canvas {
|
||||
&[data-visible="false"] {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@@ -2,11 +2,19 @@ import { Canvas, useLoader } from "@react-three/fiber";
|
||||
import { OrbitControls } from "@react-three/drei";
|
||||
import styles from "./index.module.css";
|
||||
import { GLTFLoader } from "three-stdlib";
|
||||
import { Tankopedia } from "../../stores/tankopedia";
|
||||
import { TankopediaTab } from "../../stores/tankopedia";
|
||||
|
||||
export function TankopediaSandbox() {
|
||||
const isVisible = Tankopedia.use((state) => state.tab === TankopediaTab.Tank);
|
||||
|
||||
return (
|
||||
<div className={styles.sandbox}>
|
||||
<Canvas shadows className={styles.canvas}>
|
||||
<div className={styles.sandbox} data-visible={isVisible}>
|
||||
<Canvas
|
||||
shadows
|
||||
className={styles.canvas}
|
||||
frameloop={isVisible ? "always" : "never"}
|
||||
>
|
||||
{!import.meta.env.SSR && <Content />}
|
||||
</Canvas>
|
||||
</div>
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
display: flex;
|
||||
|
||||
.sandbox {
|
||||
position: relative;
|
||||
|
||||
flex-grow: 1;
|
||||
background-color: black;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@ import { characteristicsOrder } from "../../../../tankopedia/characteristicsOrde
|
||||
import { computeCharacteristics } from "../../../../tankopedia/computeCharacteristics";
|
||||
import styles from "./_index.module.css";
|
||||
import { TankopediaSandbox } from "../../../../components/TankopediaSandbox";
|
||||
import { TankopediaNavigation } from "../../../../components/TankopediaNavigation";
|
||||
import { TankopediaCharacteristics } from "../../../../components/TankopediaCharacteristics";
|
||||
|
||||
interface PageProps {
|
||||
id: string;
|
||||
@@ -41,6 +43,8 @@ export const Page = withErrorWrapper(
|
||||
<div className={styles.page}>
|
||||
<div className={styles.sandbox}>
|
||||
<TankopediaSandbox />
|
||||
<TankopediaCharacteristics />
|
||||
<TankopediaNavigation />
|
||||
</div>
|
||||
|
||||
<div className={styles.stats}>
|
||||
|
||||
@@ -2,9 +2,13 @@ import type { Tank } from "@protos/tank";
|
||||
import { Varuna } from "varuna";
|
||||
import { createTankState } from "../tankopedia/createTankState";
|
||||
import { type TankState } from "../tankopedia/tankState";
|
||||
import { characteristicsOrder } from "../tankopedia/characteristicsOrder";
|
||||
|
||||
interface Tankopedia {
|
||||
compare: TankopediaCompare;
|
||||
tab: TankopediaTab;
|
||||
groups: Record<string, boolean>;
|
||||
|
||||
protagonist: TankState;
|
||||
}
|
||||
|
||||
@@ -14,7 +18,21 @@ export enum TankopediaCompare {
|
||||
All,
|
||||
}
|
||||
|
||||
export enum TankopediaTab {
|
||||
Tank,
|
||||
Characteristics,
|
||||
}
|
||||
|
||||
const groups: Record<string, boolean> = {};
|
||||
|
||||
for (const { group } of characteristicsOrder) {
|
||||
groups[group] = true;
|
||||
}
|
||||
|
||||
export const Tankopedia = new Varuna<Tankopedia, Tank>((tank) => ({
|
||||
compare: TankopediaCompare.TierAndClass,
|
||||
tab: TankopediaTab.Characteristics,
|
||||
groups,
|
||||
|
||||
protagonist: createTankState(tank),
|
||||
}));
|
||||
@@ -29,7 +29,7 @@ export interface CharacteristicRenderConfig {
|
||||
}) => ReactNode;
|
||||
}
|
||||
|
||||
type CharacteristicsOrder = {
|
||||
export type CharacteristicsGroup = {
|
||||
group: string;
|
||||
order: (
|
||||
| CharacteristicRenderConfig
|
||||
@@ -37,9 +37,9 @@ type CharacteristicsOrder = {
|
||||
toy: string;
|
||||
}
|
||||
)[];
|
||||
}[];
|
||||
};
|
||||
|
||||
export const characteristicsOrder: CharacteristicsOrder = [
|
||||
export const characteristicsOrder: CharacteristicsGroup[] = [
|
||||
{
|
||||
group: "meta",
|
||||
order: [
|
||||
|
||||
Reference in new issue
Block a user