mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-04-24 15:08:44 -05:00
Refactor Button to SendouButton (#2367)
* initial * done * import ordering
This commit is contained in:
parent
25d3aff133
commit
accbaf40db
11
.github/copilot-instructions.md
vendored
11
.github/copilot-instructions.md
vendored
|
|
@ -1,7 +1,11 @@
|
|||
## General
|
||||
|
||||
- only rarely use comments, prefer descriptive variable and function names
|
||||
- if you encounter an existing TODO comment assume it is there for a reason and do not remove it
|
||||
- for new code only rarely use comments, prefer descriptive variable and function names
|
||||
|
||||
## Commands
|
||||
|
||||
- `npm run typecheck` runs TypeScript type checking
|
||||
- `npm run biome:fix` runs Biome code formatter and linter
|
||||
|
||||
## Typescript
|
||||
|
||||
|
|
@ -27,7 +31,7 @@
|
|||
## Styling
|
||||
|
||||
- use CSS modules
|
||||
- one file containing React code should have a matching CSS module file e.g. `Component.tsx` should have a matching `Component.module.css`
|
||||
- one file containing React code should have a matching CSS module file e.g. `Component.tsx` should have a file with the same root name i.e. `Component.module.css`
|
||||
- clsx library is used for conditional class names
|
||||
- prefer using [CSS variables](../app/styles/vars.css) for theming
|
||||
|
||||
|
|
@ -35,4 +39,3 @@
|
|||
|
||||
- database is Sqlite3 used with the Kysely library
|
||||
- database code should only be written in Repository files
|
||||
- refer to the [database schema](../app/db/tables.ts) when writing queries
|
||||
|
|
|
|||
|
|
@ -3,8 +3,7 @@ import type { LinkProps } from "@remix-run/react";
|
|||
import clsx from "clsx";
|
||||
import * as React from "react";
|
||||
|
||||
export interface ButtonProps
|
||||
extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
||||
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
||||
variant?:
|
||||
| "primary"
|
||||
| "success"
|
||||
|
|
@ -22,50 +21,6 @@ export interface ButtonProps
|
|||
_ref?: React.LegacyRef<HTMLButtonElement> | React.ForwardedRef<unknown>;
|
||||
}
|
||||
|
||||
export function Button(props: ButtonProps) {
|
||||
const {
|
||||
variant,
|
||||
loading,
|
||||
children,
|
||||
loadingText,
|
||||
size,
|
||||
className,
|
||||
icon,
|
||||
type = "button",
|
||||
testId,
|
||||
_ref,
|
||||
...rest
|
||||
} = props;
|
||||
return (
|
||||
<button
|
||||
className={clsx(
|
||||
"button",
|
||||
variant,
|
||||
{
|
||||
"disabled-opaque": props.disabled,
|
||||
loading,
|
||||
tiny: size === "tiny",
|
||||
big: size === "big",
|
||||
miniscule: size === "miniscule",
|
||||
},
|
||||
className,
|
||||
)}
|
||||
disabled={props.disabled || loading}
|
||||
type={type}
|
||||
data-testid={testId}
|
||||
ref={props._ref as React.LegacyRef<HTMLButtonElement>}
|
||||
{...rest}
|
||||
>
|
||||
{icon &&
|
||||
React.cloneElement(icon, {
|
||||
className: clsx("button-icon", { lonely: !children }),
|
||||
title: rest.title,
|
||||
})}
|
||||
{loading && loadingText ? loadingText : children}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
type LinkButtonProps = Pick<
|
||||
ButtonProps,
|
||||
"variant" | "children" | "className" | "size" | "testId" | "icon"
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import {
|
|||
} from "@remix-run/react";
|
||||
import * as React from "react";
|
||||
import { useCopyToClipboard, useLocation } from "react-use";
|
||||
import { Button } from "~/components/Button";
|
||||
import { useUser } from "~/features/auth/core/user";
|
||||
import {
|
||||
ERROR_GIRL_IMAGE_PATH,
|
||||
|
|
@ -14,6 +13,7 @@ import {
|
|||
} from "~/utils/urls";
|
||||
import { Image } from "./Image";
|
||||
import { Main } from "./Main";
|
||||
import { SendouButton } from "./elements/Button";
|
||||
|
||||
export function Catcher() {
|
||||
const error = useRouteError();
|
||||
|
|
@ -56,9 +56,9 @@ export function Catcher() {
|
|||
<>
|
||||
<div className="mt-4 stack sm items-center">
|
||||
<textarea readOnly defaultValue={errorText} />
|
||||
<Button onClick={() => copyToClipboard(errorText)}>
|
||||
<SendouButton onPress={() => copyToClipboard(errorText)}>
|
||||
Copy to clipboard
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</div>
|
||||
</>
|
||||
) : null}
|
||||
|
|
@ -77,9 +77,9 @@ export function Catcher() {
|
|||
<form action={LOG_IN_URL} method="post">
|
||||
<p className="button-text-paragraph">
|
||||
You should try{" "}
|
||||
<Button type="submit" variant="minimal">
|
||||
<SendouButton type="submit" variant="minimal">
|
||||
logging in
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</p>
|
||||
</form>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ import * as React from "react";
|
|||
import { useTranslation } from "react-i18next";
|
||||
import { useDebounce } from "react-use";
|
||||
import { CUSTOM_CSS_VAR_COLORS } from "~/features/user-page/user-page-constants";
|
||||
import { Button } from "./Button";
|
||||
import { InfoPopover } from "./InfoPopover";
|
||||
import { Label } from "./Label";
|
||||
import { SendouButton } from "./elements/Button";
|
||||
import { AlertIcon } from "./icons/Alert";
|
||||
import { CheckmarkIcon } from "./icons/Checkmark";
|
||||
|
||||
|
|
@ -104,10 +104,10 @@ export function CustomizedColorsInput({
|
|||
}}
|
||||
data-testid={`color-input-${cssVar}`}
|
||||
/>
|
||||
<Button
|
||||
size="tiny"
|
||||
<SendouButton
|
||||
size="small"
|
||||
variant="minimal-destructive"
|
||||
onClick={() => {
|
||||
onPress={() => {
|
||||
const newColors: Record<string, string | undefined> = {
|
||||
...colors,
|
||||
};
|
||||
|
|
@ -123,7 +123,7 @@ export function CustomizedColorsInput({
|
|||
}}
|
||||
>
|
||||
{t("actions.reset")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</React.Fragment>
|
||||
);
|
||||
})}
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@ import { type FetcherWithComponents, useFetcher } from "@remix-run/react";
|
|||
import * as React from "react";
|
||||
import { createPortal } from "react-dom";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import type { SendouButtonProps } from "~/components/elements/Button";
|
||||
import { SendouDialog } from "~/components/elements/Dialog";
|
||||
import { useIsMounted } from "~/hooks/useIsMounted";
|
||||
import invariant from "~/utils/invariant";
|
||||
import type { ButtonProps } from "./Button";
|
||||
import { SubmitButton } from "./SubmitButton";
|
||||
|
||||
export function FormWithConfirm({
|
||||
|
|
@ -27,7 +27,7 @@ export function FormWithConfirm({
|
|||
submitButtonText?: string;
|
||||
action?: string;
|
||||
submitButtonTestId?: string;
|
||||
submitButtonVariant?: ButtonProps["variant"];
|
||||
submitButtonVariant?: SendouButtonProps["variant"];
|
||||
fetcher?: FetcherWithComponents<any>;
|
||||
}) {
|
||||
const componentsFetcher = useFetcher();
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import clsx from "clsx";
|
||||
import * as React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Button } from "~/components/Button";
|
||||
import { Image } from "~/components/Image";
|
||||
import type { Tables } from "~/db/tables";
|
||||
import type { SerializedMapPoolEvent } from "~/features/calendar/routes/map-pool-events";
|
||||
|
|
@ -14,6 +13,7 @@ import { split, startsWith } from "~/utils/strings";
|
|||
import { assertType } from "~/utils/types";
|
||||
import { modeImageUrl, stageImageUrl } from "~/utils/urls";
|
||||
import { MapPoolEventsCombobox } from "./Combobox";
|
||||
import { SendouButton } from "./elements/Button";
|
||||
import { ArrowLongLeftIcon } from "./icons/ArrowLongLeft";
|
||||
import { CrossIcon } from "./icons/Cross";
|
||||
|
||||
|
|
@ -120,18 +120,18 @@ export function MapPoolSelector({
|
|||
{Boolean(handleRemoval || allowBulkEdit) && (
|
||||
<div className="stack horizontal sm justify-end">
|
||||
{handleRemoval && (
|
||||
<Button variant="minimal" onClick={handleRemoval}>
|
||||
<SendouButton variant="minimal" onPress={handleRemoval}>
|
||||
{t("actions.remove")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
)}
|
||||
{allowBulkEdit && (
|
||||
<Button
|
||||
<SendouButton
|
||||
variant="minimal-destructive"
|
||||
disabled={mapPool.isEmpty()}
|
||||
onClick={handleClear}
|
||||
isDisabled={mapPool.isEmpty()}
|
||||
onPress={handleClear}
|
||||
>
|
||||
{t("actions.clear")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -321,24 +321,26 @@ export function MapPoolStages({
|
|||
{!isPresentational &&
|
||||
allowBulkEdit &&
|
||||
(mapPool.hasStage(stageId) ? (
|
||||
<Button
|
||||
<SendouButton
|
||||
key="clear"
|
||||
onClick={() => handleStageClear(stageId)}
|
||||
icon={<CrossIcon />}
|
||||
onPress={() => handleStageClear(stageId)}
|
||||
icon={<CrossIcon title={t("common:actions.remove")} />}
|
||||
variant="minimal"
|
||||
aria-label={t("common:actions.remove")}
|
||||
title={t("common:actions.remove")}
|
||||
size="tiny"
|
||||
size="small"
|
||||
/>
|
||||
) : (
|
||||
<Button
|
||||
<SendouButton
|
||||
key="select-all"
|
||||
onClick={() => handleStageAdd(stageId)}
|
||||
icon={<ArrowLongLeftIcon />}
|
||||
onPress={() => handleStageAdd(stageId)}
|
||||
icon={
|
||||
<ArrowLongLeftIcon
|
||||
title={t("common:actions.selectAll")}
|
||||
/>
|
||||
}
|
||||
variant="minimal"
|
||||
aria-label={t("common:actions.selectAll")}
|
||||
title={t("common:actions.selectAll")}
|
||||
size="tiny"
|
||||
size="small"
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import clsx from "clsx";
|
||||
import { Button } from "~/components/Button";
|
||||
import { SendouButton } from "~/components/elements/Button";
|
||||
import { ArrowLeftIcon } from "~/components/icons/ArrowLeft";
|
||||
import { ArrowRightIcon } from "~/components/icons/ArrowRight";
|
||||
import { nullFilledArray } from "~/utils/arrays";
|
||||
|
|
@ -19,12 +19,12 @@ export function Pagination({
|
|||
}) {
|
||||
return (
|
||||
<div className="pagination__container">
|
||||
<Button
|
||||
<SendouButton
|
||||
icon={<ArrowLeftIcon />}
|
||||
variant="outlined"
|
||||
className="fix-rtl"
|
||||
disabled={currentPage === 1}
|
||||
onClick={previousPage}
|
||||
isDisabled={currentPage === 1}
|
||||
onPress={previousPage}
|
||||
aria-label="Previous page"
|
||||
/>
|
||||
<div className="pagination__dots">
|
||||
|
|
@ -41,12 +41,12 @@ export function Pagination({
|
|||
<div className="pagination__page-count">
|
||||
{currentPage}/{pagesCount}
|
||||
</div>
|
||||
<Button
|
||||
<SendouButton
|
||||
icon={<ArrowRightIcon />}
|
||||
variant="outlined"
|
||||
className="fix-rtl"
|
||||
disabled={currentPage === pagesCount}
|
||||
onClick={nextPage}
|
||||
isDisabled={currentPage === pagesCount}
|
||||
onPress={nextPage}
|
||||
aria-label="Next page"
|
||||
/>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
import { type FetcherWithComponents, useNavigation } from "@remix-run/react";
|
||||
import { Button, type ButtonProps } from "./Button";
|
||||
import { SendouButton, type SendouButtonProps } from "./elements/Button";
|
||||
|
||||
interface SubmitButtonProps extends ButtonProps {
|
||||
interface SubmitButtonProps extends SendouButtonProps {
|
||||
/** If the page has multiple forms you can pass in fetcher.state to differentiate when this SubmitButton should be in submitting state */
|
||||
state?: FetcherWithComponents<any>["state"];
|
||||
_action?: string;
|
||||
testId?: string;
|
||||
}
|
||||
|
||||
export function SubmitButton({
|
||||
|
|
@ -33,15 +34,15 @@ export function SubmitButton({
|
|||
};
|
||||
|
||||
return (
|
||||
<Button
|
||||
<SendouButton
|
||||
{...rest}
|
||||
disabled={rest.disabled || isSubmitting}
|
||||
isDisabled={rest.isDisabled || isSubmitting}
|
||||
type="submit"
|
||||
name={name()}
|
||||
value={value()}
|
||||
data-testid={testId ?? "submit-button"}
|
||||
>
|
||||
{children}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { useTranslation } from "react-i18next";
|
||||
import { Button } from "../Button";
|
||||
import { SendouButton } from "../elements/Button";
|
||||
import { PlusIcon } from "../icons/Plus";
|
||||
|
||||
export function AddFieldButton({
|
||||
|
|
@ -10,16 +10,16 @@ export function AddFieldButton({
|
|||
const { t } = useTranslation(["common"]);
|
||||
|
||||
return (
|
||||
<Button
|
||||
<SendouButton
|
||||
icon={<PlusIcon />}
|
||||
aria-label="Add form field"
|
||||
size="tiny"
|
||||
size="small"
|
||||
variant="minimal"
|
||||
onClick={onClick}
|
||||
onPress={onClick}
|
||||
className="self-start"
|
||||
testId="add-field-button"
|
||||
data-testid="add-field-button"
|
||||
>
|
||||
{t("common:actions.add")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
import { Button } from "../Button";
|
||||
import { SendouButton } from "../elements/Button";
|
||||
import { TrashIcon } from "../icons/Trash";
|
||||
|
||||
export function RemoveFieldButton({ onClick }: { onClick: () => void }) {
|
||||
return (
|
||||
<Button
|
||||
<SendouButton
|
||||
icon={<TrashIcon />}
|
||||
aria-label="Remove form field"
|
||||
size="tiny"
|
||||
size="small"
|
||||
variant="minimal-destructive"
|
||||
onClick={onClick}
|
||||
onPress={onClick}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
export function ArrowLongLeftIcon({ className }: { className?: string }) {
|
||||
export function ArrowLongLeftIcon({
|
||||
className,
|
||||
title,
|
||||
}: { className?: string; title?: string }) {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
|
|
@ -8,7 +11,7 @@ export function ArrowLongLeftIcon({ className }: { className?: string }) {
|
|||
stroke="currentColor"
|
||||
className={className}
|
||||
>
|
||||
<title>Arrow Long Left Icon</title>
|
||||
<title>{title ?? "Arrow Long Left Icon"}</title>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
|
|
|
|||
|
|
@ -2,10 +2,12 @@ export function CheckmarkIcon({
|
|||
className,
|
||||
testId,
|
||||
onClick,
|
||||
title,
|
||||
}: {
|
||||
className?: string;
|
||||
testId?: string;
|
||||
onClick?: () => void;
|
||||
title?: string;
|
||||
}) {
|
||||
return (
|
||||
<svg
|
||||
|
|
@ -16,7 +18,7 @@ export function CheckmarkIcon({
|
|||
data-testid={testId}
|
||||
onClick={onClick}
|
||||
>
|
||||
<title>Checkmark Icon</title>
|
||||
<title>{title ?? "Checkmark Icon"}</title>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
export function CrossIcon({ className }: { className?: string }) {
|
||||
export function CrossIcon({
|
||||
className,
|
||||
title,
|
||||
}: { className?: string; title?: string }) {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
|
|
@ -6,7 +9,7 @@ export function CrossIcon({ className }: { className?: string }) {
|
|||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
>
|
||||
<title>Cross Icon</title>
|
||||
<title>{title ?? "Cross Icon"}</title>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import { Button } from "react-aria-components";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useUser } from "~/features/auth/core/user";
|
||||
import { FF_SCRIMS_ENABLED } from "~/features/scrims/scrims-constants";
|
||||
|
|
@ -15,6 +14,7 @@ import {
|
|||
plusSuggestionsNewPage,
|
||||
userNewBuildPage,
|
||||
} from "~/utils/urls";
|
||||
import { SendouButton } from "../elements/Button";
|
||||
import {
|
||||
SendouMenu,
|
||||
SendouMenuItem,
|
||||
|
|
@ -100,12 +100,12 @@ export function AnythingAdder() {
|
|||
return (
|
||||
<SendouMenu
|
||||
trigger={
|
||||
<Button
|
||||
<SendouButton
|
||||
className="layout__header__button"
|
||||
data-testid="anything-adder-menu-button"
|
||||
>
|
||||
<PlusIcon className="layout__header__button__icon" />
|
||||
</Button>
|
||||
</SendouButton>
|
||||
}
|
||||
>
|
||||
{items.map((item) => (
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ import { navItems } from "~/components/layout/nav-items";
|
|||
import { useUser } from "~/features/auth/core/user";
|
||||
import { LOG_OUT_URL, navIconUrl, userPage } from "~/utils/urls";
|
||||
import { Avatar } from "../Avatar";
|
||||
import { Button } from "../Button";
|
||||
import { Image } from "../Image";
|
||||
import { SendouButton } from "../elements/Button";
|
||||
import { CrossIcon } from "../icons/Cross";
|
||||
import { LogOutIcon } from "../icons/LogOut";
|
||||
import { LogInButtonContainer } from "./LogInButtonContainer";
|
||||
|
|
@ -29,11 +29,11 @@ export function NavDialog({
|
|||
aria-label="Site navigation"
|
||||
isFullScreen
|
||||
>
|
||||
<Button
|
||||
<SendouButton
|
||||
icon={<CrossIcon />}
|
||||
variant="minimal-destructive"
|
||||
className="layout__overlay-nav__close-button"
|
||||
onClick={close}
|
||||
onPress={close}
|
||||
aria-label="Close navigation dialog"
|
||||
/>
|
||||
<div className="layout__overlay-nav__nav-items-container">
|
||||
|
|
@ -61,14 +61,14 @@ export function NavDialog({
|
|||
{user ? (
|
||||
<div className="mt-6 stack items-center">
|
||||
<form method="post" action={LOG_OUT_URL}>
|
||||
<Button
|
||||
size="tiny"
|
||||
<SendouButton
|
||||
size="small"
|
||||
variant="outlined"
|
||||
icon={<LogOutIcon />}
|
||||
type="submit"
|
||||
>
|
||||
{t("common:header.logout")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</form>
|
||||
</div>
|
||||
) : null}
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ import * as React from "react";
|
|||
import { useTranslation } from "react-i18next";
|
||||
import type { RootLoaderData } from "~/root";
|
||||
import type { Breadcrumb, SendouRouteHandle } from "~/utils/remix.server";
|
||||
import { Button } from "../Button";
|
||||
import { Image } from "../Image";
|
||||
import { SendouButton } from "../elements/Button";
|
||||
import { HamburgerIcon } from "../icons/Hamburger";
|
||||
import { Footer } from "./Footer";
|
||||
import { NavDialog } from "./NavDialog";
|
||||
|
|
@ -54,11 +54,11 @@ export function Layout({
|
|||
<div className="layout__container">
|
||||
<NavDialog isOpen={navDialogOpen} close={() => setNavDialogOpen(false)} />
|
||||
{isFrontPage ? (
|
||||
<Button
|
||||
<SendouButton
|
||||
icon={<HamburgerIcon />}
|
||||
className="layout__hamburger-fab"
|
||||
variant="outlined"
|
||||
onClick={() => setNavDialogOpen(true)}
|
||||
onPress={() => setNavDialogOpen(true)}
|
||||
/>
|
||||
) : null}
|
||||
<header className="layout__header layout__item_size">
|
||||
|
|
|
|||
|
|
@ -9,12 +9,12 @@ import {
|
|||
} from "@remix-run/react";
|
||||
import * as React from "react";
|
||||
import { Avatar } from "~/components/Avatar";
|
||||
import { Button } from "~/components/Button";
|
||||
import { Catcher } from "~/components/Catcher";
|
||||
import { Input } from "~/components/Input";
|
||||
import { Main } from "~/components/Main";
|
||||
import { NewTabs } from "~/components/NewTabs";
|
||||
import { SubmitButton } from "~/components/SubmitButton";
|
||||
import { SendouButton } from "~/components/elements/Button";
|
||||
import { UserSearch } from "~/components/elements/UserSearch";
|
||||
import { SearchIcon } from "~/components/icons/Search";
|
||||
import { FRIEND_CODE_REGEXP_PATTERN } from "~/features/sendouq/q-constants";
|
||||
|
|
@ -149,13 +149,13 @@ function Impersonate() {
|
|||
onChange={(newUser) => setUserId(newUser.id)}
|
||||
/>
|
||||
<div className="stack horizontal md">
|
||||
<Button type="submit" disabled={!userId}>
|
||||
<SendouButton type="submit" isDisabled={!userId}>
|
||||
Go
|
||||
</Button>
|
||||
</SendouButton>
|
||||
{isImpersonating ? (
|
||||
<Button type="submit" formAction={STOP_IMPERSONATING_URL}>
|
||||
<SendouButton type="submit" formAction={STOP_IMPERSONATING_URL}>
|
||||
Stop impersonating
|
||||
</Button>
|
||||
</SendouButton>
|
||||
) : null}
|
||||
</div>
|
||||
</Form>
|
||||
|
|
@ -193,7 +193,7 @@ function MigrateUser() {
|
|||
<div className="stack horizontal md">
|
||||
<SubmitButton
|
||||
type="submit"
|
||||
disabled={!oldUserId || !newUserId || navigation.state !== "idle"}
|
||||
isDisabled={!oldUserId || !newUserId || navigation.state !== "idle"}
|
||||
_action="MIGRATE"
|
||||
state={fetcher.state}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import clsx from "clsx";
|
|||
import * as React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Avatar } from "~/components/Avatar";
|
||||
import { Button, LinkButton } from "~/components/Button";
|
||||
import { LinkButton } from "~/components/Button";
|
||||
import { FormWithConfirm } from "~/components/FormWithConfirm";
|
||||
import { Pagination } from "~/components/Pagination";
|
||||
import { SendouButton } from "~/components/elements/Button";
|
||||
|
|
@ -204,7 +204,11 @@ function ImagePreview({
|
|||
["_action", "DELETE_ART"],
|
||||
]}
|
||||
>
|
||||
<Button icon={<TrashIcon />} variant="destructive" size="tiny" />
|
||||
<SendouButton
|
||||
icon={<TrashIcon />}
|
||||
variant="destructive"
|
||||
size="small"
|
||||
/>
|
||||
</FormWithConfirm>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -242,7 +246,11 @@ function ImagePreview({
|
|||
]}
|
||||
submitButtonText={t("common:actions.remove")}
|
||||
>
|
||||
<Button icon={<UnlinkIcon />} variant="destructive" size="tiny" />
|
||||
<SendouButton
|
||||
icon={<UnlinkIcon />}
|
||||
variant="destructive"
|
||||
size="small"
|
||||
/>
|
||||
</FormWithConfirm>
|
||||
) : null}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -6,11 +6,11 @@ import * as React from "react";
|
|||
import { useTranslation } from "react-i18next";
|
||||
import { useFetcher } from "react-router-dom";
|
||||
import { Alert } from "~/components/Alert";
|
||||
import { Button } from "~/components/Button";
|
||||
import { Combobox } from "~/components/Combobox";
|
||||
import { FormMessage } from "~/components/FormMessage";
|
||||
import { Label } from "~/components/Label";
|
||||
import { Main } from "~/components/Main";
|
||||
import { SendouButton } from "~/components/elements/Button";
|
||||
import { SendouSwitch } from "~/components/elements/Switch";
|
||||
import { UserSearch } from "~/components/elements/UserSearch";
|
||||
import { CrossIcon } from "~/components/icons/Cross";
|
||||
|
|
@ -90,9 +90,12 @@ export default function NewArtPage() {
|
|||
<LinkedUsers />
|
||||
{data.art ? <ShowcaseToggle /> : null}
|
||||
<div>
|
||||
<Button onClick={handleSubmit} disabled={submitButtonDisabled()}>
|
||||
<SendouButton
|
||||
onPress={handleSubmit}
|
||||
isDisabled={submitButtonDisabled()}
|
||||
>
|
||||
{t("common:actions.save")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</div>
|
||||
</Form>
|
||||
</Main>
|
||||
|
|
@ -243,16 +246,19 @@ function Tags() {
|
|||
<input type="hidden" name="tags" value={JSON.stringify(tags)} />
|
||||
{creationMode ? (
|
||||
<div className="art__creation-mode-switcher-container">
|
||||
<Button variant="minimal" onClick={() => setCreationMode(false)}>
|
||||
<SendouButton
|
||||
variant="minimal"
|
||||
onPress={() => setCreationMode(false)}
|
||||
>
|
||||
{t("art:forms.tags.selectFromExisting")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</div>
|
||||
) : (
|
||||
<div className="stack horizontal sm text-xs text-lighter art__creation-mode-switcher-container">
|
||||
{t("art:forms.tags.cantFindExisting")}{" "}
|
||||
<Button variant="minimal" onClick={() => setCreationMode(true)}>
|
||||
<SendouButton variant="minimal" onPress={() => setCreationMode(true)}>
|
||||
{t("art:forms.tags.addNew")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</div>
|
||||
)}
|
||||
{tags.length >= ART.TAGS_MAX_LENGTH ? (
|
||||
|
|
@ -272,9 +278,13 @@ function Tags() {
|
|||
}
|
||||
}}
|
||||
/>
|
||||
<Button size="tiny" variant="outlined" onClick={handleAddNewTag}>
|
||||
<SendouButton
|
||||
size="small"
|
||||
variant="outlined"
|
||||
onPress={handleAddNewTag}
|
||||
>
|
||||
{t("common:actions.add")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</div>
|
||||
) : (
|
||||
<Combobox
|
||||
|
|
@ -301,12 +311,12 @@ function Tags() {
|
|||
return (
|
||||
<div key={t.name} className="stack horizontal">
|
||||
{t.name}{" "}
|
||||
<Button
|
||||
<SendouButton
|
||||
icon={<CrossIcon />}
|
||||
size="tiny"
|
||||
size="small"
|
||||
variant="minimal-destructive"
|
||||
className="art__delete-tag-button"
|
||||
onClick={() => {
|
||||
onPress={() => {
|
||||
setTags(tags.filter((tag) => tag.name !== t.name));
|
||||
}}
|
||||
/>
|
||||
|
|
@ -353,10 +363,10 @@ function LinkedUsers() {
|
|||
initialUserId={userId}
|
||||
/>
|
||||
{users.length > 1 || users[0].userId ? (
|
||||
<Button
|
||||
size="tiny"
|
||||
<SendouButton
|
||||
size="small"
|
||||
variant="minimal-destructive"
|
||||
onClick={() => {
|
||||
onPress={() => {
|
||||
if (users.length === 1) {
|
||||
setUsers([{ inputId: nanoid() }]);
|
||||
} else {
|
||||
|
|
@ -369,15 +379,15 @@ function LinkedUsers() {
|
|||
</div>
|
||||
);
|
||||
})}
|
||||
<Button
|
||||
size="tiny"
|
||||
onClick={() => setUsers([...users, { inputId: nanoid() }])}
|
||||
disabled={users.length >= ART.LINKED_USERS_MAX_LENGTH}
|
||||
<SendouButton
|
||||
size="small"
|
||||
onPress={() => setUsers([...users, { inputId: nanoid() }])}
|
||||
isDisabled={users.length >= ART.LINKED_USERS_MAX_LENGTH}
|
||||
className="my-3"
|
||||
variant="outlined"
|
||||
>
|
||||
{t("art:forms.linkedUsers.anotherOne")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
<FormMessage type="info">{t("art:forms.linkedUsers.info")}</FormMessage>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@ import type { MetaFunction, SerializeFrom } from "@remix-run/node";
|
|||
import type { ShouldRevalidateFunction } from "@remix-run/react";
|
||||
import { useLoaderData, useSearchParams } from "@remix-run/react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Button } from "~/components/Button";
|
||||
import { Combobox } from "~/components/Combobox";
|
||||
import { Label } from "~/components/Label";
|
||||
import { Main } from "~/components/Main";
|
||||
import { SendouButton } from "~/components/elements/Button";
|
||||
import { SendouSwitch } from "~/components/elements/Switch";
|
||||
import { CrossIcon } from "~/components/icons/Cross";
|
||||
import type { SendouRouteHandle } from "~/utils/remix.server";
|
||||
|
|
@ -107,19 +107,20 @@ export default function ArtPage() {
|
|||
{filteredTag ? (
|
||||
<div className="text-xs text-lighter stack md horizontal items-center">
|
||||
{t("art:filteringByTag", { tag: filteredTag })}
|
||||
<Button
|
||||
size="tiny"
|
||||
<SendouButton
|
||||
size="small"
|
||||
variant="minimal-destructive"
|
||||
icon={<CrossIcon />}
|
||||
onClick={() => {
|
||||
onPress={() => {
|
||||
setSearchParams((prev) => {
|
||||
prev.delete(FILTERED_TAG_KEY_SEARCH_PARAM_KEY);
|
||||
return prev;
|
||||
});
|
||||
}}
|
||||
data-testid="clear-filter-button"
|
||||
>
|
||||
{t("common:actions.clear")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</div>
|
||||
) : null}
|
||||
<ArtGrid arts={arts} />
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ function JoinForm() {
|
|||
})}
|
||||
</Label>
|
||||
<SubmitButton
|
||||
size="tiny"
|
||||
size="small"
|
||||
_action="JOIN_ASSOCIATION"
|
||||
state={fetcher.state}
|
||||
>
|
||||
|
|
@ -196,7 +196,7 @@ function AssociationInviteCodeActions({
|
|||
<input type="hidden" name="associationId" value={associationId} />
|
||||
<SubmitButton
|
||||
variant="minimal-destructive"
|
||||
size="tiny"
|
||||
size="small"
|
||||
className="mt-4"
|
||||
_action="REFRESH_INVITE_CODE"
|
||||
state={fetcher.state}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import clsx from "clsx";
|
|||
import * as React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Badge } from "~/components/Badge";
|
||||
import { Button } from "~/components/Button";
|
||||
import { SendouButton } from "~/components/elements/Button";
|
||||
import { TrashIcon } from "~/components/icons/Trash";
|
||||
import type { Tables } from "~/db/tables";
|
||||
|
|
@ -96,10 +95,10 @@ export function BadgeDisplay({
|
|||
<div className={styles.badgeExplanation}>
|
||||
{badgeExplanationText(t, bigBadge)}
|
||||
{onChange ? (
|
||||
<Button
|
||||
<SendouButton
|
||||
icon={<TrashIcon />}
|
||||
variant="minimal-destructive"
|
||||
onClick={() =>
|
||||
onPress={() =>
|
||||
onChange(
|
||||
badges.filter((b) => b.id !== bigBadge.id).map((b) => b.id),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { Form, useMatches, useOutletContext } from "@remix-run/react";
|
||||
import * as React from "react";
|
||||
import { Button } from "~/components/Button";
|
||||
import { Divider } from "~/components/Divider";
|
||||
import { SendouButton } from "~/components/elements/Button";
|
||||
import { SendouDialog } from "~/components/elements/Dialog";
|
||||
import { UserSearch } from "~/components/elements/UserSearch";
|
||||
import { TrashIcon } from "~/components/icons/Trash";
|
||||
|
|
@ -73,11 +73,11 @@ function Managers({ data }: { data: BadgeDetailsLoaderData }) {
|
|||
{managers.map((manager) => (
|
||||
<li key={manager.id}>
|
||||
{manager.username}
|
||||
<Button
|
||||
<SendouButton
|
||||
icon={<TrashIcon />}
|
||||
variant="minimal-destructive"
|
||||
aria-label="Delete badge manager"
|
||||
onClick={() =>
|
||||
onPress={() =>
|
||||
setManagers(managers.filter((m) => m.id !== manager.id))
|
||||
}
|
||||
/>
|
||||
|
|
@ -91,14 +91,14 @@ function Managers({ data }: { data: BadgeDetailsLoaderData }) {
|
|||
value={JSON.stringify(managers.map((m) => m.id))}
|
||||
/>
|
||||
<div>
|
||||
<Button
|
||||
<SendouButton
|
||||
type="submit"
|
||||
disabled={amountOfChanges === 0}
|
||||
isDisabled={amountOfChanges === 0}
|
||||
name="_action"
|
||||
value="MANAGERS"
|
||||
>
|
||||
{submitButtonText(amountOfChanges)}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
@ -193,14 +193,14 @@ function Owners({ data }: { data: BadgeDetailsLoaderData }) {
|
|||
value={JSON.stringify(countArrayToDuplicatedIdsArray(owners))}
|
||||
/>
|
||||
<div>
|
||||
<Button
|
||||
<SendouButton
|
||||
type="submit"
|
||||
disabled={ownerDifferences.length === 0}
|
||||
isDisabled={ownerDifferences.length === 0}
|
||||
name="_action"
|
||||
value="OWNERS"
|
||||
>
|
||||
Submit
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { useTranslation } from "react-i18next";
|
||||
import { Ability } from "~/components/Ability";
|
||||
import { Button } from "~/components/Button";
|
||||
import { ModeImage } from "~/components/Image";
|
||||
import { SendouButton } from "~/components/elements/Button";
|
||||
import { CrossIcon } from "~/components/icons/Cross";
|
||||
import { possibleApValues } from "~/features/build-analyzer";
|
||||
import { abilities } from "~/modules/in-game-lists/abilities";
|
||||
|
|
@ -40,13 +40,13 @@ export function FilterSection({
|
|||
{nthOfSame > 1 ? nthOfSame : ""}
|
||||
</div>
|
||||
<div>
|
||||
<Button
|
||||
<SendouButton
|
||||
icon={<CrossIcon />}
|
||||
size="tiny"
|
||||
size="small"
|
||||
variant="minimal-destructive"
|
||||
onClick={remove}
|
||||
onPress={remove}
|
||||
aria-label="Delete filter"
|
||||
testId="delete-filter-button"
|
||||
data-testid="delete-filter-button"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import { nanoid } from "nanoid";
|
||||
import * as React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Button } from "~/components/Button";
|
||||
import { DateInput } from "~/components/DateInput";
|
||||
import { FormMessage } from "~/components/FormMessage";
|
||||
import { Input } from "~/components/Input";
|
||||
import { Label } from "~/components/Label";
|
||||
import { SendouButton } from "~/components/elements/Button";
|
||||
import { SendouSwitch } from "~/components/elements/Switch";
|
||||
import { PlusIcon } from "~/components/icons/Plus";
|
||||
import * as Progression from "~/features/tournament-bracket/core/Progression";
|
||||
|
|
@ -113,15 +113,16 @@ export function BracketProgressionSelector({
|
|||
/>
|
||||
))}
|
||||
</div>
|
||||
<Button
|
||||
<SendouButton
|
||||
icon={<PlusIcon />}
|
||||
size="tiny"
|
||||
size="small"
|
||||
variant="outlined"
|
||||
onClick={handleAddBracket}
|
||||
disabled={brackets.length >= TOURNAMENT.MAX_BRACKETS_PER_TOURNAMENT}
|
||||
onPress={handleAddBracket}
|
||||
isDisabled={brackets.length >= TOURNAMENT.MAX_BRACKETS_PER_TOURNAMENT}
|
||||
data-testid="add-bracket-button"
|
||||
>
|
||||
Add bracket
|
||||
</Button>
|
||||
</SendouButton>
|
||||
{Progression.isError(validated) ? (
|
||||
<ErrorMessage error={validated} />
|
||||
) : null}
|
||||
|
|
@ -171,15 +172,15 @@ function TournamentFormatBracketSelector({
|
|||
<div>
|
||||
<div className="format-selector__count">Bracket #{count}</div>
|
||||
{onDelete ? (
|
||||
<Button
|
||||
size="tiny"
|
||||
<SendouButton
|
||||
size="small"
|
||||
variant="minimal-destructive"
|
||||
onClick={onDelete}
|
||||
onPress={onDelete}
|
||||
className="mx-auto"
|
||||
testId="delete-bracket-button"
|
||||
data-testid="delete-bracket-button"
|
||||
>
|
||||
Delete
|
||||
</Button>
|
||||
</SendouButton>
|
||||
) : null}
|
||||
</div>
|
||||
<div className="format-selector__divider" />
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import clsx from "clsx";
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Button } from "~/components/Button";
|
||||
import { SendouButton } from "~/components/elements/Button";
|
||||
import { CrossIcon } from "~/components/icons/Cross";
|
||||
import type { CalendarEventTag } from "~/db/tables";
|
||||
import { tags as allTags } from "../calendar-constants";
|
||||
|
|
@ -33,13 +33,13 @@ export function Tags({
|
|||
>
|
||||
{t(`tag.name.${tag}`)}
|
||||
{onDelete && (
|
||||
<Button
|
||||
onClick={() => onDelete(tag)}
|
||||
<SendouButton
|
||||
onPress={() => onDelete(tag)}
|
||||
className="calendar__event__tag-delete-button"
|
||||
icon={<CrossIcon />}
|
||||
variant="minimal"
|
||||
aria-label="Remove date"
|
||||
size="tiny"
|
||||
size="small"
|
||||
/>
|
||||
)}
|
||||
</li>
|
||||
|
|
|
|||
|
|
@ -3,11 +3,11 @@ import { Form, useLoaderData } from "@remix-run/react";
|
|||
import clsx from "clsx";
|
||||
import * as React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Button } from "~/components/Button";
|
||||
import { FormErrors } from "~/components/FormErrors";
|
||||
import { FormMessage } from "~/components/FormMessage";
|
||||
import { Label } from "~/components/Label";
|
||||
import { Main } from "~/components/Main";
|
||||
import { SendouButton } from "~/components/elements/Button";
|
||||
import { UserSearch } from "~/components/elements/UserSearch";
|
||||
import type { SendouRouteHandle } from "~/utils/remix.server";
|
||||
import type { Unpacked } from "~/utils/types";
|
||||
|
|
@ -36,9 +36,9 @@ export default function ReportWinnersPage() {
|
|||
{t("calendar:forms.reportResultsInfo")}
|
||||
</FormMessage>
|
||||
<TeamInputs />
|
||||
<Button type="submit" className="mt-4">
|
||||
<SendouButton type="submit" className="mt-4">
|
||||
{t("common:actions.submit")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
<FormErrors namespace="calendar" />
|
||||
</Form>
|
||||
</Main>
|
||||
|
|
@ -101,12 +101,12 @@ function TeamInputs() {
|
|||
</React.Fragment>
|
||||
);
|
||||
})}
|
||||
<Button
|
||||
onClick={() => setAmountOfTeams((amountOfTeams) => amountOfTeams + 1)}
|
||||
size="tiny"
|
||||
<SendouButton
|
||||
onPress={() => setAmountOfTeams((amountOfTeams) => amountOfTeams + 1)}
|
||||
size="small"
|
||||
>
|
||||
{t("forms.team.add")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
@ -202,14 +202,14 @@ function Team({
|
|||
setPlayers={(players) => setResults({ ...results, players })}
|
||||
/>
|
||||
{onRemoveTeam && (
|
||||
<Button
|
||||
onClick={onRemoveTeam}
|
||||
size="tiny"
|
||||
<SendouButton
|
||||
onPress={onRemoveTeam}
|
||||
size="small"
|
||||
variant="minimal-destructive"
|
||||
className="mt-4"
|
||||
>
|
||||
{t("forms.team.remove")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
|
@ -256,16 +256,16 @@ function Players({
|
|||
<label htmlFor={formId} className="mb-0">
|
||||
{t("forms.team.player.header", { number: i + 1 })}
|
||||
</label>
|
||||
<Button
|
||||
size="tiny"
|
||||
<SendouButton
|
||||
size="small"
|
||||
variant="minimal"
|
||||
onClick={() => handlePlayerInputTypeChange(i)}
|
||||
onPress={() => handlePlayerInputTypeChange(i)}
|
||||
className="outline-theme"
|
||||
>
|
||||
{asPlainInput
|
||||
? t("forms.team.player.addAsUser")
|
||||
: t("forms.team.player.addAsText")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</div>
|
||||
{asPlainInput ? (
|
||||
<input
|
||||
|
|
@ -286,22 +286,24 @@ function Players({
|
|||
);
|
||||
})}
|
||||
<div className="stack horizontal sm mt-2">
|
||||
<Button
|
||||
size="tiny"
|
||||
onClick={handleAddPlayer}
|
||||
disabled={players.length === CALENDAR_EVENT_RESULT.MAX_PLAYERS_LENGTH}
|
||||
<SendouButton
|
||||
size="small"
|
||||
onPress={handleAddPlayer}
|
||||
isDisabled={
|
||||
players.length === CALENDAR_EVENT_RESULT.MAX_PLAYERS_LENGTH
|
||||
}
|
||||
variant="outlined"
|
||||
>
|
||||
{t("forms.team.player.add")}
|
||||
</Button>{" "}
|
||||
<Button
|
||||
size="tiny"
|
||||
</SendouButton>{" "}
|
||||
<SendouButton
|
||||
size="small"
|
||||
variant="destructive"
|
||||
onClick={handleRemovePlayer}
|
||||
disabled={players.length === 1}
|
||||
onPress={handleRemovePlayer}
|
||||
isDisabled={players.length === 1}
|
||||
>
|
||||
{t("forms.team.player.remove")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import clsx from "clsx";
|
|||
import * as React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Avatar } from "~/components/Avatar";
|
||||
import { Button, LinkButton } from "~/components/Button";
|
||||
import { LinkButton } from "~/components/Button";
|
||||
import { FormWithConfirm } from "~/components/FormWithConfirm";
|
||||
import { Image } from "~/components/Image";
|
||||
import { Main } from "~/components/Main";
|
||||
|
|
@ -13,6 +13,7 @@ import { MapPoolStages } from "~/components/MapPoolSelector";
|
|||
import { Placement } from "~/components/Placement";
|
||||
import { Section } from "~/components/Section";
|
||||
import { Table } from "~/components/Table";
|
||||
import { SendouButton } from "~/components/elements/Button";
|
||||
import { useUser } from "~/features/auth/core/user";
|
||||
import { MapPool } from "~/features/map-list-generator/core/map-pool";
|
||||
import { useIsMounted } from "~/hooks/useIsMounted";
|
||||
|
|
@ -175,14 +176,14 @@ export default function CalendarEventPage() {
|
|||
name: data.event.name,
|
||||
})}
|
||||
>
|
||||
<Button
|
||||
<SendouButton
|
||||
className="ml-auto"
|
||||
size="tiny"
|
||||
size="small"
|
||||
variant="minimal-destructive"
|
||||
type="submit"
|
||||
>
|
||||
{t("calendar:actions.delete")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</FormWithConfirm>
|
||||
) : null}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import { useTranslation } from "react-i18next";
|
|||
import type { AlertVariation } from "~/components/Alert";
|
||||
import { Alert } from "~/components/Alert";
|
||||
import { Badge } from "~/components/Badge";
|
||||
import { Button } from "~/components/Button";
|
||||
import { DateInput } from "~/components/DateInput";
|
||||
import { Divider } from "~/components/Divider";
|
||||
import { FormMessage } from "~/components/FormMessage";
|
||||
|
|
@ -17,6 +16,7 @@ import { Main } from "~/components/Main";
|
|||
import { MapPoolSelector } from "~/components/MapPoolSelector";
|
||||
import { RequiredHiddenInput } from "~/components/RequiredHiddenInput";
|
||||
import { SubmitButton } from "~/components/SubmitButton";
|
||||
import { SendouButton } from "~/components/elements/Button";
|
||||
import { CrossIcon } from "~/components/icons/Cross";
|
||||
import { TrashIcon } from "~/components/icons/Trash";
|
||||
import type { CalendarEventTag, Tables } from "~/db/tables";
|
||||
|
|
@ -159,7 +159,7 @@ function TemplateTournamentForm() {
|
|||
</option>
|
||||
))}
|
||||
</select>
|
||||
<SubmitButton disabled={!eventId}>Use template</SubmitButton>
|
||||
<SubmitButton isDisabled={!eventId}>Use template</SubmitButton>
|
||||
</Form>
|
||||
</div>
|
||||
<hr />
|
||||
|
|
@ -279,14 +279,14 @@ function EventForm() {
|
|||
/>
|
||||
</div>
|
||||
) : null}
|
||||
<Button
|
||||
<SendouButton
|
||||
className="mt-4"
|
||||
onClick={handleSubmit}
|
||||
disabled={submitButtonDisabled()}
|
||||
testId="submit-button"
|
||||
onPress={handleSubmit}
|
||||
isDisabled={submitButtonDisabled()}
|
||||
data-testid="submit-button"
|
||||
>
|
||||
{t("actions.submit")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
|
|
@ -406,9 +406,9 @@ function AddButton({ onAdd, id }: { onAdd: () => void; id?: string }) {
|
|||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Button size="tiny" variant="outlined" onClick={onAdd} id={id}>
|
||||
<SendouButton size="small" variant="outlined" onPress={onAdd} id={id}>
|
||||
{t("actions.add")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -509,9 +509,9 @@ function DatesInput({ allowMultiDate }: { allowMultiDate?: boolean }) {
|
|||
/>
|
||||
{/* "Remove" button */}
|
||||
{datesCount > 1 && (
|
||||
<Button
|
||||
size="tiny"
|
||||
onClick={() => {
|
||||
<SendouButton
|
||||
size="small"
|
||||
onPress={() => {
|
||||
setDatesInputState((current) =>
|
||||
current.filter((e) => e.key !== key),
|
||||
);
|
||||
|
|
@ -519,8 +519,7 @@ function DatesInput({ allowMultiDate }: { allowMultiDate?: boolean }) {
|
|||
aria-controls={`date-input-${key}`}
|
||||
aria-label={t("common:actions.remove")}
|
||||
aria-describedby={`date-input-${key}-label`}
|
||||
title={t("common:actions.remove")}
|
||||
icon={<CrossIcon />}
|
||||
icon={<CrossIcon title={t("common:actions.remove")} />}
|
||||
variant="minimal-destructive"
|
||||
/>
|
||||
)}
|
||||
|
|
@ -678,9 +677,9 @@ function BadgesAdder() {
|
|||
<div className="stack horizontal md items-center" key={badge.id}>
|
||||
<Badge badge={badge} isAnimated size={32} />
|
||||
<span>{badge.displayName}</span>
|
||||
<Button
|
||||
<SendouButton
|
||||
className="ml-auto"
|
||||
onClick={() => handleBadgeDelete(badge.id)}
|
||||
onPress={() => handleBadgeDelete(badge.id)}
|
||||
icon={<TrashIcon />}
|
||||
variant="minimal-destructive"
|
||||
aria-label="Remove badge"
|
||||
|
|
@ -719,13 +718,13 @@ function AvatarImageInput({
|
|||
alt=""
|
||||
className="calendar-new__avatar-preview"
|
||||
/>
|
||||
<Button
|
||||
<SendouButton
|
||||
variant="outlined"
|
||||
size="tiny"
|
||||
onClick={() => setShowPrevious(false)}
|
||||
size="small"
|
||||
onPress={() => setShowPrevious(false)}
|
||||
>
|
||||
Edit logo
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
@ -783,14 +782,14 @@ function AvatarImageInput({
|
|||
shown.
|
||||
</FormMessage>
|
||||
{hasPreviousAvatar && (
|
||||
<Button
|
||||
<SendouButton
|
||||
variant="minimal-destructive"
|
||||
size="tiny"
|
||||
onClick={() => setShowPrevious(true)}
|
||||
size="small"
|
||||
onPress={() => setShowPrevious(true)}
|
||||
className="mt-2"
|
||||
>
|
||||
Cancel changing avatar image
|
||||
</Button>
|
||||
</SendouButton>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@ import invariant from "~/utils/invariant";
|
|||
import { logger } from "~/utils/logger";
|
||||
import { soundPath } from "~/utils/urls";
|
||||
import { Avatar } from "../../../components/Avatar";
|
||||
import { Button } from "../../../components/Button";
|
||||
import { SubmitButton } from "../../../components/SubmitButton";
|
||||
import { SendouButton } from "../../../components/elements/Button";
|
||||
import { MESSAGE_MAX_LENGTH } from "../chat-constants";
|
||||
import { useChatAutoScroll } from "../chat-hooks";
|
||||
import type { ChatMessage } from "../chat-types";
|
||||
|
|
@ -136,12 +136,13 @@ export function Chat({
|
|||
const unseen = unseenMessages.get(room.code);
|
||||
|
||||
return (
|
||||
<Button
|
||||
<SendouButton
|
||||
key={room.code}
|
||||
className={clsx("chat__room-button", {
|
||||
current: currentRoom === room.code,
|
||||
})}
|
||||
onClick={() => {
|
||||
size="small"
|
||||
onPress={() => {
|
||||
setCurrentRoom(room.code);
|
||||
resetScroller();
|
||||
}}
|
||||
|
|
@ -153,7 +154,7 @@ export function Chat({
|
|||
) : (
|
||||
<span className="chat__room-button__unseen invisible" />
|
||||
)}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
|
@ -189,9 +190,12 @@ export function Chat({
|
|||
})}
|
||||
</ol>
|
||||
{unseenMessagesInTheRoom ? (
|
||||
<Button className="chat__unseen-messages" onClick={scrollToBottom}>
|
||||
<SendouButton
|
||||
className="chat__unseen-messages"
|
||||
onPress={scrollToBottom}
|
||||
>
|
||||
{t("common:chat.newMessages")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
) : null}
|
||||
<form onSubmit={handleSubmit} className="mt-4">
|
||||
<input
|
||||
|
|
@ -216,9 +220,9 @@ export function Chat({
|
|||
</div>
|
||||
)}
|
||||
<SubmitButton
|
||||
size="tiny"
|
||||
size="small"
|
||||
variant="minimal"
|
||||
disabled={sendingMessagesDisabled}
|
||||
isDisabled={sendingMessagesDisabled}
|
||||
>
|
||||
{t("common:chat.send")}
|
||||
</SubmitButton>
|
||||
|
|
|
|||
|
|
@ -3,11 +3,11 @@ import clsx from "clsx";
|
|||
import * as React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Avatar } from "~/components/Avatar";
|
||||
import { Button } from "~/components/Button";
|
||||
import { Divider } from "~/components/Divider";
|
||||
import { Image } from "~/components/Image";
|
||||
import { Main } from "~/components/Main";
|
||||
import { NewTabs } from "~/components/NewTabs";
|
||||
import { SendouButton } from "~/components/elements/Button";
|
||||
import { ArrowRightIcon } from "~/components/icons/ArrowRight";
|
||||
import { BSKYLikeIcon } from "~/components/icons/BSKYLike";
|
||||
import { BSKYReplyIcon } from "~/components/icons/BSKYReply";
|
||||
|
|
@ -84,15 +84,15 @@ function DesktopSideNav() {
|
|||
})}
|
||||
{user ? (
|
||||
<form method="post" action={LOG_OUT_URL}>
|
||||
<Button
|
||||
size="tiny"
|
||||
<SendouButton
|
||||
size="small"
|
||||
variant="minimal"
|
||||
icon={<LogOutIcon />}
|
||||
type="submit"
|
||||
className="front-page__side-nav__log-out"
|
||||
>
|
||||
{t("common:header.logout")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</form>
|
||||
) : null}
|
||||
</nav>
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ import { useFetcher, useLoaderData } from "@remix-run/react";
|
|||
import Compressor from "compressorjs";
|
||||
import * as React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Button } from "~/components/Button";
|
||||
import { Main } from "~/components/Main";
|
||||
import { SendouButton } from "~/components/elements/Button";
|
||||
import invariant from "~/utils/invariant";
|
||||
import { imgTypeToDimensions, imgTypeToStyle } from "../upload-constants";
|
||||
import type { ImageUploadType } from "../upload-types";
|
||||
|
|
@ -98,13 +98,14 @@ export default function FileUploadPage() {
|
|||
/>
|
||||
</div>
|
||||
{img ? <PreviewImage img={img} type={data.type} /> : null}
|
||||
<Button
|
||||
<SendouButton
|
||||
className="self-start"
|
||||
disabled={!img || fetcher.state !== "idle"}
|
||||
onClick={handleSubmit}
|
||||
isDisabled={!img || fetcher.state !== "idle"}
|
||||
onPress={handleSubmit}
|
||||
data-testid="upload-button"
|
||||
>
|
||||
{t("common:actions.upload")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</Main>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import { useTranslation } from "react-i18next";
|
||||
import * as R from "remeda";
|
||||
import { Button } from "~/components/Button";
|
||||
import { WeaponCombobox } from "~/components/Combobox";
|
||||
import { WeaponImage } from "~/components/Image";
|
||||
import { Label } from "~/components/Label";
|
||||
import { SendouButton } from "~/components/elements/Button";
|
||||
import { CrossIcon } from "~/components/icons/Cross";
|
||||
import type { Tables } from "~/db/tables";
|
||||
import type { TierName } from "~/features/mmr/mmr-constants";
|
||||
|
|
@ -59,11 +59,11 @@ function Filter({
|
|||
<Label>
|
||||
{t(`lfg:filters.${filter._tag}`)} {t("lfg:filters.suffix")}
|
||||
</Label>
|
||||
<Button
|
||||
<SendouButton
|
||||
icon={<CrossIcon />}
|
||||
size="tiny"
|
||||
size="small"
|
||||
variant="minimal-destructive"
|
||||
onClick={removeFilter}
|
||||
onPress={removeFilter}
|
||||
aria-label="Delete filter"
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -139,10 +139,10 @@ function WeaponFilterFields({
|
|||
}
|
||||
/>
|
||||
{value.map((weapon) => (
|
||||
<Button
|
||||
<SendouButton
|
||||
key={weapon}
|
||||
variant="minimal"
|
||||
onClick={() =>
|
||||
onPress={() =>
|
||||
changeFilter({
|
||||
_tag: "Weapon",
|
||||
weaponSplIds: value.filter((weaponId) => weaponId !== weapon),
|
||||
|
|
@ -150,7 +150,7 @@ function WeaponFilterFields({
|
|||
}
|
||||
>
|
||||
<WeaponImage weaponSplId={weapon} size={32} variant="badge" />
|
||||
</Button>
|
||||
</SendouButton>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -4,11 +4,11 @@ import { formatDistanceToNow } from "date-fns";
|
|||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Avatar } from "~/components/Avatar";
|
||||
import { Button } from "~/components/Button";
|
||||
import { Divider } from "~/components/Divider";
|
||||
import { Flag } from "~/components/Flag";
|
||||
import { FormWithConfirm } from "~/components/FormWithConfirm";
|
||||
import { Image, TierImage, WeaponImage } from "~/components/Image";
|
||||
import { SendouButton } from "~/components/elements/Button";
|
||||
import { EditIcon } from "~/components/icons/Edit";
|
||||
import { TrashIcon } from "~/components/icons/Trash";
|
||||
import { useUser } from "~/features/auth/core/user";
|
||||
|
|
@ -463,15 +463,15 @@ function PostDeleteButton({ id, type }: { id: number; type: Post["type"] }) {
|
|||
]}
|
||||
fetcher={fetcher}
|
||||
>
|
||||
<Button
|
||||
<SendouButton
|
||||
className="build__small-text"
|
||||
variant="minimal-destructive"
|
||||
size="tiny"
|
||||
size="small"
|
||||
type="submit"
|
||||
icon={<TrashIcon className="build__icon" />}
|
||||
>
|
||||
{t("common:actions.delete")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</FormWithConfirm>
|
||||
);
|
||||
}
|
||||
|
|
@ -501,18 +501,18 @@ function PostExpandableText({
|
|||
>
|
||||
<div className={styles.text}>{text}</div>
|
||||
{isExpandable ? (
|
||||
<Button
|
||||
onClick={() => setIsExpanded(!isExpanded)}
|
||||
<SendouButton
|
||||
onPress={() => setIsExpanded(!isExpanded)}
|
||||
className={clsx([styles.showAllButton], {
|
||||
[styles.showAllButtonExpanded]: isExpanded,
|
||||
})}
|
||||
variant="outlined"
|
||||
size="tiny"
|
||||
size="small"
|
||||
>
|
||||
{isExpanded
|
||||
? t("common:actions.showLess")
|
||||
: t("common:actions.showMore")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
) : null}
|
||||
{!isExpanded ? <div className={styles.textCut} /> : null}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ function PostExpiryAlert({ postId }: { postId: number }) {
|
|||
<fetcher.Form method="post" className="stack md horizontal items-center">
|
||||
<input type="hidden" name="id" value={postId} />
|
||||
{t("lfg:expiring")}{" "}
|
||||
<SubmitButton _action="BUMP_POST" variant="outlined" size="tiny">
|
||||
<SubmitButton _action="BUMP_POST" variant="outlined" size="small">
|
||||
{t("common:actions.clickHere")}
|
||||
</SubmitButton>
|
||||
</fetcher.Form>
|
||||
|
|
|
|||
|
|
@ -4,10 +4,10 @@ import { Link, useLoaderData, useSearchParams } from "@remix-run/react";
|
|||
import * as React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useCopyToClipboard } from "react-use";
|
||||
import { Button } from "~/components/Button";
|
||||
import { Label } from "~/components/Label";
|
||||
import { Main } from "~/components/Main";
|
||||
import { MapPoolSelector, MapPoolStages } from "~/components/MapPoolSelector";
|
||||
import { SendouButton } from "~/components/elements/Button";
|
||||
import { SendouSwitch } from "~/components/elements/Switch";
|
||||
import { EditIcon } from "~/components/icons/Edit";
|
||||
import type { Tables } from "~/db/tables";
|
||||
|
|
@ -77,14 +77,14 @@ export default function MapListPage() {
|
|||
{data.calendarEvent.name}
|
||||
</Link>
|
||||
</div>
|
||||
<Button
|
||||
<SendouButton
|
||||
variant="outlined"
|
||||
onClick={switchToEditMode}
|
||||
size="tiny"
|
||||
onPress={switchToEditMode}
|
||||
size="small"
|
||||
icon={<EditIcon />}
|
||||
>
|
||||
{t("common:actions.edit")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</div>
|
||||
)}
|
||||
{readonly ? (
|
||||
|
|
@ -194,9 +194,9 @@ function MapListCreator({ mapPool }: { mapPool: MapPool }) {
|
|||
size="small"
|
||||
/>
|
||||
</div>
|
||||
<Button onClick={handleCreateMaplist} disabled={disabled}>
|
||||
<SendouButton onPress={handleCreateMaplist} isDisabled={disabled}>
|
||||
{t("common:maps.createMapList")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
{mapList && (
|
||||
<>
|
||||
<ol className={styles.mapList}>
|
||||
|
|
@ -212,10 +212,10 @@ function MapListCreator({ mapPool }: { mapPool: MapPool }) {
|
|||
</li>
|
||||
))}
|
||||
</ol>
|
||||
<Button
|
||||
size="tiny"
|
||||
<SendouButton
|
||||
size="small"
|
||||
variant="outlined"
|
||||
onClick={() =>
|
||||
onPress={() =>
|
||||
copyToClipboard(
|
||||
mapList
|
||||
.map(
|
||||
|
|
@ -229,7 +229,7 @@ function MapListCreator({ mapPool }: { mapPool: MapPool }) {
|
|||
}
|
||||
>
|
||||
{t("common:actions.copyToClipboard")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -37,8 +37,8 @@ import {
|
|||
subWeaponImageUrl,
|
||||
weaponCategoryUrl,
|
||||
} from "~/utils/urls";
|
||||
import { Button } from "../../../components/Button";
|
||||
import { Image } from "../../../components/Image";
|
||||
import { SendouButton } from "../../../components/elements/Button";
|
||||
import type { StageBackgroundStyle } from "../plans-types";
|
||||
|
||||
export default function Planner() {
|
||||
|
|
@ -275,9 +275,9 @@ function OutlineToggle({
|
|||
|
||||
return (
|
||||
<div className="plans__outline-toggle">
|
||||
<Button
|
||||
<SendouButton
|
||||
variant="minimal"
|
||||
onClick={handleClick}
|
||||
onPress={handleClick}
|
||||
className={clsx("plans__outline-toggle__button", {
|
||||
"plans__outline-toggle__button__outlined": outlined,
|
||||
})}
|
||||
|
|
@ -285,7 +285,7 @@ function OutlineToggle({
|
|||
{outlined
|
||||
? t("common:actions.outlined")
|
||||
: t("common:actions.noOutline")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -320,10 +320,10 @@ function WeaponImageSelector({
|
|||
<div className="plans__weapons-container">
|
||||
{category.weaponIds.map((weaponId) => {
|
||||
return (
|
||||
<Button
|
||||
<SendouButton
|
||||
key={weaponId}
|
||||
variant="minimal"
|
||||
onClick={() =>
|
||||
onPress={() =>
|
||||
handleAddWeapon(
|
||||
`${outlinedMainWeaponImageUrl(weaponId)}.png`,
|
||||
)
|
||||
|
|
@ -336,7 +336,7 @@ function WeaponImageSelector({
|
|||
width={36}
|
||||
height={36}
|
||||
/>
|
||||
</Button>
|
||||
</SendouButton>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
|
@ -351,10 +351,10 @@ function WeaponImageSelector({
|
|||
<div className="plans__weapons-container">
|
||||
{subWeaponIds.map((subWeaponId) => {
|
||||
return (
|
||||
<Button
|
||||
<SendouButton
|
||||
key={subWeaponId}
|
||||
variant="minimal"
|
||||
onClick={() =>
|
||||
onPress={() =>
|
||||
handleAddWeapon(`${subWeaponImageUrl(subWeaponId)}.png`)
|
||||
}
|
||||
>
|
||||
|
|
@ -365,7 +365,7 @@ function WeaponImageSelector({
|
|||
width={28}
|
||||
height={28}
|
||||
/>
|
||||
</Button>
|
||||
</SendouButton>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
|
@ -383,10 +383,10 @@ function WeaponImageSelector({
|
|||
<div className="plans__weapons-container">
|
||||
{specialWeaponIds.map((specialWeaponId) => {
|
||||
return (
|
||||
<Button
|
||||
<SendouButton
|
||||
key={specialWeaponId}
|
||||
variant="minimal"
|
||||
onClick={() =>
|
||||
onPress={() =>
|
||||
handleAddWeapon(
|
||||
`${specialWeaponImageUrl(specialWeaponId)}.png`,
|
||||
)
|
||||
|
|
@ -399,7 +399,7 @@ function WeaponImageSelector({
|
|||
width={28}
|
||||
height={28}
|
||||
/>
|
||||
</Button>
|
||||
</SendouButton>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
|
@ -412,10 +412,10 @@ function WeaponImageSelector({
|
|||
<div className="plans__weapons-container">
|
||||
{(["TC", "RM", "CB"] as const).map((mode) => {
|
||||
return (
|
||||
<Button
|
||||
<SendouButton
|
||||
key={mode}
|
||||
variant="minimal"
|
||||
onClick={() => handleAddWeapon(`${modeImageUrl(mode)}.png`)}
|
||||
onPress={() => handleAddWeapon(`${modeImageUrl(mode)}.png`)}
|
||||
>
|
||||
<Image
|
||||
alt={t(`game-misc:MODE_LONG_${mode}`)}
|
||||
|
|
@ -424,7 +424,7 @@ function WeaponImageSelector({
|
|||
width={28}
|
||||
height={28}
|
||||
/>
|
||||
</Button>
|
||||
</SendouButton>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
|
@ -499,15 +499,15 @@ function StageBackgroundSelector({
|
|||
);
|
||||
})}
|
||||
</select>
|
||||
<Button
|
||||
size="tiny"
|
||||
onClick={() =>
|
||||
<SendouButton
|
||||
size="small"
|
||||
onPress={() =>
|
||||
onAddBackground({ style: backgroundStyle, stageId, mode })
|
||||
}
|
||||
className="w-max"
|
||||
>
|
||||
{t("common:actions.setBg")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { Form, useMatches, useParams } from "@remix-run/react";
|
||||
import { Button } from "~/components/Button";
|
||||
import { Redirect } from "~/components/Redirect";
|
||||
import { SendouButton } from "~/components/elements/Button";
|
||||
import { SendouDialog } from "~/components/elements/Dialog";
|
||||
import { useUser } from "~/features/auth/core/user";
|
||||
import { atOrError } from "~/utils/arrays";
|
||||
|
|
@ -51,7 +51,7 @@ export default function PlusCommentModalPage() {
|
|||
<input type="hidden" name="suggestedId" value={targetUserId} />
|
||||
<CommentTextarea maxLength={PLUS_SUGGESTION.COMMENT_MAX_LENGTH} />
|
||||
<div>
|
||||
<Button type="submit">Submit</Button>
|
||||
<SendouButton type="submit">Submit</SendouButton>
|
||||
</div>
|
||||
</Form>
|
||||
</SendouDialog>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { Link, Outlet, useLoaderData, useSearchParams } from "@remix-run/react";
|
|||
import clsx from "clsx";
|
||||
import { Alert } from "~/components/Alert";
|
||||
import { Avatar } from "~/components/Avatar";
|
||||
import { Button, LinkButton } from "~/components/Button";
|
||||
import { LinkButton } from "~/components/Button";
|
||||
import { Catcher } from "~/components/Catcher";
|
||||
import { FormWithConfirm } from "~/components/FormWithConfirm";
|
||||
import { RelativeTime } from "~/components/RelativeTime";
|
||||
|
|
@ -26,6 +26,7 @@ import {
|
|||
canSuggestNewUser,
|
||||
} from "../plus-suggestions-utils";
|
||||
|
||||
import { SendouButton } from "~/components/elements/Button";
|
||||
import { action } from "../actions/plus.suggestions.server";
|
||||
import { loader } from "../loaders/plus.suggestions.server";
|
||||
export { action, loader };
|
||||
|
|
@ -175,14 +176,14 @@ function SuggestedForInfo() {
|
|||
]}
|
||||
dialogHeading={`Delete your suggestion to +${tier}? You won't appear in next voting.`}
|
||||
>
|
||||
<Button
|
||||
<SendouButton
|
||||
key={tier}
|
||||
size="tiny"
|
||||
size="small"
|
||||
variant="destructive"
|
||||
type="submit"
|
||||
>
|
||||
Delete your +{tier} suggestion
|
||||
</Button>
|
||||
Delete
|
||||
</SendouButton>
|
||||
</FormWithConfirm>
|
||||
))}
|
||||
</div>
|
||||
|
|
@ -325,7 +326,7 @@ function CommentDeleteButton({
|
|||
: `Delete your comment to ${suggestedUsername}'s +${tier} suggestion?`
|
||||
}
|
||||
>
|
||||
<Button
|
||||
<SendouButton
|
||||
className="plus__delete-button"
|
||||
icon={<TrashIcon />}
|
||||
variant="minimal-destructive"
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ import type { MetaFunction } from "@remix-run/node";
|
|||
import { Form, useLoaderData } from "@remix-run/react";
|
||||
import * as React from "react";
|
||||
import { Avatar } from "~/components/Avatar";
|
||||
import { Button } from "~/components/Button";
|
||||
import { RelativeTime } from "~/components/RelativeTime";
|
||||
import { SendouButton } from "~/components/elements/Button";
|
||||
import { CheckmarkIcon } from "~/components/icons/Checkmark";
|
||||
import { usePlusVoting } from "~/features/plus-voting/core";
|
||||
import { metaTags } from "~/utils/remix";
|
||||
|
|
@ -108,9 +108,13 @@ function Voting(data: Extract<PlusVotingLoaderData, { type: "voting" }>) {
|
|||
{previous.score}
|
||||
</span>{" "}
|
||||
on {previous.user.username}.
|
||||
<Button className="ml-auto" variant="minimal" onClick={undoLast}>
|
||||
<SendouButton
|
||||
className="ml-auto"
|
||||
variant="minimal"
|
||||
onPress={undoLast}
|
||||
>
|
||||
Undo?
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</p>
|
||||
) : (
|
||||
<p className="text-sm text-lighter">Tip: {randomTip}</p>
|
||||
|
|
@ -120,20 +124,20 @@ function Voting(data: Extract<PlusVotingLoaderData, { type: "voting" }>) {
|
|||
<Avatar user={currentUser.user} size="lg" />
|
||||
<h2>{currentUser.user.username}</h2>
|
||||
<div className="stack horizontal lg">
|
||||
<Button
|
||||
<SendouButton
|
||||
className="plus-voting__vote-button downvote"
|
||||
variant="outlined"
|
||||
onClick={() => addVote("downvote")}
|
||||
onPress={() => addVote("downvote")}
|
||||
>
|
||||
-1
|
||||
</Button>
|
||||
<Button
|
||||
</SendouButton>
|
||||
<SendouButton
|
||||
className="plus-voting__vote-button"
|
||||
variant="outlined"
|
||||
onClick={() => addVote("upvote")}
|
||||
onPress={() => addVote("upvote")}
|
||||
>
|
||||
+1
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</div>
|
||||
{currentUser.suggestion ? (
|
||||
<PlusSuggestionComments
|
||||
|
|
@ -153,9 +157,9 @@ function Voting(data: Extract<PlusVotingLoaderData, { type: "voting" }>) {
|
|||
) : (
|
||||
<Form method="post">
|
||||
<input type="hidden" name="votes" value={JSON.stringify(votes)} />
|
||||
<Button className="plus-voting__submit-button" type="submit">
|
||||
<SendouButton className="plus-voting__submit-button" type="submit">
|
||||
Submit votes
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</Form>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import { useTranslation } from "react-i18next";
|
|||
import * as R from "remeda";
|
||||
import type { z } from "zod";
|
||||
import { Avatar } from "~/components/Avatar";
|
||||
import { Button, LinkButton } from "~/components/Button";
|
||||
import { LinkButton } from "~/components/Button";
|
||||
import { Divider } from "~/components/Divider";
|
||||
import { FormWithConfirm } from "~/components/FormWithConfirm";
|
||||
import { Table } from "~/components/Table";
|
||||
|
|
@ -471,14 +471,14 @@ function ScrimsTable({
|
|||
) : null}
|
||||
{user && requestScrim && post.requests.length === 0 ? (
|
||||
<td className={styles.postFloatingActionCell}>
|
||||
<Button
|
||||
size="tiny"
|
||||
onClick={() => requestScrim(post.id)}
|
||||
<SendouButton
|
||||
size="small"
|
||||
onPress={() => requestScrim(post.id)}
|
||||
icon={<ArrowUpOnSquareIcon />}
|
||||
className="ml-auto"
|
||||
>
|
||||
{t("scrims:actions.request")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</td>
|
||||
) : null}
|
||||
{showDeletePost && !isAccepted ? (
|
||||
|
|
@ -492,13 +492,13 @@ function ScrimsTable({
|
|||
["_action", "DELETE_POST"],
|
||||
]}
|
||||
>
|
||||
<Button
|
||||
size="tiny"
|
||||
<SendouButton
|
||||
size="small"
|
||||
variant="destructive"
|
||||
className="ml-auto"
|
||||
>
|
||||
{t("common:actions.delete")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</FormWithConfirm>
|
||||
) : (
|
||||
<SendouPopover
|
||||
|
|
@ -531,14 +531,14 @@ function ScrimsTable({
|
|||
["_action", "CANCEL_REQUEST"],
|
||||
]}
|
||||
>
|
||||
<Button
|
||||
size="tiny"
|
||||
<SendouButton
|
||||
size="small"
|
||||
variant="destructive"
|
||||
icon={<CrossIcon />}
|
||||
className="ml-auto"
|
||||
>
|
||||
{t("common:actions.cancel")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</FormWithConfirm>
|
||||
</td>
|
||||
) : null}
|
||||
|
|
@ -645,9 +645,9 @@ function RequestRow({
|
|||
submitButtonVariant="primary"
|
||||
submitButtonText={t("common:actions.accept")}
|
||||
>
|
||||
<Button size="tiny" className="ml-auto">
|
||||
<SendouButton size="small" className="ml-auto">
|
||||
{t("common:actions.accept")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</FormWithConfirm>
|
||||
) : !request.isAccepted && !canAccept ? (
|
||||
<SendouPopover
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import { Flipped, Flipper } from "react-flip-toolkit";
|
|||
import { useTranslation } from "react-i18next";
|
||||
import { Alert } from "~/components/Alert";
|
||||
import { Avatar } from "~/components/Avatar";
|
||||
import { Button, LinkButton } from "~/components/Button";
|
||||
import { LinkButton } from "~/components/Button";
|
||||
import { WeaponCombobox } from "~/components/Combobox";
|
||||
import { Divider } from "~/components/Divider";
|
||||
import { FormWithConfirm } from "~/components/FormWithConfirm";
|
||||
|
|
@ -381,15 +381,15 @@ function AfterMatchActions({
|
|||
</SubmitButton>
|
||||
) : null}
|
||||
{showWeaponsFormButton ? (
|
||||
<Button
|
||||
<SendouButton
|
||||
icon={<ArchiveBoxIcon />}
|
||||
onClick={() => setShowWeaponsForm(!showWeaponsForm)}
|
||||
onPress={() => setShowWeaponsForm(!showWeaponsForm)}
|
||||
variant={showWeaponsForm ? "destructive" : undefined}
|
||||
>
|
||||
{showWeaponsForm
|
||||
? t("q:match.actions.stopReportingWeapons")
|
||||
: t("q:match.actions.reportWeapons")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
) : null}
|
||||
</lookAgainFetcher.Form>
|
||||
{showWeaponsForm ? <ReportWeaponsForm /> : null}
|
||||
|
|
@ -515,17 +515,17 @@ function ReportWeaponsForm() {
|
|||
showReportedOwnWeapon={false}
|
||||
/>
|
||||
{i !== 0 && reportingMode !== "MYSELF" ? (
|
||||
<Button
|
||||
size="tiny"
|
||||
<SendouButton
|
||||
size="small"
|
||||
variant="outlined"
|
||||
className="self-center"
|
||||
onClick={handleCopyWeaponsFromPreviousMap({
|
||||
onPress={handleCopyWeaponsFromPreviousMap({
|
||||
groupMatchMapId,
|
||||
mapIndex: i,
|
||||
})}
|
||||
>
|
||||
{t("q:match.report.copyWeapons")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
) : null}
|
||||
<div className="stack sm">
|
||||
{playersToReport().map((member, j) => {
|
||||
|
|
@ -779,15 +779,15 @@ function BottomSection({
|
|||
submitButtonText={t("common:actions.cancel")}
|
||||
fetcher={cancelFetcher}
|
||||
>
|
||||
<Button
|
||||
<SendouButton
|
||||
variant="minimal-destructive"
|
||||
size="tiny"
|
||||
size="small"
|
||||
type="submit"
|
||||
disabled={ownTeamReported && !data.match.mapList[0].winnerGroupId}
|
||||
isDisabled={ownTeamReported && !data.match.mapList[0].winnerGroupId}
|
||||
className="build__small-text mt-4"
|
||||
>
|
||||
{t("q:match.cancelMatch")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</FormWithConfirm>
|
||||
) : null;
|
||||
|
||||
|
|
@ -1288,8 +1288,8 @@ function MapListMap({
|
|||
{typeof ownWeapon === "number" ? (
|
||||
<div className="font-bold stack sm horizontal">
|
||||
{t(`weapons:MAIN_${ownWeapon}`)}
|
||||
<Button
|
||||
size="tiny"
|
||||
<SendouButton
|
||||
size="small"
|
||||
icon={<CrossIcon />}
|
||||
variant="minimal-destructive"
|
||||
onClick={() => {
|
||||
|
|
|
|||
|
|
@ -4,13 +4,13 @@ import * as React from "react";
|
|||
import { useState } from "react";
|
||||
import { Trans, useTranslation } from "react-i18next";
|
||||
import { Avatar } from "~/components/Avatar";
|
||||
import { Button } from "~/components/Button";
|
||||
import { WeaponCombobox } from "~/components/Combobox";
|
||||
import { FormMessage } from "~/components/FormMessage";
|
||||
import { FormWithConfirm } from "~/components/FormWithConfirm";
|
||||
import { ModeImage, WeaponImage } from "~/components/Image";
|
||||
import { Main } from "~/components/Main";
|
||||
import { SubmitButton } from "~/components/SubmitButton";
|
||||
import { SendouButton } from "~/components/elements/Button";
|
||||
import { SendouSwitch } from "~/components/elements/Switch";
|
||||
import { CrossIcon } from "~/components/icons/Cross";
|
||||
import { MapIcon } from "~/components/icons/Map";
|
||||
|
|
@ -361,10 +361,10 @@ function Languages() {
|
|||
return (
|
||||
<div key={code} className="stack horizontal items-center sm">
|
||||
{name}{" "}
|
||||
<Button
|
||||
<SendouButton
|
||||
icon={<CrossIcon />}
|
||||
variant="minimal-destructive"
|
||||
onClick={() => {
|
||||
onPress={() => {
|
||||
const newLanguages = value.filter(
|
||||
(codeInArr) => codeInArr !== code,
|
||||
);
|
||||
|
|
@ -441,11 +441,11 @@ function WeaponPool() {
|
|||
/>
|
||||
</div>
|
||||
<div className="stack sm horizontal items-center justify-center">
|
||||
<Button
|
||||
<SendouButton
|
||||
icon={weapon.isFavorite ? <StarFilledIcon /> : <StarIcon />}
|
||||
variant="minimal"
|
||||
aria-label="Favorite weapon"
|
||||
onClick={() =>
|
||||
onPress={() =>
|
||||
setWeapons(
|
||||
weapons.map((w) =>
|
||||
w.weaponSplId === weapon.weaponSplId
|
||||
|
|
@ -458,19 +458,19 @@ function WeaponPool() {
|
|||
)
|
||||
}
|
||||
/>
|
||||
<Button
|
||||
<SendouButton
|
||||
icon={<TrashIcon />}
|
||||
variant="minimal-destructive"
|
||||
aria-label="Delete weapon"
|
||||
onClick={() =>
|
||||
onPress={() =>
|
||||
setWeapons(
|
||||
weapons.filter(
|
||||
(w) => w.weaponSplId !== weapon.weaponSplId,
|
||||
),
|
||||
)
|
||||
}
|
||||
testId={`delete-weapon-${weapon.weaponSplId}`}
|
||||
size="tiny"
|
||||
data-testid={`delete-weapon-${weapon.weaponSplId}`}
|
||||
size="small"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -640,14 +640,14 @@ function TrustedUsers() {
|
|||
]}
|
||||
submitButtonText="Remove"
|
||||
>
|
||||
<Button
|
||||
<SendouButton
|
||||
className="build__small-text"
|
||||
variant="minimal-destructive"
|
||||
size="tiny"
|
||||
size="small"
|
||||
type="submit"
|
||||
>
|
||||
<TrashIcon className="build__icon" />
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</FormWithConfirm>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import * as React from "react";
|
|||
import { Flipped } from "react-flip-toolkit";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Avatar } from "~/components/Avatar";
|
||||
import { Button, LinkButton } from "~/components/Button";
|
||||
import { LinkButton } from "~/components/Button";
|
||||
import { FormWithConfirm } from "~/components/FormWithConfirm";
|
||||
import { Image, ModeImage, TierImage, WeaponImage } from "~/components/Image";
|
||||
import { SubmitButton } from "~/components/SubmitButton";
|
||||
|
|
@ -187,7 +187,7 @@ export function GroupCard({
|
|||
<fetcher.Form className="stack items-center" method="post">
|
||||
<input type="hidden" name="targetGroupId" value={group.id} />
|
||||
<SubmitButton
|
||||
size="tiny"
|
||||
size="small"
|
||||
variant={action === "UNLIKE" ? "destructive" : "outlined"}
|
||||
_action={action}
|
||||
state={fetcher.state}
|
||||
|
|
@ -424,14 +424,14 @@ function MemberNote({
|
|||
<div className="text-lighter text-center text-xs mt-1">
|
||||
{note}{" "}
|
||||
{editable ? (
|
||||
<Button
|
||||
<SendouButton
|
||||
size="miniscule"
|
||||
variant="minimal"
|
||||
onClick={startEditing}
|
||||
onPress={startEditing}
|
||||
className="mt-2 ml-auto"
|
||||
>
|
||||
{t("q:looking.groups.editNote")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
|
|
@ -440,9 +440,9 @@ function MemberNote({
|
|||
if (!editable) return null;
|
||||
|
||||
return (
|
||||
<Button variant="minimal" size="miniscule" onClick={startEditing}>
|
||||
<SendouButton variant="minimal" size="miniscule" onPress={startEditing}>
|
||||
{t("q:looking.groups.addNote")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -478,13 +478,13 @@ function AddPrivateNoteForm({
|
|||
ref={textareaRef}
|
||||
/>
|
||||
<div className="stack horizontal justify-between">
|
||||
<Button
|
||||
<SendouButton
|
||||
variant="minimal-destructive"
|
||||
size="miniscule"
|
||||
onClick={stopEditing}
|
||||
onPress={stopEditing}
|
||||
>
|
||||
{t("common:actions.cancel")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
{newValueLegal ? (
|
||||
<SubmitButton
|
||||
_action="UPDATE_NOTE"
|
||||
|
|
@ -550,7 +550,7 @@ function DeletePrivateNoteForm({
|
|||
["_action", "DELETE_PRIVATE_USER_NOTE"],
|
||||
]}
|
||||
>
|
||||
<SubmitButton variant="minimal-destructive" size="tiny" type="submit">
|
||||
<SubmitButton variant="minimal-destructive" size="small" type="submit">
|
||||
<TrashIcon className="build__icon" />
|
||||
</SubmitButton>
|
||||
</FormWithConfirm>
|
||||
|
|
@ -677,7 +677,7 @@ function MemberRoleManager({
|
|||
{member.role === "REGULAR" ? (
|
||||
<SubmitButton
|
||||
variant="outlined"
|
||||
size="tiny"
|
||||
size="small"
|
||||
_action="GIVE_MANAGER"
|
||||
state={fetcher.state}
|
||||
>
|
||||
|
|
@ -687,7 +687,7 @@ function MemberRoleManager({
|
|||
{member.role === "MANAGER" ? (
|
||||
<SubmitButton
|
||||
variant="destructive"
|
||||
size="tiny"
|
||||
size="small"
|
||||
_action="REMOVE_MANAGER"
|
||||
state={fetcher.state}
|
||||
>
|
||||
|
|
@ -697,7 +697,7 @@ function MemberRoleManager({
|
|||
{enableKicking && member.id !== loggedInUser?.id ? (
|
||||
<SubmitButton
|
||||
variant="destructive"
|
||||
size="tiny"
|
||||
size="small"
|
||||
_action="KICK_FROM_GROUP"
|
||||
state={fetcher.state}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { useFetcher } from "@remix-run/react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Button } from "~/components/Button";
|
||||
import { FormWithConfirm } from "~/components/FormWithConfirm";
|
||||
import { SubmitButton } from "~/components/SubmitButton";
|
||||
import { SendouButton } from "~/components/elements/Button";
|
||||
import { SENDOUQ_LOOKING_PAGE } from "~/utils/urls";
|
||||
|
||||
export function GroupLeaver({
|
||||
|
|
@ -21,9 +21,9 @@ export function GroupLeaver({
|
|||
submitButtonText="Leave"
|
||||
action={SENDOUQ_LOOKING_PAGE}
|
||||
>
|
||||
<Button variant="minimal-destructive" size="tiny">
|
||||
<SendouButton variant="minimal-destructive" size="small">
|
||||
{t("q:looking.groups.actions.leaveGroup")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</FormWithConfirm>
|
||||
);
|
||||
}
|
||||
|
|
@ -34,7 +34,7 @@ export function GroupLeaver({
|
|||
<SubmitButton
|
||||
_action="LEAVE_GROUP"
|
||||
variant="minimal-destructive"
|
||||
size="tiny"
|
||||
size="small"
|
||||
state={fetcher.state}
|
||||
>
|
||||
{type === "LEAVE_Q"
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ import { useFetcher } from "@remix-run/react";
|
|||
import * as React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useCopyToClipboard } from "react-use";
|
||||
import { Button } from "~/components/Button";
|
||||
import { SubmitButton } from "~/components/SubmitButton";
|
||||
import { SendouButton } from "~/components/elements/Button";
|
||||
import { CheckmarkIcon } from "~/components/icons/Checkmark";
|
||||
import { ClipboardIcon } from "~/components/icons/Clipboard";
|
||||
import { PlusIcon } from "~/components/icons/Plus";
|
||||
|
|
@ -58,9 +58,9 @@ export function MemberAdder({
|
|||
id="invite"
|
||||
className="q__member-adder__input"
|
||||
/>
|
||||
<Button
|
||||
<SendouButton
|
||||
variant={copySuccess ? "outlined-success" : "outlined"}
|
||||
onClick={() => copyToClipboard(inviteLink)}
|
||||
onPress={() => copyToClipboard(inviteLink)}
|
||||
icon={copySuccess ? <CheckmarkIcon /> : <ClipboardIcon />}
|
||||
aria-label="Copy to clipboard"
|
||||
/>
|
||||
|
|
@ -75,8 +75,8 @@ export function MemberAdder({
|
|||
/>
|
||||
<SubmitButton
|
||||
variant="outlined"
|
||||
_action="ADD_TRUSTED"
|
||||
disabled={!truster}
|
||||
_action="ADD_MEMBER"
|
||||
isDisabled={!truster}
|
||||
icon={<PlusIcon />}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ import {
|
|||
} from "~/utils/urls";
|
||||
import "../q.css";
|
||||
import type { MetaFunction } from "@remix-run/node";
|
||||
import { Button } from "~/components/Button";
|
||||
import { Image } from "~/components/Image";
|
||||
import { SendouButton } from "~/components/elements/Button";
|
||||
import { MATCHES_COUNT_NEEDED_FOR_LEADERBOARD } from "~/features/leaderboards/leaderboards-constants";
|
||||
import { USER_LEADERBOARD_MIN_ENTRIES_FOR_LEVIATHAN } from "~/features/mmr/mmr-constants";
|
||||
import { metaTags } from "~/utils/remix";
|
||||
|
|
@ -57,18 +57,21 @@ function TableOfContents() {
|
|||
<h2>Table of contents</h2>
|
||||
<ul>
|
||||
<li>
|
||||
<Button onClick={handleTitleClick("general-info")} variant="minimal">
|
||||
<SendouButton
|
||||
onPress={handleTitleClick("general-info")}
|
||||
variant="minimal"
|
||||
>
|
||||
General info
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<Button
|
||||
onClick={handleTitleClick("before-joining")}
|
||||
<SendouButton
|
||||
onPress={handleTitleClick("before-joining")}
|
||||
variant="minimal"
|
||||
>
|
||||
Before joining
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</li>
|
||||
<li>Make a sendou.ink account</li>
|
||||
<li>Select your map pool</li>
|
||||
|
|
@ -80,23 +83,23 @@ function TableOfContents() {
|
|||
<li>Reading rules</li>
|
||||
|
||||
<li>
|
||||
<Button
|
||||
onClick={handleTitleClick("joining-the-queue")}
|
||||
<SendouButton
|
||||
onPress={handleTitleClick("joining-the-queue")}
|
||||
variant="minimal"
|
||||
>
|
||||
Joining the queue
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</li>
|
||||
<li>Joining solo</li>
|
||||
<li>Joining with 1-3 mates</li>
|
||||
|
||||
<li>
|
||||
<Button
|
||||
onClick={handleTitleClick("finding-a-group")}
|
||||
<SendouButton
|
||||
onPress={handleTitleClick("finding-a-group")}
|
||||
variant="minimal"
|
||||
>
|
||||
Finding a group
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</li>
|
||||
<li>Plus Server icons</li>
|
||||
<li>Adding a note</li>
|
||||
|
|
@ -104,22 +107,22 @@ function TableOfContents() {
|
|||
<li>Group managers</li>
|
||||
|
||||
<li>
|
||||
<Button
|
||||
onClick={handleTitleClick("finding-an-opponent")}
|
||||
<SendouButton
|
||||
onPress={handleTitleClick("finding-an-opponent")}
|
||||
variant="minimal"
|
||||
>
|
||||
Finding an opponent
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</li>
|
||||
<li>Rechallenging</li>
|
||||
|
||||
<li>
|
||||
<Button
|
||||
onClick={handleTitleClick("playing-the-match")}
|
||||
<SendouButton
|
||||
onPress={handleTitleClick("playing-the-match")}
|
||||
variant="minimal"
|
||||
>
|
||||
Playing the match
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</li>
|
||||
<li>Canceling the match</li>
|
||||
<li>Enemy not reporting</li>
|
||||
|
|
@ -128,9 +131,12 @@ function TableOfContents() {
|
|||
<li>Stats</li>
|
||||
|
||||
<li>
|
||||
<Button onClick={handleTitleClick("other-topics")} variant="minimal">
|
||||
<SendouButton
|
||||
onPress={handleTitleClick("other-topics")}
|
||||
variant="minimal"
|
||||
>
|
||||
Other topics
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</li>
|
||||
<li>Ranking algorithm</li>
|
||||
<li>Ranking tiers</li>
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ function InfoText() {
|
|||
>
|
||||
{t("q:looking.inactiveGroup")}{" "}
|
||||
<SubmitButton
|
||||
size="tiny"
|
||||
size="small"
|
||||
variant="minimal"
|
||||
_action="REFRESH_GROUP"
|
||||
state={fetcher.state}
|
||||
|
|
@ -124,7 +124,7 @@ function InfoText() {
|
|||
>
|
||||
{t("q:looking.inactiveGroup.soon")}{" "}
|
||||
<SubmitButton
|
||||
size="tiny"
|
||||
size="small"
|
||||
variant="minimal"
|
||||
_action="REFRESH_GROUP"
|
||||
state={fetcher.state}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import clsx from "clsx";
|
|||
import * as React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Alert } from "~/components/Alert";
|
||||
import { Button, LinkButton } from "~/components/Button";
|
||||
import { LinkButton } from "~/components/Button";
|
||||
import { Flag } from "~/components/Flag";
|
||||
import { FormMessage } from "~/components/FormMessage";
|
||||
import { FriendCodeInput } from "~/components/FriendCodeInput";
|
||||
|
|
@ -116,7 +116,7 @@ export default function QPage() {
|
|||
<div className="stack horizontal md items-center mt-4 mx-auto">
|
||||
<SubmitButton
|
||||
icon={<UsersIcon />}
|
||||
disabled={queueJoinStatus !== "NOW"}
|
||||
isDisabled={queueJoinStatus !== "NOW"}
|
||||
>
|
||||
{t("q:front.actions.joinWithGroup")}
|
||||
</SubmitButton>
|
||||
|
|
@ -126,7 +126,7 @@ export default function QPage() {
|
|||
state={fetcher.state}
|
||||
icon={<UserIcon />}
|
||||
variant="outlined"
|
||||
disabled={queueJoinStatus !== "NOW"}
|
||||
isDisabled={queueJoinStatus !== "NOW"}
|
||||
>
|
||||
{t("q:front.actions.joinSolo")}
|
||||
</SubmitButton>
|
||||
|
|
@ -160,9 +160,9 @@ export default function QPage() {
|
|||
action={LOG_IN_URL}
|
||||
method="post"
|
||||
>
|
||||
<Button size="big" type="submit">
|
||||
<SendouButton size="big" type="submit">
|
||||
{t("q:front.actions.logIn")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</form>
|
||||
)}
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import type { MetaFunction } from "@remix-run/node";
|
|||
import { useFetcher, useNavigate, useSearchParams } from "@remix-run/react";
|
||||
import * as React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Button } from "~/components/Button";
|
||||
import { FormMessage } from "~/components/FormMessage";
|
||||
import { Label } from "~/components/Label";
|
||||
import { Main } from "~/components/Main";
|
||||
|
|
@ -229,9 +228,9 @@ function PushNotificationsEnabler() {
|
|||
: t("common:settings.notifications.permissionDenied")}
|
||||
</SendouPopover>
|
||||
) : (
|
||||
<Button size="tiny" variant="minimal" onClick={askPermission}>
|
||||
<SendouButton size="small" variant="minimal" onPress={askPermission}>
|
||||
{t("common:actions.enable")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
)}
|
||||
<FormMessage type="info">
|
||||
{t("common:settings.notifications.description")}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import type { MetaFunction, SerializeFrom } from "@remix-run/node";
|
|||
import { Form, Link, useLoaderData } from "@remix-run/react";
|
||||
import * as React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Button } from "~/components/Button";
|
||||
import { CustomizedColorsInput } from "~/components/CustomizedColorsInput";
|
||||
import { FormErrors } from "~/components/FormErrors";
|
||||
import { FormMessage } from "~/components/FormMessage";
|
||||
|
|
@ -11,6 +10,7 @@ import { Input } from "~/components/Input";
|
|||
import { Label } from "~/components/Label";
|
||||
import { Main } from "~/components/Main";
|
||||
import { SubmitButton } from "~/components/SubmitButton";
|
||||
import { SendouButton } from "~/components/elements/Button";
|
||||
import { useUser } from "~/features/auth/core/user";
|
||||
import type { SendouRouteHandle } from "~/utils/remix.server";
|
||||
import {
|
||||
|
|
@ -69,13 +69,13 @@ export default function EditTeamPage() {
|
|||
dialogHeading={t("team:deleteTeam.header", { teamName: team.name })}
|
||||
fields={[["_action", "DELETE_TEAM"]]}
|
||||
>
|
||||
<Button
|
||||
<SendouButton
|
||||
className="ml-auto"
|
||||
variant="minimal-destructive"
|
||||
data-testid="delete-team-button"
|
||||
>
|
||||
{t("team:actionButtons.deleteTeam")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</FormWithConfirm>
|
||||
) : null}
|
||||
<Form method="post" className="stack md items-start">
|
||||
|
|
@ -150,9 +150,9 @@ function ImageRemoveButtons() {
|
|||
fields={[["_action", "DELETE_AVATAR"]]}
|
||||
submitButtonText={t("common:actions.remove")}
|
||||
>
|
||||
<Button className="ml-auto" variant="minimal-destructive">
|
||||
<SendouButton className="ml-auto" variant="minimal-destructive">
|
||||
{t("team:actionButtons.deleteTeam.profilePicture")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</FormWithConfirm>
|
||||
</li>
|
||||
) : null}
|
||||
|
|
@ -165,9 +165,9 @@ function ImageRemoveButtons() {
|
|||
fields={[["_action", "DELETE_BANNER"]]}
|
||||
submitButtonText={t("common:actions.remove")}
|
||||
>
|
||||
<Button className="ml-auto" variant="minimal-destructive">
|
||||
<SendouButton className="ml-auto" variant="minimal-destructive">
|
||||
{t("team:actionButtons.deleteTeam.banner")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</FormWithConfirm>
|
||||
</li>
|
||||
) : null}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import * as React from "react";
|
|||
import { useTranslation } from "react-i18next";
|
||||
import { useCopyToClipboard } from "react-use";
|
||||
import { Alert } from "~/components/Alert";
|
||||
import { Button } from "~/components/Button";
|
||||
import { FormWithConfirm } from "~/components/FormWithConfirm";
|
||||
import { Main } from "~/components/Main";
|
||||
import { SubmitButton } from "~/components/SubmitButton";
|
||||
|
|
@ -110,13 +109,16 @@ function InviteCodeSection() {
|
|||
{inviteLink}
|
||||
</div>
|
||||
<Form method="post" className="stack horizontal md">
|
||||
<Button size="tiny" onClick={() => copyToClipboard(inviteLink)}>
|
||||
<SendouButton
|
||||
size="small"
|
||||
onPress={() => copyToClipboard(inviteLink)}
|
||||
>
|
||||
{t("common:actions.copyToClipboard")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
<SubmitButton
|
||||
variant="minimal-destructive"
|
||||
_action="RESET_INVITE_LINK"
|
||||
size="tiny"
|
||||
size="small"
|
||||
testId="reset-invite-link-button"
|
||||
>
|
||||
{t("common:actions.reset")}
|
||||
|
|
@ -243,14 +245,14 @@ function MemberRow({
|
|||
["userId", member.id],
|
||||
]}
|
||||
>
|
||||
<Button
|
||||
size="tiny"
|
||||
<SendouButton
|
||||
size="small"
|
||||
variant="destructive"
|
||||
icon={<TrashIcon />}
|
||||
testId={!isSelf ? "kick-button" : undefined}
|
||||
data-testid={!isSelf ? "kick-button" : undefined}
|
||||
>
|
||||
{t("team:actionButtons.kick")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</FormWithConfirm>
|
||||
</div>
|
||||
<hr className="team__roster__separator" />
|
||||
|
|
|
|||
|
|
@ -5,12 +5,13 @@ import React from "react";
|
|||
import { useTranslation } from "react-i18next";
|
||||
import * as R from "remeda";
|
||||
import { Avatar } from "~/components/Avatar";
|
||||
import { Button, LinkButton } from "~/components/Button";
|
||||
import { LinkButton } from "~/components/Button";
|
||||
import { Flag } from "~/components/Flag";
|
||||
import { FormWithConfirm } from "~/components/FormWithConfirm";
|
||||
import { WeaponImage } from "~/components/Image";
|
||||
import { Main } from "~/components/Main";
|
||||
import { SubmitButton } from "~/components/SubmitButton";
|
||||
import { SendouButton } from "~/components/elements/Button";
|
||||
import { BskyIcon } from "~/components/icons/Bsky";
|
||||
import { EditIcon } from "~/components/icons/Edit";
|
||||
import { StarIcon } from "~/components/icons/Star";
|
||||
|
|
@ -221,13 +222,13 @@ function ActionButtons() {
|
|||
submitButtonText={t("team:actionButtons.leaveTeam.confirm")}
|
||||
fields={[["_action", "LEAVE_TEAM"]]}
|
||||
>
|
||||
<Button
|
||||
size="tiny"
|
||||
<SendouButton
|
||||
size="small"
|
||||
variant="destructive"
|
||||
data-testid="leave-team-button"
|
||||
>
|
||||
{t("team:actionButtons.leaveTeam")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</FormWithConfirm>
|
||||
) : null}
|
||||
{isTeamManager({ user, team }) || isAdmin ? (
|
||||
|
|
@ -266,7 +267,7 @@ function ChangeMainTeamButton() {
|
|||
<fetcher.Form method="post">
|
||||
<SubmitButton
|
||||
_action="MAKE_MAIN_TEAM"
|
||||
size="tiny"
|
||||
size="small"
|
||||
variant="outlined"
|
||||
icon={<StarIcon />}
|
||||
testId="make-main-team-button"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { Link, useFetcher } from "@remix-run/react";
|
||||
import clsx from "clsx";
|
||||
import * as React from "react";
|
||||
import { Button } from "../../../../components/Button";
|
||||
import { SendouButton } from "../../../../components/elements/Button";
|
||||
import { CheckmarkIcon } from "../../../../components/icons/Checkmark";
|
||||
import { CrossIcon } from "../../../../components/icons/Cross";
|
||||
import { EditIcon } from "../../../../components/icons/Edit";
|
||||
|
|
@ -306,19 +306,17 @@ function EditableDestination({
|
|||
</td>
|
||||
<td>
|
||||
<div className="stack horizontal xs">
|
||||
<Button
|
||||
<SendouButton
|
||||
variant="minimal"
|
||||
title="Save destination"
|
||||
icon={<CheckmarkIcon />}
|
||||
size="tiny"
|
||||
onClick={handleSubmit}
|
||||
icon={<CheckmarkIcon title="Save destination" />}
|
||||
size="small"
|
||||
onPress={handleSubmit}
|
||||
/>
|
||||
<Button
|
||||
<SendouButton
|
||||
variant="minimal-destructive"
|
||||
title="Cancel"
|
||||
size="tiny"
|
||||
icon={<CrossIcon />}
|
||||
onClick={() => setEditingDestination(false)}
|
||||
size="small"
|
||||
icon={<CrossIcon title="Cancel" />}
|
||||
onPress={() => setEditingDestination(false)}
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
|
|
@ -347,12 +345,11 @@ function EditableDestination({
|
|||
)}
|
||||
{canEditDestination ? (
|
||||
<td>
|
||||
<Button
|
||||
<SendouButton
|
||||
variant="minimal"
|
||||
title="Edit destination"
|
||||
icon={<EditIcon />}
|
||||
size="tiny"
|
||||
onClick={() => setEditingDestination(true)}
|
||||
icon={<EditIcon title="Edit destination" />}
|
||||
size="small"
|
||||
onPress={() => setEditingDestination(true)}
|
||||
/>
|
||||
</td>
|
||||
) : null}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { useFetcher } from "@remix-run/react";
|
||||
import clsx from "clsx";
|
||||
import { Button } from "~/components/Button";
|
||||
import { FormWithConfirm } from "~/components/FormWithConfirm";
|
||||
import { SubmitButton } from "~/components/SubmitButton";
|
||||
import { SendouButton } from "~/components/elements/Button";
|
||||
import { useUser } from "~/features/auth/core/user";
|
||||
import {
|
||||
useBracketExpanded,
|
||||
|
|
@ -102,7 +102,7 @@ export function SwissBracket({
|
|||
{groups.length > 1 && (
|
||||
<div className="stack horizontal">
|
||||
{groups.map((g) => (
|
||||
<Button
|
||||
<SendouButton
|
||||
key={g.groupId}
|
||||
onClick={() => setSelectedGroupId(g.groupId)}
|
||||
className={clsx(
|
||||
|
|
@ -112,10 +112,10 @@ export function SwissBracket({
|
|||
selectedGroupId === g.groupId,
|
||||
},
|
||||
)}
|
||||
testId={`group-${g.groupName.split(" ")[1]}-button`}
|
||||
data-testid={`group-${g.groupName.split(" ")[1]}-button`}
|
||||
>
|
||||
{g.groupName.split(" ")[1]}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -190,15 +190,15 @@ export function SwissBracket({
|
|||
["_action", "UNADVANCE_BRACKET"],
|
||||
]}
|
||||
>
|
||||
<Button
|
||||
<SendouButton
|
||||
variant="minimal-destructive"
|
||||
type="submit"
|
||||
className="build__small-text mb-4"
|
||||
size="tiny"
|
||||
testId="reset-round-button"
|
||||
size="small"
|
||||
data-testid="reset-round-button"
|
||||
>
|
||||
Reset round
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</FormWithConfirm>
|
||||
) : null}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import { type FetcherWithComponents, Link, useFetcher } from "@remix-run/react";
|
|||
import clsx from "clsx";
|
||||
import * as React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Button } from "~/components/Button";
|
||||
import { ModeImage, StageImage } from "~/components/Image";
|
||||
import { Label } from "~/components/Label";
|
||||
import { SubmitButton } from "~/components/SubmitButton";
|
||||
|
|
@ -435,11 +434,11 @@ export function BracketMapListDialog({
|
|||
) : null}
|
||||
</div>
|
||||
{tournament.ctx.toSetMapPool.length > 0 ? (
|
||||
<Button
|
||||
size="tiny"
|
||||
<SendouButton
|
||||
size="small"
|
||||
icon={<RefreshArrowsIcon />}
|
||||
variant="outlined"
|
||||
onClick={() =>
|
||||
onPress={() =>
|
||||
setMaps(
|
||||
generateTournamentRoundMaplist({
|
||||
mapCounts,
|
||||
|
|
@ -454,7 +453,7 @@ export function BracketMapListDialog({
|
|||
}
|
||||
>
|
||||
Reroll all maps
|
||||
</Button>
|
||||
</SendouButton>
|
||||
) : null}
|
||||
</div>
|
||||
{needsToPickEliminationTeamCount ? (
|
||||
|
|
@ -592,7 +591,7 @@ export function BracketMapListDialog({
|
|||
) : (
|
||||
<SubmitButton
|
||||
variant="outlined"
|
||||
size="tiny"
|
||||
size="small"
|
||||
testId="confirm-finalize-bracket-button"
|
||||
_action={isPreparing ? "PREPARE_MAPS" : "START_BRACKET"}
|
||||
className="mx-auto"
|
||||
|
|
@ -894,13 +893,13 @@ function RoundMapList({
|
|||
<div>
|
||||
<h3 className="stack horizontal sm">
|
||||
<div>{name}</div>{" "}
|
||||
<Button
|
||||
<SendouButton
|
||||
variant={editing ? "minimal-success" : "minimal"}
|
||||
onClick={() => setEditing(!editing)}
|
||||
testId="edit-round-maps-button"
|
||||
onPress={() => setEditing(!editing)}
|
||||
data-testid="edit-round-maps-button"
|
||||
>
|
||||
{editing ? "Save" : "Edit"}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</h3>
|
||||
{unlink ? (
|
||||
<SendouButton
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { Form, useFetcher, useLoaderData } from "@remix-run/react";
|
||||
import * as React from "react";
|
||||
import { Button } from "~/components/Button";
|
||||
import { Label } from "~/components/Label";
|
||||
import { SubmitButton } from "~/components/SubmitButton";
|
||||
import { SendouButton } from "~/components/elements/Button";
|
||||
import { EditIcon } from "~/components/icons/Edit";
|
||||
import { useUser } from "~/features/auth/core/user";
|
||||
import { useTournament } from "~/features/tournament/routes/to.$id";
|
||||
|
|
@ -336,10 +336,10 @@ function ReportScoreButtons({
|
|||
</div>
|
||||
) : null}
|
||||
<SubmitButton
|
||||
size="tiny"
|
||||
size="small"
|
||||
_action="REPORT_SCORE"
|
||||
testId="report-score-button"
|
||||
disabled={submitButtonDisabled()}
|
||||
isDisabled={submitButtonDisabled()}
|
||||
>
|
||||
{wouldEndSet ? "Report & end set" : "Report"}
|
||||
</SubmitButton>
|
||||
|
|
@ -380,37 +380,37 @@ function EditScoreForm({
|
|||
<input type="hidden" name="points" value={JSON.stringify(points)} />
|
||||
) : undefined}
|
||||
<SubmitButton
|
||||
size="tiny"
|
||||
size="small"
|
||||
state={fetcher.state}
|
||||
_action="UPDATE_REPORTED_SCORE"
|
||||
disabled={submitDisabled}
|
||||
isDisabled={submitDisabled}
|
||||
testId="save-revise-button"
|
||||
>
|
||||
Save
|
||||
</SubmitButton>
|
||||
<Button
|
||||
<SendouButton
|
||||
variant="destructive"
|
||||
size="tiny"
|
||||
size="small"
|
||||
onClick={() => setEditing(false)}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</fetcher.Form>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="mt-6">
|
||||
<Button
|
||||
<SendouButton
|
||||
icon={<EditIcon />}
|
||||
variant="outlined"
|
||||
size="tiny"
|
||||
size="small"
|
||||
className="mx-auto"
|
||||
onClick={() => setEditing(true)}
|
||||
testId="revise-button"
|
||||
data-testid="revise-button"
|
||||
>
|
||||
Edit
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import type { SerializeFrom } from "@remix-run/node";
|
|||
import type { TFunction } from "i18next";
|
||||
import * as React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Button } from "~/components/Button";
|
||||
import { SendouButton } from "~/components/elements/Button";
|
||||
import { SendouDialog } from "~/components/elements/Dialog";
|
||||
import { MapIcon } from "~/components/icons/Map";
|
||||
import { useTournament } from "~/features/tournament/routes/to.$id";
|
||||
|
|
@ -102,14 +102,14 @@ export function OrganizerMatchMapListDialog({
|
|||
</div>
|
||||
) : null}
|
||||
</SendouDialog>
|
||||
<Button
|
||||
<SendouButton
|
||||
variant="outlined"
|
||||
size="tiny"
|
||||
size="small"
|
||||
icon={<MapIcon />}
|
||||
onClick={() => setIsOpen(true)}
|
||||
>
|
||||
Show maplist
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@ import { Link, useFetcher, useLoaderData } from "@remix-run/react";
|
|||
import clsx from "clsx";
|
||||
import * as React from "react";
|
||||
import { Avatar } from "~/components/Avatar";
|
||||
import { Button } from "~/components/Button";
|
||||
import { Label } from "~/components/Label";
|
||||
import { SubmitButton } from "~/components/SubmitButton";
|
||||
import { SendouButton } from "~/components/elements/Button";
|
||||
import { useUser } from "~/features/auth/core/user";
|
||||
import { inGameNameWithoutDiscriminator } from "~/utils/strings";
|
||||
import { tournamentTeamPage, userPage } from "~/utils/urls";
|
||||
|
|
@ -491,15 +491,15 @@ function RosterFormWithButtons({
|
|||
if (!editingRoster) {
|
||||
return (
|
||||
<div className="tournament-bracket__roster-buttons__container">
|
||||
<Button
|
||||
size="tiny"
|
||||
<SendouButton
|
||||
size="small"
|
||||
onClick={() => setEditingRoster(true)}
|
||||
className="tournament-bracket__edit-roster-button"
|
||||
variant="minimal"
|
||||
testId="edit-active-roster-button"
|
||||
data-testid="edit-active-roster-button"
|
||||
>
|
||||
Edit active roster
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -517,23 +517,23 @@ function RosterFormWithButtons({
|
|||
<input type="hidden" name="teamId" value={teamId} />
|
||||
<SubmitButton
|
||||
state={fetcher.state}
|
||||
size="tiny"
|
||||
size="small"
|
||||
_action="SET_ACTIVE_ROSTER"
|
||||
disabled={!valid}
|
||||
isDisabled={!valid}
|
||||
testId="save-active-roster-button"
|
||||
>
|
||||
Save
|
||||
</SubmitButton>
|
||||
{showCancelButton ? (
|
||||
<Button
|
||||
size="tiny"
|
||||
<SendouButton
|
||||
size="small"
|
||||
variant="destructive"
|
||||
onClick={() => {
|
||||
setEditingRoster(false);
|
||||
}}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
</SendouButton>
|
||||
) : null}
|
||||
</fetcher.Form>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ export function TournamentTeamActions() {
|
|||
<input type="hidden" name="bracketIdx" value={status.bracketIdx} />
|
||||
{status.canCheckIn ? (
|
||||
<SubmitButton
|
||||
size="tiny"
|
||||
size="small"
|
||||
variant="minimal"
|
||||
_action="CHECK_IN"
|
||||
state={fetcher.state}
|
||||
|
|
@ -85,7 +85,7 @@ export function TournamentTeamActions() {
|
|||
<fetcher.Form method="post">
|
||||
<input type="hidden" name="bracketIdx" value={status.bracketIdx} />
|
||||
<SubmitButton
|
||||
size="tiny"
|
||||
size="small"
|
||||
variant="minimal"
|
||||
_action="BRACKET_CHECK_IN"
|
||||
state={fetcher.state}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import { useTranslation } from "react-i18next";
|
|||
import { useCopyToClipboard } from "react-use";
|
||||
import { useEventSource } from "remix-utils/sse/react";
|
||||
import { Alert } from "~/components/Alert";
|
||||
import { Button } from "~/components/Button";
|
||||
import { Divider } from "~/components/Divider";
|
||||
import { FormWithConfirm } from "~/components/FormWithConfirm";
|
||||
import { SendouButton } from "~/components/elements/Button";
|
||||
|
|
@ -172,9 +171,12 @@ export default function TournamentBracketsPage() {
|
|||
submitButtonText={t("tournament:actions.finalize.action")}
|
||||
submitButtonVariant="outlined"
|
||||
>
|
||||
<Button variant="minimal" testId="finalize-tournament-button">
|
||||
<SendouButton
|
||||
variant="minimal"
|
||||
data-testid="finalize-tournament-button"
|
||||
>
|
||||
{t("tournament:actions.finalize.question")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</FormWithConfirm>
|
||||
</div>
|
||||
) : null}
|
||||
|
|
@ -325,14 +327,14 @@ function BracketStarter({
|
|||
key={bracketIdx}
|
||||
/>
|
||||
) : null}
|
||||
<Button
|
||||
<SendouButton
|
||||
variant="outlined"
|
||||
size="tiny"
|
||||
testId="finalize-bracket-button"
|
||||
onClick={() => setDialogOpen(true)}
|
||||
size="small"
|
||||
data-testid="finalize-bracket-button"
|
||||
onPress={() => setDialogOpen(true)}
|
||||
>
|
||||
Start the bracket
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
@ -380,15 +382,15 @@ function MapPreparer({
|
|||
testId="prepared-maps-check-icon"
|
||||
/>
|
||||
) : null}
|
||||
<Button
|
||||
size="tiny"
|
||||
<SendouButton
|
||||
size="small"
|
||||
variant="outlined"
|
||||
icon={<MapIcon />}
|
||||
onClick={() => setDialogOpen(true)}
|
||||
testId="prepare-maps-button"
|
||||
onPress={() => setDialogOpen(true)}
|
||||
data-testid="prepare-maps-button"
|
||||
>
|
||||
Prepare maps
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
|
@ -424,15 +426,15 @@ function AddSubsPopOver() {
|
|||
<Divider className="my-2" />
|
||||
<div>{t("tournament:actions.shareLink", { inviteLink })}</div>
|
||||
<div className="my-2 flex justify-center">
|
||||
<Button
|
||||
size="tiny"
|
||||
onClick={() => copyToClipboard(inviteLink)}
|
||||
<SendouButton
|
||||
size="small"
|
||||
onPress={() => copyToClipboard(inviteLink)}
|
||||
variant="minimal"
|
||||
className="tiny"
|
||||
testId="copy-invite-link-button"
|
||||
data-testid="copy-invite-link-button"
|
||||
>
|
||||
{t("common:actions.copyToClipboard")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</div>
|
||||
</>
|
||||
) : null}
|
||||
|
|
@ -522,16 +524,16 @@ function BracketNav({
|
|||
<div className="tournament-bracket__bracket-nav tournament-bracket__button-row">
|
||||
{visibleBrackets.map((bracket, i) => {
|
||||
return (
|
||||
<Button
|
||||
<SendouButton
|
||||
key={bracket.name}
|
||||
onClick={() => setBracketIdx(i)}
|
||||
onPress={() => setBracketIdx(i)}
|
||||
className={clsx("tournament-bracket__bracket-nav__link", {
|
||||
"tournament-bracket__bracket-nav__link__selected":
|
||||
bracketIdx === i,
|
||||
})}
|
||||
>
|
||||
{bracketNameForButton(bracket.name)}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
|
@ -543,14 +545,14 @@ function CompactifyButton() {
|
|||
const { bracketExpanded, setBracketExpanded } = useBracketExpanded();
|
||||
|
||||
return (
|
||||
<Button
|
||||
onClick={() => {
|
||||
<SendouButton
|
||||
onPress={() => {
|
||||
setBracketExpanded(!bracketExpanded);
|
||||
}}
|
||||
className="tournament-bracket__compactify-button"
|
||||
icon={bracketExpanded ? <EyeSlashIcon /> : <EyeIcon />}
|
||||
>
|
||||
{bracketExpanded ? "Compactify" : "Show all"}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -509,7 +509,7 @@
|
|||
border-radius: var(--rounded);
|
||||
}
|
||||
|
||||
.tournament-bracket__compactify-button .button-icon {
|
||||
.tournament-bracket__compactify-button svg {
|
||||
width: 0.85rem;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import { Form, useLoaderData } from "@remix-run/react";
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Button } from "~/components/Button";
|
||||
import { WeaponCombobox } from "~/components/Combobox";
|
||||
import { FormMessage } from "~/components/FormMessage";
|
||||
import { WeaponImage } from "~/components/Image";
|
||||
|
|
@ -13,6 +12,7 @@ import { useUser } from "~/features/auth/core/user";
|
|||
import type { MainWeaponId } from "~/modules/in-game-lists/types";
|
||||
import type { SendouRouteHandle } from "~/utils/remix.server";
|
||||
import { TOURNAMENT_SUB } from "../tournament-subs-constants";
|
||||
import { SendouButton } from "~/components/elements/Button";
|
||||
|
||||
import { action } from "../actions/to.$id.subs.new.server";
|
||||
import { loader } from "../loaders/to.$id.subs.new.server";
|
||||
|
|
@ -262,11 +262,11 @@ function WeaponPoolSelect({
|
|||
height={38}
|
||||
/>
|
||||
</div>
|
||||
<Button
|
||||
<SendouButton
|
||||
icon={<TrashIcon />}
|
||||
variant="minimal-destructive"
|
||||
aria-label="Delete weapon"
|
||||
onClick={() =>
|
||||
onPress={() =>
|
||||
setWeapons(weapons.filter((w) => w !== weapon))
|
||||
}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { Link, useLoaderData } from "@remix-run/react";
|
|||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Avatar } from "~/components/Avatar";
|
||||
import { Button, LinkButton } from "~/components/Button";
|
||||
import { LinkButton } from "~/components/Button";
|
||||
import { Flag } from "~/components/Flag";
|
||||
import { FormWithConfirm } from "~/components/FormWithConfirm";
|
||||
import { WeaponImage } from "~/components/Image";
|
||||
|
|
@ -158,14 +158,14 @@ function SubInfoSection({ sub }: { sub: SubByTournamentId }) {
|
|||
}
|
||||
fields={[["userId", sub.userId]]}
|
||||
>
|
||||
<Button
|
||||
<SendouButton
|
||||
variant="minimal-destructive"
|
||||
size="tiny"
|
||||
size="small"
|
||||
type="submit"
|
||||
icon={<TrashIcon />}
|
||||
>
|
||||
{t("common:actions.delete")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</FormWithConfirm>
|
||||
</div>
|
||||
) : null}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import clsx from "clsx";
|
|||
import * as React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Avatar } from "~/components/Avatar";
|
||||
import { Button, LinkButton } from "~/components/Button";
|
||||
import { LinkButton } from "~/components/Button";
|
||||
import { Divider } from "~/components/Divider";
|
||||
import { FormMessage } from "~/components/FormMessage";
|
||||
import { FormWithConfirm } from "~/components/FormWithConfirm";
|
||||
|
|
@ -30,9 +30,9 @@ import {
|
|||
} from "~/utils/urls";
|
||||
import { BracketProgressionSelector } from "../../calendar/components/BracketProgressionSelector";
|
||||
import { useTournament } from "./to.$id";
|
||||
import { SendouButton } from "~/components/elements/Button";
|
||||
|
||||
import { action } from "../actions/to.$id.admin.server";
|
||||
export { action };
|
||||
export { action } from "../actions/to.$id.admin.server";
|
||||
|
||||
export default function TournamentAdminPage() {
|
||||
const { t } = useTranslation(["calendar"]);
|
||||
|
|
@ -70,14 +70,14 @@ export default function TournamentAdminPage() {
|
|||
action={calendarEventPage(tournament.ctx.eventId)}
|
||||
submitButtonTestId="delete-submit-button"
|
||||
>
|
||||
<Button
|
||||
<SendouButton
|
||||
className="ml-auto"
|
||||
size="tiny"
|
||||
size="small"
|
||||
variant="minimal-destructive"
|
||||
type="submit"
|
||||
>
|
||||
{t("calendar:actions.delete")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</FormWithConfirm>
|
||||
) : null}
|
||||
</div>
|
||||
|
|
@ -86,14 +86,14 @@ export default function TournamentAdminPage() {
|
|||
tournament.hasStarted &&
|
||||
!tournament.ctx.isFinalized ? (
|
||||
<div className="stack horizontal justify-end">
|
||||
<Button
|
||||
onClick={() => setEditingProgression(true)}
|
||||
size="tiny"
|
||||
<SendouButton
|
||||
onPress={() => setEditingProgression(true)}
|
||||
size="small"
|
||||
variant="outlined"
|
||||
testId="edit-event-info-button"
|
||||
data-testid="edit-event-info-button"
|
||||
>
|
||||
Edit brackets
|
||||
</Button>
|
||||
</SendouButton>
|
||||
{editingProgression ? (
|
||||
<BracketProgressionEditDialog
|
||||
close={() => setEditingProgression(false)}
|
||||
|
|
@ -497,13 +497,13 @@ function RemoveStaffButton({
|
|||
]}
|
||||
submitButtonText="Remove"
|
||||
>
|
||||
<Button
|
||||
<SendouButton
|
||||
variant="minimal-destructive"
|
||||
size="tiny"
|
||||
size="small"
|
||||
data-testid="remove-staff-button"
|
||||
>
|
||||
<TrashIcon className="build__icon" />
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</FormWithConfirm>
|
||||
);
|
||||
}
|
||||
|
|
@ -615,9 +615,9 @@ function DownloadParticipants() {
|
|||
return (
|
||||
<div>
|
||||
<div className="stack horizontal sm flex-wrap">
|
||||
<Button
|
||||
size="tiny"
|
||||
onClick={() =>
|
||||
<SendouButton
|
||||
size="small"
|
||||
onPress={() =>
|
||||
handleDownload({
|
||||
filename: "all-participants.txt",
|
||||
content: allParticipantsContent(),
|
||||
|
|
@ -625,10 +625,10 @@ function DownloadParticipants() {
|
|||
}
|
||||
>
|
||||
All participants
|
||||
</Button>
|
||||
<Button
|
||||
size="tiny"
|
||||
onClick={() =>
|
||||
</SendouButton>
|
||||
<SendouButton
|
||||
size="small"
|
||||
onPress={() =>
|
||||
handleDownload({
|
||||
filename: "checked-in-participants.txt",
|
||||
content: checkedInParticipantsContent(),
|
||||
|
|
@ -636,10 +636,10 @@ function DownloadParticipants() {
|
|||
}
|
||||
>
|
||||
Checked in participants
|
||||
</Button>
|
||||
<Button
|
||||
size="tiny"
|
||||
onClick={() =>
|
||||
</SendouButton>
|
||||
<SendouButton
|
||||
size="small"
|
||||
onPress={() =>
|
||||
handleDownload({
|
||||
filename: "not-checked-in-participants.txt",
|
||||
content: notCheckedInParticipantsContent(),
|
||||
|
|
@ -647,10 +647,10 @@ function DownloadParticipants() {
|
|||
}
|
||||
>
|
||||
Not checked in participants
|
||||
</Button>
|
||||
<Button
|
||||
size="tiny"
|
||||
onClick={() =>
|
||||
</SendouButton>
|
||||
<SendouButton
|
||||
size="small"
|
||||
onPress={() =>
|
||||
handleDownload({
|
||||
filename: "teams-in-seeded-order.txt",
|
||||
content: simpleListInSeededOrder(),
|
||||
|
|
@ -658,11 +658,11 @@ function DownloadParticipants() {
|
|||
}
|
||||
>
|
||||
Simple list in seeded order
|
||||
</Button>
|
||||
</SendouButton>
|
||||
{tournament.isLeagueSignup ? (
|
||||
<Button
|
||||
size="tiny"
|
||||
onClick={() =>
|
||||
<SendouButton
|
||||
size="small"
|
||||
onPress={() =>
|
||||
handleDownload({
|
||||
filename: "league-format.csv",
|
||||
content: leagueFormat(),
|
||||
|
|
@ -670,7 +670,7 @@ function DownloadParticipants() {
|
|||
}
|
||||
>
|
||||
League format
|
||||
</Button>
|
||||
</SendouButton>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -745,7 +745,7 @@ function BracketReset() {
|
|||
<SubmitButton
|
||||
_action="RESET_BRACKET"
|
||||
state={fetcher.state}
|
||||
disabled={confirmText !== bracketToDeleteName}
|
||||
isDisabled={confirmText !== bracketToDeleteName}
|
||||
testId="reset-bracket-button"
|
||||
>
|
||||
Reset
|
||||
|
|
@ -791,7 +791,7 @@ function BracketProgressionEditDialog({ close }: { close: () => void }) {
|
|||
<div className="stack md horizontal justify-center mt-6">
|
||||
<SubmitButton
|
||||
_action="UPDATE_TOURNAMENT_PROGRESSION"
|
||||
disabled={bracketProgressionErrored}
|
||||
isDisabled={bracketProgressionErrored}
|
||||
>
|
||||
Save changes
|
||||
</SubmitButton>
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ export default function JoinTeamPage() {
|
|||
<Form method="post" className="tournament__invite-container">
|
||||
{validationStatus === "VALID" ? (
|
||||
<div className="stack md items-center">
|
||||
<SubmitButton size="big" disabled={!user?.friendCode}>
|
||||
<SubmitButton size="big" isDisabled={!user?.friendCode}>
|
||||
{t("common:actions.join")}
|
||||
</SubmitButton>
|
||||
{!user?.friendCode ? (
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import { useTranslation } from "react-i18next";
|
|||
import { useCopyToClipboard } from "react-use";
|
||||
import { Alert } from "~/components/Alert";
|
||||
import { Avatar } from "~/components/Avatar";
|
||||
import { Button, LinkButton } from "~/components/Button";
|
||||
import { LinkButton } from "~/components/Button";
|
||||
import { Divider } from "~/components/Divider";
|
||||
import { FormWithConfirm } from "~/components/FormWithConfirm";
|
||||
import { FriendCodeInput } from "~/components/FriendCodeInput";
|
||||
|
|
@ -267,13 +267,13 @@ function TournamentRegisterInfoTabs() {
|
|||
fields={[["_action", "LEAVE_TEAM"]]}
|
||||
submitButtonText="Leave"
|
||||
>
|
||||
<Button
|
||||
<SendouButton
|
||||
className="build__small-text"
|
||||
variant="minimal-destructive"
|
||||
type="submit"
|
||||
>
|
||||
Leave the team
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</FormWithConfirm>
|
||||
) : null}
|
||||
</div>
|
||||
|
|
@ -317,9 +317,9 @@ function PleaseLogIn() {
|
|||
|
||||
return (
|
||||
<form className="stack items-center mt-4" action={LOG_IN_URL} method="post">
|
||||
<Button size="big" type="submit">
|
||||
<SendouButton size="big" type="submit">
|
||||
{t("tournament:pre.logIn")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
|
@ -593,7 +593,7 @@ function CheckIn({
|
|||
return (
|
||||
<fetcher.Form method="post" className="stack items-center">
|
||||
<SubmitButton
|
||||
size="tiny"
|
||||
size="small"
|
||||
_action="CHECK_IN"
|
||||
state={fetcher.state}
|
||||
testId="check-in-button"
|
||||
|
|
@ -710,13 +710,13 @@ function TeamInfo({
|
|||
submitButtonText={t("tournament:pre.info.unregister")}
|
||||
fields={[["_action", "UNREGISTER"]]}
|
||||
>
|
||||
<Button
|
||||
<SendouButton
|
||||
className="build__small-text"
|
||||
variant="minimal-destructive"
|
||||
size="tiny"
|
||||
size="small"
|
||||
>
|
||||
{t("tournament:pre.info.unregister")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</FormWithConfirm>
|
||||
) : null}
|
||||
</div>
|
||||
|
|
@ -781,26 +781,26 @@ function TeamInfo({
|
|||
<div className="stack horizontal md items-center">
|
||||
<Avatar size="xsm" url={avatarUrl} />
|
||||
{canEditAvatar ? (
|
||||
<Button
|
||||
<SendouButton
|
||||
variant="minimal"
|
||||
size="tiny"
|
||||
size="small"
|
||||
onClick={() => setUploadedAvatar(null)}
|
||||
>
|
||||
{t("common:actions.edit")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
) : null}
|
||||
{canDeleteAvatar ? (
|
||||
<FormWithConfirm
|
||||
dialogHeading="Delete team logo?"
|
||||
fields={[["_action", "DELETE_LOGO"]]}
|
||||
>
|
||||
<Button
|
||||
<SendouButton
|
||||
variant="minimal-destructive"
|
||||
size="tiny"
|
||||
size="small"
|
||||
type="submit"
|
||||
>
|
||||
<TrashIcon className="small-icon" />
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</FormWithConfirm>
|
||||
) : null}
|
||||
</div>
|
||||
|
|
@ -838,13 +838,13 @@ function TeamInfo({
|
|||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
<Button
|
||||
testId="save-team-button"
|
||||
disabled={submitButtonDisabled()}
|
||||
<SendouButton
|
||||
data-testid="save-team-button"
|
||||
isDisabled={submitButtonDisabled()}
|
||||
onClick={handleSubmit}
|
||||
>
|
||||
{t("common:actions.save")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</Form>
|
||||
</section>
|
||||
</div>
|
||||
|
|
@ -1018,13 +1018,13 @@ function FillRoster({
|
|||
{t("tournament:actions.shareLink", { inviteLink })}
|
||||
</div>
|
||||
<div>
|
||||
<Button
|
||||
size="tiny"
|
||||
<SendouButton
|
||||
size="small"
|
||||
onClick={() => copyToClipboard(inviteLink)}
|
||||
variant="outlined"
|
||||
>
|
||||
{t("common:actions.copyToClipboard")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
|
|
@ -1164,13 +1164,13 @@ function DeleteMember({ members }: { members: TournamentDataTeam["members"] }) {
|
|||
|
||||
if (!expanded) {
|
||||
return (
|
||||
<Button
|
||||
size="tiny"
|
||||
<SendouButton
|
||||
size="small"
|
||||
variant="minimal-destructive"
|
||||
onClick={() => setExpanded(true)}
|
||||
>
|
||||
{t("tournament:pre.roster.delete.button")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,11 +17,11 @@ import { Link, useFetcher, useNavigation } from "@remix-run/react";
|
|||
import clsx from "clsx";
|
||||
import * as React from "react";
|
||||
import { Alert } from "~/components/Alert";
|
||||
import { Button } from "~/components/Button";
|
||||
import { Catcher } from "~/components/Catcher";
|
||||
import { Draggable } from "~/components/Draggable";
|
||||
import { SubmitButton } from "~/components/SubmitButton";
|
||||
import { Table } from "~/components/Table";
|
||||
import { SendouButton } from "~/components/elements/Button";
|
||||
import { SendouDialog } from "~/components/elements/Dialog";
|
||||
import type { TournamentDataTeam } from "~/features/tournament-bracket/core/Tournament.server";
|
||||
import { useTimeoutState } from "~/hooks/useTimeoutState";
|
||||
|
|
@ -91,12 +91,12 @@ export default function TournamentSeedsPage() {
|
|||
players change
|
||||
</div>
|
||||
) : (
|
||||
<Button
|
||||
<SendouButton
|
||||
className="tournament__seeds__order-button"
|
||||
variant="minimal"
|
||||
size="tiny"
|
||||
size="small"
|
||||
type="button"
|
||||
onClick={() => {
|
||||
onPress={() => {
|
||||
setTeamOrder(
|
||||
structuredClone(tournament.ctx.teams)
|
||||
.sort(
|
||||
|
|
@ -109,7 +109,7 @@ export default function TournamentSeedsPage() {
|
|||
}}
|
||||
>
|
||||
Sort automatically
|
||||
</Button>
|
||||
</SendouButton>
|
||||
)}
|
||||
</div>
|
||||
{tournament.isMultiStartingBracket ? (
|
||||
|
|
@ -234,13 +234,13 @@ function StartingBracketDialog() {
|
|||
|
||||
return (
|
||||
<div>
|
||||
<Button
|
||||
size="tiny"
|
||||
onClick={() => setIsOpen(true)}
|
||||
testId="set-starting-brackets"
|
||||
<SendouButton
|
||||
size="small"
|
||||
onPress={() => setIsOpen(true)}
|
||||
data-testid="set-starting-brackets"
|
||||
>
|
||||
Set starting brackets
|
||||
</Button>
|
||||
</SendouButton>
|
||||
<SendouDialog
|
||||
heading="Setting starting brackets"
|
||||
isOpen={isOpen}
|
||||
|
|
@ -372,8 +372,8 @@ function SeedAlert({ teamOrder }: { teamOrder: number[] }) {
|
|||
{(!showSuccess || teamOrderChanged) && (
|
||||
<SubmitButton
|
||||
state={fetcher.state}
|
||||
disabled={!teamOrderChanged}
|
||||
size="tiny"
|
||||
isDisabled={!teamOrderChanged}
|
||||
size="small"
|
||||
>
|
||||
Save seeds
|
||||
</SubmitButton>
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import * as React from "react";
|
|||
import { useTranslation } from "react-i18next";
|
||||
import { AbilitiesSelector } from "~/components/AbilitiesSelector";
|
||||
import { Alert } from "~/components/Alert";
|
||||
import { Button } from "~/components/Button";
|
||||
import { GearCombobox, WeaponCombobox } from "~/components/Combobox";
|
||||
import { FormMessage } from "~/components/FormMessage";
|
||||
import { Image } from "~/components/Image";
|
||||
|
|
@ -16,6 +15,7 @@ import { Label } from "~/components/Label";
|
|||
import { Main } from "~/components/Main";
|
||||
import { RequiredHiddenInput } from "~/components/RequiredHiddenInput";
|
||||
import { SubmitButton } from "~/components/SubmitButton";
|
||||
import { SendouButton } from "~/components/elements/Button";
|
||||
import { CrossIcon } from "~/components/icons/Cross";
|
||||
import { PlusIcon } from "~/components/icons/Plus";
|
||||
import type { GearType } from "~/db/tables";
|
||||
|
|
@ -234,17 +234,17 @@ function WeaponsSelector() {
|
|||
</div>
|
||||
{i === weapons.length - 1 && (
|
||||
<>
|
||||
<Button
|
||||
size="tiny"
|
||||
disabled={weapons.length === BUILD.MAX_WEAPONS_COUNT}
|
||||
onClick={() => setWeapons((weapons) => [...weapons, 0])}
|
||||
<SendouButton
|
||||
size="small"
|
||||
isDisabled={weapons.length === BUILD.MAX_WEAPONS_COUNT}
|
||||
onPress={() => setWeapons((weapons) => [...weapons, 0])}
|
||||
icon={<PlusIcon />}
|
||||
testId="add-weapon-button"
|
||||
data-testid="add-weapon-button"
|
||||
/>
|
||||
{weapons.length > 1 && (
|
||||
<Button
|
||||
size="tiny"
|
||||
onClick={() =>
|
||||
<SendouButton
|
||||
size="small"
|
||||
onPress={() =>
|
||||
setWeapons((weapons) => {
|
||||
const newWeapons = [...weapons];
|
||||
newWeapons.pop();
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@ import { useFetcher, useLoaderData, useMatches } from "@remix-run/react";
|
|||
import * as React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { BuildCard } from "~/components/BuildCard";
|
||||
import { Button } from "~/components/Button";
|
||||
import { FormMessage } from "~/components/FormMessage";
|
||||
import { Image, WeaponImage } from "~/components/Image";
|
||||
import { SubmitButton } from "~/components/SubmitButton";
|
||||
import { SendouButton } from "~/components/elements/Button";
|
||||
import { SendouDialog } from "~/components/elements/Dialog";
|
||||
import { SendouMenu, SendouMenuItem } from "~/components/elements/Menu";
|
||||
import { LockIcon } from "~/components/icons/Lock";
|
||||
|
|
@ -19,7 +19,6 @@ import type { MainWeaponId } from "~/modules/in-game-lists/types";
|
|||
import { atOrError } from "~/utils/arrays";
|
||||
import type { SendouRouteHandle } from "~/utils/remix.server";
|
||||
import { weaponCategoryUrl } from "~/utils/urls";
|
||||
import { SendouButton } from "../../../components/elements/Button";
|
||||
import type { UserPageLoaderData } from "../loaders/u.$identifier.server";
|
||||
import { DEFAULT_BUILD_SORT } from "../user-page-constants";
|
||||
|
||||
|
|
@ -154,24 +153,24 @@ function BuildsFilters({
|
|||
</SendouButton>
|
||||
{showPublicPrivateFilters ? (
|
||||
<>
|
||||
<Button
|
||||
onClick={() => setWeaponFilter("PUBLIC")}
|
||||
<SendouButton
|
||||
onPress={() => setWeaponFilter("PUBLIC")}
|
||||
variant={weaponFilter === "PUBLIC" ? undefined : "outlined"}
|
||||
size="tiny"
|
||||
size="small"
|
||||
className="u__build-filter-button"
|
||||
icon={<UnlockIcon />}
|
||||
>
|
||||
{t("builds:stats.public")} ({publicBuildsCount})
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => setWeaponFilter("PRIVATE")}
|
||||
</SendouButton>
|
||||
<SendouButton
|
||||
onPress={() => setWeaponFilter("PRIVATE")}
|
||||
variant={weaponFilter === "PRIVATE" ? undefined : "outlined"}
|
||||
size="tiny"
|
||||
size="small"
|
||||
className="u__build-filter-button"
|
||||
icon={<LockIcon />}
|
||||
>
|
||||
{t("builds:stats.private")} ({privateBuildsCount})
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</>
|
||||
) : null}
|
||||
|
||||
|
|
@ -237,14 +236,14 @@ function ChangeSortingDialog({ close }: { close: () => void }) {
|
|||
<FormMessage type="info">
|
||||
{t("user:builds.sorting.info")}
|
||||
</FormMessage>
|
||||
<Button
|
||||
<SendouButton
|
||||
className="ml-auto"
|
||||
variant="minimal"
|
||||
size="tiny"
|
||||
onClick={() => setBuildSorting([...DEFAULT_BUILD_SORT, null])}
|
||||
size="small"
|
||||
onPress={() => setBuildSorting([...DEFAULT_BUILD_SORT, null])}
|
||||
>
|
||||
{t("user:builds.sorting.backToDefaults")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
{buildSorting.map((sort, i) => {
|
||||
const isLast = i === buildSorting.length - 1;
|
||||
const isSecondToLast = i === buildSorting.length - 2;
|
||||
|
|
@ -270,10 +269,10 @@ function ChangeSortingDialog({ close }: { close: () => void }) {
|
|||
</div>
|
||||
{(isLast && !canAddMoreSorting) ||
|
||||
(canAddMoreSorting && isSecondToLast) ? (
|
||||
<Button
|
||||
<SendouButton
|
||||
icon={<TrashIcon />}
|
||||
variant="minimal-destructive"
|
||||
onClick={deleteLastSorting}
|
||||
onPress={deleteLastSorting}
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import { Form, Link, useLoaderData, useMatches } from "@remix-run/react";
|
|||
import clsx from "clsx";
|
||||
import * as React from "react";
|
||||
import { Trans, useTranslation } from "react-i18next";
|
||||
import { Button } from "~/components/Button";
|
||||
import { WeaponCombobox } from "~/components/Combobox";
|
||||
import { CustomizedColorsInput } from "~/components/CustomizedColorsInput";
|
||||
import { FormErrors } from "~/components/FormErrors";
|
||||
|
|
@ -11,6 +10,7 @@ import { WeaponImage } from "~/components/Image";
|
|||
import { Input } from "~/components/Input";
|
||||
import { Label } from "~/components/Label";
|
||||
import { SubmitButton } from "~/components/SubmitButton";
|
||||
import { SendouButton } from "~/components/elements/Button";
|
||||
import { SendouSelect, SendouSelectItem } from "~/components/elements/Select";
|
||||
import { SendouSwitch } from "~/components/elements/Switch";
|
||||
import { StarIcon } from "~/components/icons/Star";
|
||||
|
|
@ -318,11 +318,11 @@ function WeaponPoolSelect() {
|
|||
/>
|
||||
</div>
|
||||
<div className="stack sm horizontal items-center justify-center">
|
||||
<Button
|
||||
<SendouButton
|
||||
icon={weapon.isFavorite ? <StarFilledIcon /> : <StarIcon />}
|
||||
variant="minimal"
|
||||
aria-label="Favorite weapon"
|
||||
onClick={() =>
|
||||
onPress={() =>
|
||||
setWeapons(
|
||||
weapons.map((w) =>
|
||||
w.weaponSplId === weapon.weaponSplId
|
||||
|
|
@ -335,19 +335,19 @@ function WeaponPoolSelect() {
|
|||
)
|
||||
}
|
||||
/>
|
||||
<Button
|
||||
<SendouButton
|
||||
icon={<TrashIcon />}
|
||||
variant="minimal-destructive"
|
||||
aria-label="Delete weapon"
|
||||
onClick={() =>
|
||||
onPress={() =>
|
||||
setWeapons(
|
||||
weapons.filter(
|
||||
(w) => w.weaponSplId !== weapon.weaponSplId,
|
||||
),
|
||||
)
|
||||
}
|
||||
testId={`delete-weapon-${weapon.weaponSplId}`}
|
||||
size="tiny"
|
||||
data-testid={`delete-weapon-${weapon.weaponSplId}`}
|
||||
size="small"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
import { useLoaderData, useMatches } from "@remix-run/react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Button, LinkButton } from "~/components/Button";
|
||||
import { LinkButton } from "~/components/Button";
|
||||
import { useUser } from "~/features/auth/core/user";
|
||||
import { UserResultsTable } from "~/features/user-page/components/UserResultsTable";
|
||||
import { useSearchParamState } from "~/hooks/useSearchParamState";
|
||||
import invariant from "~/utils/invariant";
|
||||
import { userResultsEditHighlightsPage } from "~/utils/urls";
|
||||
import { SendouButton } from "../../../components/elements/Button";
|
||||
import type { UserPageLoaderData } from "../loaders/u.$identifier.server";
|
||||
|
||||
import { loader } from "../loaders/u.$identifier.results.server";
|
||||
|
|
@ -51,15 +52,15 @@ export default function UserResultsPage() {
|
|||
</div>
|
||||
<UserResultsTable id="user-results-table" results={resultsToShow} />
|
||||
{hasHighlightedResults ? (
|
||||
<Button
|
||||
<SendouButton
|
||||
variant="minimal"
|
||||
size="tiny"
|
||||
onClick={() => setShowAll(!showAll)}
|
||||
size="small"
|
||||
onPress={() => setShowAll(!showAll)}
|
||||
>
|
||||
{showAll
|
||||
? t("results.button.showHighlights")
|
||||
: t("results.button.showAll")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@ import * as React from "react";
|
|||
import { useTranslation } from "react-i18next";
|
||||
import { useDebounce } from "react-use";
|
||||
import { Avatar } from "~/components/Avatar";
|
||||
import { Button } from "~/components/Button";
|
||||
import { Input } from "~/components/Input";
|
||||
import { Main } from "~/components/Main";
|
||||
import { SendouButton } from "~/components/elements/Button";
|
||||
import { DiscordIcon } from "~/components/icons/Discord";
|
||||
import { SearchIcon } from "~/components/icons/Search";
|
||||
import { useUser } from "~/features/auth/core/user";
|
||||
|
|
@ -68,9 +68,9 @@ export default function UserSearchPage() {
|
|||
action={LOG_IN_URL}
|
||||
method="post"
|
||||
>
|
||||
<Button size="big" type="submit" icon={<DiscordIcon />}>
|
||||
<SendouButton size="big" type="submit" icon={<DiscordIcon />}>
|
||||
{t("user:search.pleaseLogIn.button")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</form>
|
||||
</Main>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { useLoaderData } from "@remix-run/react";
|
|||
import clsx from "clsx";
|
||||
import * as React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Button, LinkButton } from "~/components/Button";
|
||||
import { LinkButton } from "~/components/Button";
|
||||
import { FormWithConfirm } from "~/components/FormWithConfirm";
|
||||
import { Image, WeaponImage } from "~/components/Image";
|
||||
import { Main } from "~/components/Main";
|
||||
|
|
@ -25,6 +25,7 @@ import {
|
|||
stageImageUrl,
|
||||
vodVideoPage,
|
||||
} from "~/utils/urls";
|
||||
import { SendouButton } from "../../../components/elements/Button";
|
||||
import { PovUser } from "../components/VodPov";
|
||||
import type { Vod } from "../vods-types";
|
||||
import { canEditVideo, secondsToHoursMinutesSecondString } from "../vods-utils";
|
||||
|
|
@ -130,14 +131,14 @@ export default function VodPage() {
|
|||
title: data.vod.title,
|
||||
})}
|
||||
>
|
||||
<Button
|
||||
<SendouButton
|
||||
variant="minimal-destructive"
|
||||
size="tiny"
|
||||
size="small"
|
||||
type="submit"
|
||||
icon={<TrashIcon />}
|
||||
>
|
||||
{t("common:actions.delete")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</FormWithConfirm>
|
||||
</div>
|
||||
) : null}
|
||||
|
|
@ -227,13 +228,13 @@ function Match({
|
|||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
<Button
|
||||
size="tiny"
|
||||
onClick={() => setStart(match.startsAt)}
|
||||
<SendouButton
|
||||
size="small"
|
||||
onPress={() => setStart(match.startsAt)}
|
||||
variant="outlined"
|
||||
>
|
||||
{secondsToHoursMinutesSecondString(match.startsAt)}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,11 +9,11 @@ import {
|
|||
} from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import type { z } from "zod";
|
||||
import { Button } from "~/components/Button";
|
||||
import { WeaponCombobox } from "~/components/Combobox";
|
||||
import { FormMessage } from "~/components/FormMessage";
|
||||
import { Label } from "~/components/Label";
|
||||
import { Main } from "~/components/Main";
|
||||
import { SendouButton } from "~/components/elements/Button";
|
||||
import { UserSearch } from "~/components/elements/UserSearch";
|
||||
import { AddFieldButton } from "~/components/form/AddFieldButton";
|
||||
import { RemoveFieldButton } from "~/components/form/RemoveFieldButton";
|
||||
|
|
@ -191,16 +191,16 @@ function PovFormField() {
|
|||
onBlur={onBlur}
|
||||
/>
|
||||
)}
|
||||
<Button
|
||||
size="tiny"
|
||||
<SendouButton
|
||||
size="small"
|
||||
variant="minimal"
|
||||
onClick={toggleInputType}
|
||||
onPress={toggleInputType}
|
||||
className="outline-theme mt-2"
|
||||
>
|
||||
{asPlainInput
|
||||
? t("calendar:forms.team.player.addAsUser")
|
||||
: t("calendar:forms.team.player.addAsText")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
{error && (
|
||||
<FormMessage type="error">{error.message as string}</FormMessage>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import type { MetaFunction } from "@remix-run/node";
|
||||
import { useLoaderData, useSearchParams } from "@remix-run/react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Button } from "~/components/Button";
|
||||
import { WeaponCombobox } from "~/components/Combobox";
|
||||
import { Label } from "~/components/Label";
|
||||
import { Main } from "~/components/Main";
|
||||
import { SendouButton } from "~/components/elements/Button";
|
||||
import { modesShort } from "~/modules/in-game-lists/modes";
|
||||
import { stageIds } from "~/modules/in-game-lists/stage-ids";
|
||||
import { mainWeaponIds } from "~/modules/in-game-lists/weapon-ids";
|
||||
|
|
@ -61,15 +61,15 @@ export default function VodsSearchPage() {
|
|||
))}
|
||||
</div>
|
||||
{data.hasMoreVods && (
|
||||
<Button
|
||||
<SendouButton
|
||||
className="m-0-auto"
|
||||
size="tiny"
|
||||
onClick={() =>
|
||||
size="small"
|
||||
onPress={() =>
|
||||
addToSearchParams("limit", data.limit + VODS_PAGE_BATCH_SIZE)
|
||||
}
|
||||
>
|
||||
{t("common:actions.loadMore")}
|
||||
</Button>
|
||||
</SendouButton>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user