diff --git a/site/package.json b/site/package.json
index 1573aad5b70c1..56b7969b80a58 100644
--- a/site/package.json
+++ b/site/package.json
@@ -43,7 +43,6 @@
"@emoji-mart/data": "1.2.1",
"@emoji-mart/react": "1.1.1",
"@emotion/cache": "11.14.0",
- "@emotion/css": "11.13.5",
"@emotion/react": "11.14.0",
"@emotion/styled": "11.14.1",
"@fontsource-variable/geist": "5.3.0",
diff --git a/site/pnpm-lock.yaml b/site/pnpm-lock.yaml
index adaad85617e5f..b3c6980da951a 100644
--- a/site/pnpm-lock.yaml
+++ b/site/pnpm-lock.yaml
@@ -50,9 +50,6 @@ importers:
'@emotion/cache':
specifier: 11.14.0
version: 11.14.0
- '@emotion/css':
- specifier: 11.13.5
- version: 11.13.5
'@emotion/react':
specifier: 11.14.0
version: 11.14.0(@types/react@19.2.17)(react@19.2.8)
@@ -774,9 +771,6 @@ packages:
'@emotion/cache@11.14.0':
resolution: {integrity: sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==, tarball: https://registry.npmjs.org/@emotion/cache/-/cache-11.14.0.tgz}
- '@emotion/css@11.13.5':
- resolution: {integrity: sha512-wQdD0Xhkn3Qy2VNcIzbLP9MR8TafI0MJb7BEAXKp+w4+XqErksWR4OXomuDzPsN4InLdGhVe6EYcn2ZIUCpB8w==, tarball: https://registry.npmjs.org/@emotion/css/-/css-11.13.5.tgz}
-
'@emotion/hash@0.9.2':
resolution: {integrity: sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==, tarball: https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz}
@@ -6914,16 +6908,6 @@ snapshots:
'@emotion/weak-memoize': 0.4.0
stylis: 4.2.0
- '@emotion/css@11.13.5':
- dependencies:
- '@emotion/babel-plugin': 11.13.5
- '@emotion/cache': 11.14.0
- '@emotion/serialize': 1.3.3
- '@emotion/sheet': 1.4.0
- '@emotion/utils': 1.4.2
- transitivePeerDependencies:
- - supports-color
-
'@emotion/hash@0.9.2': {}
'@emotion/is-prop-valid@1.4.0':
diff --git a/site/src/components/GitDeviceAuth/GitDeviceAuth.tsx b/site/src/components/GitDeviceAuth/GitDeviceAuth.tsx
index 6f540448d0a51..e1e5bd2035a37 100644
--- a/site/src/components/GitDeviceAuth/GitDeviceAuth.tsx
+++ b/site/src/components/GitDeviceAuth/GitDeviceAuth.tsx
@@ -146,9 +146,9 @@ export const GitDeviceAuth: FC = ({
Then open the link below and paste it:
-
+
= ({
now,
}) => {
const navigate = useNavigate();
+ const lifetimeId = useId();
+ const expiresOnId = useId();
const [expDays, setExpDays] = useState
(1);
const [lifetimeDays, setLifetimeDays] = useState(
@@ -68,16 +77,16 @@ export const CreateTokenForm: FC = ({
- setFormError(undefined))}
autoFocus
- fullWidth
+ className="w-full"
/>
@@ -98,59 +107,69 @@ export const CreateTokenForm: FC = ({
"Please set a token expiration."
)
}
- classes={{ sectionInfo: classNames.sectionInfo }}
+ classes={{ sectionInfo: "min-w-[300px]" }}
>
- {
- void setLifetimeDays(event.target.value);
- }}
- fullWidth
- >
- {filterByMaxTokenLifetime(maxTokenLifetime).map((lt) => (
-
- {lt.label}
-
- ))}
-
+
+ Lifetime{" "}
+
+ *
+
+
+
- {customLifetimeDay.label}
-
-
+
+
+
+
+ {filterByMaxTokenLifetime(maxTokenLifetime).map((lt) => (
+
+ {lt.label}
+
+ ))}
+
+ {customLifetimeDay.label}
+
+
+
+
{lifetimeDays === "custom" && (
- {
- const lt = Math.ceil(
- dayjs(event.target.value).diff(dayjs(), "day", true),
- );
- setExpDays(lt);
- }}
- inputProps={{
- "data-pixel": "ignore",
- min: dayjs().add(1, "day").format("YYYY-MM-DD"),
- max: maxTokenLifetime
- ? dayjs()
- .add(maxTokenLifetime / NANO_HOUR / 24, "day")
- .format("YYYY-MM-DD")
- : undefined,
- required: true,
- }}
- fullWidth
- InputLabelProps={{
- required: true,
- }}
- />
+
+
+ Expires on{" "}
+
+ *
+
+
+ {
+ const lt = Math.ceil(
+ dayjs(event.target.value).diff(dayjs(), "day", true),
+ );
+ setExpDays(lt);
+ }}
+ />
+
)}
@@ -168,9 +187,3 @@ export const CreateTokenForm: FC
= ({
);
};
-
-const classNames = {
- sectionInfo: css`
- min-width: 300px;
- `,
-};
diff --git a/site/src/pages/ExternalAuthPage/ExternalAuthPageView.tsx b/site/src/pages/ExternalAuthPage/ExternalAuthPageView.tsx
index bace48e326419..697983ce98530 100644
--- a/site/src/pages/ExternalAuthPage/ExternalAuthPageView.tsx
+++ b/site/src/pages/ExternalAuthPage/ExternalAuthPageView.tsx
@@ -1,4 +1,3 @@
-import Link from "@mui/material/Link";
import { ExternalLinkIcon, RotateCwIcon } from "lucide-react";
import type { FC, ReactNode } from "react";
import type { ApiErrorResponse } from "#/api/errors";
@@ -6,6 +5,7 @@ import type { ExternalAuth, ExternalAuthDevice } from "#/api/typesGenerated";
import { Alert } from "#/components/Alert/Alert";
import { Avatar } from "#/components/Avatar/Avatar";
import { GitDeviceAuth } from "#/components/GitDeviceAuth/GitDeviceAuth";
+import { Link } from "#/components/Link/Link";
import { SignInLayout } from "#/components/SignInLayout/SignInLayout";
import {
Tooltip,
@@ -56,6 +56,8 @@ const ExternalAuthPageView: FC = ({
href={externalAuth.app_install_url}
target="_blank"
rel="noreferrer"
+ showExternalIcon={false}
+ className="p-0 text-sm font-medium"
>
{installTheApp}
@@ -88,6 +90,8 @@ const ExternalAuthPageView: FC = ({
href={install.account.profile_url}
target="_blank"
rel="noreferrer"
+ showExternalIcon={false}
+ className="p-0 after:hover:content-none"
>
= ({
)}
-
+
{!hasInstallations && externalAuth.app_installable && (
You must {installTheApp} to clone private repositories. Accounts
@@ -122,7 +126,8 @@ const ExternalAuthPageView: FC = ({
href={externalAuth.app_install_url}
target="_blank"
rel="noreferrer"
- className="flex items-center justify-center gap-2 text-base"
+ showExternalIcon={false}
+ className="inline-flex items-center gap-2 p-0 text-base font-medium [&_svg]:size-icon-xs [&_svg]:p-0"
>
{externalAuth.installations.length > 0 ? "Configure" : "Install"}{" "}
@@ -130,8 +135,9 @@ const ExternalAuthPageView: FC = ({
)}
{
onReauthenticate();
}}
diff --git a/site/src/pages/OrganizationSettingsPage/CreateOrganizationPageView.tsx b/site/src/pages/OrganizationSettingsPage/CreateOrganizationPageView.tsx
index 4b1bfedf21967..69980a654550c 100644
--- a/site/src/pages/OrganizationSettingsPage/CreateOrganizationPageView.tsx
+++ b/site/src/pages/OrganizationSettingsPage/CreateOrganizationPageView.tsx
@@ -1,4 +1,3 @@
-import TextField from "@mui/material/TextField";
import { useFormik } from "formik";
import { ArrowLeftIcon } from "lucide-react";
import type { FC } from "react";
@@ -9,15 +8,19 @@ import type { CreateOrganizationRequest } from "#/api/typesGenerated";
import { ErrorAlert } from "#/components/Alert/ErrorAlert";
import { Badges, PremiumBadge } from "#/components/Badges/Badges";
import { Button } from "#/components/Button/Button";
+import { FormField } from "#/components/FormField/FormField";
import { IconField } from "#/components/IconField/IconField";
+import { Label } from "#/components/Label/Label";
import { PaywallPremium } from "#/components/Paywall/PaywallPremium";
import { PopoverPaywall } from "#/components/Paywall/PopoverPaywall";
import { Spinner } from "#/components/Spinner/Spinner";
+import { Textarea } from "#/components/Textarea/Textarea";
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from "#/components/Tooltip/Tooltip";
+import { cn } from "#/utils/cn";
import { docs } from "#/utils/docs";
import {
displayNameValidator,
@@ -59,6 +62,11 @@ export const CreateOrganizationPageView: FC<
});
const navigate = useNavigate();
const getFieldHelpers = getFormHelpers(form, error);
+ const descriptionField = getFieldHelpers("description", {
+ maxLength: MAX_DESCRIPTION_CHAR_LIMIT,
+ });
+ const descriptionErrorId = `${descriptionField.id}-error`;
+ const descriptionHelperId = `${descriptionField.id}-helper`;
return (
@@ -130,23 +138,54 @@ export const CreateOrganizationPageView: FC<
disabled={form.isSubmitting}
className="flex flex-col gap-6 w-full border-none"
>
-
-
-
+
+ Description
+
+ {descriptionField.error ? (
+
+ {descriptionField.helperText}
+
+ ) : (
+ descriptionField.helperText && (
+
+ {descriptionField.helperText}
+
+ )
+ )}
+
= ({
const resourceTypes = getUniqueResourceTypes(permissions);
return (
-
+
{permissions.length > 0 ? (
= ({
permissions={permissions.slice(1)}
/>
)}
-
+
);
};
diff --git a/site/src/pages/OrganizationSettingsPage/IdpSyncPage/IdpPillList.tsx b/site/src/pages/OrganizationSettingsPage/IdpSyncPage/IdpPillList.tsx
index 4053056372594..e41ba13712192 100644
--- a/site/src/pages/OrganizationSettingsPage/IdpSyncPage/IdpPillList.tsx
+++ b/site/src/pages/OrganizationSettingsPage/IdpSyncPage/IdpPillList.tsx
@@ -1,4 +1,3 @@
-import Stack from "@mui/material/Stack";
import type { FC } from "react";
import { Pill } from "#/components/Pill/Pill";
import {
@@ -14,7 +13,7 @@ interface PillListProps {
export const IdpPillList: FC = ({ roles }) => {
return (
-
+
{roles.length > 0 ? (
{roles[0]}
@@ -24,7 +23,7 @@ export const IdpPillList: FC = ({ roles }) => {
)}
{roles.length > 1 && }
-
+
);
};
diff --git a/site/src/pages/UserSettingsPage/SecurityPage/SingleSignOnSection.tsx b/site/src/pages/UserSettingsPage/SecurityPage/SingleSignOnSection.tsx
index bd2a50fa9b837..093eb8e7baae9 100644
--- a/site/src/pages/UserSettingsPage/SecurityPage/SingleSignOnSection.tsx
+++ b/site/src/pages/UserSettingsPage/SecurityPage/SingleSignOnSection.tsx
@@ -1,7 +1,5 @@
-import Link from "@mui/material/Link";
-import TextField from "@mui/material/TextField";
import { CircleCheckIcon, KeyIcon } from "lucide-react";
-import { type FC, useState } from "react";
+import { type FC, useId, useState } from "react";
import { useMutation } from "react-query";
import { API } from "#/api/api";
import { getErrorMessage } from "#/api/errors";
@@ -15,11 +13,15 @@ import { Button } from "#/components/Button/Button";
import { ConfirmDialog } from "#/components/Dialog/ConfirmDialog/ConfirmDialog";
import { EmptyState } from "#/components/EmptyState/EmptyState";
import { ExternalImage } from "#/components/ExternalImage/ExternalImage";
+import { Input } from "#/components/Input/Input";
+import { Label } from "#/components/Label/Label";
+import { Link } from "#/components/Link/Link";
import {
SettingsHeader,
SettingsHeaderDescription,
SettingsHeaderTitle,
} from "#/components/SettingsHeader/SettingsHeader";
+import { cn } from "#/utils/cn";
import { docs } from "#/utils/docs";
type LoginTypeConfirmation =
@@ -250,6 +252,12 @@ const ConfirmLoginTypeChangeModal: FC = ({
onConfirm,
}) => {
const [password, setPassword] = useState("");
+ const passwordId = useId();
+ const errorId = useId();
+ const hasError = Boolean(error);
+ const errorMessage = error
+ ? getErrorMessage(error, "Your password is incorrect")
+ : undefined;
const handleConfirm = () => {
onConfirm(password);
@@ -273,26 +281,30 @@ const ConfirmLoginTypeChangeModal: FC = ({
After changing your login type, you will not be able to change it
again. Are you sure you want to proceed and change your login type?
- {
- if (event.key === "Enter") {
- handleConfirm();
- }
- }}
- error={Boolean(error)}
- helperText={
- error
- ? getErrorMessage(error, "Your password is incorrect")
- : undefined
- }
- name="confirm-password"
- id="confirm-password"
- value={password}
- onChange={(e) => setPassword(e.currentTarget.value)}
- label="Confirm your password"
- type="password"
- />
+
+ Confirm your password
+ {
+ if (event.key === "Enter") {
+ handleConfirm();
+ }
+ }}
+ name="confirm-password"
+ id={passwordId}
+ value={password}
+ onChange={(e) => setPassword(e.currentTarget.value)}
+ type="password"
+ aria-invalid={hasError}
+ aria-describedby={hasError ? errorId : undefined}
+ className={cn(hasError && "border-border-destructive")}
+ />
+ {hasError && (
+
+ {errorMessage}
+
+ )}
+
}
/>
diff --git a/site/src/utils/schedule.tsx b/site/src/utils/schedule.tsx
index 0cd1f1081ad56..8c58c4859e12a 100644
--- a/site/src/utils/schedule.tsx
+++ b/site/src/utils/schedule.tsx
@@ -1,4 +1,3 @@
-import Link from "@mui/material/Link";
import cronParser from "cron-parser";
import cronstrue from "cronstrue";
import dayjs, { type Dayjs } from "dayjs";
@@ -10,6 +9,7 @@ import type { ReactNode } from "react";
import { Link as RouterLink } from "react-router";
import type { Template, Workspace } from "#/api/typesGenerated";
import { HelpPopoverTitle } from "#/components/HelpPopover/HelpPopover";
+import { Link } from "#/components/Link/Link";
import type { WorkspaceActivityStatus } from "#/modules/workspaces/activity";
import { isWorkspaceOn } from "./workspace";
@@ -140,8 +140,8 @@ export const autostopDisplay = (
{" "}
because this workspace has enabled autostop. You can disable autostop
from this workspace's{" "}
-
- schedule settings
+
+ schedule settings
.