web/satellite: responsiveness and accessibility fixes for new access grant flow

Fixed responsiveness and accessibility for new access grant flow.

Change-Id: Ie39c807a702995610d240e19cf5dfd2c8a51d860
This commit is contained in:
Vitalii 2023-02-21 16:06:51 +02:00 committed by Storj Robot
parent 4362761fc7
commit e9c4d1151f
16 changed files with 167 additions and 46 deletions

View File

@ -607,12 +607,22 @@ onMounted(async () => {
flex-direction: column;
position: relative;
@media screen and (max-width: 460px) {
width: 280px;
padding: 16px;
}
&__header {
display: flex;
align-items: center;
padding-bottom: 16px;
border-bottom: 1px solid var(--c-grey-2);
@media screen and (max-width: 460px) {
flex-direction: column;
align-items: flex-start;
}
&__title {
margin-left: 16px;
font-family: 'font_bold', sans-serif;
@ -620,6 +630,11 @@ onMounted(async () => {
line-height: 31px;
letter-spacing: -0.02em;
color: var(--c-black);
text-align: left;
@media screen and (max-width: 460px) {
margin: 10px 0 0;
}
}
}

View File

@ -36,6 +36,12 @@ const props = withDefaults(defineProps<{
align-items: center;
column-gap: 16px;
display: flex;
@media screen and (max-width: 460px) {
flex-direction: column-reverse;
column-gap: unset;
row-gap: 10px;
}
}
}
</style>

View File

@ -4,12 +4,24 @@
<template>
<div v-click-outside="closePicker" class="date-picker">
<ul class="date-picker__column">
<li class="date-picker__column__item" @click="onOneDayClick">24 Hours</li>
<li class="date-picker__column__item" @click="onOneWeekClick">1 Week</li>
<li class="date-picker__column__item" @click="onOneMonthClick">1 month</li>
<li class="date-picker__column__item" @click="onSixMonthsClick">6 Months</li>
<li class="date-picker__column__item" @click="onOneYearClick">1 Year</li>
<li class="date-picker__column__item" @click="onForeverClick">No end date</li>
<li class="date-picker__column__item" tabindex="0" @click="onOneDayClick" @keyup.space="onOneDayClick">
24 Hours
</li>
<li class="date-picker__column__item" tabindex="0" @click="onOneWeekClick" @keyup.space="onOneWeekClick">
1 Week
</li>
<li class="date-picker__column__item" tabindex="0" @click="onOneMonthClick" @keyup.space="onOneMonthClick">
1 month
</li>
<li class="date-picker__column__item" tabindex="0" @click="onSixMonthsClick" @keyup.space="onSixMonthsClick">
6 Months
</li>
<li class="date-picker__column__item" tabindex="0" @click="onOneYearClick" @keyup.space="onOneYearClick">
1 Year
</li>
<li class="date-picker__column__item" tabindex="0" @click="onForeverClick" @keyup.space="onForeverClick">
No end date
</li>
</ul>
<VDatePicker :on-date-pick="onCustomDatePick" />
</div>
@ -132,11 +144,26 @@ function onOneYearClick(): void {
align-items: center;
cursor: default;
@media screen and (max-width: 600px) {
left: -90px;
}
@media screen and (max-width: 460px) {
flex-direction: column;
width: 320px;
left: -78px;
}
&__column {
list-style-type: none;
padding-left: 0;
margin-top: 0;
@media screen and (max-width: 460px) {
columns: 2;
width: 100%;
}
&__item {
font-size: 14px;
font-weight: 400;
@ -151,9 +178,5 @@ function onOneYearClick(): void {
}
}
}
&__wrapper {
width: 100%;
}
}
</style>

View File

@ -5,8 +5,10 @@
<div class="date-select">
<div
class="date-select__toggle-container"
tabindex="0"
aria-roledescription="select-date"
@click.stop="togglePicker"
@keyup.space="togglePicker"
>
<h1 class="date-select__toggle-container__label">{{ notAfterLabel }}</h1>
<ExpandIcon />

View File

@ -57,5 +57,9 @@ const props = withDefaults(defineProps<{
fill: #fff;
}
}
&:focus {
outline: 2px solid #376fff;
}
}
</style>

View File

@ -3,11 +3,11 @@
<template>
<div class="radio">
<input :id="id || label" :checked="checked" type="radio" @change="onCheck">
<input :id="id || label" tabindex="0" :checked="checked" type="radio" @change="onCheck">
<label class="radio__label" :for="id || label">{{ label }}</label>
<VInfo class="radio__info">
<template #icon>
<InfoIcon class="radio__info__icon" />
<template #icon="{onSpace}">
<InfoIcon tabindex="0" class="radio__info__icon" @keyup.space="onSpace" />
</template>
<template #message>
<p class="radio__info__message">{{ info }}</p>
@ -50,6 +50,7 @@ const props = withDefaults(defineProps<{
line-height: 20px;
color: var(--c-black);
cursor: pointer;
text-align: left;
}
&__info {
@ -74,6 +75,11 @@ const props = withDefaults(defineProps<{
cursor: default;
filter: none;
transform: rotate(-180deg);
@media screen and (max-width: 530px) {
left: unset;
right: -5px;
}
}
:deep(.info__box__message) {
@ -88,5 +94,9 @@ const props = withDefaults(defineProps<{
width: 10px;
height: 10px;
margin-bottom: -3px;
@media screen and (max-width: 530px) {
margin-right: 245px;
}
}
</style>

View File

@ -9,11 +9,17 @@
</label>
<label class="toggle__label" :for="id || label">{{ label }}</label>
<template v-if="onShowHideAll">
<ChevronIcon class="toggle__chevron" :class="{'toggle__chevron--up': allShown}" @click="onShowHideAll" />
<ChevronIcon
tabindex="0"
class="toggle__chevron"
:class="{'toggle__chevron--up': allShown}"
@click="onShowHideAll"
@keyup.space="onShowHideAll"
/>
</template>
<VInfo v-if="slots.infoMessage" class="toggle__info">
<template #icon>
<InfoIcon class="toggle__info__icon" />
<template #icon="{onSpace}">
<InfoIcon tabindex="0" class="toggle__info__icon" @keyup.space="onSpace" />
</template>
<template #message>
<slot name="infoMessage" />
@ -67,6 +73,10 @@ const props = withDefaults(defineProps<{
cursor: pointer;
height: 0;
width: 0;
&:focus + span {
outline: 2px solid #376fff;
}
}
span {
@ -117,6 +127,7 @@ const props = withDefaults(defineProps<{
line-height: 20px;
color: var(--c-black);
cursor: pointer;
text-align: left;
}
&__info {
@ -147,6 +158,11 @@ const props = withDefaults(defineProps<{
cursor: default;
filter: none;
transform: rotate(-180deg);
@media screen and (max-width: 460px) {
left: unset;
right: -83px;
}
}
:deep(.info__box__message) {
@ -161,5 +177,9 @@ const props = withDefaults(defineProps<{
width: 10px;
height: 10px;
margin-bottom: -3px;
@media screen and (max-width: 460px) {
margin-right: 88px;
}
}
</style>

View File

@ -15,9 +15,15 @@
</VInfo>
</div>
<div class="blured-container__wrap" :class="{justify: !isMnemonic}">
<p v-if="isMnemonic" class="blured-container__wrap__mnemonic">{{ value }}</p>
<p v-else class="blured-container__wrap__text">{{ value }}</p>
<div v-if="!isMnemonic" v-clipboard:copy="value" class="blured-container__wrap__copy" @click="onCopy">
<p v-if="isMnemonic" tabindex="0" class="blured-container__wrap__mnemonic" @keyup.space="onCopy">{{ value }}</p>
<p v-else tabindex="0" class="blured-container__wrap__text" @keyup.space="onCopy">{{ value }}</p>
<div
v-if="!isMnemonic"
tabindex="0"
class="blured-container__wrap__copy"
@click="onCopy"
@keyup.space="onCopy"
>
<CopyIcon />
</div>
<div v-if="!isValueShown" class="blured-container__wrap__blur">
@ -76,6 +82,7 @@ function showValue(): void {
* Holds on copy click logic.
*/
function onCopy(): void {
navigator.clipboard.writeText(props.value);
analytics.eventTriggered(AnalyticsEvent.COPY_TO_CLIPBOARD_CLICKED);
notify.success(`${props.title} was copied successfully`);
}

View File

@ -9,7 +9,6 @@
<ButtonsContainer label="Save your access grant">
<template #leftButton>
<VButton
v-clipboard:copy="accessGrant"
:label="isCopied ? 'Copied' : 'Copy'"
width="100%"
height="40px"
@ -104,6 +103,7 @@ const hasNextStep = computed((): boolean => {
* Saves passphrase to clipboard.
*/
function onCopy(): void {
navigator.clipboard.writeText(props.accessGrant);
isCopied.value = true;
analytics.eventTriggered(AnalyticsEvent.COPY_TO_CLIPBOARD_CLICKED);
notify.success(`Access Grant was copied successfully`);

View File

@ -25,31 +25,31 @@
you use for this project. This allows you to manage existing data you have uploaded with the
same passphrase."
/>
<div class="encryption__radios__advanced" @click="toggleAdvanced">
<div tabindex="0" class="encryption__radios__advanced" @click="toggleAdvanced" @keyup.space="toggleAdvanced">
<h2 class="encryption__radios__advanced__label">Advanced</h2>
<ChevronIcon
class="encryption__radios__advanced__chevron"
:class="{'encryption__radios__advanced__chevron--up': advancedShown}"
/>
</div>
<template v-if="advancedShown">
<Radio
id="newPassphrase"
:checked="isSelectedOption(_PassphraseOption.EnterNewPassphrase)"
:on-check="() => setOption(_PassphraseOption.EnterNewPassphrase)"
label="Enter a new passphrase"
info="Create this access with a new encryption passphrase that you can enter on the next step.
The access will not be able to manage any existing data."
/>
<Radio
id="generatePassphrase"
:checked="isSelectedOption(_PassphraseOption.GenerateNewPassphrase)"
:on-check="() => setOption(_PassphraseOption.GenerateNewPassphrase)"
label="Generate 12-word passphrase"
info="Create this access with a new encryption passphrase that will be generated for you on
the next step. The access will not be able to manage any existing data."
/>
</template>
<Radio
v-show="advancedShown"
id="new passphrase"
:checked="isSelectedOption(_PassphraseOption.EnterNewPassphrase)"
:on-check="() => setOption(_PassphraseOption.EnterNewPassphrase)"
label="Enter a new passphrase"
info="Create this access with a new encryption passphrase that you can enter on the next step.
The access will not be able to manage any existing data."
/>
<Radio
v-show="advancedShown"
id="generate passphrase"
:checked="isSelectedOption(_PassphraseOption.GenerateNewPassphrase)"
:on-check="() => setOption(_PassphraseOption.GenerateNewPassphrase)"
label="Generate 12-word passphrase"
info="Create this access with a new encryption passphrase that will be generated for you on
the next step. The access will not be able to manage any existing data."
/>
</div>
</template>
<template #info>
@ -193,9 +193,17 @@ function isSelectedOption(option: PassphraseOption): boolean {
align-items: flex-start;
margin-top: 16px;
@media screen and (max-width: 460px) {
flex-direction: column;
}
&__icon {
min-width: 32px;
margin-right: 16px;
@media screen and (max-width: 460px) {
margin: 0 0 16px;
}
}
&__message {

View File

@ -9,7 +9,6 @@
<ButtonsContainer label="Save your CLI access">
<template #leftButton>
<VButton
v-clipboard:copy="`${satelliteAddress} ${apiKey}`"
:label="isCopied ? 'Copied' : 'Copy all'"
width="100%"
height="40px"
@ -102,6 +101,7 @@ const satelliteAddress = MetaUtils.getMetaContent('satellite-nodeurl');
* Saves CLI access to clipboard.
*/
function onCopy(): void {
navigator.clipboard.writeText(`${satelliteAddress} ${props.apiKey}`);
isCopied.value = true;
analytics.eventTriggered(AnalyticsEvent.COPY_TO_CLIPBOARD_CLICKED);
notify.success(`CLI access was copied successfully`);

View File

@ -53,7 +53,7 @@
<div v-if="selectedBuckets.length" class="choose__selected-container">
<div v-for="bucket in selectedBuckets" :key="bucket" class="choose__selected-container__item">
<p class="choose__selected-container__item__label">{{ bucket }}</p>
<CloseIcon @click="() => onUnselectBucket(bucket)" />
<CloseIcon tabindex="0" @click="() => onUnselectBucket(bucket)" @keyup.space="() => onUnselectBucket(bucket)" />
</div>
</div>
<div class="choose__search-container">
@ -65,8 +65,10 @@
<p
v-for="bucket in bucketsList"
:key="bucket"
tabindex="0"
class="choose__bucket-results__item"
@click="() => selectBucket(bucket)"
@keyup.space="() => selectBucket(bucket)"
>
{{ bucket }}
</p>
@ -81,7 +83,13 @@
<ContainerWithIcon :icon-and-title="FUNCTIONAL_CONTAINER_ICON_AND_TITLE[FunctionalContainer.EndDate]">
<template #functional>
<div class="choose__date-selection">
<p v-if="!settingDate && !notAfter" class="choose__date-selection__label" @click="toggleSettingDate">
<p
v-if="!settingDate && !notAfter"
tabindex="0"
class="choose__date-selection__label"
@click="toggleSettingDate"
@keyup.space="toggleSettingDate"
>
Add Date (optional)
</p>
<EndDateSelection

View File

@ -15,6 +15,7 @@
<p class="create__toggles__info">
Keys to upload, delete, and view your project's data.
<a
tabindex="0"
class="create__toggles__info__link"
href="https://docs.storj.io/dcs/concepts/access/access-grants"
target="_blank"
@ -32,6 +33,7 @@
<p class="create__toggles__info">
Generates access key, secret key, and endpoint to use in your S3-supporting application.
<a
tabindex="0"
class="create__toggles__info__link"
href="https://docs.storj.io/dcs/api-reference/s3-compatible-gateway"
target="_blank"
@ -49,6 +51,7 @@
<p class="create__toggles__info">
Creates access grant to run in the command line.
<a
tabindex="0"
class="create__toggles__info__link"
href="https://docs.storj.io/dcs/getting-started/quickstart-uplink-cli/generate-access-grants-and-tokens/generate-a-token"
target="_blank"
@ -140,6 +143,10 @@ const isButtonDisabled = computed((): boolean => {
&:visited {
color: var(--c-white);
}
&:focus {
outline: 2px solid #fff;
}
}
}
}

View File

@ -9,7 +9,6 @@
<ButtonsContainer label="Save your S3 credentials">
<template #leftButton>
<VButton
v-clipboard:copy="`${credentials.accessKeyId} ${credentials.secretKey} ${credentials.endpoint}`"
:label="isCopied ? 'Copied' : 'Copy all'"
width="100%"
height="40px"
@ -108,6 +107,9 @@ const analytics: AnalyticsHttpApi = new AnalyticsHttpApi();
* Saves CLI access to clipboard.
*/
function onCopy(): void {
const { credentials } = props;
navigator.clipboard.writeText(`${credentials.accessKeyId} ${credentials.secretKey} ${credentials.endpoint}`);
isCopied.value = true;
analytics.eventTriggered(AnalyticsEvent.COPY_TO_CLIPBOARD_CLICKED);
notify.success(`S3 credentials were copied successfully`);

View File

@ -32,8 +32,8 @@
:class="containerClassName"
:style="style"
tabindex="0"
@click="onPress"
@keyup.enter="onPress"
@click="handleClick"
@keyup.enter="handleClick"
>
<slot name="icon" />
<div v-if="isWhiteGreen" class="greenCheck">&#x2713;</div>
@ -135,6 +135,15 @@ const containerClassName = computed((): string => {
const style = computed(() => {
return { width: props.width, height: props.height, borderRadius: props.borderRadius, fontSize: props.fontSize };
});
/**
* This wrapper handles button's disabled state for accessibility purposes.
*/
function handleClick(): void {
if (!props.isDisabled) {
props.onPress();
}
}
</script>
<style scoped lang="scss">

View File

@ -3,7 +3,7 @@
<template>
<div class="info" @mouseenter="toggleVisibility" @mouseleave="toggleVisibility">
<slot name="icon" />
<slot name="icon" :on-space="toggleVisibility" />
<div v-if="isVisible" class="info__box">
<div class="info__box__arrow" />
<div class="info__box__message">