- Notifications
You must be signed in to change notification settings - Fork1k
chore(site): refactor filters#13394
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Closed
Uh oh!
There was an error while loading.Please reload this page.
Closed
Changes fromall commits
Commits
Show all changes
27 commits Select commitHold shift + click to select a range
d7a4be0
Add base structure for the new filter component
BrunoQuaresmaf6df4fa
Add error state
BrunoQuaresmad41d307
Simplify component
BrunoQuaresma47fd44b
Make it accessible
BrunoQuaresmad28e9b4
Add simple dropdown button component
BrunoQuaresma16bbf5a
Refactor search and add preset filter menu
BrunoQuaresma5d8829e
Add status menu
BrunoQuaresmac89cf8c
Add status menu to workspaces search
BrunoQuaresma0c501e5
WIP: Create base UserMenu
BrunoQuaresmac38cd7b
Finish user menu
BrunoQuaresma38b10a5
Add search
BrunoQuaresma3797ae9
Refactor search field to be more extensible
BrunoQuaresmab552828
Extract reusable menu elements
BrunoQuaresma498f6cd
Simplify usage
BrunoQuaresmade83eda
Improve MenuSearch component
BrunoQuaresmac2aa478
Keep search fixed on top
BrunoQuaresma30a8373
Add more tests
BrunoQuaresma542c377
Merge branch 'main' of https://github.com/coder/coder into bq/improve…
BrunoQuaresma01a6616
Handle filtering
BrunoQuaresmae97ce00
Add focus on arrow down
BrunoQuaresma7638595
Add template menu
BrunoQuaresma76224c3
Merge branch 'main' of https://github.com/coder/coder into bq/improve…
BrunoQuaresma6d1ce99
Use users paginated request
BrunoQuaresmad3c9ef5
Remove forgotten debuggers
BrunoQuaresma3250b48
Merge branch 'main' of https://github.com/coder/coder into bq/improve…
BrunoQuaresmad1b71b1
Remove unecessary prop
BrunoQuaresmaa804a40
Apply michaels review
BrunoQuaresmaFile filter
Filter by extension
Conversations
Failed to load comments.
Loading
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Jump to file
Failed to load files.
Loading
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
There are no files selected for viewing
1 change: 1 addition & 0 deletions.vscode/settings.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -155,6 +155,7 @@ | ||
"typesafe", | ||
"unconvert", | ||
"Untar", | ||
"upsert", | ||
"Userspace", | ||
"VMID", | ||
"walkthrough", | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import Button, { type ButtonProps } from "@mui/material/Button"; | ||
import { forwardRef } from "react"; | ||
import { DropdownArrow } from "components/DropdownArrow/DropdownArrow"; | ||
export const MenuButton = forwardRef<HTMLButtonElement, ButtonProps>( | ||
(props, ref) => { | ||
return <Button endIcon={<DropdownArrow />} ref={ref} {...props} />; | ||
}, | ||
); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import CheckOutlined from "@mui/icons-material/CheckOutlined"; | ||
import type { FC } from "react"; | ||
import { MenuIcon } from "./MenuIcon"; | ||
export const MenuCheck: FC<{ isVisible: boolean }> = ({ isVisible }) => { | ||
return ( | ||
<MenuIcon> | ||
<CheckOutlined | ||
role="presentation" | ||
css={{ | ||
visibility: isVisible ? "visible" : "hidden", | ||
marginLeft: "auto", | ||
}} | ||
/> | ||
</MenuIcon> | ||
); | ||
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { css } from "@emotion/css"; | ||
import { | ||
type FC, | ||
type PropsWithChildren, | ||
type ReactElement, | ||
cloneElement, | ||
} from "react"; | ||
type MenuIconProps = { | ||
size?: number; | ||
}; | ||
export const MenuIcon: FC<PropsWithChildren<MenuIconProps>> = ({ | ||
children, | ||
size = 14, | ||
}) => { | ||
return cloneElement(children as ReactElement, { | ||
className: css({ | ||
fontSize: size, | ||
}), | ||
}); | ||
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { useTheme } from "@emotion/react"; | ||
import type { FC } from "react"; | ||
export const MenuNoResults: FC = () => { | ||
const theme = useTheme(); | ||
return ( | ||
<div | ||
css={{ | ||
padding: "8px 12px", | ||
color: theme.palette.text.secondary, | ||
fontSize: 14, | ||
textAlign: "center", | ||
}} | ||
> | ||
No results found | ||
</div> | ||
); | ||
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import { css } from "@emotion/css"; | ||
import { useTheme } from "@emotion/react"; | ||
import type { FC } from "react"; | ||
import { | ||
SearchField, | ||
type SearchFieldProps, | ||
} from "components/Search/SearchField"; | ||
export const MenuSearch: FC<SearchFieldProps> = (props) => { | ||
const theme = useTheme(); | ||
return ( | ||
<SearchField | ||
{...props} | ||
onKeyDown={(e) => { | ||
if (e.key === "ArrowDown") { | ||
e.preventDefault(); | ||
const firstMenuItem = e.currentTarget | ||
.closest<HTMLDivElement>(".MuiPaper-root") | ||
?.querySelector<HTMLElement>("[role=menuitem]"); | ||
if (firstMenuItem) { | ||
firstMenuItem.focus(); | ||
} | ||
} | ||
}} | ||
className={css({ | ||
position: "sticky", | ||
top: 0, | ||
backgroundColor: theme.palette.background.paper, | ||
zIndex: 1, | ||
"& fieldset": { | ||
border: 0, | ||
borderRadius: 0, | ||
borderBottomStyle: "solid", | ||
borderBottomWidth: `1px !important`, | ||
borderColor: `${theme.palette.divider} !important`, | ||
}, | ||
})} | ||
/> | ||
); | ||
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
import type { Meta, StoryObj } from "@storybook/react"; | ||
import { userEvent, within, expect } from "@storybook/test"; | ||
import { useState } from "react"; | ||
import { SearchField } from "./SearchField"; | ||
const searchLabel = "Search for something"; | ||
const meta: Meta<typeof SearchField> = { | ||
title: "components/SearchField", | ||
component: SearchField, | ||
args: { | ||
id: "search", | ||
label: searchLabel, | ||
}, | ||
render: function SearchFieldWithState(args) { | ||
const [value, setValue] = useState<string>(args.value); | ||
return <SearchField {...args} value={value} onChange={setValue} />; | ||
}, | ||
}; | ||
export default meta; | ||
type Story = StoryObj<typeof SearchField>; | ||
export const Empty: Story = { | ||
args: { | ||
value: "", | ||
}, | ||
}; | ||
export const DefaultValue: Story = { | ||
args: { | ||
value: "owner:CoderUser", | ||
}, | ||
}; | ||
export const Error: Story = { | ||
args: { | ||
value: "number_of_users:7", | ||
error: `"number_of_users" is not a valid query param`, | ||
}, | ||
}; | ||
export const Focused: Story = { | ||
args: { | ||
value: "", | ||
}, | ||
play: async ({ canvasElement }) => { | ||
const canvas = within(canvasElement); | ||
const input = canvas.getByLabelText(searchLabel); | ||
await userEvent.click(input); | ||
await expect(input).toHaveFocus(); | ||
}, | ||
}; | ||
export const Typing: Story = { | ||
args: { | ||
value: "", | ||
}, | ||
play: async ({ canvasElement }) => { | ||
const text = "owner:SomeSearchString"; | ||
const canvas = within(canvasElement); | ||
const input = canvas.getByLabelText(searchLabel); | ||
await userEvent.type(input, text); | ||
await expect(input).toHaveValue(text); | ||
}, | ||
}; | ||
export const ClearInput: Story = { | ||
args: { | ||
value: "owner:CoderUser", | ||
}, | ||
play: async ({ canvasElement }) => { | ||
const canvas = within(canvasElement); | ||
const input = canvas.getByLabelText(searchLabel); | ||
await userEvent.click(canvas.getByRole("button", { name: "Clear filter" })); | ||
await expect(input).toHaveValue(""); | ||
}, | ||
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
import { useTheme } from "@emotion/react"; | ||
import CloseOutlined from "@mui/icons-material/CloseOutlined"; | ||
import SearchOutlined from "@mui/icons-material/SearchOutlined"; | ||
import IconButton from "@mui/material/IconButton"; | ||
import InputAdornment from "@mui/material/InputAdornment"; | ||
import TextField, { type TextFieldProps } from "@mui/material/TextField"; | ||
import Tooltip from "@mui/material/Tooltip"; | ||
import { visuallyHidden } from "@mui/utils"; | ||
import type { FC } from "react"; | ||
export type SearchFieldProps = Omit< | ||
TextFieldProps, | ||
"onChange" | "id" | "label" | "value" | "error" | ||
> & { | ||
id: string; | ||
label: string; | ||
value: string; | ||
autoFocus?: boolean; | ||
error?: string; | ||
onChange: (value: string) => void; | ||
}; | ||
export const SearchField: FC<SearchFieldProps> = (props) => { | ||
const theme = useTheme(); | ||
const { value, label, id, error, onChange, autoFocus, ...textFieldProps } = | ||
props; | ||
const isEmpty = value.length === 0; | ||
return ( | ||
<> | ||
<label htmlFor={id} css={{ ...visuallyHidden }}> | ||
{label} | ||
</label> | ||
<TextField | ||
{...textFieldProps} | ||
error={Boolean(error)} | ||
helperText={error} | ||
type="text" | ||
InputProps={{ | ||
...textFieldProps.InputProps, | ||
autoFocus, | ||
id, | ||
size: "small", | ||
startAdornment: ( | ||
<InputAdornment position="start"> | ||
<SearchOutlined | ||
role="presentation" | ||
css={{ | ||
fontSize: 14, | ||
color: theme.palette.text.secondary, | ||
}} | ||
/> | ||
</InputAdornment> | ||
), | ||
endAdornment: !isEmpty && ( | ||
<Tooltip title="Clear filter"> | ||
<IconButton | ||
size="small" | ||
onClick={() => { | ||
onChange(""); | ||
}} | ||
> | ||
<CloseOutlined | ||
css={{ | ||
fontSize: 14, | ||
color: theme.palette.text.secondary, | ||
}} | ||
/> | ||
<span css={{ ...visuallyHidden }}>Clear filter</span> | ||
</IconButton> | ||
</Tooltip> | ||
), | ||
}} | ||
value={value} | ||
onChange={(e) => { | ||
onChange(e.target.value); | ||
}} | ||
placeholder={textFieldProps.placeholder ?? "Search..."} | ||
fullWidth | ||
/> | ||
</> | ||
); | ||
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import type { FC } from "react"; | ||
import type { Template } from "api/typesGenerated"; | ||
import { Avatar, type AvatarProps } from "components/Avatar/Avatar"; | ||
type TemplateAvatarProps = { | ||
template: Template; | ||
size: AvatarProps["size"]; | ||
}; | ||
export const TemplateAvatar: FC<TemplateAvatarProps> = ({ template, size }) => { | ||
BrunoQuaresma marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
const hasIcon = template.icon && template.icon !== ""; | ||
if (hasIcon) { | ||
return <Avatar size={size} src={template.icon} variant="square" fitImage />; | ||
} | ||
return <Avatar size={size}>{template.name}</Avatar>; | ||
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
Oops, something went wrong.
Uh oh!
There was an error while loading.Please reload this page.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.