migrate tank filters

This commit is contained in:
tresabhi committed 2026-08-26 14:02:44 -05:00
1 parent d477a3a7a4
commit 1e1040816b
13 files changed
+153 -60

No files matched your search

@@ -10,6 +10,7 @@ export interface ButtonProps extends ComponentProps<"button"> {
size?: "regular" | "minor";
array?: boolean;
parentArray?: boolean;
highContrast?: boolean; // TODO: add high contrast
}
export const LIGHT_TEXT_COLORS = new Set<Color>([
@@ -51,4 +52,4 @@ export function Button({
{...props}
/>
);
}
}
@@ -0,0 +1,3 @@
.flex {
display: flex;
}
@@ -0,0 +1,20 @@
import type { ComponentProps } from "react";
import type { Space } from "../../types/space";
import { classNames } from "../../ui/classNames";
import styles from "./index.module.css";
interface Props extends ComponentProps<"div"> {
gap?: Space;
}
export function Flex({ children, className, gap, ...props }: Props) {
return (
<div
{...props}
className={classNames(styles.flex, className)}
data-gap={gap}
>
{children}
</div>
);
}
@@ -0,0 +1,5 @@
.icon-button {
padding: var(--space-3);
aspect-ratio: 1 / 1;
}
@@ -0,0 +1,12 @@
import { classNames } from "../../ui/classNames";
import { Button, type ButtonProps } from "../Button";
import styles from "./index.module.css";
export function IconButton({ className, ...props }: ButtonProps) {
return (
<Button
className={classNames(className, styles["icon-button"])}
{...props}
/>
);
}
@@ -20,7 +20,7 @@ import { App } from "../stores/app";
import { TankFilters } from "../stores/tankFilters";
import type { MaybeSkeletonComponentProps } from "../types/maybeSkeletonComponentProps";
import { LinkI18n } from "./LinkI18n";
import { FilterControl } from "./TankSearch/components/FilterControl";
import { TankSearchFilters } from "./TankSearchFilters";
const tankDefinitions = await api.tankDefinitions();
@@ -87,7 +87,7 @@ export function PlaylistGenerator({ skeleton }: MaybeSkeletonComponentProps) {
direction={{ initial: "column-reverse", md: "row" }}
>
<Flex direction="column" gap="4" align="center">
<FilterControl />
<TankSearchFilters />
<Button
onClick={() => {
@@ -25,12 +25,12 @@ import type { MaybeSkeletonComponentProps } from "../../types/maybeSkeletonCompo
import { Callout } from "../Callout";
import { ExperimentIcon } from "../ExperimentIcon";
import { Link } from "../Link";
import { TankSearchBar } from "../TankSearchBar";
import { TankSearchFilters } from "../TankSearchFilters";
import { Text } from "../Text";
import { TankSearchCard } from "./components/Card";
import { FilterControl } from "./components/FilterControl";
import { NoResults } from "./components/NoResults";
import { RecentlyViewed } from "./components/RecentlyViewed";
import { TankSearchBar } from "../TankSearchBar";
import { SkeletonTankCard } from "./components/SkeletonTankCard";
import { TankCardWrapper } from "./components/TankCardWrapper";
import { MAX_RECENTLY_VIEWED } from "./constants";
@@ -437,7 +437,7 @@ export const TankSearch = memo<TankSearchProps>(
onSelect={onSelect}
/>
{!tankFilters.search && !tankFilters.searching && <FilterControl />}
{!tankFilters.search && !tankFilters.searching && <TankSearchFilters />}
{!skeleton && !compact && <RecentlyViewed />}
@@ -0,0 +1,25 @@
.nation-option {
/* width="calc(100% + calc(4 * var(--space-2)))"
height="100%"
position="absolute"
right="0"
mr="-2"
style={{
backgroundImage: `url(${alias("api", `/flags/scratched/${nation}.webp`)})`,
backgroundSize: "100%",
backgroundRepeat: "no-repeat",
backgroundPosition: "5rem center",
}} */
.overlay {
/* width="100%"
height="100%"
style={{
background: `linear-gradient(90deg, var(--gray-2) 50%, transparent)`,
}} */
}
}
.overflow-plus {
/* ml="1" */
}
@@ -17,18 +17,25 @@ import {
} from "@radix-ui/react-icons";
import { times } from "lodash-es";
import { Fragment, type ComponentProps, type ReactNode } from "react";
import { api } from "../../../core/blitzkit/api";
import { useLocale } from "../../../hooks/useLocale";
import { App } from "../../../stores/app";
import { TankFilters, type CaseType } from "../../../stores/tankFilters";
import { classIcons } from "../../ClassIcon";
import { GunAutoloaderIcon } from "../../GunAutoloaderIcon";
import { GunAutoreloaderIcon } from "../../GunAutoreloaderIcon";
import { GunRegularIcon } from "../../GunRegularIcon";
import { MissingShellIcon } from "../../MissingShellIcon";
import { ResearchedIcon } from "../../ResearchedIcon";
import { ScienceIcon } from "../../ScienceIcon";
import { ScienceOffIcon } from "../../ScienceOffIcon";
import { api } from "../../core/blitzkit/api";
import { useLocale } from "../../hooks/useLocale";
import { App } from "../../stores/app";
import { TankFilters, type CaseType } from "../../stores/tankFilters";
import { Button } from "../Button";
import { classIcons } from "../ClassIcon";
import { DropdownMenu } from "../DropdownMenu";
import { Flex } from "../Flex";
import { GunAutoloaderIcon } from "../GunAutoloaderIcon";
import { GunAutoreloaderIcon } from "../GunAutoreloaderIcon";
import { GunRegularIcon } from "../GunRegularIcon";
import { IconButton } from "../IconButton";
import { MissingShellIcon } from "../MissingShellIcon";
import { ResearchedIcon } from "../ResearchedIcon";
import { ScienceIcon } from "../ScienceIcon";
import { ScienceOffIcon } from "../ScienceOffIcon";
import { Text } from "../Text";
import { Tooltip } from "../Tooltip";
import styles from "./index.module.css";
const gameDefinitions = await api.gameDefinitions();
const consumableDefinitions = await api.consumableDefinitions();
@@ -165,14 +172,9 @@ const MAX_ICONS = 4;
const TIERS = times(10, (i) => 10 - i);
export function FilterControl() {
export function TankSearchFilters() {
return (
<Flex
align="center"
justify={{ initial: "start", md: "center" }}
gap="2"
wrap="wrap"
>
<div className={styles.container}>
<TiersFilter />
<ClassFilter />
<TypeFilter />
@@ -188,7 +190,7 @@ export function FilterControl() {
<GameModeAbilitiesFilter />
<ResetButton />
</Flex>
</div>
);
}
@@ -217,13 +219,13 @@ function TiersFilter() {
<Button color="gray" variant="surface">
<Flex gap="1">
{tiers.slice(0, MAX_ICONS).map((tier) => (
<Text size="1" key={tier}>
<Text size="minor" key={tier}>
{TIER_ROMAN_NUMERALS[tier]}
</Text>
))}
{tiers.length > MAX_ICONS && (
<Text size="1">
<Text size="minor">
{literals(strings.common.units.plus, {
value: tiers.length - MAX_ICONS,
})}
@@ -330,27 +332,9 @@ function NationsFilter() {
position: "relative",
}}
>
<Box
width="calc(100% + calc(4 * var(--space-2)))"
height="100%"
position="absolute"
right="0"
mr="-2"
style={{
backgroundImage: `url(${alias("api", `/flags/scratched/${nation}.webp`)})`,
backgroundSize: "100%",
backgroundRepeat: "no-repeat",
backgroundPosition: "5rem center",
}}
>
<Box
width="100%"
height="100%"
style={{
background: `linear-gradient(90deg, var(--gray-2) 50%, transparent)`,
}}
/>
</Box>
<div className={styles["nation-option"]}>
<div className={styles.overlay} />
</div>
<Text style={{ zIndex: 1 }}>
{
@@ -651,7 +635,6 @@ function IndividualShellFilter({
<DropdownMenu.Root modal={false}>
<DropdownMenu.Trigger>
<IconButton
ml="-0.5px"
variant="surface"
style={{
borderTopLeftRadius: index === 0 ? undefined : 0,
@@ -756,19 +739,19 @@ function OwnershipFilter() {
return wargaming ? (
<OwnershipFilterInternal />
) : (
<Tooltip content={strings.website.common.tank_search.login}>
<Tooltip tooltip={strings.website.common.tank_search.login}>
<OwnershipFilterInternal />
</Tooltip>
);
}
function OwnershipFilterInternal(props: FlexProps) {
function OwnershipFilterInternal() {
const wargaming = App.use((state) => state.logins.wargaming);
const showOwned = TankFilters.use((state) => state.showOwned);
const showUnowned = TankFilters.use((state) => state.showUnowned);
return (
<Flex {...props}>
<Flex>
<IconButton
style={{
borderTopRightRadius: 0,
@@ -883,7 +866,7 @@ function ConsumablesFilter() {
))}
{consumables.length > MAX_ICONS && (
<Text size="1" ml="1">
<Text size="minor" className={styles["overflow-plus"]}>
{literals(strings.common.units.plus, {
value: consumables.length - MAX_ICONS,
})}
@@ -977,7 +960,7 @@ function ProvisionsFilter() {
))}
{provisions.length > MAX_ICONS && (
<Text size="1" ml="1">
<Text size="minor" className={styles["overflow-plus"]}>
{literals(strings.common.units.plus, {
value: provisions.length - MAX_ICONS,
})}
@@ -1086,7 +1069,7 @@ function GameModeAbilitiesFilter() {
))}
{icons.length > MAX_ICONS && (
<Text size="1" ml="1">
<Text size="minor" className={styles["overflow-plus"]}>
{literals(strings.common.units.plus, {
value: icons.length - MAX_ICONS,
})}
@@ -0,0 +1,28 @@
.tooltip {
position: relative;
.text {
display: none;
position: absolute;
bottom: 100%;
left: 50%;
transform: translateX(-50%);
z-index: 1;
background-color: var(--gray-12);
color: var(--gray-1);
border-radius: var(--space-3);
padding: var(--space-2) var(--space-3);
margin-bottom: var(--space-3);
white-space: nowrap;
}
&:hover {
.text {
display: block;
}
}
}
@@ -0,0 +1,16 @@
import type { ReactNode } from "react";
import styles from "./index.module.css";
interface Props {
children: ReactNode;
tooltip: string;
}
export function Tooltip({ children, tooltip }: Props) {
return (
<div className={styles.tooltip}>
<div className={styles.text}>{tooltip}</div>
{children}
</div>
);
}
@@ -1,7 +1,7 @@
import { PageWrapper } from "../../../../components/PageWrapper";
import { PlayerCountControl } from "../../../../components/Performance/PlayerCountControl";
import { TankTable } from "../../../../components/Performance/Table";
import { FilterControl } from "../../../../components/TankSearch/components/FilterControl";
import { TankSearchFilters } from "../../../../components/TankSearchFilters";
import {
LocaleProvider,
type LocaleAcceptorProps,
@@ -21,7 +21,7 @@ export function Page({ skeleton, locale }: PageProps) {
function Content({ skeleton }: MaybeSkeletonComponentProps) {
return (
<PageWrapper pb="0" px="0" color="jade" maxWidth="100%">
<FilterControl />
<TankSearchFilters />
<PlayerCountControl />
<TankTable skeleton={skeleton} />
@@ -1,5 +1,5 @@
import { PageWrapper } from "../../../../components/PageWrapper";
import { FilterControl } from "../../../../components/TankSearch/components/FilterControl";
import { TankSearchFilters } from "../../../../components/TankSearchFilters";
import { TierListControls } from "../../../../components/TierList/Controls";
import { TierListTable } from "../../../../components/TierList/Table";
import { TierListTiles } from "../../../../components/TierList/Tiles";
@@ -23,7 +23,7 @@ function Content() {
<URLManager />
<TierListControls />
<TierListTable />
<FilterControl />
<TankSearchFilters />
<TierListTiles />
</PageWrapper>
);