diff --git a/.codesandbox/ci.json b/.codesandbox/ci.json new file mode 100644 index 0000000..4b02a0f --- /dev/null +++ b/.codesandbox/ci.json @@ -0,0 +1,5 @@ +{ + "buildCommand": "build", + "sandboxes": ["65ohb", "vz9ut", "v8lt7q", "h6uwj1"], + "node": "16" +} diff --git a/.eslintrc b/.eslintrc index 785c9c6..936c61e 100644 --- a/.eslintrc +++ b/.eslintrc @@ -24,14 +24,16 @@ }, "project": "tsconfig.eslint.json" }, - "plugins": ["@typescript-eslint"], + "plugins": ["deprecation", "@typescript-eslint"], "rules": { + "deprecation/deprecation": "warn", "no-console": "error", "curly": ["error", "all"], "no-underscore-dangle": "off", "import/prefer-default-export": "off", "react/prop-types": "off", "react/jsx-props-no-spreading": "off", + "react/jsx-key": "error", "react/jsx-filename-extension": [ "error", { @@ -52,6 +54,14 @@ "prefer": "type-imports", "disallowTypeAnnotations": true } + ], + "@typescript-eslint/ban-types": [ + "error", + { + "types": { + "{}": false + } + } ] } } diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index f0e8c50..29d03a8 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -2,7 +2,9 @@ blank_issues_enabled: false contact_links: - name: Feature request url: https://github.com/csandman/chakra-react-select/discussions/categories/ideas - about: Got an idea for a feature or want to propose a change? Then this is the place for you. + about: + Got an idea for a feature or want to propose a change? Then this is the + place for you. - name: Question on usage url: https://github.com/csandman/chakra-react-select/discussions/categories/q-a about: If you have a question regarding the usage of the library. diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 715316b..32d3929 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -23,7 +23,7 @@ jobs: cache: "npm" - name: Install Dependencies - run: npm ci + run: npm install - name: Build package run: npm run build --if-present diff --git a/.github/workflows/package-size-report.yml b/.github/workflows/package-size-report.yml new file mode 100644 index 0000000..9c122a3 --- /dev/null +++ b/.github/workflows/package-size-report.yml @@ -0,0 +1,24 @@ +name: Package Size Report + +on: + pull_request: + branches: [main] + +jobs: + pkg-size-report: + name: Package Size Report + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Setup Node.js + uses: actions/setup-node@v2 + with: + node-version: "16" # ⬅ Specify a version of Node.js to build your app + + - name: Package size report + uses: pkg-size/action@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.prettierrc b/.prettierrc index df5ea0e..f6e8a8d 100644 --- a/.prettierrc +++ b/.prettierrc @@ -11,9 +11,10 @@ "arrowParens": "always", "requirePragma": false, "insertPragma": false, - "proseWrap": "preserve", + "proseWrap": "always", "htmlWhitespaceSensitivity": "css", "endOfLine": "lf", + "plugins": ["@trivago/prettier-plugin-sort-imports"], "importOrder": [ "^react$", "^@chakra-ui/react$", diff --git a/LICENSE.md b/LICENSE.md index 8ceb994..6ec03aa 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -2,20 +2,19 @@ MIT License Copyright (c) 2022 Chris Sandvik -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index 0c24f14..1fbd433 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,38 @@ -[cs-ts-demo]: https://img.shields.io/badge/CodeSandbox-TypeScript-047bd4?logo=codesandbox&style=for-the-badge&labelColor=040404&logoColor=DBDBDB "CodeSandbox TypeScript Demo" -[cs-js-demo]: https://img.shields.io/badge/CodeSandbox-JavaScript-f4dc1b?logo=codesandbox&style=for-the-badge&labelColor=040404&logoColor=DBDBDB "CodeSandbox JavaScript Demo" -[cs-ts]: https://img.shields.io/badge/CodeSandbox-TypeScript-047bd4?logo=codesandbox&style=flat&labelColor=040404&logoColor=DBDBDB "CodeSandbox TypeScript Demo" -[cs-js]: https://img.shields.io/badge/CodeSandbox-JavaScript-f4dc1b?logo=codesandbox&style=flat&labelColor=040404&logoColor=DBDBDB "CodeSandbox JavaScript Demo" +[cs-ts-demo]: + https://img.shields.io/badge/CodeSandbox-TypeScript-047bd4?logo=codesandbox&style=for-the-badge&labelColor=040404&logoColor=DBDBDB + "CodeSandbox TypeScript Demo" +[cs-js-demo]: + https://img.shields.io/badge/CodeSandbox-JavaScript-f4dc1b?logo=codesandbox&style=for-the-badge&labelColor=040404&logoColor=DBDBDB + "CodeSandbox JavaScript Demo" +[cs-ts]: + https://img.shields.io/badge/CodeSandbox-TypeScript-047bd4?logo=codesandbox&style=flat&labelColor=040404&logoColor=DBDBDB + "CodeSandbox TypeScript Demo" +[cs-js]: + https://img.shields.io/badge/CodeSandbox-JavaScript-f4dc1b?logo=codesandbox&style=flat&labelColor=040404&logoColor=DBDBDB + "CodeSandbox JavaScript Demo" # chakra-react-select v4 -> This version of `chakra-react-select` is updated for [Chakra UI v2](https://chakra-ui.com/getting-started/migration) which works exclusively with React v18. `chakra-react-select` v3 will be maintained until the majority of users have migrated. If you're still using Chakra UI v1 check [the docs for chakra-react-select v3 here](https://github.com/csandman/chakra-react-select/tree/v3). +> This version of `chakra-react-select` is updated for +> [Chakra UI v2](https://chakra-ui.com/getting-started/migration) which works +> exclusively with React v18. `chakra-react-select` v3 will be maintained until +> the majority of users have migrated. If you're still using Chakra UI v1 check +> [the docs for chakra-react-select v3 here](https://github.com/csandman/chakra-react-select/tree/v3). [![](https://github.com/csandman/chakra-react-select/actions/workflows/build.yml/badge.svg?branch=main "Build Status")](https://github.com/csandman/chakra-react-select/actions/workflows/build.yml?query=branch%3Amain) [![](https://github.com/csandman/chakra-react-select/actions/workflows/lint.yml/badge.svg?branch=main "Lint Status")](https://github.com/csandman/chakra-react-select/actions/workflows/lint.yml?query=branch%3Amain) [![](https://img.shields.io/npm/v/chakra-react-select "chakra-react-select npm")](https://www.npmjs.com/package/chakra-react-select) [![](https://badgen.net/bundlephobia/min/chakra-react-select "Minified Bundle Size")](https://bundlephobia.com/result?p=chakra-react-select) [![](https://badgen.net/bundlephobia/minzip/chakra-react-select "Minzipped Bundle Size")](https://bundlephobia.com/result?p=chakra-react-select) -[![](https://badgen.net/npm/dt/chakra-react-select?color=blue "Total NPM Downloads")](https://www.npmjs.com/package/chakra-react-select) +[![](https://badgen.net/npm/dt/chakra-react-select?color=blue&icon=npm "Total NPM Downloads")](https://npm-stat.com/charts.html?package=chakra-react-select&from=2021-09-13) +[![](https://badgen.net/npm/dw/chakra-react-select?color=blue&icon=npm "Weekly NPM Downloads")](https://npm-stat.com/charts.html?package=chakra-react-select&from=2021-09-13) [![](https://snyk.io/test/github/csandman/chakra-react-select/badge.svg "Known Vulnerabilities")](https://snyk.io/test/github/csandman/chakra-react-select) [![](https://img.shields.io/badge/Code_Style-prettier-c596c7.svg?logo=prettier "Code Style: Prettier")](https://github.com/prettier/prettier) [![](https://badgen.net/github/license/csandman/chakra-react-select "MIT License")](LICENSE.md) -This component is a wrapper for the popular react component [react-select](https://react-select.com/home) made using the UI library [Chakra UI](https://chakra-ui.com/). +This component is a wrapper for the popular react component +[react-select](https://react-select.com/home) made using the UI library +[Chakra UI](https://chakra-ui.com/). ![Chakra React Select Banner](./github/chakra-react-select.png) @@ -26,22 +41,25 @@ Check out these demos: [![CS-JS-demo]](https://codesandbox.io/s/chakra-react-select-demo-65ohb?file=/example.js) [![CS-TS-demo]](https://codesandbox.io/s/chakra-react-select-ts-demo-vz9ut?file=/app.tsx) -**NOTE:** Before leaving an issue on this project, remember that this is just a _wrapper_ for `react-select`, not a standalone package. A large percent of the questions people have end up being about how `react-select` itself works, so please read through their documentation to familiarize yourself with it! https://react-select.com/home +**NOTE:** Before leaving an issue on this project, remember that this is just a +_wrapper_ for `react-select`, not a standalone package. A large percentage of +the questions people have end up being about how `react-select` itself works, so +please read through their documentation to familiarize yourself with it! +https://react-select.com/home ## Contents - [Usage](#usage) - [Extra Props](#extra-props) - - [`size`](#size--options-sm-md-lg--default-md) + - [`size`](#size--options-responsivevaluesm--md--lg--default-md) - [`colorScheme`](#colorscheme) - - [`tagVariant`](#tagvariant--options-subtle-solid-outline--default-subtle) - - [`isInvalid`](#isinvalid--default-false) + - [`tagVariant`](#tagvariant--options-subtle--solid--outline--default-subtle) + - [`isInvalid` / `isReadOnly`](#isinvalid--default-false--isreadonly---default-false) - [`focusBorderColor` / `errorBorderColor`](#focusbordercolor--default-blue500--errorbordercolor--default-red500) - [`useBasicStyles`](#usebasicstyles--default-false) - - [`hasStickyGroupHeaders`](#hasstickygroupheaders--default-false) - - [`selectedOptionStyle`](#selectedoptionstyle--options-color-check--default-color) - - [`selectedOptionColor`](#selectedoptioncolor--default-blue) - - [`isFixed`](#isfixed) + - [`selectedOptionStyle`](#selectedoptionstyle--options-color--check--default-color) + - [`selectedOptionColorScheme`](#selectedoptioncolorscheme--default-blue) + - [`variant`](#variant--options-outline--filled--flushed--unstyled--default-outline) - [Styling](#styling) - [`chakraStyles`](#chakrastyles) - [Caveats](#caveats) @@ -59,7 +77,12 @@ Check out these demos: ## Usage -In order to use this package, you'll need to have `@chakra-ui/react@2` set up [like in the guide in their docs](https://chakra-ui.com/getting-started). If you already have `@chakra-ui/react@1` set up you can follow the steps in [the official migration guide](https://chakra-ui.com/getting-started/migration) to update to v2. If you don't have Chakra UI installed already, you can install it like this: +To use this package, you'll need to have `@chakra-ui/react@2` set up +[like in the guide in their docs](https://chakra-ui.com/getting-started). If you +already have `@chakra-ui/react@1` set up you can follow the steps in +[the official migration guide](https://chakra-ui.com/getting-started/migration) +to update to v2. If you don't have Chakra UI installed already, you can install +it like this: ```sh npm i @chakra-ui/react @emotion/react@^11.8.1 @emotion/styled@^11 framer-motion@^6 @@ -67,9 +90,14 @@ npm i @chakra-ui/react @emotion/react@^11.8.1 @emotion/styled@^11 framer-motion@ yarn add @chakra-ui/react @emotion/react@^11.8.1 @emotion/styled@^11 framer-motion@^6 ``` -**NOTE:** As of [`v3.3.3`](https://github.com/csandman/chakra-react-select/releases/tag/v3.3.3), your project will need to have a minimum of `@emotion/react@11.8.1` installed in order to avoid having multiple copies of `@emotion/react` installed. For more info, see [PR #115](https://github.com/csandman/chakra-react-select/pull/115). +**NOTE:** As of +[`v3.3.3`](https://github.com/csandman/chakra-react-select/releases/tag/v3.3.3), +your project will need to have a minimum of `@emotion/react@11.8.1` installed to +avoid having multiple copies of `@emotion/react` installed. For more info, see +[PR #115](https://github.com/csandman/chakra-react-select/pull/115). -After Chakra UI is setup, [install this package from NPM](https://www.npmjs.com/package/chakra-react-select): +After Chakra UI is set up, +[install this package from NPM](https://www.npmjs.com/package/chakra-react-select): ```sh npm i chakra-react-select @@ -77,7 +105,8 @@ npm i chakra-react-select yarn add chakra-react-select ``` -Once installed, you can import the base select package, the async select, the creatable select or the async creatable select like so: +Once installed, you can import the base select package, the async select, the +creatable select or the async creatable select like so: ```js import { @@ -95,15 +124,31 @@ const { } = require("chakra-react-select"); ``` -All of the types and other exports from the original `react-select` package are also exported from this package, so you can import any of them if you need them. +All exports, including types, from the original `react-select` package are also +exported from this package, so you can import any of them if you need them. The +only exception is the root `Select` components. -In order to use this component, you can implement it and use it like you would normally use [react-select](https://react-select.com/home). It should accept almost all of the props that the original takes, with a few additions and exceptions listed below. +Implementing this component in your application should be almost identical to +how you'd normally use [react-select](https://react-select.com/home). It will +accept all of the props that the original package does, with a few additions and +exceptions listed below. So if you have a question on basic usage, your best bet +is to check the original docs or google "How to (some functionality) with +react-select" and just swap out `react-select` for `chakra-react-select`. ## Extra Props -#### `size` — Options: `sm`, `md`, `lg` — Default: `md` +#### `size` — Options: `ResponsiveValue<"sm" | "md" | "lg">` — Default: `md` -You can pass the `size` prop with either `sm`, `md`, or `lg` (default is `md`). These will reflect the sizes available on the [Chakra `` component](https://chakra-ui.com/docs/components/input#changing-the-size-of-the-input) (with the exception of `xs` because it's too small to work). +You can pass the `size` prop with either `sm`, `md`, or `lg` (default is `md`). +These will reflect the sizes available on the +[Chakra `` component](https://chakra-ui.com/docs/components/input#changing-the-size-of-the-input) +(except for `xs` because it's too small to work). Alternatively, you can pass a +[responsive style array or object](https://chakra-ui.com/docs/styled-system/responsive-styles) +of `size` values to allow it to change depending on your theme's breakpoints. + +If no `size` is passed, it will default to `defaultProps.size` from the theme +for Chakra's `Input` component. If your component theme for `Input` is not +modified, it will be `md`. ```js return ( @@ -115,11 +160,20 @@ return ( ); ``` +[![CS-JS]](https://codesandbox.io/s/chakra-react-select-sizes-w9sf8e?file=/example.js) + +--- + #### `colorScheme` -You can pass the `colorScheme` prop to the select component to change all of the selected options tags' colors. You can view the whole list of available color schemes in [the Chakra docs](https://chakra-ui.com/docs/components/tag/props), or if you have a custom color palette, any of the custom color names in that will be available instead. +You can pass the `colorScheme` prop to the select component to change all of the +selected options tags' colors. You can view the whole list of available color +schemes in [the Chakra docs](https://chakra-ui.com/docs/components/tag/props), +or if you have a custom color palette, any of the custom color names in that +will be available instead. -Alternatively you can add the `colorScheme` key to any of your options objects and it will only style that option when selected. +Alternatively, you can add the `colorScheme` key to any of your options objects +and it will only style that option when selected. ```js return ( @@ -141,11 +195,21 @@ return ( ); ``` -#### `tagVariant` — Options: `subtle`, `solid`, `outline` — Default: `subtle` +[![CS-JS]](https://codesandbox.io/s/chakra-react-select-color-schemes-c38jlo?file=/example.js) + +--- -You can pass the `tagVariant` prop with either `subtle`, `solid`, or `outline` (default is `subtle`). These will reflect the `variant` prop available on the [Chakra `` component](https://chakra-ui.com/docs/components/tag/props). +#### `tagVariant` — Options: `subtle` | `solid` | `outline` — Default: `subtle` -Alternatively you can add the `variant` key to any of your options objects and it will only style that option when selected. This will override the `tagVariant` prop on the select if both are set +You can pass the `tagVariant` prop with either `subtle`, `solid`, or `outline` +(default is `subtle`). These will reflect the `variant` prop available on the +[Chakra `` component](https://chakra-ui.com/docs/components/tag/props). +Alternatively, if you have added any custom variants to your theme, you can use +those instead. + +Alternatively, you can add the `variant` key to any of your options objects and +it will only style that option when selected. This will override the +`tagVariant` prop on the select if both are set ```js return ( @@ -167,11 +231,20 @@ return ( ); ``` -#### `isInvalid` — Default: `false` +[![CS-JS]](https://codesandbox.io/s/chakra-react-select-tag-variants-w31gnt?file=/example.js) + +--- -You can pass `isInvalid` to the select component to style it like the Chakra `` is styled when it receives the same prop. +#### `isInvalid` — Default: `false` | `isReadOnly` - Default: `false` -You can pass also pass `isInvalid` or `isDisabled` to a wrapping `` and it will output their corresponding `` on the select. +You can pass `isInvalid` to the select component to style it like the Chakra +`Input` is styled when it receives the same prop. Alternatively, you can pass +`isReadOnly` to make the component non-interactive in the same way Chakra's +`Input` does. + +You can pass also pass `isInvalid`, `isDisabled`, or `isReadOnly` into a +wrapping `` to achieve the same result as passing these props +into the `Select` component. ```js return ( @@ -179,7 +252,11 @@ return ( {/* This will show up with a red border */} + + {/* This will show up grayed out and will not be interactive */} + {/* Additionally, it will have a red border and the error message will be shown */} Invalid & Disabled Select ` component](https://chakra-ui.com/docs/components/input#changing-the-focus-and-error-border-colors). +The props `focusBorderColor` and `errorBorderColor` can be passed with Chakra +color strings which will emulate the respective props being passed to +[Chakra's `` component](https://chakra-ui.com/docs/components/input#changing-the-focus-and-error-border-colors). ```js return ( <> + - -); +return ; -``` - -[![CS-JS]](https://codesandbox.io/s/chakra-react-select-hasstickygroupheaders-wg39g?file=/example.js) - -**NOTE:** It has recently been discovered that when using this prop, navigating up through the available options with the arrow key will keep the focused option underneath the header, as it will not scroll enough to account for it being there. So if this is an issue for you, avoid this prop. A fix for this is being investigated. +[![CS-JS]](https://codesandbox.io/s/chakra-react-select-usebasicstyles-jjnqsd?file=/example.js) -![Sticky Group Headers](./github/sticky-group-headers.png) +--- -#### `selectedOptionStyle` — Options: `color`, `check` — Default: `color` +#### `selectedOptionStyle` — Options: `color` | `check` — Default: `color` -In `v1.3.0` you can now pass the prop `selectedOptionStyle` with either `"color"` or `"check"` (defaults to `"color"`). The default option `"color"` will style a selected option similar to how react-select does it, by highlighting the selected option in the color blue. Alternatively if you pass `"check"` for the value, the selected option will be styled like the [Chakra UI Menu component](https://chakra-ui.com/docs/components/menu#menu-option-groups) and include a check icon next to the selected option(s). If `isMulti` and `selectedOptionStyle="check"` are passed, space will only be added for the check marks if `hideSelectedOptions={false}` is also passed. +As of `v1.3.0` you can pass the prop `selectedOptionStyle` with either `"color"` +or `"check"`. The default option `"color"` will style a selected option similar +to how react-select does it, by highlighting the selected option in the color +blue. Alternatively, if you pass `"check"` for the value, the selected option +will be styled like the +[Chakra UI Menu component](https://chakra-ui.com/docs/components/menu#menu-option-groups) +and include a check icon next to the selected option(s). If `isMulti` and +`selectedOptionStyle="check"` are passed, space will only be added for the check +marks if `hideSelectedOptions={false}` is also passed. ```js return ( @@ -251,15 +342,34 @@ return ( ![Check Highlighted Selected Option](./github/check-selected-option.png) -#### `selectedOptionColor` — Default: `blue` +[![CS-JS]](https://codesandbox.io/s/chakra-react-select-border-selectedoptionstyle-yxkcos?file=/example.js) -If you choose to stick with the default `selectedOptionStyle="color"`, you have one additional styling option. If you do not like the default of blue for the highlight color, you can pass the `selectedOptionColor` prop to change it. This prop will accept any named color from your color theme, and it will use the `500` value in light mode or the `300` value in dark mode. +--- + +#### `selectedOptionColorScheme` — Default: `blue` + +If you choose to stick with the default `selectedOptionStyle="color"`, you have +one additional styling option. If you do not like the default of blue for the +highlight color, you can pass the `selectedOptionColorScheme` prop to change it. +This prop will accept any named color from your theme's color palette, and it +will use the `500` value in light mode or the `300` value in dark mode. + +> **NOTE:** This prop can only be used for named colors from your theme, not +> arbitrary hex/rgb colors. If you would like to use a specific color for the +> background that's not a part of your theme, use the +> [`chakraStyles`](#chakrastyles) prop to customize it (see +> [#99](https://github.com/csandman/chakra-react-select/discussions/99) for an +> example). +> +> Prior to `v4.6.0` this prop was named `selectedOptionColor`, and it was +> renamed to prevent confusion about its purpose. `selectedOptionColor` is still +> available but will be removed in the next major version. ```js return ( <> - + ); ``` @@ -268,40 +378,90 @@ return ( ![Purple Selected Option Color (dark mode)](./github/purple-selected-option-dark.png) -#### `isFixed` +[![CS-JS]](https://codesandbox.io/s/chakra-react-select-border-selectedoptioncolor-yyd321?file=/example.js) -In your options objects, you can add the key `isFixed: true` to emulate the example in the [react-select docs](https://react-select.com/home#fixed-options). This will prevent the options which have this flag from having the remove button on its corresponding tag, and it changes the default `tagVariant` for that tag to be solid. This only applies when using `isMulti`. +--- + +#### `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). +Alternatively, if you've added any custom variants to your Chakra theme you can +use those instead. However, it is not guaranteed all styles will be applied how +you intend them to as there are some differences in the structure of the +Select's input component. + +If no `variant` is passed, it will default to `defaultProps.variant` from the +theme for Chakra's `Input` component. If your component theme for `Input` is not +modified, it will be `outline`. ```js return ( - {/* Default */} + + ` element, and there is no key for styling the input itself. With the `chakraStyles` object, the `input` key now styles the actual `` element and there is a new key, `inputContainer`, that styles the surrounding `Box`. Both functions use the `state` argument for the original `input` key. - -There are also two extra style keys for the icons contained within the indicators that are not offered in the original package. These are `downChevron` which is contained inside the `DropdownIndicator`, and the `crossIcon` which is contained inside the `ClearIndicator`. Both styles receive the same `state` values as their containing indicators. These style keys were added as a convenience, however you could also apply the same styles using the parent `chakraStyles` by doing something like this: +One change between the keys in the `chakraStyles` prop and the original `styles` +prop, is that in the original the `input` styles apply to a container +surrounding the HTML `` element, and there is no key for styling the +input itself. With the `chakraStyles` object, the `input` key now styles the +actual `` element and there is a new key, `inputContainer`, that +styles the surrounding `Box`. Both functions use the `state` argument for the +original `input` key. + +There are also two extra style keys for the icons contained within the +indicators that are not offered in the original package. These are `downChevron` +which is contained inside the `DropdownIndicator`, and the `crossIcon` which is +contained inside the `ClearIndicator`. Both styles receive the same `state` +values as their containing indicators. These style keys were added as a +convenience, however you could also apply the same styles using the parent +`chakraStyles` by doing something like this: ```js const chakraStyles = { @@ -386,36 +565,49 @@ const chakraStyles = { [![CS-JS]](https://codesandbox.io/s/chakra-react-select-dropdown-indicator-flip-lhc4ep?file=/example.js) -Additionally, there is one key that is available in the `styles` prop that does not exist in the `chakraStyles` object; `menuPortal`. This key applies to the `MenuPortal` element which is only used when the [`menuPortalTarget`](https://react-select.com/advanced#portaling) prop is passed in. This component is replaceable, however it is very tightly integrated with the menu placement logic (and a context provider) so it appears to be impossible to fully replace it with a chakra component. And in turn, it can't pull a key from the `chakraStyles` prop. Therefor, if you are passing the `menuPortalTarget` prop and would like to change the styles of the `MenuPortal` component, you have two options: +Additionally, there is one key that is available in the `styles` prop that does +not exist in the `chakraStyles` object; `menuPortal`. This key applies to the +`MenuPortal` element which is only used when the +[`menuPortalTarget`](https://react-select.com/advanced#portaling) prop is passed +in. This component is replaceable, however, it is very tightly integrated with +the menu placement logic (and a context provider) so it appears to be impossible +to fully replace it with a chakra component. And in turn, it can't pull a key +from the `chakraStyles` prop. Therefore, if you are passing the +`menuPortalTarget` prop and would like to change the styles of the `MenuPortal` +component, you have two options: -1. Pass the original `styles` prop with the `menuPortal` key. This is the only key in the `styles` object that will be applied to your components. +1. Pass the original `styles` prop with the `menuPortal` key. This is the only + key in the `styles` object that will be applied to your components. ```jsx return ( -) +); ``` ```css @@ -426,7 +618,10 @@ return ( } ``` -If anyone has any suggestions for how to fully replace the `MenuPortal` component, please leave a comment on [this issue](https://github.com/csandman/chakra-react-select/issues/55) or submit a pull request. +If anyone has any suggestions for how to fully replace the `MenuPortal` +component, please leave a comment on +[this issue](https://github.com/csandman/chakra-react-select/issues/55) or +submit a pull request. #### Examples @@ -435,46 +630,73 @@ Dropdown menu attached to control example: [![CS-JS]](https://codesandbox.io/s/chakra-react-select-chakrastyles-vanilla-kgdnf?file=/example.js) [![CS-TS]](https://codesandbox.io/s/chakra-react-select-chakrastyles-5yh6q?file=/app.tsx) -Default [Chakra ``](https://chakra-ui.com/docs/form/select) styles +example: [![CS-JS]](https://codesandbox.io/s/chakra-react-select-styled-like-a-default-chakra-select-vanilla-iydfe?file=/example.js) [![CS-TS]](https://codesandbox.io/s/chakra-react-select-styled-like-a-default-chakra-select-qwq3o?file=/app.tsx) -> _NOTE: This can now be accomplished with the [`useBasicStyles`](#usebasicstyles--default-false) prop_ +> _NOTE: This can now be accomplished with the +> [`useBasicStyles`](#usebasicstyles--default-false) prop_ ### Theme Styles -As mentioned above, a few of the custom components this package implements either use styles from the global [Chakra component theme](https://chakra-ui.com/docs/styled-system/customize-theme#customizing-component-styles) or are themselves those components. As this package pulls directly from your Chakra theme, any changes you make to those components' themes will propagate to the components in this package. Here is a list of all components that will be affected by changes to your global styles: - -| `react-select` component | `chakra-ui` component styles | -| ------------------------ | --------------------------------------------------------------------------------------------------------------- | -| `ClearIndicator` | [`CloseButton`](https://github.com/chakra-ui/chakra-ui/blob/main/packages/theme/src/components/close-button.ts) | -| `Control` | [`Input`](https://github.com/chakra-ui/chakra-ui/blob/main/packages/theme/src/components/input.ts) | -| `DropdownIndicator` | [`InputRightAddon`](https://github.com/chakra-ui/chakra-ui/blob/main/packages/theme/src/components/input.ts) | -| `GroupHeading` | [`Menu` group title](https://github.com/chakra-ui/chakra-ui/blob/main/packages/theme/src/components/menu.ts) | -| `IndicatorSeparator` | [`Divider`](https://github.com/chakra-ui/chakra-ui/blob/main/packages/theme/src/components/divider.ts) | -| `LoadingIndicator` | [`Spinner`](https://github.com/chakra-ui/chakra-ui/blob/main/packages/theme/src/components/spinner.ts) | -| `MenuList` | [`MenuList`](https://github.com/chakra-ui/chakra-ui/blob/main/packages/theme/src/components/menu.ts) | -| `MultiValueContainer` | [`Tag`](https://github.com/chakra-ui/chakra-ui/blob/main/packages/theme/src/components/tag.ts) | -| `MultiValueLabel` | [`TagLabel`](https://github.com/chakra-ui/chakra-ui/blob/main/packages/theme/src/components/tag.ts) | -| `MultiValueRemove` | [`TagCloseButton`](https://github.com/chakra-ui/chakra-ui/blob/main/packages/theme/src/components/tag.ts) | -| `Option` | [`MenuItem`](https://github.com/chakra-ui/chakra-ui/blob/main/packages/theme/src/components/menu.ts) | - -In addition to specific component styles, any changes you make to your global color scheme will also be reflected in these custom components. - -**NOTE:** Only make changes to your global component themes if you want them to appear in all instances of that component. Otherwise, just change the individual components' styles using the `chakraStyles` prop. +As mentioned above, a few of the custom components this package implements +either use styles from the global +[Chakra component theme](https://chakra-ui.com/docs/styled-system/customize-theme#customizing-component-styles) +or are themselves those components. As this package pulls directly from your +Chakra theme, any changes you make to those components' themes will propagate to +the components in this package. + +**NOTE:** Some of the theme styles are manually overridden when this package +implements them. This is necessary for implementing styles for +[`size`](#size--options-sm--md--lg--default-md) variants in components that do +not natively have them in Chakra's default theme. This mostly concerns +components that make up the `Menu`, but there are a few other cases where this +exception applies. There is no alternative to this currently, so if your custom +theme styles are not being applied correctly please use +[`chakraStyles`](#chakrastyles) to style your components instead. `chakraStyles` +always takes the highest priority in overriding the styles of a component. See +#194 for more info. + +Here is a list of all components that will be affected by changes to your theme: + +| `react-select` component | `chakra-ui` component styles | +| ------------------------ | -------------------------------------------------------------------------------------------------------------------------- | +| `ClearIndicator` | [`CloseButton`](https://github.com/chakra-ui/chakra-ui/blob/main/packages/components/theme/src/components/close-button.ts) | +| `Control` | [`Input`](https://github.com/chakra-ui/chakra-ui/blob/main/packages/components/theme/src/components/input.ts) | +| `DropdownIndicator` | [`InputRightAddon`](https://github.com/chakra-ui/chakra-ui/blob/main/packages/components/theme/src/components/input.ts) | +| `GroupHeading` | [`Menu` group title](https://github.com/chakra-ui/chakra-ui/blob/main/packages/components/theme/src/components/menu.ts) | +| `LoadingIndicator` | [`Spinner`](https://github.com/chakra-ui/chakra-ui/blob/main/packages/components/theme/src/components/spinner.ts) | +| `MenuList` | [`MenuList`](https://github.com/chakra-ui/chakra-ui/blob/main/packages/components/theme/src/components/menu.ts) | +| `MultiValueContainer` | [`Tag`](https://github.com/chakra-ui/chakra-ui/blob/main/packages/components/theme/src/components/tag.ts) | +| `MultiValueLabel` | [`TagLabel`](https://github.com/chakra-ui/chakra-ui/blob/main/packages/components/theme/src/components/tag.ts) | +| `MultiValueRemove` | [`TagCloseButton`](https://github.com/chakra-ui/chakra-ui/blob/main/packages/components/theme/src/components/tag.ts) | +| `Option` | [`MenuItem`](https://github.com/chakra-ui/chakra-ui/blob/main/packages/components/theme/src/components/menu.ts) | + +In addition to specific component styles, any changes you make to your global +color scheme will also be reflected in these custom components. + +**NOTE:** Only make changes to your global component themes if you want them to +appear in all instances of that component. Otherwise, just change the individual +components' styles using the `chakraStyles` prop. ### `className` -This package implements the same classNames on the sub components as the original package so you can use these to style sub-components with CSS. Here is an excerpt from [the react-select docs](https://react-select.com/styles#using-classnames) describing how it works: +This package implements the same classNames on the sub components as the +original package so you can use these to style sub-components with CSS. Here is +an excerpt from +[the react-select docs](https://react-select.com/styles#using-classnames) +describing how it works: -> If you provide the `className` prop to react-select, the SelectContainer will be given a className based on the provided value. +> If you provide the `className` prop to react-select, the SelectContainer will +> be given a className based on the provided value. > -> If you provide the `classNamePrefix` prop to react-select, all inner elements will be given a className -> with the provided prefix. +> If you provide the `classNamePrefix` prop to react-select, all inner elements +> will be given a className with the provided prefix. > -> For example, given `className='react-select-container'` and `classNamePrefix="react-select"`, -> the DOM structure is similar to this: +> For example, given `className='react-select-container'` and +> `classNamePrefix="react-select"`, the DOM structure is similar to this: > > ```html >
@@ -490,7 +712,10 @@ This package implements the same classNames on the sub components as the origina >
> ``` > -> While we encourage you to use the new Styles API, you still have the option of styling via CSS classes. This ensures compatibility with [styled components](https://www.styled-components.com/), [CSS modules](https://github.com/css-modules/css-modules) and other libraries. +> While we encourage you to use the new Styles API, you still have the option of +> styling via CSS classes. This ensures compatibility with +> [styled components](https://www.styled-components.com/), +> [CSS modules](https://github.com/css-modules/css-modules) and other libraries. Here is an example of using classNames to style the components: @@ -498,19 +723,50 @@ Here is an example of using classNames to style the components: ## TypeScript Support -This package has always supported typescript, however until `3.0.0` none of the type inference was working on the props passed into this component. Now that they are, you may need to pass in some generics in order for your component to work properly. +This package has always supported typescript, however until `3.0.0` none of the +type inference was working on the props passed into this component. Now that +they are, you may need to pass in some generics for your component to work +properly, but **in most cases you shouldn't need to**. Here is a snippet from +the original documentation on the subject: -This package exports all of the named module members of the original `react-select` in case you need their built in types in any of your variable declarations. The root select `Props` type that is exported by `react-select` has been extended using module augmentation,[[1]](https://react-select.com/typescript#custom-select-props)[[2]](https://github.com/JedWatson/react-select/issues/4804#issuecomment-927223471) so if you import that type it will include all of the extra props offered. This package also exports a few custom types that are specific to the custom props offered by this package: - -- `ChakraStylesConfig` — The type for the prop `chakraStyles` that can be passed to customize the component styles. This is almost identical to the built in `StylesConfig` type, however it uses Chakra's [`CSSObject`](https://github.com/chakra-ui/chakra-ui/blob/790d2417a3f5d59e2d69229a027af671c2dc0cbc/packages/styled-system/src/system.types.ts#L81) type instead of react-select's emotion styles. -- `OptionBase` — A type for your individual select options that includes the custom props for styling each of your selected options. This type is made to give you a base to extend off of and pass in as a generic to the root `Select` component. +> ### Select generics +> +> There are three generics used by the Select component: `Option`, `IsMulti`, +> and `Group`. All of them are optional and TypeScript attempts to detect them +> automatically, but sometimes it might need some help. Many of the +> `react-select` types include the three generics like this: +> +> — https://react-select.com/typescript + +Read their [full documentation](https://react-select.com/typescript) on the +topic for more info. + +This package exports all of the named module members of the original +`react-select` in case you need their built-in types in any of your variable +declarations. The root select `Props` type that is exported by `react-select` +has been extended using module +augmentation,[[1]](https://react-select.com/typescript#custom-select-props)[[2]](https://github.com/JedWatson/react-select/issues/4804#issuecomment-927223471) +so if you import that type it will include all of the extra props offered. This +package also exports a few custom types that are specific to the custom props +offered by this package: + +- `ChakraStylesConfig` — The type for the prop `chakraStyles` that can be passed + to customize the component styles. This is almost identical to the built-in + `StylesConfig` type, however, it uses Chakra's + [`CSSObject`](https://github.com/chakra-ui/chakra-ui/blob/790d2417a3f5d59e2d69229a027af671c2dc0cbc/packages/styled-system/src/system.types.ts#L81) + type instead of react-select's emotion styles. +- `OptionBase` — A type for your individual select options that includes the + custom props for styling each of your selected options. This type is made to + give you a base to extend off of and pass in as a generic to the root `Select` + component. - Each of the four Select components has a type exported with it: - `SelectComponent` - `AsyncSelectComponent` - `CreatableSelectComponent` - `AsyncCreatableSelectComponent` -Here is an example of how to pass in the proper generics to `chakra-react-select`: +Here is an example of how to pass in the proper generics to +`chakra-react-select`: ````ts import { GroupBase, OptionBase, Select } from "chakra-react-select"; @@ -524,7 +780,6 @@ import { GroupBase, OptionBase, Select } from "chakra-react-select"; * type OptionBase = { * variant?: string; * colorScheme?: string; - * isFixed?: boolean; * isDisabled?: boolean; * }; * ``` @@ -548,7 +803,7 @@ const colorOptions = [ function CustomMultiSelect() { return { - > + > // <-- None of these generics should be required isMulti name="colors" options={colorOptions} @@ -560,9 +815,22 @@ function CustomMultiSelect() { ## Customizing Components -Like the original `react-select`, this package exports all of the custom components that make up the overall select. However, instead of being exported as `components` they are exported as `chakraComponents` in order to leave the original `components` export from react-select alone (you can export that as well if you'd like). When implementing this component, you have the option to wrap these components and alter their state and the children they return [in the same way the original does](https://react-select.com/components#defining-components). - -It's important to note however, that there are 3 components offered in the original `react-select` that are missing from `chakraComponents`. These are the `CrossIcon`, `DownChevron`, and `MenuPortal`. The `MenuPortal` could not be replaced at all [as mentioned earlier](#caveats), so if you'd like to customize it, use the original from the `components` import. The icons posed issues with prop compatibility when passing them into the core `Select` so the easiest way to replace them would be to use a custom `DropdownIndicator` or `ClearIndicator` and pass custom icons in as children: +Like the original `react-select`, this package exports all of the custom +components that make up the overall select. However, instead of being exported +as `components` they are exported as `chakraComponents` to leave the original +`components` export from react-select alone (you can export that as well if +you'd like). When implementing this component, you have the option to wrap these +components and alter their state and the children they return +[in the same way the original does](https://react-select.com/components#defining-components). + +It's important to note, however, that there are 3 components offered in the +original `react-select` that are missing from `chakraComponents`. These are the +`CrossIcon`, `DownChevron`, and `MenuPortal`. The `MenuPortal` could not be +replaced at all [as mentioned earlier](#caveats), so if you'd like to customize +it, use the original from the `components` import. The icons posed issues with +prop compatibility when passing them into the core `Select` so the easiest way +to replace them would be to use a custom `DropdownIndicator` or `ClearIndicator` +and pass custom icons in as children: ```js const components = { @@ -581,7 +849,8 @@ const components = { [![CS-JS]](https://codesandbox.io/s/chakra-react-select-custom-icons-xf7scd?file=/example.js) -Here's a complete example of how you might use custom components to create a select with a custom `Option`: +Here's a complete example of how you might use custom components to create a +select with a custom `Option`: ```ts import { Icon } from "@chakra-ui/react"; @@ -641,7 +910,14 @@ const Example = () => ( ### Custom `LoadingIndicator` (Chakra `Spinner`) -For most sub components, the styling can be easily accomplished using the [`chakraStyles`](#chakrastyles) prop. However, in the case of the `LoadingIndicator` there are a few props which do not directly correlate very well with styling props. To solve that problem, the `chakraComponents.LoadingIndicator` component can be passed a few extra props which are normally available on the Chakra UI [`Spinner`](https://chakra-ui.com/docs/components/spinner). Here is an example demonstrating which extra props are offered: +For most sub components, the styling can be easily accomplished using the +[`chakraStyles`](#chakrastyles) prop. However, in the case of the +`LoadingIndicator` there are a few props which do not directly correlate very +well with styling props. To solve that problem, the +`chakraComponents.LoadingIndicator` component can be passed a few extra props +which are normally available on the Chakra UI +[`Spinner`](https://chakra-ui.com/docs/components/spinner). Here is an example +demonstrating which extra props are offered: ```jsx import { AsyncSelect, chakraComponents } from "chakra-react-select"; @@ -691,22 +967,42 @@ const App = () => ( ## `useChakraSelectProps` -Being a wrapper for `react-select`, all of the customizations done to react-select are passed in as props. There is a hook, [`useChakraSelectProps`](https://github.com/csandman/chakra-react-select/blob/main/src/use-chakra-select-props.ts) that handles merging any extra customizations from the end user with the customizations done by this package. In some cases you may simply want to use this hook to get the custom props and pass them into a `react-select` instance yourself. +Being a wrapper for `react-select`, all of the customizations done to +react-select are passed in as props. There is a hook, +[`useChakraSelectProps`](https://github.com/csandman/chakra-react-select/blob/main/src/use-chakra-select-props.ts) +that handles merging any extra customizations from the end user with the +customizations done by this package. In some cases you may simply want to use +this hook to get the custom props and pass them into a `react-select` instance +yourself. -To do so, simply import the hook from this package, and call it by passing in any extra custom props you'd like into it and spread it onto a base `react-select` component: +To do so, simply import the hook from this package, and call it by passing in +any extra custom props you'd like into it and spread it onto a base +`react-select` component: ```jsx +import { useState } from "react"; import { useChakraSelectProps } from "chakra-react-select"; import Select from "react-select"; +import { options } from "./data"; -const CustomSelect = (customSelectProps) => { - const selectProps = useChakraSelectProps(customSelectProps); +const CustomSelect = () => { + const [selectedOptions, setSelectedOptions] = useState([]); + + const selectProps = useChakraSelectProps({ + isMulti: true, + value: selectedOptions, + onChange: setSelectedOptions, + }); return