mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
refactor: reorganize and restyle some oddities (#24855)
This commit is contained in:
+1
-1
@@ -26,7 +26,7 @@ test-output/
|
||||
|
||||
# Front-end ignore patterns.
|
||||
.next/
|
||||
site/build-storybook.log
|
||||
site/*-storybook.log
|
||||
site/coverage/
|
||||
site/storybook-static/
|
||||
site/test-results/*
|
||||
|
||||
@@ -35,10 +35,10 @@ export const AvatarData: FC<AvatarDataProps> = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex items-center w-full gap-3">
|
||||
<div className="flex items-center gap-3">
|
||||
{avatar}
|
||||
|
||||
<div className="flex flex-col w-full">
|
||||
<div className="flex flex-col">
|
||||
<span className="text-sm font-semibold text-content-primary">
|
||||
{title}
|
||||
</span>
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
import type { FC } from "react";
|
||||
import { CoderIcon } from "#/components/Icons/CoderIcon";
|
||||
import { getApplicationName, getLogoURL } from "#/utils/appearance";
|
||||
import { cn } from "#/utils/cn";
|
||||
|
||||
/**
|
||||
* Enterprise customers can set a custom logo for their Coder application. Use
|
||||
* the custom logo wherever the Coder logo is used, if a custom one is provided.
|
||||
*/
|
||||
export const CustomLogo: FC<{ className?: string }> = ({ className }) => {
|
||||
const applicationName = getApplicationName();
|
||||
const logoURL = getLogoURL();
|
||||
|
||||
return logoURL ? (
|
||||
<img
|
||||
alt={applicationName}
|
||||
src={logoURL}
|
||||
// This prevent browser to display the ugly error icon if the
|
||||
// image path is wrong or user didn't finish typing the url
|
||||
onError={(e) => {
|
||||
e.currentTarget.style.display = "none";
|
||||
}}
|
||||
onLoad={(e) => {
|
||||
e.currentTarget.style.display = "inline";
|
||||
}}
|
||||
className={cn("max-w-[200px] application-logo", className)}
|
||||
/>
|
||||
) : (
|
||||
<CoderIcon className={cn("w-12 h-12", className)} />
|
||||
);
|
||||
};
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
useRouteError,
|
||||
} from "react-router";
|
||||
import { Button } from "#/components/Button/Button";
|
||||
import { CoderIcon } from "#/components/Icons/CoderIcon";
|
||||
import { ProductLogo } from "#/components/Icons/ProductLogo";
|
||||
import { Link } from "#/components/Link/Link";
|
||||
import { useEmbeddedMetadata } from "#/hooks/useEmbeddedMetadata";
|
||||
|
||||
@@ -37,7 +37,7 @@ export const GlobalErrorBoundaryInner: FC<GlobalErrorBoundaryInnerProps> = ({
|
||||
|
||||
<main className="flex gap-6 w-full max-w-prose p-4 flex-col flex-nowrap">
|
||||
<div className="flex gap-2 flex-col items-center">
|
||||
<CoderIcon className="w-11 h-11" />
|
||||
<ProductLogo />
|
||||
|
||||
<div className="text-content-primary flex flex-col gap-1">
|
||||
<h1 className="text-2xl font-semibold m-0">{errorPageTitle}</h1>
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
import type { ComponentProps, FC } from "react";
|
||||
import { cn } from "#/utils/cn";
|
||||
|
||||
/**
|
||||
* CoderIcon represents the cloud with brackets Coder brand icon. It does not
|
||||
* contain additional aspects, like the word 'Coder'.
|
||||
*/
|
||||
export const CoderIcon: FC<ComponentProps<"svg">> = ({
|
||||
className,
|
||||
...props
|
||||
}) => (
|
||||
<svg
|
||||
// This is a case where prop order does matter. We want fill to be easy
|
||||
// to override, but all other local props should stay locked down
|
||||
fill="currentColor"
|
||||
{...props}
|
||||
className={cn("w-14 h-7 text-content-primary", className)}
|
||||
viewBox="0 0 120 60"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<title>Coder logo</title>
|
||||
<path d="M34.5381 0C54.5335 6.29882e-05 65.7432 10.1355 66.122 25.0544L48.853 25.6216C48.3984 17.3514 41.544 11.9189 34.5381 12.0809C24.919 12.2836 17.7989 19.1351 17.7988 29.9999C17.7988 40.8648 24.919 47.5951 34.5381 47.5951C41.544 47.5945 48.2468 42.4055 49.0043 34.1352L66.2733 34.5408C65.8189 49.7027 53.9276 60 34.5381 60C15.1484 60 0 48.2433 0 29.9999C7.1014e-05 11.6757 14.5426 0 34.5381 0ZM120 1.7728V58.5299H74.5559V1.7728H120Z" />
|
||||
</svg>
|
||||
);
|
||||
@@ -0,0 +1,49 @@
|
||||
import type { FC } from "react";
|
||||
import { getApplicationName, getLogoURL } from "#/utils/appearance";
|
||||
import { cn } from "#/utils/cn";
|
||||
import { ExternalImage } from "../ExternalImage/ExternalImage";
|
||||
|
||||
/**
|
||||
* Enterprise customers can set a custom logo for their Coder application. Use
|
||||
* the custom logo wherever the Coder logo is used, if a custom one is provided.
|
||||
*/
|
||||
export const ProductLogo: FC<{ className?: string }> = ({ className }) => {
|
||||
const applicationName = getApplicationName();
|
||||
const logoURL = getLogoURL();
|
||||
|
||||
return logoURL ? (
|
||||
<ExternalImage
|
||||
alt={applicationName}
|
||||
src={logoURL}
|
||||
// This prevent browser to display the ugly error icon if the
|
||||
// image path is wrong or user didn't finish typing the url
|
||||
onError={(e) => {
|
||||
e.currentTarget.style.display = "none";
|
||||
}}
|
||||
onLoad={(e) => {
|
||||
e.currentTarget.style.display = "inline";
|
||||
}}
|
||||
className={cn("h-12 max-w-[200px] application-logo", className)}
|
||||
/>
|
||||
) : (
|
||||
<CoderLogo className={cn("h-12", className)} />
|
||||
);
|
||||
};
|
||||
|
||||
const CoderLogo: FC<React.ComponentProps<"svg">> = ({
|
||||
className,
|
||||
...props
|
||||
}) => (
|
||||
<svg
|
||||
// This is a case where prop order does matter. We want fill to be easy
|
||||
// to override, but all other local props should stay locked down
|
||||
fill="currentColor"
|
||||
{...props}
|
||||
className={cn("h-7 aspect-square text-content-primary", className)}
|
||||
viewBox="0 0 120 60"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<title>Coder logo</title>
|
||||
<path d="M34.5381 0C54.5335 6.29882e-05 65.7432 10.1355 66.122 25.0544L48.853 25.6216C48.3984 17.3514 41.544 11.9189 34.5381 12.0809C24.919 12.2836 17.7989 19.1351 17.7988 29.9999C17.7988 40.8648 24.919 47.5951 34.5381 47.5951C41.544 47.5945 48.2468 42.4055 49.0043 34.1352L66.2733 34.5408C65.8189 49.7027 53.9276 60 34.5381 60C15.1484 60 0 48.2433 0 29.9999C7.1014e-05 11.6757 14.5426 0 34.5381 0ZM120 1.7728V58.5299H74.5559V1.7728H120Z" />
|
||||
</svg>
|
||||
);
|
||||
@@ -25,7 +25,7 @@ export const mockPaginationResultBase: ResultBase = {
|
||||
onPageChange: () => {},
|
||||
};
|
||||
|
||||
export const mockInitialRenderResult: PaginationResult = {
|
||||
export const mockInitialRenderResult = {
|
||||
...mockPaginationResultBase,
|
||||
isSuccess: false,
|
||||
isPlaceholderData: false,
|
||||
@@ -35,13 +35,13 @@ export const mockInitialRenderResult: PaginationResult = {
|
||||
totalRecords: undefined,
|
||||
totalPages: undefined,
|
||||
countIsCapped: false,
|
||||
};
|
||||
} as const satisfies PaginationResult;
|
||||
|
||||
export const mockSuccessResult: PaginationResult = {
|
||||
export const mockSuccessResult = {
|
||||
...mockPaginationResultBase,
|
||||
isSuccess: true,
|
||||
isPlaceholderData: false,
|
||||
currentOffsetStart: 1,
|
||||
totalPages: 1,
|
||||
totalRecords: 4,
|
||||
};
|
||||
} as const satisfies PaginationResult;
|
||||
|
||||
@@ -3,8 +3,9 @@ import type { PaginationResultInfo } from "#/hooks/usePaginatedQuery";
|
||||
import { PaginationAmount } from "./PaginationAmount";
|
||||
import { PaginationWidgetBase } from "./PaginationWidgetBase";
|
||||
|
||||
export type PaginationResult = PaginationResultInfo & {
|
||||
export type PaginationResult<Data = unknown> = PaginationResultInfo & {
|
||||
isPlaceholderData: boolean;
|
||||
data?: Data;
|
||||
};
|
||||
|
||||
type PaginationProps = HTMLAttributes<HTMLDivElement> & {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { FC, PropsWithChildren } from "react";
|
||||
import { CoderIcon } from "../Icons/CoderIcon";
|
||||
import { ProductLogo } from "../Icons/ProductLogo";
|
||||
|
||||
type WelcomeProps = Readonly<
|
||||
PropsWithChildren<{
|
||||
@@ -10,7 +10,7 @@ export const Welcome: FC<WelcomeProps> = ({ children, className }) => {
|
||||
return (
|
||||
<div className={className}>
|
||||
<div className="flex justify-center pb-1">
|
||||
<CoderIcon className="w-12 h-12" />
|
||||
<ProductLogo />
|
||||
</div>
|
||||
|
||||
<h1 className="text-3xl font-semibold m-0 flex justify-center items-center text-center leading-snug">
|
||||
|
||||
@@ -38,7 +38,6 @@ export const Navbar: FC = () => {
|
||||
return (
|
||||
<NavbarView
|
||||
user={me}
|
||||
logo_url={appearance.logo_url}
|
||||
buildInfo={buildInfoQuery.data}
|
||||
supportLinks={Array.from(uniqueLinks.values())}
|
||||
onSignOut={signOut}
|
||||
|
||||
@@ -106,12 +106,6 @@ export const ForMemberWithAgentsAccess: Story = {
|
||||
},
|
||||
};
|
||||
|
||||
export const CustomLogo: Story = {
|
||||
args: {
|
||||
logo_url: "/icon/github.svg",
|
||||
},
|
||||
};
|
||||
|
||||
export const IdleTasks: Story = {
|
||||
parameters: {
|
||||
queries: [
|
||||
|
||||
@@ -5,8 +5,7 @@ import { API } from "#/api/api";
|
||||
import type * as TypesGen from "#/api/typesGenerated";
|
||||
import { Badge } from "#/components/Badge/Badge";
|
||||
import { Button } from "#/components/Button/Button";
|
||||
import { ExternalImage } from "#/components/ExternalImage/ExternalImage";
|
||||
import { CoderIcon } from "#/components/Icons/CoderIcon";
|
||||
import { ProductLogo } from "#/components/Icons/ProductLogo";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
@@ -24,7 +23,6 @@ import { SupportIcon } from "./SupportIcon";
|
||||
import { UserDropdown } from "./UserDropdown/UserDropdown";
|
||||
|
||||
interface NavbarViewProps {
|
||||
logo_url?: string;
|
||||
user: TypesGen.User;
|
||||
buildInfo?: TypesGen.BuildInfoResponse;
|
||||
supportLinks: readonly TypesGen.LinkConfig[];
|
||||
@@ -47,7 +45,6 @@ const linkStyles = {
|
||||
|
||||
export const NavbarView: FC<NavbarViewProps> = ({
|
||||
user,
|
||||
logo_url,
|
||||
buildInfo,
|
||||
supportLinks,
|
||||
onSignOut,
|
||||
@@ -83,11 +80,7 @@ export const NavbarView: FC<NavbarViewProps> = ({
|
||||
}}
|
||||
>
|
||||
<NavLink to="/workspaces">
|
||||
{logo_url ? (
|
||||
<ExternalImage className="h-7" src={logo_url} alt="Custom Logo" />
|
||||
) : (
|
||||
<CoderIcon className="h-7 w-7 fill-content-primary" />
|
||||
)}
|
||||
<ProductLogo className="h-7" />
|
||||
</NavLink>
|
||||
|
||||
<NavItems
|
||||
|
||||
@@ -50,7 +50,7 @@ const DeploymentSettingsLayout: FC = () => {
|
||||
</BreadcrumbItem>
|
||||
</BreadcrumbList>
|
||||
</Breadcrumb>
|
||||
<hr className="h-px border-none bg-border" />
|
||||
<div className="h-px border-none bg-border" />
|
||||
<section className="px-10 max-w-screen-2xl mx-auto">
|
||||
<div className="flex flex-row gap-28 py-10">
|
||||
<DeploymentSidebar />
|
||||
|
||||
@@ -23,7 +23,7 @@ export const RequirePermission: FC<RequirePermissionProps> = ({
|
||||
}) => {
|
||||
if (!isFeatureVisible) {
|
||||
return (
|
||||
<Dialog open={true}>
|
||||
<Dialog open>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
} from "lucide-react";
|
||||
import { type FC, useState } from "react";
|
||||
import { useMutation, useQuery, useQueryClient } from "react-query";
|
||||
import { Link as RouterLink, useNavigate, useParams } from "react-router";
|
||||
import { Link, useNavigate, useParams } from "react-router";
|
||||
import { toast } from "sonner";
|
||||
import { API } from "#/api/api";
|
||||
import { getErrorDetail, getErrorMessage } from "#/api/errors";
|
||||
@@ -23,7 +23,7 @@ import {
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from "#/components/DropdownMenu/DropdownMenu";
|
||||
import { CoderIcon } from "#/components/Icons/CoderIcon";
|
||||
import { ProductLogo } from "#/components/Icons/ProductLogo";
|
||||
import { ScrollArea } from "#/components/ScrollArea/ScrollArea";
|
||||
import { Skeleton } from "#/components/Skeleton/Skeleton";
|
||||
import { Spinner } from "#/components/Spinner/Spinner";
|
||||
@@ -62,17 +62,10 @@ export const TasksSidebar: FC = () => {
|
||||
<div className="p-3 flex flex-col gap-6">
|
||||
<div className="flex items-center place-content-between">
|
||||
{!isCollapsed && (
|
||||
<Button
|
||||
size="icon"
|
||||
variant="subtle"
|
||||
className={cn(["size-8 p-0 transition-[margin,opacity]"])}
|
||||
asChild
|
||||
>
|
||||
<RouterLink to="/tasks">
|
||||
<CoderIcon className="fill-content-primary !size-6 !p-0" />
|
||||
<span className="sr-only">Navigate to tasks</span>
|
||||
</RouterLink>
|
||||
</Button>
|
||||
<Link to="/tasks">
|
||||
<ProductLogo className="block size-6 m-1" />
|
||||
<span className="sr-only">Navigate to tasks</span>
|
||||
</Link>
|
||||
)}
|
||||
|
||||
<TooltipProvider>
|
||||
@@ -106,10 +99,10 @@ export const TasksSidebar: FC = () => {
|
||||
asChild
|
||||
className={cn({ "[&_svg]:p-0": isCollapsed })}
|
||||
>
|
||||
<RouterLink to="/tasks">
|
||||
<Link to="/tasks">
|
||||
<span className={isCollapsed ? "hidden" : ""}>New Task</span>{" "}
|
||||
<EditIcon />
|
||||
</RouterLink>
|
||||
</Link>
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="right" align="center">
|
||||
@@ -233,7 +226,7 @@ const TaskSidebarMenuItem: FC<TaskSidebarMenuItemProps> = ({ task }) => {
|
||||
},
|
||||
)}
|
||||
>
|
||||
<RouterLink
|
||||
<Link
|
||||
to={{
|
||||
pathname: `/tasks/${task.owner_name}/${task.id}`,
|
||||
search: location.search,
|
||||
@@ -306,7 +299,7 @@ const TaskSidebarMenuItem: FC<TaskSidebarMenuItemProps> = ({ task }) => {
|
||||
</DropdownMenuGroup>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</RouterLink>
|
||||
</Link>
|
||||
</Button>
|
||||
|
||||
<TaskDeleteDialog
|
||||
|
||||
@@ -38,7 +38,6 @@ import type * as TypesGen from "#/api/typesGenerated";
|
||||
import { ConfirmDialog } from "#/components/Dialogs/ConfirmDialog/ConfirmDialog";
|
||||
import { DeleteDialog } from "#/components/Dialogs/DeleteDialog/DeleteDialog";
|
||||
import { useAuthenticated } from "#/hooks/useAuthenticated";
|
||||
import { useDashboard } from "#/modules/dashboard/useDashboard";
|
||||
import { createReconnectingWebSocket } from "#/utils/reconnectingWebSocket";
|
||||
import { clearPersistedSidebarTabId } from "./AgentChatPage";
|
||||
import { AgentsPageView } from "./AgentsPageView";
|
||||
@@ -67,7 +66,6 @@ const AgentsPage: FC = () => {
|
||||
const location = useLocation();
|
||||
const { agentId } = useParams();
|
||||
const { permissions } = useAuthenticated();
|
||||
const { appearance } = useDashboard();
|
||||
const isAgentsAdmin = permissions.editDeploymentConfig;
|
||||
|
||||
const [archivedFilter, setArchivedFilter] = useArchivedFilterParam();
|
||||
@@ -621,7 +619,6 @@ const AgentsPage: FC = () => {
|
||||
chatList={chatList}
|
||||
catalogModelOptions={catalogModelOptions}
|
||||
modelConfigs={chatModelConfigsQuery.data ?? []}
|
||||
logoUrl={appearance.logo_url}
|
||||
handleNewAgent={handleNewAgent}
|
||||
isCreating={false}
|
||||
isArchiving={isArchiving}
|
||||
|
||||
@@ -207,7 +207,6 @@ const defaultArgs: ComponentProps<typeof AgentsPageView> = {
|
||||
chatList: [],
|
||||
catalogModelOptions: defaultModelOptions,
|
||||
modelConfigs: defaultModelConfigs,
|
||||
logoUrl: "",
|
||||
handleNewAgent: fn(),
|
||||
isCreating: false,
|
||||
isArchiving: false,
|
||||
|
||||
@@ -40,7 +40,6 @@ interface AgentsPageViewProps {
|
||||
chatList: TypesGen.Chat[];
|
||||
catalogModelOptions: readonly ModelSelectorOption[];
|
||||
modelConfigs: readonly TypesGen.ChatModelConfig[];
|
||||
logoUrl: string;
|
||||
handleNewAgent: () => void;
|
||||
isCreating: boolean;
|
||||
isArchiving: boolean;
|
||||
@@ -81,7 +80,6 @@ export const AgentsPageView: FC<AgentsPageViewProps> = ({
|
||||
chatList,
|
||||
catalogModelOptions,
|
||||
modelConfigs,
|
||||
logoUrl,
|
||||
handleNewAgent,
|
||||
isCreating,
|
||||
isArchiving,
|
||||
@@ -174,7 +172,6 @@ export const AgentsPageView: FC<AgentsPageViewProps> = ({
|
||||
chatErrorReasons={sidebarChatErrorReasons}
|
||||
modelOptions={catalogModelOptions}
|
||||
modelConfigs={modelConfigs}
|
||||
logoUrl={logoUrl}
|
||||
onArchiveAgent={requestArchiveAgent}
|
||||
onUnarchiveAgent={requestUnarchiveAgent}
|
||||
onArchiveAndDeleteWorkspace={requestArchiveAndDeleteWorkspace}
|
||||
|
||||
@@ -27,12 +27,10 @@ import {
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "#/components/DropdownMenu/DropdownMenu";
|
||||
import { ExternalImage } from "#/components/ExternalImage/ExternalImage";
|
||||
import { FeatureStageBadge } from "#/components/FeatureStageBadge/FeatureStageBadge";
|
||||
import { CoderIcon } from "#/components/Icons/CoderIcon";
|
||||
import { ProductLogo } from "#/components/Icons/ProductLogo";
|
||||
import { Spinner } from "#/components/Spinner/Spinner";
|
||||
import { useWebpushNotifications } from "#/contexts/useWebpushNotifications";
|
||||
import { useDashboard } from "#/modules/dashboard/useDashboard";
|
||||
import type { AgentsOutletContext } from "../AgentsPageView";
|
||||
import { getChimeEnabled, setChimeEnabled } from "../utils/chime";
|
||||
|
||||
@@ -57,8 +55,6 @@ export const AgentPageHeader: FC<AgentPageHeaderProps> = ({
|
||||
}) => {
|
||||
const { isSidebarCollapsed, onExpandSidebar } =
|
||||
useOutletContext<AgentsOutletContext>();
|
||||
const { appearance } = useDashboard();
|
||||
const logoUrl = appearance.logo_url;
|
||||
const location = useLocation();
|
||||
|
||||
const [internalChimeEnabled, setInternalChimeEnabled] =
|
||||
@@ -135,11 +131,7 @@ export const AgentPageHeader: FC<AgentPageHeaderProps> = ({
|
||||
) : (
|
||||
<div className="inline-flex shrink-0 items-center gap-2 md:hidden">
|
||||
<NavLink to="/workspaces" className="inline-flex">
|
||||
{logoUrl ? (
|
||||
<ExternalImage className="h-6" src={logoUrl} alt="Logo" />
|
||||
) : (
|
||||
<CoderIcon className="h-6 w-6 fill-content-primary" />
|
||||
)}
|
||||
<ProductLogo className="size-6" />
|
||||
</NavLink>
|
||||
<FeatureStageBadge contentType="beta" size="sm" />
|
||||
</div>
|
||||
|
||||
@@ -88,9 +88,8 @@ import {
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from "#/components/DropdownMenu/DropdownMenu";
|
||||
import { ExternalImage } from "#/components/ExternalImage/ExternalImage";
|
||||
import { FeatureStageBadge } from "#/components/FeatureStageBadge/FeatureStageBadge";
|
||||
import { CoderIcon } from "#/components/Icons/CoderIcon";
|
||||
import { ProductLogo } from "#/components/Icons/ProductLogo";
|
||||
import { ScrollArea } from "#/components/ScrollArea/ScrollArea";
|
||||
import { Skeleton } from "#/components/Skeleton/Skeleton";
|
||||
import { Spinner } from "#/components/Spinner/Spinner";
|
||||
@@ -164,7 +163,6 @@ interface AgentsSidebarProps {
|
||||
chatErrorReasons: Record<string, string>;
|
||||
modelOptions: readonly ModelSelectorOption[];
|
||||
modelConfigs: readonly ChatModelConfig[];
|
||||
logoUrl?: string;
|
||||
onArchiveAgent: (chatId: string) => void;
|
||||
onUnarchiveAgent: (chatId: string) => void;
|
||||
onArchiveAndDeleteWorkspace: (chatId: string, workspaceId: string) => void;
|
||||
@@ -822,7 +820,6 @@ export const AgentsSidebar: FC<AgentsSidebarProps> = (props) => {
|
||||
chatErrorReasons,
|
||||
modelOptions,
|
||||
modelConfigs,
|
||||
logoUrl,
|
||||
onArchiveAgent,
|
||||
onUnarchiveAgent,
|
||||
onArchiveAndDeleteWorkspace,
|
||||
@@ -1090,11 +1087,7 @@ export const AgentsSidebar: FC<AgentsSidebarProps> = (props) => {
|
||||
<div className="mb-2.5 flex items-center justify-between">
|
||||
<div className="flex items-center gap-2">
|
||||
<NavLink to="/workspaces" className="inline-flex">
|
||||
{logoUrl ? (
|
||||
<ExternalImage className="h-6" src={logoUrl} alt="Logo" />
|
||||
) : (
|
||||
<CoderIcon className="h-6 w-6 fill-content-primary" />
|
||||
)}
|
||||
<ProductLogo className="size-6" />
|
||||
</NavLink>
|
||||
<FeatureStageBadge contentType="beta" size="sm" />
|
||||
</div>
|
||||
|
||||
@@ -102,7 +102,7 @@ export const SpendDrillInView: FC<SpendDrillInViewProps> = ({
|
||||
{backButton}
|
||||
{header}
|
||||
</div>
|
||||
<div className="flex flex-wrap items-center gap-3 rounded-lg border border-border-default bg-surface-secondary px-4 py-3">
|
||||
<div className="flex items-center justify-between rounded-lg bg-surface-secondary px-4 py-3">
|
||||
<AvatarData
|
||||
title={selectedUser.name || selectedUser.username}
|
||||
subtitle={`@${selectedUser.username}`}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { type FC, useState } from "react";
|
||||
import { useLocation } from "react-router";
|
||||
import type { AuthMethods, BuildInfoResponse } from "#/api/typesGenerated";
|
||||
import { Button } from "#/components/Button/Button";
|
||||
import { CustomLogo } from "#/components/CustomLogo/CustomLogo";
|
||||
import { ProductLogo } from "#/components/Icons/ProductLogo";
|
||||
import { Loader } from "#/components/Loader/Loader";
|
||||
import { SignInForm } from "./SignInForm";
|
||||
import { TermsOfServiceLink } from "./TermsOfServiceLink";
|
||||
@@ -37,7 +37,7 @@ export const LoginPageView: FC<LoginPageViewProps> = ({
|
||||
return (
|
||||
<div className="p-6 flex items-center justify-center min-h-full text-center">
|
||||
<div className="w-full max-w-xs flex flex-col items-center gap-4">
|
||||
<CustomLogo />
|
||||
<ProductLogo />
|
||||
{isLoading ? (
|
||||
<Loader />
|
||||
) : tosAcceptanceRequired ? (
|
||||
|
||||
@@ -8,7 +8,7 @@ import { isApiValidationError } from "#/api/errors";
|
||||
import { changePasswordWithOTP } from "#/api/queries/users";
|
||||
import { ErrorAlert } from "#/components/Alert/ErrorAlert";
|
||||
import { Button } from "#/components/Button/Button";
|
||||
import { CustomLogo } from "#/components/CustomLogo/CustomLogo";
|
||||
import { ProductLogo } from "#/components/Icons/ProductLogo";
|
||||
import { Input } from "#/components/Input/Input";
|
||||
import { Label } from "#/components/Label/Label";
|
||||
import { Spinner } from "#/components/Spinner/Spinner";
|
||||
@@ -77,7 +77,7 @@ const ChangePasswordPage: FC<ChangePasswordChangeProps> = ({ redirect }) => {
|
||||
<div className="p-6 flex items-center justify-center flex-col min-h-full text-center">
|
||||
<main className="w-full max-w-xs flex flex-col items-center">
|
||||
<div className="mb-10">
|
||||
<CustomLogo />
|
||||
<ProductLogo />
|
||||
</div>
|
||||
<h1 className="m-0 mb-6 text-xl font-semibold leading-7">
|
||||
Choose a new password
|
||||
|
||||
@@ -6,7 +6,7 @@ import * as Yup from "yup";
|
||||
import { requestOneTimePassword } from "#/api/queries/users";
|
||||
import { ErrorAlert } from "#/components/Alert/ErrorAlert";
|
||||
import { Button } from "#/components/Button/Button";
|
||||
import { CustomLogo } from "#/components/CustomLogo/CustomLogo";
|
||||
import { ProductLogo } from "#/components/Icons/ProductLogo";
|
||||
import { Input } from "#/components/Input/Input";
|
||||
import { Label } from "#/components/Label/Label";
|
||||
import { Spinner } from "#/components/Spinner/Spinner";
|
||||
@@ -26,7 +26,7 @@ const RequestOTPPage: FC = () => {
|
||||
|
||||
<main className="p-6 flex items-center justify-center flex-col min-h-full text-center">
|
||||
<div>
|
||||
<CustomLogo />
|
||||
<ProductLogo />
|
||||
</div>
|
||||
{requestOTPMutation.isSuccess ? (
|
||||
<RequestOTPSuccess
|
||||
|
||||
@@ -9,7 +9,7 @@ import { Button } from "#/components/Button/Button";
|
||||
import { Checkbox } from "#/components/Checkbox/Checkbox";
|
||||
import { ExternalImage } from "#/components/ExternalImage/ExternalImage";
|
||||
import { FormField } from "#/components/FormField/FormField";
|
||||
import { CoderIcon } from "#/components/Icons/CoderIcon";
|
||||
import { ProductLogo } from "#/components/Icons/ProductLogo";
|
||||
import { Label } from "#/components/Label/Label";
|
||||
import { PasswordField } from "#/components/PasswordField/PasswordField";
|
||||
import {
|
||||
@@ -192,7 +192,7 @@ export const SetupPageView: FC<SetupPageViewProps> = ({
|
||||
<div className="grow basis-0 min-h-screen flex justify-center items-center py-12">
|
||||
<div className="flex flex-col w-full max-w-[500px] px-4">
|
||||
<header className="mb-8">
|
||||
<CoderIcon className="w-12 h-12 text-content-primary" />
|
||||
<ProductLogo />
|
||||
<h1 className="text-2xl font-normal mt-4 mb-0">
|
||||
Welcome to <strong>Coder</strong>
|
||||
</h1>
|
||||
|
||||
@@ -210,7 +210,6 @@ export default defineConfig({
|
||||
"@mui/material/styles",
|
||||
"@mui/system/createTheme",
|
||||
"@mui/system/useTheme",
|
||||
"@mui/x-tree-view",
|
||||
// Discovered at runtime without this entry, triggering
|
||||
// a mid-run dep re-optimization that breaks imports.
|
||||
"@tanstack/react-query-devtools",
|
||||
|
||||
Reference in New Issue
Block a user