mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-07-27 22:29:02 +03:00
UI tweaks (#23346)
CI / AMD64 Build (push) Has been cancelled
CI / ARM Build (push) Has been cancelled
CI / Jetson Jetpack 6 (push) Has been cancelled
CI / AMD64 Extra Build (push) Has been cancelled
CI / ARM Extra Build (push) Has been cancelled
CI / Synaptics Build (push) Has been cancelled
CI / Assemble and push default build (push) Has been cancelled
CI / AMD64 Build (push) Has been cancelled
CI / ARM Build (push) Has been cancelled
CI / Jetson Jetpack 6 (push) Has been cancelled
CI / AMD64 Extra Build (push) Has been cancelled
CI / ARM Extra Build (push) Has been cancelled
CI / Synaptics Build (push) Has been cancelled
CI / Assemble and push default build (push) Has been cancelled
* remove redundant per-view toasters in settings * add variants to standardize dialog footer button layouts * remove text-md this class name compiles to nothing in tailwind. we used to add it to prevent iOS from zooming when focusing on an input, but that is now solved via the viewport meta in index.html * make wizard footers consistent with dialog footers * consistent destructive button style remove text-white from individual buttons and add it to the variant
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import ActivityIndicator from "@/components/indicators/activity-indicator";
|
||||
import { FrigateConfig } from "@/types/frigateConfig";
|
||||
import { Toaster } from "@/components/ui/sonner";
|
||||
import useSWR from "swr";
|
||||
import Heading from "@/components/ui/heading";
|
||||
import { User } from "@/types/user";
|
||||
@@ -790,7 +789,6 @@ export default function AuthenticationView({
|
||||
|
||||
return (
|
||||
<div className="flex size-full flex-col">
|
||||
<Toaster position="top-center" closeButton={true} />
|
||||
<div className="scrollbar-container order-last mb-2 mt-2 flex h-full w-full flex-col overflow-y-auto pb-2 md:order-none md:mr-3 md:mt-0">
|
||||
{section === "users" && UsersSection}
|
||||
{section === "roles" && RolesSection}
|
||||
|
||||
@@ -250,7 +250,7 @@ export default function CameraManagementView({
|
||||
<Button
|
||||
variant="destructive"
|
||||
onClick={() => setShowDeleteDialog(true)}
|
||||
className="mb-2 flex max-w-48 items-center gap-2 text-white"
|
||||
className="mb-2 flex max-w-48 items-center gap-2"
|
||||
>
|
||||
<LuTrash2 className="h-4 w-4" />
|
||||
{t("cameraManagement.deleteCamera")}
|
||||
@@ -261,7 +261,7 @@ export default function CameraManagementView({
|
||||
{enabledCameras.length + disabledCameras.length > 0 && (
|
||||
<div className="mb-5 space-y-3">
|
||||
<div className="space-y-0.5">
|
||||
<div className="text-md font-medium">
|
||||
<div className="font-medium">
|
||||
{t("cameraManagement.clone.sectionTitle")}
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
|
||||
@@ -22,7 +22,6 @@ import ActivityIndicator from "@/components/indicators/activity-indicator";
|
||||
import Heading from "@/components/ui/heading";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Toaster } from "@/components/ui/sonner";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import {
|
||||
@@ -598,7 +597,6 @@ export default function DetectorsAndModelSettingsView({
|
||||
|
||||
return (
|
||||
<div className="flex size-full flex-col md:pr-2">
|
||||
<Toaster position="top-center" closeButton={true} />
|
||||
<div className="mb-1 flex items-center justify-between gap-4 pt-2">
|
||||
<div className="flex max-w-5xl flex-col">
|
||||
<Heading as="h4">{t("detectorsAndModel.title")}</Heading>
|
||||
|
||||
@@ -306,9 +306,7 @@ export default function EnrichmentsSettingsView({
|
||||
</div>
|
||||
<div className="mt-2 flex flex-col space-y-6">
|
||||
<div className="space-y-0.5">
|
||||
<div className="text-md">
|
||||
{t("enrichments.semanticSearch.modelSize.label")}
|
||||
</div>
|
||||
<div>{t("enrichments.semanticSearch.modelSize.label")}</div>
|
||||
<div className="space-y-1 text-sm text-muted-foreground">
|
||||
<p>
|
||||
<Trans ns="views/settings">
|
||||
@@ -436,9 +434,7 @@ export default function EnrichmentsSettingsView({
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-0.5">
|
||||
<div className="text-md">
|
||||
{t("enrichments.faceRecognition.modelSize.label")}
|
||||
</div>
|
||||
<div>{t("enrichments.faceRecognition.modelSize.label")}</div>
|
||||
<div className="space-y-1 text-sm text-muted-foreground">
|
||||
<p>
|
||||
<Trans ns="views/settings">
|
||||
|
||||
@@ -4,7 +4,6 @@ import { Link, useNavigate } from "react-router-dom";
|
||||
import useSWR from "swr";
|
||||
import { CheckCircle2, XCircle } from "lucide-react";
|
||||
import { LuExternalLink } from "react-icons/lu";
|
||||
import { Toaster } from "@/components/ui/sonner";
|
||||
import ActivityIndicator from "@/components/indicators/activity-indicator";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import Heading from "@/components/ui/heading";
|
||||
@@ -35,7 +34,6 @@ export default function FrigatePlusSettingsView(_props: SettingsPageProps) {
|
||||
|
||||
return (
|
||||
<div className="flex size-full flex-col md:pr-2">
|
||||
<Toaster position="top-center" closeButton={true} />
|
||||
<div className="w-full max-w-5xl space-y-6 pt-2">
|
||||
<div className="flex flex-col gap-0">
|
||||
<Heading as="h4" className="mb-2">
|
||||
|
||||
@@ -446,10 +446,7 @@ export default function Go2RtcStreamsSettingsView({
|
||||
{t("button.cancel", { ns: "common" })}
|
||||
</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
className={cn(
|
||||
buttonVariants({ variant: "destructive" }),
|
||||
"text-white",
|
||||
)}
|
||||
className={cn(buttonVariants({ variant: "destructive" }))}
|
||||
onClick={() => deleteDialog && deleteStream(deleteDialog)}
|
||||
>
|
||||
{t("go2rtcStreams.deleteStream")}
|
||||
@@ -533,7 +530,6 @@ function RenameStreamDialog({
|
||||
<div className="space-y-2 py-2">
|
||||
<Label>{t("go2rtcStreams.newStreamName")}</Label>
|
||||
<Input
|
||||
className="text-md"
|
||||
value={newName}
|
||||
onChange={(e) => setNewName(e.target.value)}
|
||||
onKeyDown={(e) => {
|
||||
@@ -547,7 +543,7 @@ function RenameStreamDialog({
|
||||
<p className="text-xs text-destructive">{nameError}</p>
|
||||
)}
|
||||
</div>
|
||||
<DialogFooter className="gap-2 sm:justify-end md:gap-0">
|
||||
<DialogFooter>
|
||||
<DialogClose asChild>
|
||||
<Button>{t("button.cancel", { ns: "common" })}</Button>
|
||||
</DialogClose>
|
||||
@@ -614,7 +610,6 @@ function AddStreamDialog({
|
||||
<Label>{t("go2rtcStreams.streamName")}</Label>
|
||||
<Input
|
||||
value={name}
|
||||
className="text-md"
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === "Enter" && canSubmit) {
|
||||
@@ -628,7 +623,7 @@ function AddStreamDialog({
|
||||
<p className="text-xs text-destructive">{nameError}</p>
|
||||
)}
|
||||
</div>
|
||||
<DialogFooter className="gap-2 sm:justify-end md:gap-0">
|
||||
<DialogFooter>
|
||||
<DialogClose asChild>
|
||||
<Button>{t("button.cancel", { ns: "common" })}</Button>
|
||||
</DialogClose>
|
||||
@@ -924,7 +919,7 @@ function StreamUrlEntry({
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="relative flex-1">
|
||||
<Input
|
||||
className="text-md h-8 pr-10"
|
||||
className="h-8 pr-10"
|
||||
value={baseUrlForDisplay}
|
||||
onChange={(e) => handleBaseUrlChange(e.target.value)}
|
||||
onFocus={() => setIsFocused(true)}
|
||||
|
||||
@@ -15,7 +15,6 @@ import {
|
||||
} from "@/components/ui/hover-card";
|
||||
import copy from "copy-to-clipboard";
|
||||
import { toast } from "sonner";
|
||||
import { Toaster } from "@/components/ui/sonner";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Tooltip,
|
||||
@@ -730,7 +729,6 @@ export default function MasksAndZonesView({
|
||||
<>
|
||||
{cameraConfig && editingPolygons && (
|
||||
<div className="flex size-full flex-col md:flex-row">
|
||||
<Toaster position="top-center" closeButton={true} />
|
||||
<div className="scrollbar-container order-last mb-2 mt-2 flex h-full w-full flex-col overflow-y-auto rounded-lg border-[1px] border-secondary-foreground bg-background_alt p-2 md:order-none md:mr-3 md:mt-0 md:w-3/12 md:min-w-0 md:shrink-0">
|
||||
{editPane == "zone" && (
|
||||
<ZoneEditPane
|
||||
@@ -793,7 +791,7 @@ export default function MasksAndZonesView({
|
||||
<div className="my-3 flex flex-row items-center justify-between">
|
||||
<HoverCard>
|
||||
<HoverCardTrigger asChild>
|
||||
<div className="text-md cursor-default">
|
||||
<div className="cursor-default">
|
||||
{t("masksAndZones.zones.label")}
|
||||
</div>
|
||||
</HoverCardTrigger>
|
||||
@@ -871,7 +869,7 @@ export default function MasksAndZonesView({
|
||||
<div className="my-3 flex flex-row items-center justify-between">
|
||||
<HoverCard>
|
||||
<HoverCardTrigger asChild>
|
||||
<div className="text-md cursor-default">
|
||||
<div className="cursor-default">
|
||||
{t("masksAndZones.motionMasks.label")}
|
||||
</div>
|
||||
</HoverCardTrigger>
|
||||
@@ -953,7 +951,7 @@ export default function MasksAndZonesView({
|
||||
<div className="my-3 flex flex-row items-center justify-between">
|
||||
<HoverCard>
|
||||
<HoverCardTrigger asChild>
|
||||
<div className="text-md cursor-default">
|
||||
<div className="cursor-default">
|
||||
{t("masksAndZones.objectMasks.label")}
|
||||
</div>
|
||||
</HoverCardTrigger>
|
||||
|
||||
@@ -2,7 +2,6 @@ import Heading from "@/components/ui/heading";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import { Toaster } from "@/components/ui/sonner";
|
||||
import ActivityIndicator from "@/components/indicators/activity-indicator";
|
||||
import { useCallback, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
@@ -105,7 +104,6 @@ export default function MediaSyncSettingsView() {
|
||||
return (
|
||||
<>
|
||||
<div className="flex size-full flex-col md:flex-row">
|
||||
<Toaster position="top-center" closeButton={true} />
|
||||
<div className="scrollbar-container order-last mb-2 mt-2 flex h-full w-full flex-col overflow-y-auto px-2 md:order-none">
|
||||
<div className="grid w-full grid-cols-1 gap-4 md:grid-cols-2">
|
||||
<div className="col-span-1">
|
||||
|
||||
@@ -15,7 +15,6 @@ import {
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { Toaster } from "@/components/ui/sonner";
|
||||
import { toast } from "sonner";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import { Link } from "react-router-dom";
|
||||
@@ -184,7 +183,6 @@ export default function MotionTunerView({
|
||||
|
||||
return (
|
||||
<div className="flex size-full flex-col md:flex-row">
|
||||
<Toaster position="top-center" closeButton={true} />
|
||||
<div className="scrollbar-container order-last mb-2 mt-2 flex h-full w-full flex-col overflow-y-auto rounded-lg border-[1px] border-secondary-foreground bg-background_alt p-2 md:order-none md:mr-3 md:mt-0 md:w-3/12">
|
||||
<Heading as="h4" className="mb-2">
|
||||
{t("motionDetectionTuner.title")}
|
||||
@@ -208,7 +206,7 @@ export default function MotionTunerView({
|
||||
<div className="flex w-full flex-col space-y-6">
|
||||
<div className="mt-2 space-y-6">
|
||||
<div className="space-y-0.5">
|
||||
<Label htmlFor="motion-threshold" className="text-md">
|
||||
<Label htmlFor="motion-threshold">
|
||||
{t("motionDetectionTuner.Threshold.title")}
|
||||
</Label>
|
||||
<div className="my-2 text-sm text-muted-foreground">
|
||||
@@ -237,7 +235,7 @@ export default function MotionTunerView({
|
||||
</div>
|
||||
<div className="mt-2 space-y-6">
|
||||
<div className="space-y-0.5">
|
||||
<Label htmlFor="motion-threshold" className="text-md">
|
||||
<Label htmlFor="motion-threshold">
|
||||
{t("motionDetectionTuner.contourArea.title")}
|
||||
</Label>
|
||||
<div className="my-2 text-sm text-muted-foreground">
|
||||
|
||||
@@ -415,7 +415,7 @@ function ObjectList({ cameraConfig, objects }: ObjectListProps) {
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex w-8/12 flex-row items-center justify-end">
|
||||
<div className="text-md mr-2 w-1/3">
|
||||
<div className="mr-2 w-1/3">
|
||||
<div className="flex flex-col items-end justify-end">
|
||||
<p className="mb-1.5 text-sm text-primary-variant">
|
||||
{t("debug.objectShapeFilterDrawing.score")}
|
||||
@@ -426,7 +426,7 @@ function ObjectList({ cameraConfig, objects }: ObjectListProps) {
|
||||
%
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-md mr-2 w-1/3">
|
||||
<div className="mr-2 w-1/3">
|
||||
<div className="flex flex-col items-end justify-end">
|
||||
<p className="mb-1.5 text-sm text-primary-variant">
|
||||
{t("debug.objectShapeFilterDrawing.ratio")}
|
||||
@@ -434,7 +434,7 @@ function ObjectList({ cameraConfig, objects }: ObjectListProps) {
|
||||
{obj.ratio ? obj.ratio.toFixed(2).toString() : "-"}
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-md mr-2 w-1/3">
|
||||
<div className="mr-2 w-1/3">
|
||||
<div className="flex flex-col items-end justify-end">
|
||||
<p className="mb-1.5 text-sm text-primary-variant">
|
||||
{t("debug.objectShapeFilterDrawing.area")}
|
||||
@@ -505,7 +505,7 @@ function AudioList({ cameraConfig, audioDetections }: AudioListProps) {
|
||||
<div className="ml-3 text-lg">{getTranslatedLabel(key)}</div>
|
||||
</div>
|
||||
<div className="flex w-8/12 flex-row items-center justify-end">
|
||||
<div className="text-md mr-2 w-1/3">
|
||||
<div className="mr-2 w-1/3">
|
||||
<div className="flex flex-col items-end justify-end">
|
||||
<p className="mb-1.5 text-sm text-primary-variant">
|
||||
{t("debug.audio.score")}
|
||||
|
||||
@@ -24,7 +24,7 @@ import { resolveCameraName } from "@/hooks/use-camera-friendly-name";
|
||||
import { useDocDomain } from "@/hooks/use-doc-domain";
|
||||
import { cn } from "@/lib/utils";
|
||||
import Heading from "@/components/ui/heading";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Button, buttonVariants } from "@/components/ui/button";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import NameAndIdFields from "@/components/input/NameAndIdFields";
|
||||
@@ -654,10 +654,9 @@ export default function ProfilesView({
|
||||
ns: "views/settings",
|
||||
})}
|
||||
/>
|
||||
<DialogFooter className="gap-2 md:gap-0">
|
||||
<DialogFooter>
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
onClick={() => setAddDialogOpen(false)}
|
||||
disabled={addingProfile}
|
||||
>
|
||||
@@ -709,7 +708,7 @@ export default function ProfilesView({
|
||||
{t("button.cancel", { ns: "common" })}
|
||||
</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
className="bg-destructive text-white hover:bg-destructive/90"
|
||||
className={cn(buttonVariants({ variant: "destructive" }))}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
handleDeleteProfile();
|
||||
@@ -746,7 +745,6 @@ export default function ProfilesView({
|
||||
/>
|
||||
<DialogFooter>
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => setRenameProfile(null)}
|
||||
disabled={renaming}
|
||||
>
|
||||
|
||||
@@ -10,7 +10,6 @@ import {
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
} from "@/components/ui/alert-dialog";
|
||||
import { Toaster } from "@/components/ui/sonner";
|
||||
import { useCallback, useContext, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import axios from "axios";
|
||||
@@ -59,7 +58,6 @@ export default function RegionGridSettingsView({
|
||||
return (
|
||||
<>
|
||||
<div className="flex size-full flex-col md:flex-row">
|
||||
<Toaster position="top-center" closeButton={true} />
|
||||
<div className="scrollbar-container order-last mb-2 mt-2 flex h-full w-full flex-col overflow-y-auto px-2 md:order-none">
|
||||
<Heading as="h4" className="mb-2 hidden md:block">
|
||||
{t("maintenance.regionGrid.title")}
|
||||
@@ -85,7 +83,7 @@ export default function RegionGridSettingsView({
|
||||
onClick={() => setIsConfirmOpen(true)}
|
||||
disabled={isClearing}
|
||||
variant="destructive"
|
||||
className="flex flex-1 text-white md:max-w-sm"
|
||||
className="flex flex-1 md:max-w-sm"
|
||||
>
|
||||
{t("maintenance.regionGrid.clear")}
|
||||
</Button>
|
||||
@@ -108,10 +106,7 @@ export default function RegionGridSettingsView({
|
||||
{t("button.cancel", { ns: "common" })}
|
||||
</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
className={cn(
|
||||
buttonVariants({ variant: "destructive" }),
|
||||
"text-white",
|
||||
)}
|
||||
className={cn(buttonVariants({ variant: "destructive" }))}
|
||||
onClick={handleClear}
|
||||
>
|
||||
{t("maintenance.regionGrid.clear")}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { Trans, useTranslation } from "react-i18next";
|
||||
import { toast } from "sonner";
|
||||
import { Toaster } from "@/components/ui/sonner";
|
||||
import useSWR from "swr";
|
||||
import axios from "axios";
|
||||
import { Button } from "@/components/ui/button";
|
||||
@@ -443,7 +442,6 @@ export default function TriggerView({
|
||||
|
||||
return (
|
||||
<div className="flex size-full flex-col md:flex-row">
|
||||
<Toaster position="top-center" closeButton={true} />
|
||||
<div
|
||||
className={cn(
|
||||
"scrollbar-container order-last mb-2 mt-2 flex h-full w-full flex-col overflow-y-auto pb-2",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { ReactNode, useCallback, useContext, useEffect } from "react";
|
||||
import { Toaster, toast } from "sonner";
|
||||
import { toast } from "sonner";
|
||||
import { Button } from "../../components/ui/button";
|
||||
import useSWR from "swr";
|
||||
import { FrigateConfig } from "@/types/frigateConfig";
|
||||
@@ -211,7 +211,6 @@ export default function UiSettingsView() {
|
||||
|
||||
return (
|
||||
<div className="flex size-full flex-col">
|
||||
<Toaster position="top-center" closeButton={true} />
|
||||
<div className="scrollbar-container mb-2 mt-2 flex h-full w-full flex-col overflow-y-auto pb-2">
|
||||
<Heading as="h4" className="mb-3">
|
||||
{t("general.title")}
|
||||
|
||||
Reference in New Issue
Block a user