Skip to content

Commit

Permalink
frontend: update UI of add account dropdown to use react-select
Browse files Browse the repository at this point in the history
Identical UI with the select account dropdown in buy & sell page
with icon and coin name on the option and selected value.
  • Loading branch information
shonsirsha committed Nov 11, 2024
1 parent 074e758 commit f00344c
Show file tree
Hide file tree
Showing 2 changed files with 172 additions and 19 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
.dropdown {
appearance: none;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' aria-labelledby='chevron down' color='%23777'%3E%3Cdefs/%3E%3Cpolyline points='6 10 12 16 18 10'/%3E%3C/svg%3E%0A");
background-repeat: no-repeat;
font-weight: 400;
height: calc(var(--space-quarter) * 3);
padding: 0 calc(var(--space-quarter) + var(--space-eight));
}

.select {
margin-bottom: var(--space-half);
}

.select :global(.react-select__group-heading) {
color: var(--color-default);
font-size: var(--size-default);
margin: 0;
padding-right: var(--space-quarter);
text-transform: unset;
}

.select :global(.react-select__menu) {
background-color: var(--background-secondary);
z-index: 14;
}

.select :global(.react-select__option) {
background-color: var(--background-secondary);
}

.select :global(.react-select__option):hover {
background-color: var(--background-custom-select-hover);
}

.select :global(.react-select__option--is-selected),
.select :global(.react-select__option--is-selected):hover {
background-color: var(--background-custom-select-selected);
}

.select :global(.react-select__option--is-disabled) span {
color: var(--color-secondary);
}

.select :global(.react-select__option--is-disabled.react-select__option--is-selected):hover {
background-color: var(--background-custom-select-selected);
}

.select :global(.react-select__option--is-disabled):hover {
background-color: transparent;
}

.select :global(.react-select__option--is-selected) .balance {
color: var(--color-default);
}

.select :global(.react-select__control) {
background-color: var(--background-secondary);
padding: var(--space-quarter) var(--space-eight);
}

.select :global(.react-select__single-value) {
width: 100%;
}

.select :global(.react-select__option--is-selected) .selectLabelText {
color: var(--color-default);
}

.singleValueContainer {
align-items: center;
display: flex;
left: var(--space-quarter);
position: absolute;
width: 100%;
}


.valueContainer {
align-items: center;
color: var(--color-default);
display: flex;
}

.valueContainer > img {
width: 20px;
height: 20px;
}

.selectLabelText {
margin-left: 6px;
}
100 changes: 81 additions & 19 deletions frontends/web/src/routes/account/add/components/coin-dropdown.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@

/**
* Copyright 2021 Shift Crypto AG
* Copyright 2021-2024 Shift Crypto AG
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -16,39 +17,100 @@

import { useTranslation } from 'react-i18next';
import * as backendAPI from '@/api/backend';
import { Select } from '@/components/forms';
import Select, { components, SingleValueProps, OptionProps, SingleValue, DropdownIndicatorProps } from 'react-select';
import { Logo } from '@/components/icon/logo';
import styles from './coin-dropdown.module.css';

type TCoinDropDownProps = {
onChange: (coin: backendAPI.ICoin) => void;
supportedCoins: backendAPI.ICoin[];
value: string;
};

type TOption = {
label: string;
value: backendAPI.ICoin['coinCode'];
isDisabled: boolean;
}


const DropdownIndicator = (props: DropdownIndicatorProps<TOption>) => {
return (
<components.DropdownIndicator {...props}>
<div className={styles.dropdown} />
</components.DropdownIndicator>
);
};

const SelectSingleValue = (props: SingleValueProps<TOption>) => {
const { value, label } = props.data;
return (
<div className={styles.singleValueContainer}>
<components.SingleValue {...props}>
<div className={styles.valueContainer}>
<Logo coinCode={value} alt={label} />
<span className={styles.selectLabelText}>{label}</span>
</div>
</components.SingleValue>
</div>
);
};


const SelectOption = (props: OptionProps<TOption>) => {
const { label, value } = props.data;

return (
<components.Option {...props}>
<div className={styles.valueContainer}>
<Logo coinCode={value} alt={label} />
<span className={styles.selectLabelText}>{label}</span>
</div>
</components.Option>
);
};


export const CoinDropDown = ({
onChange,
supportedCoins,
value,
}: TCoinDropDownProps) => {
const { t } = useTranslation();

const options = [
{ label: t('buy.info.selectPlaceholder'), value: 'choose', isDisabled: true },
...supportedCoins.map(({ coinCode, name, canAddAccount }) => ({
value: coinCode,
label: name,
isDisabled: !canAddAccount,
})),
] as TOption[];

return (
<Select
className={styles.select}
classNamePrefix="react-select"
autoFocus
options={[
{
text: t('buy.info.selectPlaceholder'),
disabled: true,
value: 'choose',
},
...(supportedCoins).map(({ coinCode, name, canAddAccount }) => ({
value: coinCode,
text: name,
disabled: !canAddAccount,
}))
]}
onInput={e => onChange(supportedCoins.find(c => {
return c.coinCode === (e.target as HTMLSelectElement).value;
}) as backendAPI.ICoin)}
value={value}
id="coinCodeDropDown" />
isSearchable={false}
options={options}
onChange={(e) => {
const selectedOption = e as SingleValue<TOption>;
if (selectedOption) {
const selectedCoin = supportedCoins.find(c => c.coinCode === selectedOption.value);
if (selectedCoin) {
onChange(selectedCoin);
}
}
}}
value={options.find(option => option.value === value)}
components={{
DropdownIndicator,
SingleValue: SelectSingleValue,
Option: SelectOption,
IndicatorSeparator: () => null,
}}
placeholder={t('buy.info.selectPlaceholder')}
/>
);
};

0 comments on commit f00344c

Please sign in to comment.