Skip to content

Commit

Permalink
feat: add direction prop to #dropdown so the dropdown can show the op…
Browse files Browse the repository at this point in the history
…tions opening from the top
  • Loading branch information
tujoworker committed Apr 11, 2019
1 parent dfc15e8 commit b96b9e0
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ draft: true

import { Data } from 'Pages/uilib/components/dropdown/Examples'

| Properties | Description |
| --------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `data` | _(mandatory)_ the data we want to fill the list with. Provide the data as a json string or data array structure. |
| `selected_item` | _(optional)_ a number as a string or integer, defines the active item in the data array. The default value is the first item. |
| `icon` | _(optional)_ name of icon to be included in the dropdown. |
| `icon_position` | _(optional)_ position of icon inside the dropdown. Set to `left` or `right`. Defaults to `right` if not set. |
| `disabled` | _(optional)_ to disable/enable the dropdown without using the `attribute` property. |
| `id` | _(optional)_ the `id` of the input. |
| Properties | Description |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `data` | _(mandatory)_ the data we want to fill the list with. Provide the data as a json string or data array structure. |
| `selected_item` | _(optional)_ a number as a string or integer, defines the active item in the data array. The default value is the first item. |
| `icon` | _(optional)_ name of icon to be included in the dropdown. |
| `icon_position` | _(optional)_ position of icon inside the dropdown. Set to `left` or `right`. Defaults to `right` if not set. |
| `disabled` | _(optional)_ to disable/enable the dropdown without using the `attribute` property. |
| `direction` | _(optional)_ defines the direction of how the dropdown shows the options. Can be `top` or `bottom`. Defaults to `auto`. |
| `scrollable` | _(optional)_ defines if the dropdown options should be scrollable (the `max-height` is set by default to `50vh`). Defaults to `true`. |

## Data structure

Expand Down
24 changes: 19 additions & 5 deletions packages/dnb-ui-lib/src/components/dropdown/Dropdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export const propTypes = {
status_state: PropTypes.string,
status_animation: PropTypes.string,
scrollable: PropTypes.bool,
direction: PropTypes.oneOf(['auto', 'top', 'bottom']),
no_animation: PropTypes.bool,
data: PropTypes.oneOfType([
PropTypes.string,
Expand Down Expand Up @@ -79,7 +80,8 @@ export const defaultProps = {
status: null,
status_state: 'error',
status_animation: null,
scrollable: false,
scrollable: true,
direction: 'auto',
no_animation: false,
data: null,
selected_item: 0,
Expand Down Expand Up @@ -337,6 +339,15 @@ export default class Dropdown extends Component {
}
}

selectItemHandler = e => {
const selected_item = parseFloat(
e.currentTarget.getAttribute('data-item')
)
if (selected_item > -1) {
this.selectItem(selected_item, { fireSelectEvent: true })
}
}

selectItem = (selected_item, { fireSelectEvent } = {}) => {
if (this.state.selected_item !== selected_item) {
dispatchCustomElementEvent(this, 'on_change', {
Expand All @@ -345,6 +356,7 @@ export default class Dropdown extends Component {
}
this.setState({
selected_item,
active_item: selected_item,
_listenForPropChanges: false
})
if (fireSelectEvent) {
Expand Down Expand Up @@ -372,6 +384,7 @@ export default class Dropdown extends Component {
status_state,
status_animation,
scrollable,
direction,
no_animation,
className,
class: _className,
Expand All @@ -395,6 +408,7 @@ export default class Dropdown extends Component {
const classes = classnames(
'dnb-dropdown',
icon_position && `dnb-dropdown--icon-position-${icon_position}`,
direction === 'bottom' && `dnb-dropdown--direction-bottom`,
scrollable && 'dnb-dropdown--scroll',
opened && 'dnb-dropdown--opened',
hidden && 'dnb-dropdown--hidden',
Expand Down Expand Up @@ -490,7 +504,6 @@ export default class Dropdown extends Component {
</button>

<span className="dnb-dropdown__list">
<span className="dnb-dropdown__triangle" />
<ul {...ulParams}>
{this.state.data.map((dataItem, i) => {
const isCurrent = i === parseFloat(selected_item)
Expand All @@ -509,9 +522,9 @@ export default class Dropdown extends Component {
<span
title={Dropdown.parseContentTitle(dataItem)}
className="dnb-dropdown__option__inner"
onMouseDown={() =>
this.selectItem(i, { fireSelectEvent: true })
}
data-item={i}
onTouchStart={this.selectItemHandler}
onMouseDown={this.selectItemHandler}
role="button"
tabIndex="-1"
>
Expand All @@ -533,6 +546,7 @@ export default class Dropdown extends Component {
)
})}
</ul>
<span className="dnb-dropdown__triangle" />
</span>
</span>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ exports[`Dropdown component have to match snapshot 1`] = `
},
]
}
direction="'auto'"
disabled="disabled"
icon="icon"
icon_position="icon_position"
Expand Down Expand Up @@ -137,9 +138,6 @@ exports[`Dropdown component have to match snapshot 1`] = `
<span
className="dnb-dropdown__list"
>
<span
className="dnb-dropdown__triangle"
/>
<ul
aria-activedescendant="option-dropdown-id-2"
aria-labelledby="dropdown-id"
Expand All @@ -156,7 +154,9 @@ exports[`Dropdown component have to match snapshot 1`] = `
>
<span
className="dnb-dropdown__option__inner"
data-item={0}
onMouseDown={[Function]}
onTouchStart={[Function]}
role="button"
tabIndex="-1"
title="Brukskonto - Kari Nordmann"
Expand Down Expand Up @@ -184,7 +184,9 @@ exports[`Dropdown component have to match snapshot 1`] = `
>
<span
className="dnb-dropdown__option__inner"
data-item={1}
onMouseDown={[Function]}
onTouchStart={[Function]}
role="button"
tabIndex="-1"
title="Sparekonto - Ole Nordmann"
Expand Down Expand Up @@ -212,7 +214,9 @@ exports[`Dropdown component have to match snapshot 1`] = `
>
<span
className="dnb-dropdown__option__inner"
data-item={2}
onMouseDown={[Function]}
onTouchStart={[Function]}
role="button"
tabIndex="-1"
title="Feriekonto - Kari Nordmann med et kjempelangt etternavnsen"
Expand Down Expand Up @@ -240,7 +244,9 @@ exports[`Dropdown component have to match snapshot 1`] = `
>
<span
className="dnb-dropdown__option__inner"
data-item={3}
onMouseDown={[Function]}
onTouchStart={[Function]}
role="button"
tabIndex="-1"
title="Oppussing - Ole Nordmann"
Expand All @@ -260,6 +266,9 @@ exports[`Dropdown component have to match snapshot 1`] = `
</span>
</li>
</ul>
<span
className="dnb-dropdown__triangle"
/>
</span>
</span>
<FormStatus
Expand Down Expand Up @@ -385,7 +394,7 @@ exports[`Dropdown scss have to match default theme snapshot 1`] = `
color: var(--dropdown-option-color--hover);
background-color: var(--dropdown-option-background-color--hover); }
.dnb-dropdown__option--focus .dnb-dropdown__option__inner {
box-shadow: 0 0 0 2px var(--dropdown-border-color--selected);
box-shadow: 0 0 0 var(--dropdown-focus-border-width, 2px) var(--dropdown-border-color--selected);
border-color: transparent; }
.dnb-dropdown__option--selected {
color: var(--dropdown-option-color--selected);
Expand Down Expand Up @@ -447,10 +456,6 @@ exports[`Dropdown scss have to match default theme snapshot 1`] = `
border: none;
background-color: var(--color-white);
box-shadow: 0 1px 6px rgba(0, 0, 0, 0.16); }
.dnb-dropdown__option--selected .dnb-dropdown__triangle::before {
background-color: var(--dropdown-option-background-color--selected); }
.dnb-dropdown__option:not(.dnb-dropdown__option--selected):hover .dnb-dropdown__triangle::before {
background-color: var(--dropdown-option-background-color--hover); }
.dnb-dropdown__input[disabled] ~ .dnb-dropdown__icon,
.dnb-dropdown__input[disabled] ~ .dnb-dropdown__trigger {
border-color: var(--dropdown-text-color--disabled);
Expand Down Expand Up @@ -729,6 +734,7 @@ exports[`Dropdown scss have to match snapshot 1`] = `
--dropdown-height: 2rem;
--dropdown-padding-horizontal: 1rem;
--dropdown-border-width: 0.0625rem;
--dropdown-focus-border-width: 0.125rem;
--dropdown-text-padding: 0.5rem;
--dropdown-border-radius: calc(var(--dropdown-height) / 2); }
Expand Down Expand Up @@ -781,6 +787,9 @@ exports[`Dropdown scss have to match snapshot 1`] = `
background-color: transparent;
transform: translateY(0);
transition: transform 200ms, opacity 160ms ease-out; }
.dnb-dropdown--direction-bottom .dnb-dropdown__list {
top: auto;
bottom: calc( var(--dropdown-height) * 2 + var(--dropdown-focus-border-width)); }
.dnb-dropdown__options {
display: flex;
flex-direction: column;
Expand All @@ -792,15 +801,15 @@ exports[`Dropdown scss have to match snapshot 1`] = `
.dnb-spacing .dnb-dropdown__options li {
margin: 0; }
.dnb-dropdown--scroll .dnb-dropdown__options {
max-height: 20rem;
max-height: 50vh;
overflow-y: scroll;
overscroll-behavior: contain;
scroll-behavior: smooth; }
.dnb-dropdown__option {
position: relative;
cursor: pointer;
margin: 0;
padding: 2px;
padding: var(--dropdown-focus-border-width);
color: inherit;
background-color: var(--color-white); }
.dnb-dropdown__option__inner {
Expand Down Expand Up @@ -845,7 +854,7 @@ exports[`Dropdown scss have to match snapshot 1`] = `
color: inherit; }
.dnb-dropdown__triangle {
position: absolute;
top: calc(2px - var(--dropdown-height) / 2);
top: calc( var(--dropdown-focus-border-width) - var(--dropdown-height) / 2);
left: auto;
right: 0;
margin: 0 calc( var(--dropdown-padding-horizontal) + var(--dropdown-border-width));
Expand All @@ -865,6 +874,10 @@ exports[`Dropdown scss have to match snapshot 1`] = `
.dnb-dropdown--icon-position-left .dnb-dropdown__triangle {
left: 0;
right: auto; }
.dnb-dropdown--direction-bottom .dnb-dropdown__triangle {
top: auto;
bottom: calc( var(--dropdown-focus-border-width) - var(--dropdown-height) / 2);
transform: rotate(180deg); }
.dnb-dropdown__trigger {
position: relative;
z-index: 1;
Expand Down
25 changes: 22 additions & 3 deletions packages/dnb-ui-lib/src/components/dropdown/style/_dropdown.scss
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
--dropdown-height: 2rem;
--dropdown-padding-horizontal: 1rem;
--dropdown-border-width: 0.0625rem;
--dropdown-focus-border-width: 0.125rem;
--dropdown-text-padding: 0.5rem;
--dropdown-border-radius: calc(var(--dropdown-height) / 2);
}
Expand Down Expand Up @@ -109,6 +110,13 @@
transition: transform 200ms, opacity 160ms ease-out;
}

&--direction-bottom &__list {
top: auto;
bottom: calc(
var(--dropdown-height) * 2 + var(--dropdown-focus-border-width)
);
}

// ul element
&__options {
@at-root .dnb-spacing & li {
Expand All @@ -127,7 +135,7 @@
}

&--scroll &__options {
max-height: 20rem;
max-height: 50vh;
overflow-y: scroll;
overscroll-behavior: contain;
scroll-behavior: smooth;
Expand All @@ -140,7 +148,9 @@
cursor: pointer;

margin: 0;
padding: 2px; // to make space for the fakeFocus
padding: var(
--dropdown-focus-border-width
); // to make space for the fakeFocus
color: inherit;

background-color: var(--color-white);
Expand Down Expand Up @@ -209,7 +219,9 @@

&__triangle {
position: absolute;
top: calc(2px - var(--dropdown-height) / 2);
top: calc(
var(--dropdown-focus-border-width) - var(--dropdown-height) / 2
);
left: auto;
right: 0;
margin: 0
Expand Down Expand Up @@ -240,6 +252,13 @@
left: 0;
right: auto;
}
&--direction-bottom &__triangle {
top: auto;
bottom: calc(
var(--dropdown-focus-border-width) - var(--dropdown-height) / 2
);
transform: rotate(180deg);
}

// button
&__trigger {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,10 @@
// Focus ring arround item. Only for keyboard usage
&--focus {
.dnb-dropdown__option__inner {
@include fakeBorder(var(--dropdown-border-color--selected), 2px);
@include fakeBorder(
var(--dropdown-border-color--selected),
var(--dropdown-focus-border-width, 2px)
);
}
}

Expand Down Expand Up @@ -164,13 +167,14 @@
background-color: var(--color-white);
@include defaultDropShadow();
}
&__option--selected &__triangle::before {
background-color: var(--dropdown-option-background-color--selected);
}
&__option:not(.dnb-dropdown__option--selected):hover
&__triangle::before {
background-color: var(--dropdown-option-background-color--hover);
}
// Hover etc. is not working anymore, as we have the triangle outside
// &__option--selected &__triangle::before {
// background-color: var(--dropdown-option-background-color--selected);
// }
// &__option:not(.dnb-dropdown__option--selected):hover
// &__triangle::before {
// background-color: var(--dropdown-option-background-color--hover);
// }

&__input[disabled] ~ &__icon,
&__input[disabled] ~ &__trigger {
Expand Down

0 comments on commit b96b9e0

Please sign in to comment.