Skip to content
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

feat(Search): new Search component #2064

Merged
merged 31 commits into from
Apr 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
f1a2f31
chore(BaseInput): reusable, internal Input component
YossiSaadi Apr 9, 2024
985042e
chore(BaseInput): set hard coded height for sizes
YossiSaadi Apr 9, 2024
a141fe4
refactor(BaseInput): remove mistakenly inserted example
YossiSaadi Apr 9, 2024
0c2be39
feat(BaseInput): update api, allow change role of wrapper and input, …
YossiSaadi Apr 11, 2024
3e7f958
feat(BaseInput): remove underline, allow input to always take maximum…
YossiSaadi Apr 11, 2024
400f06d
test(BaseInput): add tests for basic usage of component
YossiSaadi Apr 11, 2024
15c9695
docs(BaseInput): internal story for component (hidden in prod)
YossiSaadi Apr 11, 2024
584dfa2
Merge branch 'master' into chore/yossi/reusable-base-input
YossiSaadi Apr 15, 2024
73e5f24
feat(BaseInput): add flex-shrink 0, to avoid the fixed height not bei…
YossiSaadi Apr 15, 2024
50b6e1c
Merge branch 'master' into chore/yossi/reusable-base-input
YossiSaadi Apr 15, 2024
b5ecf9f
fix(BaseInput): fix import of typography styles, add import to mixins
YossiSaadi Apr 17, 2024
82d9597
refactor(BaseInput): only use has for supported browsers, otherwise u…
YossiSaadi Apr 17, 2024
61b9e15
test(BaseInput): refactor test
YossiSaadi Apr 17, 2024
2978e90
feat(Search): new Search component
YossiSaadi Apr 11, 2024
a6da489
test(Search): add tests to new component
YossiSaadi Apr 14, 2024
29d2917
chore(Search): export old Search from LegacySearch path, export new S…
YossiSaadi Apr 14, 2024
bb8471c
chore(LegacySearch): update naming
YossiSaadi Apr 14, 2024
2983824
chore(LegacySearch): use LegacySearch in existing components and stories
YossiSaadi Apr 14, 2024
6c2e0d2
docs(Search): document new Search component
YossiSaadi Apr 14, 2024
4504ff6
docs(Search): add import statement from /next
YossiSaadi Apr 14, 2024
4ba93b6
docs(LegacySearch): add import statement from root, add deprecation w…
YossiSaadi Apr 14, 2024
49a3f53
docs(Catalog): use new search
YossiSaadi Apr 14, 2024
a192705
refactor(Search): css changes
YossiSaadi Apr 17, 2024
b331a61
test(LegacySearch): change name to not break snapshots
YossiSaadi Apr 17, 2024
829a2d1
feat(Search): use default debounceRate of 400 instead of 200
YossiSaadi Apr 17, 2024
04186f3
docs(Search): jsdoc for props
YossiSaadi Apr 17, 2024
1f7d460
feat: fix PR comments
YossiSaadi Apr 17, 2024
55edc2c
Merge remote-tracking branch 'origin/master' into feat/yossi/Search--…
YossiSaadi Apr 17, 2024
53c929a
docs(BaseInput): jsdoc for props
YossiSaadi Apr 17, 2024
a04f470
docs(Search): fix story prop
YossiSaadi Apr 17, 2024
b304a9d
style(Search): prettier
YossiSaadi Apr 17, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { createComponentTemplate, StoryDescription } from "vibe-storybook-compon
import DialogContentContainer from "../../DialogContentContainer/DialogContentContainer";
import { Info, Invite, ThumbsUp } from "../../Icon/Icons";
import Icon from "../../Icon/Icon";
import Search from "../../Search/Search";
YossiSaadi marked this conversation as resolved.
Show resolved Hide resolved
import LegacySearch from "../../LegacySearch/LegacySearch";
import Avatar from "../../Avatar/Avatar";
import person from "./assets/person.png";
import Flex from "../../Flex/Flex";
Expand Down Expand Up @@ -159,7 +159,7 @@ export const AttentionBoxInsideADialogCombobox = {

return (
<DialogContentContainer className="monday-storybook-attention-box_search-bar">
<Search placeholder="Search by name, role, team, or email" />
<LegacySearch placeholder="Search by name, role, team, or email" />
<div className="monday-storybook-attention-box_lable">Suggested people</div>
<div className="monday-storybook-attention-box_search">
<div className="monday-storybook-attention-box_inline-container">
Expand Down
30 changes: 18 additions & 12 deletions packages/core/src/components/BaseInput/BaseInput.tsx
Original file line number Diff line number Diff line change
@@ -1,43 +1,49 @@
import React, { forwardRef } from "react";
import cx from "classnames";
import styles from "./BaseInput.module.scss";
import { BaseInputComponent } from "./BaseInput.types";
import { BaseInputProps } from "./BaseInput.types";
import { getStyle } from "../../helpers/typesciptCssModulesHelper";

const BaseInput: BaseInputComponent = forwardRef(
const BaseInput = forwardRef(
(
{
size = "medium",
leftRender,
rightRender,
renderLeft,
renderRight,
success,
error,
wrapperRole,
inputRole,
className,
wrapperClassName,
inputClassName,
...props
},
ref
}: BaseInputProps,
ref: React.ForwardedRef<HTMLInputElement>
) => {
const wrapperClassNames = cx(
styles.wrapper,
{
[styles.rightThinnerPadding]: !rightRender,
[styles.rightThinnerPadding]: !renderRight,
[styles.error]: error,
[styles.success]: success,
[styles.readOnly]: props.readOnly,
[styles.disabled]: props.disabled
},
getStyle(styles, size),
wrapperClassName
className
);

return (
<div className={wrapperClassNames} role={wrapperRole}>
{leftRender}
<input {...props} ref={ref} className={cx(styles.input, className)} aria-invalid={error} role={inputRole} />
{rightRender}
{renderLeft}
<input
{...props}
ref={ref}
className={cx(styles.input, inputClassName)}
aria-invalid={error}
role={inputRole}
/>
{renderRight}
</div>
);
}
Expand Down
40 changes: 34 additions & 6 deletions packages/core/src/components/BaseInput/BaseInput.types.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,49 @@
import { AriaRole, InputHTMLAttributes, ReactNode } from "react";
import { VibeComponentProps } from "../../types";
import { BASE_SIZES } from "../../constants";
import VibeComponent from "../../types/VibeComponent";

export type InputSize = (typeof BASE_SIZES)[keyof typeof BASE_SIZES];
type BaseInputNativeInputProps = Omit<InputHTMLAttributes<HTMLInputElement>, "size" | "role">;
type Renderer = ReactNode | ReactNode[];

export interface BaseInputProps extends BaseInputNativeInputProps, VibeComponentProps {
/**
* Size of the input element. Will influence also padding and font size.
*/
size?: InputSize;
leftRender?: Renderer;
rightRender?: Renderer;
/**
* A render prop function for adding a component or element to the left side of the input.
* This could be an icon, text, or any custom element that fits within the input's design.
*/
renderLeft?: Renderer;
/**
* Similar to renderLeft, but for adding an element to the right side of the input.
* Useful for clear buttons, password visibility toggles, or custom validation icons.
*/
renderRight?: Renderer;
/**
* When true, indicates that the input has successfully passed validation or meets some criteria.
* This control the visual styling of the input to convey success to the user.
*/
success?: boolean;
/**
* When true, indicates that there is an error with the input's current value.
* This control the visual styling of the input to convey error to the user.
*/
error?: boolean;
/**
* ARIA role for the input wrapper. This can be used to improve accessibility by
* giving screen readers more context about the input's purpose.
*/
wrapperRole?: AriaRole;
/**
* ARIA role for the input. Setting this helps in making the input more
* accessible by providing additional semantic information to assistive technologies.
*/
inputRole?: AriaRole;
wrapperClassName?: string;
/**
* Additional CSS class names to be applied to the input element. This allows for custom
* styling on top of the default styles provided by the component.
*/
inputClassName?: string;
}

export type BaseInputComponent = VibeComponent<BaseInputProps, HTMLInputElement>;
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ describe("BaseInput", () => {
});

it("should show left and right elements when provided", () => {
const leftRender = <div>Left</div>;
const rightRender = <div>Right</div>;
const { getByText } = renderBaseInput({ leftRender, rightRender });
const renderLeft = <div>Left</div>;
const renderRight = <div>Right</div>;
const { getByText } = renderBaseInput({ renderLeft, renderRight });

expect(getByText("Left")).toBeInTheDocument();
expect(getByText("Right")).toBeInTheDocument();
Expand All @@ -42,7 +42,7 @@ describe("BaseInput", () => {
});

it("should apply the className for input and wrapperClassName for wrapper", () => {
const { getByLabelText } = renderBaseInput({ className: "inputClass", wrapperClassName: "customWrapper" });
const { getByLabelText } = renderBaseInput({ className: "customWrapper", inputClassName: "inputClass" });
expect(getByLabelText("base-input")).toHaveClass("inputClass");
expect(getByLabelText("base-input").parentNode).toHaveClass("customWrapper");
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Chips from "../Chips";
import Text from "../../Text/Text";
import { createStoryMetaSettingsDecorator } from "../../../storybook";
import { createComponentTemplate } from "vibe-storybook-components";
import Search from "../../Search/Search";
import LegacySearch from "../../LegacySearch/LegacySearch";
import Avatar from "../../Avatar/Avatar";
import DialogContentContainer from "../../DialogContentContainer/DialogContentContainer";
import { Email } from "../../Icon/Icons";
Expand Down Expand Up @@ -187,7 +187,7 @@ export const ColorfulChipsForDifferentContent = {
<div className={styles.item}>
<Chips label="January" color={Chips.colors.POSITIVE} />
</div>
<Search />
<LegacySearch />
<div className={styles.item}>
<Chips label="August" readOnly color={Chips.colors.LIPSTICK} />
</div>
Expand All @@ -206,7 +206,7 @@ export const ColorfulChipsForDifferentContent = {
export const ChipsInAPersonPickerComboBox = {
render: () => (
<DialogContentContainer className={styles.searchBar}>
<Search placeholder="Search names, positions, or a team" />
<LegacySearch placeholder="Search names, positions, or a team" />
<Flex align={Flex.align.CENTER} justify={Flex.justify.CENTER}>
<Chips label="Esther Schanler" leftAvatar={person1} />
<Chips label="Rotem Dekel" leftAvatar={rotem} />
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/components/Combobox/Combobox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { isFunction, noop as NOOP } from "lodash-es";
import { getStyle } from "../../helpers/typesciptCssModulesHelper";
import { ComponentDefaultTestId, getTestId } from "../../tests/test-ids-utils";
import useMergeRef from "../../hooks/useMergeRef";
import Search from "../Search/Search";
import LegacySearch from "../LegacySearch/LegacySearch";
import { BASE_SIZES } from "../../constants";
import Button from "../Button/Button";
import Text from "../Text/Text";
Expand Down Expand Up @@ -283,7 +283,7 @@ const Combobox: React.FC<ComboboxProps> & {
ellipsis={false}
>
<div className={styles.comboboxList} style={{ maxHeight: optionsListHeight }} role="listbox">
<Search
<LegacySearch
ref={inputRef}
value={filterValue}
wrapperClassName={cx(styles.comboboxSearchWrapper, searchWrapperClassName)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { ONE_LINE_ELLIPSIS_TEST_ID, OVERFLOW_TITLE_CONTAINER_ID } from "../__tes
import { headingOverflowSuite } from "../__tests__/Heading.interactions";
import Divider from "../../Divider/Divider";
import Text from "../../Text/Text";
import Search from "../../Search/Search";
import LegacySearch from "../../LegacySearch/LegacySearch";
import Checkbox from "../../Checkbox/Checkbox";
import Button from "../../Button/Button";
import { Custom } from "../../Icon/Icons";
Expand Down Expand Up @@ -156,7 +156,7 @@ export const BuiltInPageHeaderNotEditable = {
</Heading>
<Divider className={styles.pageDivider} />
<Flex align={Flex.align.CENTER} gap={Flex.gaps.SMALL} aria-labelledby="my-work-id">
<Search wrapperClassName={styles.pageHeaderSearch} placeholder="Search" />
<LegacySearch wrapperClassName={styles.pageHeaderSearch} placeholder="Search" />
<Checkbox label="Hide done items" checked />
<Button leftIcon={Custom} kind={Button.kinds.TERTIARY}>
Customize
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/components/Icon/__stories__/IconsList.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useState } from "react";
import { iconsMetaData } from "monday-ui-style/src/Icons/iconsMetaData";
import Search from "../../Search/Search";
import LegacySearch from "../../LegacySearch/LegacySearch";
import * as allIcons from "../Icons";
import Flex from "../../Flex/Flex";
import styles from "./Icon.stories.module.scss";
Expand All @@ -18,7 +18,7 @@ export default function IconsList() {

return (
<section className={styles.wrapper}>
<Search value={query} onChange={setQuery} placeholder="Search for icons" wrapperClassName={styles.search} />
<LegacySearch value={query} onChange={setQuery} placeholder="Search for icons" wrapperClassName={styles.search} />
<div className={styles.grid}>
{iconsMetaData
.filter((icon: IconMeta) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Heading from "../LegacyHeading";
import { createStoryMetaSettingsDecorator } from "../../../storybook";
import Divider from "../../Divider/Divider";
import Search from "../../Search/Search";
import LegacySearch from "../../LegacySearch/LegacySearch";
import Checkbox from "../../Checkbox/Checkbox";
import Button from "../../Button/Button";
import Flex from "../../Flex/Flex";
Expand Down Expand Up @@ -127,7 +127,7 @@ export const NotEditableHeaderOfAPage = {
<Heading type={Heading.types.h1} value="My Work" id="my-work-id" />
<Divider />
<Flex align={Flex.align.CENTER} gap={Flex.gaps.SMALL} aria-labelledby="my-work-id">
<Search wrapperClassName={styles["page-header_search"]} placeholder="Search" />
<LegacySearch wrapperClassName={styles["page-header_search"]} placeholder="Search" />
<Checkbox label="Hide done items" checked />
<Button leftIcon={Custom} kind={Button.kinds.TERTIARY}>
Customize
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
.searchWrapper input[type="search"] {
-webkit-appearance: textfield;
}

.searchWrapper input[type="search"]::-webkit-search-decoration,
.searchWrapper input[type="search"]::-webkit-search-cancel-button,
.searchWrapper input[type="search"]::-webkit-search-results-button,
.searchWrapper input[type="search"]::-webkit-search-results-decoration {
-webkit-appearance: none;
}

.searchWrapper:focus-within .searchFocusElementFirst {
animation: dashForward 5s linear forwards;
}

.searchWrapper:focus-within .searchFocusElementSecond {
animation: dashBackwards 5s linear forwards;
}

.search.round {
border-radius: 50px !important;
}

@keyframes dashForward {
to {
stroke-dashoffset: 0;
}
}

@keyframes dashBackwards {
to {
stroke-dashoffset: 2000;
}
}
Loading