DrMint dd3beff508
Added meilisearch (#89)
* Added search on most pages

* Changed material icons to symbols and added wikipage search

* Updated deps

* Changed color of the play button on previewcard overlay

* Updated search params

* Updated deps

* Audit fix

* Removed unused graphql files
2023-01-07 01:59:54 +01:00

116 lines
4.3 KiB
TypeScript

import { MouseEventHandler, useCallback } from "react";
import { MaterialSymbol } from "material-symbols";
import { Link } from "./Link";
import { Ico } from "components/Ico";
import { cIf, cJoin } from "helpers/className";
import { isDefined, isDefinedAndNotEmpty } from "helpers/asserts";
import { TranslatedProps } from "types/TranslatedProps";
import { useSmartLanguage } from "hooks/useSmartLanguage";
/*
* ╭─────────────╮
* ───────────────────────────────────────╯ COMPONENT ╰───────────────────────────────────────────
*/
interface Props {
id?: string;
className?: string;
href?: string;
active?: boolean;
icon?: MaterialSymbol;
text?: string | null | undefined;
alwaysNewTab?: boolean;
onClick?: MouseEventHandler<HTMLDivElement>;
onMouseUp?: MouseEventHandler<HTMLDivElement>;
draggable?: boolean;
badgeNumber?: number;
disabled?: boolean;
size?: "normal" | "small";
}
// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
export const Button = ({
draggable,
id,
onClick,
onMouseUp,
active = false,
className,
icon,
text,
href,
alwaysNewTab = false,
badgeNumber,
disabled,
size = "normal",
}: Props): JSX.Element => (
<Link href={href} alwaysNewTab={alwaysNewTab} disabled={disabled}>
<div className="relative">
<div
draggable={draggable}
id={id}
onClick={(event) => !disabled && onClick?.(event)}
onMouseUp={onMouseUp}
onFocus={(event) => event.target.blur()}
className={cJoin(
`group grid cursor-pointer select-none grid-flow-col place-content-center
place-items-center gap-2 rounded-full border border-dark py-3 px-4
leading-none text-dark transition-all`,
cIf(size === "small", "px-3 py-1 text-xs"),
cIf(active, "!border-black bg-black !text-light drop-shadow-lg shadow-black"),
cIf(
disabled,
"cursor-not-allowed opacity-50 grayscale",
cIf(
!active,
`shadow-shade hover:bg-dark hover:text-light hover:drop-shadow-lg
active:hover:!border-black active:hover:bg-black active:hover:!text-light
active:hover:drop-shadow-lg active:hover:shadow-black`
)
),
className
)}>
{isDefined(badgeNumber) && (
<div
className={cJoin(
`absolute -top-3 -right-2 grid h-8 w-8 place-items-center rounded-full bg-dark
font-bold text-light transition-opacity group-hover:opacity-0`,
cIf(size === "small", "-top-2 -right-2 h-5 w-5")
)}>
<p className="-translate-y-[0.05em]">{badgeNumber}</p>
</div>
)}
{isDefinedAndNotEmpty(icon) && (
<Ico
className="[font-size:150%] [line-height:0.66]"
icon={icon}
isFilled={active}
opticalSize={size === "normal" ? 24 : 20}
weight={size === "normal" ? 500 : 800}
/>
)}
{isDefinedAndNotEmpty(text) && <p className="-translate-y-[0.05em] text-center">{text}</p>}
</div>
</div>
</Link>
);
/*
* ╭──────────────────────╮
* ───────────────────────────────────╯ TRANSLATED VARIANT ╰──────────────────────────────────────
*/
export const TranslatedButton = ({
translations,
fallback,
...otherProps
}: TranslatedProps<Props, "text">): JSX.Element => {
const [selectedTranslation] = useSmartLanguage({
items: translations,
languageExtractor: useCallback((item: { language: string }): string => item.language, []),
});
return <Button text={selectedTranslation?.text ?? fallback.text} {...otherProps} />;
};