lint and add frontend-ui workflow

This commit is contained in:
Eduard Gert
2026-06-18 13:56:42 +02:00
parent 9cbaf62eda
commit 0b5fa75549
53 changed files with 499 additions and 308 deletions
@@ -88,7 +88,7 @@ export const ProfileDropdown = ({ onManageProfiles }: ProfileDropdownProps) => {
listRef.current?.focus();
}}
className={cn(
"z-50 min-w-64 overflow-hidden rounded-lg border border-nb-gray-900 bg-nb-gray-935 p-1 text-nb-gray-200 shadow-lg select-none wails-no-draggable",
"wails-no-draggable z-50 min-w-64 select-none overflow-hidden rounded-lg border border-nb-gray-900 bg-nb-gray-935 p-1 text-nb-gray-200 shadow-lg",
"data-[state=open]:animate-in data-[state=closed]:animate-out",
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
@@ -111,7 +111,10 @@ export const ProfileDropdown = ({ onManageProfiles }: ProfileDropdownProps) => {
>
{sortedProfiles.length > 0 && (
<>
<ScrollArea.Root type={"auto"} className={"overflow-hidden -mx-1"}>
<ScrollArea.Root
type={"auto"}
className={"-mx-1 overflow-hidden"}
>
<ScrollArea.Viewport className={"max-h-60 px-1"}>
{sortedProfiles.map((profile) => (
<ProfileRow
@@ -125,11 +128,15 @@ export const ProfileDropdown = ({ onManageProfiles }: ProfileDropdownProps) => {
<ScrollArea.Scrollbar
orientation={"vertical"}
className={cn(
"flex select-none touch-none transition-colors",
"flex touch-none select-none transition-colors",
"w-1.5 bg-transparent",
)}
>
<ScrollArea.Thumb className={"flex-1 rounded-full bg-nb-gray-800 hover:bg-nb-gray-700 relative"} />
<ScrollArea.Thumb
className={
"relative flex-1 rounded-full bg-nb-gray-800 hover:bg-nb-gray-700"
}
/>
</ScrollArea.Scrollbar>
</ScrollArea.Root>
<div className={"-mx-1 h-px bg-nb-gray-910"} />
@@ -143,13 +150,17 @@ export const ProfileDropdown = ({ onManageProfiles }: ProfileDropdownProps) => {
disabled={!onManageProfiles}
className={cn(
"flex items-center gap-2 px-2 py-1.5",
"rounded-md outline-none cursor-default text-sm",
"cursor-default rounded-md text-sm outline-none",
"data-[selected=true]:bg-nb-gray-900",
"data-[disabled=true]:opacity-50 data-[disabled=true]:pointer-events-none",
"data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50",
)}
>
<Settings2 size={14} aria-hidden={"true"} className={"shrink-0"} />
<span className={"truncate flex-1"}>
<Settings2
size={14}
aria-hidden={"true"}
className={"shrink-0"}
/>
<span className={"flex-1 truncate"}>
{t("profile.dropdown.manageProfiles")}
</span>
</Command.Item>
@@ -167,13 +178,13 @@ const ProfileTriggerSkeleton = () => (
role={"status"}
aria-busy={"true"}
aria-live={"polite"}
className={"h-10 flex items-center gap-2 px-3 rounded-lg select-none wails-no-draggable"}
className={"wails-no-draggable flex h-10 select-none items-center gap-2 rounded-lg px-3"}
>
<div
aria-hidden={"true"}
className={"size-4 rounded-full bg-nb-gray-900 animate-pulse shrink-0"}
className={"size-4 shrink-0 animate-pulse rounded-full bg-nb-gray-900"}
/>
<div aria-hidden={"true"} className={"h-4 w-24 rounded bg-nb-gray-900 animate-pulse"} />
<div aria-hidden={"true"} className={"h-4 w-24 animate-pulse rounded bg-nb-gray-900"} />
</div>
);
@@ -194,12 +205,12 @@ const ProfileTriggerButton = forwardRef<HTMLButtonElement, ProfileTriggerButtonP
aria-label={t("header.profile.switch")}
aria-haspopup={"listbox"}
className={cn(
"h-10 flex items-center gap-2 px-3 rounded-lg outline-none cursor-default select-none wails-no-draggable",
"wails-no-draggable flex h-10 cursor-default select-none items-center gap-2 rounded-lg px-3 outline-none",
"text-nb-gray-200 hover:bg-nb-gray-900",
"data-[state=open]:bg-nb-gray-900",
"disabled:opacity-50 disabled:hover:bg-transparent",
"focus-visible:ring-2 focus-visible:ring-white/60 focus-visible:ring-offset-2 focus-visible:ring-offset-nb-gray-940",
"transition-colors duration-150 wails-no-draggable",
"wails-no-draggable transition-colors duration-150",
className,
)}
{...props}
@@ -207,15 +218,15 @@ const ProfileTriggerButton = forwardRef<HTMLButtonElement, ProfileTriggerButtonP
<Icon
size={16}
aria-hidden={"true"}
className={"text-nb-gray-200 shrink-0 wails-no-draggable"}
className={"wails-no-draggable shrink-0 text-nb-gray-200"}
/>
<span className={"text-sm font-medium truncate max-w-[140px] wails-no-draggable"}>
<span className={"wails-no-draggable max-w-[140px] truncate text-sm font-medium"}>
{name}
</span>
<ChevronDown
size={14}
aria-hidden={"true"}
className={"text-nb-gray-200 shrink-0 wails-no-draggable"}
className={"wails-no-draggable shrink-0 text-nb-gray-200"}
/>
</button>
);
@@ -235,13 +246,13 @@ const ProfileRow = ({ profile, isActive, onSelect }: ProfileRowProps) => {
value={profile.id}
onSelect={() => onSelect(profile.id)}
className={cn(
"flex gap-2 px-2 py-2 pr-3 w-auto last:mb-1",
"rounded-md outline-none cursor-default text-sm",
"flex w-auto gap-2 px-2 py-2 pr-3 last:mb-1",
"cursor-default rounded-md text-sm outline-none",
"data-[selected=true]:bg-nb-gray-900",
showEmail ? "items-start" : "items-center",
)}
>
<div className={"flex flex-col min-w-0 flex-1 leading-tight"}>
<div className={"flex min-w-0 flex-1 flex-col leading-tight"}>
<span className={"truncate"}>{profile.name}</span>
{showEmail && <TruncatedEmail email={profile.email} />}
</div>
@@ -267,7 +278,7 @@ const TruncatedEmail = ({ email }: { email: string }) => {
}, [email]);
const span = (
<span ref={ref} className={"text-xs mt-0.5 text-nb-gray-300 truncate max-w-[180px]"}>
<span ref={ref} className={"mt-0.5 max-w-[180px] truncate text-xs text-nb-gray-300"}>
{email}
</span>
);
@@ -125,7 +125,7 @@ export function ProfilesTab() {
<div
className={cn(
"bg-nb-gray-930/60 border border-nb-gray-900 rounded-xl overflow-hidden",
"overflow-hidden rounded-xl border border-nb-gray-900 bg-nb-gray-930/60",
)}
>
<ProfilesTable
@@ -138,17 +138,19 @@ export function ProfilesTab() {
{loaded && ordered.length === 0 && (
<div
className={"flex flex-col items-center justify-center py-10 text-center"}
className={
"flex flex-col items-center justify-center py-10 text-center"
}
>
<UserCircle
size={28}
aria-hidden={"true"}
className={"text-nb-gray-500 mb-2"}
className={"mb-2 text-nb-gray-500"}
/>
<p className={"text-sm font-semibold text-nb-gray-200"}>
{t("settings.profiles.emptyTitle")}
</p>
<p className={"mt-1 text-xs text-nb-gray-400 max-w-sm text-balance"}>
<p className={"mt-1 max-w-sm text-balance text-xs text-nb-gray-400"}>
{t("settings.profiles.emptyDescription")}
</p>
</div>
@@ -271,7 +273,7 @@ const ProfilesTable = ({
return (
<table
aria-label={t("settings.profiles.section.profiles")}
className={"w-full text-sm border-separate border-spacing-0"}
className={"w-full border-separate border-spacing-0 text-sm"}
>
<tbody className={"flex flex-col"}>
{ordered.map((profile, index) => (
@@ -347,19 +349,21 @@ const ProfileRow = ({
>
<td
className={cn(
"flex gap-2 min-w-0 leading-tight flex-1",
"flex min-w-0 flex-1 gap-2 leading-tight",
showEmail ? "items-start" : "items-center",
)}
>
<Icon
size={15}
aria-hidden={"true"}
className={cn("text-nb-gray-200 shrink-0", showEmail ? "mt-0.5" : "")}
className={cn("shrink-0 text-nb-gray-200", showEmail ? "mt-0.5" : "")}
/>
<div className={"flex flex-col min-w-0 flex-1 leading-tight"}>
<div className={"flex items-center gap-2 min-w-0"}>
<div className={"flex min-w-0 flex-1 flex-col leading-tight"}>
<div className={"flex min-w-0 items-center gap-2"}>
<span
className={"truncate font-medium text-nb-gray-100 select-text cursor-text"}
className={
"cursor-text select-text truncate font-medium text-nb-gray-100"
}
>
{profile.name}
</span>
@@ -397,7 +401,7 @@ const TruncatedEmail = ({ email }: { email: string }) => {
const span = (
<span
ref={ref}
className={"text-xs text-nb-gray-300 truncate mt-0.5 select-text cursor-text"}
className={"mt-0.5 cursor-text select-text truncate text-xs text-nb-gray-300"}
>
{email}
</span>
@@ -490,15 +494,15 @@ const ActionIconButton = ({
aria-disabled={disabled || undefined}
tabIndex={hidden || !tabbable ? -1 : 0}
className={cn(
"h-9 w-9 inline-flex items-center justify-center rounded-md cursor-default outline-none",
"inline-flex h-9 w-9 cursor-default items-center justify-center rounded-md outline-none",
"transition-colors duration-150",
"focus-visible:ring-2 focus-visible:ring-white/60 focus-visible:ring-offset-2 focus-visible:ring-offset-nb-gray-940",
variant === "danger"
? "text-nb-gray-400 hover:text-red-500 hover:bg-red-500/10"
: "text-nb-gray-400 hover:text-nb-gray-100 hover:bg-nb-gray-900",
hidden && "opacity-0 pointer-events-none",
? "text-nb-gray-400 hover:bg-red-500/10 hover:text-red-500"
: "text-nb-gray-400 hover:bg-nb-gray-900 hover:text-nb-gray-100",
hidden && "pointer-events-none opacity-0",
disabled &&
"opacity-40 cursor-not-allowed hover:!text-nb-gray-400 hover:!bg-transparent",
"cursor-not-allowed opacity-40 hover:!bg-transparent hover:!text-nb-gray-400",
)}
>
<Icon size={16} aria-hidden={"true"} />