mirror of
https://github.com/hex248/sprint.git
synced 2026-02-08 02:33:01 +00:00
use Icon component
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { UserRound } from "lucide-react";
|
||||
import { useSession } from "@/components/session-provider";
|
||||
import Icon from "@/components/ui/icon";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const FALLBACK_COLOURS = [
|
||||
@@ -89,7 +89,7 @@ export default function Avatar({
|
||||
) : name ? (
|
||||
<span className={textClass}>{getInitials(name)}</span>
|
||||
) : (
|
||||
<UserRound className={"size-10"} />
|
||||
<Icon icon="userRound" className={"size-10"} />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import type { IssueResponse, ProjectResponse, SprintRecord, UserRecord } from "@sprint/shared";
|
||||
import { Check, Link, Trash, X } from "lucide-react";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
import { MultiAssigneeSelect } from "@/components/multi-assignee-select";
|
||||
@@ -10,6 +9,7 @@ import StatusTag from "@/components/status-tag";
|
||||
import { TimerDisplay } from "@/components/timer-display";
|
||||
import { TimerModal } from "@/components/timer-modal";
|
||||
import { ConfirmDialog } from "@/components/ui/confirm-dialog";
|
||||
import Icon from "@/components/ui/icon";
|
||||
import { SelectTrigger } from "@/components/ui/select";
|
||||
import { issue } from "@/lib/server";
|
||||
import { issueID } from "@/lib/utils";
|
||||
@@ -246,13 +246,13 @@ export function IssueDetailPane({
|
||||
</span>
|
||||
<div className="flex items-center">
|
||||
<IconButton onClick={handleCopyLink} title={linkCopied ? "Copied" : "Copy link"}>
|
||||
{linkCopied ? <Check /> : <Link />}
|
||||
{linkCopied ? <Icon icon="check" /> : <Icon icon="link" />}
|
||||
</IconButton>
|
||||
<IconButton variant="destructive" onClick={handleDelete} title={"Delete issue"}>
|
||||
<Trash />
|
||||
<Icon icon="trash" />
|
||||
</IconButton>
|
||||
<IconButton onClick={close} title={"Close"}>
|
||||
<X />
|
||||
<Icon icon="x" />
|
||||
</IconButton>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { LogOut } from "lucide-react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import Icon from "@/components/ui/icon";
|
||||
import { clearAuth, cn, getCsrfToken, getServerURL } from "@/lib/utils";
|
||||
|
||||
export default function LogOutButton({
|
||||
@@ -37,7 +37,7 @@ export default function LogOutButton({
|
||||
size={noStyle ? "none" : "default"}
|
||||
>
|
||||
Log out
|
||||
<LogOut size={15} />
|
||||
<Icon icon="logOut" size={15} />
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/** biome-ignore-all lint/correctness/useExhaustiveDependencies: <> */
|
||||
|
||||
import { USER_NAME_MAX_LENGTH, USER_USERNAME_MAX_LENGTH } from "@sprint/shared";
|
||||
import { AlertTriangle, X } from "lucide-react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useNavigate, useSearchParams } from "react-router-dom";
|
||||
import Avatar from "@/components/avatar";
|
||||
@@ -10,6 +9,7 @@ import { useSession } from "@/components/session-provider";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Dialog, DialogContent, DialogTitle, DialogTrigger } from "@/components/ui/dialog";
|
||||
import { Field } from "@/components/ui/field";
|
||||
import Icon from "@/components/ui/icon";
|
||||
import { IconButton } from "@/components/ui/icon-button";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { UploadAvatar } from "@/components/upload-avatar";
|
||||
@@ -153,9 +153,9 @@ export default function LogInForm() {
|
||||
setShowWarning(false);
|
||||
}}
|
||||
>
|
||||
<X />
|
||||
<Icon icon="x" />
|
||||
</IconButton>
|
||||
<AlertTriangle className="w-16 h-16 text-yellow-500" strokeWidth={1.5} />
|
||||
<Icon icon="alertTriangle" className="w-16 h-16 text-yellow-500" />
|
||||
<div className="text-center text-sm text-muted-foreground font-500">
|
||||
<p>
|
||||
This application is currently under construction. Your data is very likely to be
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { UserRecord } from "@sprint/shared";
|
||||
import { Plus } from "lucide-react";
|
||||
import Icon from "@/components/ui/icon";
|
||||
import { IconButton } from "@/components/ui/icon-button";
|
||||
import { UserSelect } from "@/components/user-select";
|
||||
|
||||
@@ -62,7 +62,7 @@ export function MultiAssigneeSelect({
|
||||
</div>
|
||||
{index === assigneeIds.length - 1 && canAddMore && (
|
||||
<IconButton onClick={handleAddAssignee} title={"Add assignee"} className="w-9 h-9">
|
||||
<Plus className="h-4 w-4" />
|
||||
<Icon icon="plus" className="h-4 w-4" />
|
||||
</IconButton>
|
||||
)}
|
||||
</>
|
||||
|
||||
@@ -7,7 +7,6 @@ import {
|
||||
type ProjectResponse,
|
||||
type SprintRecord,
|
||||
} from "@sprint/shared";
|
||||
import { ChevronDown, ChevronUp, EllipsisVertical, Plus, X } from "lucide-react";
|
||||
import { type ReactNode, useCallback, useEffect, useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
import { AddMemberDialog } from "@/components/add-member-dialog";
|
||||
@@ -28,6 +27,7 @@ import {
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
import Icon from "@/components/ui/icon";
|
||||
import { IconButton } from "@/components/ui/icon-button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
||||
@@ -571,9 +571,15 @@ function OrganisationsDialog({
|
||||
>
|
||||
{member.OrganisationMember.role ===
|
||||
"admin" ? (
|
||||
<ChevronDown className="size-5" />
|
||||
<Icon
|
||||
icon="chevronDown"
|
||||
className="size-5"
|
||||
/>
|
||||
) : (
|
||||
<ChevronUp className="size-5" />
|
||||
<Icon
|
||||
icon="chevronUp"
|
||||
className="size-5"
|
||||
/>
|
||||
)}
|
||||
</IconButton>
|
||||
<IconButton
|
||||
@@ -585,7 +591,7 @@ function OrganisationsDialog({
|
||||
)
|
||||
}
|
||||
>
|
||||
<X className="size-5" />
|
||||
<Icon icon="x" className="size-5" />
|
||||
</IconButton>
|
||||
</>
|
||||
)}
|
||||
@@ -609,7 +615,7 @@ function OrganisationsDialog({
|
||||
}}
|
||||
trigger={
|
||||
<Button variant="outline">
|
||||
Add user <Plus className="size-4" />
|
||||
Add user <Icon icon="plus" className="size-4" />
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
@@ -683,7 +689,10 @@ function OrganisationsDialog({
|
||||
trigger={
|
||||
<Button variant="outline" size="sm">
|
||||
Create sprint{" "}
|
||||
<Plus className="size-4" />
|
||||
<Icon
|
||||
icon="plus"
|
||||
className="size-4"
|
||||
/>
|
||||
</Button>
|
||||
}
|
||||
sprints={sprints}
|
||||
@@ -726,7 +735,10 @@ function OrganisationsDialog({
|
||||
noStyle
|
||||
className="hover:opacity-80 cursor-pointer"
|
||||
>
|
||||
<EllipsisVertical className="size-4 text-foreground" />
|
||||
<Icon
|
||||
icon="ellipsisVertical"
|
||||
className="size-4 text-foreground"
|
||||
/>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent
|
||||
align="end"
|
||||
@@ -740,7 +752,10 @@ function OrganisationsDialog({
|
||||
}
|
||||
className="hover:bg-primary-foreground"
|
||||
>
|
||||
<ChevronUp className="size-4 text-muted-foreground" />
|
||||
<Icon
|
||||
icon="chevronUp"
|
||||
className="size-4 text-muted-foreground"
|
||||
/>
|
||||
Move up
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
@@ -753,7 +768,10 @@ function OrganisationsDialog({
|
||||
}
|
||||
className="hover:bg-primary-foreground"
|
||||
>
|
||||
<ChevronDown className="size-4 text-muted-foreground" />
|
||||
<Icon
|
||||
icon="chevronDown"
|
||||
className="size-4 text-muted-foreground"
|
||||
/>
|
||||
Move down
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
@@ -766,7 +784,7 @@ function OrganisationsDialog({
|
||||
}
|
||||
className="hover:bg-destructive/10"
|
||||
>
|
||||
<X className="size-4" />
|
||||
<Icon icon="x" className="size-4" />
|
||||
Remove
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
@@ -815,7 +833,7 @@ function OrganisationsDialog({
|
||||
ISSUE_STATUS_MAX_LENGTH
|
||||
}
|
||||
>
|
||||
<Plus className="size-4" />
|
||||
<Icon icon="plus" className="size-4" />
|
||||
</IconButton>
|
||||
</div>
|
||||
{statusError && (
|
||||
@@ -833,7 +851,7 @@ function OrganisationsDialog({
|
||||
}}
|
||||
className="flex gap-2 w-full min-w-0"
|
||||
>
|
||||
Create status <Plus className="size-4" />
|
||||
Create status <Icon icon="plus" className="size-4" />
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { CheckIcon, ServerIcon, Undo2 } from "lucide-react";
|
||||
import { type ReactNode, useState } from "react";
|
||||
import { createPortal } from "react-dom";
|
||||
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog";
|
||||
import Icon from "@/components/ui/icon";
|
||||
import { IconButton } from "@/components/ui/icon-button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
@@ -118,7 +118,7 @@ export function ServerConfigurationDialog({ trigger }: { trigger?: ReactNode })
|
||||
className="absolute top-2 right-2"
|
||||
title={"Server Configuration"}
|
||||
>
|
||||
<ServerIcon className="size-4" />
|
||||
<Icon icon="serverIcon" className="size-4" />
|
||||
</IconButton>
|
||||
)}
|
||||
</DialogTrigger>
|
||||
@@ -152,7 +152,7 @@ export function ServerConfigurationDialog({ trigger }: { trigger?: ReactNode })
|
||||
disabled={!canSave || isCheckingHealth}
|
||||
onClick={handleSave}
|
||||
>
|
||||
<CheckIcon className="size-4" />
|
||||
<Icon icon="checkIcon" className="size-4" />
|
||||
</IconButton>
|
||||
<IconButton
|
||||
variant="secondary"
|
||||
@@ -161,7 +161,7 @@ export function ServerConfigurationDialog({ trigger }: { trigger?: ReactNode })
|
||||
onClick={handleResetToDefault}
|
||||
title="Reset to default"
|
||||
>
|
||||
<Undo2 className="size-4" />
|
||||
<Icon icon="undo2" className="size-4" />
|
||||
</IconButton>
|
||||
</div>
|
||||
{!isValid && (
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Moon, Sun } from "lucide-react";
|
||||
import { useTheme } from "@/components/theme-provider";
|
||||
import Icon from "@/components/ui/icon";
|
||||
import { IconButton } from "@/components/ui/icon-button";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
@@ -20,7 +20,7 @@ function ThemeToggle({ className }: { className?: string }) {
|
||||
onClick={() => setTheme(isDark ? "light" : "dark")}
|
||||
title={isDark ? "Switch to light mode" : "Switch to dark mode"}
|
||||
>
|
||||
{isDark ? <Sun className="size-5" /> : <Moon className="size-5" />}
|
||||
{isDark ? <Icon icon="sun" className="size-5" /> : <Icon icon="moon" className="size-5" />}
|
||||
</IconButton>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Timer } from "lucide-react";
|
||||
import { useState } from "react";
|
||||
import { IssueTimer } from "@/components/issue-timer";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Dialog, DialogContent, DialogTrigger } from "@/components/ui/dialog";
|
||||
import Icon from "@/components/ui/icon";
|
||||
|
||||
export function TimerModal({ issueId }: { issueId: number }) {
|
||||
const [open, setOpen] = useState(false);
|
||||
@@ -11,7 +11,7 @@ export function TimerModal({ issueId }: { issueId: number }) {
|
||||
<Dialog open={open} onOpenChange={setOpen}>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="outline" size="sm">
|
||||
<Timer className="size-4" />
|
||||
<Icon icon="timer" className="size-4" />
|
||||
Timer
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import type { SprintRecord } from "@sprint/shared";
|
||||
import { ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon } from "lucide-react";
|
||||
import * as React from "react";
|
||||
import { type DayButton, DayPicker, getDefaultClassNames } from "react-day-picker";
|
||||
import { Button, buttonVariants } from "@/components/ui/button";
|
||||
import Icon from "@/components/ui/icon";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
function Calendar({
|
||||
@@ -109,14 +109,16 @@ function Calendar({
|
||||
},
|
||||
Chevron: ({ className, orientation, ...props }) => {
|
||||
if (orientation === "left") {
|
||||
return <ChevronLeftIcon className={cn("size-4", className)} {...props} />;
|
||||
return <Icon icon="chevronLeftIcon" className={cn("size-4", className)} {...props} />;
|
||||
}
|
||||
|
||||
if (orientation === "right") {
|
||||
return <ChevronRightIcon className={cn("size-4", className)} {...props} />;
|
||||
return (
|
||||
<Icon icon="chevronRightIcon" className={cn("size-4", className)} {...props} />
|
||||
);
|
||||
}
|
||||
|
||||
return <ChevronDownIcon className={cn("size-4", className)} {...props} />;
|
||||
return <Icon icon="chevronDownIcon" className={cn("size-4", className)} {...props} />;
|
||||
},
|
||||
DayButton: (props) => <CalendarDayButton {...props} sprints={sprints} isEnd={isEnd} />,
|
||||
WeekNumber: ({ children, ...props }) => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
||||
import { XIcon } from "lucide-react";
|
||||
import type * as React from "react";
|
||||
import Icon from "@/components/ui/icon";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
@@ -71,7 +71,7 @@ function DialogContent({
|
||||
"[&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
||||
)}
|
||||
>
|
||||
<XIcon />
|
||||
<Icon icon="x" />
|
||||
<span className="sr-only">Close</span>
|
||||
</DialogPrimitive.Close>
|
||||
)}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
|
||||
import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react";
|
||||
import type * as React from "react";
|
||||
import Icon from "@/components/ui/icon";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
function DropdownMenu({ ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Root>) {
|
||||
@@ -136,7 +136,7 @@ function DropdownMenuCheckboxItem({
|
||||
>
|
||||
<span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
|
||||
<DropdownMenuPrimitive.ItemIndicator>
|
||||
<CheckIcon className="size-4" />
|
||||
<Icon icon="checkIcon" className="size-4" />
|
||||
</DropdownMenuPrimitive.ItemIndicator>
|
||||
</span>
|
||||
{children}
|
||||
@@ -168,7 +168,7 @@ function DropdownMenuRadioItem({
|
||||
>
|
||||
<span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
|
||||
<DropdownMenuPrimitive.ItemIndicator>
|
||||
<CircleIcon className="size-2 fill-current" />
|
||||
<Icon icon="circleIcon" className="size-2 fill-current" />
|
||||
</DropdownMenuPrimitive.ItemIndicator>
|
||||
</span>
|
||||
{children}
|
||||
@@ -242,7 +242,7 @@ function DropdownMenuSubTrigger({
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
<ChevronRightIcon className="ml-auto size-4" />
|
||||
<Icon icon="chevronRightIcon" className="ml-auto size-4" />
|
||||
</DropdownMenuPrimitive.SubTrigger>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -56,6 +56,7 @@ import {
|
||||
WarningIcon as PhosphorWarning,
|
||||
XIcon as PhosphorX,
|
||||
} from "@phosphor-icons/react";
|
||||
import type { IconStyle } from "@sprint/shared";
|
||||
import {
|
||||
AlertTriangle,
|
||||
Check,
|
||||
@@ -92,6 +93,7 @@ import {
|
||||
UserRound,
|
||||
X,
|
||||
} from "lucide-react";
|
||||
import { useSessionSafe } from "@/components/session-provider";
|
||||
|
||||
const icons = {
|
||||
alertTriangle: { lucide: AlertTriangle, pixel: PixelAlert, phosphor: PhosphorWarning },
|
||||
@@ -141,11 +143,11 @@ const icons = {
|
||||
export type IconName = keyof typeof icons;
|
||||
export const iconNames = Object.keys(icons) as IconName[];
|
||||
export const iconStyles = ["lucide", "pixel", "phosphor"] as const;
|
||||
export type IconStyle = (typeof iconStyles)[number];
|
||||
export type { IconStyle };
|
||||
|
||||
export default function Icon({
|
||||
icon,
|
||||
iconStyle = "lucide",
|
||||
iconStyle,
|
||||
size = 24,
|
||||
...props
|
||||
}: {
|
||||
@@ -154,7 +156,9 @@ export default function Icon({
|
||||
size?: number | string;
|
||||
color?: string;
|
||||
} & React.ComponentProps<"svg">) {
|
||||
const IconComponent = icons[icon]?.[iconStyle];
|
||||
const session = useSessionSafe();
|
||||
const resolvedStyle = (iconStyle ?? session?.user?.iconPreference ?? "lucide") as IconStyle;
|
||||
const IconComponent = icons[icon]?.[resolvedStyle];
|
||||
|
||||
if (!IconComponent) {
|
||||
return null;
|
||||
@@ -164,9 +168,9 @@ export default function Icon({
|
||||
<IconComponent
|
||||
size={size}
|
||||
fill={
|
||||
(iconStyle === "pixel" && icon === "moon") ||
|
||||
(iconStyle === "pixel" && icon === "hash") ||
|
||||
iconStyle === "phosphor"
|
||||
(resolvedStyle === "pixel" && icon === "moon") ||
|
||||
(resolvedStyle === "pixel" && icon === "hash") ||
|
||||
resolvedStyle === "phosphor"
|
||||
? "var(--foreground)"
|
||||
: "transparent"
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Hash } from "lucide-react";
|
||||
import type * as React from "react";
|
||||
import Icon from "@/components/ui/icon";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
function Input({
|
||||
@@ -25,7 +25,7 @@ function Input({
|
||||
>
|
||||
{showHashPrefix && (
|
||||
<span className="border-r px-1 py-1 text-muted-foreground">
|
||||
<Hash className="size-3.5" strokeWidth={1.5} />
|
||||
<Icon icon="hash" className="size-3.5" />
|
||||
</span>
|
||||
)}
|
||||
<input
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
"use client";
|
||||
|
||||
import { GripVerticalIcon } from "lucide-react";
|
||||
import type * as React from "react";
|
||||
import { Group, Panel, Separator } from "react-resizable-panels";
|
||||
import Icon from "@/components/ui/icon";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
@@ -49,7 +49,7 @@ function ResizableSeparator({
|
||||
>
|
||||
{withHandle && (
|
||||
<div className="bg-border z-10 flex h-4 w-3 items-center justify-center rounded-xs border">
|
||||
<GripVerticalIcon className="size-2.5" />
|
||||
<Icon icon="gripVerticalIcon" className="size-2.5" />
|
||||
</div>
|
||||
)}
|
||||
</Separator>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as SelectPrimitive from "@radix-ui/react-select";
|
||||
import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "lucide-react";
|
||||
import type * as React from "react";
|
||||
import Icon from "@/components/ui/icon";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
@@ -72,8 +72,9 @@ function SelectTrigger({
|
||||
)}
|
||||
{children}
|
||||
<SelectPrimitive.Icon asChild>
|
||||
<ChevronDownIcon
|
||||
className={cn("size-4 opacity-50", chevronClassName)}
|
||||
<Icon
|
||||
icon="chevronDownIcon"
|
||||
className={cn("size-4.5 opacity-50", chevronClassName)}
|
||||
style={{ rotate: isOpen ? "180deg" : "0deg" }}
|
||||
/>
|
||||
</SelectPrimitive.Icon>
|
||||
@@ -165,7 +166,7 @@ function SelectItem({
|
||||
className="absolute right-2 flex size-3.5 items-center justify-center"
|
||||
>
|
||||
<SelectPrimitive.ItemIndicator>
|
||||
<CheckIcon className="size-4" />
|
||||
<Icon icon="checkIcon" className="size-4" />
|
||||
</SelectPrimitive.ItemIndicator>
|
||||
</span>
|
||||
{textClassName ? (
|
||||
@@ -197,7 +198,7 @@ function SelectScrollUpButton({
|
||||
className={cn("flex cursor-default items-center justify-center py-1", className)}
|
||||
{...props}
|
||||
>
|
||||
<ChevronUpIcon className="size-4" />
|
||||
<Icon icon="chevronUpIcon" className="size-4" />
|
||||
</SelectPrimitive.ScrollUpButton>
|
||||
);
|
||||
}
|
||||
@@ -212,7 +213,7 @@ function SelectScrollDownButton({
|
||||
className={cn("flex cursor-default items-center justify-center py-1", className)}
|
||||
{...props}
|
||||
>
|
||||
<ChevronDownIcon className="size-4" />
|
||||
<Icon icon="chevronDownIcon" className="size-4" />
|
||||
</SelectPrimitive.ScrollDownButton>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { CircleCheckIcon, InfoIcon, Loader2Icon, OctagonXIcon, TriangleAlertIcon } from "lucide-react";
|
||||
import { useTheme } from "next-themes";
|
||||
import { Toaster as Sonner, type ToasterProps } from "sonner";
|
||||
import Icon from "@/components/ui/icon";
|
||||
|
||||
const Toaster = ({ ...props }: ToasterProps) => {
|
||||
const { theme = "system" } = useTheme();
|
||||
@@ -10,11 +10,11 @@ const Toaster = ({ ...props }: ToasterProps) => {
|
||||
theme={theme as ToasterProps["theme"]}
|
||||
className="toaster group"
|
||||
icons={{
|
||||
success: <CircleCheckIcon className="size-4" />,
|
||||
info: <InfoIcon className="size-4" />,
|
||||
warning: <TriangleAlertIcon className="size-4" />,
|
||||
error: <OctagonXIcon className="size-4" />,
|
||||
loading: <Loader2Icon className="size-4 animate-spin" />,
|
||||
success: <Icon icon="circleCheckIcon" className="size-4" />,
|
||||
info: <Icon icon="infoIcon" className="size-4" />,
|
||||
warning: <Icon icon="triangleAlertIcon" className="size-4" />,
|
||||
error: <Icon icon="octagonXIcon" className="size-4" />,
|
||||
loading: <Icon icon="loader2Icon" className="size-4 animate-spin" />,
|
||||
}}
|
||||
style={
|
||||
{
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { Loader } from "lucide-react";
|
||||
|
||||
import Icon from "@/components/ui/icon";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
function Spinner({ className, ...props }: React.ComponentProps<"svg">) {
|
||||
return (
|
||||
<Loader
|
||||
<Icon
|
||||
icon="loader"
|
||||
role="status"
|
||||
aria-label="Loading"
|
||||
className={cn("size-4 animate-spin", className)}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Edit } from "lucide-react";
|
||||
import { useRef, useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
import Avatar from "@/components/avatar";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import Icon from "@/components/ui/icon";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { parseError, user } from "@/lib/server";
|
||||
import { cn } from "@/lib/utils";
|
||||
@@ -82,7 +82,7 @@ export function UploadAvatar({
|
||||
|
||||
{!uploading && showEdit && (
|
||||
<div className="absolute inset-0 flex items-center justify-center bg-black/40">
|
||||
<Edit className="size-6 text-white drop-shadow-md" />
|
||||
<Icon icon="edit" className="size-6 text-white drop-shadow-md" />
|
||||
</div>
|
||||
)}
|
||||
</Button>
|
||||
|
||||
Reference in New Issue
Block a user