diff --git a/docs/screenshots/ui-browser-defaults/role-dark-after.png b/docs/screenshots/ui-browser-defaults/role-dark-after.png new file mode 100644 index 0000000..7c5e46c Binary files /dev/null and b/docs/screenshots/ui-browser-defaults/role-dark-after.png differ diff --git a/docs/screenshots/ui-browser-defaults/role-dark-before.png b/docs/screenshots/ui-browser-defaults/role-dark-before.png new file mode 100644 index 0000000..edc1943 Binary files /dev/null and b/docs/screenshots/ui-browser-defaults/role-dark-before.png differ diff --git a/docs/screenshots/ui-browser-defaults/role-light-after.png b/docs/screenshots/ui-browser-defaults/role-light-after.png new file mode 100644 index 0000000..7700871 Binary files /dev/null and b/docs/screenshots/ui-browser-defaults/role-light-after.png differ diff --git a/docs/screenshots/ui-browser-defaults/role-light-before.png b/docs/screenshots/ui-browser-defaults/role-light-before.png new file mode 100644 index 0000000..7a2d920 Binary files /dev/null and b/docs/screenshots/ui-browser-defaults/role-light-before.png differ diff --git a/docs/screenshots/ui-browser-defaults/search-after.png b/docs/screenshots/ui-browser-defaults/search-after.png new file mode 100644 index 0000000..465a914 Binary files /dev/null and b/docs/screenshots/ui-browser-defaults/search-after.png differ diff --git a/docs/screenshots/ui-browser-defaults/search-before.png b/docs/screenshots/ui-browser-defaults/search-before.png new file mode 100644 index 0000000..7710096 Binary files /dev/null and b/docs/screenshots/ui-browser-defaults/search-before.png differ diff --git a/src/components/account/access-panels.tsx b/src/components/account/access-panels.tsx index ee49a63..9bf6c9c 100644 --- a/src/components/account/access-panels.tsx +++ b/src/components/account/access-panels.tsx @@ -1,3 +1,5 @@ +import { SearchInput } from "@/components/ui/search-input"; +import { Hint } from "@/components/ui/tooltip"; import { useState, type ReactNode } from "react"; import { cn } from "cn"; import { BadgeCheck, Fingerprint, Plus, Search, Trash2 } from "lucide-react"; @@ -73,20 +75,20 @@ export function GroupsPanel({ groups }: { groups: AccountDetails["groups"] }) { {groups.length ? ( ) : ( @@ -146,18 +148,14 @@ export function PermissionsPanel({ permissions }: { permissions: Permission[] }) className="pointer-events-none absolute top-1/2 left-2.5 size-4 -translate-y-1/2 text-muted-foreground" aria-hidden="true" /> - setSearch(event.target.value)} - onKeyDown={(event) => { - if (event.key === "Escape") setSearch(""); - }} + onValueChange={setSearch} aria-label="Search permissions" placeholder="Search" autoComplete="off" spellCheck={false} - className="h-9 w-full rounded-md border bg-background pr-2.5 pl-8 text-base outline-none placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 sm:text-sm dark:bg-input/30" + className="h-9 w-full rounded-md border bg-background pl-8 text-base outline-none placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 sm:text-sm dark:bg-input/30" /> {matching.length ? ( diff --git a/src/components/account/account-cards.tsx b/src/components/account/account-cards.tsx index 8b309be..84ff258 100644 --- a/src/components/account/account-cards.tsx +++ b/src/components/account/account-cards.tsx @@ -1,3 +1,4 @@ +import { Hint } from "@/components/ui/tooltip"; import { useRouter } from "@tanstack/react-router"; import { useState, type ReactNode } from "react"; import { cn } from "cn"; @@ -67,17 +68,19 @@ function UnlinkAction({ onClick: () => void; }) { return ( - - - + + + + + ); } @@ -295,6 +298,7 @@ function StudentVerification({ onDone }: { onDone: () => void }) { return (
{ event.preventDefault(); diff --git a/src/components/account/mcp-panel.tsx b/src/components/account/mcp-panel.tsx index 5bcfdd9..256dd42 100644 --- a/src/components/account/mcp-panel.tsx +++ b/src/components/account/mcp-panel.tsx @@ -1,3 +1,4 @@ +import { Hint } from "@/components/ui/tooltip"; import { useState } from "react"; import { Bot, Unplug } from "lucide-react"; import type { AccountDetails } from "@/auth/account.functions"; @@ -54,17 +55,19 @@ export function McpPanel({ mcp, actions }: { mcp: Mcp; actions: AccountActions } Active

- + + + ); })} diff --git a/src/components/account/secret-text.tsx b/src/components/account/secret-text.tsx index d77dca1..23ddc5a 100644 --- a/src/components/account/secret-text.tsx +++ b/src/components/account/secret-text.tsx @@ -1,3 +1,4 @@ +import { Hint } from "@/components/ui/tooltip"; import { useEffect, useState } from "react"; import { cn } from "cn"; import { CopyButton } from "@/components/copy-button"; @@ -57,26 +58,28 @@ export function SecretText({ return ( - + + {truncate(revealed ? value : scramble(value), maxChars)} + + + ); diff --git a/src/components/account/sessions-panel.tsx b/src/components/account/sessions-panel.tsx index 78a887b..84b6c54 100644 --- a/src/components/account/sessions-panel.tsx +++ b/src/components/account/sessions-panel.tsx @@ -1,3 +1,4 @@ +import { Hint } from "@/components/ui/tooltip"; import { useState } from "react"; import { LogOut, Monitor, Smartphone } from "lucide-react"; import type { AccountDetails } from "@/auth/account.functions"; @@ -105,17 +106,19 @@ export function SessionsPanel({

{!entry.current && ( - + + + )} ); diff --git a/src/components/copy-button.tsx b/src/components/copy-button.tsx index 05646aa..01f6fb8 100644 --- a/src/components/copy-button.tsx +++ b/src/components/copy-button.tsx @@ -1,3 +1,4 @@ +import { Hint } from "@/components/ui/tooltip"; import { useEffect, useState } from "react"; import { Check, Copy } from "lucide-react"; import { Button } from "@/components/ui/button"; @@ -20,24 +21,30 @@ export function CopyButton({ return () => clearTimeout(timer); }, [copied]); return ( - + + + ); } diff --git a/src/components/oidc/form-fields.tsx b/src/components/oidc/form-fields.tsx index d9e72f4..3da7c0e 100644 --- a/src/components/oidc/form-fields.tsx +++ b/src/components/oidc/form-fields.tsx @@ -1,3 +1,4 @@ +import { Hint } from "@/components/ui/tooltip"; // Fields shared by the new-application wizard and the application settings page. import { useEffect, useId, useRef, useState, type KeyboardEvent, type ReactNode } from "react"; import { cn } from "cn"; @@ -136,27 +137,28 @@ export function LogoPreview({ url, dark }: { url: string; dark?: boolean }) { }, [url]); const broken = !!src && failed === src; return ( -
- {broken ? ( -
+ +
+ {broken ? ( +
+
); } @@ -535,36 +537,37 @@ export function IdentityScopeList({ const checkboxId = `${id}-${scope.id}`; return (
  • - +
  • ); })} @@ -742,37 +745,39 @@ export function ApiAccessTable({ {apiScopes .filter((scope) => scope.resource === resource.id) .map((scope) => ( - - - - {scope.label} - - {scope.id} - - - - {columns.map((column) => ( - - - - ))} - + + + + + {scope.label} + + {scope.id} + + + + {columns.map((column) => ( + + + + ))} + + ))} ))} diff --git a/src/components/rbac/catalog-search.tsx b/src/components/rbac/catalog-search.tsx index 2ea49df..1487aab 100644 --- a/src/components/rbac/catalog-search.tsx +++ b/src/components/rbac/catalog-search.tsx @@ -1,9 +1,8 @@ -import { useRef, type ReactNode } from "react"; -import { Search, X } from "lucide-react"; +import { type ReactNode } from "react"; +import { Search } from "lucide-react"; import { cn } from "cn"; -import { Button } from "@/components/ui/button"; import { Card } from "@/components/ui/card"; -import { Input } from "@/components/ui/input"; +import { SearchInput } from "@/components/ui/search-input"; /** The search box on its own, for pages that lay out the rest of the toolbar themselves. */ export function SearchField({ @@ -19,40 +18,19 @@ export function SearchField({ className?: string; inputClassName?: string; }) { - const input = useRef(null); - return (
    ); } diff --git a/src/components/rbac/pick-list.tsx b/src/components/rbac/pick-list.tsx index 9bf9a55..1dc3900 100644 --- a/src/components/rbac/pick-list.tsx +++ b/src/components/rbac/pick-list.tsx @@ -4,6 +4,7 @@ import { cn } from "cn"; import { Search } from "lucide-react"; import { Checkbox } from "@/components/ui/checkbox"; import { Input } from "@/components/ui/input"; +import { ScrollArea } from "@/components/ui/scroll-area"; export type PickOption = { key: string; @@ -72,50 +73,50 @@ export function PickList({ /> )} -
    - {visible.length === 0 ? ( -

    - {options.length === 0 ? emptyText : "Nothing matches that filter."} -

    - ) : ( - visible.map((option) => { - const checked = selected.includes(option.key); - return ( - + ); + }) + )} +
    + {error && (