diff --git a/README.md b/README.md index 147c77e..6a25917 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,7 @@ Check out these demos: - [`useBasicStyles`](#usebasicstyles--default-false) - [`selectedOptionStyle`](#selectedoptionstyle--options-color--check--default-color) - [`selectedOptionColor`](#selectedoptioncolor--default-blue) + - [`variant`](#variant--options-outline--filled--flushed--unstyled--default-outline) - [`hasStickyGroupHeaders`](#hasstickygroupheaders--default-false) - [`isFixed`](#isfixed) - [Styling](#styling) @@ -270,6 +271,35 @@ return ( [![CS-JS]](https://codesandbox.io/s/chakra-react-select-border-selectedoptioncolor-yyd321?file=/example.js) +#### `variant` — Options: `outline` | `filled` | `flushed` | `unstyled` — Default: `outline` + +You can pass the `variant` prop with any of `outline`, `filled`, `flushed`, or `unstyled` to change the overall styling of the `Select`. These will reflect the various appearances available for [Chakra's `` component](https://chakra-ui.com/docs/components/input#changing-the-size-of-the-input). + +```js +return ( + <> + + + +); +``` + +![variant in light mode](./github/variant-light.png) + +![variant in dark mode](./github/variant-dark.png) + +By default, the `flushed` and `unstyled` variants look a bit strange in combination with the `DropdownIndicator`. An easy way to make these styles look more natural is to pass the [`useBasicStyles`](#usebasicstyles--default-false) prop along with them to remove the background from the indicator. Or alternatively, you could hide the indicator completely using [`chakraStyles`](#chakrastyles). + +![variant with useBasicStyles](./github/variant-use-basic-styles.png) + +Another thing to note is that the default styling for `variant="filled"` and `isMulti` results in the select and selected option tags having the same background color when the select is not focused. The easiest solution for this is to pass the [`tagVariant`](#tagvariant--options-subtle--solid--outline--default-subtle) or [`colorScheme`](#colorscheme) prop to add some contrast between the two elements. + +![variant with useBasicStyles](./github/filled-variant.png) + +[![CS-JS]](https://codesandbox.io/s/chakra-react-select-variant-5cf755?file=/example.js) + #### `hasStickyGroupHeaders` — Default: `false` One additional feature which isn’t specific to Chakra or react-select is sticky group headers. It adds a border to the bottom of the header and keeps it in view while its corresponding group of options is visible. This can be very nice for when you have long lists of grouped options so you can always tell which group of options you're looking at. To add it, pass the `hasStickyGroupHeaders` prop to the select component. diff --git a/github/filled-variant.png b/github/filled-variant.png new file mode 100644 index 0000000..fdf2b6c Binary files /dev/null and b/github/filled-variant.png differ diff --git a/github/variant-dark.png b/github/variant-dark.png new file mode 100644 index 0000000..d80a3c1 Binary files /dev/null and b/github/variant-dark.png differ diff --git a/github/variant-light.png b/github/variant-light.png new file mode 100644 index 0000000..70558cb Binary files /dev/null and b/github/variant-light.png differ diff --git a/github/variant-use-basic-styles.png b/github/variant-use-basic-styles.png new file mode 100644 index 0000000..7c92407 Binary files /dev/null and b/github/variant-use-basic-styles.png differ diff --git a/src/chakra-components/containers.tsx b/src/chakra-components/containers.tsx index 992d76a..dfdca53 100644 --- a/src/chakra-components/containers.tsx +++ b/src/chakra-components/containers.tsx @@ -1,13 +1,13 @@ import React from "react"; import { Box } from "@chakra-ui/layout"; import type { CSSObject } from "@chakra-ui/system"; +import { useMultiStyleConfig } from "@chakra-ui/system"; import type { ContainerProps, GroupBase, IndicatorsContainerProps, ValueContainerProps, } from "react-select"; -import type { SizeProps } from "../types"; export const SelectContainer = < Option, @@ -69,20 +69,22 @@ export const ValueContainer = < isMulti, hasValue, innerProps, - selectProps: { size, chakraStyles }, + selectProps: { size, chakraStyles, variant }, } = props; - const px: SizeProps = { - sm: "0.75rem", - md: "1rem", - lg: "1rem", - }; + // Getting the css from input instead of select + // to fit better with each of the variants + const inputStyles = useMultiStyleConfig("Input", { + size, + variant, + }); const initialSx: CSSObject = { display: "flex", alignItems: "center", flex: 1, - padding: `0.125rem ${px[size || "md"]}`, + paddingY: "2px", + paddingX: inputStyles.field.px, flexWrap: "wrap", WebkitOverflowScrolling: "touch", position: "relative", diff --git a/src/chakra-components/control.tsx b/src/chakra-components/control.tsx index 03824d9..ffe625c 100644 --- a/src/chakra-components/control.tsx +++ b/src/chakra-components/control.tsx @@ -37,6 +37,7 @@ const Control = < chakraStyles, focusBorderColor, errorBorderColor, + variant, }, } = props; @@ -44,6 +45,7 @@ const Control = < focusBorderColor, errorBorderColor, size, + variant, }); const heights: SizeProps = { @@ -100,12 +102,12 @@ export const IndicatorSeparator = < const { className, cx, - selectProps: { chakraStyles, useBasicStyles }, + selectProps: { chakraStyles, useBasicStyles, variant }, } = props; const initialSx: CSSObject = { opacity: 1, - ...(useBasicStyles && { display: "none" }), + ...(useBasicStyles || variant !== "outline" ? { display: "none" } : {}), }; const sx = chakraStyles?.indicatorSeparator diff --git a/src/module-augmentation.ts b/src/module-augmentation.ts index 66718d6..683d9b1 100644 --- a/src/module-augmentation.ts +++ b/src/module-augmentation.ts @@ -6,6 +6,7 @@ import type { SelectedOptionStyle, Size, TagVariant, + Variant, } from "./types"; /** @@ -157,6 +158,17 @@ declare module "react-select/dist/declarations/src/Select" { * @see {@link https://chakra-ui.com/docs/components/select} */ useBasicStyles?: boolean; + + /** + * The main style variant of the `Select` component + * + * Options: `outline` | `filled` | `flushed` | `unstyled` + * + * @defaultValue `outline` + * @see {@link https://chakra-ui.com/docs/components/select#changing-the-appearance} + * @see {@link https://github.com/csandman/chakra-react-select#variant--options-outline--filled--flushed--unstyled--default-outline} + */ + variant?: Variant; } } diff --git a/src/types.ts b/src/types.ts index 168e2b3..b244d0a 100644 --- a/src/types.ts +++ b/src/types.ts @@ -44,6 +44,8 @@ export type TagVariant = "subtle" | "solid" | "outline"; export type SelectedOptionStyle = "color" | "check"; +export type Variant = "outline" | "filled" | "flushed" | "unstyled"; + export type StylesFunction = ( provided: CSSObject, state: ComponentProps diff --git a/src/use-chakra-select-props.ts b/src/use-chakra-select-props.ts index 0a7d0bf..67f940d 100644 --- a/src/use-chakra-select-props.ts +++ b/src/use-chakra-select-props.ts @@ -1,7 +1,7 @@ import { useFormControl } from "@chakra-ui/form-control"; import type { GroupBase, Props } from "react-select"; import chakraComponents from "./chakra-components"; -import type { SelectedOptionStyle, Size, TagVariant } from "./types"; +import type { SelectedOptionStyle, Size, TagVariant, Variant } from "./types"; const useChakraSelectProps = < Option, @@ -21,6 +21,7 @@ const useChakraSelectProps = < hasStickyGroupHeaders = false, selectedOptionStyle = "color", selectedOptionColor = "blue", + variant = "outline", focusBorderColor, errorBorderColor, chakraStyles = {}, @@ -75,6 +76,17 @@ const useChakraSelectProps = < realSelectedOptionColor = "blue"; } + let realVariant: Variant = variant; + const variantOptions: Variant[] = [ + "outline", + "filled", + "flushed", + "unstyled", + ]; + if (!variantOptions.includes(variant)) { + realVariant = "outline"; + } + const select: Props = { // Allow overriding of custom components components: { @@ -87,6 +99,7 @@ const useChakraSelectProps = < tagVariant: realTagVariant, selectedOptionStyle: realSelectedOptionStyle, selectedOptionColor: realSelectedOptionColor, + variant: realVariant, hasStickyGroupHeaders, chakraStyles, focusBorderColor,