UNPKG

@neo4j-ndl/react

Version:

React implementation of Neo4j Design System

531 lines (445 loc) 14.4 kB
# Select Import: `import { Select } from '@neo4j-ndl/react'` ## Props ### Select | Prop | Type | Required | Default | Description | |------|------|----------|---------|-------------| | `ariaLabel` | `string` | | | Aria label of the select component | | `as` | `ElementType<any, keyof IntrinsicElements>` | | | An override of the default HTML tag of the root of the component. Can also be another React component. | | `errorText` | `ReactNode` | | | Error message, if it exists the select will be in error state | | `helpText` | `ReactNode` | | | Help text of the select component | | `isClean` | `boolean` | | `false` | Whether the select component is clean. If true, the select component will have a transparent background, no border and be hug the width of the content. | | `isDisabled` | `boolean` | | | Whether the select component is disabled | | `isFluid` | `boolean` | | `true` | Whether the select component is fluid | | `label` | `ReactNode` | | | Label of the select component. If not provided, please provide an ariaLabel. | | `ref` | `any` | | | A ref to apply to the root element. | | `selectProps` | `StateManagerProps<OptionType, IsMulti, GroupType> \| CreatableProps<OptionType, IsMulti, GroupType> \| AsyncProps<...>` | | `{}` | Props of the select component, based of React Select props | | `size` | `'large' \| 'medium' \| 'small'` | | `medium` | Size of the component | | `type` | `'async' \| 'creatable' \| 'select'` | | `select` | Type of the select component | The `type` prop is used to specify the type of select component to render, which will be passed to the underlying React Select component. The `selectProps` prop is dynamically typed based on the `type` prop and can be one of the following: `StateManagerProps`, `CreatableProps`, `AsyncProps`. All select variants will have the `SelectProps` base type from React Select. For more information on the available props, see the [React Select documentation](https://react-select.com/props). ## Examples ### Default ```tsx import '@neo4j-ndl/base/lib/neo4j-ds-styles.css'; import { Select } from '@neo4j-ndl/react'; const EXAMPLE_OPTIONS = [ { label: 'Neo4j', value: 'neo4j' }, { label: 'Needle 🪡', value: 'needle' }, { label: 'Graph Databases', value: 'graph-database' }, { label: 'Really long label that does not fit on one row', value: 'long-label', }, { isDisabled: true, label: 'Disabled database option', value: 'disabled' }, ]; const Component = (props: React.ComponentProps<typeof Select>) => { return ( <Select label="Select an option" helpText="Help text" type="select" selectProps={{ menuIsOpen: props.selectProps?.menuIsOpen, options: EXAMPLE_OPTIONS, }} /> ); }; export default Component; ``` ### Async ```tsx import '@neo4j-ndl/base/lib/neo4j-ds-styles.css'; import { Select } from '@neo4j-ndl/react'; const EXAMPLE_OPTIONS = [ { label: 'Neo4j', value: 'neo4j' }, { label: 'Needle 🪡', value: 'needle' }, { label: 'Graph Databases', value: 'graph-database' }, { isDisabled: true, label: 'Disabled database option', value: 'disabled' }, ]; const loadOptions = (inputValue: string) => { return new Promise<typeof EXAMPLE_OPTIONS>((resolve) => { setTimeout(() => { const filteredOptions = EXAMPLE_OPTIONS.filter((option) => option.label.toLowerCase().includes(inputValue.toLowerCase()), ); resolve(filteredOptions); }, 1000); }); }; const Component = (props: React.ComponentProps<typeof Select>) => { return ( <Select label="Label" helpText="Start typing to load options dynamically" type="async" selectProps={{ cacheOptions: true, defaultOptions: true, isClearable: true, loadOptions, menuIsOpen: props.selectProps?.menuIsOpen, placeholder: 'Type to search...', }} /> ); }; export default Component; ``` ### Clean ```tsx import '@neo4j-ndl/base/lib/neo4j-ds-styles.css'; import { Select } from '@neo4j-ndl/react'; const EXAMPLE_OPTIONS = [ { label: 'Neo4j', value: 'neo4j' }, { label: 'Needle 🪡', value: 'needle' }, { label: 'Graph Databases', value: 'graph-database' }, { isDisabled: true, label: 'Disabled database option', value: 'disabled' }, ]; const Component = (props: React.ComponentProps<typeof Select>) => { return ( <Select label="Label" type="select" isClean={true} isFluid={false} selectProps={{ menuIsOpen: props.selectProps?.menuIsOpen, options: EXAMPLE_OPTIONS, }} /> ); }; export default Component; ``` ### Controlled ```tsx import { Select, Typography } from '@neo4j-ndl/react'; import { useState } from 'react'; const EXAMPLE_OPTIONS = [ { label: 'Neo4j', value: 'neo4j' }, { label: 'Needle 🪡', value: 'needle' }, { label: 'Graph Databases', value: 'graph-database' }, { isDisabled: true, label: 'Disabled database option', value: 'disabled' }, ]; const Component = (props: React.ComponentProps<typeof Select>) => { const [value, setValue] = useState<(typeof EXAMPLE_OPTIONS)[number]>( EXAMPLE_OPTIONS[0], ); return ( <div className="n-flex n-flex-col n-gap-token-8"> <Select label="Label" type="select" selectProps={{ isMulti: false, menuIsOpen: props.selectProps?.menuIsOpen, menuPortalTarget: document.querySelector('body'), onChange: (newValue) => newValue && setValue(newValue), options: EXAMPLE_OPTIONS, value: value, }} /> <Typography variant="body-small"> Value Selected: {JSON.stringify(value)} </Typography> </div> ); }; export default Component; ``` ### Creatable ```tsx import '@neo4j-ndl/base/lib/neo4j-ds-styles.css'; import { Select } from '@neo4j-ndl/react'; const EXAMPLE_OPTIONS = [ { label: 'Neo4j', value: 'neo4j' }, { label: 'Needle 🪡', value: 'needle' }, { label: 'Graph Databases', value: 'graph-database' }, { isDisabled: true, label: 'Disabled database option', value: 'disabled' }, ]; const Component = (props: React.ComponentProps<typeof Select>) => { return ( <Select label="Label" helpText="You can create values even if they don't exist as options" type="creatable" selectProps={{ isClearable: true, menuIsOpen: props.selectProps?.menuIsOpen, options: EXAMPLE_OPTIONS, }} /> ); }; export default Component; ``` ### Custom Label ```tsx import '@neo4j-ndl/base/lib/neo4j-ds-styles.css'; import { Select } from '@neo4j-ndl/react'; import { QuestionMarkCircleIconOutline } from '@neo4j-ndl/react/icons'; const EXAMPLE_OPTIONS = [ { label: 'Neo4j', value: 'neo4j' }, { label: 'Needle 🪡', value: 'needle' }, { label: 'Graph Databases', value: 'graph-database' }, { isDisabled: true, label: 'Disabled database option', value: 'disabled' }, ]; const Component = (props: React.ComponentProps<typeof Select>) => { return ( <Select label={ <div className="n-flex n-flex-row n-gap-token-4 n-h-7 n-items-center"> Custom JSX element <QuestionMarkCircleIconOutline className="n-h-token-16" /> </div> } helpText="You can have a custom label with JSX code 😱" type="select" selectProps={{ defaultValue: EXAMPLE_OPTIONS[1], menuIsOpen: props.selectProps?.menuIsOpen, options: EXAMPLE_OPTIONS, }} /> ); }; export default Component; ``` ### Disabled ```tsx import '@neo4j-ndl/base/lib/neo4j-ds-styles.css'; import { Select } from '@neo4j-ndl/react'; const EXAMPLE_OPTIONS = [ { label: 'Neo4j', value: 'neo4j' }, { label: 'Needle 🪡', value: 'needle' }, { label: 'Graph Databases', value: 'graph-database' }, { isDisabled: true, label: 'Disabled database option', value: 'disabled' }, ]; const Component = (props: React.ComponentProps<typeof Select>) => { return ( <Select label="Label" type="select" selectProps={{ isDisabled: true, menuIsOpen: props.selectProps?.menuIsOpen, options: EXAMPLE_OPTIONS, }} /> ); }; export default Component; ``` ### Empty ```tsx import '@neo4j-ndl/base/lib/neo4j-ds-styles.css'; import { Select } from '@neo4j-ndl/react'; const Component = (props: React.ComponentProps<typeof Select>) => { return ( <Select label="Label" helpText="Help text" type="select" selectProps={{ menuIsOpen: props.selectProps?.menuIsOpen, options: [], }} /> ); }; export default Component; ``` ### Error State ```tsx import '@neo4j-ndl/base/lib/neo4j-ds-styles.css'; import { Select } from '@neo4j-ndl/react'; const EXAMPLE_OPTIONS = [ { label: 'Neo4j', value: 'neo4j' }, { label: 'Needle 🪡', value: 'needle' }, { label: 'Graph Databases', value: 'graph-database' }, { isDisabled: true, label: 'Disabled database option', value: 'disabled' }, ]; const Component = (props: React.ComponentProps<typeof Select>) => { return ( <Select label="Label" errorText="Validate that your selection is correct" type="select" selectProps={{ menuIsOpen: props.selectProps?.menuIsOpen, options: EXAMPLE_OPTIONS, }} /> ); }; export default Component; ``` ### Inside Dialog ```tsx import '@neo4j-ndl/base/lib/neo4j-ds-styles.css'; import { Dialog, FilledButton, Select, Typography } from '@neo4j-ndl/react'; import { useRef, useState } from 'react'; const EXAMPLE_OPTIONS = [ { label: 'Neo4j', value: 'neo4j' }, { label: 'Needle 🪡', value: 'needle' }, { label: 'Graph Databases', value: 'graph-database' }, { isDisabled: true, label: 'Disabled database option', value: 'disabled' }, ]; const Component = (props: React.ComponentProps<typeof Select>) => { const ref = useRef<HTMLDivElement | null>(null); const [isOpen, setIsOpen] = useState<boolean>(false); return ( <div ref={ref} className="n-flex n-flex-col n-items-center n-justify-center n-relative n-h-[500px]" > <FilledButton size="medium" onClick={() => setIsOpen(true)}> Open Dialog </FilledButton> <Dialog container={ref?.current || undefined} isOpen={isOpen} onClose={() => setIsOpen(false)} aria-label="Dialog" > <Dialog.Header>Using Select inside a dialog</Dialog.Header> <Dialog.Description className="n-flex n-flex-col n-gap-token-32"> <Typography variant="body-medium"> To use select inside a dialog and avoid the cut-off, you need to use the property <code>menuPosition: &quot;fixed&quot;</code> inside the{' '} <code>selectProps</code>. This is done automatically if used in a Needle Dialog, but can always be overridden manually. </Typography> <Select label="Inside a dialog" type="select" selectProps={{ defaultValue: EXAMPLE_OPTIONS[1], menuIsOpen: props.selectProps?.menuIsOpen, options: EXAMPLE_OPTIONS, }} /> </Dialog.Description> </Dialog> </div> ); }; export default Component; ``` ### Menu Positionings ```tsx import '@neo4j-ndl/base/lib/neo4j-ds-styles.css'; import { Select } from '@neo4j-ndl/react'; const EXAMPLE_OPTIONS = [ { label: 'Neo4j', value: 'neo4j' }, { label: 'Needle 🪡', value: 'needle' }, ]; const Component = (props: React.ComponentProps<typeof Select>) => { return ( <div className="n-flex n-gap-token-16 n-pt-token-64"> <Select label="Automatic menu placement" type="select" selectProps={{ menuIsOpen: props.selectProps?.menuIsOpen, menuPlacement: 'auto', options: EXAMPLE_OPTIONS, }} /> <Select label="Bottom menu placement" type="select" selectProps={{ menuIsOpen: props.selectProps?.menuIsOpen, menuPlacement: 'bottom', options: EXAMPLE_OPTIONS, }} /> <Select label="Top menu placement" type="select" selectProps={{ menuIsOpen: props.selectProps?.menuIsOpen, menuPlacement: 'top', options: EXAMPLE_OPTIONS, }} /> </div> ); }; export default Component; ``` ### Multi ```tsx import '@neo4j-ndl/base/lib/neo4j-ds-styles.css'; import { Select } from '@neo4j-ndl/react'; const EXAMPLE_OPTIONS = [ { label: 'Neo4j', value: 'neo4j' }, { label: 'Needle 🪡', value: 'needle' }, { label: 'Graph Databases', value: 'graph-database' }, { isDisabled: true, label: 'Disabled database option', value: 'disabled' }, ]; const Component = (props: React.ComponentProps<typeof Select>) => { return ( <Select label="Label" type="select" selectProps={{ defaultValue: EXAMPLE_OPTIONS[1], isClearable: true, isMulti: true, menuIsOpen: props.selectProps?.menuIsOpen, options: EXAMPLE_OPTIONS, }} /> ); }; export default Component; ``` ### Sizes ```tsx import '@neo4j-ndl/base/lib/neo4j-ds-styles.css'; import { Select } from '@neo4j-ndl/react'; const EXAMPLE_OPTIONS = [ { label: 'Neo4j', value: 'neo4j' }, { label: 'Needle 🪡', value: 'needle' }, { label: 'Graph Databases', value: 'graph-database' }, { isDisabled: true, label: 'Disabled database option', value: 'disabled' }, ]; const Component = (props: React.ComponentProps<typeof Select>) => { return ( <div className="n-flex n-gap-token-16"> <Select label="Small" type="select" size="small" selectProps={{ menuIsOpen: props.selectProps?.menuIsOpen, options: EXAMPLE_OPTIONS, }} /> <Select label="Medium" type="select" size="medium" selectProps={{ menuIsOpen: props.selectProps?.menuIsOpen, options: EXAMPLE_OPTIONS, }} /> <Select label="Large" type="select" size="large" selectProps={{ menuIsOpen: props.selectProps?.menuIsOpen, options: EXAMPLE_OPTIONS, }} /> </div> ); }; export default Component; ```