diff --git a/frontend/src/js/app/About.tsx b/frontend/src/js/app/About.tsx
index 4fdd4934ff..eaa7e50b0d 100644
--- a/frontend/src/js/app/About.tsx
+++ b/frontend/src/js/app/About.tsx
@@ -11,8 +11,9 @@ import {
import { useHotkeys } from "react-hotkeys-hook";
import { useSelector } from "react-redux";
import type { GetFrontendConfigResponseT } from "../api/types";
-import IconButton from "../button/IconButton";
import Modal from "../modal/Modal";
+import { Button } from "../ui-components/Button";
+import { Icon } from "../ui-components/Icon";
import type { StateT } from "./reducers";
const initialState = {
@@ -90,9 +91,10 @@ export const About = memo(() => {
{frontendGitDescribe} – {frontendTimestamp}
-
+
+
Copy version info
-
+
);
diff --git a/frontend/src/js/authorization/LoginPage.tsx b/frontend/src/js/authorization/LoginPage.tsx
index 69b2b4f488..b819d57c3e 100644
--- a/frontend/src/js/authorization/LoginPage.tsx
+++ b/frontend/src/js/authorization/LoginPage.tsx
@@ -21,7 +21,7 @@ const wrap = tv({
});
const logo = tv({
- base: ["h-[35px]", "bg-no-repeat", "[background-position-y:50%]"],
+ base: ["h-9", "bg-no-repeat", "[background-position-y:50%]"],
});
const headline = tv({
diff --git a/frontend/src/js/button/BasicButton.tsx b/frontend/src/js/button/BasicButton.tsx
deleted file mode 100644
index bdb8dcad4c..0000000000
--- a/frontend/src/js/button/BasicButton.tsx
+++ /dev/null
@@ -1,78 +0,0 @@
-import type { CSSProperties, ReactNode, Ref } from "react";
-import {
- Button as RacButton,
- type ButtonProps as RacButtonProps,
-} from "react-aria-components";
-import { tv } from "tailwind-variants";
-
-export interface BasicButtonProps
- extends Omit<
- RacButtonProps,
- "className" | "style" | "children" | "isDisabled"
- > {
- className?: string;
- style?: CSSProperties;
- children?: ReactNode;
- /** maps to react-aria's `isDisabled` */
- disabled?: boolean;
- bare?: boolean;
- tiny?: boolean;
- small?: boolean;
- large?: boolean;
- active?: boolean;
- secondary?: boolean;
-}
-
-const button = tv({
- base: [
- "cursor-pointer",
- "rounded",
- "px-[15px] py-2",
- "text-sm",
- "font-normal",
- "transition-all duration-200",
- "disabled:cursor-not-allowed disabled:opacity-40",
- ],
- variants: {
- active: { true: "font-bold" },
- secondary: { true: "font-bold" },
- // later wins when several are set
- large: { true: "px-[18px] py-3 text-xl" },
- small: { true: "px-2 py-[6px] text-xs" },
- tiny: { true: "px-[6px] py-1 text-xs" },
- bare: { true: "p-0" },
- },
-});
-
-// react-aria's Button is the trigger that TooltipTrigger, MenuTrigger and
-// friends expect. `onClick` is react-aria's alias for `onPress` and receives
-// a mouse event; react-aria prefers `onPress`.
-const BasicButton = ({
- ref,
- className,
- bare,
- tiny,
- small,
- large,
- active,
- secondary,
- disabled,
- ...props
-}: BasicButtonProps & { ref?: Ref }) => (
-
-);
-
-export default BasicButton;
diff --git a/frontend/src/js/button/DownloadButton.tsx b/frontend/src/js/button/DownloadButton.tsx
index 4147ff571c..4dbd6587cd 100644
--- a/frontend/src/js/button/DownloadButton.tsx
+++ b/frontend/src/js/button/DownloadButton.tsx
@@ -13,8 +13,8 @@ import { tv } from "tailwind-variants";
import type { ResultUrlWithLabel } from "../api/types";
import { AuthTokenContext } from "../authorization/AuthTokenProvider";
import { getEnding } from "../query-runner/DownloadResultsDropdownButton";
-
-import IconButton, { type IconButtonPropsT } from "./IconButton";
+import { Button, type ButtonProps } from "../ui-components/Button";
+import { Icon } from "../ui-components/Icon";
const link = tv({ base: "leading-none" });
@@ -43,12 +43,11 @@ export function getFileIcon(url: string): FileIcon {
return { icon: faFileDownload };
}
-interface Props extends Omit {
+interface Props extends Omit {
resultUrl: ResultUrlWithLabel;
className?: string;
children?: ReactNode;
simpleIcon?: boolean;
- onClick?: () => void;
showColoredIcon?: boolean;
}
@@ -58,7 +57,6 @@ const DownloadButton = ({
resultUrl,
className,
children,
- onClick,
showColoredIcon,
...restProps
}: Props & { ref?: Ref }) => {
@@ -70,16 +68,13 @@ const DownloadButton = ({
return (
-
+
+
{children}
-
+
);
};
diff --git a/frontend/src/js/button/HistoryButton.tsx b/frontend/src/js/button/HistoryButton.tsx
index b6697c21d8..7c0f3b8b6f 100644
--- a/frontend/src/js/button/HistoryButton.tsx
+++ b/frontend/src/js/button/HistoryButton.tsx
@@ -2,12 +2,11 @@ import { faListUl } from "@fortawesome/free-solid-svg-icons";
import { useCallback } from "react";
import { useTranslation } from "react-i18next";
import { useDispatch } from "react-redux";
-
import { openHistory } from "../entity-history/actions";
+import { Button } from "../ui-components/Button";
+import { Icon } from "../ui-components/Icon";
import { Tooltip, TooltipTrigger } from "../ui-components/Tooltip";
-import IconButton from "./IconButton";
-
export const HistoryButton = () => {
const { t } = useTranslation();
const dispatch = useDispatch();
@@ -18,7 +17,13 @@ export const HistoryButton = () => {
return (
-
+
+
+
{t("history.history")}
);
diff --git a/frontend/src/js/button/IconButton.tsx b/frontend/src/js/button/IconButton.tsx
deleted file mode 100644
index 0f7527ba5f..0000000000
--- a/frontend/src/js/button/IconButton.tsx
+++ /dev/null
@@ -1,93 +0,0 @@
-import type { IconProp } from "@fortawesome/fontawesome-svg-core";
-import { memo, type Ref } from "react";
-import { tv } from "tailwind-variants";
-
-import { Icon } from "../ui-components/Icon";
-
-import BasicButton, { type BasicButtonProps } from "./BasicButton";
-
-const iconButton = tv({
- base: [
- "inline-flex items-center",
- "gap-[10px]",
- "rounded",
- "bg-transparent",
- "text-sm",
- "text-gray-800",
- "opacity-75 hover:opacity-100 disabled:hover:opacity-40",
- "transition-[opacity,background-color] duration-100",
- ],
- variants: {
- // later wins when several are set
- active: { true: "text-primary-500" },
- red: { true: "text-red" },
- frame: { true: "opacity-100 border border-gray-500 hover:bg-bg-100" },
- bgHover: { true: "hover:bg-bg-100" },
- tight: { true: "gap-[5px]" },
- large: { true: "text-base" },
- },
-});
-
-// The button's text color reaches the icon; this is the exception.
-const buttonIcon = tv({
- variants: {
- light: { true: "text-gray-500" },
- },
-});
-
-export interface IconButtonPropsT extends Omit {
- icon: IconProp;
- active?: boolean;
- large?: boolean;
- tight?: boolean;
- red?: boolean;
- frame?: boolean;
- bare?: boolean;
- light?: boolean;
- bgHover?: boolean;
- iconColor?: string;
-}
-
-// A button that is prefixed by an icon
-const IconButton = ({
- ref,
- icon,
- active,
- red,
- large,
- children,
- tight,
- light,
- bgHover,
- iconColor,
- frame,
- className,
- ...restProps
-}: IconButtonPropsT & { ref?: Ref }) => (
-
-
- {children && (
- {children}
- )}
-
-);
-
-export default memo(IconButton);
diff --git a/frontend/src/js/button/PreviewButton.tsx b/frontend/src/js/button/PreviewButton.tsx
index c1e792fefd..0a00ab0ddd 100644
--- a/frontend/src/js/button/PreviewButton.tsx
+++ b/frontend/src/js/button/PreviewButton.tsx
@@ -5,19 +5,13 @@ import {
import { useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import { useDispatch, useSelector } from "react-redux";
-import { tv } from "tailwind-variants";
+
import type { StateT } from "../app/reducers";
import { openPreview, useLoadPreviewData } from "../preview/actions";
-import IconButton, { type IconButtonPropsT } from "./IconButton";
-
-const previewButton = tv({
- base: ["whitespace-nowrap", "h-[35px]", "px-3 py-[5px]"],
-});
+import { Button, type ButtonProps } from "../ui-components/Button";
+import { Icon } from "../ui-components/Icon";
-const PreviewButton = ({
- className,
- ...buttonProps
-}: Partial) => {
+const PreviewButton = (props: ButtonProps) => {
const { t } = useTranslation();
const dispatch = useDispatch();
@@ -33,11 +27,9 @@ const PreviewButton = ({
);
return (
- {
+ {
if (queryId) {
setLoading(true);
setTimeout(async () => {
@@ -47,10 +39,11 @@ const PreviewButton = ({
});
}
}}
- {...buttonProps}
+ {...props}
>
+
{t("preview.preview")}
-
+
);
};
diff --git a/frontend/src/js/button/QueryResultHistoryButton.tsx b/frontend/src/js/button/QueryResultHistoryButton.tsx
index 3491c2300f..a6a3d2d6ab 100644
--- a/frontend/src/js/button/QueryResultHistoryButton.tsx
+++ b/frontend/src/js/button/QueryResultHistoryButton.tsx
@@ -5,7 +5,8 @@ import type { ColumnDescription } from "../api/types";
import type { StateT } from "../app/reducers";
import { useGetAuthorizedUrl } from "../authorization/useAuthorizedUrl";
import { openHistory, useNewHistorySession } from "../entity-history/actions";
-import IconButton from "./IconButton";
+import { Button } from "../ui-components/Button";
+import { Icon } from "../ui-components/Icon";
export const QueryResultHistoryButton = ({
url,
@@ -26,16 +27,16 @@ export const QueryResultHistoryButton = ({
const newHistorySession = useNewHistorySession();
return (
- {
+ {
await newHistorySession(getAuthorizedUrl(url), columns, label);
dispatch(openHistory());
}}
+ className="whitespace-nowrap"
>
+
{t("history.history")}
-
+
);
};
diff --git a/frontend/src/js/concept-trees-open/ConceptTreesOpenButtons.tsx b/frontend/src/js/concept-trees-open/ConceptTreesOpenButtons.tsx
index 3112f25965..debf2b7b38 100644
--- a/frontend/src/js/concept-trees-open/ConceptTreesOpenButtons.tsx
+++ b/frontend/src/js/concept-trees-open/ConceptTreesOpenButtons.tsx
@@ -3,11 +3,11 @@ import { memo, useCallback, useRef } from "react";
import { useTranslation } from "react-i18next";
import { useDispatch, useSelector } from "react-redux";
import { tv } from "tailwind-variants";
-
import type { StateT } from "../app/reducers";
-import IconButton from "../button/IconButton";
import { clearSearchQuery } from "../concept-trees/actions";
import { useRootConceptIds } from "../concept-trees/useRootConceptIds";
+import { Button } from "../ui-components/Button";
+import { Icon } from "../ui-components/Icon";
import { Tooltip, TooltipTrigger } from "../ui-components/Tooltip";
import { closeAllConceptOpen, resetAllConceptOpen } from "./actions";
@@ -72,22 +72,24 @@ const ConceptTreesOpenButtonsView = memo(
return (
-
+
+
+
{t("conceptTreesOpen.resetAll")}
-
+
+
+
{t("conceptTreesOpen.closeAll")}
diff --git a/frontend/src/js/concept-trees/ConceptTree.tsx b/frontend/src/js/concept-trees/ConceptTree.tsx
index 04eef73fa2..ac9c70ad43 100644
--- a/frontend/src/js/concept-trees/ConceptTree.tsx
+++ b/frontend/src/js/concept-trees/ConceptTree.tsx
@@ -6,7 +6,7 @@ import {
import { useTranslation } from "react-i18next";
import { tv } from "tailwind-variants";
import type { ConceptIdT, ConceptT } from "../api/types";
-import IconButton from "../button/IconButton";
+import { Button } from "../ui-components/Button";
import { Icon } from "../ui-components/Icon";
import ConceptTreeNode from "./ConceptTreeNode";
import ConceptTreeNodeText from "./ConceptTreeNodeText";
@@ -57,12 +57,13 @@ const ConceptTree = ({
className={message({ error: true })}
style={{ paddingLeft: 12 + depth * 15 }}
>
- onLoadTree(conceptId)}
- />
+ onLoadTree(conceptId)}
+ className="text-red"
+ >
+
+
{t("conceptTreeList.error", { tree: label })}
);
diff --git a/frontend/src/js/editor-v2/EditorV2.tsx b/frontend/src/js/editor-v2/EditorV2.tsx
index 3c160611bb..2f0d09cc91 100644
--- a/frontend/src/js/editor-v2/EditorV2.tsx
+++ b/frontend/src/js/editor-v2/EditorV2.tsx
@@ -13,8 +13,6 @@ import { useCallback, useEffect, useMemo, useState } from "react";
import { useHotkeys } from "react-hotkeys-hook";
import { useTranslation } from "react-i18next";
import { tv } from "tailwind-variants";
-
-import IconButton from "../button/IconButton";
import { useDatasetId } from "../dataset/selectors";
import { nodeIsConceptQueryNode, useActiveState } from "../model/node";
import { EmptyQueryEditorDropzone } from "../standard-query-editor/EmptyQueryEditorDropzone";
@@ -22,8 +20,10 @@ import type {
DragItemConceptTreeNode,
DragItemQuery,
} from "../standard-query-editor/types";
+import { Button } from "../ui-components/Button";
import { ConfirmMenu } from "../ui-components/ConfirmMenu";
import Dropzone from "../ui-components/Dropzone";
+import { Icon } from "../ui-components/Icon";
import { Tooltip, TooltipTrigger } from "../ui-components/Tooltip";
import { EDITOR_DROP_TYPES, HOTKEYS } from "./config";
import { useConnectorEditing } from "./connector-update/useConnectorRotation";
@@ -52,10 +52,6 @@ const main = tv({
],
});
-const actionIconButton = tv({
- base: ["flex items-center", "gap-[5px]"],
-});
-
const useEditorState = () => {
const [tree, setTree] = useState(undefined);
const [selectedNodeId, setSelectedNodeId] = useState(
@@ -301,134 +297,132 @@ export function EditorV2({
- {
- e.stopPropagation();
+ aria-pressed={selectedNodeActive}
+ onPress={() => {
onOpenQueryNodeEditor();
}}
>
+
{t("editorV2.edit")}
-
+
)}
{featureDates && selectedNode && (
- {
- e.stopPropagation();
+ {
onOpen();
}}
>
+
{t("editorV2.dates")}
-
+
)}
{featureNegate && selectedNode && (
- {
- e.stopPropagation();
+ {
onNegateClick();
}}
+ className="aria-pressed:text-red"
>
+
{t("editorV2.negate")}
-
+
)}
{featureConnectorRotate && selectedNode && connection && (
- {
- e.stopPropagation();
+ {
onRotateConnector();
}}
>
+
{connection}
-
+
)}
{selectedNode?.children?.connection === "time" && (
- {
- e.stopPropagation();
+ {
onOpenTimeModal();
}}
>
+
{t("editorV2.timeConnection")}
-
+
)}
{canExpand && (
- {
- e.stopPropagation();
+ {
onExpand();
}}
>
+
{t("editorV2.expand")}
-
+
)}
{selectedNode && (
- {
- e.stopPropagation();
+ {
onFlip();
}}
>
+
{t("editorV2.flip")}
-
+
)}
{selectedNode && (
- {
- e.stopPropagation();
+ {
onDelete();
}}
>
+
{t("editorV2.delete")}
-
+
)}
@@ -436,10 +430,13 @@ export function EditorV2({
onConfirm={onReset}
confirmationText={t("editorV2.clearConfirm")}
>
-
+
+
+
{t("editorV2.clear")}
diff --git a/frontend/src/js/editor-v2/date-restriction/DateModal.tsx b/frontend/src/js/editor-v2/date-restriction/DateModal.tsx
index 06274d2947..ab69219fb6 100644
--- a/frontend/src/js/editor-v2/date-restriction/DateModal.tsx
+++ b/frontend/src/js/editor-v2/date-restriction/DateModal.tsx
@@ -4,11 +4,10 @@ import { useCallback, useMemo } from "react";
import { useHotkeys } from "react-hotkeys-hook";
import { useTranslation } from "react-i18next";
import { tv } from "tailwind-variants";
-
import type { DateRangeT } from "../../api/types";
-import IconButton from "../../button/IconButton";
import type { DateStringMinMax } from "../../common/helpers/dateHelper";
import Modal from "../../modal/Modal";
+import { Button } from "../../ui-components/Button";
import { Icon } from "../../ui-components/Icon";
import InputCheckbox from "../../ui-components/InputCheckbox";
import InputDateRange from "../../ui-components/InputDateRange";
@@ -54,14 +53,15 @@ export const DateModal = ({
const labelSuffix = useMemo(() => {
return hasActiveDate ? (
-
+
{t("queryNodeEditor.reset")}
-
+
) : null;
}, [t, hasActiveDate, onResetDates]);
diff --git a/frontend/src/js/entity-history/ContentControl.tsx b/frontend/src/js/entity-history/ContentControl.tsx
index a5ddcfa80c..d4fa8635f4 100644
--- a/frontend/src/js/entity-history/ContentControl.tsx
+++ b/frontend/src/js/entity-history/ContentControl.tsx
@@ -6,8 +6,9 @@ import {
} from "@fortawesome/free-solid-svg-icons";
import { memo, useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
+import { Button } from "../ui-components/Button";
+import { Icon } from "../ui-components/Icon";
-import IconButton from "../button/IconButton";
import { Tooltip, TooltipTrigger } from "../ui-components/Tooltip";
export type ContentType =
@@ -59,14 +60,19 @@ const ContentControl = ({ value, onChange }: Props) => {
const active = value[option.key];
return (
- {
+ {
onChange({ ...value, [option.key]: !value[option.key] });
}}
- />
+ >
+
+
{option.tooltip}
);
diff --git a/frontend/src/js/entity-history/DetailControl.tsx b/frontend/src/js/entity-history/DetailControl.tsx
index 60ce3d5b95..9c1140255d 100644
--- a/frontend/src/js/entity-history/DetailControl.tsx
+++ b/frontend/src/js/entity-history/DetailControl.tsx
@@ -6,10 +6,10 @@ import {
} from "@fortawesome/free-solid-svg-icons";
import { type Dispatch, memo, type SetStateAction, useMemo } from "react";
import { useTranslation } from "react-i18next";
-
import { tv } from "tailwind-variants";
+import { Button } from "../ui-components/Button";
+import { Icon } from "../ui-components/Icon";
-import IconButton from "../button/IconButton";
import { Tooltip, TooltipTrigger } from "../ui-components/Tooltip";
const root = tv({ base: "flex flex-col items-center" });
@@ -59,12 +59,15 @@ export const DetailControl = memo(
return (
- setDetailLevel(value as DetailLevel)}
- icon={icon}
- active={selected}
- />
+ onPress={() => setDetailLevel(value as DetailLevel)}
+ aria-pressed={selected}
+ >
+
+
{tooltip}
);
diff --git a/frontend/src/js/entity-history/InteractionControl.tsx b/frontend/src/js/entity-history/InteractionControl.tsx
index 7d5e723bb0..e8946803fc 100644
--- a/frontend/src/js/entity-history/InteractionControl.tsx
+++ b/frontend/src/js/entity-history/InteractionControl.tsx
@@ -1,8 +1,9 @@
import { faChevronRight, faHome } from "@fortawesome/free-solid-svg-icons";
import { memo } from "react";
import { useTranslation } from "react-i18next";
+import { Button } from "../ui-components/Button";
+import { Icon } from "../ui-components/Icon";
-import IconButton from "../button/IconButton";
import { Tooltip, TooltipTrigger } from "../ui-components/Tooltip";
const InteractionControl = ({
@@ -17,11 +18,23 @@ const InteractionControl = ({
return (
-
+
+
+
{t("history.closeAll")}
-
+
+
+
{t("history.openAll")}
diff --git a/frontend/src/js/entity-history/Navigation.tsx b/frontend/src/js/entity-history/Navigation.tsx
index 4c02ecdea0..9babc6aba5 100644
--- a/frontend/src/js/entity-history/Navigation.tsx
+++ b/frontend/src/js/entity-history/Navigation.tsx
@@ -16,11 +16,11 @@ import { useHotkeys } from "react-hotkeys-hook";
import { useTranslation } from "react-i18next";
import { useDispatch, useSelector } from "react-redux";
import { tv } from "tailwind-variants";
-
import type { SelectOptionT } from "../api/types";
import type { StateT } from "../app/reducers";
-import IconButton from "../button/IconButton";
+import { Button } from "../ui-components/Button";
import { ConfirmMenu } from "../ui-components/ConfirmMenu";
+import { Icon } from "../ui-components/Icon";
import {
Tooltip,
TooltipTrigger,
@@ -61,11 +61,11 @@ const loadHistoryDropzone = tv({
],
});
-const containedIconButton = tv({
+const containedButton = tv({
base: ["grow", "justify-center"],
});
-const fullWidthIconButton = tv({
+const fullWidthButton = tv({
base: ["w-full", "justify-center"],
});
@@ -146,14 +146,14 @@ export const Navigation = memo(
>
-
+
{t("common.back")}
-
+
{backButtonWarning}
{!empty && (
@@ -161,13 +161,10 @@ export const Navigation = memo(
onConfirm={onReset}
confirmationText={t("history.settings.resetConfirm")}
>
-
+
+
{t("history.settings.reset")}
-
+
)}
@@ -184,11 +181,14 @@ export const Navigation = memo(
{!empty && (
-
+
+
+
{`${t("history.prevButtonLabel")} (shift + ⬆)`}
@@ -213,25 +213,27 @@ export const Navigation = memo(
<>
-
+
+
+
{`${t("history.nextButtonLabel")} (shift + ⬇)`}
-
+
CSV
-
+
{t("history.downloadButtonLabel")}
diff --git a/frontend/src/js/entity-history/NavigationHeader.tsx b/frontend/src/js/entity-history/NavigationHeader.tsx
index 5e9b3c31f0..4cad30709e 100644
--- a/frontend/src/js/entity-history/NavigationHeader.tsx
+++ b/frontend/src/js/entity-history/NavigationHeader.tsx
@@ -3,12 +3,12 @@ import { type Dispatch, memo, type SetStateAction, useState } from "react";
import { useTranslation } from "react-i18next";
import { useSelector } from "react-redux";
import { tv } from "tailwind-variants";
-
import type { SelectOptionT } from "../api/types";
import type { StateT } from "../app/reducers";
-import IconButton from "../button/IconButton";
import ProgressBar from "../common/components/ProgressBar";
import { Heading3 } from "../headings/Headings";
+import { Button } from "../ui-components/Button";
+import { Icon } from "../ui-components/Icon";
import { Tooltip, TooltipTrigger } from "../ui-components/Tooltip";
import { SettingsModal } from "./SettingsModal";
@@ -88,10 +88,13 @@ export const NavigationHeader = memo(
{t("history.history")}
- setSettingsModalOpen(true)}
- />
+ setSettingsModalOpen(true)}
+ >
+
+
{t("history.settings.headline")}
diff --git a/frontend/src/js/entity-history/VisibilityControl.tsx b/frontend/src/js/entity-history/VisibilityControl.tsx
index 31f43c50e8..1f605a8366 100644
--- a/frontend/src/js/entity-history/VisibilityControl.tsx
+++ b/frontend/src/js/entity-history/VisibilityControl.tsx
@@ -1,8 +1,9 @@
import { faEye, faEyeSlash } from "@fortawesome/free-regular-svg-icons";
import { memo } from "react";
import { useTranslation } from "react-i18next";
+import { Button } from "../ui-components/Button";
+import { Icon } from "../ui-components/Icon";
-import IconButton from "../button/IconButton";
import { Tooltip, TooltipTrigger } from "../ui-components/Tooltip";
const VisibilityControl = ({
@@ -17,11 +18,13 @@ const VisibilityControl = ({
return (
-
+
+
+
{t("history.blurred")}
diff --git a/frontend/src/js/entity-history/timeline-search/SearchControl.tsx b/frontend/src/js/entity-history/timeline-search/SearchControl.tsx
index 44b4a7a9e0..f5fc79ce12 100644
--- a/frontend/src/js/entity-history/timeline-search/SearchControl.tsx
+++ b/frontend/src/js/entity-history/timeline-search/SearchControl.tsx
@@ -1,7 +1,8 @@
import { faSearch } from "@fortawesome/free-solid-svg-icons";
import { memo } from "react";
import { useTranslation } from "react-i18next";
-import IconButton from "../../button/IconButton";
+import { Button } from "../../ui-components/Button";
+import { Icon } from "../../ui-components/Icon";
import { Tooltip, TooltipTrigger } from "../../ui-components/Tooltip";
import { useTimelineSearch } from "./timelineSearchState";
@@ -14,12 +15,14 @@ const SearchControl = () => {
return (
-
+
+
+
{t("history.search")}
diff --git a/frontend/src/js/external-forms/FormHeader.tsx b/frontend/src/js/external-forms/FormHeader.tsx
index a946c4c7f5..3465c33428 100644
--- a/frontend/src/js/external-forms/FormHeader.tsx
+++ b/frontend/src/js/external-forms/FormHeader.tsx
@@ -1,8 +1,8 @@
import { faBook } from "@fortawesome/free-solid-svg-icons";
import { useTranslation } from "react-i18next";
-
import { tv } from "tailwind-variants";
-import IconButton from "../button/IconButton";
+import { Button } from "../ui-components/Button";
+import { Icon } from "../ui-components/Icon";
const root = tv({
base: ["flex flex-col", "w-full", "gap-[7px]"],
@@ -29,9 +29,10 @@ const FormHeader = ({
{descriptionText}
{manualUrl && (
-
+
+
{t("externalForms.manualButton")}
-
+
)}
diff --git a/frontend/src/js/external-forms/FormsNavigation.tsx b/frontend/src/js/external-forms/FormsNavigation.tsx
index 8c6faecb01..0838744b4f 100644
--- a/frontend/src/js/external-forms/FormsNavigation.tsx
+++ b/frontend/src/js/external-forms/FormsNavigation.tsx
@@ -2,11 +2,11 @@ import { faTrash } from "@fortawesome/free-solid-svg-icons";
import { useTranslation } from "react-i18next";
import { useDispatch, useSelector } from "react-redux";
import { tv } from "tailwind-variants";
-
import type { StateT } from "../app/reducers";
-import IconButton from "../button/IconButton";
import { useActiveLang } from "../localization/useActiveLang";
+import { Button } from "../ui-components/Button";
import { ConfirmMenu } from "../ui-components/ConfirmMenu";
+import { Icon } from "../ui-components/Icon";
import InputSelect from "../ui-components/InputSelect/InputSelect";
import { Tooltip, TooltipTrigger } from "../ui-components/Tooltip";
@@ -77,11 +77,13 @@ const FormsNavigation = ({ onReset }: { onReset: () => void }) => {
onConfirm={onReset}
confirmationText={t("externalForms.common.clearConfirm")}
>
-
+
+
+
{t("externalForms.common.clear")}
diff --git a/frontend/src/js/external-forms/form-components/DropzoneList.tsx b/frontend/src/js/external-forms/form-components/DropzoneList.tsx
index 61a63c797c..54e6f5f4fd 100644
--- a/frontend/src/js/external-forms/form-components/DropzoneList.tsx
+++ b/frontend/src/js/external-forms/form-components/DropzoneList.tsx
@@ -2,8 +2,7 @@ import { faTimes } from "@fortawesome/free-solid-svg-icons";
import type { ReactNode, Ref } from "react";
import type { DropTargetMonitor } from "react-dnd";
import { tv } from "tailwind-variants";
-
-import IconButton from "../../button/IconButton";
+import { Button } from "../../ui-components/Button";
import type {
ChildArgs,
PossibleDroppableObject,
@@ -11,6 +10,7 @@ import type {
import DropzoneWithFileInput, {
type DragItemFile,
} from "../../ui-components/DropzoneWithFileInput";
+import { Icon } from "../../ui-components/Icon";
import InfoTooltip from "../../ui-components/InfoTooltip";
import Label from "../../ui-components/Label";
@@ -93,12 +93,14 @@ const DropzoneList = ({
/>
)}
- onDelete(i)}
className="absolute top-0 right-0"
- bgHover
- icon={faTimes}
- onClick={() => onDelete(i)}
- />
+ >
+
+
{item}
diff --git a/frontend/src/js/external-forms/form-components/DynamicInputGroup.tsx b/frontend/src/js/external-forms/form-components/DynamicInputGroup.tsx
index 86c5ff0b33..ac4a296147 100644
--- a/frontend/src/js/external-forms/form-components/DynamicInputGroup.tsx
+++ b/frontend/src/js/external-forms/form-components/DynamicInputGroup.tsx
@@ -1,9 +1,8 @@
import { faPlus, faTimes } from "@fortawesome/free-solid-svg-icons";
import type { ReactNode } from "react";
-
import { tv } from "tailwind-variants";
-
-import IconButton from "../../button/IconButton";
+import { Button } from "../../ui-components/Button";
+import { Icon } from "../../ui-components/Icon";
interface PropsT {
className?: string;
@@ -19,7 +18,7 @@ const container = tv({
});
const removeButton = tv({
- base: ["absolute -top-[7px] -right-[7px]", "z-1", "bg-white", "opacity-100"],
+ base: ["absolute -top-[7px] -right-[7px]", "z-1", "bg-white"],
});
const groupItem = tv({
@@ -52,18 +51,21 @@ const DynamicInputGroup = ({
you can also just delete the following constraint:
*/}
{limit !== 1 && (
- onRemoveClick(idx)}
className={removeButton()}
- bgHover
- tiny
- icon={faTimes}
- onClick={() => onRemoveClick(idx)}
- />
+ >
+
+
)}
))}
{limitNotReached && (
-
+
+
+
)}
);
diff --git a/frontend/src/js/external-forms/form-concept-group/FormConceptNode.tsx b/frontend/src/js/external-forms/form-concept-group/FormConceptNode.tsx
index 48115e5e0d..fbf094ed5b 100644
--- a/frontend/src/js/external-forms/form-concept-group/FormConceptNode.tsx
+++ b/frontend/src/js/external-forms/form-concept-group/FormConceptNode.tsx
@@ -6,13 +6,13 @@ import { useRef } from "react";
import { useDrag } from "react-dnd";
import { useTranslation } from "react-i18next";
import { tv } from "tailwind-variants";
-
import { getWidthAndHeight } from "../../app/DndProvider";
-import IconButton from "../../button/IconButton";
import { canNodeBeDropped } from "../../model/node";
import { HoverNavigatable } from "../../small-tab-navigation/HoverNavigatable";
import { getRootNodeLabel } from "../../standard-query-editor/helper";
import type { DragItemConceptTreeNode } from "../../standard-query-editor/types";
+import { Button } from "../../ui-components/Button";
+import { Icon } from "../../ui-components/Icon";
import {
Tooltip,
TooltipTarget,
@@ -160,15 +160,18 @@ const FormConceptNode = ({
{expand?.expandable && (
- {
- e.stopPropagation();
+ {
expand.onClick();
}}
- />
+ >
+
+
{t("externalForms.common.concept.expand")}
)}
diff --git a/frontend/src/js/external-forms/form-query-dropzone/FormQueryResult.tsx b/frontend/src/js/external-forms/form-query-dropzone/FormQueryResult.tsx
index 895989624c..c4598c93c9 100644
--- a/frontend/src/js/external-forms/form-query-dropzone/FormQueryResult.tsx
+++ b/frontend/src/js/external-forms/form-query-dropzone/FormQueryResult.tsx
@@ -1,9 +1,9 @@
import { faTimes } from "@fortawesome/free-solid-svg-icons";
import { tv } from "tailwind-variants";
-
-import IconButton from "../../button/IconButton";
import { exists } from "../../common/helpers/exists";
import type { DragItemQuery } from "../../standard-query-editor/types";
+import { Button } from "../../ui-components/Button";
+import { Icon } from "../../ui-components/Icon";
const root = tv({
base: [
@@ -43,7 +43,11 @@ const FormQueryResult = ({
) : queryResult ? (
queryResult.label || queryResult.id
) : null}
- {onDelete && }
+ {onDelete && (
+
+
+
+ )}
);
};
diff --git a/frontend/src/js/external-forms/form/fields/DisclosureListField.tsx b/frontend/src/js/external-forms/form/fields/DisclosureListField.tsx
index 561a56bebc..99bd4990b7 100644
--- a/frontend/src/js/external-forms/form/fields/DisclosureListField.tsx
+++ b/frontend/src/js/external-forms/form/fields/DisclosureListField.tsx
@@ -7,7 +7,6 @@ import {
import { type ComponentProps, useEffect, useState } from "react";
import { useFieldArray } from "react-hook-form";
import { tv } from "tailwind-variants";
-import IconButton from "../../../button/IconButton";
import { exists } from "../../../common/helpers/exists";
import { usePrevious } from "../../../common/helpers/usePrevious";
import { Button } from "../../../ui-components/Button";
@@ -82,11 +81,14 @@ const DisclosureField = ({
)}
{field.creatable && canRemove && (
- remove(index)}
className="absolute right-0 top-1/2 -translate-y-1/2"
- icon={faTimes}
- onClick={() => remove(index)}
- />
+ >
+
+
)}
diff --git a/frontend/src/js/header/HelpMenu.tsx b/frontend/src/js/header/HelpMenu.tsx
index e18bedfdae..3f7ec7a067 100644
--- a/frontend/src/js/header/HelpMenu.tsx
+++ b/frontend/src/js/header/HelpMenu.tsx
@@ -6,9 +6,8 @@ import {
} from "@fortawesome/free-solid-svg-icons";
import { MenuTrigger } from "react-aria-components";
import { useTranslation } from "react-i18next";
-
import { useAbout } from "../app/About";
-import IconButton from "../button/IconButton";
+import { Button } from "../ui-components/Button";
import { Icon } from "../ui-components/Icon";
import { Menu, MenuItem } from "../ui-components/Menu";
@@ -23,12 +22,9 @@ export const HelpMenu = ({ contactEmail, manualUrl }: Props) => {
return (
-
+
+
+
{
@@ -36,12 +36,13 @@ const LogoutButton = () => {
return (
-
+
+
+
{t("common.logout")}
);
diff --git a/frontend/src/js/info-pane/InfoPane.tsx b/frontend/src/js/info-pane/InfoPane.tsx
index 4ba7f30bf0..98b1dfcdb8 100644
--- a/frontend/src/js/info-pane/InfoPane.tsx
+++ b/frontend/src/js/info-pane/InfoPane.tsx
@@ -10,8 +10,8 @@ import remarkFlexibleMarkers from "remark-flexible-markers";
import remarkGfm from "remark-gfm";
import { tv } from "tailwind-variants";
import type { StateT } from "../app/reducers";
-import IconButton from "../button/IconButton";
import { Highlighter } from "../common/components/Highlighter";
+import { Button } from "../ui-components/Button";
import { Icon } from "../ui-components/Icon";
import { toggleAdditionalInfos as toggleInfos } from "./actions";
import InfoPaneCollapsed from "./InfoPaneCollapsed";
@@ -50,10 +50,7 @@ const head = tv({
const typeIcon = tv({ base: ["mt-px", "mr-[6px]", "text-primary-500"] });
-const tackButton = tv({
- // inline-flex to remove some height that seemed to be added
- base: ["inline-flex", "ml-[5px]"],
-});
+const tackButton = tv({ base: "ml-[5px]" });
const pinnedLabel = tv({
base: ["flex flex-row items-start", "m-0", "leading-[1.2]", "text-sm"],
@@ -187,13 +184,15 @@ const InfoPane = () => {
conceptIcon={mainIcon}
tackIcon={
toggleAdditionalInfos && (
-
+ >
+
+
)
}
/>
diff --git a/frontend/src/js/info-pane/InfoPaneCollapsed.tsx b/frontend/src/js/info-pane/InfoPaneCollapsed.tsx
index 801921b4c1..56395adc4e 100644
--- a/frontend/src/js/info-pane/InfoPaneCollapsed.tsx
+++ b/frontend/src/js/info-pane/InfoPaneCollapsed.tsx
@@ -1,18 +1,18 @@
import { faAngleRight } from "@fortawesome/free-solid-svg-icons";
import { useDispatch } from "react-redux";
import { tv } from "tailwind-variants";
-
-import IconButton from "../button/IconButton";
+import { Button } from "../ui-components/Button";
+import { Icon } from "../ui-components/Icon";
import { toggleInfoPane } from "./actions";
const button = tv({
base: [
"absolute top-[40px] right-0 bottom-0",
- "w-full",
- "p-3",
+ "w-full h-auto",
+ "pt-3",
"rounded-none",
- "flex items-start",
+ "items-start",
],
});
@@ -22,12 +22,9 @@ const InfoPaneCollapsed = () => {
return (
-
+
+
+
);
};
diff --git a/frontend/src/js/info-pane/InfoPaneHeader.tsx b/frontend/src/js/info-pane/InfoPaneHeader.tsx
index c52042b1d5..8149c68d08 100644
--- a/frontend/src/js/info-pane/InfoPaneHeader.tsx
+++ b/frontend/src/js/info-pane/InfoPaneHeader.tsx
@@ -3,7 +3,8 @@ import { memo } from "react";
import { useTranslation } from "react-i18next";
import { useDispatch } from "react-redux";
import { tv } from "tailwind-variants";
-import IconButton from "../button/IconButton";
+import { Button } from "../ui-components/Button";
+import { Icon } from "../ui-components/Icon";
import { toggleInfoPane } from "./actions";
const header = tv({
@@ -34,12 +35,13 @@ export const InfoPaneHeader = memo(() => {
return (
<>
-
+ >
+
+
{t("infoPane.headline")}
>
);
diff --git a/frontend/src/js/preview/Charts.tsx b/frontend/src/js/preview/Charts.tsx
index 3e013e06e7..1597f2297e 100644
--- a/frontend/src/js/preview/Charts.tsx
+++ b/frontend/src/js/preview/Charts.tsx
@@ -3,7 +3,8 @@ import { t } from "i18next";
import { useHotkeys } from "react-hotkeys-hook";
import { tv } from "tailwind-variants";
import type { PreviewStatistics } from "../api/types";
-import IconButton from "../button/IconButton";
+import { Button } from "../ui-components/Button";
+import { Icon } from "../ui-components/Icon";
import Diagram from "./Diagram";
const diagram = tv({
@@ -74,20 +75,24 @@ export default function Charts({
})}
- updatePage(-1)}
- disabled={page === 0}
- />
+ updatePage(-1)}
+ isDisabled={page === 0}
+ >
+
+
{t("preview.page")} {page + 1}/
{Math.ceil(statistics.length / DIAGRAMS_PER_PAGE)}
- updatePage(1)}
- disabled={page === maxPage - 1}
- />
+ updatePage(1)}
+ isDisabled={page === maxPage - 1}
+ >
+
+
);
diff --git a/frontend/src/js/preview/ScrollBox.tsx b/frontend/src/js/preview/ScrollBox.tsx
index 882fafd144..12b08b0370 100644
--- a/frontend/src/js/preview/ScrollBox.tsx
+++ b/frontend/src/js/preview/ScrollBox.tsx
@@ -7,7 +7,8 @@ import {
useState,
} from "react";
import { tv } from "tailwind-variants";
-import IconButton from "../button/IconButton";
+import { Button } from "../ui-components/Button";
+import { Icon } from "../ui-components/Icon";
const root = tv({ base: "overflow-auto" });
@@ -49,14 +50,15 @@ export default function ScrollBox({
return (
{showButton && (
-
+
scrollBoxRef.current?.scrollTo({ top: 0, behavior: "smooth" })
}
- />
+ className={scrollTopButton()}
+ >
+
+
)}
{children}
diff --git a/frontend/src/js/previous-queries/list/DeleteProjectItemButton.tsx b/frontend/src/js/previous-queries/list/DeleteProjectItemButton.tsx
index 2df56fd682..743537523b 100644
--- a/frontend/src/js/previous-queries/list/DeleteProjectItemButton.tsx
+++ b/frontend/src/js/previous-queries/list/DeleteProjectItemButton.tsx
@@ -1,9 +1,9 @@
import { faTimes } from "@fortawesome/free-solid-svg-icons";
import { useCallback, useMemo } from "react";
import { useTranslation } from "react-i18next";
-
-import IconButton from "../../button/IconButton";
+import { Button } from "../../ui-components/Button";
import { ConfirmMenu } from "../../ui-components/ConfirmMenu";
+import { Icon } from "../../ui-components/Icon";
import { Tooltip, TooltipTrigger } from "../../ui-components/Tooltip";
import { useRemoveFormConfig, useRemoveQuery } from "./actions";
import { isFormConfig } from "./helpers";
@@ -33,12 +33,14 @@ export const DeleteProjectItemButton = ({ item }: { item: ProjectItemT }) => {
return (
-
+ >
+
+
{t("common.delete")}
diff --git a/frontend/src/js/previous-queries/list/Folders.tsx b/frontend/src/js/previous-queries/list/Folders.tsx
index ba4f1eafa8..e75729a7f1 100644
--- a/frontend/src/js/previous-queries/list/Folders.tsx
+++ b/frontend/src/js/previous-queries/list/Folders.tsx
@@ -3,14 +3,14 @@ import { useCallback, useEffect, useRef, useState } from "react";
import { useTranslation } from "react-i18next";
import { useDispatch, useSelector } from "react-redux";
import { tv } from "tailwind-variants";
-
import type { StateT } from "../../app/reducers";
-import IconButton from "../../button/IconButton";
import { DNDType } from "../../common/constants/dndTypes";
import { useResizeObserver } from "../../common/helpers/useResizeObserver";
import type { DragItemFormConfig } from "../../external-forms/types";
import type { DragItemQuery } from "../../standard-query-editor/types";
+import { Button } from "../../ui-components/Button";
import Dropzone from "../../ui-components/Dropzone";
+import { Icon } from "../../ui-components/Icon";
import { Tooltip, TooltipTrigger } from "../../ui-components/Tooltip";
import {
removeFolderFromFilter,
@@ -46,8 +46,6 @@ const deleteButton = tv({
"absolute top-0 right-0",
"invisible group-hover/folder:visible",
"bg-bg-50",
- "px-2 py-[2px]",
- "opacity-100",
"rounded-none",
],
});
@@ -191,15 +189,15 @@ const Folders = ({ className }: { className?: string }) => {
className="mb-3 flex w-full min-w-[100px] items-start"
ref={parentRef}
>
- setShowAddFolderModal(true)}
+ setShowAddFolderModal(true)}
+ className="text-left"
>
+
{isNarrow ? t("folders.addShort") : t("folders.add")}
-
+
{showAddFolderModal && (
{
resultWords={searchResultWords}
/>
- {
+ {
setFolderToDelete(folder);
- e.stopPropagation();
}}
- />
+ className={deleteButton()}
+ >
+
+
{t("common.delete")}
>
diff --git a/frontend/src/js/previous-queries/list/FoldersToggleButton.tsx b/frontend/src/js/previous-queries/list/FoldersToggleButton.tsx
index 2b37aa4ca6..d9973b3ca3 100644
--- a/frontend/src/js/previous-queries/list/FoldersToggleButton.tsx
+++ b/frontend/src/js/previous-queries/list/FoldersToggleButton.tsx
@@ -1,7 +1,8 @@
import { faFolder } from "@fortawesome/free-solid-svg-icons";
import { useTranslation } from "react-i18next";
+import { Button } from "../../ui-components/Button";
+import { Icon } from "../../ui-components/Icon";
-import IconButton from "../../button/IconButton";
import { Tooltip, TooltipTrigger } from "../../ui-components/Tooltip";
const FoldersToggleButton = ({
@@ -15,13 +16,15 @@ const FoldersToggleButton = ({
return (
-
+
+
+
{t("previousQueriesFolderButton.tooltip")}
);
diff --git a/frontend/src/js/previous-queries/list/ProjectItem.tsx b/frontend/src/js/previous-queries/list/ProjectItem.tsx
index 6463213ede..bd552596f9 100644
--- a/frontend/src/js/previous-queries/list/ProjectItem.tsx
+++ b/frontend/src/js/previous-queries/list/ProjectItem.tsx
@@ -17,13 +17,13 @@ import { tv } from "tailwind-variants";
import type { ResultUrlWithLabel, SecondaryId } from "../../api/types";
import type { StateT } from "../../app/reducers";
import DownloadButton from "../../button/DownloadButton";
-import IconButton from "../../button/IconButton";
import { Highlighter } from "../../common/components/Highlighter";
import { formatDate } from "../../common/helpers/dateHelper";
import { exists } from "../../common/helpers/exists";
import { useFormLabelByType } from "../../external-forms/stateSelectors";
import FormSymbol from "../../symbols/FormSymbol";
import QuerySymbol from "../../symbols/QuerySymbol";
+import { Button } from "../../ui-components/Button";
import { Icon } from "../../ui-components/Icon";
import {
Tooltip,
@@ -139,13 +139,15 @@ const ShareButton = ({
const { t } = useTranslation();
return (
-
+ onPress={onClick}
+ >
+
+
{
@@ -184,8 +186,6 @@ const ResultsLabel = ({
@@ -265,14 +265,17 @@ const ProjectItem = ({
-
+ >
+
+
{ }
@@ -295,7 +298,14 @@ const ProjectItem = ({
{executedAt}
{secondaryId && (
- {}} />
+ {}}
+ >
+
+
{`${t("queryEditor.secondaryId")}: ${secondaryId.label}`}
)}
diff --git a/frontend/src/js/previous-queries/list/ShareProjectItemModal.tsx b/frontend/src/js/previous-queries/list/ShareProjectItemModal.tsx
index 209226b966..13f3576161 100644
--- a/frontend/src/js/previous-queries/list/ShareProjectItemModal.tsx
+++ b/frontend/src/js/previous-queries/list/ShareProjectItemModal.tsx
@@ -2,11 +2,11 @@ import { faCheck, faSpinner } from "@fortawesome/free-solid-svg-icons";
import { useEffect, useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import { useSelector } from "react-redux";
-
import type { SelectOptionT, UserGroupT } from "../../api/types";
import type { StateT } from "../../app/reducers";
-import IconButton from "../../button/IconButton";
import Modal from "../../modal/Modal";
+import { Button } from "../../ui-components/Button";
+import { Icon } from "../../ui-components/Icon";
import InputMultiSelect from "../../ui-components/InputMultiSelect/InputMultiSelect";
import { Tooltip, TooltipTrigger } from "../../ui-components/Tooltip";
import {
@@ -147,13 +147,15 @@ const ShareProjectItemModal = ({ item, onClose }: PropsT) => {
options={userGroupOptions}
/>
-
+ isDisabled={buttonDisabled}
+ className="ml-[3px]"
+ >
+
+
{shareLabel}
diff --git a/frontend/src/js/previous-queries/upload/CSVColumnPicker.tsx b/frontend/src/js/previous-queries/upload/CSVColumnPicker.tsx
index 2034ce85a6..08f082ca73 100644
--- a/frontend/src/js/previous-queries/upload/CSVColumnPicker.tsx
+++ b/frontend/src/js/previous-queries/upload/CSVColumnPicker.tsx
@@ -13,7 +13,6 @@ import { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { tv } from "tailwind-variants";
import type { QueryUploadConfigT, UploadQueryResponseT } from "../../api/types";
-import IconButton from "../../button/IconButton";
import { parseCSV, toCSV } from "../../file/csv";
import { useActiveLang } from "../../localization/useActiveLang";
import ScrollableList from "../../scrollable-list/ScrollableList";
@@ -259,7 +258,13 @@ const CSVColumnPicker = ({
{csv.length} Zeilen
-
+
+
+
{t("common.clear")}
diff --git a/frontend/src/js/previous-queries/upload/UploadQueryResults.tsx b/frontend/src/js/previous-queries/upload/UploadQueryResults.tsx
index 92c661705c..c4c170ba29 100644
--- a/frontend/src/js/previous-queries/upload/UploadQueryResults.tsx
+++ b/frontend/src/js/previous-queries/upload/UploadQueryResults.tsx
@@ -2,7 +2,6 @@ import { faUpload } from "@fortawesome/free-solid-svg-icons";
import { useState } from "react";
import { useTranslation } from "react-i18next";
import { useDispatch, useSelector } from "react-redux";
-
import { usePostQueryUpload } from "../../api/api";
import type {
DatasetT,
@@ -10,8 +9,9 @@ import type {
UploadQueryResponseT,
} from "../../api/types";
import type { StateT } from "../../app/reducers";
-import IconButton from "../../button/IconButton";
import { setMessage } from "../../snack-message/actions";
+import { Button } from "../../ui-components/Button";
+import { Icon } from "../../ui-components/Icon";
import { Tooltip, TooltipTrigger } from "../../ui-components/Tooltip";
import { useLoadQueries } from "../list/actions";
@@ -77,12 +77,13 @@ const UploadQueryResults = ({
return (
- setIsModalOpen(true)}
- />
+ setIsModalOpen(true)}
+ >
+
+
{t("uploadQueryResults.uploadResults")}
{isModalOpen && (
diff --git a/frontend/src/js/query-group-modal/QueryGroupModal.tsx b/frontend/src/js/query-group-modal/QueryGroupModal.tsx
index 1dd250bd93..7f00c18742 100644
--- a/frontend/src/js/query-group-modal/QueryGroupModal.tsx
+++ b/frontend/src/js/query-group-modal/QueryGroupModal.tsx
@@ -4,12 +4,13 @@ import { useTranslation } from "react-i18next";
import { useDispatch, useSelector } from "react-redux";
import { tv } from "tailwind-variants";
import type { StateT } from "../app/reducers";
-import IconButton from "../button/IconButton";
import type { DateStringMinMax } from "../common/helpers/dateHelper";
import Modal from "../modal/Modal";
import { nodeIsConceptQueryNode } from "../model/node";
import type { StandardQueryStateT } from "../standard-query-editor/queryReducer";
import type { QueryGroupType } from "../standard-query-editor/types";
+import { Button } from "../ui-components/Button";
+import { Icon } from "../ui-components/Icon";
import InputDateRange from "../ui-components/InputDateRange";
import {
@@ -81,14 +82,15 @@ const QueryGroupModal = ({
const labelSuffix = useMemo(() => {
return hasActiveDate ? (
-
+
{t("queryNodeEditor.reset")}
-
+
) : null;
}, [t, hasActiveDate, onResetAllDates]);
diff --git a/frontend/src/js/query-node-editor/ConceptEntry.tsx b/frontend/src/js/query-node-editor/ConceptEntry.tsx
index 98415555cb..e1052c3ce8 100644
--- a/frontend/src/js/query-node-editor/ConceptEntry.tsx
+++ b/frontend/src/js/query-node-editor/ConceptEntry.tsx
@@ -1,11 +1,11 @@
import { faTrashCan } from "@fortawesome/free-regular-svg-icons";
import { useTranslation } from "react-i18next";
import { tv } from "tailwind-variants";
-
import type { ConceptIdT, ConceptT } from "../api/types";
-import IconButton from "../button/IconButton";
import { getConceptById } from "../concept-trees/globalTreeStoreHelper";
import AdditionalInfoHoverable from "../info-pane/AdditionalInfoHoverable";
+import { Button } from "../ui-components/Button";
+import { Icon } from "../ui-components/Icon";
const concept = tv({
base: [
@@ -58,12 +58,14 @@ const ConceptEntry = ({
)}
{canRemoveConcepts && (
- onRemoveConcept(conceptId)}
className="shrink-0"
- onClick={() => onRemoveConcept(conceptId)}
- tiny
- icon={faTrashCan}
- />
+ >
+
+
)}
);
diff --git a/frontend/src/js/query-node-editor/MenuColumnItem.tsx b/frontend/src/js/query-node-editor/MenuColumnItem.tsx
index 1a81f4dd59..81f6df2af4 100644
--- a/frontend/src/js/query-node-editor/MenuColumnItem.tsx
+++ b/frontend/src/js/query-node-editor/MenuColumnItem.tsx
@@ -2,11 +2,11 @@ import { faCheckSquare, faSquare } from "@fortawesome/free-regular-svg-icons";
import { faFilter } from "@fortawesome/free-solid-svg-icons";
import { useTranslation } from "react-i18next";
import { tv } from "tailwind-variants";
-
-import IconButton from "../button/IconButton";
import type { NodeResetConfig } from "../model/node";
import { tableHasFilterValues, tableIsDisabled } from "../model/table";
import type { TableWithFilterValueT } from "../standard-query-editor/types";
+import { Button } from "../ui-components/Button";
+import { Icon } from "../ui-components/Icon";
import { Tooltip, TooltipTrigger } from "../ui-components/Tooltip";
const container = tv({
@@ -30,15 +30,6 @@ const container = tv({
},
});
-const toggleButton = tv({
- base: [
- "p-0",
- "text-xl",
- "leading-[20px]",
- "[&_svg]:text-xl [&_svg]:leading-[20px]",
- ],
-});
-
const MenuColumnItem = ({
table,
isOnlyOneTableIncluded,
@@ -74,13 +65,11 @@ const MenuColumnItem = ({
// biome-ignore lint/a11y/noStaticElementInteractions: see above
- {
+ {
// To prevent selecting the table as well, see above
- event.stopPropagation();
if (isDisabled) {
return;
@@ -90,18 +79,23 @@ const MenuColumnItem = ({
onToggleTable(!table.exclude);
}
}}
- />
+ size="sm"
+ >
+
+
{table.label}
{isFilterActive && (
- {
+ {
// To prevent selecting the table as well, see above
- event.stopPropagation();
if (isDisabled) {
return;
@@ -109,7 +103,9 @@ const MenuColumnItem = ({
onResetTable({ useDefaults: false });
}}
- />
+ >
+
+
{t("queryNodeEditor.clearSettings")}
)}
diff --git a/frontend/src/js/query-node-editor/ResetAllSettingsButton.tsx b/frontend/src/js/query-node-editor/ResetAllSettingsButton.tsx
index 23cb88a9f5..987b5e3ae5 100644
--- a/frontend/src/js/query-node-editor/ResetAllSettingsButton.tsx
+++ b/frontend/src/js/query-node-editor/ResetAllSettingsButton.tsx
@@ -1,8 +1,8 @@
import { faTrash } from "@fortawesome/free-solid-svg-icons";
import { useTranslation } from "react-i18next";
-
-import IconButton from "../button/IconButton";
+import { Button } from "../ui-components/Button";
import { ConfirmMenu } from "../ui-components/ConfirmMenu";
+import { Icon } from "../ui-components/Icon";
import { Tooltip, TooltipTrigger } from "../ui-components/Tooltip";
const ResetAllSettingsButton = ({
@@ -17,9 +17,10 @@ const ResetAllSettingsButton = ({
const confirmationText = t("queryNodeEditor.clearAllSettingsConfirm");
const trigger = (
-
+
+
{compact ? null : text}
-
+
);
return compact ? (
diff --git a/frontend/src/js/query-node-editor/ResetAndClose.tsx b/frontend/src/js/query-node-editor/ResetAndClose.tsx
index 7d25570311..9d60f55b62 100644
--- a/frontend/src/js/query-node-editor/ResetAndClose.tsx
+++ b/frontend/src/js/query-node-editor/ResetAndClose.tsx
@@ -22,7 +22,7 @@ const ResetAndClose = ({
const { t } = useTranslation();
return (
-
+
{showClearReset && (
onResetAllSettings({ useDefaults: false })}
diff --git a/frontend/src/js/query-runner/DownloadResultsDropdownButton.tsx b/frontend/src/js/query-runner/DownloadResultsDropdownButton.tsx
index 705bef818d..e39b197d74 100644
--- a/frontend/src/js/query-runner/DownloadResultsDropdownButton.tsx
+++ b/frontend/src/js/query-runner/DownloadResultsDropdownButton.tsx
@@ -3,11 +3,10 @@ import { memo, useContext, useEffect, useMemo, useState } from "react";
import { MenuTrigger } from "react-aria-components";
import { useTranslation } from "react-i18next";
import { tv } from "tailwind-variants";
-
import type { ResultUrlWithLabel } from "../api/types";
import { AuthTokenContext } from "../authorization/AuthTokenProvider";
import DownloadButton, { getFileIcon } from "../button/DownloadButton";
-import IconButton from "../button/IconButton";
+import { Button } from "../ui-components/Button";
import { Icon } from "../ui-components/Icon";
import { Menu, MenuItem } from "../ui-components/Menu";
import { Tooltip, TooltipTrigger } from "../ui-components/Tooltip";
@@ -29,8 +28,6 @@ const downloadButton = tv({
base: ["[&_button]:w-full", "[&_button]:px-[14px] [&_button]:py-2"],
});
-const dropdownOpenButton = tv({ base: "px-2 py-[9px]" });
-
const separator = tv({ base: ["h-[33px] w-px", "bg-gray-500"] });
interface FileChoice {
@@ -99,7 +96,6 @@ const DownloadResultsDropdownButton = ({
<>
@@ -110,11 +106,9 @@ const DownloadResultsDropdownButton = ({
)}
-
+
+
+
{
diff --git a/frontend/src/js/search-bar/SearchBar.tsx b/frontend/src/js/search-bar/SearchBar.tsx
index db2ef181ce..251de7bc78 100644
--- a/frontend/src/js/search-bar/SearchBar.tsx
+++ b/frontend/src/js/search-bar/SearchBar.tsx
@@ -1,17 +1,17 @@
import { faSearch } from "@fortawesome/free-solid-svg-icons";
import { memo, useEffect, useState } from "react";
import { tv } from "tailwind-variants";
-
-import IconButton from "../button/IconButton";
import { exists } from "../common/helpers/exists";
import BaseInput from "../ui-components/BaseInput";
+import { Button } from "../ui-components/Button";
+import { Icon } from "../ui-components/Icon";
const inputContainer = tv({ base: ["relative", "grow"] });
const baseInput = tv({
base: [
"w-full",
- "[&_input]:h-[34px] [&_input]:w-full",
+ "[&_input]:h-[30px] [&_input]:w-full",
"[&_input]:pr-[60px]",
"[&_input]:placeholder:text-gray-400",
"[&_input]:placeholder:opacity-100",
@@ -22,11 +22,11 @@ const right = tv({
base: [
"absolute top-0 right-[30px]",
"flex flex-row items-center",
- "h-[34px]",
+ "h-[30px]",
],
});
-const searchButton = tv({ base: ["px-[10px] py-2", "text-gray-500"] });
+const searchButton = tv({ base: "text-gray-500" });
interface Props {
className?: string;
@@ -71,12 +71,14 @@ const SearchBar = ({
/>
{exists(localSearchTerm) && (
- onSearch(localSearchTerm)}
- />
+ onPress={() => onSearch(localSearchTerm)}
+ className={searchButton()}
+ >
+
+
)}
diff --git a/frontend/src/js/snack-message/SnackMessage.tsx b/frontend/src/js/snack-message/SnackMessage.tsx
index e37af837f0..b18d69c4a0 100644
--- a/frontend/src/js/snack-message/SnackMessage.tsx
+++ b/frontend/src/js/snack-message/SnackMessage.tsx
@@ -1,9 +1,11 @@
import { faTimes } from "@fortawesome/free-solid-svg-icons";
import { memo, useRef } from "react";
+import { useTranslation } from "react-i18next";
import { useDispatch, useSelector } from "react-redux";
import { tv } from "tailwind-variants";
import type { StateT } from "../app/reducers";
import { useClickOutside } from "../common/helpers/useClickOutside";
+import { Button } from "../ui-components/Button";
import { Icon } from "../ui-components/Icon";
import { resetMessage as resetMessageAction } from "./actions";
import type { SnackMessageStateT } from "./reducer";
@@ -34,6 +36,7 @@ export const SnackMessage = memo(function SnackMessageComponent() {
const { message, type } = useSelector
(
(state) => state.snackMessage,
);
+ const { t } = useTranslation();
const dispatch = useDispatch();
const resetMessage = () => dispatch(resetMessageAction());
@@ -50,13 +53,14 @@ export const SnackMessage = memo(function SnackMessageComponent() {
{/* biome-ignore lint/security/noDangerouslySetInnerHtml: messages are our own i18n text */}
-
-
+
)}
diff --git a/frontend/src/js/standard-query-editor/QueryClearButton.tsx b/frontend/src/js/standard-query-editor/QueryClearButton.tsx
index 077313359c..cd9d192aab 100644
--- a/frontend/src/js/standard-query-editor/QueryClearButton.tsx
+++ b/frontend/src/js/standard-query-editor/QueryClearButton.tsx
@@ -1,9 +1,9 @@
import { faTrash } from "@fortawesome/free-solid-svg-icons";
import { useTranslation } from "react-i18next";
import { useDispatch } from "react-redux";
-
-import IconButton from "../button/IconButton";
+import { Button } from "../ui-components/Button";
import { ConfirmMenu } from "../ui-components/ConfirmMenu";
+import { Icon } from "../ui-components/Icon";
import { Tooltip, TooltipTrigger } from "../ui-components/Tooltip";
import { clearQuery } from "./actions";
@@ -20,7 +20,14 @@ const QueryClearButton = ({ className }: { className?: string }) => {
confirmationText={t(`queryEditor.clearConfirm`)}
onConfirm={onClearQuery}
>
-
+
+
+
{t("queryEditor.clear")}
diff --git a/frontend/src/js/standard-query-editor/QueryGroupActions.tsx b/frontend/src/js/standard-query-editor/QueryGroupActions.tsx
index 722f425eef..ae18517cd5 100644
--- a/frontend/src/js/standard-query-editor/QueryGroupActions.tsx
+++ b/frontend/src/js/standard-query-editor/QueryGroupActions.tsx
@@ -3,8 +3,9 @@ import { faBan, faTimes } from "@fortawesome/free-solid-svg-icons";
import { memo } from "react";
import { useTranslation } from "react-i18next";
import { tv } from "tailwind-variants";
+import { Button } from "../ui-components/Button";
+import { Icon } from "../ui-components/Icon";
-import IconButton from "../button/IconButton";
import {
Tooltip,
TooltipTrigger,
@@ -17,7 +18,7 @@ const actions = tv({
});
const dateButton = tv({
- base: ["mr-[5px]", "px-[3px] py-0"],
+ base: "mr-[5px]",
variants: {
active: {
true: "underline",
@@ -26,16 +27,8 @@ const dateButton = tv({
},
});
-const excludeButton = tv({
- base: ["mr-[5px]", "px-[3px] py-0", "hover:opacity-70"],
- variants: {
- active: {
- // beats IconButton's own colors (incl. its red flag) via merge
- true: ["text-red hover:text-red", "[&_svg]:text-red"],
- false: ["text-gray-800 hover:text-gray-800", "[&_svg]:text-gray-800"],
- },
- },
-});
+// excluding is a warning state: pressed shows red, not the usual primary
+const excludeButton = tv({ base: ["mr-[5px]", "aria-pressed:text-red"] });
interface PropsT {
excludeActive: boolean;
@@ -58,34 +51,42 @@ const QueryGroupActions = ({
-
+
{t("queryEditor.exclude")}
-
+
{t("help.queryEditorExclude")}
-
+
{t("queryEditor.date")}
-
+
{t("help.queryEditorDate")}
-
+
+
+
{t("queryEditor.removeColumn")}
diff --git a/frontend/src/js/standard-query-editor/QueryNodeActions.tsx b/frontend/src/js/standard-query-editor/QueryNodeActions.tsx
index 1b07cd4f34..fc36aa6b16 100644
--- a/frontend/src/js/standard-query-editor/QueryNodeActions.tsx
+++ b/frontend/src/js/standard-query-editor/QueryNodeActions.tsx
@@ -8,8 +8,8 @@ import {
import { memo } from "react";
import { useTranslation } from "react-i18next";
import { tv } from "tailwind-variants";
+import { Button } from "../ui-components/Button";
-import IconButton from "../button/IconButton";
import { Icon } from "../ui-components/Icon";
import {
Tooltip,
@@ -17,10 +17,6 @@ import {
TooltipTrigger,
} from "../ui-components/Tooltip";
-const actionButton = tv({
- base: "px-[6px] py-1",
-});
-
const crossedOut = tv({
base: [
"absolute top-[40%] left-[10%]",
@@ -54,27 +50,30 @@ const QueryNodeActions = (props: Props) => {
return (
- {
- e.stopPropagation();
+ {
props.onDeleteNode(props.andIdx, props.orIdx);
}}
- />
+ >
+
+
{t("queryEditor.removeNode")}
{props.excludeTimestamps && (
- {
- e.stopPropagation();
+ {
props.onToggleTimestamps(props.andIdx, props.orIdx);
}}
- />
+ className="text-red"
+ >
+
+
{t("queryNodeEditor.excludingTimestamps")}
)}
@@ -92,29 +91,36 @@ const QueryNodeActions = (props: Props) => {
)}
{!props.error && props.isExpandable && !props.previousQueryLoading && (
- {
- e.stopPropagation();
+ {
props.onExpandClick();
}}
- />
+ >
+
+
{t("queryEditor.expand")}
)}
{props.hasActiveSecondaryId && (
-
{
- e.stopPropagation();
+ onPress={() => {
props.onToggleSecondaryIdExclude(props.andIdx, props.orIdx);
}}
- />
+ >
+
+
{props.excludeFromSecondaryId &&
}
diff --git a/frontend/src/js/ui-components/BaseInput.tsx b/frontend/src/js/ui-components/BaseInput.tsx
index e53ecb38b8..34d4d368f7 100644
--- a/frontend/src/js/ui-components/BaseInput.tsx
+++ b/frontend/src/js/ui-components/BaseInput.tsx
@@ -11,11 +11,10 @@ import {
} from "react";
import { useTranslation } from "react-i18next";
import { tv } from "tailwind-variants";
-
import type { CurrencyConfigT } from "../api/types";
-import IconButton from "../button/IconButton";
import { isEmpty } from "../common/helpers/commonHelper";
import { exists } from "../common/helpers/exists";
+import { Button } from "./Button";
import CurrencyInput from "./CurrencyInput";
import { Icon } from "./Icon";
import {
@@ -33,12 +32,12 @@ const input = tv({
"w-full",
"border border-gray-400",
"rounded",
- "py-[6px] pr-[30px] pl-[10px]",
+ "h-[30px] pr-[30px] pl-[10px]",
"text-sm",
"font-normal",
],
variants: {
- large: { true: "py-[10px] pr-[30px] pl-[14px] text-xl" },
+ large: { true: "h-9 pr-[30px] pl-[14px] text-base" },
disabled: { true: "opacity-50" },
},
});
@@ -205,15 +204,17 @@ const BaseInput = ({
{invalidText}
)}
-
onChange(null)}
- />
+ onPress={() => onChange(null)}
+ className={clearZoneIconButton()}
+ >
+
+
>
)}
diff --git a/frontend/src/js/ui-components/Button.tsx b/frontend/src/js/ui-components/Button.tsx
index 2a9aa9d35d..360bcc074b 100644
--- a/frontend/src/js/ui-components/Button.tsx
+++ b/frontend/src/js/ui-components/Button.tsx
@@ -9,7 +9,7 @@ import {
Button as RacButton,
type ButtonProps as RacButtonProps,
} from "react-aria-components";
-import { tv } from "tailwind-variants";
+import { type ClassValue, tv } from "tailwind-variants";
import { Icon } from "./Icon";
@@ -72,7 +72,7 @@ export interface ButtonProps
/** what the button does in its context; the look follows */
intent?: "primary" | "secondary" | "tertiary" | "danger" | "link";
size?: "sm" | "md" | "lg";
- className?: string;
+ className?: ClassValue;
style?: CSSProperties;
children?: ReactNode;
ref?: Ref
;
diff --git a/frontend/src/js/ui-components/CurrencyInput.tsx b/frontend/src/js/ui-components/CurrencyInput.tsx
index ed06ee3d29..8418726ef8 100644
--- a/frontend/src/js/ui-components/CurrencyInput.tsx
+++ b/frontend/src/js/ui-components/CurrencyInput.tsx
@@ -20,7 +20,7 @@ const numberFormat = tv({
"text-sm",
],
variants: {
- large: { true: "py-[10px] pr-[30px] pl-[14px] text-xl" },
+ large: { true: "h-9 pr-[30px] pl-[14px] text-base" },
},
});
diff --git a/frontend/src/js/ui-components/EditableTagsForm.tsx b/frontend/src/js/ui-components/EditableTagsForm.tsx
index 8b2cc6f70c..adb6c21f7d 100644
--- a/frontend/src/js/ui-components/EditableTagsForm.tsx
+++ b/frontend/src/js/ui-components/EditableTagsForm.tsx
@@ -2,10 +2,10 @@ import { faCheck, faSpinner } from "@fortawesome/free-solid-svg-icons";
import { type FormEvent, useRef, useState } from "react";
import { useTranslation } from "react-i18next";
import { tv } from "tailwind-variants";
-
import type { SelectOptionT } from "../api/types";
-import IconButton from "../button/IconButton";
import { useClickOutside } from "../common/helpers/useClickOutside";
+import { Button } from "./Button";
+import { Icon } from "./Icon";
import InputMultiSelect from "./InputMultiSelect/InputMultiSelect";
import { Tooltip, TooltipTrigger } from "./Tooltip";
@@ -14,7 +14,7 @@ const form = tv({
});
const saveButton = tv({
- base: ["ml-[3px]", "px-[10px] py-[7px]"],
+ base: "ml-[3px]",
});
const multiSelect = tv({
@@ -71,13 +71,15 @@ const EditableTagsForm = ({
placeholder={t("inputMultiSelect.tagPlaceholder")}
/>
-
+ isDisabled={!!loading}
+ className={saveButton()}
+ >
+
+
{t("common.save")}
diff --git a/frontend/src/js/ui-components/EditableText.tsx b/frontend/src/js/ui-components/EditableText.tsx
index 2b8cc0c825..a709544499 100644
--- a/frontend/src/js/ui-components/EditableText.tsx
+++ b/frontend/src/js/ui-components/EditableText.tsx
@@ -1,14 +1,13 @@
import { faPen } from "@fortawesome/free-solid-svg-icons";
import { tv } from "tailwind-variants";
-
-import IconButton from "../button/IconButton";
import { Highlighter } from "../common/components/Highlighter";
import HighlightableLabel from "../highlightable-label/HighlightableLabel";
+import { Button } from "./Button";
import EditableTextForm from "./EditableTextForm";
+import { Icon } from "./Icon";
import { Tooltip, TooltipTrigger } from "./Tooltip";
const editButton = tv({
- base: ["px-0 py-[2px]"],
variants: {
large: {
true: "mr-[10px]",
@@ -65,13 +64,15 @@ const EditableText = ({
) : (
-
+ >
+
+
{tooltip}
diff --git a/frontend/src/js/ui-components/EditableTextForm.tsx b/frontend/src/js/ui-components/EditableTextForm.tsx
index d1d169ad7a..07eae4bf11 100644
--- a/frontend/src/js/ui-components/EditableTextForm.tsx
+++ b/frontend/src/js/ui-components/EditableTextForm.tsx
@@ -2,9 +2,9 @@ import { faCheck, faSpinner } from "@fortawesome/free-solid-svg-icons";
import { type FormEvent, useRef, useState } from "react";
import { useTranslation } from "react-i18next";
import { tv } from "tailwind-variants";
-
-import IconButton from "../button/IconButton";
import { useClickOutside } from "../common/helpers/useClickOutside";
+import { Button } from "./Button";
+import { Icon } from "./Icon";
import { Tooltip, TooltipTrigger } from "./Tooltip";
const input = tv({
@@ -16,7 +16,7 @@ const form = tv({
});
const saveButton = tv({
- base: ["ml-[3px]", "px-[10px] py-[6px]"],
+ base: "ml-[3px]",
});
const EditableTextForm = ({
@@ -68,13 +68,15 @@ const EditableTextForm = ({
/>
{!saveOnClickoutside && (
-
+ isDisabled={loading}
+ className={saveButton()}
+ >
+
+
{t("common.save")}
)}
diff --git a/frontend/src/js/ui-components/Icon.stories.tsx b/frontend/src/js/ui-components/Icon.stories.tsx
index d8462a9045..e059345055 100644
--- a/frontend/src/js/ui-components/Icon.stories.tsx
+++ b/frontend/src/js/ui-components/Icon.stories.tsx
@@ -9,7 +9,6 @@ import {
faUser,
} from "@fortawesome/free-solid-svg-icons";
import type { Meta, StoryObj } from "@storybook/react";
-import IconButton from "../button/IconButton";
import { Button } from "./Button";
import { Icon } from "./Icon";
@@ -81,9 +80,10 @@ export const InheritsColor: Story = {
inside a button
-
+
+
red icon button
-
+
),
};
diff --git a/frontend/src/js/ui-components/ImportModal.tsx b/frontend/src/js/ui-components/ImportModal.tsx
index 88ee86c281..18d22eeb56 100644
--- a/frontend/src/js/ui-components/ImportModal.tsx
+++ b/frontend/src/js/ui-components/ImportModal.tsx
@@ -4,14 +4,13 @@ import { NativeTypes } from "react-dnd-html5-backend";
import { createPortal } from "react-dom";
import { useTranslation } from "react-i18next";
import { tv } from "tailwind-variants";
-import IconButton from "../button/IconButton";
import { getUniqueFileRows } from "../common/helpers/fileHelper";
import Modal from "../modal/Modal";
import { Button } from "./Button";
-
import DropzoneWithFileInput, {
type DragItemFile,
} from "./DropzoneWithFileInput";
+import { Icon } from "./Icon";
const content = tv({
base: ["flex flex-col", "gap-5"],
@@ -164,13 +163,15 @@ export const ImportModal = ({
)}
-
+
+
{t("common.openFileDialog")}
-
+
{canReadClipboard && (
-
+
+
{t("importModal.paste")}
-
+
)}
{
return (
-
+
+
+
-
+
+
+
);
};
diff --git a/frontend/src/js/ui-components/InputDate/InputDate.tsx b/frontend/src/js/ui-components/InputDate/InputDate.tsx
index 20d5410508..fdaf242cf6 100644
--- a/frontend/src/js/ui-components/InputDate/InputDate.tsx
+++ b/frontend/src/js/ui-components/InputDate/InputDate.tsx
@@ -1,11 +1,12 @@
import { faCalendar } from "@fortawesome/free-regular-svg-icons";
import { type Ref, useRef } from "react";
import ReactDatePicker from "react-datepicker";
+import { Button } from "../Button";
+import { Icon } from "../Icon";
import "react-datepicker/dist/react-datepicker.css";
import { mergeRefs } from "react-merge-refs";
import { tv } from "tailwind-variants";
-import IconButton from "../../button/IconButton";
import { formatDate, parseDate } from "../../common/helpers/dateHelper";
import BaseInput, { type Props as BaseInputProps } from "../BaseInput";
@@ -18,7 +19,7 @@ const root = tv({
});
const calendarButton = tv({
- base: ["absolute top-0 left-0", "px-[10px] py-2"],
+ base: "absolute top-0 left-0",
});
const baseInput = tv({
@@ -68,11 +69,13 @@ const InputDate = ({
},
}}
/>
- datePickerRef.current?.setOpen(true)}
className={calendarButton()}
- icon={faCalendar}
- onClick={() => datePickerRef.current?.setOpen(true)}
- />
+ >
+
+
}
{!loading && (inputValue.length > 0 || selectedItems.length > 0) && (
{
+ isDisabled={disabled}
+ onPress={() => {
setInputValue("");
resetMultiSelectState();
resetComboboxState();
}}
- />
+ >
+
+
)}
-
+
+
+
{isOpen ? (
diff --git a/frontend/src/js/ui-components/InputMultiSelect/SelectedItem.tsx b/frontend/src/js/ui-components/InputMultiSelect/SelectedItem.tsx
index 44bfe3fd74..79300abf3f 100644
--- a/frontend/src/js/ui-components/InputMultiSelect/SelectedItem.tsx
+++ b/frontend/src/js/ui-components/InputMultiSelect/SelectedItem.tsx
@@ -2,9 +2,9 @@ import { faTimes } from "@fortawesome/free-solid-svg-icons";
import { memo, type Ref } from "react";
import ReactMarkdown from "react-markdown";
import { tv } from "tailwind-variants";
-
import type { SelectOptionT } from "../../api/types";
-import IconButton from "../../button/IconButton";
+import { Button } from "../Button";
+import { Icon } from "../Icon";
const container = tv({
base: [
@@ -20,8 +20,6 @@ const container = tv({
],
});
-const removeButton = tv({ base: "py-px pr-[2px] pl-[5px]" });
-
const SelectedItem = ({
ref,
index,
@@ -52,15 +50,17 @@ const SelectedItem = ({
return (
{String(label)}
- {
- e.stopPropagation(); // otherwise the click handler on the Container overrides this
+ {
+ // otherwise the click handler on the Container overrides this
removeSelectedItem(item);
}}
- />
+ >
+
+
);
};
diff --git a/frontend/src/js/ui-components/InputSelect/InputSelect.tsx b/frontend/src/js/ui-components/InputSelect/InputSelect.tsx
index 261abd5ec1..189cddc5a9 100644
--- a/frontend/src/js/ui-components/InputSelect/InputSelect.tsx
+++ b/frontend/src/js/ui-components/InputSelect/InputSelect.tsx
@@ -3,11 +3,11 @@ import { useCombobox } from "downshift";
import { useCallback, useEffect, useRef, useState } from "react";
import { useTranslation } from "react-i18next";
import { mergeRefs } from "react-merge-refs";
-
import type { SelectOptionT } from "../../api/types";
import { exists } from "../../common/helpers/exists";
import { useClickOutside } from "../../common/helpers/useClickOutside";
import { usePrevious } from "../../common/helpers/usePrevious";
+import { Icon } from "../Icon";
import InfoTooltip from "../InfoTooltip";
import Labeled from "../Labeled";
import SelectEmptyPlaceholder from "../SelectEmptyPlaceholder";
@@ -269,23 +269,25 @@ const InputSelect = ({
{clearable && (inputValue.length > 0 || exists(selectedItem)) && (
{
+ isDisabled={disabled}
+ onPress={() => {
resetComboboxState();
if (clearable) {
onChange(null);
}
}}
- />
+ >
+
+
)}
+ >
+
+
{isOpen ? (
diff --git a/frontend/src/js/ui-components/InputSelect/InputSelectComponents.tsx b/frontend/src/js/ui-components/InputSelect/InputSelectComponents.tsx
index 40bfdc3015..ffa784269f 100644
--- a/frontend/src/js/ui-components/InputSelect/InputSelectComponents.tsx
+++ b/frontend/src/js/ui-components/InputSelect/InputSelectComponents.tsx
@@ -1,18 +1,20 @@
import type { ComponentProps } from "react";
import { tv } from "tailwind-variants";
-
-import IconButton from "../../button/IconButton";
+import { Button } from "../Button";
import SelectListOption from "./SelectListOption";
const control = tv({
base: [
- "flex items-start",
+ "flex items-center",
+ "min-h-[30px]",
"overflow-hidden",
"rounded-[4px]",
"border border-gray-500",
"bg-white",
- "py-1 pr-[3px] pl-2",
+ // 2 px + the 24 px buttons + the border fill the 30 px exactly; wrapped
+ // lines of chips keep off the edges
+ "py-0.5 pr-[3px] pl-2",
"focus:outline focus:outline-1 focus:outline-black",
],
variants: {
@@ -112,22 +114,18 @@ export const Input = ({ className, ...props }: ComponentProps<"input">) => (
);
-const dropdownToggleButton = tv({ base: "py-[2px] pr-1 pl-[6px]" });
-
export const DropdownToggleButton = ({
className,
...props
-}: ComponentProps) => (
-
+}: ComponentProps) => (
+
);
-const resetButton = tv({ base: ["w-[26px]", "px-2 py-[2px]"] });
-
export const ResetButton = ({
className,
...props
-}: ComponentProps) => (
-
+}: ComponentProps) => (
+
);
const verticalSeparator = tv({
diff --git a/frontend/src/js/ui-components/InputTextarea/InputTextarea.tsx b/frontend/src/js/ui-components/InputTextarea/InputTextarea.tsx
index 14609dec0f..84b3b0deda 100644
--- a/frontend/src/js/ui-components/InputTextarea/InputTextarea.tsx
+++ b/frontend/src/js/ui-components/InputTextarea/InputTextarea.tsx
@@ -2,8 +2,9 @@ import { faTimes } from "@fortawesome/free-solid-svg-icons";
import type { DetailedHTMLProps, Ref, TextareaHTMLAttributes } from "react";
import { useTranslation } from "react-i18next";
import { tv } from "tailwind-variants";
+import { Button } from "../Button";
+import { Icon } from "../Icon";
-import IconButton from "../../button/IconButton";
import Labeled from "../Labeled";
const textarea = tv({
@@ -70,14 +71,16 @@ export const InputTextarea = ({
value={props.value || ""}
/>
{props.value && (
- onChange(null)}
- />
+ onPress={() => onChange(null)}
+ className={clearZoneIconButton()}
+ >
+
+
)}
diff --git a/frontend/src/js/ui-components/Menu.stories.tsx b/frontend/src/js/ui-components/Menu.stories.tsx
index 5fc274d13b..ea8eaa08e0 100644
--- a/frontend/src/js/ui-components/Menu.stories.tsx
+++ b/frontend/src/js/ui-components/Menu.stories.tsx
@@ -6,7 +6,6 @@ import {
} from "@fortawesome/free-solid-svg-icons";
import type { Meta, StoryObj } from "@storybook/react";
import { MenuTrigger } from "react-aria-components";
-import IconButton from "../button/IconButton";
import { Button } from "./Button";
import { ConfirmMenu } from "./ConfirmMenu";
import { Icon } from "./Icon";
@@ -24,7 +23,9 @@ type Story = StoryObj;
export const Default: Story = {
render: () => (
-
+
+
+
console.log(key)}>
A link item
@@ -56,7 +57,9 @@ export const Confirm: Story = {
confirmationText="Delete for good"
onConfirm={() => {}}
>
-
+
+
+
),
@@ -66,7 +69,9 @@ export const WithTooltipOnTrigger: Story = {
render: () => (
{}}>
-
+
+
+
Delete
diff --git a/frontend/src/js/ui-components/Menu.tsx b/frontend/src/js/ui-components/Menu.tsx
index 894e2cffac..d27a34a2d9 100644
--- a/frontend/src/js/ui-components/Menu.tsx
+++ b/frontend/src/js/ui-components/Menu.tsx
@@ -47,7 +47,7 @@ const menuItem = tv({
* react-aria does it. The popover is part of the Menu:
*
*
- *
+ *
* …}>
* …
* …
diff --git a/frontend/src/js/ui-components/TooManyValues.tsx b/frontend/src/js/ui-components/TooManyValues.tsx
index 668bcc6254..6c985e59b3 100644
--- a/frontend/src/js/ui-components/TooManyValues.tsx
+++ b/frontend/src/js/ui-components/TooManyValues.tsx
@@ -1,8 +1,8 @@
import { faTimes } from "@fortawesome/free-solid-svg-icons";
import { useTranslation } from "react-i18next";
import { tv } from "tailwind-variants";
-
-import IconButton from "../button/IconButton";
+import { Button } from "./Button";
+import { Icon } from "./Icon";
const root = tv({
base: [
@@ -27,12 +27,14 @@ const TooManyValues = ({
return (
{t("queryNodeEditor.tooManyValues", { count })}
-
+ onPress={onClear}
+ >
+
+
);
};
diff --git a/frontend/src/js/ui-components/Tooltip.stories.tsx b/frontend/src/js/ui-components/Tooltip.stories.tsx
index 59c2b5a79f..94d231a29c 100644
--- a/frontend/src/js/ui-components/Tooltip.stories.tsx
+++ b/frontend/src/js/ui-components/Tooltip.stories.tsx
@@ -1,6 +1,5 @@
import { faInfoCircle, faTrash } from "@fortawesome/free-solid-svg-icons";
import type { Meta, StoryObj } from "@storybook/react";
-import IconButton from "../button/IconButton";
import { Button } from "./Button";
import { Icon } from "./Icon";
@@ -23,7 +22,9 @@ export const OnButtons: Story = {
render: () => (
-
+
+
+
Delete
@@ -63,7 +64,9 @@ export const Timing: Story = {
render: () => (
-
+
+
+
Names a control: short warm-up, neighbors open instantly
diff --git a/frontend/src/js/ui-components/Tooltip.tsx b/frontend/src/js/ui-components/Tooltip.tsx
index 008126f7ef..554a854cde 100644
--- a/frontend/src/js/ui-components/Tooltip.tsx
+++ b/frontend/src/js/ui-components/Tooltip.tsx
@@ -59,7 +59,7 @@ const arrow = tv({
* Wraps a trigger element and its Tooltip:
*
*
- *
+ *
* {text}
*
*