From a0b75faa14e8085f637af601aa96c14910d9d491 Mon Sep 17 00:00:00 2001 From: shindigira Date: Thu, 5 Oct 2023 16:04:05 -0400 Subject: [PATCH 01/14] style: Indicator Separator of Dropdown is now the proper color --- src/components/Dropdown/Dropdown.less | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/components/Dropdown/Dropdown.less b/src/components/Dropdown/Dropdown.less index c6960868..15e249f0 100644 --- a/src/components/Dropdown/Dropdown.less +++ b/src/components/Dropdown/Dropdown.less @@ -11,12 +11,10 @@ outline-offset: 2px !important; } - .dropdown-indicator-separator { margin-top: 0 !important; margin-bottom: 0 !important; background: #919395 !important; - border-color: inherit !important; width: 1px !important; } From 76cfa0ab68686d0aeaf857cde039deb91c17c9c8 Mon Sep 17 00:00:00 2001 From: shindigira Date: Thu, 5 Oct 2023 16:24:46 -0400 Subject: [PATCH 02/14] chore: Dropdown passing id to Checkbox, indiciator container same height and width --- src/components/Dropdown/Dropdown.less | 2 ++ src/components/Dropdown/Dropdown.tsx | 13 ++++++++----- .../Dropdown/DropdownInputWithCheckbox.tsx | 2 ++ 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/components/Dropdown/Dropdown.less b/src/components/Dropdown/Dropdown.less index 15e249f0..506b2183 100644 --- a/src/components/Dropdown/Dropdown.less +++ b/src/components/Dropdown/Dropdown.less @@ -27,6 +27,8 @@ background: #e7e8e9 !important; color: inherit !important; border-color: inherit !important; + height: 2.1875em !important; + width: 2.1875em !important; } .dropdown-value-container, diff --git a/src/components/Dropdown/Dropdown.tsx b/src/components/Dropdown/Dropdown.tsx index 6cec0a8c..f4080be4 100644 --- a/src/components/Dropdown/Dropdown.tsx +++ b/src/components/Dropdown/Dropdown.tsx @@ -18,11 +18,14 @@ import { filterOptions, onSelectInputFocus } from './utils'; import { Icon } from '../Icon/Icon'; -const customDropdownIndicator = (properties): JSX.Element => ( - - - -); +const customDropdownIndicator = (properties): JSX.Element => { + const shouldBeUp = Boolean(properties.selectProps.menuIsOpen); + return ( + + + + ); +}; /** * A dropdown input component that supports multi-select. diff --git a/src/components/Dropdown/DropdownInputWithCheckbox.tsx b/src/components/Dropdown/DropdownInputWithCheckbox.tsx index 25a4def7..898de776 100644 --- a/src/components/Dropdown/DropdownInputWithCheckbox.tsx +++ b/src/components/Dropdown/DropdownInputWithCheckbox.tsx @@ -34,6 +34,7 @@ const CheckboxInputOption = ({ }; const withCheckbox = Boolean(rest.selectProps.customProps.withCheckbox); + const { id } = rest.selectProps; return ( {withCheckbox ? ( Date: Thu, 5 Oct 2023 16:33:12 -0400 Subject: [PATCH 03/14] style: Select text is the proper color --- src/components/Dropdown/Dropdown.less | 4 ++++ src/components/Dropdown/Dropdown.tsx | 1 + 2 files changed, 5 insertions(+) diff --git a/src/components/Dropdown/Dropdown.less b/src/components/Dropdown/Dropdown.less index 506b2183..30d2512b 100644 --- a/src/components/Dropdown/Dropdown.less +++ b/src/components/Dropdown/Dropdown.less @@ -31,6 +31,10 @@ width: 2.1875em !important; } +.dropdown-single-value { + color: #101820 !important; +} + .dropdown-value-container, .dropdown-control--error { border: none !important; diff --git a/src/components/Dropdown/Dropdown.tsx b/src/components/Dropdown/Dropdown.tsx index f4080be4..1c0ad5f8 100644 --- a/src/components/Dropdown/Dropdown.tsx +++ b/src/components/Dropdown/Dropdown.tsx @@ -131,6 +131,7 @@ export function Dropdown< }`, indicatorsContainer: () => 'dropdown-indicators-container', dropdownIndicator: () => 'dropdown-dropdown-indicator', + singleValue: () => 'dropdown-single-value', valueContainer: () => `dropdown-value-container ${ error From b6bd99851a73fe99c18070baa2efd655b17b047f Mon Sep 17 00:00:00 2001 From: shindigira Date: Thu, 5 Oct 2023 17:13:45 -0400 Subject: [PATCH 04/14] style: Select -- 2.1875em height --- src/components/Dropdown/Dropdown.less | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/components/Dropdown/Dropdown.less b/src/components/Dropdown/Dropdown.less index 30d2512b..b8b33c10 100644 --- a/src/components/Dropdown/Dropdown.less +++ b/src/components/Dropdown/Dropdown.less @@ -3,6 +3,8 @@ border-width: 1px !important; width: 100% !important; border-color: #919395 !important; + min-height: 2.1875em !important; // 35px to match CFPB design + height: 2.1875em !important; } .dropdown-control:focus { @@ -48,6 +50,9 @@ outline-offset: 0; } +.dropdown-indicators-container--error { + border: 1px solid #919395; +} .dropdown-clear-indicator-container { margin-left: 4px; margin-right: 4px; From 2943f6fadd29509d3f0dfe6f0d9e437848c8b2a0 Mon Sep 17 00:00:00 2001 From: shindigira Date: Thu, 5 Oct 2023 17:14:41 -0400 Subject: [PATCH 05/14] style: Select's caret container has the normal border during errors --- src/components/Dropdown/Dropdown.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/Dropdown/Dropdown.tsx b/src/components/Dropdown/Dropdown.tsx index 1c0ad5f8..dfa6b5d6 100644 --- a/src/components/Dropdown/Dropdown.tsx +++ b/src/components/Dropdown/Dropdown.tsx @@ -129,7 +129,8 @@ export function Dropdown< ? '' : 'dropdown-indicator-separator__none' }`, - indicatorsContainer: () => 'dropdown-indicators-container', + indicatorsContainer: () => + `${error ? 'dropdown-indicators-container--error' : ''}`, dropdownIndicator: () => 'dropdown-dropdown-indicator', singleValue: () => 'dropdown-single-value', valueContainer: () => From 40b19e7e5eb79ec817a7e88af802502bf62bd0ce Mon Sep 17 00:00:00 2001 From: shindigira Date: Thu, 5 Oct 2023 17:19:08 -0400 Subject: [PATCH 06/14] style: Dropdown Option color should be correct --- src/components/Dropdown/DropdownInputWithCheckbox.css | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/Dropdown/DropdownInputWithCheckbox.css b/src/components/Dropdown/DropdownInputWithCheckbox.css index 4d8a5182..66f71f34 100644 --- a/src/components/Dropdown/DropdownInputWithCheckbox.css +++ b/src/components/Dropdown/DropdownInputWithCheckbox.css @@ -1,5 +1,6 @@ .dropdown-option-container { width: 100%; + color: #101820; } /* controls highlighting the checkbox if the entire line is focused */ From b0e258702a4594238c6f1956abfce5affc564f56 Mon Sep 17 00:00:00 2001 From: shindigira Date: Thu, 5 Oct 2023 17:40:15 -0400 Subject: [PATCH 07/14] style: square caret box --- src/components/Dropdown/Dropdown.less | 10 ++++++++-- src/components/Dropdown/Dropdown.tsx | 4 +++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/components/Dropdown/Dropdown.less b/src/components/Dropdown/Dropdown.less index b8b33c10..5d06635a 100644 --- a/src/components/Dropdown/Dropdown.less +++ b/src/components/Dropdown/Dropdown.less @@ -29,7 +29,6 @@ background: #e7e8e9 !important; color: inherit !important; border-color: inherit !important; - height: 2.1875em !important; width: 2.1875em !important; } @@ -50,8 +49,15 @@ outline-offset: 0; } +.dropdown-indicators-container { + background-color: #e7e8e9 !important; + height: 100%; + overflow: hidden; +} + .dropdown-indicators-container--error { - border: 1px solid #919395; + border: 1px solid #919395 !important; + border-left: none !important; } .dropdown-clear-indicator-container { margin-left: 4px; diff --git a/src/components/Dropdown/Dropdown.tsx b/src/components/Dropdown/Dropdown.tsx index dfa6b5d6..605999c9 100644 --- a/src/components/Dropdown/Dropdown.tsx +++ b/src/components/Dropdown/Dropdown.tsx @@ -130,7 +130,9 @@ export function Dropdown< : 'dropdown-indicator-separator__none' }`, indicatorsContainer: () => - `${error ? 'dropdown-indicators-container--error' : ''}`, + `dropdown-indicators-container ${ + error ? 'dropdown-indicators-container--error' : '' + }`, dropdownIndicator: () => 'dropdown-dropdown-indicator', singleValue: () => 'dropdown-single-value', valueContainer: () => From a6e9e941900cd8111843d461bb1c4f0e2d47b108 Mon Sep 17 00:00:00 2001 From: shindigira Date: Thu, 5 Oct 2023 23:30:40 -0400 Subject: [PATCH 08/14] feat: Renamed all references of Dropdown --> Select --- .../Dropdown.less => Select/Select.less} | 24 +- .../Select.stories.tsx} | 119 +- .../Select.test.tsx} | 32 +- .../Dropdown.tsx => Select/Select.tsx} | 52 +- .../Select.types.tsx} | 2 +- .../SelectInputWithCheckbox.css} | 10 +- .../SelectInputWithCheckbox.tsx} | 8 +- .../SelectPills.less} | 0 .../SelectPills.test.tsx} | 14 +- .../SelectPills.tsx} | 18 +- .../{Dropdown => Select}/styles.tsx | 0 src/components/{Dropdown => Select}/utils.tsx | 2 +- src/index.ts | 8 +- yarn.lock | 1449 ++++++++--------- 14 files changed, 792 insertions(+), 946 deletions(-) rename src/components/{Dropdown/Dropdown.less => Select/Select.less} (74%) rename src/components/{Dropdown/Dropdown.stories.tsx => Select/Select.stories.tsx} (54%) rename src/components/{Dropdown/Dropdown.test.tsx => Select/Select.test.tsx} (92%) rename src/components/{Dropdown/Dropdown.tsx => Select/Select.tsx} (78%) rename src/components/{Dropdown/Dropdown.types.tsx => Select/Select.types.tsx} (92%) rename src/components/{Dropdown/DropdownInputWithCheckbox.css => Select/SelectInputWithCheckbox.css} (68%) rename src/components/{Dropdown/DropdownInputWithCheckbox.tsx => Select/SelectInputWithCheckbox.tsx} (82%) rename src/components/{Dropdown/DropdownPills.less => Select/SelectPills.less} (100%) rename src/components/{Dropdown/DropdownPills.test.tsx => Select/SelectPills.test.tsx} (80%) rename src/components/{Dropdown/DropdownPills.tsx => Select/SelectPills.tsx} (88%) rename src/components/{Dropdown => Select}/styles.tsx (100%) rename src/components/{Dropdown => Select}/utils.tsx (96%) diff --git a/src/components/Dropdown/Dropdown.less b/src/components/Select/Select.less similarity index 74% rename from src/components/Dropdown/Dropdown.less rename to src/components/Select/Select.less index 5d06635a..a3c277b2 100644 --- a/src/components/Dropdown/Dropdown.less +++ b/src/components/Select/Select.less @@ -1,4 +1,4 @@ -.dropdown-control { +.select-control { border-radius: 0 !important; border-width: 1px !important; width: 100% !important; @@ -7,41 +7,41 @@ height: 2.1875em !important; } -.dropdown-control:focus { +.select-control:focus { border-color: #0072ce !important; outline: 1px dotted #0072ce !important; outline-offset: 2px !important; } -.dropdown-indicator-separator { +.select-indicator-separator { margin-top: 0 !important; margin-bottom: 0 !important; background: #919395 !important; width: 1px !important; } -.dropdown-indicator-separator__none { +.select-indicator-separator__none { width: 0px !important; border-left: #919395 1px solid; } -.dropdown-dropdown-indicator { +.select-dropdown-indicator { background: #e7e8e9 !important; color: inherit !important; border-color: inherit !important; width: 2.1875em !important; } -.dropdown-single-value { +.select-single-value { color: #101820 !important; } -.dropdown-value-container, -.dropdown-control--error { +.select-value-container, +.select-control--error { border: none !important; } -.dropdown-value-container--error { +.select-value-container--error { border-style: solid !important; border-color: #d14124 !important; border-width: 1px !important; @@ -49,17 +49,17 @@ outline-offset: 0; } -.dropdown-indicators-container { +.select-indicators-container { background-color: #e7e8e9 !important; height: 100%; overflow: hidden; } -.dropdown-indicators-container--error { +.select-indicators-container--error { border: 1px solid #919395 !important; border-left: none !important; } -.dropdown-clear-indicator-container { +.select-clear-indicator-container { margin-left: 4px; margin-right: 4px; } diff --git a/src/components/Dropdown/Dropdown.stories.tsx b/src/components/Select/Select.stories.tsx similarity index 54% rename from src/components/Dropdown/Dropdown.stories.tsx rename to src/components/Select/Select.stories.tsx index a2f8e5e6..bb4338c5 100644 --- a/src/components/Dropdown/Dropdown.stories.tsx +++ b/src/components/Select/Select.stories.tsx @@ -1,18 +1,18 @@ /* eslint-disable react/jsx-handler-names */ -import { useArgs, useState } from '@storybook/client-api'; +import { useArgs } from '@storybook/client-api'; import type { Meta, StoryObj } from '@storybook/react'; import { Button } from '../Buttons/Button'; -import { Dropdown } from './Dropdown'; +import Select from './Select'; import { MockOptions } from './utils'; /** - * Dropdowns allow the user to choose from a finite list of options. They are not always the best choice from a usability perspective; see the use cases documentation for more details. + * Selects allow the user to choose from a finite list of options. They are not always the best choice from a usability perspective; see the use cases documentation for more details. * - * Source: https://cfpb.github.io/design-system/components/dropdowns-and-multiselects + * Source: https://cfpb.github.io/design-system/components/selects */ -const meta: Meta = { - title: 'Components (Draft)/Dropdowns', - component: Dropdown +const meta: Meta = { + title: 'Components (Draft)/Selects', + component: Select }; export default meta; @@ -21,16 +21,15 @@ type Story = StoryObj; const LAST_ELEMENT = -1; -function DropdownWrapper({ ...arguments_ }): JSX.Element { - const [selected, updateSelected] = useState(arguments_.value); - const [, updateArguments] = useArgs(); +function SelectWrapper({ ...arguments_ }): JSX.Element { + const [{ value }, updateArguments] = useArgs(); + console.log(value); return ( - { - updateSelected(newValue); updateArguments({ value: newValue }); @@ -39,128 +38,128 @@ function DropdownWrapper({ ...arguments_ }): JSX.Element { ); } -export const DefaultDropdown: Story = { - render: _arguments => DropdownWrapper(_arguments), - name: 'Default dropdown', +export const DefaultSelect: Story = { + render: _arguments => SelectWrapper(_arguments), + name: 'Default select', args: { - label: 'Default Dropdown', - id: 'dropdown', - options: MockOptions, - value: [MockOptions[0]] + label: '', + id: 'select', + options: MockOptions } }; export const WithError: Story = { - render: _arguments => DropdownWrapper(_arguments), + render: _arguments => SelectWrapper(_arguments), name: 'With error', args: { - ...DefaultDropdown.args, + ...DefaultSelect.args, id: 'WithError', - error: true, - label: 'With Error' + error: true + // label: 'With Error' } }; export const WithDefaultValue: Story = { - render: _arguments => DropdownWrapper(_arguments), + render: _arguments => SelectWrapper(_arguments), name: 'With default value', args: { - ...DefaultDropdown.args, + ...DefaultSelect.args, id: 'WithDefaultValue', - value: MockOptions.at(LAST_ELEMENT), - label: 'With Default Value' + value: MockOptions.at(LAST_ELEMENT) + // label: 'With Default Value' } }; export const Disabled: Story = { - render: _arguments => DropdownWrapper(_arguments), + render: _arguments => SelectWrapper(_arguments), args: { - ...DefaultDropdown.args, + ...DefaultSelect.args, id: 'Disabled', - label: 'Disabled', + // label: 'Disabled', isDisabled: true } }; export const MultiSelect: Story = { - render: _arguments => DropdownWrapper(_arguments), + render: _arguments => SelectWrapper(_arguments), name: 'Multi-select', args: { - ...DefaultDropdown.args, + ...DefaultSelect.args, options: [...MockOptions], id: 'MultiSelect', - isMulti: true, - label: 'Multi-select' + isMulti: true + // label: 'Multi-select' } }; export const MultiSelectWithDefaultValue: Story = { - render: _arguments => DropdownWrapper(_arguments), + render: _arguments => SelectWrapper(_arguments), name: 'Multi-select with default value (and pills above)', args: { - ...DefaultDropdown.args, + ...DefaultSelect.args, options: [...MockOptions], value: [MockOptions[0]], id: 'MultiSelectWithDefaultValue', - isMulti: true, - label: 'Multi-select with default value (and pills above)' + isMulti: true + // label: 'Multi-select with default value (and pills above)' } }; export const MultiSelectWithCheckboxes: Story = { - render: _arguments => DropdownWrapper(_arguments), + render: _arguments => SelectWrapper(_arguments), name: 'Multi-select with checkboxes', args: { - ...DefaultDropdown.args, + ...DefaultSelect.args, options: [...MockOptions], value: [MockOptions[0]], id: 'MultiSelectWithCheckboxes', isMulti: true, - label: 'Multi-select with checkboxes', + // label: 'Multi-select with checkboxes', pillAlign: 'bottom', withCheckbox: true } }; export const MultiSelectWithPillsAlignedBottom: Story = { - render: _arguments => DropdownWrapper(_arguments), + render: _arguments => SelectWrapper(_arguments), name: 'Multi-select with pills bottom-aligned', args: { - ...DefaultDropdown.args, + ...DefaultSelect.args, options: [...MockOptions], value: [MockOptions[0]], id: 'MultiSelectWithPillsAlignedBottom', isMulti: true, - label: 'Multi-select with pills bottom-aligned', - pillAlign: 'bottom' + // label: 'Multi-select with pills bottom-aligned', + pillAlign: 'bottom', + showClearAllSelectedButton: true } }; export const MultiSelectWithCheckboxesWithoutPills: Story = { - render: _arguments => DropdownWrapper(_arguments), + render: _arguments => SelectWrapper(_arguments), name: 'Multi-select with checkboxes, without pills', args: { - ...DefaultDropdown.args, + ...DefaultSelect.args, options: [...MockOptions], value: [MockOptions[0]], id: 'MultiSelectWithCheckboxesWithoutPills', isMulti: true, - label: 'Multi-select with checkboxes, without pills', + // label: 'Multi-select with checkboxes, without pills', pillAlign: 'hide', withCheckbox: true } }; export const MultiSelectWithCheckboxesWithoutClearAllButton: Story = { - render: _arguments => DropdownWrapper(_arguments), - name: 'Multi-select with checkboxes, without bottom clear all button', + render: _arguments => SelectWrapper(_arguments), + name: 'Multi-select with checkboxes', args: { - ...DefaultDropdown.args, + ...DefaultSelect.args, options: [...MockOptions], value: [MockOptions[0]], id: 'MultiSelectWithCheckboxesWithoutClearAllButton', isMulti: true, - label: 'Multi-select with checkboxes, without clear all button', + // label: 'Multi-select with checkboxes, without clear all button', pillAlign: 'bottom', withCheckbox: true, showClearAllSelectedButton: false @@ -168,8 +167,7 @@ export const MultiSelectWithCheckboxesWithoutClearAllButton: Story = { }; function AsAControlled({ ...arguments_ }): JSX.Element { - const [selected, updateSelected] = useState(arguments_.value); - const [, updateArguments] = useArgs(); + const [{ value }, updateArguments] = useArgs(); return ( <> @@ -177,7 +175,6 @@ function AsAControlled({ ...arguments_ }): JSX.Element {