diff --git a/apps/webapp/app/assets/icons/KeyboardDownIcon.tsx b/apps/webapp/app/assets/icons/KeyboardDownIcon.tsx
new file mode 100644
index 0000000000..1ef015d900
--- /dev/null
+++ b/apps/webapp/app/assets/icons/KeyboardDownIcon.tsx
@@ -0,0 +1,17 @@
+export function KeyboardDownIcon({ className }: { className?: string }) {
+ return (
+
+ );
+}
diff --git a/apps/webapp/app/assets/icons/KeyboardLeftIcon.tsx b/apps/webapp/app/assets/icons/KeyboardLeftIcon.tsx
new file mode 100644
index 0000000000..6b6999e683
--- /dev/null
+++ b/apps/webapp/app/assets/icons/KeyboardLeftIcon.tsx
@@ -0,0 +1,17 @@
+export function KeyboardLeftIcon({ className }: { className?: string }) {
+ return (
+
+ );
+}
diff --git a/apps/webapp/app/assets/icons/KeyboardRightIcon.tsx b/apps/webapp/app/assets/icons/KeyboardRightIcon.tsx
new file mode 100644
index 0000000000..879e7e183c
--- /dev/null
+++ b/apps/webapp/app/assets/icons/KeyboardRightIcon.tsx
@@ -0,0 +1,17 @@
+export function KeyboardRightIcon({ className }: { className?: string }) {
+ return (
+
+ );
+}
diff --git a/apps/webapp/app/assets/icons/KeyboardUpIcon.tsx b/apps/webapp/app/assets/icons/KeyboardUpIcon.tsx
new file mode 100644
index 0000000000..d87f26488d
--- /dev/null
+++ b/apps/webapp/app/assets/icons/KeyboardUpIcon.tsx
@@ -0,0 +1,17 @@
+export function KeyboardUpIcon({ className }: { className?: string }) {
+ return (
+
+ );
+}
diff --git a/apps/webapp/app/assets/icons/KeyboardWindowsIcon.tsx b/apps/webapp/app/assets/icons/KeyboardWindowsIcon.tsx
new file mode 100644
index 0000000000..859a633a30
--- /dev/null
+++ b/apps/webapp/app/assets/icons/KeyboardWindowsIcon.tsx
@@ -0,0 +1,17 @@
+export function KeyboardWindowsIcon({ className }: { className?: string }) {
+ return (
+
+ );
+}
diff --git a/apps/webapp/app/components/ErrorDisplay.tsx b/apps/webapp/app/components/ErrorDisplay.tsx
index fb2be3cfeb..fcb720df88 100644
--- a/apps/webapp/app/components/ErrorDisplay.tsx
+++ b/apps/webapp/app/components/ErrorDisplay.tsx
@@ -49,7 +49,7 @@ export function ErrorDisplay({ title, message, button }: DisplayOptionsProps) {
{message && {message}}
diff --git a/apps/webapp/app/components/ListPagination.tsx b/apps/webapp/app/components/ListPagination.tsx
index 7ac60cd283..bdefc32399 100644
--- a/apps/webapp/app/components/ListPagination.tsx
+++ b/apps/webapp/app/components/ListPagination.tsx
@@ -30,10 +30,12 @@ function NextButton({ cursor }: { cursor?: string }) {
trailingIconClassName="text-text-dimmed"
className={cn(
"flex items-center",
- !path &&
- "cursor-not-allowed opacity-50 group-hover:bg-transparent group-hover:text-text-dimmed"
+ !path && "cursor-not-allowed opacity-50 group-hover/button:bg-transparent"
)}
onClick={(e) => !path && e.preventDefault()}
+ shortcut={{ key: "k" }}
+ tooltip="Next"
+ disabled={!path}
>
Next
@@ -51,10 +53,12 @@ function PreviousButton({ cursor }: { cursor?: string }) {
leadingIconClassName="text-text-dimmed"
className={cn(
"flex items-center",
- !path &&
- "cursor-not-allowed opacity-50 group-hover:bg-transparent group-hover:text-text-dimmed"
+ !path && "cursor-not-allowed opacity-50 group-hover/button:bg-transparent"
)}
onClick={(e) => !path && e.preventDefault()}
+ shortcut={{ key: "j" }}
+ tooltip="Previous"
+ disabled={!path}
>
Prev
diff --git a/apps/webapp/app/components/Shortcuts.tsx b/apps/webapp/app/components/Shortcuts.tsx
new file mode 100644
index 0000000000..d44359bb4e
--- /dev/null
+++ b/apps/webapp/app/components/Shortcuts.tsx
@@ -0,0 +1,148 @@
+import { Keyboard } from "lucide-react";
+import { Header3 } from "./primitives/Headers";
+import { Paragraph } from "./primitives/Paragraph";
+import {
+ Sheet,
+ SheetContent,
+ SheetDescription,
+ SheetHeader,
+ SheetTitle,
+ SheetTrigger,
+} from "./primitives/SheetV3";
+import { ShortcutKey } from "./primitives/ShortcutKey";
+import { Button } from "./primitives/Buttons";
+
+export function Shortcuts() {
+ return (
+
+
+
+
+
+
+
+
+
+
+ Keyboard shortcuts
+
+
+
+
+
+
General
+
+
+
+
+
+
+
+
+
+
+
+
+
+ to
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Runs page
+
+
+
+
+
+
+
+
+
+
+
+
Run page
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ to
+
+
+
+
+
+ Schedules page
+
+
+
+
+
+ Alerts page
+
+
+
+
+
+
+
+
+ );
+}
+
+function Shortcut({ children, name }: { children: React.ReactNode; name: string }) {
+ return (
+
+ {name}
+ {children}
+
+ );
+}
diff --git a/apps/webapp/app/components/navigation/HelpAndFeedbackPopover.tsx b/apps/webapp/app/components/navigation/HelpAndFeedbackPopover.tsx
index a68f1988c7..cb2f6a263c 100644
--- a/apps/webapp/app/components/navigation/HelpAndFeedbackPopover.tsx
+++ b/apps/webapp/app/components/navigation/HelpAndFeedbackPopover.tsx
@@ -19,7 +19,7 @@ import { Paragraph } from "../primitives/Paragraph";
import { Popover, PopoverContent, PopoverSideMenuTrigger } from "../primitives/Popover";
import { StepNumber } from "../primitives/StepNumber";
import { MenuCount, SideMenuItem } from "./SideMenuItem";
-
+import { Shortcuts } from "../Shortcuts";
export function HelpAndFeedback() {
const [isHelpMenuOpen, setHelpMenuOpen] = useState(false);
const currentPlan = useCurrentPlan();
@@ -84,6 +84,7 @@ export function HelpAndFeedback() {
data-action="changelog"
target="_blank"
/>
+
Need help?
diff --git a/apps/webapp/app/components/primitives/Buttons.tsx b/apps/webapp/app/components/primitives/Buttons.tsx
index 7cd4a83f2d..138b6ed5a4 100644
--- a/apps/webapp/app/components/primitives/Buttons.tsx
+++ b/apps/webapp/app/components/primitives/Buttons.tsx
@@ -1,9 +1,10 @@
import { Link, LinkProps, NavLink, NavLinkProps } from "@remix-run/react";
-import React, { forwardRef, useImperativeHandle, useRef } from "react";
+import React, { forwardRef, ReactNode, useImperativeHandle, useRef } from "react";
import { ShortcutDefinition, useShortcutKeys } from "~/hooks/useShortcutKeys";
import { cn } from "~/utils/cn";
import { IconNamesOrString, NamedIcon } from "./NamedIcon";
import { ShortcutKey } from "./ShortcutKey";
+import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "./Tooltip";
const sizes = {
small: {
@@ -65,8 +66,7 @@ const theme = {
icon: "text-text-bright",
},
minimal: {
- textColor:
- "text-text-dimmed group-hover/button:text-text-bright transition group-disabled/button:text-text-dimmed/80",
+ textColor: "text-text-dimmed group-disabled/button:text-text-dimmed transition",
button:
"bg-transparent group-hover/button:bg-tertiary disabled:opacity-50 group-disabled/button:bg-transparent group-disabled/button:pointer-events-none",
shortcut:
@@ -175,6 +175,8 @@ export type ButtonContentPropsType = {
shortcut?: ShortcutDefinition;
variant: keyof typeof variant;
shortcutPosition?: "before-trailing-icon" | "after-trailing-icon";
+ tooltip?: ReactNode;
+ iconSpacing?: string;
};
export function ButtonContent(props: ButtonContentPropsType) {
@@ -188,23 +190,34 @@ export function ButtonContent(props: ButtonContentPropsType) {
fullWidth,
textAlignLeft,
className,
+ tooltip,
+ iconSpacing,
} = props;
const variation = allVariants.variant[props.variant];
- // Based on the size prop, we'll use the corresponding variant classnames
const btnClassName = cn(allVariants.$all, variation.button);
const iconClassName = variation.icon;
const iconSpacingClassName = variation.iconSpacing;
const shortcutClassName = variation.shortcut;
const textColorClassName = variation.textColor;
- return (
+ const renderShortcutKey = () =>
+ shortcut && (
+
+ );
+
+ const buttonContent = (
{LeadingIcon &&
@@ -238,13 +251,10 @@ export function ButtonContent(props: ButtonContentPropsType) {
<>{text}>
))}
- {shortcut && props.shortcutPosition === "before-trailing-icon" && (
-
- )}
+ {shortcut &&
+ !tooltip &&
+ props.shortcutPosition === "before-trailing-icon" &&
+ renderShortcutKey()}
{TrailingIcon &&
(typeof TrailingIcon === "string" ? (
@@ -269,16 +279,27 @@ export function ButtonContent(props: ButtonContentPropsType) {
))}
{shortcut &&
- (!props.shortcutPosition || props.shortcutPosition === "after-trailing-icon") && (
-
- )}
+ !tooltip &&
+ (!props.shortcutPosition || props.shortcutPosition === "after-trailing-icon") &&
+ renderShortcutKey()}
);
+
+ if (tooltip) {
+ return (
+
+
+ {buttonContent}
+
+ {tooltip} {shortcut && renderShortcutKey()}
+
+
+
+ );
+ }
+
+ return buttonContent;
}
type ButtonPropsType = Pick<
diff --git a/apps/webapp/app/components/primitives/LinkWithDisabled.tsx b/apps/webapp/app/components/primitives/LinkWithDisabled.tsx
deleted file mode 100644
index 85b87a9b14..0000000000
--- a/apps/webapp/app/components/primitives/LinkWithDisabled.tsx
+++ /dev/null
@@ -1,19 +0,0 @@
-import { Link } from "@remix-run/react";
-import { cn } from "~/utils/cn";
-
-type Props = Parameters
[0] & {
- disabled?: boolean;
- disabledClassName?: string;
-};
-
-export function LinkDisabled({ disabled = false, disabledClassName, ...props }: Props) {
- if (disabled) {
- return (
-
- {props.children}
-
- );
- } else {
- return {props.children};
- }
-}
diff --git a/apps/webapp/app/components/primitives/Pagination.tsx b/apps/webapp/app/components/primitives/Pagination.tsx
index 633e815d03..20a1a93be2 100644
--- a/apps/webapp/app/components/primitives/Pagination.tsx
+++ b/apps/webapp/app/components/primitives/Pagination.tsx
@@ -2,8 +2,7 @@ import { ChevronRightIcon } from "@heroicons/react/24/outline";
import { ChevronLeftIcon } from "@heroicons/react/24/solid";
import { Link, useLocation } from "@remix-run/react";
import { cn } from "~/utils/cn";
-import { ButtonContent } from "./Buttons";
-import { LinkDisabled } from "./LinkWithDisabled";
+import { LinkButton } from "./Buttons";
export function PaginationControls({
currentPage,
@@ -21,16 +20,17 @@ export function PaginationControls({
return (
);
}
@@ -61,7 +62,7 @@ function pageUrl(location: ReturnType, page: number): string
}
const baseClass =
- "flex items-center justify-center border border-transparent min-w-6 h-6 px-1 text-xs font-medium transition text-text-dimmed rounded-sm";
+ "flex items-center justify-center border border-transparent min-w-6 h-6 px-1 text-xs font-medium transition text-text-dimmed rounded-sm focus-visible:focus-custom";
const unselectedClass = "hover:bg-tertiary hover:text-text-bright";
const selectedClass = "border-charcoal-600 bg-tertiary text-text-bright hover:bg-charcoal-600/50";
diff --git a/apps/webapp/app/components/primitives/SheetV3.tsx b/apps/webapp/app/components/primitives/SheetV3.tsx
new file mode 100644
index 0000000000..2bac7e9cb9
--- /dev/null
+++ b/apps/webapp/app/components/primitives/SheetV3.tsx
@@ -0,0 +1,126 @@
+import * as SheetPrimitive from "@radix-ui/react-dialog";
+import { cva, type VariantProps } from "class-variance-authority";
+import * as React from "react";
+import { cn } from "~/utils/cn";
+import { Header2 } from "./Headers";
+import { NamedIcon } from "./NamedIcon";
+import { ShortcutKey } from "./ShortcutKey";
+
+const Sheet = SheetPrimitive.Root;
+
+const SheetTrigger = SheetPrimitive.Trigger;
+
+const SheetClose = SheetPrimitive.Close;
+
+const SheetPortal = SheetPrimitive.Portal;
+
+const SheetOverlay = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+SheetOverlay.displayName = SheetPrimitive.Overlay.displayName;
+
+const sheetVariants = cva(
+ "fixed z-50 gap-4 overflow-y-auto bg-background-dimmed shadow-lg transition ease-in-out border-grid-dimmed data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-300",
+ {
+ variants: {
+ side: {
+ top: "inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top",
+ bottom:
+ "inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",
+ left: "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm",
+ right:
+ "inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm",
+ },
+ },
+ defaultVariants: {
+ side: "right",
+ },
+ }
+);
+
+interface SheetContentProps
+ extends React.ComponentPropsWithoutRef,
+ VariantProps {}
+
+const SheetContent = React.forwardRef<
+ React.ElementRef,
+ SheetContentProps
+>(({ side = "right", className, children, ...props }, ref) => (
+
+
+
+ {children}
+
+
+));
+SheetContent.displayName = SheetPrimitive.Content.displayName;
+
+const SheetHeader = ({ className, ...props }: React.HTMLAttributes) => (
+
+);
+SheetHeader.displayName = "SheetHeader";
+
+const SheetFooter = ({ className, ...props }: React.HTMLAttributes) => (
+
+);
+SheetFooter.displayName = "SheetFooter";
+
+const SheetTitle = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, children, ...props }, ref) => (
+
+ {children}
+
+
+
+ Close
+
+
+));
+SheetTitle.displayName = SheetPrimitive.Title.displayName;
+
+const SheetDescription = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+SheetDescription.displayName = SheetPrimitive.Description.displayName;
+
+export {
+ Sheet,
+ SheetClose,
+ SheetContent,
+ SheetDescription,
+ SheetFooter,
+ SheetHeader,
+ SheetOverlay,
+ SheetPortal,
+ SheetTitle,
+ SheetTrigger,
+};
diff --git a/apps/webapp/app/components/primitives/ShortcutKey.tsx b/apps/webapp/app/components/primitives/ShortcutKey.tsx
index df422eaf2c..faa7745c11 100644
--- a/apps/webapp/app/components/primitives/ShortcutKey.tsx
+++ b/apps/webapp/app/components/primitives/ShortcutKey.tsx
@@ -1,25 +1,35 @@
-import { Fragment } from "react";
-import { Modifier, ShortcutDefinition } from "~/hooks/useShortcutKeys";
+import { KeyboardDownIcon } from "~/assets/icons/KeyboardDownIcon";
+import { KeyboardLeftIcon } from "~/assets/icons/KeyboardLeftIcon";
+import { KeyboardRightIcon } from "~/assets/icons/KeyboardRightIcon";
+import { KeyboardUpIcon } from "~/assets/icons/KeyboardUpIcon";
+import { KeyboardWindowsIcon } from "~/assets/icons/KeyboardWindowsIcon";
+import { Modifier, Shortcut } from "~/hooks/useShortcutKeys";
import { cn } from "~/utils/cn";
import { useOperatingSystem } from "./OperatingSystemProvider";
-import {
- ChevronDownIcon,
- ChevronLeftIcon,
- ChevronRightIcon,
- ChevronUpIcon,
-} from "@heroicons/react/20/solid";
+
+const medium =
+ "text-[0.75rem] font-medium min-w-[17px] rounded-[2px] tabular-nums px-1 ml-1 -mr-0.5 flex items-center gap-x-1.5 border border-dimmed/40 text-text-dimmed group-hover:text-text-bright/80 group-hover:border-dimmed/60 transition uppercase";
export const variants = {
small:
- "text-[0.6rem] font-medium min-w-[17px] rounded-[2px] px-1 ml-1 -mr-0.5 grid place-content-center border border-dimmed/40 text-text-dimmed group-hover:text-text-bright/80 group-hover:border-dimmed/60 transition uppercase",
- medium:
- "text-[0.75rem] font-medium min-w-[17px] rounded-[2px] px-1 ml-1 -mr-0.5 grid place-content-center border border-dimmed/40 text-text-dimmed group-hover:text-text-bright/80 group-hover:border-dimmed/60 transition uppercase",
+ "text-[0.6rem] font-medium min-w-[17px] rounded-[2px] tabular-nums px-1 ml-1 -mr-0.5 flex items-center gap-x-1 border border-dimmed/40 text-text-dimmed group-hover:text-text-bright/80 group-hover:border-dimmed/60 transition uppercase",
+ medium,
+ "medium/bright": cn(medium, "bg-charcoal-750 text-text-bright border-charcoal-650"),
};
export type ShortcutKeyVariant = keyof typeof variants;
+type ShortcutKey = Partial;
+
+type ShortcutKeyDefinition =
+ | {
+ windows: ShortcutKey;
+ mac: ShortcutKey;
+ }
+ | ShortcutKey;
+
type ShortcutKeyProps = {
- shortcut: ShortcutDefinition;
+ shortcut: ShortcutKeyDefinition;
variant: ShortcutKeyVariant;
className?: string;
};
@@ -29,50 +39,62 @@ export function ShortcutKey({ shortcut, variant, className }: ShortcutKeyProps)
const isMac = platform === "mac";
let relevantShortcut = "mac" in shortcut ? (isMac ? shortcut.mac : shortcut.windows) : shortcut;
const modifiers = relevantShortcut.modifiers ?? [];
- const character = keyString(relevantShortcut.key, isMac, variant);
+ const character = relevantShortcut.key ? keyString(relevantShortcut.key, isMac, variant) : null;
return (
{modifiers.map((k) => (
- {modifierString(k, isMac)}
+
+ {modifierString(k, isMac, variant)}
+
))}
- {character}
+ {character && {character}}
);
}
-function keyString(key: String, isMac: boolean, size: "small" | "medium") {
+function keyString(key: string, isMac: boolean, variant: "small" | "medium" | "medium/bright") {
key = key.toLowerCase();
- const className = size === "small" ? "w-2.5 h-4" : "w-3 h-5";
+ const className = variant === "small" ? "w-2.5 h-4" : "w-3 h-5";
switch (key) {
case "enter":
- return isMac ? "↵" : key;
+ return isMac ? "↵" : Enter;
+ case "esc":
+ return Esc;
+ case "del":
+ return Del;
case "arrowdown":
- return ;
+ return ;
case "arrowup":
- return ;
+ return ;
case "arrowleft":
- return ;
+ return ;
case "arrowright":
- return ;
+ return ;
default:
return key;
}
}
-function modifierString(modifier: Modifier, isMac: boolean) {
+function modifierString(
+ modifier: Modifier,
+ isMac: boolean,
+ variant: "small" | "medium" | "medium/bright"
+): string | JSX.Element {
+ const className = variant === "small" ? "w-2.5 h-4" : "w-3.5 h-5";
+
switch (modifier) {
case "alt":
- return isMac ? "⌥" : "Alt+";
+ return isMac ? "⌥" : Alt;
case "ctrl":
- return isMac ? "⌃" : "Ctrl+";
+ return isMac ? "⌃" : Ctrl;
case "meta":
- return isMac ? "⌘" : "⊞+";
+ return isMac ? "⌘" : ;
case "shift":
- return isMac ? "⇧" : "Shift+";
+ return "⇧";
case "mod":
- return isMac ? "⌘" : "Ctrl+";
+ return isMac ? "⌘" : Ctrl;
}
}
diff --git a/apps/webapp/app/components/primitives/Switch.tsx b/apps/webapp/app/components/primitives/Switch.tsx
index 2c3121676f..5cb860910b 100644
--- a/apps/webapp/app/components/primitives/Switch.tsx
+++ b/apps/webapp/app/components/primitives/Switch.tsx
@@ -8,15 +8,15 @@ const variations = {
large: {
container: "flex items-center gap-x-2 rounded-md hover:bg-tertiary p-2 transition focus-custom",
root: "h-6 w-11",
- thumb: "h-5 w-5 data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0",
- text: "text-sm text-charcoal-400 group-hover:text-charcoal-200 transition",
+ thumb: "size-5 data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0",
+ text: "text-sm text-text-dimmed",
},
small: {
container:
"flex items-center h-[1.5rem] gap-x-1.5 rounded hover:bg-tertiary disabled:hover:bg-transparent pr-1 py-[0.1rem] pl-1.5 transition focus-custom disabled:hover:text-charcoal-400 disabled:opacity-50 text-charcoal-400 hover:text-charcoal-200 disabled:hover:cursor-not-allowed hover:cursor-pointer",
root: "h-3 w-6",
- thumb: "h-2.5 w-2.5 data-[state=checked]:translate-x-2.5 data-[state=unchecked]:translate-x-0",
- text: "text-xs",
+ thumb: "size-2.5 data-[state=checked]:translate-x-2.5 data-[state=unchecked]:translate-x-0",
+ text: "text-xs text-text-dimmed",
},
};
@@ -38,7 +38,7 @@ export const Switch = React.forwardRef
diff --git a/apps/webapp/app/components/runs/v3/BatchFilters.tsx b/apps/webapp/app/components/runs/v3/BatchFilters.tsx
index 02474fa46f..f7ab261d4e 100644
--- a/apps/webapp/app/components/runs/v3/BatchFilters.tsx
+++ b/apps/webapp/app/components/runs/v3/BatchFilters.tsx
@@ -400,7 +400,7 @@ function BatchIdDropdown({
disabled={error !== undefined || !batchId}
variant="secondary/small"
shortcut={{
- modifiers: ["meta"],
+ modifiers: ["mod"],
key: "Enter",
enabledOnInputElements: true,
}}
diff --git a/apps/webapp/app/components/runs/v3/CancelRunDialog.tsx b/apps/webapp/app/components/runs/v3/CancelRunDialog.tsx
index d4264886b7..2d0439402f 100644
--- a/apps/webapp/app/components/runs/v3/CancelRunDialog.tsx
+++ b/apps/webapp/app/components/runs/v3/CancelRunDialog.tsx
@@ -40,7 +40,7 @@ export function CancelRunDialog({ runFriendlyId, redirectPath }: CancelRunDialog
variant="danger/medium"
LeadingIcon={isLoading ? "spinner-white" : NoSymbolIcon}
disabled={isLoading}
- shortcut={{ modifiers: ["meta"], key: "enter" }}
+ shortcut={{ modifiers: ["mod"], key: "enter" }}
>
{isLoading ? "Canceling..." : "Cancel run"}
diff --git a/apps/webapp/app/components/runs/v3/CheckBatchCompletionDialog.tsx b/apps/webapp/app/components/runs/v3/CheckBatchCompletionDialog.tsx
index 70a51a3cf6..10df63a4de 100644
--- a/apps/webapp/app/components/runs/v3/CheckBatchCompletionDialog.tsx
+++ b/apps/webapp/app/components/runs/v3/CheckBatchCompletionDialog.tsx
@@ -39,7 +39,7 @@ export function CheckBatchCompletionDialog({
variant="primary/medium"
LeadingIcon={isLoading ? "spinner-white" : undefined}
disabled={isLoading}
- shortcut={{ modifiers: ["meta"], key: "enter" }}
+ shortcut={{ modifiers: ["mod"], key: "enter" }}
>
{isLoading ? "Attempting resume..." : "Attempt resume"}
diff --git a/apps/webapp/app/components/runs/v3/ReplayRunDialog.tsx b/apps/webapp/app/components/runs/v3/ReplayRunDialog.tsx
index 589b686a5c..e29b8a9e4b 100644
--- a/apps/webapp/app/components/runs/v3/ReplayRunDialog.tsx
+++ b/apps/webapp/app/components/runs/v3/ReplayRunDialog.tsx
@@ -159,7 +159,7 @@ function ReplayForm({
variant="primary/medium"
LeadingIcon={isSubmitting ? ButtonSpinner : undefined}
disabled={isSubmitting}
- shortcut={{ modifiers: ["meta"], key: "enter", enabledOnInputElements: true }}
+ shortcut={{ modifiers: ["mod"], key: "enter", enabledOnInputElements: true }}
>
{isSubmitting ? "Replaying..." : "Replay run"}
diff --git a/apps/webapp/app/components/runs/v3/RetryDeploymentIndexingDialog.tsx b/apps/webapp/app/components/runs/v3/RetryDeploymentIndexingDialog.tsx
index d689a874e8..6c1ca5fe92 100644
--- a/apps/webapp/app/components/runs/v3/RetryDeploymentIndexingDialog.tsx
+++ b/apps/webapp/app/components/runs/v3/RetryDeploymentIndexingDialog.tsx
@@ -48,7 +48,7 @@ export function RetryDeploymentIndexingDialog({
variant="primary/medium"
LeadingIcon={isLoading ? "spinner-white" : ArrowPathIcon}
disabled={isLoading}
- shortcut={{ modifiers: ["meta"], key: "enter" }}
+ shortcut={{ modifiers: ["mod"], key: "enter" }}
>
{isLoading ? "Retrying..." : "Retry indexing"}
diff --git a/apps/webapp/app/components/runs/v3/RollbackDeploymentDialog.tsx b/apps/webapp/app/components/runs/v3/RollbackDeploymentDialog.tsx
index aeb2f61cc0..ccba03b030 100644
--- a/apps/webapp/app/components/runs/v3/RollbackDeploymentDialog.tsx
+++ b/apps/webapp/app/components/runs/v3/RollbackDeploymentDialog.tsx
@@ -48,7 +48,7 @@ export function RollbackDeploymentDialog({
variant="primary/medium"
LeadingIcon={isLoading ? "spinner-white" : ArrowPathIcon}
disabled={isLoading}
- shortcut={{ modifiers: ["meta"], key: "enter" }}
+ shortcut={{ modifiers: ["mod"], key: "enter" }}
>
{isLoading ? "Rolling back..." : "Roll back deployment"}
diff --git a/apps/webapp/app/components/runs/v3/RunFilters.tsx b/apps/webapp/app/components/runs/v3/RunFilters.tsx
index 242ef0a491..6cc75a6129 100644
--- a/apps/webapp/app/components/runs/v3/RunFilters.tsx
+++ b/apps/webapp/app/components/runs/v3/RunFilters.tsx
@@ -804,7 +804,7 @@ function RunIdDropdown({
disabled={error !== undefined || !runId}
variant="secondary/small"
shortcut={{
- modifiers: ["meta"],
+ modifiers: ["mod"],
key: "Enter",
enabledOnInputElements: true,
}}
@@ -922,7 +922,7 @@ function BatchIdDropdown({
disabled={error !== undefined || !batchId}
variant="secondary/small"
shortcut={{
- modifiers: ["meta"],
+ modifiers: ["mod"],
key: "Enter",
enabledOnInputElements: true,
}}
@@ -1040,7 +1040,7 @@ function ScheduleIdDropdown({
disabled={error !== undefined || !scheduleId}
variant="secondary/small"
shortcut={{
- modifiers: ["meta"],
+ modifiers: ["mod"],
key: "Enter",
enabledOnInputElements: true,
}}
diff --git a/apps/webapp/app/components/runs/v3/SharedFilters.tsx b/apps/webapp/app/components/runs/v3/SharedFilters.tsx
index 3f07f133ed..03474b5960 100644
--- a/apps/webapp/app/components/runs/v3/SharedFilters.tsx
+++ b/apps/webapp/app/components/runs/v3/SharedFilters.tsx
@@ -390,7 +390,7 @@ export function CustomDateRangeDropdown({
@@ -403,7 +403,7 @@ function ReplayRuns({ onOpen }: { onOpen: (open: boolean) => void }) {
variant="primary/medium"
LeadingIcon={isLoading ? "spinner-white" : ArrowPathIcon}
disabled={isLoading}
- shortcut={{ modifiers: ["meta"], key: "enter" }}
+ shortcut={{ modifiers: ["mod"], key: "enter" }}
>
{isLoading ? "Replaying..." : `Replay ${selectedItems.size} runs`}
diff --git a/apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.schedules.new/route.tsx b/apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.schedules.new/route.tsx
index 56c82e9148..d85c3d53f4 100644
--- a/apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.schedules.new/route.tsx
+++ b/apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.schedules.new/route.tsx
@@ -393,7 +393,7 @@ export function UpsertScheduleForm({
variant="primary/medium"
type="submit"
disabled={isLoading}
- shortcut={{ key: "enter", modifiers: ["meta"] }}
+ shortcut={{ key: "enter", modifiers: ["mod"] }}
LeadingIcon={isLoading ? "spinner" : undefined}
>
{buttonText(mode, isLoading)}
diff --git a/apps/webapp/app/routes/storybook.buttons/route.tsx b/apps/webapp/app/routes/storybook.buttons/route.tsx
index 3baff3b1c3..f6e6ce0b7e 100644
--- a/apps/webapp/app/routes/storybook.buttons/route.tsx
+++ b/apps/webapp/app/routes/storybook.buttons/route.tsx
@@ -70,7 +70,7 @@ export default function Story() {
Shortcut
-
@@ -193,19 +193,19 @@ export default function Story() {
Shortcut
-
+
Primary button
-
+
Secondary button
-
+
Tertiary button
-
+
Minimal button
-
+
Danger button
diff --git a/apps/webapp/app/routes/storybook.shortcuts/route.tsx b/apps/webapp/app/routes/storybook.shortcuts/route.tsx
index 54b7ddad59..785247a4c9 100644
--- a/apps/webapp/app/routes/storybook.shortcuts/route.tsx
+++ b/apps/webapp/app/routes/storybook.shortcuts/route.tsx
@@ -7,11 +7,13 @@ import { ShortcutDefinition } from "~/hooks/useShortcutKeys";
const shortcuts: ShortcutDefinition[] = [
{ key: "esc" },
{ key: "f" },
- { key: "f", modifiers: ["meta"] },
- { key: "k", modifiers: ["meta"] },
+ { key: "f", modifiers: ["mod"] },
+ { key: "k", modifiers: ["mod"] },
{ key: "del", modifiers: ["ctrl", "alt"] },
- { key: "enter", modifiers: ["meta"] },
+ { key: "f", modifiers: ["shift"] },
{ key: "enter", modifiers: ["mod"] },
+ { key: "enter", modifiers: ["mod"] },
+ { key: "g", modifiers: ["meta"] },
];
export default function Story() {
@@ -31,6 +33,7 @@ function Collection({ platform }: { platform: "mac" | "windows" }) {
+
Primary small