1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-23 09:52:26 +01:00

Add dropdown component (#8524)

This new dropdown component uses a native `select` element, thus
avoiding various issues encountered in attempting to reuse our existing
dropdown components for the new permission system alert modal.

The prefixed forms of `appearance` have been added temporarily so that
the component can be used in Storybook, as our Storybook config isn't
setup to do autoprefixing yet. Our real build system does handle
autoprefixing for this rule correctly already.
This commit is contained in:
Mark Stacey 2020-05-06 11:48:38 -03:00 committed by GitHub
parent 351424df7d
commit 8a12257f8e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 178 additions and 0 deletions

View File

@ -100,6 +100,8 @@
@import '../ui/check-box/index'; @import '../ui/check-box/index';
@import '../ui/dropdown/dropdown';
@import 'permissions-connect-header/index'; @import 'permissions-connect-header/index';
@import 'permissions-connect-footer/index'; @import 'permissions-connect-footer/index';

View File

@ -0,0 +1,63 @@
import React, { useCallback } from 'react'
import PropTypes from 'prop-types'
import classnames from 'classnames'
const Dropdown = ({ className, disabled, onChange, options, selectedOption, style, title }) => {
const _onChange = useCallback(
(event) => {
event.preventDefault()
event.stopPropagation()
onChange(event.target.value)
},
[onChange],
)
return (
<select
className={classnames('dropdown', className)}
disabled={disabled}
title={title}
onChange={_onChange}
style={style}
value={selectedOption}
>
{
options.map((option) => {
return (
<option
key={option.value}
value={option.value}
>
{ option.name || option.value }
</option>
)
})
}
</select>
)
}
Dropdown.propTypes = {
className: PropTypes.string,
disabled: PropTypes.bool,
title: PropTypes.string,
onChange: PropTypes.func.isRequired,
options: PropTypes.arrayOf(
PropTypes.exact({
name: PropTypes.string,
value: PropTypes.string.isRequired,
})
).isRequired,
selectedOption: PropTypes.string,
style: PropTypes.object,
}
Dropdown.defaultProps = {
className: undefined,
disabled: false,
title: undefined,
selectedOption: null,
style: undefined,
}
export default Dropdown

View File

@ -0,0 +1,22 @@
.dropdown {
appearance: none;
// TODO: remove these after getting autoprefixer working in Storybook
-moz-appearance: none;
-webkit-appearance: none;
border: 1px solid $Grey-500;
border-radius: 6px;
background-image: url('/images/icons/caret-down.svg');
background-repeat: no-repeat, repeat;
background-position: right 18px top 50%;
background-color: white;
padding: 8px 32px 8px 16px;
font-family: Roboto, 'sans-serif';
font-size: 14px;
[dir='rtl'] & {
background-position: left 18px top 50%;
padding: 8px 16px 8px 32px;
}
}

View File

@ -0,0 +1,90 @@
import React from 'react'
import { action } from '@storybook/addon-actions'
import Dropdown from '.'
import { boolean, select, text } from '@storybook/addon-knobs/react'
export default {
title: 'Dropdown',
}
const unnamedOptions = [...Array(10).keys()].map((index) => {
return { value: `option${index}` }
})
const namedOptions = unnamedOptions.map((option, index) => {
return Object.assign({}, option, { name: `Option ${index}` })
})
const namedOptionsWithVeryLongNames = unnamedOptions.map((option, index) => {
return Object.assign({}, option, { name: `Option ${index} with a very${', very'.repeat(index)} long name` })
})
export const simple = () => (
<Dropdown
disabled={boolean('Disabled', false)}
title={text('Title', 'Test dropdown name')}
onChange={action('Selection changed')}
options={namedOptions}
required={boolean('Required', false)}
selectedOption={
select(
'Selected Option',
namedOptions.map((option) => option.value),
namedOptions[0].value
)
}
/>
)
export const optionsWithoutNames = () => (
<Dropdown
disabled={boolean('Disabled', false)}
title={text('Title', 'Test dropdown name')}
onChange={action('Selection changed')}
options={unnamedOptions}
required={boolean('Required', false)}
selectedOption={
select(
'Selected Option',
unnamedOptions.map((option) => option.value),
unnamedOptions[0].value
)
}
/>
)
export const optionsWithLongNames = () => (
<Dropdown
disabled={boolean('Disabled', false)}
title={text('Title', 'Test dropdown name')}
onChange={action('Selection changed')}
options={namedOptionsWithVeryLongNames}
required={boolean('Required', false)}
selectedOption={
select(
'Selected Option',
namedOptionsWithVeryLongNames.map((option) => option.value),
namedOptionsWithVeryLongNames[0].value
)
}
/>
)
export const optionsWithLongNamesAndShortWidth = () => (
<Dropdown
disabled={boolean('Disabled', false)}
title={text('Title', 'Test dropdown name')}
onChange={action('Selection changed')}
options={namedOptionsWithVeryLongNames}
required={boolean('Required', false)}
selectedOption={
select(
'Selected Option',
namedOptionsWithVeryLongNames.map((option) => option.value),
namedOptionsWithVeryLongNames[0].value
)
}
style={{ width: '200px' }}
/>
)

View File

@ -0,0 +1 @@
export { default } from './dropdown'