mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-23 11:39:50 +02:00
tank search ui rebuilt... somewhat
This commit is contained in:
1 parent
b400ff6d07
commit
1f1c9f26f1
21 files changed
+455
-369
No files matched your search
@@ -1,43 +0,0 @@
|
||||
.tank-search-card {
|
||||
user-select: none;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: var(--space-2);
|
||||
background-position: top left;
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.tank-search-card[data-provide-link='true'] {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.tank-search-card .link {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.tank-search-card .image {
|
||||
width: 100%;
|
||||
height: 8rem;
|
||||
object-position: center right;
|
||||
object-fit: contain;
|
||||
filter: drop-shadow(-1px -1px 4px black);
|
||||
}
|
||||
|
||||
.tank-search-card .class-icon {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
min-width: 1em;
|
||||
min-height: 1em;
|
||||
}
|
||||
|
||||
.tank-search-card .name {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
.image-wrapper {
|
||||
overflow: hidden;
|
||||
|
||||
box-sizing: border-box;
|
||||
|
||||
background-size: auto 100%;
|
||||
background-repeat: no-repeat;
|
||||
|
||||
height: 6rem;
|
||||
}
|
||||
|
||||
.icon {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
}
|
||||
@@ -1,15 +1,15 @@
|
||||
import { alias, TankType, type TankDefinition } from "@blitzkit/core";
|
||||
import { uniq } from "lodash-es";
|
||||
import { forwardRef, type ReactNode } from "react";
|
||||
import { type ReactNode } from "react";
|
||||
import { api } from "../../core/blitzkit/api";
|
||||
import { useLocale } from "../../hooks/useLocale";
|
||||
import { TankopediaPersistent } from "../../stores/tankopediaPersistent";
|
||||
import { classIcons } from "../ClassIcon";
|
||||
import { Flex } from "../Flex";
|
||||
import { LinkI18n } from "../LinkI18n";
|
||||
import { LinkI18nWrapper } from "../LinkI18nWrapper";
|
||||
import { MAX_RECENTLY_VIEWED } from "../TankSearch/constants";
|
||||
import { Text, type TextProps } from "../Text";
|
||||
import "./index.css";
|
||||
import styles from "./index.module.css";
|
||||
|
||||
type TankCardProps = TextProps & {
|
||||
tank: TankDefinition;
|
||||
@@ -20,100 +20,80 @@ type TankCardProps = TextProps & {
|
||||
|
||||
const tankDefinitions = await api.tankDefinitions();
|
||||
|
||||
export const TankCard = forwardRef<HTMLSpanElement, TankCardProps>(
|
||||
(
|
||||
{
|
||||
tank,
|
||||
discriminator,
|
||||
onTankSelect: onSelect,
|
||||
noLink,
|
||||
style,
|
||||
...props
|
||||
}: TankCardProps,
|
||||
ref,
|
||||
) => {
|
||||
const { unwrap, locale } = useLocale();
|
||||
const provideLink = !noLink && onSelect === undefined;
|
||||
export const TankCard = ({
|
||||
tank,
|
||||
discriminator,
|
||||
onTankSelect: onSelect,
|
||||
noLink,
|
||||
style,
|
||||
...props
|
||||
}: TankCardProps) => {
|
||||
const { unwrap, locale } = useLocale();
|
||||
|
||||
const Icon = classIcons[tank.class];
|
||||
const provideLink = !noLink && onSelect === undefined;
|
||||
const name = unwrap(tank.name!);
|
||||
|
||||
return (
|
||||
<Text
|
||||
ref={ref}
|
||||
tabIndex={onSelect ? 0 : undefined}
|
||||
size="2"
|
||||
color={
|
||||
tank.type === TankType.TANK_TYPE_COLLECTOR
|
||||
? "blue"
|
||||
: tank.type === TankType.TANK_TYPE_PREMIUM
|
||||
? "amber"
|
||||
: "gray"
|
||||
}
|
||||
highContrast={tank.type === TankType.TANK_TYPE_RESEARCHABLE}
|
||||
onClick={() => {
|
||||
onSelect?.(tank);
|
||||
TankopediaPersistent.mutate((draft) => {
|
||||
draft.recentlyViewed = uniq([tank.id, ...draft.recentlyViewed])
|
||||
.filter((id) => id in tankDefinitions.tanks)
|
||||
.slice(0, MAX_RECENTLY_VIEWED);
|
||||
});
|
||||
}}
|
||||
className="tank-search-card"
|
||||
data-provide-link={provideLink}
|
||||
const color: TextProps["color"] =
|
||||
tank.type === TankType.TANK_TYPE_COLLECTOR
|
||||
? "blue"
|
||||
: tank.type === TankType.TANK_TYPE_PREMIUM
|
||||
? "amber"
|
||||
: "gray";
|
||||
const lowContrast = tank.type !== TankType.TANK_TYPE_RESEARCHABLE;
|
||||
|
||||
const Icon = classIcons[tank.class];
|
||||
|
||||
const content = (
|
||||
<Flex
|
||||
column
|
||||
gap="3"
|
||||
onClick={() => {
|
||||
onSelect?.(tank);
|
||||
TankopediaPersistent.mutate((draft) => {
|
||||
draft.recentlyViewed = uniq([tank.id, ...draft.recentlyViewed])
|
||||
.filter((id) => id in tankDefinitions.tanks)
|
||||
.slice(0, MAX_RECENTLY_VIEWED);
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Flex
|
||||
justify="end"
|
||||
className={styles["image-wrapper"]}
|
||||
style={{
|
||||
backgroundImage: `url(${alias(
|
||||
"api",
|
||||
`/flags/scratched/${tank.nation}.webp`,
|
||||
)})`,
|
||||
...style,
|
||||
}}
|
||||
{...props}
|
||||
>
|
||||
<LinkI18n
|
||||
locale={locale}
|
||||
className="link"
|
||||
underline="hover"
|
||||
href={provideLink ? `/tanks/${tank.slug}` : "#"}
|
||||
onClick={(event) => {
|
||||
if (!provideLink) event.preventDefault();
|
||||
}}
|
||||
>
|
||||
<img
|
||||
alt={unwrap(tank.name!)}
|
||||
src={alias("api", `/tanks/${tank.id}/icons/big.webp`)}
|
||||
className="image"
|
||||
draggable={false}
|
||||
/>
|
||||
<img
|
||||
alt={name}
|
||||
src={alias("api", `/tanks/${tank.id}/icons/big.webp`)}
|
||||
/>
|
||||
</Flex>
|
||||
|
||||
<Flex
|
||||
justify="center"
|
||||
gap="1"
|
||||
align="center"
|
||||
overflow="hidden"
|
||||
width="100%"
|
||||
mt="1"
|
||||
>
|
||||
<Icon className="class-icon" />
|
||||
<Text align="center" className="name">
|
||||
{unwrap(tank.name!)}
|
||||
</Text>
|
||||
</Flex>
|
||||
|
||||
{discriminator && (
|
||||
<Text
|
||||
color="gray"
|
||||
align="center"
|
||||
style={{
|
||||
whiteSpace: "nowrap",
|
||||
overflow: "hidden",
|
||||
textOverflow: "ellipsis",
|
||||
}}
|
||||
>
|
||||
{discriminator}
|
||||
</Text>
|
||||
)}
|
||||
</LinkI18n>
|
||||
<Text color={color} lowContrast={lowContrast}>
|
||||
<Flex align="center" gap="2" justify="center">
|
||||
<Icon className={styles.icon} />
|
||||
{name}
|
||||
</Flex>
|
||||
</Text>
|
||||
|
||||
{discriminator && (
|
||||
<Text lowContrast align="center">
|
||||
{discriminator}
|
||||
</Text>
|
||||
)}
|
||||
</Flex>
|
||||
);
|
||||
|
||||
if (provideLink) {
|
||||
return (
|
||||
<LinkI18nWrapper locale={locale} href={`/tanks/${tank.slug}`}>
|
||||
{content}
|
||||
</LinkI18nWrapper>
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return content;
|
||||
};
|
||||
Reference in new issue
Block a user