Skip to content
This repository was archived by the owner on Apr 26, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .storybook/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ module.exports = ({ config }) => {
});

config.module.rules.push({
test: /\.(svg)$/,
test: /\.(svg|png|jpg)$/i,
use: [
{
loader: 'url-loader',
Expand Down
Binary file added src/inputs/Select/dai.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/inputs/Select/gnosis.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
60 changes: 54 additions & 6 deletions src/inputs/Select/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ import FormControl from '@material-ui/core/FormControl';
import SelectMUI from '@material-ui/core/Select';
import styled from 'styled-components';

import { Text } from '../../dataDisplay';

const IconImg = styled.img`
width: 20px;
margin-right: 10px;
`;

const StyledSelect = styled(SelectMUI)`
background-color: #e8e7e6;
background-color: ${(props) => props.theme.colors.separator};
border-radius: 5px;
height: 56px;
width: 140px;
Expand All @@ -22,18 +24,40 @@ const StyledSelect = styled(SelectMUI)`
}

.MuiSelect-selectMenu {
font-family: ${(p) => p.theme.fonts.fontFamily};
font-family: ${(props) => props.theme.fonts.fontFamily};
}

&.MuiInput-underline:hover:not(.Mui-disabled):before {
border-bottom: 2px solid ${(props) => props.theme.colors.primary};
}
&.MuiInput-underline:after {
border-bottom: 2px solid ${(props) => props.theme.colors.primary};
}
`;

export type SelectItem = {
id: string;
label: string;
subLabel?: string;
iconUrl?: string;
};

type Props = {
items: Array<{ id: string; label: string; iconUrl?: string }>;
items: Array<SelectItem>;
activeItemId: string;
onItemClick: (id: string) => void;
id?: string;
fallbackImage?: string;
};

function Select({ items, activeItemId, onItemClick, id, ...rest }: Props) {
function Select({
items,
activeItemId,
onItemClick,
id,
fallbackImage,
...rest
}: Props) {
const [open, setOpen] = React.useState(false);

const handleChange = (event: React.ChangeEvent<{ value: unknown }>) => {
Expand All @@ -48,6 +72,15 @@ function Select({ items, activeItemId, onItemClick, id, ...rest }: Props) {
setOpen(true);
};

const onFallbackImage: React.ReactEventHandler<HTMLImageElement> = (e) => {
if (!fallbackImage) {
return;
}

(e.target as HTMLImageElement).onerror = null;
(e.target as HTMLImageElement).src = fallbackImage;
};

return (
<div>
<FormControl>
Expand All @@ -63,8 +96,23 @@ function Select({ items, activeItemId, onItemClick, id, ...rest }: Props) {
{items.map((i) => {
return (
<MenuItem value={i.id} key={i.id}>
{i.iconUrl && <IconImg alt={i.label} src={i.iconUrl} />}
<span>{i.label}</span>
{i.iconUrl && (
<IconImg
alt={i.label}
onError={onFallbackImage}
src={i.iconUrl}
/>
)}
<div>
<Text size="sm" color="text">
{i.label}
</Text>
{i.subLabel && (
<Text size="sm" color="secondary" strong>
{i.subLabel}
</Text>
)}
</div>
</MenuItem>
);
})}
Expand Down
22 changes: 14 additions & 8 deletions src/inputs/Select/select.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,35 @@
import React, { useState } from 'react';

import Select from './';
import gnoIcon from './gnosis.png';
import daiIcon from './dai.png';
import tokenPlaceholder from './token-placeholder.svg';
import Select, { SelectItem } from './';

export default {
title: 'Inputs/Select',
component: Select,
parameters: {
componentSubtitle: 'Checkbox Input.'
componentSubtitle: 'Select Input.'
}
};

const items = [
{ id: '1', label: 'ETH' },
{ id: '2', label: 'GNO' }
];

export const select = () => {
const items: Array<SelectItem> = [
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

moved here, so it's shown in storybook example.

{ id: '1', label: 'DAI', subLabel: 'stablecoin', iconUrl: daiIcon },
{ id: '2', label: 'GNO', iconUrl: gnoIcon },
{ id: '2', label: 'BrokenImage', iconUrl: 'https://broken-image.test' },
{ id: '3', label: 'without icon' }
];

const [activeItemId, setActiveItemId] = useState('');
return (
<Select
items={items}
activeItemId={activeItemId}
onItemClick={(id) => {
setActiveItemId(id);
}}
}}
fallbackImage={tokenPlaceholder} // image source or URL
/>
);
};
1 change: 1 addition & 0 deletions src/inputs/Select/token-placeholder.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/typings/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
declare module "*.png"
declare module '*.svg' {
import React = require('react');

Expand Down
2 changes: 1 addition & 1 deletion webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ module.exports = {
}
},
{
test: /\.(svg)$/i,
test: /\.(svg|png|jpg)$/i,
use: {
loader: 'url-loader',
options: {}
Expand Down