mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-29 06:33:28 +00:00
refactor(ui): use the shadcn Kbd primitive for keyboard hints (#48885)
Replaces the hand-rolled kbd and code key chips across the dashboard with the shared Kbd component from components/ui/kbd, so every shortcut hint renders the same way
This commit is contained in:
parent
7c7304c22b
commit
1bd9a0780a
10 changed files with 25 additions and 46 deletions
|
|
@ -2,6 +2,7 @@ import React, { useState } from "react";
|
|||
import { Copy, Info } from "lucide-react";
|
||||
import { toast } from "@/lib/toast";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Kbd } from "@/components/ui/kbd";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
|
||||
import { UiLoadingSpinner } from "@/components/ui/ui-loading-spinner";
|
||||
|
|
@ -165,9 +166,7 @@ export function GuardrailTestPanel({
|
|||
/>
|
||||
<div className="mt-1 flex items-center justify-between">
|
||||
<span className="text-xs text-muted-foreground">
|
||||
Press <kbd className="rounded-sm border border-border bg-muted px-1 py-0.5 text-xs">Enter</kbd> to
|
||||
submit • <kbd className="rounded-sm border border-border bg-muted px-1 py-0.5 text-xs">Shift+Enter</kbd>{" "}
|
||||
for new line
|
||||
Press <Kbd>Enter</Kbd> to submit • <Kbd>Shift+Enter</Kbd> for new line
|
||||
</span>
|
||||
<span className="text-xs text-muted-foreground">Characters: {inputText.length}</span>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import React, { useId, useState } from "react";
|
|||
import { Alert, AlertDescription, AlertTitle } from "@/components/shared/Alert";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Card, CardContent } from "@/components/ui/card";
|
||||
import { Kbd } from "@/components/ui/kbd";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||
|
|
@ -369,8 +370,7 @@ const MCPConnect: React.FC<MCPConnectProps> = ({ currentServerAccessGroups = []
|
|||
<div className="flex w-full flex-col gap-6">
|
||||
<StepCard step={1} title="Open Cursor Settings">
|
||||
<span className="text-muted-foreground">
|
||||
Use the keyboard shortcut <code className="bg-muted px-2 py-1 rounded-sm">⇧+⌘+J</code> (Mac) or{" "}
|
||||
<code className="bg-muted px-2 py-1 rounded-sm">Ctrl+Shift+J</code> (Windows/Linux)
|
||||
Use the keyboard shortcut <Kbd>⇧+⌘+J</Kbd> (Mac) or <Kbd>Ctrl+Shift+J</Kbd> (Windows/Linux)
|
||||
</span>
|
||||
</StepCard>
|
||||
|
||||
|
|
@ -380,9 +380,8 @@ const MCPConnect: React.FC<MCPConnectProps> = ({ currentServerAccessGroups = []
|
|||
|
||||
<StepCard step={3} title="Add Configuration">
|
||||
<span className="mb-3 text-muted-foreground">
|
||||
Copy the JSON configuration below and paste it into Cursor, then save with{" "}
|
||||
<code className="bg-muted px-2 py-1 rounded-sm">Cmd+S</code> or{" "}
|
||||
<code className="bg-muted px-2 py-1 rounded-sm">Ctrl+S</code>
|
||||
Copy the JSON configuration below and paste it into Cursor, then save with <Kbd>Cmd+S</Kbd> or{" "}
|
||||
<Kbd>Ctrl+S</Kbd>
|
||||
</span>
|
||||
<FeatureCard
|
||||
icon={<Code className="text-purple-600 dark:text-purple-400" size={16} />}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import { getGuardrailsList, testPoliciesAndGuardrails } from "@/components/netwo
|
|||
import PolicySelector, { getPolicyOptionEntries } from "@/components/policies/PolicySelector";
|
||||
import { Policy } from "@/components/policies/types";
|
||||
import { makeOpenAIChatCompletionRequest } from "@/components/llm_calls/chat_completion";
|
||||
import { Kbd } from "@/components/ui/kbd";
|
||||
import {
|
||||
AlertTriangle,
|
||||
BarChart3,
|
||||
|
|
@ -1306,10 +1307,7 @@ export default function ComplianceUI({
|
|||
/>
|
||||
<div className="flex items-center justify-between px-3 pb-2">
|
||||
<span className="text-[10px] text-muted-foreground">
|
||||
Press <kbd className="px-1 py-0.5 bg-muted rounded-sm text-[10px] font-mono">Enter</kbd> to
|
||||
submit ·{" "}
|
||||
<kbd className="px-1 py-0.5 bg-muted rounded-sm text-[10px] font-mono">Shift+Enter</kbd> for new
|
||||
line
|
||||
Press <Kbd>Enter</Kbd> to submit · <Kbd>Shift+Enter</Kbd> for new line
|
||||
</span>
|
||||
<span className="text-[10px] text-muted-foreground tabular-nums">{quickTestInput.length}</span>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { Card, CardContent } from "@/components/ui/card";
|
|||
import { Checkbox } from "@/components/ui/checkbox";
|
||||
import { Dialog, DialogContent, DialogTitle } from "@/components/ui/dialog";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Kbd } from "@/components/ui/kbd";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
|
||||
import { UiLoadingSpinner } from "@/components/ui/ui-loading-spinner";
|
||||
|
|
@ -654,8 +655,7 @@ const AiSuggestionModal: React.FC<AiSuggestionModalProps> = ({
|
|||
/>
|
||||
<div className="mt-1">
|
||||
<span className="text-xs text-muted-foreground">
|
||||
Press <kbd className="rounded-sm border border-border bg-muted px-1 py-0.5 text-xs">Enter</kbd> to
|
||||
submit
|
||||
Press <Kbd>Enter</Kbd> to submit
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import { usePathname, useRouter } from "next/navigation";
|
|||
import { useKeys } from "@/app/(dashboard)/hooks/keys/useKeys";
|
||||
import { useTeams } from "@/app/(dashboard)/hooks/teams/useTeams";
|
||||
import { Dialog, DialogContent, DialogTitle } from "@/components/ui/dialog";
|
||||
import { Kbd } from "@/components/ui/kbd";
|
||||
import { useTerminology } from "@/contexts/TerminologyContext";
|
||||
import { DEBOUNCE_WAIT_MS } from "@/utils/debounceConstants";
|
||||
import { keyDetailHref } from "@/utils/entityLinks";
|
||||
|
|
@ -31,9 +32,6 @@ interface PaletteGroup {
|
|||
isLoading?: boolean;
|
||||
}
|
||||
|
||||
const shortcutChipClass =
|
||||
"rounded-sm border border-border border-b-2 bg-muted px-[3px] font-mono text-muted-foreground";
|
||||
|
||||
export function CommandPalette({ open, setOpen }: { open: boolean; setOpen: (open: boolean) => void }) {
|
||||
if (!open) return null;
|
||||
return <CommandPaletteDialog setOpen={setOpen} />;
|
||||
|
|
@ -305,13 +303,13 @@ function CommandPaletteDialog({ setOpen }: { setOpen: (open: boolean) => void })
|
|||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<span className="flex items-center gap-1">
|
||||
<kbd className={shortcutChipClass}>↵</kbd> Open
|
||||
<Kbd>↵</Kbd> Open
|
||||
</span>
|
||||
<span className="flex items-center gap-1">
|
||||
<kbd className={shortcutChipClass}>↑↓</kbd> Navigate
|
||||
<Kbd>↑↓</Kbd> Navigate
|
||||
</span>
|
||||
<span className="flex items-center gap-1">
|
||||
<kbd className={shortcutChipClass}>esc</kbd> Close
|
||||
<Kbd>esc</Kbd> Close
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
import { Search, X } from "lucide-react";
|
||||
import { z } from "zod";
|
||||
import { Kbd } from "@/components/ui/kbd";
|
||||
import { storageKey } from "@/lib/storage";
|
||||
import type { PaletteScope } from "./utils";
|
||||
import { useCommandPalette } from "./CommandPaletteProvider";
|
||||
|
|
@ -26,9 +27,7 @@ export function CommandPaletteHint({ scope, onDismiss }: CommandPaletteHintProps
|
|||
<button type="button" className="flex items-center gap-1.5 hover:text-foreground" onClick={() => setOpen(true)}>
|
||||
<Search className="size-3.5" aria-hidden="true" />
|
||||
<span>Press</span>
|
||||
<kbd className="rounded-sm border border-border border-b-2 bg-muted px-[3px] font-mono text-xs text-muted-foreground">
|
||||
{shortcut}
|
||||
</kbd>
|
||||
<Kbd>{shortcut}</Kbd>
|
||||
<span>{scope === "keys" ? "to search keys" : "to search or jump to a page"}</span>
|
||||
</button>
|
||||
<button
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
import { Search } from "lucide-react";
|
||||
import { usePathname } from "next/navigation";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Kbd } from "@/components/ui/kbd";
|
||||
import { routeSegmentForPathname } from "@/utils/uiHref";
|
||||
import { paletteScopeForRoute } from "./utils";
|
||||
import { useCommandPalette } from "./CommandPaletteProvider";
|
||||
|
|
@ -42,9 +43,7 @@ export function CommandPaletteTrigger({ mobile = false }: { mobile?: boolean })
|
|||
<Search className="size-4 shrink-0" />
|
||||
<span className="truncate">{label}</span>
|
||||
</span>
|
||||
<kbd className="ml-2 shrink-0 rounded-sm border border-border border-b-2 bg-muted px-[3px] font-mono text-xs text-muted-foreground">
|
||||
{shortcut}
|
||||
</kbd>
|
||||
<Kbd className="ml-2 shrink-0">{shortcut}</Kbd>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import { Button } from "@/components/ui/button";
|
|||
import { Card, CardContent, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { Dialog, DialogClose, DialogContent, DialogDescription, DialogTitle } from "@/components/ui/dialog";
|
||||
import { FieldError } from "@/components/ui/field";
|
||||
import { Kbd } from "@/components/ui/kbd";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import { useTerminology } from "@/contexts/TerminologyContext";
|
||||
import { cn } from "@/lib/cva.config";
|
||||
|
|
@ -185,7 +186,7 @@ export default function LiteAdminTrigger() {
|
|||
>
|
||||
<AriaAvatar />
|
||||
<span className="hidden lg:inline">{ARIA_AGENT_LABEL}</span>
|
||||
<kbd className="hidden rounded-full border border-info/30 px-1.5 font-sans text-xs lg:inline">⌘J</kbd>
|
||||
<Kbd className="hidden lg:inline-flex">⌘J</Kbd>
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
"use client";
|
||||
|
||||
import { Fragment, type ReactNode } from "react";
|
||||
import { Fragment } from "react";
|
||||
import { useHotkeysContext } from "react-hotkeys-hook";
|
||||
|
||||
import { Kbd } from "@/components/ui/kbd";
|
||||
import { cn } from "@/lib/cva.config";
|
||||
|
||||
type BoundShortcut = ReturnType<typeof useHotkeysContext>["hotkeys"][number];
|
||||
|
|
@ -59,14 +60,6 @@ export function shortcutHints(shortcuts: readonly BoundShortcut[]): readonly Sho
|
|||
>((hints, [key, shortcut]) => mergeAdjacent(hints, key, shortcut.description ?? ""), []);
|
||||
}
|
||||
|
||||
function Kbd({ children }: { children: ReactNode }) {
|
||||
return (
|
||||
<kbd className="rounded-sm border border-border border-b-2 bg-muted px-[3px] font-mono text-muted-foreground">
|
||||
{children}
|
||||
</kbd>
|
||||
);
|
||||
}
|
||||
|
||||
/** The shortcuts active right now, read from what is bound rather than typed by hand. */
|
||||
export function ShortcutHints({ className }: { className?: string }) {
|
||||
const { hotkeys } = useHotkeysContext();
|
||||
|
|
|
|||
|
|
@ -8,9 +8,10 @@ import { Check, Copy, CornerDownLeft, Loader2, type LucideIcon, Search } from "l
|
|||
import { Schema } from "prosemirror-model";
|
||||
import { EditorState, Plugin, TextSelection, type Transaction } from "prosemirror-state";
|
||||
import { Decoration, DecorationSet, type EditorView } from "prosemirror-view";
|
||||
import { type ComponentProps, createContext, type ReactNode, useContext, useId, useMemo, useState } from "react";
|
||||
import { type ComponentProps, createContext, useContext, useId, useMemo, useState } from "react";
|
||||
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Kbd } from "@/components/ui/kbd";
|
||||
import { cn } from "@/lib/cva.config";
|
||||
|
||||
import { type FilterOp, languageOps, parseQuery, type QueryClause, type QueryLanguage } from "./language";
|
||||
|
|
@ -326,7 +327,7 @@ function Suggestions({ className, children, ...props }: SearchBoxSuggestionsProp
|
|||
</span>
|
||||
<span className="flex items-center gap-1">
|
||||
<Kbd>
|
||||
<CornerDownLeft className="size-3" />
|
||||
<CornerDownLeft />
|
||||
</Kbd>
|
||||
Select
|
||||
</span>
|
||||
|
|
@ -392,12 +393,4 @@ function OperatorHints({ ops }: { ops: readonly FilterOp[] }) {
|
|||
);
|
||||
}
|
||||
|
||||
function Kbd({ children }: { children: ReactNode }) {
|
||||
return (
|
||||
<kbd className="inline-flex h-5 min-w-5 items-center justify-center rounded border border-border px-1 font-sans">
|
||||
{children}
|
||||
</kbd>
|
||||
);
|
||||
}
|
||||
|
||||
export const SearchBox = { Root, Input, Suggestions, CopyCommand } as const;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue