mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-24 03:59:50 +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",
|
"uasset",
|
||||||
"oodle",
|
"oodle",
|
||||||
"blitzkit",
|
"blitzkit",
|
||||||
"webp"
|
"webp",
|
||||||
|
"hocs"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -202,6 +202,20 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
"tanks": {
|
"tanks": {
|
||||||
|
"characteristics": {
|
||||||
|
"titles": {
|
||||||
|
"meta": "Meta",
|
||||||
|
"firepower": "Firepower",
|
||||||
|
"maneuverability": "Maneuverability",
|
||||||
|
"survivability": "Survivability"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"navigation": {
|
||||||
|
"tank": "Tank",
|
||||||
|
"characteristics": "Characteristics"
|
||||||
|
},
|
||||||
|
|
||||||
"loadout": {
|
"loadout": {
|
||||||
"consumables": "Consumables",
|
"consumables": "Consumables",
|
||||||
"modules": "Modules",
|
"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 {
|
.sandbox {
|
||||||
position: relative;
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
height: 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 { OrbitControls } from "@react-three/drei";
|
||||||
import styles from "./index.module.css";
|
import styles from "./index.module.css";
|
||||||
import { GLTFLoader } from "three-stdlib";
|
import { GLTFLoader } from "three-stdlib";
|
||||||
|
import { Tankopedia } from "../../stores/tankopedia";
|
||||||
|
import { TankopediaTab } from "../../stores/tankopedia";
|
||||||
|
|
||||||
export function TankopediaSandbox() {
|
export function TankopediaSandbox() {
|
||||||
|
const isVisible = Tankopedia.use((state) => state.tab === TankopediaTab.Tank);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.sandbox}>
|
<div className={styles.sandbox} data-visible={isVisible}>
|
||||||
<Canvas shadows className={styles.canvas}>
|
<Canvas
|
||||||
|
shadows
|
||||||
|
className={styles.canvas}
|
||||||
|
frameloop={isVisible ? "always" : "never"}
|
||||||
|
>
|
||||||
{!import.meta.env.SSR && <Content />}
|
{!import.meta.env.SSR && <Content />}
|
||||||
</Canvas>
|
</Canvas>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
.sandbox {
|
.sandbox {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
background-color: black;
|
background-color: black;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ import { characteristicsOrder } from "../../../../tankopedia/characteristicsOrde
|
|||||||
import { computeCharacteristics } from "../../../../tankopedia/computeCharacteristics";
|
import { computeCharacteristics } from "../../../../tankopedia/computeCharacteristics";
|
||||||
import styles from "./_index.module.css";
|
import styles from "./_index.module.css";
|
||||||
import { TankopediaSandbox } from "../../../../components/TankopediaSandbox";
|
import { TankopediaSandbox } from "../../../../components/TankopediaSandbox";
|
||||||
|
import { TankopediaNavigation } from "../../../../components/TankopediaNavigation";
|
||||||
|
import { TankopediaCharacteristics } from "../../../../components/TankopediaCharacteristics";
|
||||||
|
|
||||||
interface PageProps {
|
interface PageProps {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -41,6 +43,8 @@ export const Page = withErrorWrapper(
|
|||||||
<div className={styles.page}>
|
<div className={styles.page}>
|
||||||
<div className={styles.sandbox}>
|
<div className={styles.sandbox}>
|
||||||
<TankopediaSandbox />
|
<TankopediaSandbox />
|
||||||
|
<TankopediaCharacteristics />
|
||||||
|
<TankopediaNavigation />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={styles.stats}>
|
<div className={styles.stats}>
|
||||||
|
|||||||
@@ -2,9 +2,13 @@ import type { Tank } from "@protos/tank";
|
|||||||
import { Varuna } from "varuna";
|
import { Varuna } from "varuna";
|
||||||
import { createTankState } from "../tankopedia/createTankState";
|
import { createTankState } from "../tankopedia/createTankState";
|
||||||
import { type TankState } from "../tankopedia/tankState";
|
import { type TankState } from "../tankopedia/tankState";
|
||||||
|
import { characteristicsOrder } from "../tankopedia/characteristicsOrder";
|
||||||
|
|
||||||
interface Tankopedia {
|
interface Tankopedia {
|
||||||
compare: TankopediaCompare;
|
compare: TankopediaCompare;
|
||||||
|
tab: TankopediaTab;
|
||||||
|
groups: Record<string, boolean>;
|
||||||
|
|
||||||
protagonist: TankState;
|
protagonist: TankState;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -14,7 +18,21 @@ export enum TankopediaCompare {
|
|||||||
All,
|
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) => ({
|
export const Tankopedia = new Varuna<Tankopedia, Tank>((tank) => ({
|
||||||
compare: TankopediaCompare.TierAndClass,
|
compare: TankopediaCompare.TierAndClass,
|
||||||
|
tab: TankopediaTab.Characteristics,
|
||||||
|
groups,
|
||||||
|
|
||||||
protagonist: createTankState(tank),
|
protagonist: createTankState(tank),
|
||||||
}));
|
}));
|
||||||
@@ -29,7 +29,7 @@ export interface CharacteristicRenderConfig {
|
|||||||
}) => ReactNode;
|
}) => ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
type CharacteristicsOrder = {
|
export type CharacteristicsGroup = {
|
||||||
group: string;
|
group: string;
|
||||||
order: (
|
order: (
|
||||||
| CharacteristicRenderConfig
|
| CharacteristicRenderConfig
|
||||||
@@ -37,9 +37,9 @@ type CharacteristicsOrder = {
|
|||||||
toy: string;
|
toy: string;
|
||||||
}
|
}
|
||||||
)[];
|
)[];
|
||||||
}[];
|
};
|
||||||
|
|
||||||
export const characteristicsOrder: CharacteristicsOrder = [
|
export const characteristicsOrder: CharacteristicsGroup[] = [
|
||||||
{
|
{
|
||||||
group: "meta",
|
group: "meta",
|
||||||
order: [
|
order: [
|
||||||
|
|||||||
Reference in new issue
Block a user