Skip to content

Commit

Permalink
feat(SelectCountry): use autocomplete instead of dropdown (#3023)
Browse files Browse the repository at this point in the history
With that change we support browser auto-fill and much quicker UX search
ability. Also, users can search in both/all locales at the same time.

Fixes #2993
  • Loading branch information
tujoworker authored Dec 8, 2023
1 parent 6fb8d4a commit 0f2990c
Show file tree
Hide file tree
Showing 16 changed files with 601 additions and 71 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import DataValueReadwriteProperties from '../../data-value-readwrite-properties.
| --------------------------------------- | ------------------- | ----------------------------------------------------------------------------------------------------------- |
| `pattern` | `boolean` | _(optional)_ Validation based on regex pattern for the number field e.g. `pattern="^[49]+"`. |
| `help` | `object` | _(optional)_ Provide a help button. Object consisting of `title` and `contents`. |
| `countries` | `string` | _(optional)_ List only a certain set of countries: `Scandinavia`, `NorthernNordic` or `Europe`. |
| `countries` | `string` | _(optional)_ List only a certain set of countries: `Scandinavia`, `Nordic` or `Europe`. |
| `omitCountryCodeField` | `boolean` | _(optional)_ If `true` is given, then everything related to country code is removed. |
| `countryCodeFieldClassName` | `string` | _(optional)_ Class name for the country code component. |
| `numberFieldClassName` | `string` | _(optional)_ Class name for the number component. |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,19 @@ When selecting a country, the value returned is the selected country's [ISO 3166
import { Field } from '@dnb/eufemia/extensions/forms'
render(<Field.SelectCountry />)
```

It supports the HTML [autofill](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete) attribute (`country-name`) if no value is given.

### Filter or prioritize country listing

Countries are sorted in alphabetically order. You can filter countries with the `countries` property or put these countries on top of the list:

- Norway
- Sweden
- Denmark
- Finland

```jsx
import { Field } from '@dnb/eufemia/extensions/forms'
render(<Field.PhoneNumber countries="Prioritized" />)
```
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ import DataValueReadwriteProperties from '../../data-value-readwrite-properties.

### Component-specific props

| Property | Type | Description |
| --------------------------------------- | -------- | -------------------------------------------------------------------------------- |
| `help` | `object` | _(optional)_ Provide a help button. Object consisting of `title` and `contents`. |
| [Space](/uilib/layout/space/properties) | Various | _(optional)_ Spacing properties like `top` or `bottom` are supported. |
| Property | Type | Description |
| --------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------ |
| `help` | `object` | _(optional)_ Provide a help button. Object consisting of `title` and `contents`. |
| `countries` | `string` | _(optional)_ List only a certain set of countries: `Scandinavia`, `Nordic`, `Europe` or `Prioritized`. |
| [Space](/uilib/layout/space/properties) | Various | _(optional)_ Spacing properties like `top` or `bottom` are supported. |

<DataValueReadwriteProperties type="string" />
22 changes: 15 additions & 7 deletions packages/dnb-eufemia/src/components/autocomplete/Autocomplete.js
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,10 @@ class AutocompleteInstance extends React.PureComponent {

setHidden = (args = null, onStateComplete = null) => {
this.context.drawerList.setHidden(args, onStateComplete)
this.setState({
hasFocus: false,
hasBlur: false,
})
}

toggleVisible = (args = null, onStateComplete = null) => {
Expand Down Expand Up @@ -528,7 +532,7 @@ class AutocompleteInstance extends React.PureComponent {
this.setVisible(null, onStateComplete)
}

onInputChangeHandler = ({ value, event }, options = {}) => {
onInputChangeHandler = ({ value, event }) => {
this.setState({
typedInputValue: value,
inputValue: value,
Expand All @@ -543,7 +547,7 @@ class AutocompleteInstance extends React.PureComponent {

value = String(value).trim()
if (value !== this.state.inputValue) {
this.runFilterWithSideEffects(value, options)
this.runFilterWithSideEffects(value)
}
}

Expand All @@ -558,9 +562,7 @@ class AutocompleteInstance extends React.PureComponent {
if (value && value.length > 0) {
// show the "no_options" message
if (count === 0) {
if (this.state.mode !== 'async') {
this.showNoOptionsItem()
}
this.showNoOptionsItem()
} else if (count > 0) {
this.context.drawerList.setData(this.wrapWithShowAll(data))
this.context.drawerList.setState({
Expand Down Expand Up @@ -588,8 +590,10 @@ class AutocompleteInstance extends React.PureComponent {
}

// Opens the drawer, also when pressing on the clear button
this.setVisible()
this.setAriaLiveUpdate()
if (this.state.hasFocus) {
this.setVisible()
this.setAriaLiveUpdate()
}

return data
}
Expand Down Expand Up @@ -722,6 +726,9 @@ class AutocompleteInstance extends React.PureComponent {
}

showNoOptionsItem = () => {
if (this.state.mode === 'async') {
return
}
this.resetActiveItem()
this.ignoreEvents()
this.context.drawerList.setData([
Expand Down Expand Up @@ -1117,6 +1124,7 @@ class AutocompleteInstance extends React.PureComponent {
clearInputValue: this.clearInputValue,
showAllItems: this.showAllItems,
setVisible: this.setVisible,
resetInputValue: this.resetInputValue,
setHidden: this.setHidden,
emptyData: this.emptyData,
focusInput: this.focusInput,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -356,9 +356,12 @@ describe('Autocomplete component', () => {
/>
)

const inputElement = document.querySelector('.dnb-input__input')

toggle()

fireEvent.change(document.querySelector('.dnb-input__input'), {
fireEvent.focus(inputElement)
fireEvent.change(inputElement, {
target: { value: 'bb' },
})

Expand All @@ -372,7 +375,7 @@ describe('Autocomplete component', () => {
.textContent
).toBe(mockData[1])

fireEvent.change(document.querySelector('.dnb-input__input'), {
fireEvent.change(inputElement, {
target: { value: 'cc' },
})

Expand All @@ -386,7 +389,7 @@ describe('Autocomplete component', () => {
.textContent
).toBe((content as string[]).join(''))

fireEvent.change(document.querySelector('.dnb-input__input'), {
fireEvent.change(inputElement, {
target: { value: 'c' },
})

Expand All @@ -399,7 +402,7 @@ describe('Autocomplete component', () => {
.textContent
).toBe((content as string[]).join(''))

fireEvent.change(document.querySelector('.dnb-input__input'), {
fireEvent.change(inputElement, {
target: { value: 'invalid' },
})

Expand Down Expand Up @@ -748,6 +751,7 @@ describe('Autocomplete component', () => {
document.querySelectorAll('li.dnb-drawer-list__option')

// check "cc"
fireEvent.focus(inputElement)
fireEvent.change(inputElement, {
target: { value: 'cc' },
})
Expand Down Expand Up @@ -1180,6 +1184,7 @@ describe('Autocomplete component', () => {

expect(document.querySelector('input').value).toBe('')

fireEvent.focus(document.querySelector('input'))
fireEvent.change(document.querySelector('input'), {
target: { value: 'cc' },
})
Expand All @@ -1204,6 +1209,7 @@ describe('Autocomplete component', () => {
expect(on_change).toHaveBeenCalledTimes(2)
expect(on_change.mock.calls[1][0].data).toEqual(undefined)

fireEvent.focus(document.querySelector('input'))
fireEvent.change(document.querySelector('input'), {
target: { value: 'cc' },
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1002,9 +1002,6 @@ button .dnb-form-status__text {
.dnb-input__input::-ms-clear {
display: none;
}
.dnb-input__input:autofill {
box-shadow: 0 0 0 var(--input-border-width) var(--input-border-color), 0 0 0 10em var(--input-background-color) inset;
}
.dnb-input ::-webkit-file-upload-button {
cursor: pointer;
outline: none;
Expand Down Expand Up @@ -1036,6 +1033,9 @@ button .dnb-form-status__text {
display: inline-flex;
align-items: center;
}
.dnb-input__input:autofill {
box-shadow: 0 0 0 var(--input-border-width) var(--input-border-color) var(--autofill-inset, inset), 0 0 0 10em var(--input-background-color) inset;
}
.dnb-input__suffix {
color: inherit;
}
Expand Down Expand Up @@ -1223,6 +1223,7 @@ html:not([data-whatintent=touch]) .dnb-input--clear.dnb-input__submit-element .d
.dnb-input__icon {
order: 0;
position: absolute;
z-index: 2;
left: 1rem;
right: auto;
top: 0;
Expand All @@ -1249,6 +1250,9 @@ html:not([data-whatintent=touch]) .dnb-input--clear.dnb-input__submit-element .d
html[data-visual-test] .dnb-input__input {
caret-color: var(--color-white);
}
.dnb-input[data-has-content=false] .dnb-input__input:focus:autofill {
--autofill-inset: none;
}
@media screen and (max-width: 40em) {
.dnb-responsive-component .dnb-input {
display: flex;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1002,9 +1002,6 @@ button .dnb-form-status__text {
.dnb-input__input::-ms-clear {
display: none;
}
.dnb-input__input:autofill {
box-shadow: 0 0 0 var(--input-border-width) var(--input-border-color), 0 0 0 10em var(--input-background-color) inset;
}
.dnb-input ::-webkit-file-upload-button {
cursor: pointer;
outline: none;
Expand Down Expand Up @@ -1036,6 +1033,9 @@ button .dnb-form-status__text {
display: inline-flex;
align-items: center;
}
.dnb-input__input:autofill {
box-shadow: 0 0 0 var(--input-border-width) var(--input-border-color) var(--autofill-inset, inset), 0 0 0 10em var(--input-background-color) inset;
}
.dnb-input__suffix {
color: inherit;
}
Expand Down Expand Up @@ -1223,6 +1223,7 @@ html:not([data-whatintent=touch]) .dnb-input--clear.dnb-input__submit-element .d
.dnb-input__icon {
order: 0;
position: absolute;
z-index: 2;
left: 1rem;
right: auto;
top: 0;
Expand All @@ -1249,6 +1250,9 @@ html:not([data-whatintent=touch]) .dnb-input--clear.dnb-input__submit-element .d
html[data-visual-test] .dnb-input__input {
caret-color: var(--color-white);
}
.dnb-input[data-has-content=false] .dnb-input__input:focus:autofill {
--autofill-inset: none;
}
@media screen and (max-width: 40em) {
.dnb-responsive-component .dnb-input {
display: flex;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1002,9 +1002,6 @@ button .dnb-form-status__text {
.dnb-input__input::-ms-clear {
display: none;
}
.dnb-input__input:autofill {
box-shadow: 0 0 0 var(--input-border-width) var(--input-border-color), 0 0 0 10em var(--input-background-color) inset;
}
.dnb-input ::-webkit-file-upload-button {
cursor: pointer;
outline: none;
Expand Down Expand Up @@ -1036,6 +1033,9 @@ button .dnb-form-status__text {
display: inline-flex;
align-items: center;
}
.dnb-input__input:autofill {
box-shadow: 0 0 0 var(--input-border-width) var(--input-border-color) var(--autofill-inset, inset), 0 0 0 10em var(--input-background-color) inset;
}
.dnb-input__suffix {
color: inherit;
}
Expand Down Expand Up @@ -1223,6 +1223,7 @@ html:not([data-whatintent=touch]) .dnb-input--clear.dnb-input__submit-element .d
.dnb-input__icon {
order: 0;
position: absolute;
z-index: 2;
left: 1rem;
right: auto;
top: 0;
Expand All @@ -1249,6 +1250,9 @@ html:not([data-whatintent=touch]) .dnb-input--clear.dnb-input__submit-element .d
html[data-visual-test] .dnb-input__input {
caret-color: var(--color-white);
}
.dnb-input[data-has-content=false] .dnb-input__input:focus:autofill {
--autofill-inset: none;
}
@media screen and (max-width: 40em) {
.dnb-responsive-component .dnb-input {
display: flex;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -995,9 +995,6 @@ button .dnb-form-status__text {
.dnb-input__input::-ms-clear {
display: none;
}
.dnb-input__input:autofill {
box-shadow: 0 0 0 var(--input-border-width) var(--input-border-color), 0 0 0 10em var(--input-background-color) inset;
}
.dnb-input ::-webkit-file-upload-button {
cursor: pointer;
outline: none;
Expand Down Expand Up @@ -1029,6 +1026,9 @@ button .dnb-form-status__text {
display: inline-flex;
align-items: center;
}
.dnb-input__input:autofill {
box-shadow: 0 0 0 var(--input-border-width) var(--input-border-color) var(--autofill-inset, inset), 0 0 0 10em var(--input-background-color) inset;
}
.dnb-input__suffix {
color: inherit;
}
Expand Down Expand Up @@ -1216,6 +1216,7 @@ html:not([data-whatintent=touch]) .dnb-input--clear.dnb-input__submit-element .d
.dnb-input__icon {
order: 0;
position: absolute;
z-index: 2;
left: 1rem;
right: auto;
top: 0;
Expand All @@ -1242,6 +1243,9 @@ html:not([data-whatintent=touch]) .dnb-input--clear.dnb-input__submit-element .d
html[data-visual-test] .dnb-input__input {
caret-color: var(--color-white);
}
.dnb-input[data-has-content=false] .dnb-input__input:focus:autofill {
--autofill-inset: none;
}
@media screen and (max-width: 40em) {
.dnb-responsive-component .dnb-input {
display: flex;
Expand Down
22 changes: 14 additions & 8 deletions packages/dnb-eufemia/src/components/input/style/dnb-input.scss
Original file line number Diff line number Diff line change
Expand Up @@ -118,14 +118,6 @@
display: none;
}

// change the autocomplete appearance once filled out
&__input:autofill {
// set the border and the background
box-shadow:
0 0 0 var(--input-border-width) var(--input-border-color),
0 0 0 10em var(--input-background-color) inset;
}

// change file type appearance on type="file"
::-webkit-file-upload-button {
cursor: pointer;
Expand Down Expand Up @@ -174,6 +166,15 @@
align-items: center; // Safari gets wired if we use "baseline"
}

// change the autocomplete appearance once filled out
&__input:autofill {
// set the border and the background
box-shadow:
0 0 0 var(--input-border-width) var(--input-border-color)
var(--autofill-inset, inset),
0 0 0 10em var(--input-background-color) inset;
}

&__suffix {
color: inherit;
}
Expand Down Expand Up @@ -431,6 +432,7 @@
&__icon {
order: 0;
position: absolute;
z-index: 2; // to ensure its still visible on autofill
left: 1rem;
right: auto;

Expand Down Expand Up @@ -467,6 +469,10 @@
caret-color: var(--color-white);
}

&[data-has-content='false'] &__input:focus:autofill {
--autofill-inset: none;
}

.dnb-responsive-component & {
@media screen and (max-width: 40em) {
display: flex;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export type Props = FieldHelpProps &
omitCountryCodeField?: boolean
onCountryCodeChange?: (value: string | undefined) => void
onNumberChange?: (value: string | undefined) => void
countries?: 'Scandinavia' | 'NorthernNordic' | 'Europe'
countries?: 'Scandinavia' | 'Nordic' | 'Europe'

/**
* For internal use only.
Expand Down Expand Up @@ -111,7 +111,7 @@ function PhoneNumber(props: Props) {
? (country) => {
switch (ccFilter) {
case 'Scandinavia':
case 'NorthernNordic':
case 'Nordic':
return country.regions?.includes(ccFilter)
default:
return country.continent.includes(ccFilter)
Expand Down
Loading

0 comments on commit 0f2990c

Please sign in to comment.