m/cup
1
0
mirror of https://github.com/sergi0g/cup.git synced 2025-11-14 08:03:48 -05:00

Switch to Lucide Icons

This commit is contained in:
Sergio
2025-02-15 12:50:59 +02:00
parent 550fb955a3
commit f79d7ff03a
8 changed files with 34 additions and 47 deletions

Binary file not shown.

View File

@@ -13,10 +13,10 @@
"dependencies": { "dependencies": {
"@headlessui/react": "^2.1.10", "@headlessui/react": "^2.1.10",
"@radix-ui/react-tooltip": "^1.1.2", "@radix-ui/react-tooltip": "^1.1.2",
"@tabler/icons-react": "^3.14.0",
"caniuse-lite": "^1.0.30001698", "caniuse-lite": "^1.0.30001698",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"date-fns": "^3.6.0", "date-fns": "^3.6.0",
"lucide-react": "^0.475.0",
"react": "^18.3.1", "react": "^18.3.1",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"tailwind-merge": "^2.5.2", "tailwind-merge": "^2.5.2",

View File

@@ -1,6 +1,6 @@
import { ReactNode, useState } from "react"; import { ReactNode, useState } from "react";
import { theme } from "../theme"; import { theme } from "../theme";
import { IconCheck, IconClipboard } from "@tabler/icons-react"; import { Clipboard, ClipboardCheck } from "lucide-react";
export function CodeBlock({ export function CodeBlock({
children, children,
@@ -29,7 +29,7 @@ export function CodeBlock({
{enableCopy && {enableCopy &&
navigator.clipboard && navigator.clipboard &&
(copySuccess ? ( (copySuccess ? (
<IconCheck <ClipboardCheck
className={`absolute right-3 size-7 bg-${theme}-100 py-1 pl-2 dark:bg-${theme}-950`} className={`absolute right-3 size-7 bg-${theme}-100 py-1 pl-2 dark:bg-${theme}-950`}
/> />
) : ( ) : (
@@ -37,7 +37,7 @@ export function CodeBlock({
className={`duration-50 absolute right-3 bg-${theme}-100 py-1 pl-2 opacity-0 transition-opacity group-hover:opacity-100 dark:bg-${theme}-950`} className={`duration-50 absolute right-3 bg-${theme}-100 py-1 pl-2 opacity-0 transition-opacity group-hover:opacity-100 dark:bg-${theme}-950`}
onClick={handleCopy(`docker pull ${children}`)} onClick={handleCopy(`docker pull ${children}`)}
> >
<IconClipboard className="size-5" /> <Clipboard className="size-5" />
</button> </button>
))} ))}
</div> </div>

View File

@@ -5,19 +5,11 @@ import {
DialogPanel, DialogPanel,
DialogTitle, DialogTitle,
} from "@headlessui/react"; } from "@headlessui/react";
import {
IconAlertTriangleFilled,
IconCircleArrowUpFilled,
IconCircleCheckFilled,
IconCube,
IconHelpCircleFilled,
IconStopwatch,
IconX,
} from "@tabler/icons-react";
import { WithTooltip } from "./Tooltip"; import { WithTooltip } from "./Tooltip";
import type { Image } from "../types"; import type { Image } from "../types";
import { theme } from "../theme"; import { theme } from "../theme";
import { CodeBlock } from "./CodeBlock"; import { CodeBlock } from "./CodeBlock";
import { Box, CircleArrowUp, CircleCheck, HelpCircle, Timer, TriangleAlert, X } from "lucide-react";
const clickable_registries = [ const clickable_registries = [
"registry-1.docker.io", "registry-1.docker.io",
@@ -53,7 +45,7 @@ export default function Image({ data }: { data: Image }) {
<> <>
<button onClick={handleOpen} className="w-full"> <button onClick={handleOpen} className="w-full">
<li className="flex items-center gap-4 break-all px-6 py-4 text-start"> <li className="flex items-center gap-4 break-all px-6 py-4 text-start">
<IconCube className="size-6 shrink-0" /> <Box className="size-6 shrink-0" />
{data.reference} {data.reference}
<Icon data={data} /> <Icon data={data} />
</li> </li>
@@ -73,7 +65,7 @@ export default function Image({ data }: { data: Image }) {
className={`flex flex-col gap-3 px-6 py-4 text-${theme}-400 dark:text-${theme}-600`} className={`flex flex-col gap-3 px-6 py-4 text-${theme}-400 dark:text-${theme}-600`}
> >
<div className="mb-4 flex items-center gap-3"> <div className="mb-4 flex items-center gap-3">
<IconCube className="size-6 shrink-0 text-black dark:text-white" /> <Box className="size-6 shrink-0 text-black dark:text-white" />
<DialogTitle className="text-black dark:text-white"> <DialogTitle className="text-black dark:text-white">
{url ? ( {url ? (
<> <>
@@ -103,21 +95,21 @@ export default function Image({ data }: { data: Image }) {
)} )}
</DialogTitle> </DialogTitle>
<button onClick={handleClose} className="ml-auto"> <button onClick={handleClose} className="ml-auto">
<IconX className="size-6 shrink-0 text-gray-500" /> <X className="size-6 shrink-0 text-gray-500" />
</button> </button>
</div> </div>
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<DialogIcon data={data} /> <DialogIcon data={data} />
</div> </div>
<div className="mb-4 flex items-center gap-3"> <div className="mb-4 flex items-center gap-3">
<IconStopwatch className="size-6 shrink-0 text-gray-500" /> <Timer className="size-6 shrink-0 text-gray-500" />
<span> <span>
Checked in <b>{data.time}</b> ms Checked in <b>{data.time}</b> ms
</span> </span>
</div> </div>
{data.result.error && ( {data.result.error && (
<div className="break-before mb-4 flex items-center gap-3 overflow-hidden rounded-md bg-yellow-400/10 px-3 py-2"> <div className="break-before mb-4 flex items-center gap-3 overflow-hidden rounded-md bg-yellow-400/10 px-3 py-2">
<IconAlertTriangleFilled className="size-6 shrink-0 text-yellow-500" /> <TriangleAlert className="size-6 shrink-0 text-yellow-500" />
{data.result.error} {data.result.error}
</div> </div>
)} )}
@@ -164,7 +156,7 @@ function Icon({ data }: { data: Image }) {
text="Unknown" text="Unknown"
className="ml-auto size-6 shrink-0 text-gray-500" className="ml-auto size-6 shrink-0 text-gray-500"
> >
<IconHelpCircleFilled /> <HelpCircle />
</WithTooltip> </WithTooltip>
); );
case false: case false:
@@ -173,7 +165,7 @@ function Icon({ data }: { data: Image }) {
text="Up to date" text="Up to date"
className="ml-auto size-6 shrink-0 text-green-500" className="ml-auto size-6 shrink-0 text-green-500"
> >
<IconCircleCheckFilled /> <CircleCheck />
</WithTooltip> </WithTooltip>
); );
case true: case true:
@@ -185,7 +177,7 @@ function Icon({ data }: { data: Image }) {
text="Major Update" text="Major Update"
className="ml-auto size-6 shrink-0 text-red-500" className="ml-auto size-6 shrink-0 text-red-500"
> >
<IconCircleArrowUpFilled /> <CircleArrowUp />
</WithTooltip> </WithTooltip>
); );
case "minor": case "minor":
@@ -194,7 +186,7 @@ function Icon({ data }: { data: Image }) {
text="Minor Update" text="Minor Update"
className="ml-auto size-6 shrink-0 text-yellow-500" className="ml-auto size-6 shrink-0 text-yellow-500"
> >
<IconCircleArrowUpFilled /> <CircleArrowUp />
</WithTooltip> </WithTooltip>
); );
case "patch": case "patch":
@@ -203,7 +195,7 @@ function Icon({ data }: { data: Image }) {
text="Patch Update" text="Patch Update"
className="ml-auto size-6 shrink-0 text-blue-500" className="ml-auto size-6 shrink-0 text-blue-500"
> >
<IconCircleArrowUpFilled /> <CircleArrowUp />
</WithTooltip> </WithTooltip>
); );
} }
@@ -213,7 +205,7 @@ function Icon({ data }: { data: Image }) {
text="Update available" text="Update available"
className="ml-auto size-6 shrink-0 text-blue-500" className="ml-auto size-6 shrink-0 text-blue-500"
> >
<IconCircleArrowUpFilled /> <CircleArrowUp />
</WithTooltip> </WithTooltip>
); );
} }
@@ -225,14 +217,14 @@ function DialogIcon({ data }: { data: Image }) {
case null: case null:
return ( return (
<> <>
<IconHelpCircleFilled className="size-6 shrink-0 text-gray-500" /> <HelpCircle className="size-6 shrink-0 text-gray-500" />
Unknown Unknown
</> </>
); );
case false: case false:
return ( return (
<> <>
<IconCircleCheckFilled className="size-6 shrink-0 text-green-500" /> <CircleCheck className="size-6 shrink-0 text-green-500" />
Up to date Up to date
</> </>
); );
@@ -242,21 +234,21 @@ function DialogIcon({ data }: { data: Image }) {
case "major": case "major":
return ( return (
<> <>
<IconCircleArrowUpFilled className="size-6 shrink-0 text-red-500" /> <CircleArrowUp className="size-6 shrink-0 text-red-500" />
Major update Major update
</> </>
); );
case "minor": case "minor":
return ( return (
<> <>
<IconCircleArrowUpFilled className="size-6 shrink-0 text-yellow-500" /> <CircleArrowUp className="size-6 shrink-0 text-yellow-500" />
Minor update Minor update
</> </>
); );
case "patch": case "patch":
return ( return (
<> <>
<IconCircleArrowUpFilled className="size-6 shrink-0 text-blue-500" /> <CircleArrowUp className="size-6 shrink-0 text-blue-500" />
Patch update Patch update
</> </>
); );
@@ -264,7 +256,7 @@ function DialogIcon({ data }: { data: Image }) {
} else if (data.result.info?.type === "digest") { } else if (data.result.info?.type === "digest") {
return ( return (
<> <>
<IconCircleArrowUpFilled className="size-6 shrink-0 text-blue-500" /> <CircleArrowUp className="size-6 shrink-0 text-blue-500" />
Update available Update available
</> </>
); );

View File

@@ -1,7 +1,7 @@
import { IconLoader2 } from "@tabler/icons-react";
import { Data } from "../types"; import { Data } from "../types";
import Logo from "./Logo"; import Logo from "./Logo";
import { theme } from "../theme"; import { theme } from "../theme";
import { RefreshCw } from "lucide-react";
export default function Loading({ onLoad }: { onLoad: (data: Data) => void }) { export default function Loading({ onLoad }: { onLoad: (data: Data) => void }) {
fetch( fetch(
@@ -28,7 +28,7 @@ export default function Loading({ onLoad }: { onLoad: (data: Data) => void }) {
<div <div
className={`flex h-full items-center justify-center gap-1 text-${theme}-500 dark:text-${theme}-400`} className={`flex h-full items-center justify-center gap-1 text-${theme}-500 dark:text-${theme}-400`}
> >
Loading <IconLoader2 className="animate-spin" /> Loading <RefreshCw className="animate-spin" />
</div> </div>
</div> </div>
</div> </div>

View File

@@ -1,6 +1,6 @@
import { ChangeEvent, useState } from "react"; import { ChangeEvent, useState } from "react";
import { theme } from "../theme"; import { theme } from "../theme";
import { IconSearch, IconX } from "@tabler/icons-react"; import { SearchIcon, X } from "lucide-react";
export default function Search({ export default function Search({
onChange, onChange,
@@ -27,7 +27,7 @@ export default function Search({
<div <div
className={`flex w-full items-center rounded-md border border-${theme}-300 dark:border-${theme}-700 gap-1 px-2 bg-${theme}-200 dark:bg-${theme}-800 peer flex-nowrap`} className={`flex w-full items-center rounded-md border border-${theme}-300 dark:border-${theme}-700 gap-1 px-2 bg-${theme}-200 dark:bg-${theme}-800 peer flex-nowrap`}
> >
<IconSearch className="size-5" /> <SearchIcon className="size-5" />
<div className="w-full"> <div className="w-full">
<input <input
className={`h-10 w-full text-sm text-${theme}-600 dark:text-${theme}-400 peer bg-transparent focus:outline-none placeholder:text-${theme}-500`} className={`h-10 w-full text-sm text-${theme}-600 dark:text-${theme}-400 peer bg-transparent focus:outline-none placeholder:text-${theme}-500`}
@@ -41,7 +41,7 @@ export default function Search({
onClick={handleClear} onClick={handleClear}
className={`hover:text-${theme}-600 dark:hover:text-${theme}-400`} className={`hover:text-${theme}-600 dark:hover:text-${theme}-400`}
> >
<IconX className="size-5" /> <X className="size-5" />
</button> </button>
)} )}
</div> </div>

View File

@@ -4,7 +4,7 @@ import {
DisclosurePanel, DisclosurePanel,
} from "@headlessui/react"; } from "@headlessui/react";
import { theme } from "../theme"; import { theme } from "../theme";
import { IconChevronDown } from "@tabler/icons-react"; import { ChevronDown } from "lucide-react";
export function Server({ export function Server({
name, name,
@@ -29,7 +29,7 @@ export function Server({
> >
{name} {name}
</span> </span>
<IconChevronDown <ChevronDown
className={`duration-300 size-5 text-${theme}-600 transition-transform group-data-[open]:rotate-180 dark:text-${theme}-400 group-data-[hover]:text-${theme}-800 group-data-[hover]:dark:text-${theme}-200 transition-colors`} className={`duration-300 size-5 text-${theme}-600 transition-transform group-data-[open]:rotate-180 dark:text-${theme}-400 group-data-[hover]:text-${theme}-800 group-data-[hover]:dark:text-${theme}-200 transition-colors`}
/> />
</DisclosureButton> </DisclosureButton>

View File

@@ -1,9 +1,4 @@
import { import { CircleArrowUp, CircleCheck, Eye, HelpCircle } from "lucide-react";
IconCircleArrowUpFilled,
IconCircleCheckFilled,
IconEyeFilled,
IconHelpCircleFilled,
} from "@tabler/icons-react";
import { theme } from "../theme"; import { theme } from "../theme";
import { Data } from "../types"; import { Data } from "../types";
@@ -39,14 +34,14 @@ export default function Statistic({
{metrics[name]} {metrics[name]}
</dd> </dd>
{name === "monitored_images" && ( {name === "monitored_images" && (
<IconEyeFilled className="size-6 shrink-0 text-black dark:text-white" /> <Eye className="size-6 shrink-0 text-black dark:text-white" />
)} )}
{name === "up_to_date" && ( {name === "up_to_date" && (
<IconCircleCheckFilled className="size-6 shrink-0 text-green-500" /> <CircleCheck className="size-6 shrink-0 text-green-500" />
)} )}
{name === "updates_available" && getUpdatesAvailableIcon(metrics)} {name === "updates_available" && getUpdatesAvailableIcon(metrics)}
{name === "unknown" && ( {name === "unknown" && (
<IconHelpCircleFilled className="size-6 shrink-0 text-gray-500" /> <HelpCircle className="size-6 shrink-0 text-gray-500" />
)} )}
</div> </div>
</div> </div>
@@ -75,5 +70,5 @@ function getUpdatesAvailableIcon(metrics: Data["metrics"]) {
default: default:
color = "text-blue-500"; color = "text-blue-500";
} }
return <IconCircleArrowUpFilled className={`size-6 shrink-0 ${color}`} />; return <CircleArrowUp className={`size-6 shrink-0 ${color}`} />;
} }