diff --git a/plugins/backstage-plugin-coder/src/components/A11yInfoCard/A11yInfoCard.tsx b/plugins/backstage-plugin-coder/src/components/A11yInfoCard/A11yInfoCard.tsx index 4c5959b9..fb18a4c5 100644 --- a/plugins/backstage-plugin-coder/src/components/A11yInfoCard/A11yInfoCard.tsx +++ b/plugins/backstage-plugin-coder/src/components/A11yInfoCard/A11yInfoCard.tsx @@ -6,6 +6,7 @@ */ import React, { type HTMLAttributes, type ReactNode, forwardRef } from 'react'; import { makeStyles } from '@material-ui/core'; +import { scaleCssUnit } from '../../utils/styling'; export type A11yInfoCardProps = Readonly< HTMLAttributes & { @@ -23,10 +24,7 @@ const useStyles = makeStyles(theme => ({ }, headerContent: { - // Ideally wouldn't be using hard-coded font sizes, but couldn't figure out - // how to use the theme.typography property, especially since not all - // sub-properties have font sizes defined - fontSize: '1.5rem', + fontSize: scaleCssUnit(theme.typography.body1.fontSize, 1.5), color: theme.palette.text.primary, fontWeight: 700, borderBottom: `1px solid ${theme.palette.divider}`, diff --git a/plugins/backstage-plugin-coder/src/components/CoderAuthForm/CoderAuthForm.tsx b/plugins/backstage-plugin-coder/src/components/CoderAuthForm/CoderAuthForm.tsx index 638a1a75..9c67f584 100644 --- a/plugins/backstage-plugin-coder/src/components/CoderAuthForm/CoderAuthForm.tsx +++ b/plugins/backstage-plugin-coder/src/components/CoderAuthForm/CoderAuthForm.tsx @@ -45,6 +45,9 @@ export const CoderAuthForm = ({ descriptionId }: CoderAuthFormProps) => { return ; } + // It shouldn't be possible for these branches to run, because parent + // code should show main content instead of the form when the user is + // authenticated. Still adding them for extra assurance case 'authenticated': case 'distrustedWithGracePeriod': { return ; diff --git a/plugins/backstage-plugin-coder/src/components/CoderAuthForm/CoderAuthSuccessStatus.tsx b/plugins/backstage-plugin-coder/src/components/CoderAuthForm/CoderAuthSuccessStatus.tsx index d2c71513..1c3877c8 100644 --- a/plugins/backstage-plugin-coder/src/components/CoderAuthForm/CoderAuthSuccessStatus.tsx +++ b/plugins/backstage-plugin-coder/src/components/CoderAuthForm/CoderAuthSuccessStatus.tsx @@ -26,7 +26,7 @@ const useStyles = makeStyles(theme => ({ marginLeft: 'auto', marginRight: 'auto', color: theme.palette.text.primary, - fontSize: '1rem', + fontSize: theme.typography.body1.fontSize, }, statusArea: { @@ -35,13 +35,9 @@ const useStyles = makeStyles(theme => ({ alignItems: 'center', }, - logo: { - // - }, - text: { textAlign: 'center', - lineHeight: '1rem', + lineHeight: theme.typography.body1.fontSize, }, })); @@ -51,8 +47,8 @@ export function CoderAuthSuccessStatus() { return (
- -

You are fully authenticated with Coder!

+ +

You are fully authenticated with Coder.

diff --git a/plugins/backstage-plugin-coder/src/components/CoderAuthFormDialog/CoderAuthFormDialog.tsx b/plugins/backstage-plugin-coder/src/components/CoderAuthFormDialog/CoderAuthFormDialog.tsx index 7c39fc95..cb3d501a 100644 --- a/plugins/backstage-plugin-coder/src/components/CoderAuthFormDialog/CoderAuthFormDialog.tsx +++ b/plugins/backstage-plugin-coder/src/components/CoderAuthFormDialog/CoderAuthFormDialog.tsx @@ -7,6 +7,7 @@ import DialogContent from '@material-ui/core/DialogContent'; import DialogTitle from '@material-ui/core/DialogTitle'; import DialogActions from '@material-ui/core/DialogActions'; import { CoderAuthForm } from '../CoderAuthForm/CoderAuthForm'; +import { scaleCssUnit } from '../../utils/styling'; const useStyles = makeStyles(theme => ({ trigger: { @@ -41,7 +42,7 @@ const useStyles = makeStyles(theme => ({ }, dialogTitle: { - fontSize: '24px', + fontSize: scaleCssUnit(theme.typography.body1.fontSize, 1.5), borderBottom: `${theme.palette.divider} 1px solid`, padding: `${theme.spacing(1)}px ${theme.spacing(3)}px`, }, @@ -60,6 +61,10 @@ const useStyles = makeStyles(theme => ({ }, closeButton: { + // MUI's typography object doesn't expose any letter tracking values, even + // though you need them to make sure that all-caps text doesn't bunch up. + // Even if the text of the button changes, the styles might look slightly + // wonky, but they won't cause any obvious readability/styling issues letterSpacing: '0.05em', padding: `${theme.spacing(0.5)}px ${theme.spacing(1)}px`, color: theme.palette.primary.main, diff --git a/plugins/backstage-plugin-coder/src/components/CoderWorkspacesCard/CreateWorkspaceLink.tsx b/plugins/backstage-plugin-coder/src/components/CoderWorkspacesCard/CreateWorkspaceLink.tsx index a0a1ab84..7a279b8e 100644 --- a/plugins/backstage-plugin-coder/src/components/CoderWorkspacesCard/CreateWorkspaceLink.tsx +++ b/plugins/backstage-plugin-coder/src/components/CoderWorkspacesCard/CreateWorkspaceLink.tsx @@ -29,7 +29,7 @@ const useStyles = makeStyles(theme => { justifyContent: 'center', alignItems: 'center', backgroundColor: 'inherit', - borderRadius: '9999px', + borderRadius: theme.shape.borderRadius, lineHeight: 1, color: canCreateWorkspace ? theme.palette.text.primary diff --git a/plugins/backstage-plugin-coder/src/components/CoderWorkspacesCard/ExtraActionsButton.tsx b/plugins/backstage-plugin-coder/src/components/CoderWorkspacesCard/ExtraActionsButton.tsx index a6ccfb19..b62be388 100644 --- a/plugins/backstage-plugin-coder/src/components/CoderWorkspacesCard/ExtraActionsButton.tsx +++ b/plugins/backstage-plugin-coder/src/components/CoderWorkspacesCard/ExtraActionsButton.tsx @@ -33,7 +33,7 @@ const useStyles = makeStyles(theme => { width: theme.spacing(4) + padding, height: theme.spacing(4) + padding, border: 'none', - borderRadius: '9999px', + borderRadius: theme.shape.borderRadius, backgroundColor: 'inherit', lineHeight: 1, diff --git a/plugins/backstage-plugin-coder/src/components/CoderWorkspacesCard/HeaderRow.tsx b/plugins/backstage-plugin-coder/src/components/CoderWorkspacesCard/HeaderRow.tsx index b96f2361..f1ffcbb6 100644 --- a/plugins/backstage-plugin-coder/src/components/CoderWorkspacesCard/HeaderRow.tsx +++ b/plugins/backstage-plugin-coder/src/components/CoderWorkspacesCard/HeaderRow.tsx @@ -2,6 +2,7 @@ import React, { HTMLAttributes, ReactNode } from 'react'; import { type Theme, makeStyles } from '@material-ui/core'; import { useWorkspacesCardContext } from './Root'; import type { HtmlHeader } from '../../typesConstants'; +import { scaleCssUnit } from '../../utils/styling'; type StyleKey = 'root' | 'header' | 'hgroup' | 'subheader'; const useStyles = makeStyles(theme => ({ @@ -18,14 +19,16 @@ const useStyles = makeStyles(theme => ({ }, header: { - fontSize: '1.5rem', + // Setting line height solid (when leading and font size are equal) to make + // it easier for header and subtitle to sit next to each other lineHeight: 1, + fontSize: scaleCssUnit(theme.typography.body1.fontSize, 1.5), margin: 0, }, subheader: { margin: '0', - fontSize: '0.875rem', + fontSize: scaleCssUnit(theme.typography.body1.fontSize, 0.875), fontWeight: 400, color: theme.palette.text.secondary, paddingTop: theme.spacing(0.5), diff --git a/plugins/backstage-plugin-coder/src/components/CoderWorkspacesCard/Placeholder.tsx b/plugins/backstage-plugin-coder/src/components/CoderWorkspacesCard/Placeholder.tsx index ac4f44fe..9973df2e 100644 --- a/plugins/backstage-plugin-coder/src/components/CoderWorkspacesCard/Placeholder.tsx +++ b/plugins/backstage-plugin-coder/src/components/CoderWorkspacesCard/Placeholder.tsx @@ -11,6 +11,7 @@ import { useWorkspacesCardContext } from './Root'; import { makeStyles } from '@material-ui/core'; import { CoderLogo } from '../CoderLogo'; import { VisuallyHidden } from '../VisuallyHidden'; +import { scaleCssUnit } from '../../utils/styling'; const usePlaceholderStyles = makeStyles(theme => ({ root: { @@ -24,7 +25,7 @@ const usePlaceholderStyles = makeStyles(theme => ({ textAlign: 'center', padding: `0 ${theme.spacing(2.5)}px`, fontWeight: 400, - fontSize: '1.125rem', + fontSize: scaleCssUnit(theme.typography.body1.fontSize, 1.125), color: theme.palette.text.secondary, lineHeight: 1.1, }, diff --git a/plugins/backstage-plugin-coder/src/components/CoderWorkspacesCard/SearchBox.tsx b/plugins/backstage-plugin-coder/src/components/CoderWorkspacesCard/SearchBox.tsx index d6f17b07..de7b3385 100644 --- a/plugins/backstage-plugin-coder/src/components/CoderWorkspacesCard/SearchBox.tsx +++ b/plugins/backstage-plugin-coder/src/components/CoderWorkspacesCard/SearchBox.tsx @@ -14,6 +14,7 @@ import { Theme, makeStyles } from '@material-ui/core'; import { useWorkspacesCardContext } from './Root'; import SearchIcon from '@material-ui/icons/Search'; import CloseIcon from '@material-ui/icons/Close'; +import { CUSTOM_FOCUS_COLOR } from '../../utils/styling'; const LABEL_TEXT = 'Search your Coder workspaces'; const SEARCH_DEBOUNCE_MS = 400; @@ -50,7 +51,7 @@ const useStyles = makeStyles(theme => ({ }, '&:focus-within': { - boxShadow: '0 0 0 1px hsl(213deg, 94%, 68%)', + boxShadow: `0 0 0 1px ${CUSTOM_FOCUS_COLOR}`, }, // Makes it so that the container doesn't have visible focus while you're @@ -93,7 +94,7 @@ const useStyles = makeStyles(theme => ({ cursor: 'pointer', '&:focus': { - boxShadow: '0 0 0 1px hsl(213deg, 94%, 68%)', + boxShadow: `0 0 0 1px ${CUSTOM_FOCUS_COLOR}`, }, }), })); diff --git a/plugins/backstage-plugin-coder/src/components/CoderWorkspacesCard/WorkspacesListIcon.tsx b/plugins/backstage-plugin-coder/src/components/CoderWorkspacesCard/WorkspacesListIcon.tsx index 079189a9..6da0d66d 100644 --- a/plugins/backstage-plugin-coder/src/components/CoderWorkspacesCard/WorkspacesListIcon.tsx +++ b/plugins/backstage-plugin-coder/src/components/CoderWorkspacesCard/WorkspacesListIcon.tsx @@ -1,6 +1,7 @@ import React, { ForwardedRef, HTMLAttributes, useState } from 'react'; import { useUrlSync } from '../../hooks/useUrlSync'; import { Theme, makeStyles } from '@material-ui/core'; +import { scaleCssUnit } from '../../utils/styling'; type WorkspaceListIconProps = Readonly< Omit, 'children' | 'aria-hidden'> & { @@ -21,7 +22,7 @@ const useStyles = makeStyles(theme => ({ root: { width: theme.spacing(2.5), height: theme.spacing(2.5), - fontSize: '0.625rem', + fontSize: scaleCssUnit(theme.typography.body1.fontSize, 0.625), backgroundColor: theme.palette.background.default, borderRadius: '9999px', display: 'flex', diff --git a/plugins/backstage-plugin-coder/src/components/CoderWorkspacesCard/WorkspacesListItem.tsx b/plugins/backstage-plugin-coder/src/components/CoderWorkspacesCard/WorkspacesListItem.tsx index a5a588ae..ba495bc1 100644 --- a/plugins/backstage-plugin-coder/src/components/CoderWorkspacesCard/WorkspacesListItem.tsx +++ b/plugins/backstage-plugin-coder/src/components/CoderWorkspacesCard/WorkspacesListItem.tsx @@ -82,7 +82,7 @@ const useStyles = makeStyles(theme => ({ alignItems: 'center', gap: theme.spacing(1), color: theme.palette.text.secondary, - fontSize: '16px', + fontSize: theme.typography.body1.fontSize ?? '1rem', }, onlineStatusLight: ({ isAvailable }) => ({ diff --git a/plugins/backstage-plugin-coder/src/components/Disclosure/Disclosure.tsx b/plugins/backstage-plugin-coder/src/components/Disclosure/Disclosure.tsx index c53eca54..40d1765c 100644 --- a/plugins/backstage-plugin-coder/src/components/Disclosure/Disclosure.tsx +++ b/plugins/backstage-plugin-coder/src/components/Disclosure/Disclosure.tsx @@ -1,13 +1,14 @@ import React, { type HTMLAttributes, type ReactNode, useState } from 'react'; import { useId } from '../../hooks/hookPolyfills'; import { makeStyles } from '@material-ui/core'; +import { scaleCssUnit } from '../../utils/styling'; const useStyles = makeStyles(theme => ({ disclosureTriangle: { display: 'inline-block', textAlign: 'right', width: theme.spacing(2.25), - fontSize: '0.7rem', + fontSize: scaleCssUnit(theme.typography.body1.fontSize, 0.7), }, disclosureBody: { diff --git a/plugins/backstage-plugin-coder/src/utils/styling.ts b/plugins/backstage-plugin-coder/src/utils/styling.ts new file mode 100644 index 00000000..dad9f866 --- /dev/null +++ b/plugins/backstage-plugin-coder/src/utils/styling.ts @@ -0,0 +1,37 @@ +/** + * A custom focus color chosen to look close to a system default, while + * remaining visible in dark and light themes. The focus values from Backstage's + * theme object are too low-contrast to meet accessibility requirements. + */ +export const CUSTOM_FOCUS_COLOR = 'hsl(213deg, 94%, 68%)'; + +export function scaleCssUnit( + baseSize: string | number | undefined, + scale: number, +): string { + if (!Number.isFinite(scale)) { + return '1rem'; + } + + if (baseSize === undefined) { + return `${scale}rem`; + } + + if (typeof baseSize === 'number') { + if (!Number.isFinite(baseSize)) { + return `${scale}rem`; + } + + return `${baseSize * scale}px`; + } + + const sizeRe = /^\s*(?\d+(?:\.\d+))?s*(?px|r?em)\s*$/i; + const { value, unit } = sizeRe.exec(baseSize)?.groups ?? {}; + const numValue = Number(value); + + if (Number.isNaN(numValue) || unit === undefined) { + return `${scale}rem`; + } + + return `${scale * numValue}${unit}`; +}