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

Make all UI tabs accessible via keyboard (#9518)

This commit is contained in:
David Walsh 2020-11-05 12:05:41 -06:00 committed by GitHub
parent f5265c24ab
commit cfbcc12398
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 99 additions and 33 deletions

View File

@ -846,7 +846,7 @@ describe('MetaMask', function () {
}) })
it('displays the contract creation data', async function () { it('displays the contract creation data', async function () {
await driver.clickElement(By.xpath(`//li[contains(text(), 'Data')]`)) await driver.clickElement(By.xpath(`//button[contains(text(), 'Data')]`))
await driver.delay(regularDelayMs) await driver.delay(regularDelayMs)
await driver.findElement(By.xpath(`//div[contains(text(), '127.0.0.1')]`)) await driver.findElement(By.xpath(`//div[contains(text(), '127.0.0.1')]`))
@ -860,7 +860,9 @@ describe('MetaMask', function () {
assert.ok(confirmDataText.includes('Bytes:')) assert.ok(confirmDataText.includes('Bytes:'))
assert.ok(confirmDataText.includes('675')) assert.ok(confirmDataText.includes('675'))
await driver.clickElement(By.xpath(`//li[contains(text(), 'Details')]`)) await driver.clickElement(
By.xpath(`//button[contains(text(), 'Details')]`),
)
await driver.delay(regularDelayMs) await driver.delay(regularDelayMs)
}) })
@ -1055,7 +1057,9 @@ describe('MetaMask', function () {
) )
await driver.delay(regularDelayMs) await driver.delay(regularDelayMs)
await driver.clickElement(By.xpath(`//li[contains(text(), 'Advanced')]`)) await driver.clickElement(
By.xpath(`//button[contains(text(), 'Advanced')]`),
)
await driver.delay(tinyDelayMs) await driver.delay(tinyDelayMs)
const [gasPriceInput, gasLimitInput] = await driver.findElements( const [gasPriceInput, gasLimitInput] = await driver.findElements(
@ -1098,7 +1102,7 @@ describe('MetaMask', function () {
it('picks the newly created Test token', async function () { it('picks the newly created Test token', async function () {
await driver.clickElement( await driver.clickElement(
By.xpath("//li[contains(text(), 'Custom Token')]"), By.xpath("//button[contains(text(), 'Custom Token')]"),
) )
await driver.delay(regularDelayMs) await driver.delay(regularDelayMs)
@ -1165,7 +1169,7 @@ describe('MetaMask', function () {
}) })
it('displays the token transfer data', async function () { it('displays the token transfer data', async function () {
await driver.clickElement(By.xpath(`//li[contains(text(), 'Data')]`)) await driver.clickElement(By.xpath(`//button[contains(text(), 'Data')]`))
await driver.delay(regularDelayMs) await driver.delay(regularDelayMs)
const functionType = await driver.findElement( const functionType = await driver.findElement(
@ -1192,7 +1196,9 @@ describe('MetaMask', function () {
), ),
) )
await driver.clickElement(By.xpath(`//li[contains(text(), 'Details')]`)) await driver.clickElement(
By.xpath(`//button[contains(text(), 'Details')]`),
)
await driver.delay(regularDelayMs) await driver.delay(regularDelayMs)
}) })

View File

@ -93,10 +93,16 @@ const AssetListItem = ({
className={classnames('asset-list-item', className)} className={classnames('asset-list-item', className)}
data-testid={dataTestId} data-testid={dataTestId}
title={ title={
<> <button
<h2 className="asset-list-item__token-value">{primary}</h2> className="asset-list-item__token-button"
<h2 className="asset-list-item__token-symbol">{tokenSymbol}</h2> onClick={onClick}
</> title={`${primary} ${tokenSymbol || ''}`}
>
<h2>
<span className="asset-list-item__token-value">{primary}</span>
<span className="asset-list-item__token-symbol">{tokenSymbol}</span>
</h2>
</button>
} }
titleIcon={titleIcon} titleIcon={titleIcon}
subtitle={<h3 title={secondary}>{secondary}</h3>} subtitle={<h3 title={secondary}>{secondary}</h3>}

View File

@ -1,9 +1,24 @@
.asset-list-item { .asset-list-item {
&__token-value { & .list-item__heading {
padding: 0 5px 0 0; max-width: 100%;
overflow: hidden; }
white-space: nowrap;
text-overflow: ellipsis; &__token-button {
padding-inline-start: 0;
min-width: 0;
min-height: 0;
text-align: start;
& h2 {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
max-width: 100%;
}
& span {
padding-right: 5px;
}
} }
&__chevron-right { &__chevron-right {

View File

@ -77,6 +77,12 @@
color: #8c8e94; color: #8c8e94;
text-transform: uppercase; text-transform: uppercase;
margin: 0 8px; margin: 0 8px;
& button {
font-size: unset;
color: #8c8e94;
text-transform: uppercase;
}
} }
.page-container__footer { .page-container__footer {

View File

@ -57,6 +57,10 @@
display: none; display: none;
} }
&__tab {
margin-right: 0;
}
&__tabs { &__tabs {
margin-top: 0; margin-top: 0;
} }
@ -70,9 +74,12 @@
margin-right: 0; margin-right: 0;
} }
&--selected { & button {
font-size: unset;
}
&.tab--active button {
color: $primary-blue; color: $primary-blue;
border-bottom: 2px solid $primary-blue;
} }
} }
} }

View File

@ -37,6 +37,8 @@
padding: 6px 1px; padding: 6px 1px;
border-radius: 10px; border-radius: 10px;
cursor: pointer; cursor: pointer;
width: 100%;
background-color: unset;
&:hover { &:hover {
background-color: $Grey-000; background-color: $Grey-000;

View File

@ -43,7 +43,7 @@ class SelectedAccount extends Component {
this.state.copied ? t('copiedExclamation') : t('copyToClipboard') this.state.copied ? t('copiedExclamation') : t('copyToClipboard')
} }
> >
<div <button
className="selected-account__clickable" className="selected-account__clickable"
onClick={() => { onClick={() => {
this.setState({ copied: true }) this.setState({ copied: true })
@ -60,7 +60,7 @@ class SelectedAccount extends Component {
<div className="selected-account__address"> <div className="selected-account__address">
{shortenAddress(checksummedAddress)} {shortenAddress(checksummedAddress)}
</div> </div>
</div> </button>
</Tooltip> </Tooltip>
</div> </div>
) )

View File

@ -16,6 +16,8 @@
padding: 16px 24px; padding: 16px 24px;
opacity: 0.5; opacity: 0.5;
transition: opacity 200ms ease-in-out; transition: opacity 200ms ease-in-out;
background-color: unset;
text-align: start;
@media screen and (min-width: 576px) { @media screen and (min-width: 576px) {
&:hover { &:hover {

View File

@ -8,7 +8,7 @@ const TabBar = (props) => {
return ( return (
<div className="tab-bar"> <div className="tab-bar">
{tabs.map(({ key, content, description }) => ( {tabs.map(({ key, content, description }) => (
<div <button
key={key} key={key}
className={classnames('tab-bar__tab pointer', { className={classnames('tab-bar__tab pointer', {
'tab-bar__tab--active': isActive(key, content), 'tab-bar__tab--active': isActive(key, content),
@ -22,7 +22,7 @@ const TabBar = (props) => {
</div> </div>
</div> </div>
<div className="tab-bar__tab__caret" /> <div className="tab-bar__tab__caret" />
</div> </button>
))} ))}
</div> </div>
) )

View File

@ -19,7 +19,8 @@
align-items: start; align-items: start;
cursor: pointer; cursor: pointer;
&:hover { &:hover,
&:focus-within {
background-color: $Grey-000; background-color: $Grey-000;
} }
@ -44,6 +45,12 @@
display: flex; display: flex;
align-items: center; align-items: center;
& button {
background: unset;
font-size: unset;
padding-inline-start: 0;
}
&-wrap { &-wrap {
display: inline-block; display: inline-block;
margin-left: 8px; margin-left: 8px;

View File

@ -27,7 +27,9 @@ export default function ListItem({
{React.isValidElement(title) ? ( {React.isValidElement(title) ? (
title title
) : ( ) : (
<h2 className="list-item__title">{title}</h2> <button onClick={onClick}>
<h2 className="list-item__title">{title}</h2>
</button>
)} )}
{titleIcon && ( {titleIcon && (
<div className="list-item__heading-wrap">{titleIcon}</div> <div className="list-item__heading-wrap">{titleIcon}</div>

View File

@ -1,8 +1,15 @@
.tab { .tab {
cursor: pointer; button {
padding: 8px; cursor: pointer;
min-width: 50px; padding: 8px;
text-align: center; min-width: 50px;
text-align: center;
display: block;
width: 100%;
background-color: unset;
font-size: unset;
color: unset;
}
&--active { &--active {
color: $black; color: $black;

View File

@ -25,7 +25,7 @@ const Tab = (props) => {
onClick(tabIndex) onClick(tabIndex)
}} }}
> >
{name} <button>{name}</button>
</li> </li>
) )
} }

View File

@ -23,7 +23,8 @@
border: 1px solid transparent; border: 1px solid transparent;
position: relative; position: relative;
&:hover { &:hover,
&:focus {
border-color: rgba($malibu-blue, 0.5); border-color: rgba($malibu-blue, 0.5);
} }

View File

@ -37,6 +37,8 @@ export default class InfoBox extends Component {
.map((_, i) => { .map((_, i) => {
const { logo, symbol, name, address } = results[i] || {} const { logo, symbol, name, address } = results[i] || {}
const tokenAlreadyAdded = checkExistingAddresses(address, tokens) const tokenAlreadyAdded = checkExistingAddresses(address, tokens)
const onClick = () =>
!tokenAlreadyAdded && onToggleToken(results[i])
return ( return (
Boolean(logo || symbol || name) && ( Boolean(logo || symbol || name) && (
@ -45,10 +47,10 @@ export default class InfoBox extends Component {
'token-list__token--selected': selectedTokens[address], 'token-list__token--selected': selectedTokens[address],
'token-list__token--disabled': tokenAlreadyAdded, 'token-list__token--disabled': tokenAlreadyAdded,
})} })}
onClick={() => onClick={onClick}
!tokenAlreadyAdded && onToggleToken(results[i]) onKeyPress={(event) => event.key === 'Enter' && onClick()}
}
key={i} key={i}
tabIndex="0"
> >
<div <div
className="token-list__token-icon" className="token-list__token-icon"

View File

@ -31,7 +31,6 @@
flex-grow: 1; flex-grow: 1;
color: $Grey-500; color: $Grey-500;
padding: 16px 8px;
font-weight: 500; font-weight: 500;
} }
@ -39,6 +38,10 @@
color: $Blue-500; color: $Blue-500;
} }
&__main-view &__tab button {
padding: 16px 8px;
}
&__connect-status-text { &__connect-status-text {
display: flex; display: flex;
flex-direction: column; flex-direction: column;