From fb17a77718e6a5e792167c92cb55d02be91095f5 Mon Sep 17 00:00:00 2001 From: Bruno Quaresma Date: Fri, 3 Feb 2023 14:46:32 +0000 Subject: [PATCH 1/3] Refactor auto complete --- site/src/components/Avatar/Avatar.tsx | 7 +- .../UserAutocomplete.stories.tsx | 23 +++++ .../UserAutocomplete/UserAutocomplete.tsx | 92 +++++-------------- .../CreateWorkspacePageView.tsx | 2 - site/src/pages/GroupsPage/GroupPage.tsx | 14 ++- site/src/theme/overrides.ts | 4 +- 6 files changed, 68 insertions(+), 74 deletions(-) create mode 100644 site/src/components/UserAutocomplete/UserAutocomplete.stories.tsx diff --git a/site/src/components/Avatar/Avatar.tsx b/site/src/components/Avatar/Avatar.tsx index f93e2d671d91e..f9937fb0aea36 100644 --- a/site/src/components/Avatar/Avatar.tsx +++ b/site/src/components/Avatar/Avatar.tsx @@ -9,7 +9,7 @@ import { combineClasses } from "util/combineClasses" import { firstLetter } from "./firstLetter" export type AvatarProps = MuiAvatarProps & { - size?: "md" | "xl" + size?: "sm" | "md" | "xl" colorScheme?: "light" | "darken" fitImage?: boolean } @@ -50,6 +50,11 @@ export const AvatarIcon: FC<{ src: string }> = ({ src }) => { const useStyles = makeStyles((theme) => ({ // Size styles + sm: { + width: theme.spacing(3), + height: theme.spacing(3), + fontSize: theme.spacing(1.5), + }, // Just use the default value from theme md: {}, xl: { diff --git a/site/src/components/UserAutocomplete/UserAutocomplete.stories.tsx b/site/src/components/UserAutocomplete/UserAutocomplete.stories.tsx new file mode 100644 index 0000000000000..090c903a512fb --- /dev/null +++ b/site/src/components/UserAutocomplete/UserAutocomplete.stories.tsx @@ -0,0 +1,23 @@ +import { Story } from "@storybook/react" +import { MockUser } from "testHelpers/entities" +import { UserAutocomplete, UserAutocompleteProps } from "./UserAutocomplete" + +export default { + title: "components/UserAutocomplete", + component: UserAutocomplete, +} + +const Template: Story = ( + args: UserAutocompleteProps, +) => + +export const Example = Template.bind({}) +Example.args = { + value: MockUser, + label: "User", +} + +export const NoLabel = Template.bind({}) +NoLabel.args = { + value: MockUser, +} diff --git a/site/src/components/UserAutocomplete/UserAutocomplete.tsx b/site/src/components/UserAutocomplete/UserAutocomplete.tsx index 1f4bf3ef8c79c..cf912f6710db9 100644 --- a/site/src/components/UserAutocomplete/UserAutocomplete.tsx +++ b/site/src/components/UserAutocomplete/UserAutocomplete.tsx @@ -1,5 +1,5 @@ import CircularProgress from "@material-ui/core/CircularProgress" -import { makeStyles, Theme } from "@material-ui/core/styles" +import { makeStyles } from "@material-ui/core/styles" import TextField from "@material-ui/core/TextField" import Autocomplete from "@material-ui/lab/Autocomplete" import { useMachine } from "@xstate/react" @@ -8,29 +8,22 @@ import { Avatar } from "components/Avatar/Avatar" import { AvatarData } from "components/AvatarData/AvatarData" import debounce from "just-debounce-it" import { ChangeEvent, FC, useEffect, useState } from "react" -import { combineClasses } from "util/combineClasses" import { searchUserMachine } from "xServices/users/searchUserXService" export type UserAutocompleteProps = { value: User | null onChange: (user: User | null) => void label?: string - inputMargin?: "none" | "dense" | "normal" - inputStyles?: string className?: string - showAvatar?: boolean } export const UserAutocomplete: FC = ({ value, onChange, - className, label, - inputMargin, - inputStyles, - showAvatar = false, + className, }) => { - const styles = useStyles({ showAvatar }) + const styles = useStyles() const [isAutocompleteOpen, setIsAutocompleteOpen] = useState(false) const [searchState, sendSearch] = useMachine(searchUserMachine) const { searchResults } = searchState.context @@ -53,6 +46,9 @@ export const UserAutocomplete: FC = ({ return ( = ({ src={option.avatar_url} /> )} - options={searchResults} - loading={searchState.matches("searching")} - className={combineClasses([styles.autocomplete, className])} renderInput={(params) => ( {value.username} + startAdornment: value && ( + + {value.username} + ), endAdornment: ( <> @@ -105,6 +100,9 @@ export const UserAutocomplete: FC = ({ {params.InputProps.endAdornment} ), + classes: { + root: styles.inputRoot, + }, }} /> )} @@ -112,54 +110,14 @@ export const UserAutocomplete: FC = ({ ) } -interface styleProps { - showAvatar: boolean -} - -export const useStyles = makeStyles((theme) => { - return { - autocomplete: (props) => ({ - width: "100%", - - "& .MuiFormControl-root": { - width: "100%", - }, - - "& .MuiInputBase-root": { - width: "100%", - // Match button small height - height: props.showAvatar ? 60 : 40, - }, - - "& input": { - fontSize: 16, - padding: `${theme.spacing(0, 0.5, 0, 0.5)} !important`, - }, - }), - } -}) - -export const UserAutocompleteInline: React.FC = ( - props, -) => { - const style = useInlineStyle() - - return -} - -export const useInlineStyle = makeStyles(() => { - return { - inline: { - width: "300px", - - "& .MuiFormControl-root": { - margin: 0, - }, - - "& .MuiInputBase-root": { - // Match button small height - height: 36, - }, +export const useStyles = makeStyles((theme) => ({ + textField: { + "&:not(:has(label))": { + margin: 0, }, - } -}) + }, + inputRoot: { + paddingLeft: `${theme.spacing(1.75)}px !important`, // Same padding left as input + gap: theme.spacing(0.5), + }, +})) diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx index d2b8936bf306f..4eaedcacffd72 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx @@ -215,8 +215,6 @@ export const CreateWorkspacePageView: FC< value={props.owner} onChange={props.setOwner} label={t("ownerLabel")} - inputMargin="dense" - showAvatar /> diff --git a/site/src/pages/GroupsPage/GroupPage.tsx b/site/src/pages/GroupsPage/GroupPage.tsx index 0149bcc71f8b8..80ade4b93b413 100644 --- a/site/src/pages/GroupsPage/GroupPage.tsx +++ b/site/src/pages/GroupsPage/GroupPage.tsx @@ -25,19 +25,21 @@ import { } from "components/PageHeader/PageHeader" import { Stack } from "components/Stack/Stack" import { TableRowMenu } from "components/TableRowMenu/TableRowMenu" -import { UserAutocompleteInline } from "components/UserAutocomplete/UserAutocomplete" +import { UserAutocomplete } from "components/UserAutocomplete/UserAutocomplete" import { useState } from "react" import { Helmet } from "react-helmet-async" import { Link as RouterLink, useNavigate, useParams } from "react-router-dom" import { pageTitle } from "util/page" import { groupMachine } from "xServices/groups/groupXService" import { Maybe } from "components/Conditionals/Maybe" +import { makeStyles } from "@material-ui/core/styles" const AddGroupMember: React.FC<{ isLoading: boolean onSubmit: (user: User, reset: () => void) => void }> = ({ isLoading, onSubmit }) => { const [selectedUser, setSelectedUser] = useState(null) + const styles = useStyles() const resetValues = () => { setSelectedUser(null) @@ -54,7 +56,8 @@ const AddGroupMember: React.FC<{ }} > - { setSelectedUser(newValue) @@ -64,7 +67,6 @@ const AddGroupMember: React.FC<{ } loading={isLoading} > @@ -223,4 +225,10 @@ export const GroupPage: React.FC = () => { ) } +const useStyles = makeStyles(() => ({ + autoComplete: { + width: 300, + }, +})) + export default GroupPage diff --git a/site/src/theme/overrides.ts b/site/src/theme/overrides.ts index 025a5c9bb6daa..561a798065b42 100644 --- a/site/src/theme/overrides.ts +++ b/site/src/theme/overrides.ts @@ -42,7 +42,8 @@ export const getOverrides = ({ MuiButton: { root: { // Prevents a loading button from collapsing! - minHeight: 42, + minHeight: 40, + height: 40, // Same size of input height fontWeight: "normal", fontSize: 16, textTransform: "none", @@ -73,6 +74,7 @@ export const getOverrides = ({ padding: `0 16px`, fontSize: 14, minHeight: 36, + height: 36, borderRadius: borderRadiusSm, }, iconSizeSmall: { From 2c5d7f82b72da184c522ffce2c34a0e378dbf4ad Mon Sep 17 00:00:00 2001 From: Bruno Quaresma Date: Fri, 3 Feb 2023 15:01:45 +0000 Subject: [PATCH 2/3] Fix avatars --- site/src/components/Workspace/Workspace.tsx | 18 +++++------ .../WorkspacesTable/WorkspacesRow.tsx | 32 ++++++------------- site/src/hooks/useClickableTableRow.ts | 5 +++ .../SelectedTemplate.stories.tsx | 5 ++- .../CreateWorkspacePage/SelectedTemplate.tsx | 8 ++++- 5 files changed, 34 insertions(+), 34 deletions(-) diff --git a/site/src/components/Workspace/Workspace.tsx b/site/src/components/Workspace/Workspace.tsx index 75f0dab640647..e3c75a1a5c6fd 100644 --- a/site/src/components/Workspace/Workspace.tsx +++ b/site/src/components/Workspace/Workspace.tsx @@ -92,8 +92,6 @@ export const Workspace: FC> = ({ const styles = useStyles() const navigate = useNavigate() const serverVersion = buildInfo?.version || "" - const hasTemplateIcon = - workspace.template_icon && workspace.template_icon !== "" const buildError = Boolean(workspaceErrors[WorkspaceErrors.BUILD_ERROR]) && ( > = ({ } > - {hasTemplateIcon && ( - - )} + + {workspace.name} +
{workspace.name} diff --git a/site/src/components/WorkspacesTable/WorkspacesRow.tsx b/site/src/components/WorkspacesTable/WorkspacesRow.tsx index dab63c15a4671..2e4185d0ef745 100644 --- a/site/src/components/WorkspacesTable/WorkspacesRow.tsx +++ b/site/src/components/WorkspacesTable/WorkspacesRow.tsx @@ -4,7 +4,6 @@ import TableRow from "@material-ui/core/TableRow" import KeyboardArrowRight from "@material-ui/icons/KeyboardArrowRight" import { AvatarData } from "components/AvatarData/AvatarData" import { WorkspaceStatusBadge } from "components/WorkspaceStatusBadge/WorkspaceStatusBadge" -import { useClickable } from "hooks/useClickable" import { FC } from "react" import { useNavigate, Link as RouterLink } from "react-router-dom" import { getDisplayWorkspaceTemplateName } from "util/workspace" @@ -15,6 +14,7 @@ import { Avatar } from "components/Avatar/Avatar" import { Stack } from "components/Stack/Stack" import TemplateLinkIcon from "@material-ui/icons/OpenInNewOutlined" import Link from "@material-ui/core/Link" +import { useClickableTableRow } from "hooks/useClickableTableRow" export const WorkspacesRow: FC<{ workspace: Workspace @@ -23,20 +23,13 @@ export const WorkspacesRow: FC<{ const styles = useStyles() const navigate = useNavigate() const workspacePageLink = `/@${workspace.owner_name}/${workspace.name}` - const hasTemplateIcon = - workspace.template_icon && workspace.template_icon !== "" const displayTemplateName = getDisplayWorkspaceTemplateName(workspace) - const clickable = useClickable(() => { + const clickable = useClickableTableRow(() => { navigate(workspacePageLink) }) return ( - + - ) + + {workspace.name} + } /> @@ -95,15 +92,6 @@ export const WorkspacesRow: FC<{ } const useStyles = makeStyles((theme) => ({ - row: { - cursor: "pointer", - - "&:focus": { - outline: `1px solid ${theme.palette.secondary.dark}`, - outlineOffset: -1, - }, - }, - arrowRight: { color: theme.palette.text.secondary, width: 20, diff --git a/site/src/hooks/useClickableTableRow.ts b/site/src/hooks/useClickableTableRow.ts index 26c62c46f3700..2610e2fb76503 100644 --- a/site/src/hooks/useClickableTableRow.ts +++ b/site/src/hooks/useClickableTableRow.ts @@ -27,5 +27,10 @@ const useStyles = makeStyles((theme) => ({ outline: `1px solid ${theme.palette.secondary.dark}`, outlineOffset: -1, }, + + "&:last-of-type": { + borderBottomLeftRadius: theme.shape.borderRadius, + borderBottomRightRadius: theme.shape.borderRadius, + }, }, })) diff --git a/site/src/pages/CreateWorkspacePage/SelectedTemplate.stories.tsx b/site/src/pages/CreateWorkspacePage/SelectedTemplate.stories.tsx index c2f72af1f5a10..254ccdf7913cd 100644 --- a/site/src/pages/CreateWorkspacePage/SelectedTemplate.stories.tsx +++ b/site/src/pages/CreateWorkspacePage/SelectedTemplate.stories.tsx @@ -13,7 +13,10 @@ const Template: Story = (args) => ( export const WithIcon = Template.bind({}) WithIcon.args = { - template: MockTemplate, + template: { + ...MockTemplate, + icon: "/icon/docker.png", + }, } export const WithoutIcon = Template.bind({}) diff --git a/site/src/pages/CreateWorkspacePage/SelectedTemplate.tsx b/site/src/pages/CreateWorkspacePage/SelectedTemplate.tsx index 7d77c9a78de92..efb400c4577e5 100644 --- a/site/src/pages/CreateWorkspacePage/SelectedTemplate.tsx +++ b/site/src/pages/CreateWorkspacePage/SelectedTemplate.tsx @@ -18,7 +18,13 @@ export const SelectedTemplate: FC = ({ template }) => { className={styles.template} alignItems="center" > - {template.name} + + {template.name} + From a65ebff7a2714b0fa66f7941b3e095ed70c11b61 Mon Sep 17 00:00:00 2001 From: Bruno Quaresma Date: Fri, 3 Feb 2023 15:54:42 +0000 Subject: [PATCH 3/3] Fix filter --- .../SearchBarWithFilter/SearchBarWithFilter.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/site/src/components/SearchBarWithFilter/SearchBarWithFilter.tsx b/site/src/components/SearchBarWithFilter/SearchBarWithFilter.tsx index 2ffe4534804ba..31267a5e93245 100644 --- a/site/src/components/SearchBarWithFilter/SearchBarWithFilter.tsx +++ b/site/src/components/SearchBarWithFilter/SearchBarWithFilter.tsx @@ -156,6 +156,11 @@ interface StyleProps { const useStyles = makeStyles((theme) => ({ root: { marginBottom: theme.spacing(2), + + "&:has(button) .MuiInputBase-root": { + borderTopLeftRadius: 0, + borderBottomLeftRadius: 0, + }, }, // necessary to expand the textField // the length of the page (within the bordered filterContainer) @@ -174,7 +179,6 @@ const useStyles = makeStyles((theme) => ({ inputStyles: { height: "100%", width: "100%", - borderRadius: `0px ${theme.shape.borderRadius}px ${theme.shape.borderRadius}px 0px`, color: theme.palette.primary.contrastText, backgroundColor: theme.palette.background.paper, @@ -189,7 +193,7 @@ const useStyles = makeStyles((theme) => ({ paddingTop: "inherit", paddingBottom: "inherit", // The same as the button - minHeight: 42, + minHeight: 40, }, }, searchIcon: {