diff --git a/apps/docs/components/ExampleSearchHeader.tsx b/apps/docs/components/ExampleSearchHeader.tsx new file mode 100644 index 00000000..225ad1ae --- /dev/null +++ b/apps/docs/components/ExampleSearchHeader.tsx @@ -0,0 +1,12 @@ +import { SearchHeader } from '@enterwell/react-ui'; + +export function ExampleSearchHeader() { + return ( + console.log(searchTerm)} + placeholder='Search by term'> + Search + + ) +} \ No newline at end of file diff --git a/apps/docs/pages/react-ui/components/search-header.mdx b/apps/docs/pages/react-ui/components/search-header.mdx new file mode 100644 index 00000000..3424c511 --- /dev/null +++ b/apps/docs/pages/react-ui/components/search-header.mdx @@ -0,0 +1,33 @@ +--- +title: SearchHeader +--- + +import { SearchHeader } from '@enterwell/react-ui'; +import { ComponentWithSource } from '../../../components/docs/ComponentWithSource.tsx'; +import { ExampleSearchHeader } from '../../../components/ExampleSearchHeader.tsx'; +import { ComponentDescription, ComponentParameters, ComponentSource } from '../../../components/docs/ComponentDocs'; + +# SearchHeader + +## Description + + + +### Parameters + + + +## Example + + + +## Inspect + +
+ Source code + +
\ No newline at end of file diff --git a/packages/react-ui/SearchHeader/SearchHeader.tsx b/packages/react-ui/SearchHeader/SearchHeader.tsx new file mode 100644 index 00000000..ccfed7eb --- /dev/null +++ b/packages/react-ui/SearchHeader/SearchHeader.tsx @@ -0,0 +1,95 @@ +import React, { ReactNode, type MouseEvent } from 'react'; +import { + Typography, Stack, IconButton, InputBase, useTheme +} from '@mui/material'; +import { Variant } from '@mui/material/styles/createTypography'; +import { Search, Clear } from '@mui/icons-material'; + +/** + * The SearchHeader component props. + * @public + */ +export type SearchHeaderProps = { + onSubmit?: (searchTerm: string) => void, + placeholder?: string | undefined, + /** + * @defaultValue 'h1' + */ + variant?: Variant | undefined, + children?: ReactNode | undefined +} + +/** + * Search header. + * @param props - The props of the component. + * @returns The search header component. + * @public + */ +export function SearchHeader({ + onSubmit, + placeholder, + children, + variant = 'h1' +}: SearchHeaderProps) { + const [isSearching, setIsSearching] = React.useState(false); + const [searchTerm, setSearchTerm] = React.useState(''); + + const theme = useTheme(); + + const handleSearchClick = (e: MouseEvent) => { + e.stopPropagation(); + setIsSearching(true); + }; + + const handleClearClick = (e: MouseEvent) => { + e.stopPropagation(); + setSearchTerm(''); + setIsSearching(false); + if (onSubmit) + onSubmit(''); + }; + + const handleInputBlur = () => { + if (searchTerm === '') { + setIsSearching(false); + if (onSubmit) + onSubmit(''); + } + }; + + const handleSubmit = (e: any) => { + if (e.key === 'Enter' && onSubmit) { + onSubmit(searchTerm); + } else if (e.key === 'Escape') { + handleClearClick(e); + } + }; + + const fontSize = variant ? theme.typography[variant as Variant].fontSize : undefined; + + return isSearching ? ( + + + + )} + autoFocus + placeholder={placeholder} + onClick={(e) => e.stopPropagation()} + value={searchTerm} + onChange={(e) => setSearchTerm(e.target.value)} + onKeyDown={handleSubmit} + onBlur={handleInputBlur} + /> + ) : ( + + {children} + {onSubmit && ( + + + + )} + + ); +} diff --git a/packages/react-ui/SearchHeader/index.tsx b/packages/react-ui/SearchHeader/index.tsx new file mode 100644 index 00000000..cfa1983a --- /dev/null +++ b/packages/react-ui/SearchHeader/index.tsx @@ -0,0 +1 @@ +export * from "./SearchHeader"; diff --git a/packages/react-ui/changes/Added SearchHeader component b/packages/react-ui/changes/Added SearchHeader component new file mode 100644 index 00000000..e69de29b diff --git a/packages/react-ui/index.tsx b/packages/react-ui/index.tsx index 340b98ee..9e5500af 100644 --- a/packages/react-ui/index.tsx +++ b/packages/react-ui/index.tsx @@ -9,4 +9,5 @@ export * from "./TimeInput"; export * from "./DateTimeRangePicker"; export * from "./ConfirmDialog"; export * from "./DropdownButton"; -export * from "./PageDrawer"; \ No newline at end of file +export * from "./PageDrawer"; +export * from "./SearchHeader"; \ No newline at end of file diff --git a/packages/react-ui/temp/react-ui.api.md b/packages/react-ui/temp/react-ui.api.md index 3f81932f..0ce6193f 100644 --- a/packages/react-ui/temp/react-ui.api.md +++ b/packages/react-ui/temp/react-ui.api.md @@ -20,6 +20,7 @@ import { ReactNode } from 'react'; import { SyntheticEvent } from 'react'; import { TextField } from '@mui/material'; import { TextFieldProps } from '@mui/material'; +import { Variant } from '@mui/material/styles/createTypography'; // @public export function ConfirmButton({ header, message, confirmButtonText, color, onConfirm, slots, ...rest }: ConfirmButtonProps): react_jsx_runtime.JSX.Element; @@ -114,6 +115,17 @@ export type PageDrawerProps = HTMLAttributes & { onResize?: (height: number | undefined) => void; }; +// @public +export function SearchHeader({ onSubmit, placeholder, children, variant }: SearchHeaderProps): react_jsx_runtime.JSX.Element; + +// @public +export type SearchHeaderProps = { + onSubmit?: (searchTerm: string) => void; + placeholder?: string | undefined; + variant?: Variant | undefined; + children?: ReactNode | undefined; +}; + // @public export function Select({ multiple, value, options, placeholder, loading: parentLoading, label, onChange, displayOption, pageSize, onPage, debounce, noOptionsText, loadingOptionsText, error, helperText, required, disableFilterOptions, stopPropagationOnKeyCodeSpace, onBlur, listStartDecorator, listEndDecorator, ...rest }: SelectProps): react_jsx_runtime.JSX.Element;