Theme scrollbars with tailwind-scrollbar (#11723)

This commit is contained in:
Josh Hawkins 2024-06-03 13:43:30 -05:00 committed by GitHub
parent 9808ff64e7
commit e6d1ad0ac5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
29 changed files with 55 additions and 34 deletions

12
web/package-lock.json generated
View File

@ -66,6 +66,7 @@
"strftime": "^0.10.2",
"swr": "^2.2.5",
"tailwind-merge": "^2.3.0",
"tailwind-scrollbar": "^3.1.0",
"tailwindcss-animate": "^1.0.7",
"vaul": "^0.9.1",
"vite-plugin-monaco-editor": "^1.1.0",
@ -7389,6 +7390,17 @@
"url": "https://github.com/sponsors/dcastil"
}
},
"node_modules/tailwind-scrollbar": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/tailwind-scrollbar/-/tailwind-scrollbar-3.1.0.tgz",
"integrity": "sha512-pmrtDIZeHyu2idTejfV59SbaJyvp1VRjYxAjZBH0jnyrPRo6HL1kD5Glz8VPagasqr6oAx6M05+Tuw429Z8jxg==",
"engines": {
"node": ">=12.13.0"
},
"peerDependencies": {
"tailwindcss": "3.x"
}
},
"node_modules/tailwindcss": {
"version": "3.4.3",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.3.tgz",

View File

@ -72,6 +72,7 @@
"strftime": "^0.10.2",
"swr": "^2.2.5",
"tailwind-merge": "^2.3.0",
"tailwind-scrollbar": "^3.1.0",
"tailwindcss-animate": "^1.0.7",
"vaul": "^0.9.1",
"vite-plugin-monaco-editor": "^1.1.0",

View File

@ -310,7 +310,7 @@ function NewGroupDialog({
<Content
className={`min-w-0 ${isMobile ? "max-h-[90%] w-full rounded-t-2xl p-3" : "max-h-dvh w-6/12 overflow-y-hidden"}`}
>
<div className="my-4 flex flex-col overflow-y-auto">
<div className="scrollbar-container my-4 flex flex-col overflow-y-auto">
{editState === "none" && (
<>
<div className="flex flex-row items-center justify-between py-2">
@ -400,7 +400,7 @@ export function EditGroupDialog({
<DialogContent
className={`min-w-0 ${isMobile ? "max-h-[90%] w-full rounded-t-2xl p-3" : "max-h-dvh w-6/12 overflow-y-hidden"}`}
>
<div className="my-4 flex flex-col overflow-y-auto">
<div className="scrollbar-container my-4 flex flex-col overflow-y-auto">
<div className="mb-3 flex flex-row items-center justify-between">
<DialogTitle>Edit Camera Group</DialogTitle>
</div>
@ -651,7 +651,7 @@ export function CameraGroupEdit({
/>
<Separator className="my-2 flex bg-secondary" />
<div className="max-h-[25dvh] overflow-y-auto md:max-h-[40dvh]">
<div className="scrollbar-container max-h-[25dvh] overflow-y-auto md:max-h-[40dvh]">
<FormField
control={form.control}
name="cameras"

View File

@ -58,7 +58,7 @@ export function GeneralFilterContent({
}: GeneralFilterContentProps) {
return (
<>
<div className="h-auto overflow-y-auto overflow-x-hidden">
<div className="scrollbar-container h-auto overflow-y-auto overflow-x-hidden">
<div className="my-2.5 flex items-center justify-between">
<Label
className="mx-2 cursor-pointer text-primary"

View File

@ -263,7 +263,7 @@ export function CamerasFilterButton({
<DropdownMenuSeparator />
</>
)}
<div className="h-auto max-h-[80dvh] overflow-y-auto overflow-x-hidden p-4">
<div className="scrollbar-container h-auto max-h-[80dvh] overflow-y-auto overflow-x-hidden p-4">
<FilterSwitch
isChecked={currentCameras == undefined}
label="All Cameras"
@ -602,7 +602,7 @@ export function GeneralFilterContent({
}: GeneralFilterContentProps) {
return (
<>
<div className="h-auto max-h-[80dvh] overflow-y-auto overflow-x-hidden">
<div className="scrollbar-container h-auto max-h-[80dvh] overflow-y-auto overflow-x-hidden">
{currentSeverity && setShowAll && (
<div className="my-2.5 flex flex-col gap-2.5">
<FilterSwitch

View File

@ -115,7 +115,7 @@ export default function IconPicker({
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
/>
<div className="flex h-full flex-col overflow-y-auto">
<div className="scrollbar-container flex h-full flex-col overflow-y-auto">
<div className="grid grid-cols-6 gap-2 pr-1">
{icons.map(([name, Icon]) => (
<div

View File

@ -62,7 +62,7 @@ export default function AccountSettings({ className }: AccountSettingsProps) {
isDesktop ? "mr-5 w-72" : "max-h-[75dvh] overflow-hidden p-2"
}
>
<div className="w-full flex-col overflow-y-auto overflow-x-hidden">
<div className="scrollbar-container w-full flex-col overflow-y-auto overflow-x-hidden">
<DropdownMenuLabel>
Current User: {profile?.username || "anonymous"}
</DropdownMenuLabel>

View File

@ -142,7 +142,7 @@ export default function GeneralSettings({ className }: GeneralSettingsProps) {
isDesktop ? "mr-5 w-72" : "max-h-[75dvh] overflow-hidden p-2"
}
>
<div className="w-full flex-col overflow-y-auto overflow-x-hidden">
<div className="scrollbar-container w-full flex-col overflow-y-auto overflow-x-hidden">
<DropdownMenuLabel>System</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuGroup className={isDesktop ? "" : "flex flex-col"}>

View File

@ -93,7 +93,7 @@ function StatusAlertNav({ className }: StatusAlertNavProps) {
className,
)}
>
<div className="flex h-auto w-full flex-col items-center gap-2 overflow-y-auto overflow-x-hidden py-4">
<div className="scrollbar-container flex h-auto w-full flex-col items-center gap-2 overflow-y-auto overflow-x-hidden py-4">
{Object.entries(messages).map(([key, messageArray]) => (
<div key={key} className="flex w-full items-center gap-2">
{messageArray.map(({ id, text, color, link }: StatusMessage) => {

View File

@ -12,7 +12,7 @@ function Sidebar() {
const navbarLinks = useNavigation();
return (
<aside className="left-o scrollbar-hidden absolute inset-y-0 z-10 flex w-[52px] flex-col justify-between overflow-y-auto border-r border-secondary-highlight bg-background_alt py-4">
<aside className="scrollbar-container scrollbar-hidden absolute inset-y-0 left-0 z-10 flex w-[52px] flex-col justify-between overflow-y-auto border-r border-secondary-highlight bg-background_alt py-4">
<span tabIndex={0} className="sr-only" />
<div className="flex w-full flex-col items-center gap-0">
<Logo className="mb-6 h-8 w-8" />

View File

@ -28,7 +28,7 @@ export default function MobileCameraDrawer({
</Button>
</DrawerTrigger>
<DrawerContent className="mx-1 max-h-[75dvh] overflow-hidden rounded-t-2xl px-4">
<div className="flex h-auto w-full flex-col items-center gap-2 overflow-y-auto overflow-x-hidden py-4">
<div className="scrollbar-container flex h-auto w-full flex-col items-center gap-2 overflow-y-auto overflow-x-hidden py-4">
{allCameras.map((cam) => (
<div
key={cam}

View File

@ -222,7 +222,7 @@ export default function MobileReviewSettingsDrawer({
);
} else if (drawerMode == "filter") {
content = (
<div className="flex h-auto w-full flex-col overflow-y-auto">
<div className="scrollbar-container flex h-auto w-full flex-col overflow-y-auto">
<div className="relative mb-2 h-8 w-full">
<div
className="absolute left-0 text-selected"

View File

@ -33,7 +33,7 @@ export default function VainfoDialog({
<DialogTitle>Vainfo Output</DialogTitle>
</DialogHeader>
{vainfo ? (
<div className="mb-2 max-h-96 overflow-y-scroll whitespace-pre-line">
<div className="scrollbar-container mb-2 max-h-96 overflow-y-scroll whitespace-pre-line">
<div>Return Code: {vainfo.return_code}</div>
<br />
<div>Process {vainfo.return_code == 0 ? "Output" : "Error"}:</div>

View File

@ -587,7 +587,7 @@ export function ZoneObjectSelector({
return (
<>
<div className="h-auto overflow-y-auto overflow-x-hidden">
<div className="scrollbar-container h-auto overflow-y-auto overflow-x-hidden">
<div className="my-2.5 flex items-center justify-between">
<Label className="cursor-pointer text-primary" htmlFor="allLabels">
All Objects

View File

@ -24,6 +24,12 @@
}
}
@layer utilities {
.scrollbar-container {
@apply scrollbar-thumb-rounded-full scrollbar-track-rounded-full scrollbar-thin scrollbar-thumb-border scrollbar-track-background_alt;
}
}
/* Hide scrollbar for Chrome, Safari and Opera */
.no-scrollbar::-webkit-scrollbar {
display: none;

View File

@ -139,7 +139,7 @@ function Exports() {
<div className="w-full overflow-hidden">
{exports && filteredExports && (
<div className="grid size-full gap-2 overflow-y-auto sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
<div className="scrollbar-container grid size-full gap-2 overflow-y-auto sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
{Object.values(exports).map((item) => (
<ExportCard
key={item.name}

View File

@ -242,7 +242,7 @@ function CameraSelectButton({
<DropdownMenuSeparator />
</>
)}
<div className="mb-5 h-auto max-h-[80dvh] overflow-y-auto overflow-x-hidden p-4 md:mb-1">
<div className="scrollbar-container mb-5 h-auto max-h-[80dvh] overflow-y-auto overflow-x-hidden p-4 md:mb-1">
<div className="flex flex-col gap-2.5">
{allCameras.map((item) => (
<FilterSwitch

View File

@ -226,7 +226,7 @@ export default function SubmitPlus() {
return (
<div className="flex size-full flex-col">
<div className="flex h-16 w-full items-center justify-between overflow-x-auto px-2">
<div className="scrollbar-container flex h-16 w-full items-center justify-between overflow-x-auto px-2">
<PlusFilterGroup
selectedCameras={selectedCameras}
selectedLabels={selectedLabels}

View File

@ -610,7 +610,7 @@ function PtzControlPanel({
<BsThreeDotsVertical />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="max-h-[40dvh] overflow-y-auto">
<DropdownMenuContent className="scrollbar-container max-h-[40dvh] overflow-y-auto">
{ptz?.presets.map((preset) => {
return (
<DropdownMenuItem

View File

@ -163,7 +163,7 @@ export default function LiveDashboardView({
return (
<div
className="size-full overflow-y-auto px-1 pt-2 md:p-2"
className="scrollbar-container size-full overflow-y-auto px-1 pt-2 md:p-2"
ref={containerRef}
>
{isMobile && (

View File

@ -88,7 +88,7 @@ export default function AuthenticationView() {
return (
<div className="flex size-full flex-col md:flex-row">
<Toaster position="top-center" closeButton={true} />
<div className="order-last mb-10 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:mb-0 md:mr-2 md:mt-0">
<div className="scrollbar-container order-last mb-10 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:mb-0 md:mr-2 md:mt-0">
<div className="flex flex-row items-center justify-between gap-2">
<Heading as="h3" className="my-2">
Users

View File

@ -58,7 +58,7 @@ export default function GeneralSettingsView() {
<>
<div className="flex size-full flex-col md:flex-row">
<Toaster position="top-center" closeButton={true} />
<div className="order-last mb-10 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:mb-0 md:mr-2 md:mt-0">
<div className="scrollbar-container order-last mb-10 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:mb-0 md:mr-2 md:mt-0">
<Heading as="h3" className="my-2">
General Settings
</Heading>

View File

@ -379,7 +379,7 @@ export default function MasksAndZonesView({
{cameraConfig && editingPolygons && (
<div className="flex size-full flex-col md:flex-row">
<Toaster position="top-center" closeButton={true} />
<div className="order-last mb-10 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:mb-0 md:mr-2 md:mt-0 md:w-3/12">
<div className="scrollbar-container order-last mb-10 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:mb-0 md:mr-2 md:mt-0 md:w-3/12">
{editPane == "zone" && (
<ZoneEditPane
polygons={editingPolygons}

View File

@ -177,7 +177,7 @@ export default function MotionTunerView({
return (
<div className="flex size-full flex-col md:flex-row">
<Toaster position="top-center" closeButton={true} />
<div className="order-last mb-10 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:mb-0 md:mr-2 md:mt-0 md:w-3/12">
<div className="scrollbar-container order-last mb-10 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:mb-0 md:mr-2 md:mt-0 md:w-3/12">
<Heading as="h3" className="my-2">
Motion Detection Tuner
</Heading>

View File

@ -113,7 +113,7 @@ export default function ObjectSettingsView({
return (
<div className="flex size-full flex-col md:flex-row">
<Toaster position="top-center" closeButton={true} />
<div className="order-last mb-10 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:mb-0 md:mr-2 md:mt-0 md:w-3/12">
<div className="scrollbar-container order-last mb-10 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:mb-0 md:mr-2 md:mt-0 md:w-3/12">
<Heading as="h3" className="my-2">
Debug
</Heading>
@ -162,12 +162,10 @@ export default function ObjectSettingsView({
</div>
</div>
<Switch
key={`${param}-${optionsLoaded}`}
key={`${param}-${selectedCamera}`}
className="ml-1"
id={param}
checked={
optionsLoaded ? options && options[param] : false
}
checked={options && options[param]}
onCheckedChange={(isChecked) => {
handleSetOption(param, isChecked);
}}
@ -224,7 +222,7 @@ function ObjectList(objects?: ObjectType[]) {
);
return (
<div className="flex w-full flex-col overflow-y-auto">
<div className="scrollbar-container flex w-full flex-col overflow-y-auto">
{objects && objects.length > 0 ? (
objects.map((obj) => {
return (

View File

@ -204,7 +204,7 @@ export default function CameraMetrics({
}, [statsHistory]);
return (
<div className="mt-4 flex size-full flex-col gap-3 overflow-y-auto">
<div className="scrollbar-container mt-4 flex size-full flex-col gap-3 overflow-y-auto">
<div className="text-sm font-medium text-muted-foreground">Overview</div>
<div className="grid grid-cols-1 md:grid-cols-3">
{statsHistory.length != 0 ? (

View File

@ -344,7 +344,7 @@ export default function GeneralMetrics({
<>
<VainfoDialog showVainfo={showVainfo} setShowVainfo={setShowVainfo} />
<div className="mt-4 flex size-full flex-col overflow-y-auto">
<div className="scrollbar-container mt-4 flex size-full flex-col overflow-y-auto">
<div className="text-sm font-medium text-muted-foreground">
Detectors
</div>

View File

@ -42,7 +42,7 @@ export default function StorageMetrics({
}
return (
<div className="mt-4 flex size-full flex-col overflow-y-auto">
<div className="scrollbar-container mt-4 flex size-full flex-col overflow-y-auto">
<div className="text-sm font-medium text-muted-foreground">Overview</div>
<div className="mt-4 grid grid-cols-1 gap-2 sm:grid-cols-3">
<div className="flex-col rounded-lg bg-background_alt p-2.5 md:rounded-2xl">

View File

@ -144,5 +144,9 @@ module.exports = {
},
},
},
plugins: [require("tailwindcss-animate")],
plugins: [
require("tailwindcss-animate"),
// eslint-disable-next-line @typescript-eslint/no-var-requires
require("tailwind-scrollbar")({ nocompatible: true }),
],
};