diff --git a/cspell.json b/cspell.json
index ba729b144..edc0cd11e 100644
--- a/cspell.json
+++ b/cspell.json
@@ -6,6 +6,7 @@
"uasset",
"oodle",
"blitzkit",
- "webp"
+ "webp",
+ "hocs"
]
}
\ No newline at end of file
diff --git a/packages/i18n/strings/en.json b/packages/i18n/strings/en.json
index 3aa611c5d..e6bd6a8e7 100644
--- a/packages/i18n/strings/en.json
+++ b/packages/i18n/strings/en.json
@@ -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",
diff --git a/packages/website-ue/src/components/TankopediaCharacteristics/index.module.css b/packages/website-ue/src/components/TankopediaCharacteristics/index.module.css
new file mode 100644
index 000000000..e834eff75
--- /dev/null
+++ b/packages/website-ue/src/components/TankopediaCharacteristics/index.module.css
@@ -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;
+ }
+ }
+}
diff --git a/packages/website-ue/src/components/TankopediaCharacteristics/index.tsx b/packages/website-ue/src/components/TankopediaCharacteristics/index.tsx
new file mode 100644
index 000000000..e96336710
--- /dev/null
+++ b/packages/website-ue/src/components/TankopediaCharacteristics/index.tsx
@@ -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 (
+
+ {characteristicsOrder.map((group) => (
+
+ ))}
+
+ );
+}
+
+function Group({ group, order }: CharacteristicsGroup) {
+ const isOpen = Tankopedia.use((state) => state.groups[group]);
+ const strings = useStrings();
+
+ return (
+
+
+
+
+ {isOpen ? : }
+ {strings.tanks.characteristics.titles[group]}
+
+
+
+
+
+
+
+ {order.map((item) =>
+ "toy" in item ? : ,
+ )}
+
+
+ );
+}
+
+interface ToyProps {
+ toy: string;
+}
+
+function Toy({ toy }: ToyProps) {
+ return {toy};
+}
+
+function Item({ name }: CharacteristicRenderConfig) {
+ return {name};
+}
diff --git a/packages/website-ue/src/components/TankopediaNavigation/index.module.css b/packages/website-ue/src/components/TankopediaNavigation/index.module.css
new file mode 100644
index 000000000..9d3251994
--- /dev/null
+++ b/packages/website-ue/src/components/TankopediaNavigation/index.module.css
@@ -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);
+ }
+ }
+}
diff --git a/packages/website-ue/src/components/TankopediaNavigation/index.tsx b/packages/website-ue/src/components/TankopediaNavigation/index.tsx
new file mode 100644
index 000000000..a553eaa0b
--- /dev/null
+++ b/packages/website-ue/src/components/TankopediaNavigation/index.tsx
@@ -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 (
+
+
{
+ Tankopedia.mutate((draft) => {
+ draft.tab = TankopediaTab.Tank;
+ });
+ }}
+ >
+ {strings.tanks.navigation.tank}
+
+
+
{
+ Tankopedia.mutate((draft) => {
+ draft.tab = TankopediaTab.Characteristics;
+ });
+ }}
+ >
+ {strings.tanks.navigation.characteristics}
+
+
+ );
+}
diff --git a/packages/website-ue/src/components/TankopediaSandbox/index.module.css b/packages/website-ue/src/components/TankopediaSandbox/index.module.css
index 2b50355e7..59f36b805 100644
--- a/packages/website-ue/src/components/TankopediaSandbox/index.module.css
+++ b/packages/website-ue/src/components/TankopediaSandbox/index.module.css
@@ -1,7 +1,11 @@
.sandbox {
- position: relative;
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
height: 100%;
- .canvas {
+ &[data-visible="false"] {
+ display: none;
}
}
diff --git a/packages/website-ue/src/components/TankopediaSandbox/index.tsx b/packages/website-ue/src/components/TankopediaSandbox/index.tsx
index 1ac6162ec..7097ced63 100644
--- a/packages/website-ue/src/components/TankopediaSandbox/index.tsx
+++ b/packages/website-ue/src/components/TankopediaSandbox/index.tsx
@@ -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 (
-
-