Skip to content

fix(site): fix search menu for creating workspace and templates filter #11674

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 17, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Fix templates key
  • Loading branch information
BrunoQuaresma committed Jan 17, 2024
commit 7f3c66f99102852adf6a1869e959f230fdebb8db
60 changes: 12 additions & 48 deletions site/src/components/Filter/filter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ import { Loader } from "components/Loader/Loader";
import { useDebouncedFunction } from "hooks/debounce";
import { useFilterMenu } from "./menu";
import type { BaseOption } from "./options";
import {
Search,
SearchEmpty,
SearchInput,
searchContentStyles,
} from "components/Menu/Search";

export type PresetFilter = {
name: string;
Expand Down Expand Up @@ -489,7 +495,7 @@ export const FilterSearchMenu = <TOption extends BaseOption>({
onQueryChange={menu.setQuery}
renderOption={(option) => (
<MenuItem
key={option.label}
key={option.value}
selected={option.value === menu.selectedOption?.value}
onClick={() => {
menu.selectOption(option);
Expand Down Expand Up @@ -576,7 +582,6 @@ function SearchMenu<TOption extends BaseOption>({
}: SearchMenuProps<TOption>) {
const menuListRef = useRef<HTMLUListElement>(null);
const searchInputRef = useRef<HTMLInputElement>(null);
const theme = useTheme();

return (
<Menu
Expand All @@ -586,10 +591,7 @@ function SearchMenu<TOption extends BaseOption>({
onQueryChange("");
}}
css={{
"& .MuiPaper-root": {
width: 320,
padding: 0,
},
"& .MuiPaper-root": searchContentStyles,
}}
// Disabled this so when we clear the filter and do some sorting in the
// search items it does not look strange. Github removes exit transitions
Expand All @@ -606,44 +608,16 @@ function SearchMenu<TOption extends BaseOption>({
}
}}
>
<li
css={{
display: "flex",
alignItems: "center",
paddingLeft: 16,
height: 40,
borderBottom: `1px solid ${theme.palette.divider}`,
}}
>
<SearchOutlined
css={{
fontSize: 14,
color: theme.palette.text.secondary,
}}
/>
<input
tabIndex={-1}
type="text"
placeholder="Search..."
<Search component="li">
<SearchInput
autoFocus
value={query}
ref={searchInputRef}
onChange={(e) => {
onQueryChange(e.target.value);
}}
css={{
height: "100%",
border: 0,
background: "none",
width: "100%",
marginLeft: 16,
outline: 0,
"&::placeholder": {
color: theme.palette.text.secondary,
},
}}
/>
</li>
</Search>

<li css={{ maxHeight: 480, overflowY: "auto" }}>
<MenuList
Expand All @@ -660,17 +634,7 @@ function SearchMenu<TOption extends BaseOption>({
options.length > 0 ? (
options.map(renderOption)
) : (
<div
css={{
fontSize: 13,
color: theme.palette.text.secondary,
textAlign: "center",
paddingTop: 8,
paddingBottom: 8,
}}
>
No results
</div>
<SearchEmpty />
)
) : (
<Loader size={14} />
Expand Down
98 changes: 98 additions & 0 deletions site/src/components/Menu/Search.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import SearchOutlined from "@mui/icons-material/SearchOutlined";
// eslint-disable-next-line no-restricted-imports -- use it to have the component prop
import Box, { BoxProps } from "@mui/material/Box";
import { Interpolation, Theme, useTheme } from "@mui/material/styles";
import visuallyHidden from "@mui/utils/visuallyHidden";
import { FC, HTMLAttributes, InputHTMLAttributes, forwardRef } from "react";

export const Search = forwardRef<HTMLElement, BoxProps>(
({ children, ...boxProps }, ref) => {
const theme = useTheme();

return (
<Box
ref={ref}
{...boxProps}
css={{
display: "flex",
alignItems: "center",
paddingLeft: 16,
height: 40,
borderBottom: `1px solid ${theme.palette.divider}`,
}}
>
<SearchOutlined
css={{
fontSize: 14,
color: theme.palette.text.secondary,
}}
/>
{children}
</Box>
);
},
);

type SearchInputProps = InputHTMLAttributes<HTMLInputElement> & {
label?: string;
};

export const SearchInput = forwardRef<HTMLInputElement, SearchInputProps>(
({ label, ...inputProps }, ref) => {
const theme = useTheme();

return (
<>
<label css={{ ...visuallyHidden }} htmlFor={inputProps.id}>
{label}
</label>
<input
ref={ref}
tabIndex={-1}
type="text"
placeholder="Search..."
css={{
height: "100%",
border: 0,
background: "none",
flex: 1,
marginLeft: 16,
outline: 0,
"&::placeholder": {
color: theme.palette.text.secondary,
},
}}
{...inputProps}
/>
</>
);
},
);

export const SearchEmpty: FC<HTMLAttributes<HTMLDivElement>> = ({
children = "Not found",
...props
}) => {
const theme = useTheme();

return (
<div
css={{
fontSize: 13,
color: theme.palette.text.secondary,
textAlign: "center",
paddingTop: 8,
paddingBottom: 8,
}}
{...props}
>
{children}
</div>
);
};

export const searchContentStyles = {
width: 320,
padding: 0,
borderRadius: 4,
} satisfies Record<string, Interpolation<Theme>>;
25 changes: 14 additions & 11 deletions site/src/pages/WorkspacesPage/WorkspacesButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ import AddIcon from "@mui/icons-material/AddOutlined";
import OpenIcon from "@mui/icons-material/OpenInNewOutlined";
import { Loader } from "components/Loader/Loader";
import { OverflowY } from "components/OverflowY/OverflowY";
import { EmptyState } from "components/EmptyState/EmptyState";
import { Avatar } from "components/Avatar/Avatar";
import { SearchBox } from "./WorkspacesSearchBox";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "components/Popover/Popover";
import { SearchEmpty, searchContentStyles } from "components/Menu/Search";

const ICON_SIZE = 18;

Expand All @@ -43,17 +43,15 @@ export const WorkspacesButton: FC<WorkspacesButtonProps> = ({
let emptyState: ReactNode = undefined;
if (templates?.length === 0) {
emptyState = (
<EmptyState
message="No templates yet"
cta={
<Link to="/templates" component={RouterLink}>
Create one now.
</Link>
}
/>
<SearchEmpty>
No templates yet.{" "}
<Link to="/templates" component={RouterLink}>
Create one now.
</Link>
</SearchEmpty>
);
} else if (processed.length === 0) {
emptyState = <EmptyState message="No templates match your text" />;
emptyState = <SearchEmpty>No templates found</SearchEmpty>;
}

return (
Expand All @@ -63,7 +61,12 @@ export const WorkspacesButton: FC<WorkspacesButtonProps> = ({
{children}
</Button>
</PopoverTrigger>
<PopoverContent horizontal="right">
<PopoverContent
horizontal="right"
css={{
".MuiPaper-root": searchContentStyles,
}}
>
<SearchBox
value={searchTerm}
onValueChange={(newValue) => setSearchTerm(newValue)}
Expand Down
49 changes: 5 additions & 44 deletions site/src/pages/WorkspacesPage/WorkspacesSearchBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@ import {
forwardRef,
useId,
} from "react";
import SearchIcon from "@mui/icons-material/SearchOutlined";
import { visuallyHidden } from "@mui/utils";
import { useTheme } from "@emotion/react";
import { Search, SearchInput } from "components/Menu/Search";

interface SearchBoxProps extends InputHTMLAttributes<HTMLInputElement> {
label?: string;
Expand All @@ -35,39 +33,12 @@ export const SearchBox = forwardRef(function SearchBox(
} = props;

const hookId = useId();
const theme = useTheme();

const inputId = `${hookId}-${SearchBox.name}-input`;

return (
<div
css={{
display: "flex",
flexFlow: "row nowrap",
alignItems: "center",
padding: "0 8px",
height: "40px",
borderBottom: `1px solid ${theme.palette.divider}`,
}}
>
<div css={{ width: 18 }}>
<SearchIcon
css={{
display: "block",
fontSize: "14px",
marginLeft: "auto",
marginRight: "auto",
color: theme.palette.text.secondary,
}}
/>
</div>

<label css={{ ...visuallyHidden }} htmlFor={inputId}>
{label}
</label>

<input
type="text"
<Search>
<SearchInput
label={label}
ref={ref}
id={inputId}
autoFocus
Expand All @@ -76,17 +47,7 @@ export const SearchBox = forwardRef(function SearchBox(
{...attrs}
onKeyDown={onKeyDown}
onChange={(e) => onValueChange(e.target.value)}
css={{
height: "100%",
border: 0,
background: "none",
width: "100%",
outline: 0,
"&::placeholder": {
color: theme.palette.text.secondary,
},
}}
/>
</div>
</Search>
);
});