From a10086e62e78fe6bac33a6f10207671c1beb77e9 Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Thu, 7 Mar 2024 18:52:24 +0000 Subject: [PATCH 1/5] refactor `Search` to avoid `forwardRef` --- site/src/components/Filter/filter.tsx | 4 +- site/src/components/Menu/Search.tsx | 105 ----------------- site/src/components/Search/Search.tsx | 110 ++++++++++++++++++ .../pages/WorkspacesPage/WorkspacesButton.tsx | 2 +- .../WorkspacesPage/WorkspacesSearchBox.tsx | 31 +++-- 5 files changed, 127 insertions(+), 125 deletions(-) delete mode 100644 site/src/components/Menu/Search.tsx create mode 100644 site/src/components/Search/Search.tsx diff --git a/site/src/components/Filter/filter.tsx b/site/src/components/Filter/filter.tsx index 44e2101a1635e..8335408c11733 100644 --- a/site/src/components/Filter/filter.tsx +++ b/site/src/components/Filter/filter.tsx @@ -34,7 +34,7 @@ import { SearchEmpty, SearchInput, searchStyles, -} from "components/Menu/Search"; +} from "components/Search/Search"; import { useDebouncedFunction } from "hooks/debounce"; import type { useFilterMenu } from "./menu"; import type { BaseOption } from "./options"; @@ -612,7 +612,7 @@ function SearchMenu({ { onQueryChange(e.target.value); }} diff --git a/site/src/components/Menu/Search.tsx b/site/src/components/Menu/Search.tsx deleted file mode 100644 index 19c3ea97330d8..0000000000000 --- a/site/src/components/Menu/Search.tsx +++ /dev/null @@ -1,105 +0,0 @@ -import { type Interpolation, type Theme, useTheme } from "@emotion/react"; -import SearchOutlined from "@mui/icons-material/SearchOutlined"; -// eslint-disable-next-line no-restricted-imports -- use it to have the component prop -import Box, { type BoxProps } from "@mui/material/Box"; -import visuallyHidden from "@mui/utils/visuallyHidden"; -import { - type FC, - type HTMLAttributes, - type InputHTMLAttributes, - forwardRef, -} from "react"; - -export const Search = forwardRef( - ({ children, ...boxProps }, ref) => { - const theme = useTheme(); - - return ( - - - {children} - - ); - }, -); - -type SearchInputProps = InputHTMLAttributes & { - label?: string; -}; - -export const SearchInput = forwardRef( - ({ label, ...inputProps }, ref) => { - const theme = useTheme(); - - return ( - <> - - - - ); - }, -); - -export const SearchEmpty: FC> = ({ - children = "Not found", - ...props -}) => { - const theme = useTheme(); - - return ( -
- {children} -
- ); -}; - -export const searchStyles = { - content: { - width: 320, - padding: 0, - borderRadius: 4, - }, -} satisfies Record>; diff --git a/site/src/components/Search/Search.tsx b/site/src/components/Search/Search.tsx new file mode 100644 index 0000000000000..9fcc792a0dbae --- /dev/null +++ b/site/src/components/Search/Search.tsx @@ -0,0 +1,110 @@ +import { type Interpolation, type Theme, useTheme } from "@emotion/react"; +import SearchOutlined from "@mui/icons-material/SearchOutlined"; +// eslint-disable-next-line no-restricted-imports -- use it to have the component prop +import Box, { type BoxProps } from "@mui/material/Box"; +import visuallyHidden from "@mui/utils/visuallyHidden"; +import { + type FC, + type HTMLAttributes, + type InputHTMLAttributes, + type Ref, +} from "react"; + +interface SearchProps extends BoxProps { + $$ref?: Ref; +} + +export const Search: FC = ({ children, $$ref, ...boxProps }) => { + const theme = useTheme(); + + return ( + + + {children} + + ); +}; + +type SearchInputProps = InputHTMLAttributes & { + label?: string; + $$ref?: Ref; +}; + +export const SearchInput: FC = ({ + label, + $$ref, + ...inputProps +}) => { + const theme = useTheme(); + + return ( + <> + + + + ); +}; + +export const SearchEmpty: FC> = ({ + children = "Not found", + ...props +}) => { + const theme = useTheme(); + + return ( +
+ {children} +
+ ); +}; + +export const searchStyles = { + content: { + width: 320, + padding: 0, + borderRadius: 4, + }, +} satisfies Record>; diff --git a/site/src/pages/WorkspacesPage/WorkspacesButton.tsx b/site/src/pages/WorkspacesPage/WorkspacesButton.tsx index b8e03a2582886..cbfbc16974ddf 100644 --- a/site/src/pages/WorkspacesPage/WorkspacesButton.tsx +++ b/site/src/pages/WorkspacesPage/WorkspacesButton.tsx @@ -11,7 +11,7 @@ import { import type { Template } from "api/typesGenerated"; import { Avatar } from "components/Avatar/Avatar"; import { Loader } from "components/Loader/Loader"; -import { SearchEmpty, searchStyles } from "components/Menu/Search"; +import { SearchEmpty, searchStyles } from "components/Search/Search"; import { OverflowY } from "components/OverflowY/OverflowY"; import { Popover, diff --git a/site/src/pages/WorkspacesPage/WorkspacesSearchBox.tsx b/site/src/pages/WorkspacesPage/WorkspacesSearchBox.tsx index 09274b743d58a..d92d27c6ee238 100644 --- a/site/src/pages/WorkspacesPage/WorkspacesSearchBox.tsx +++ b/site/src/pages/WorkspacesPage/WorkspacesSearchBox.tsx @@ -5,33 +5,30 @@ * reusable this is outside of workspace dropdowns. */ import { - type ForwardedRef, + type FC, type KeyboardEvent, type InputHTMLAttributes, - forwardRef, + type Ref, useId, } from "react"; -import { Search, SearchInput } from "components/Menu/Search"; +import { Search, SearchInput } from "components/Search/Search"; interface SearchBoxProps extends InputHTMLAttributes { label?: string; value: string; onKeyDown?: (event: KeyboardEvent) => void; onValueChange: (newValue: string) => void; + $$ref?: Ref; } -export const SearchBox = forwardRef(function SearchBox( - props: SearchBoxProps, - ref?: ForwardedRef, -) { - const { - onValueChange, - onKeyDown, - label = "Search", - placeholder = "Search...", - ...attrs - } = props; - +export const SearchBox: FC = ({ + onValueChange, + onKeyDown, + label = "Search", + placeholder = "Search...", + $$ref, + ...attrs +}) => { const hookId = useId(); const inputId = `${hookId}-${SearchBox.name}-input`; @@ -39,7 +36,7 @@ export const SearchBox = forwardRef(function SearchBox( ); -}); +}; From 2975598914921b8bcfa5a83c5d3a096ee2c346d1 Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Thu, 7 Mar 2024 18:57:44 +0000 Subject: [PATCH 2/5] basic story --- site/src/components/Search/Search.stories.tsx | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 site/src/components/Search/Search.stories.tsx diff --git a/site/src/components/Search/Search.stories.tsx b/site/src/components/Search/Search.stories.tsx new file mode 100644 index 0000000000000..52586a12a8f95 --- /dev/null +++ b/site/src/components/Search/Search.stories.tsx @@ -0,0 +1,19 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { Search, SearchInput } from "./Search"; + +const meta: Meta = { + title: "components/Search", + component: SearchInput, + decorators: [ + (Story) => ( + + + + ), + ], +}; + +export default meta; +type Story = StoryObj; + +export const Example: Story = {}; From 23962dfc747f84834d331b1cd5f6c4aff2102442 Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Thu, 7 Mar 2024 21:51:05 +0000 Subject: [PATCH 3/5] =?UTF-8?q?=F0=9F=AA=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- site/src/components/Search/Search.stories.tsx | 7 ++ site/src/components/Search/Search.tsx | 100 ++++++++++-------- 2 files changed, 63 insertions(+), 44 deletions(-) diff --git a/site/src/components/Search/Search.stories.tsx b/site/src/components/Search/Search.stories.tsx index 52586a12a8f95..dd2d866a83638 100644 --- a/site/src/components/Search/Search.stories.tsx +++ b/site/src/components/Search/Search.stories.tsx @@ -17,3 +17,10 @@ export default meta; type Story = StoryObj; export const Example: Story = {}; + +export const WithPlaceholder: Story = { + args: { + label: "uwu", + placeholder: "uwu", + }, +}; diff --git a/site/src/components/Search/Search.tsx b/site/src/components/Search/Search.tsx index 9fcc792a0dbae..861929f0e1d49 100644 --- a/site/src/components/Search/Search.tsx +++ b/site/src/components/Search/Search.tsx @@ -14,32 +14,39 @@ interface SearchProps extends BoxProps { $$ref?: Ref; } +/** + * A container component meant for `SearchInput` + * + * ``` + * + * + * + * ``` + */ export const Search: FC = ({ children, $$ref, ...boxProps }) => { - const theme = useTheme(); - return ( - - + + {children} ); }; +const SearchStyles = { + container: (theme) => ({ + display: "flex", + alignItems: "center", + paddingLeft: 16, + height: 40, + borderBottom: `1px solid ${theme.palette.divider}`, + }), + + icon: (theme) => ({ + fontSize: 14, + color: theme.palette.text.secondary, + }), +} satisfies Record>; + type SearchInputProps = InputHTMLAttributes & { label?: string; $$ref?: Ref; @@ -50,8 +57,6 @@ export const SearchInput: FC = ({ $$ref, ...inputProps }) => { - const theme = useTheme(); - return ( <>