Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
72 changes: 71 additions & 1 deletion docs/docs/components/select.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { Select } from "@hover-design/react";
### Code Snippets and Examples

import "@hover-design/react/dist/style.css";
import { Select } from "@hover-design/react";
import { Select, Loader } from "@hover-design/react";
import { useState } from "react";

##### Select Default
Expand Down Expand Up @@ -146,6 +146,67 @@ const options = [
]}
/>

##### Select Loading

```jsx
const options = [
{ label: "First", value: "first" },
{ label: "Second", value: "second", disabled: true },
{ label: "Third", value: "third" },
{ label: "Fourth", value: "fourth" },
];

<div className="App">
<Select options={options} isLoading />
</div>;
```

<Select
width="40%"
isLoading
options={[
{ label: "First", value: "first" },
{ label: "Second", value: "second", disabled: true },
{ label: "Third", value: "third" },
{ label: "Fourth", value: "fourth" },
]}
/>

##### Select with Loading Options

```jsx
const options = [
{ label: "First", value: "first" },
{ label: "Second", value: "second", disabled: true },
{ label: "Third", value: "third" },
{ label: "Fourth", value: "fourth" },
];

const loadingOptions = {
loadingContent: "Data is Loading",
loader: <Loader color="orange" />,
}

<div className="App">
<Select options={options} isLoading loadingOptions={loadingOptions} />
</div>;
```

<Select
width="40%"
isLoading
loadingOptions={{
loadingContent: "Data is Loading",
loader: <Loader color="orange" />,
}}
options={[
{ label: "First", value: "first" },
{ label: "Second", value: "second", disabled: true },
{ label: "Third", value: "third" },
{ label: "Fourth", value: "fourth" },
]}
/>

##### Select Disabled

```jsx
Expand Down Expand Up @@ -263,6 +324,8 @@ const options = [
| DropIcon | `JSX Element` | | Yes |
| onDropDownOpen | `()=> void ` | | Yes |
| onDropDownClose | `()=> void ` | | Yes |
| isLoading | `boolean` | `false` | Yes |
| loadingOptions | **[Loading Options](#loading-option)** | `false` | Yes |

### Option Object

Expand All @@ -273,6 +336,13 @@ const options = [
| disabled | `boolean` | Yes |
| ref | `MutableRefObject<HTMLDivElement>` | Yes |

### Loading Option

| Key | type | Optional ? |
| :------------- | :---------: | ---------: |
| loadingContent | `ReactNode` | Yes |
| loader | `ReactNode` | Yes |

### Keyboard Controls

> Keyboard controls will only work when the ** Select ** is focused (selected)
Expand Down
120 changes: 68 additions & 52 deletions lib/src/components/Select/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,11 @@ import {
noDataFoundStyles,
selectPlaceholderRecipe,
inputRecipe,
loadingContentContainer,
} from "./select.css";
import { SelectPropsType, OptionsType } from "./select.types";
import "./select.global.styles.css";
import { Loader } from "../Loader";

const SelectComponent: ForwardRefRenderFunction<
HTMLDivElement,
Expand All @@ -55,6 +57,8 @@ const SelectComponent: ForwardRefRenderFunction<
style,
onDropDownClose = () => {},
onDropDownOpen = () => {},
isLoading = false,
loadingOptions,
},
ref
) => {
Expand Down Expand Up @@ -379,6 +383,52 @@ const SelectComponent: ForwardRefRenderFunction<
isMulti,
});

const renderDropDown = () => {
return Array.isArray(internalOptions) && internalOptions?.length !== 0 ? (
internalOptions.map((option, ind) => {
const selectListClass = selectListRecipe({
disabled: option.disabled,
active:
!isMulti &&
!Array.isArray(selectValue) &&
option.value === selectValue?.value,
});
return (
<div
key={ind}
ref={option.ref}
role="option"
data-value={option.value}
aria-selected={
!Array.isArray(selectValue) && option.value === selectValue?.value
}
className={selectListClass}
onClick={(event) =>
!option.disabled && internalClickHandler(option, event)
}
onMouseEnter={(event) => {
if (!option.disabled) {
setCursor(ind);
focusElement(ind);
}
}}
onMouseLeave={(event) => {
event.currentTarget.setAttribute("data-hover", "false");
}}
>
<span>{option.label}</span>
</div>
);
})
) : (
<div className={noDataFoundStyles}>
{checkIfAllValuesSelected()
? "No more Data!"
: nothingFoundLabel || "Nothing Found!"}
</div>
);
};

useClickOutside(
selectRef,
() => {
Expand Down Expand Up @@ -462,17 +512,20 @@ const SelectComponent: ForwardRefRenderFunction<
</div>
))}
</Flex>

<Flex
alignItems="center"
className={selectIconClass}
onClick={handleIconClick}
>
{DropIcon
? !isClearable && DropIcon
: !isClearable && <ArrowDown width={18} height={18} />}
{isClearable && <Clear width={18} height={18} />}
</Flex>
{!isLoading ? (
<Flex
alignItems="center"
className={selectIconClass}
onClick={handleIconClick}
>
{DropIcon
? !isClearable && DropIcon
: !isClearable && <ArrowDown width={18} height={18} />}
{isClearable && <Clear width={18} height={18} />}
</Flex>
) : (
loadingOptions?.loader || <Loader color={color} />
)}
</Flex>

{isDropped && (
Expand All @@ -482,48 +535,11 @@ const SelectComponent: ForwardRefRenderFunction<
className={`${selectListContainerStyle}`}
role={"listbox"}
>
{Array.isArray(internalOptions) && internalOptions?.length !== 0 ? (
internalOptions.map((option, ind) => {
const selectListClass = selectListRecipe({
disabled: option.disabled,
active:
!isMulti &&
!Array.isArray(selectValue) &&
option.value === selectValue?.value,
});
return (
<div
key={ind}
ref={option.ref}
role="option"
data-value={option.value}
aria-selected={
!Array.isArray(selectValue) &&
option.value === selectValue?.value
}
className={selectListClass}
onClick={(event) =>
!option.disabled && internalClickHandler(option, event)
}
onMouseEnter={(event) => {
if (!option.disabled) {
setCursor(ind);
focusElement(ind);
}
}}
onMouseLeave={(event) => {
event.currentTarget.setAttribute("data-hover", "false");
}}
>
<span>{option.label}</span>
</div>
);
})
{!isLoading ? (
renderDropDown()
) : (
<div className={noDataFoundStyles}>
{checkIfAllValuesSelected()
? "No more Data!"
: nothingFoundLabel || "Nothing Found!"}
<div className={loadingContentContainer}>
{loadingOptions?.loadingContent || "Loading..."}
</div>
)}
</Flex>
Expand Down
5 changes: 5 additions & 0 deletions lib/src/components/Select/select.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,3 +169,8 @@ export const inputTextContainer = style({
overflow: "hidden",
height: "100%",
});

export const loadingContentContainer = style({
padding: "10px 16px",
cursor: "default",
});
7 changes: 6 additions & 1 deletion lib/src/components/Select/select.types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { KeyboardEvent, MouseEvent, MutableRefObject } from "react";
import { KeyboardEvent, MouseEvent, MutableRefObject, ReactNode } from "react";
type divType = Omit<JSX.IntrinsicElements["div"], "onChange">;
export type SelectPropsType = divType & {
placeholder?: string;
Expand All @@ -24,6 +24,11 @@ export type SelectPropsType = divType & {
error?: boolean | string;
onDropDownClose?: () => void;
onDropDownOpen?: () => void;
isLoading?: boolean;
loadingOptions?: {
loadingContent?: ReactNode;
loader?: ReactNode;
};
};

export type OptionsType = {
Expand Down