diff --git a/.gitignore b/.gitignore index f94151d621..88850ed504 100644 --- a/.gitignore +++ b/.gitignore @@ -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/* diff --git a/site/src/components/Avatar/AvatarData.tsx b/site/src/components/Avatar/AvatarData.tsx index 702ecfc69a..7e2515c934 100644 --- a/site/src/components/Avatar/AvatarData.tsx +++ b/site/src/components/Avatar/AvatarData.tsx @@ -35,10 +35,10 @@ export const AvatarData: FC = ({ } return ( -
+
{avatar} -
+
{title} diff --git a/site/src/components/CustomLogo/CustomLogo.tsx b/site/src/components/CustomLogo/CustomLogo.tsx deleted file mode 100644 index c0629f10fd..0000000000 --- a/site/src/components/CustomLogo/CustomLogo.tsx +++ /dev/null @@ -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 ? ( - {applicationName} { - e.currentTarget.style.display = "none"; - }} - onLoad={(e) => { - e.currentTarget.style.display = "inline"; - }} - className={cn("max-w-[200px] application-logo", className)} - /> - ) : ( - - ); -}; diff --git a/site/src/components/ErrorBoundary/GlobalErrorBoundary.tsx b/site/src/components/ErrorBoundary/GlobalErrorBoundary.tsx index 8188053322..36e044e9ce 100644 --- a/site/src/components/ErrorBoundary/GlobalErrorBoundary.tsx +++ b/site/src/components/ErrorBoundary/GlobalErrorBoundary.tsx @@ -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 = ({
- +

{errorPageTitle}

diff --git a/site/src/components/Icons/CoderIcon.tsx b/site/src/components/Icons/CoderIcon.tsx deleted file mode 100644 index 1bd1527126..0000000000 --- a/site/src/components/Icons/CoderIcon.tsx +++ /dev/null @@ -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> = ({ - className, - ...props -}) => ( - - Coder logo - - -); diff --git a/site/src/components/Icons/ProductLogo.tsx b/site/src/components/Icons/ProductLogo.tsx new file mode 100644 index 0000000000..e370151d61 --- /dev/null +++ b/site/src/components/Icons/ProductLogo.tsx @@ -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 ? ( + { + e.currentTarget.style.display = "none"; + }} + onLoad={(e) => { + e.currentTarget.style.display = "inline"; + }} + className={cn("h-12 max-w-[200px] application-logo", className)} + /> + ) : ( + + ); +}; + +const CoderLogo: FC> = ({ + className, + ...props +}) => ( + + Coder logo + + +); diff --git a/site/src/components/PaginationWidget/PaginationContainer.mocks.ts b/site/src/components/PaginationWidget/PaginationContainer.mocks.ts index 7466529af5..bccf0371e3 100644 --- a/site/src/components/PaginationWidget/PaginationContainer.mocks.ts +++ b/site/src/components/PaginationWidget/PaginationContainer.mocks.ts @@ -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; diff --git a/site/src/components/PaginationWidget/PaginationContainer.tsx b/site/src/components/PaginationWidget/PaginationContainer.tsx index ce43d98e47..9544484811 100644 --- a/site/src/components/PaginationWidget/PaginationContainer.tsx +++ b/site/src/components/PaginationWidget/PaginationContainer.tsx @@ -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 = PaginationResultInfo & { isPlaceholderData: boolean; + data?: Data; }; type PaginationProps = HTMLAttributes & { diff --git a/site/src/components/Welcome/Welcome.tsx b/site/src/components/Welcome/Welcome.tsx index ea5f8ca834..2a4ff3ca90 100644 --- a/site/src/components/Welcome/Welcome.tsx +++ b/site/src/components/Welcome/Welcome.tsx @@ -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 = ({ children, className }) => { return (
- +

diff --git a/site/src/modules/dashboard/Navbar/Navbar.tsx b/site/src/modules/dashboard/Navbar/Navbar.tsx index 34755375c6..48e1cadfc5 100644 --- a/site/src/modules/dashboard/Navbar/Navbar.tsx +++ b/site/src/modules/dashboard/Navbar/Navbar.tsx @@ -38,7 +38,6 @@ export const Navbar: FC = () => { return ( = ({ user, - logo_url, buildInfo, supportLinks, onSignOut, @@ -83,11 +80,7 @@ export const NavbarView: FC = ({ }} > - {logo_url ? ( - - ) : ( - - )} + { -
+
diff --git a/site/src/modules/permissions/RequirePermission.tsx b/site/src/modules/permissions/RequirePermission.tsx index d476464efd..6096ae00a1 100644 --- a/site/src/modules/permissions/RequirePermission.tsx +++ b/site/src/modules/permissions/RequirePermission.tsx @@ -23,7 +23,7 @@ export const RequirePermission: FC = ({ }) => { if (!isFeatureVisible) { return ( - + diff --git a/site/src/modules/tasks/TasksSidebar/TasksSidebar.tsx b/site/src/modules/tasks/TasksSidebar/TasksSidebar.tsx index 68096455d6..4d9821a646 100644 --- a/site/src/modules/tasks/TasksSidebar/TasksSidebar.tsx +++ b/site/src/modules/tasks/TasksSidebar/TasksSidebar.tsx @@ -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 = () => {
{!isCollapsed && ( - + + + Navigate to tasks + )} @@ -106,10 +99,10 @@ export const TasksSidebar: FC = () => { asChild className={cn({ "[&_svg]:p-0": isCollapsed })} > - + New Task{" "} - + @@ -233,7 +226,7 @@ const TaskSidebarMenuItem: FC = ({ task }) => { }, )} > - = ({ task }) => { - + { 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} diff --git a/site/src/pages/AgentsPage/AgentsPageView.stories.tsx b/site/src/pages/AgentsPage/AgentsPageView.stories.tsx index cc4694ae26..ccdbfeb726 100644 --- a/site/src/pages/AgentsPage/AgentsPageView.stories.tsx +++ b/site/src/pages/AgentsPage/AgentsPageView.stories.tsx @@ -207,7 +207,6 @@ const defaultArgs: ComponentProps = { chatList: [], catalogModelOptions: defaultModelOptions, modelConfigs: defaultModelConfigs, - logoUrl: "", handleNewAgent: fn(), isCreating: false, isArchiving: false, diff --git a/site/src/pages/AgentsPage/AgentsPageView.tsx b/site/src/pages/AgentsPage/AgentsPageView.tsx index 622e8641c7..f64967455f 100644 --- a/site/src/pages/AgentsPage/AgentsPageView.tsx +++ b/site/src/pages/AgentsPage/AgentsPageView.tsx @@ -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 = ({ chatList, catalogModelOptions, modelConfigs, - logoUrl, handleNewAgent, isCreating, isArchiving, @@ -174,7 +172,6 @@ export const AgentsPageView: FC = ({ chatErrorReasons={sidebarChatErrorReasons} modelOptions={catalogModelOptions} modelConfigs={modelConfigs} - logoUrl={logoUrl} onArchiveAgent={requestArchiveAgent} onUnarchiveAgent={requestUnarchiveAgent} onArchiveAndDeleteWorkspace={requestArchiveAndDeleteWorkspace} diff --git a/site/src/pages/AgentsPage/components/AgentPageHeader.tsx b/site/src/pages/AgentsPage/components/AgentPageHeader.tsx index a36b743353..d4b1d577b8 100644 --- a/site/src/pages/AgentsPage/components/AgentPageHeader.tsx +++ b/site/src/pages/AgentsPage/components/AgentPageHeader.tsx @@ -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 = ({ }) => { const { isSidebarCollapsed, onExpandSidebar } = useOutletContext(); - const { appearance } = useDashboard(); - const logoUrl = appearance.logo_url; const location = useLocation(); const [internalChimeEnabled, setInternalChimeEnabled] = @@ -135,11 +131,7 @@ export const AgentPageHeader: FC = ({ ) : (
- {logoUrl ? ( - - ) : ( - - )} +
diff --git a/site/src/pages/AgentsPage/components/Sidebar/AgentsSidebar.tsx b/site/src/pages/AgentsPage/components/Sidebar/AgentsSidebar.tsx index 8905babc98..78faff52d2 100644 --- a/site/src/pages/AgentsPage/components/Sidebar/AgentsSidebar.tsx +++ b/site/src/pages/AgentsPage/components/Sidebar/AgentsSidebar.tsx @@ -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; 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 = (props) => { chatErrorReasons, modelOptions, modelConfigs, - logoUrl, onArchiveAgent, onUnarchiveAgent, onArchiveAndDeleteWorkspace, @@ -1090,11 +1087,7 @@ export const AgentsSidebar: FC = (props) => {
- {logoUrl ? ( - - ) : ( - - )} +
diff --git a/site/src/pages/AgentsPage/components/SpendDrillInView.tsx b/site/src/pages/AgentsPage/components/SpendDrillInView.tsx index 2fca900402..79aed263a2 100644 --- a/site/src/pages/AgentsPage/components/SpendDrillInView.tsx +++ b/site/src/pages/AgentsPage/components/SpendDrillInView.tsx @@ -102,7 +102,7 @@ export const SpendDrillInView: FC = ({ {backButton} {header}
-
+
= ({ return (
- + {isLoading ? ( ) : tosAcceptanceRequired ? ( diff --git a/site/src/pages/ResetPasswordPage/ChangePasswordPage.tsx b/site/src/pages/ResetPasswordPage/ChangePasswordPage.tsx index cd0e6aceeb..dc3e9d8597 100644 --- a/site/src/pages/ResetPasswordPage/ChangePasswordPage.tsx +++ b/site/src/pages/ResetPasswordPage/ChangePasswordPage.tsx @@ -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 = ({ redirect }) => {
- +

Choose a new password diff --git a/site/src/pages/ResetPasswordPage/RequestOTPPage.tsx b/site/src/pages/ResetPasswordPage/RequestOTPPage.tsx index d54ddfcb0b..7de2650b35 100644 --- a/site/src/pages/ResetPasswordPage/RequestOTPPage.tsx +++ b/site/src/pages/ResetPasswordPage/RequestOTPPage.tsx @@ -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 = () => {
- +
{requestOTPMutation.isSuccess ? ( = ({
- +

Welcome to Coder

diff --git a/site/vite.config.mts b/site/vite.config.mts index 4a561decca..9c78cafd13 100644 --- a/site/vite.config.mts +++ b/site/vite.config.mts @@ -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",