mirror of
https://github.com/signalapp/Signal-Desktop.git
synced 2025-12-20 10:19:08 +00:00
Migrate all preferences buttons to axo button
This commit is contained in:
@@ -819,10 +819,6 @@ $secondary-text-color: light-dark(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.Preferences--BackupsAuthButton[disabled] {
|
|
||||||
cursor: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Preferences--BackupsRow {
|
.Preferences--BackupsRow {
|
||||||
padding-block: 8px;
|
padding-block: 8px;
|
||||||
margin-block-start: 8px;
|
margin-block-start: 8px;
|
||||||
@@ -915,6 +911,7 @@ $secondary-text-color: light-dark(
|
|||||||
}
|
}
|
||||||
|
|
||||||
.Preferences--LocalBackupsSetupScreenPane-top {
|
.Preferences--LocalBackupsSetupScreenPane-top {
|
||||||
|
flex-grow: 0;
|
||||||
min-height: 154px;
|
min-height: 154px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -923,25 +920,6 @@ $secondary-text-color: light-dark(
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.Preferences--LocalBackupsSetupScreenCopyButton {
|
|
||||||
@include mixins.font-body-small;
|
|
||||||
padding-inline: 15px 21px;
|
|
||||||
font-weight: 500;
|
|
||||||
vertical-align: text-top;
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
content: '';
|
|
||||||
display: inline-block;
|
|
||||||
height: 16px;
|
|
||||||
width: 16px;
|
|
||||||
margin-inline-end: 6px;
|
|
||||||
@include mixins.color-svg(
|
|
||||||
'../images/icons/v3/copy/copy-compact.svg',
|
|
||||||
variables.$color-black
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.Preferences--LocalBackupsSetupScreenPane-footer {
|
.Preferences--LocalBackupsSetupScreenPane-footer {
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
flex-grow: 0;
|
flex-grow: 0;
|
||||||
@@ -958,258 +936,15 @@ $secondary-text-color: light-dark(
|
|||||||
justify-content: right;
|
justify-content: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
.Preferences--LocalBackupsSetupScreenFooterSeeKeyButton {
|
|
||||||
@include mixins.font-body-1-bold;
|
|
||||||
padding-block: 0;
|
|
||||||
padding-inline: 0;
|
|
||||||
background: none;
|
|
||||||
border: none;
|
|
||||||
outline: none;
|
|
||||||
color: variables.$color-ultramarine;
|
|
||||||
|
|
||||||
@include mixins.keyboard-mode {
|
|
||||||
&:focus {
|
|
||||||
outline: 2px solid variables.$color-ultramarine;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.Preferences--LocalBackupsSetupScreenFooterButton {
|
|
||||||
padding-inline: 34px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Preferences--LocalBackupsSetupScreenBody {
|
.Preferences--LocalBackupsSetupScreenBody {
|
||||||
@include mixins.font-body-1;
|
@include mixins.font-body-1;
|
||||||
margin-block: 8px;
|
margin-block: 8px;
|
||||||
color: $secondary-text-color;
|
color: $secondary-text-color;
|
||||||
}
|
|
||||||
|
|
||||||
.Preferences--LocalBackupsSetupScreenBody--folder {
|
a {
|
||||||
margin-block-end: 57px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Preferences--LocalBackupsBackupKey {
|
|
||||||
width: 274px;
|
|
||||||
height: 201px;
|
|
||||||
padding-block: 28px;
|
|
||||||
padding-inline: 36px;
|
|
||||||
margin-block: 28px 20px;
|
|
||||||
background: variables.$color-gray-02;
|
|
||||||
border-radius: 12px;
|
|
||||||
border-width: 0;
|
|
||||||
outline: none;
|
|
||||||
color: variables.$color-gray-90;
|
|
||||||
font-family: variables.$monospace;
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: 400;
|
|
||||||
line-height: 36.128px;
|
|
||||||
letter-spacing: 0.624px;
|
|
||||||
overflow: hidden;
|
|
||||||
resize: none;
|
|
||||||
word-break: break-all;
|
|
||||||
text-transform: uppercase;
|
|
||||||
|
|
||||||
&::placeholder {
|
|
||||||
color: variables.$color-gray-45;
|
|
||||||
text-transform: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.Preferences--LocalBackupsSetupIcon {
|
|
||||||
display: inline-flex;
|
|
||||||
width: 64px;
|
|
||||||
height: 64px;
|
|
||||||
border-radius: 64px;
|
|
||||||
background: variables.$color-ultramarine-pale;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
height: 38px;
|
|
||||||
width: 38px;
|
|
||||||
content: '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.Preferences--LocalBackupsSetupIcon-folder {
|
|
||||||
margin-block-start: 60px;
|
|
||||||
margin-block-end: 12px;
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
@include mixins.color-svg(
|
|
||||||
'../images/icons/v3/folder/folder.svg',
|
|
||||||
variables.$color-ultramarine-logo
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.Preferences--LocalBackupsSetupIcon-key {
|
|
||||||
&::before {
|
|
||||||
@include mixins.color-svg(
|
|
||||||
'../images/icons/v3/key/key.svg',
|
|
||||||
variables.$color-ultramarine-logo
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.Preferences--LocalBackupsSetupIcon-lock {
|
|
||||||
&::before {
|
|
||||||
@include mixins.color-svg(
|
|
||||||
'../images/icons/v3/lock/lock.svg',
|
|
||||||
variables.$color-ultramarine-logo
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.Preferences--LocalBackupsConfirmKeyModal {
|
|
||||||
padding-block: 36px 20px;
|
|
||||||
padding-inline: 32px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Preferences--LocalBackupsConfirmKeyModal__body {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Preferences--LocalBackupsConfirmKeyModalTitle {
|
|
||||||
@include mixins.font-title-medium;
|
|
||||||
margin-block: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Preferences--LocalBackupsConfirmKeyModalBody {
|
|
||||||
@include mixins.font-body-1;
|
|
||||||
margin-block: 8px 32px;
|
|
||||||
color: $secondary-text-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Preferences--LocalBackupsConfirmKeyModalButton {
|
|
||||||
padding-inline: 32px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Preferences--LocalBackupsConfirmKeyModal .module-Modal__button-footer {
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Preferences__BackupsIcon {
|
|
||||||
@include mixins.light-theme {
|
|
||||||
@include mixins.color-svg(
|
|
||||||
'../images/icons/v3/signal_backups/signal_backups.svg',
|
|
||||||
variables.$color-gray-75
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@include mixins.dark-theme {
|
|
||||||
@include mixins.color-svg(
|
|
||||||
'../images/icons/v3/signal_backups/signal_backups.svg',
|
|
||||||
variables.$color-gray-15
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.Preferences__LocalBackupsIcon {
|
|
||||||
@include mixins.light-theme {
|
|
||||||
@include mixins.color-svg(
|
|
||||||
'../images/icons/v3/device/device-laptop.svg',
|
|
||||||
variables.$color-gray-75
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@include mixins.dark-theme {
|
|
||||||
@include mixins.color-svg(
|
|
||||||
'../images/icons/v3/device/device-laptop.svg',
|
|
||||||
variables.$color-gray-15
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.Preferences--LocalBackupsSetupScreen {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Preferences--LocalBackupsSetupScreenHeader {
|
|
||||||
@include mixins.font-title-2;
|
|
||||||
margin-block: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Preferences--LocalBackupsSetupScreenPane {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
flex-grow: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Preferences--LocalBackupsSetupScreenPane-top {
|
|
||||||
flex-grow: 0;
|
|
||||||
min-height: 154px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Preferences--LocalBackupsSetupScreenPaneContent {
|
|
||||||
display: block;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Preferences--LocalBackupsSetupScreenCopyButton {
|
|
||||||
@include mixins.font-body-small;
|
|
||||||
padding-inline: 15px 21px;
|
|
||||||
font-weight: 500;
|
|
||||||
vertical-align: text-top;
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
content: '';
|
|
||||||
display: inline-block;
|
|
||||||
height: 16px;
|
|
||||||
width: 16px;
|
|
||||||
margin-inline-end: 6px;
|
|
||||||
@include mixins.color-svg(
|
|
||||||
'../images/icons/v3/copy/copy-compact.svg',
|
|
||||||
variables.$color-black
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.Preferences--LocalBackupsSetupScreenPane-footer {
|
|
||||||
flex-direction: row;
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Preferences--LocalBackupsSetupScreenFooterSection {
|
|
||||||
display: flex;
|
|
||||||
flex-grow: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Preferences--LocalBackupsSetupScreenFooterSection-right {
|
|
||||||
justify-content: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Preferences--LocalBackupsSetupScreenFooterSeeKeyButton {
|
|
||||||
@include mixins.font-body-1-bold;
|
|
||||||
padding-block: 0;
|
|
||||||
padding-inline: 0;
|
|
||||||
background: none;
|
|
||||||
border: none;
|
|
||||||
outline: none;
|
|
||||||
color: variables.$color-ultramarine;
|
|
||||||
|
|
||||||
@include mixins.keyboard-mode {
|
|
||||||
&:focus {
|
|
||||||
outline: 2px solid variables.$color-ultramarine;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.Preferences--LocalBackupsSetupScreenFooterButton {
|
|
||||||
padding-inline: 34px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Preferences--LocalBackupsSetupScreenBody {
|
|
||||||
@include mixins.font-body-1;
|
|
||||||
margin-block: 8px;
|
|
||||||
color: $secondary-text-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Preferences--LocalBackupsSetupScreenBody a {
|
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.Preferences--LocalBackupsSetupScreenBody--folder {
|
.Preferences--LocalBackupsSetupScreenBody--folder {
|
||||||
margin-block-end: 57px;
|
margin-block-end: 57px;
|
||||||
@@ -1309,10 +1044,6 @@ $secondary-text-color: light-dark(
|
|||||||
color: $secondary-text-color;
|
color: $secondary-text-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
.Preferences--LocalBackupsConfirmKeyModalButton {
|
|
||||||
padding-inline: 32px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Preferences--LocalBackupsConfirmKeyModal .module-Modal__button-footer {
|
.Preferences--LocalBackupsConfirmKeyModal .module-Modal__button-footer {
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,10 +42,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__donate-button {
|
|
||||||
margin-block-end: 32px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__separator {
|
&__separator {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 0.5px;
|
height: 0.5px;
|
||||||
@@ -466,15 +462,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.PreferencesDonations__PrimaryButton {
|
|
||||||
@include mixins.font-body-2;
|
|
||||||
padding-block: 5px;
|
|
||||||
padding-inline: 12px;
|
|
||||||
font-weight: 400;
|
|
||||||
border: 0.5px solid variables.$color-black-alpha-16;
|
|
||||||
border-radius: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.PreferencesDonations__badge-list {
|
.PreferencesDonations__badge-list {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin-block: 4px 8px;
|
margin-block: 4px 8px;
|
||||||
|
|||||||
@@ -392,12 +392,3 @@
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
margin-block-end: 16px;
|
margin-block-end: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ProfileEditor__EditPhoto {
|
|
||||||
@include mixins.font-subtitle;
|
|
||||||
|
|
||||||
padding-block: 5px;
|
|
||||||
padding-inline: 10px;
|
|
||||||
border-radius: 14px;
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// Copyright 2025 Signal Messenger, LLC
|
// Copyright 2025 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
import React from 'react';
|
import React, { useState } from 'react';
|
||||||
import type { Meta } from '@storybook/react';
|
import type { Meta } from '@storybook/react';
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
import {
|
import {
|
||||||
@@ -9,6 +9,7 @@ import {
|
|||||||
AxoButton,
|
AxoButton,
|
||||||
} from './AxoButton.dom.js';
|
} from './AxoButton.dom.js';
|
||||||
import { tw } from './tw.dom.js';
|
import { tw } from './tw.dom.js';
|
||||||
|
import { AxoSwitch } from './AxoSwitch.dom.js';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Axo/AxoButton',
|
title: 'Axo/AxoButton',
|
||||||
@@ -89,3 +90,46 @@ export function Basic(): JSX.Element {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function Spinner(): JSX.Element {
|
||||||
|
const sizes = _getAllAxoButtonSizes();
|
||||||
|
const variants = _getAllAxoButtonVariants();
|
||||||
|
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
|
||||||
|
function handleClick() {
|
||||||
|
setLoading(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className={tw('mb-4 flex gap-2')}>
|
||||||
|
<AxoSwitch.Root checked={loading} onCheckedChange={setLoading} />
|
||||||
|
<span>Loading</span>
|
||||||
|
</div>
|
||||||
|
<div className={tw('flex flex-col gap-2')}>
|
||||||
|
{sizes.map(size => {
|
||||||
|
return (
|
||||||
|
<div key={size} className={tw('flex gap-2')}>
|
||||||
|
{variants.map(variant => {
|
||||||
|
return (
|
||||||
|
<AxoButton.Root
|
||||||
|
variant={variant}
|
||||||
|
size={size}
|
||||||
|
disabled={loading}
|
||||||
|
experimentalSpinner={
|
||||||
|
loading ? { 'aria-label': 'Loading' } : null
|
||||||
|
}
|
||||||
|
onClick={handleClick}
|
||||||
|
>
|
||||||
|
Save
|
||||||
|
</AxoButton.Root>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,11 +6,13 @@ import type { TailwindStyles } from './tw.dom.js';
|
|||||||
import { tw } from './tw.dom.js';
|
import { tw } from './tw.dom.js';
|
||||||
import { AxoSymbol } from './AxoSymbol.dom.js';
|
import { AxoSymbol } from './AxoSymbol.dom.js';
|
||||||
import { assert } from './_internal/assert.dom.js';
|
import { assert } from './_internal/assert.dom.js';
|
||||||
|
import type { SpinnerVariant } from '../components/SpinnerV2.dom.js';
|
||||||
|
import { SpinnerV2 } from '../components/SpinnerV2.dom.js';
|
||||||
|
|
||||||
const Namespace = 'AxoButton';
|
const Namespace = 'AxoButton';
|
||||||
|
|
||||||
const baseAxoButtonStyles = tw(
|
const baseAxoButtonStyles = tw(
|
||||||
'flex items-center-safe justify-center-safe gap-1 truncate rounded-full select-none',
|
'relative inline-flex items-center-safe justify-center-safe rounded-full select-none',
|
||||||
'outline-0 outline-border-focused focused:outline-[2.5px]',
|
'outline-0 outline-border-focused focused:outline-[2.5px]',
|
||||||
'forced-colors:border'
|
'forced-colors:border'
|
||||||
);
|
);
|
||||||
@@ -126,9 +128,9 @@ const AxoButtonVariants = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const AxoButtonSizes = {
|
const AxoButtonSizes = {
|
||||||
large: tw('px-4 py-2 type-body-medium font-medium'),
|
large: tw('min-w-16 px-4 py-2 type-body-medium font-medium'),
|
||||||
medium: tw('px-3 py-1.5 type-body-medium font-medium'),
|
medium: tw('min-w-14 px-3 py-1.5 type-body-medium font-medium'),
|
||||||
small: tw('px-2 py-1 type-body-small font-medium'),
|
small: tw('min-w-12 px-2 py-1 type-body-small font-medium'),
|
||||||
} as const satisfies Record<string, TailwindStyles>;
|
} as const satisfies Record<string, TailwindStyles>;
|
||||||
|
|
||||||
type BaseButtonAttrs = Omit<
|
type BaseButtonAttrs = Omit<
|
||||||
@@ -147,21 +149,82 @@ export function _getAllAxoButtonSizes(): ReadonlyArray<AxoButtonSize> {
|
|||||||
return Object.keys(AxoButtonSizes) as Array<AxoButtonSize>;
|
return Object.keys(AxoButtonSizes) as Array<AxoButtonSize>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const AxoButtonSpinnerVariants: Record<AxoButtonVariant, SpinnerVariant> = {
|
||||||
|
primary: 'axo-button-spinner-on-color',
|
||||||
|
secondary: 'axo-button-spinner-secondary',
|
||||||
|
affirmative: 'axo-button-spinner-on-color',
|
||||||
|
destructive: 'axo-button-spinner-on-color',
|
||||||
|
'subtle-primary': 'axo-button-spinner-primary',
|
||||||
|
'subtle-affirmative': 'axo-button-spinner-affirmative',
|
||||||
|
'subtle-destructive': 'axo-button-spinner-destructive',
|
||||||
|
'floating-primary': 'axo-button-spinner-primary',
|
||||||
|
'floating-secondary': 'axo-button-spinner-secondary',
|
||||||
|
'floating-affirmative': 'axo-button-spinner-affirmative',
|
||||||
|
'floating-destructive': 'axo-button-spinner-destructive',
|
||||||
|
'borderless-primary': 'axo-button-spinner-primary',
|
||||||
|
'borderless-secondary': 'axo-button-spinner-secondary',
|
||||||
|
'borderless-affirmative': 'axo-button-spinner-affirmative',
|
||||||
|
'borderless-destructive': 'axo-button-spinner-destructive',
|
||||||
|
};
|
||||||
|
|
||||||
|
const AxoButtonSpinnerSizes: Record<
|
||||||
|
AxoButtonSize,
|
||||||
|
{ size: number; strokeWidth: number }
|
||||||
|
> = {
|
||||||
|
large: { size: 20, strokeWidth: 2 },
|
||||||
|
medium: { size: 20, strokeWidth: 2 },
|
||||||
|
small: { size: 16, strokeWidth: 1.5 },
|
||||||
|
};
|
||||||
|
|
||||||
|
type ExperimentalButtonSpinnerProps = Readonly<{
|
||||||
|
buttonVariant: AxoButtonVariant;
|
||||||
|
buttonSize: AxoButtonSize;
|
||||||
|
'aria-label': string;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
function ExperimentalButtonSpinner(
|
||||||
|
props: ExperimentalButtonSpinnerProps
|
||||||
|
): JSX.Element {
|
||||||
|
const variant = AxoButtonSpinnerVariants[props.buttonVariant];
|
||||||
|
const sizeConfig = AxoButtonSpinnerSizes[props.buttonSize];
|
||||||
|
return (
|
||||||
|
<span className={tw('absolute inset-0 flex items-center justify-center')}>
|
||||||
|
<SpinnerV2
|
||||||
|
size={sizeConfig.size}
|
||||||
|
strokeWidth={sizeConfig.strokeWidth}
|
||||||
|
variant={variant}
|
||||||
|
value="indeterminate"
|
||||||
|
ariaLabel={props['aria-label']}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export namespace AxoButton {
|
export namespace AxoButton {
|
||||||
export type Variant = AxoButtonVariant;
|
export type Variant = AxoButtonVariant;
|
||||||
export type Size = AxoButtonSize;
|
export type Size = AxoButtonSize;
|
||||||
|
|
||||||
export type RootProps = BaseButtonAttrs &
|
export type RootProps = BaseButtonAttrs &
|
||||||
Readonly<{
|
Readonly<{
|
||||||
variant: AxoButtonVariant;
|
variant: AxoButtonVariant;
|
||||||
size: AxoButtonSize;
|
size: AxoButtonSize;
|
||||||
symbol?: AxoSymbol.InlineGlyphName;
|
symbol?: AxoSymbol.InlineGlyphName;
|
||||||
arrow?: boolean;
|
arrow?: boolean;
|
||||||
|
experimentalSpinner?: { 'aria-label': string } | null;
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
export const Root: FC<RootProps> = memo(
|
export const Root: FC<RootProps> = memo(
|
||||||
forwardRef((props, ref: ForwardedRef<HTMLButtonElement>) => {
|
forwardRef((props, ref: ForwardedRef<HTMLButtonElement>) => {
|
||||||
const { variant, size, symbol, arrow, children, ...rest } = props;
|
const {
|
||||||
|
variant,
|
||||||
|
size,
|
||||||
|
symbol,
|
||||||
|
arrow,
|
||||||
|
experimentalSpinner,
|
||||||
|
children,
|
||||||
|
...rest
|
||||||
|
} = props;
|
||||||
const variantStyles = assert(
|
const variantStyles = assert(
|
||||||
AxoButtonVariants[variant],
|
AxoButtonVariants[variant],
|
||||||
`${Namespace}: Invalid variant ${variant}`
|
`${Namespace}: Invalid variant ${variant}`
|
||||||
@@ -170,12 +233,19 @@ export namespace AxoButton {
|
|||||||
AxoButtonSizes[size],
|
AxoButtonSizes[size],
|
||||||
`${Namespace}: Invalid size ${size}`
|
`${Namespace}: Invalid size ${size}`
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
ref={ref}
|
ref={ref}
|
||||||
type="button"
|
type="button"
|
||||||
className={tw(variantStyles, sizeStyles)}
|
className={tw(variantStyles, sizeStyles)}
|
||||||
{...rest}
|
{...rest}
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
className={tw(
|
||||||
|
'flex shrink grow items-center-safe justify-center-safe gap-1 truncate',
|
||||||
|
experimentalSpinner != null ? 'opacity-0' : null
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
{symbol != null && (
|
{symbol != null && (
|
||||||
<AxoSymbol.InlineGlyph symbol={symbol} label={null} />
|
<AxoSymbol.InlineGlyph symbol={symbol} label={null} />
|
||||||
@@ -184,6 +254,14 @@ export namespace AxoButton {
|
|||||||
{arrow && (
|
{arrow && (
|
||||||
<AxoSymbol.InlineGlyph symbol="chevron-[end]" label={null} />
|
<AxoSymbol.InlineGlyph symbol="chevron-[end]" label={null} />
|
||||||
)}
|
)}
|
||||||
|
</span>
|
||||||
|
{experimentalSpinner != null && (
|
||||||
|
<ExperimentalButtonSpinner
|
||||||
|
buttonVariant={variant}
|
||||||
|
buttonSize={size}
|
||||||
|
aria-label={experimentalSpinner['aria-label']}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -2,11 +2,10 @@
|
|||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
|
|
||||||
import { Button, ButtonVariant } from './Button.dom.js';
|
|
||||||
import { ConfirmDiscardDialog } from './ConfirmDiscardDialog.dom.js';
|
import { ConfirmDiscardDialog } from './ConfirmDiscardDialog.dom.js';
|
||||||
import type { LocalizerType } from '../types/Util.std.js';
|
import type { LocalizerType } from '../types/Util.std.js';
|
||||||
import { Modal } from './Modal.dom.js';
|
import { Modal } from './Modal.dom.js';
|
||||||
|
import { AxoButton } from '../axo/AxoButton.dom.js';
|
||||||
|
|
||||||
export type PropsType = {
|
export type PropsType = {
|
||||||
hasChanges: boolean;
|
hasChanges: boolean;
|
||||||
@@ -27,7 +26,9 @@ export function AvatarModalButtons({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal.ButtonFooter>
|
<Modal.ButtonFooter>
|
||||||
<Button
|
<AxoButton.Root
|
||||||
|
variant="secondary"
|
||||||
|
size="large"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (hasChanges) {
|
if (hasChanges) {
|
||||||
setConfirmDiscardAction(() => onCancel);
|
setConfirmDiscardAction(() => onCancel);
|
||||||
@@ -35,13 +36,17 @@ export function AvatarModalButtons({
|
|||||||
onCancel();
|
onCancel();
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
variant={ButtonVariant.Secondary}
|
|
||||||
>
|
>
|
||||||
{i18n('icu:cancel')}
|
{i18n('icu:cancel')}
|
||||||
</Button>
|
</AxoButton.Root>
|
||||||
<Button disabled={!hasChanges} onClick={onSave}>
|
<AxoButton.Root
|
||||||
|
variant="primary"
|
||||||
|
size="large"
|
||||||
|
disabled={!hasChanges}
|
||||||
|
onClick={onSave}
|
||||||
|
>
|
||||||
{i18n('icu:save')}
|
{i18n('icu:save')}
|
||||||
</Button>
|
</AxoButton.Root>
|
||||||
{confirmDiscardAction && (
|
{confirmDiscardAction && (
|
||||||
<ConfirmDiscardDialog
|
<ConfirmDiscardDialog
|
||||||
i18n={i18n}
|
i18n={i18n}
|
||||||
|
|||||||
@@ -16,8 +16,6 @@ import * as LocaleMatcher from '@formatjs/intl-localematcher';
|
|||||||
import type { MutableRefObject, ReactNode } from 'react';
|
import type { MutableRefObject, ReactNode } from 'react';
|
||||||
import type { RowType } from '@signalapp/sqlcipher';
|
import type { RowType } from '@signalapp/sqlcipher';
|
||||||
import type { BackupLevel } from '@signalapp/libsignal-client/zkgroup.js';
|
import type { BackupLevel } from '@signalapp/libsignal-client/zkgroup.js';
|
||||||
|
|
||||||
import { Button, ButtonVariant } from './Button.dom.js';
|
|
||||||
import { ChatColorPicker } from './ChatColorPicker.dom.js';
|
import { ChatColorPicker } from './ChatColorPicker.dom.js';
|
||||||
import { Checkbox } from './Checkbox.dom.js';
|
import { Checkbox } from './Checkbox.dom.js';
|
||||||
import { WidthBreakpoint } from './_util.std.js';
|
import { WidthBreakpoint } from './_util.std.js';
|
||||||
@@ -26,7 +24,6 @@ import { DisappearingTimeDialog } from './DisappearingTimeDialog.dom.js';
|
|||||||
import { PhoneNumberDiscoverability } from '../util/phoneNumberDiscoverability.std.js';
|
import { PhoneNumberDiscoverability } from '../util/phoneNumberDiscoverability.std.js';
|
||||||
import { PhoneNumberSharingMode } from '../types/PhoneNumberSharingMode.std.js';
|
import { PhoneNumberSharingMode } from '../types/PhoneNumberSharingMode.std.js';
|
||||||
import { Select } from './Select.dom.js';
|
import { Select } from './Select.dom.js';
|
||||||
import { Spinner } from './Spinner.dom.js';
|
|
||||||
import { getCustomColorStyle } from '../util/getCustomColorStyle.dom.js';
|
import { getCustomColorStyle } from '../util/getCustomColorStyle.dom.js';
|
||||||
import {
|
import {
|
||||||
DEFAULT_DURATIONS_IN_SECONDS,
|
DEFAULT_DURATIONS_IN_SECONDS,
|
||||||
@@ -949,21 +946,23 @@ export function Preferences({
|
|||||||
}
|
}
|
||||||
modalFooter={
|
modalFooter={
|
||||||
<>
|
<>
|
||||||
<Button
|
<AxoButton.Root
|
||||||
variant={ButtonVariant.Secondary}
|
variant="secondary"
|
||||||
|
size="large"
|
||||||
onClick={closeLanguageDialog}
|
onClick={closeLanguageDialog}
|
||||||
>
|
>
|
||||||
{i18n('icu:cancel')}
|
{i18n('icu:cancel')}
|
||||||
</Button>
|
</AxoButton.Root>
|
||||||
<Button
|
<AxoButton.Root
|
||||||
variant={ButtonVariant.Primary}
|
variant="primary"
|
||||||
|
size="large"
|
||||||
disabled={selectedLanguageLocale === localeOverride}
|
disabled={selectedLanguageLocale === localeOverride}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setLanguageDialog(LanguageDialog.Confirmation);
|
setLanguageDialog(LanguageDialog.Confirmation);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{i18n('icu:Preferences__LanguageModal__Set')}
|
{i18n('icu:Preferences__LanguageModal__Set')}
|
||||||
</Button>
|
</AxoButton.Root>
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
@@ -1210,7 +1209,7 @@ export function Preferences({
|
|||||||
}
|
}
|
||||||
right={
|
right={
|
||||||
<AxoButton.Root
|
<AxoButton.Root
|
||||||
size="medium"
|
size="large"
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setSettingsLocation({
|
setSettingsLocation({
|
||||||
@@ -1254,12 +1253,13 @@ export function Preferences({
|
|||||||
}
|
}
|
||||||
right={
|
right={
|
||||||
<div className="Preferences__right-button">
|
<div className="Preferences__right-button">
|
||||||
<Button
|
<AxoButton.Root
|
||||||
aria-label={
|
variant="secondary"
|
||||||
nowSyncing ? i18n('icu:syncing') : i18n('icu:syncNow')
|
size="large"
|
||||||
}
|
|
||||||
aria-live="polite"
|
|
||||||
disabled={nowSyncing}
|
disabled={nowSyncing}
|
||||||
|
experimentalSpinner={
|
||||||
|
nowSyncing ? { 'aria-label': i18n('icu:syncing') } : null
|
||||||
|
}
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
setShowSyncFailed(false);
|
setShowSyncFailed(false);
|
||||||
setNowSyncing(true);
|
setNowSyncing(true);
|
||||||
@@ -1272,14 +1272,9 @@ export function Preferences({
|
|||||||
setNowSyncing(false);
|
setNowSyncing(false);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
variant={ButtonVariant.SecondaryAffirmative}
|
|
||||||
>
|
>
|
||||||
{nowSyncing ? (
|
{i18n('icu:syncNow')}
|
||||||
<Spinner svgSize="small" />
|
</AxoButton.Root>
|
||||||
) : (
|
|
||||||
i18n('icu:syncNow')
|
|
||||||
)}
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
@@ -1558,11 +1553,9 @@ export function Preferences({
|
|||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
right={
|
right={
|
||||||
<Button
|
<AxoButton.Root
|
||||||
testId="OnboardNotificationProfiles"
|
variant="secondary"
|
||||||
aria-label={i18n('icu:NotificationProfiles--setup')}
|
size="large"
|
||||||
aria-live="polite"
|
|
||||||
variant={ButtonVariant.SecondaryAffirmative}
|
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
setSettingsLocation({
|
setSettingsLocation({
|
||||||
page: SettingsPage.NotificationProfilesHome,
|
page: SettingsPage.NotificationProfilesHome,
|
||||||
@@ -1570,7 +1563,7 @@ export function Preferences({
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
{i18n('icu:NotificationProfiles--setup')}
|
{i18n('icu:NotificationProfiles--setup')}
|
||||||
</Button>
|
</AxoButton.Root>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</SettingsRow>
|
</SettingsRow>
|
||||||
@@ -1610,12 +1603,13 @@ export function Preferences({
|
|||||||
'Preferences__one-third-flow--align-right'
|
'Preferences__one-third-flow--align-right'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Button
|
<AxoButton.Root
|
||||||
|
variant="secondary"
|
||||||
|
size="large"
|
||||||
onClick={() => setSettingsLocation({ page: SettingsPage.PNP })}
|
onClick={() => setSettingsLocation({ page: SettingsPage.PNP })}
|
||||||
variant={ButtonVariant.Secondary}
|
|
||||||
>
|
>
|
||||||
{i18n('icu:Preferences__pnp__row--button')}
|
{i18n('icu:Preferences__pnp__row--button')}
|
||||||
</Button>
|
</AxoButton.Root>
|
||||||
</div>
|
</div>
|
||||||
</FlowingControl>
|
</FlowingControl>
|
||||||
</SettingsRow>
|
</SettingsRow>
|
||||||
@@ -1767,20 +1761,21 @@ export function Preferences({
|
|||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{hasStoriesDisabled ? (
|
{hasStoriesDisabled ? (
|
||||||
<Button
|
<AxoButton.Root
|
||||||
onClick={() => onHasStoriesDisabledChanged(false)}
|
onClick={() => onHasStoriesDisabledChanged(false)}
|
||||||
variant={ButtonVariant.Secondary}
|
variant="secondary"
|
||||||
|
size="large"
|
||||||
>
|
>
|
||||||
{i18n('icu:Preferences__turn-stories-on')}
|
{i18n('icu:Preferences__turn-stories-on')}
|
||||||
</Button>
|
</AxoButton.Root>
|
||||||
) : (
|
) : (
|
||||||
<Button
|
<AxoButton.Root
|
||||||
className="Preferences__stories-off"
|
|
||||||
onClick={() => setConfirmStoriesOff(true)}
|
onClick={() => setConfirmStoriesOff(true)}
|
||||||
variant={ButtonVariant.SecondaryDestructive}
|
variant="subtle-destructive"
|
||||||
|
size="large"
|
||||||
>
|
>
|
||||||
{i18n('icu:Preferences__turn-stories-off')}
|
{i18n('icu:Preferences__turn-stories-off')}
|
||||||
</Button>
|
</AxoButton.Root>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</FlowingControl>
|
</FlowingControl>
|
||||||
@@ -1807,12 +1802,13 @@ export function Preferences({
|
|||||||
'Preferences__one-third-flow--align-right'
|
'Preferences__one-third-flow--align-right'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Button
|
<AxoButton.Root
|
||||||
|
variant="subtle-destructive"
|
||||||
|
size="large"
|
||||||
onClick={() => setConfirmDelete(true)}
|
onClick={() => setConfirmDelete(true)}
|
||||||
variant={ButtonVariant.SecondaryDestructive}
|
|
||||||
>
|
>
|
||||||
{i18n('icu:clearDataButton')}
|
{i18n('icu:clearDataButton')}
|
||||||
</Button>
|
</AxoButton.Root>
|
||||||
</div>
|
</div>
|
||||||
</FlowingControl>
|
</FlowingControl>
|
||||||
</SettingsRow>
|
</SettingsRow>
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import {
|
|||||||
LightIconLabel,
|
LightIconLabel,
|
||||||
SettingsRow,
|
SettingsRow,
|
||||||
} from './PreferencesUtil.dom.js';
|
} from './PreferencesUtil.dom.js';
|
||||||
import { Button, ButtonVariant } from './Button.dom.js';
|
import { ButtonVariant } from './Button.dom.js';
|
||||||
import type { SettingsLocation } from '../types/Nav.std.js';
|
import type { SettingsLocation } from '../types/Nav.std.js';
|
||||||
import { SettingsPage } from '../types/Nav.std.js';
|
import { SettingsPage } from '../types/Nav.std.js';
|
||||||
import { I18n } from './I18n.dom.js';
|
import { I18n } from './I18n.dom.js';
|
||||||
@@ -27,6 +27,7 @@ import type {
|
|||||||
PromptOSAuthResultType,
|
PromptOSAuthResultType,
|
||||||
} from '../util/os/promptOSAuthMain.main.js';
|
} from '../util/os/promptOSAuthMain.main.js';
|
||||||
import { ConfirmationDialog } from './ConfirmationDialog.dom.js';
|
import { ConfirmationDialog } from './ConfirmationDialog.dom.js';
|
||||||
|
import { AxoButton } from '../axo/AxoButton.dom.js';
|
||||||
import { BackupLevel } from '../services/backups/types.std.js';
|
import { BackupLevel } from '../services/backups/types.std.js';
|
||||||
import {
|
import {
|
||||||
BackupsDetailsPage,
|
BackupsDetailsPage,
|
||||||
@@ -230,14 +231,15 @@ export function PreferencesBackups({
|
|||||||
'Preferences__one-third-flow--align-right'
|
'Preferences__one-third-flow--align-right'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Button
|
<AxoButton.Root
|
||||||
|
variant="secondary"
|
||||||
|
size="large"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
setSettingsLocation({ page: SettingsPage.BackupsDetails })
|
setSettingsLocation({ page: SettingsPage.BackupsDetails })
|
||||||
}
|
}
|
||||||
variant={ButtonVariant.Secondary}
|
|
||||||
>
|
>
|
||||||
{i18n('icu:Preferences__button--manage')}
|
{i18n('icu:Preferences__button--manage')}
|
||||||
</Button>
|
</AxoButton.Root>
|
||||||
</div>
|
</div>
|
||||||
</FlowingControl>
|
</FlowingControl>
|
||||||
</SettingsRow>
|
</SettingsRow>
|
||||||
@@ -273,8 +275,9 @@ export function PreferencesBackups({
|
|||||||
'Preferences__one-third-flow--align-right'
|
'Preferences__one-third-flow--align-right'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Button
|
<AxoButton.Root
|
||||||
className="Preferences--BackupsAuthButton"
|
variant="secondary"
|
||||||
|
size="large"
|
||||||
disabled={isAuthPending}
|
disabled={isAuthPending}
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
setAuthError(undefined);
|
setAuthError(undefined);
|
||||||
@@ -294,12 +297,11 @@ export function PreferencesBackups({
|
|||||||
|
|
||||||
setSettingsLocation({ page: SettingsPage.LocalBackups });
|
setSettingsLocation({ page: SettingsPage.LocalBackups });
|
||||||
}}
|
}}
|
||||||
variant={ButtonVariant.Secondary}
|
|
||||||
>
|
>
|
||||||
{isLocalBackupsSetup
|
{isLocalBackupsSetup
|
||||||
? i18n('icu:Preferences__button--manage')
|
? i18n('icu:Preferences__button--manage')
|
||||||
: i18n('icu:Preferences__button--set-up')}
|
: i18n('icu:Preferences__button--set-up')}
|
||||||
</Button>
|
</AxoButton.Root>
|
||||||
</div>
|
</div>
|
||||||
</FlowingControl>
|
</FlowingControl>
|
||||||
</SettingsRow>
|
</SettingsRow>
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import React, {
|
|||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import type { LocalizerType } from '../types/Util.std.js';
|
import type { LocalizerType } from '../types/Util.std.js';
|
||||||
import { useConfirmDiscard } from '../hooks/useConfirmDiscard.dom.js';
|
import { useConfirmDiscard } from '../hooks/useConfirmDiscard.dom.js';
|
||||||
import { Button, ButtonVariant } from './Button.dom.js';
|
|
||||||
import {
|
import {
|
||||||
donationStateSchema,
|
donationStateSchema,
|
||||||
ONE_TIME_DONATION_CONFIG_ID,
|
ONE_TIME_DONATION_CONFIG_ID,
|
||||||
@@ -70,6 +69,7 @@ import { DonationsOfflineTooltip } from './conversation/DonationsOfflineTooltip.
|
|||||||
import { DonateInputAmount } from './preferences/donations/DonateInputAmount.dom.js';
|
import { DonateInputAmount } from './preferences/donations/DonateInputAmount.dom.js';
|
||||||
import { Tooltip, TooltipPlacement } from './Tooltip.dom.js';
|
import { Tooltip, TooltipPlacement } from './Tooltip.dom.js';
|
||||||
import { offsetDistanceModifier } from '../util/popperUtil.std.js';
|
import { offsetDistanceModifier } from '../util/popperUtil.std.js';
|
||||||
|
import { AxoButton } from '../axo/AxoButton.dom.js';
|
||||||
|
|
||||||
const SUPPORT_URL = 'https://support.signal.org/hc/requests/new?desktop';
|
const SUPPORT_URL = 'https://support.signal.org/hc/requests/new?desktop';
|
||||||
|
|
||||||
@@ -516,14 +516,14 @@ function AmountPicker({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const continueButton = (
|
const continueButton = (
|
||||||
<Button
|
<AxoButton.Root
|
||||||
className="PreferencesDonations__PrimaryButton"
|
variant={isOnline ? 'primary' : 'secondary'}
|
||||||
|
size="large"
|
||||||
disabled={!isContinueEnabled}
|
disabled={!isContinueEnabled}
|
||||||
onClick={handleContinueClicked}
|
onClick={handleContinueClicked}
|
||||||
variant={isOnline ? ButtonVariant.Primary : ButtonVariant.Secondary}
|
|
||||||
>
|
>
|
||||||
{i18n('icu:DonateFlow__continue')}
|
{i18n('icu:DonateFlow__continue')}
|
||||||
</Button>
|
</AxoButton.Root>
|
||||||
);
|
);
|
||||||
|
|
||||||
let continueButtonWithTooltip: JSX.Element | undefined;
|
let continueButtonWithTooltip: JSX.Element | undefined;
|
||||||
@@ -759,16 +759,16 @@ function CardForm({
|
|||||||
}, [handleDonateClicked, isDonateDisabled]);
|
}, [handleDonateClicked, isDonateDisabled]);
|
||||||
|
|
||||||
const donateButton = (
|
const donateButton = (
|
||||||
<Button
|
<AxoButton.Root
|
||||||
className="PreferencesDonations__PrimaryButton"
|
|
||||||
disabled={isDonateDisabled}
|
disabled={isDonateDisabled}
|
||||||
onClick={handleDonateClicked}
|
onClick={handleDonateClicked}
|
||||||
variant={isOnline ? ButtonVariant.Primary : ButtonVariant.Secondary}
|
variant={isOnline ? 'primary' : 'secondary'}
|
||||||
|
size="large"
|
||||||
>
|
>
|
||||||
{i18n('icu:PreferencesDonations__donate-button-with-amount', {
|
{i18n('icu:PreferencesDonations__donate-button-with-amount', {
|
||||||
formattedCurrencyAmount,
|
formattedCurrencyAmount,
|
||||||
})}
|
})}
|
||||||
</Button>
|
</AxoButton.Root>
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -55,6 +55,8 @@ import type { AvatarUpdateOptionsType } from '../types/Avatar.std.js';
|
|||||||
import { drop } from '../util/drop.std.js';
|
import { drop } from '../util/drop.std.js';
|
||||||
import { DonationsOfflineTooltip } from './conversation/DonationsOfflineTooltip.dom.js';
|
import { DonationsOfflineTooltip } from './conversation/DonationsOfflineTooltip.dom.js';
|
||||||
import { getInProgressDonation } from '../util/donations.dom.js';
|
import { getInProgressDonation } from '../util/donations.dom.js';
|
||||||
|
import { AxoButton } from '../axo/AxoButton.dom.js';
|
||||||
|
import { tw } from '../axo/tw.dom.js';
|
||||||
|
|
||||||
const { groupBy, sortBy } = lodash;
|
const { groupBy, sortBy } = lodash;
|
||||||
|
|
||||||
@@ -234,15 +236,16 @@ function DonationsHome({
|
|||||||
const hasReceipts = donationReceipts.length > 0;
|
const hasReceipts = donationReceipts.length > 0;
|
||||||
|
|
||||||
const donateButton = (
|
const donateButton = (
|
||||||
<Button
|
<span className={tw('mb-8')}>
|
||||||
className="PreferencesDonations__PrimaryButton PreferencesDonations__donate-button"
|
<AxoButton.Root
|
||||||
|
variant={isOnline ? 'primary' : 'secondary'}
|
||||||
|
size="medium"
|
||||||
disabled={!isOnline}
|
disabled={!isOnline}
|
||||||
variant={isOnline ? ButtonVariant.Primary : ButtonVariant.Secondary}
|
|
||||||
size={ButtonSize.Medium}
|
|
||||||
onClick={handleDonateButtonClicked}
|
onClick={handleDonateButtonClicked}
|
||||||
>
|
>
|
||||||
{i18n('icu:PreferencesDonations__donate-button')}
|
{i18n('icu:PreferencesDonations__donate-button')}
|
||||||
</Button>
|
</AxoButton.Root>
|
||||||
|
</span>
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -12,8 +12,6 @@ import { formatFileSize } from '../util/formatFileSize.std.js';
|
|||||||
import { SECOND } from '../util/durations/index.std.js';
|
import { SECOND } from '../util/durations/index.std.js';
|
||||||
import type { ValidationResultType as BackupValidationResultType } from '../services/backups/index.preload.js';
|
import type { ValidationResultType as BackupValidationResultType } from '../services/backups/index.preload.js';
|
||||||
import { SettingsRow, FlowingSettingsControl } from './PreferencesUtil.dom.js';
|
import { SettingsRow, FlowingSettingsControl } from './PreferencesUtil.dom.js';
|
||||||
import { Button, ButtonVariant } from './Button.dom.js';
|
|
||||||
import { Spinner } from './Spinner.dom.js';
|
|
||||||
import type { MessageCountBySchemaVersionType } from '../sql/Interface.std.js';
|
import type { MessageCountBySchemaVersionType } from '../sql/Interface.std.js';
|
||||||
import type { MessageAttributesType } from '../model-types.d.ts';
|
import type { MessageAttributesType } from '../model-types.d.ts';
|
||||||
import type { DonationReceipt } from '../types/Donations.std.js';
|
import type { DonationReceipt } from '../types/Donations.std.js';
|
||||||
@@ -21,6 +19,7 @@ import { createLogger } from '../logging/log.std.js';
|
|||||||
import { isStagingServer } from '../util/isStagingServer.dom.js';
|
import { isStagingServer } from '../util/isStagingServer.dom.js';
|
||||||
import { getHumanDonationAmount } from '../util/currency.dom.js';
|
import { getHumanDonationAmount } from '../util/currency.dom.js';
|
||||||
import { AutoSizeTextArea } from './AutoSizeTextArea.dom.js';
|
import { AutoSizeTextArea } from './AutoSizeTextArea.dom.js';
|
||||||
|
import { AxoButton } from '../axo/AxoButton.dom.js';
|
||||||
|
|
||||||
const log = createLogger('PreferencesInternal');
|
const log = createLogger('PreferencesInternal');
|
||||||
|
|
||||||
@@ -240,17 +239,19 @@ export function PreferencesInternal({
|
|||||||
'Preferences__one-third-flow--align-right'
|
'Preferences__one-third-flow--align-right'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Button
|
<AxoButton.Root
|
||||||
variant={ButtonVariant.Secondary}
|
variant="secondary"
|
||||||
|
size="large"
|
||||||
onClick={validateBackup}
|
onClick={validateBackup}
|
||||||
disabled={isValidationPending}
|
disabled={isValidationPending}
|
||||||
|
experimentalSpinner={
|
||||||
|
isValidationPending
|
||||||
|
? { 'aria-label': i18n('icu:loading') }
|
||||||
|
: null
|
||||||
|
}
|
||||||
>
|
>
|
||||||
{isValidationPending ? (
|
{i18n('icu:Preferences__internal__validate-backup')}
|
||||||
<Spinner size="22px" svgSize="small" />
|
</AxoButton.Root>
|
||||||
) : (
|
|
||||||
i18n('icu:Preferences__internal__validate-backup')
|
|
||||||
)}
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
</FlowingSettingsControl>
|
</FlowingSettingsControl>
|
||||||
|
|
||||||
@@ -274,17 +275,17 @@ export function PreferencesInternal({
|
|||||||
'Preferences__one-third-flow--align-right'
|
'Preferences__one-third-flow--align-right'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Button
|
<AxoButton.Root
|
||||||
variant={ButtonVariant.Secondary}
|
variant="secondary"
|
||||||
|
size="large"
|
||||||
onClick={exportLocalBackup}
|
onClick={exportLocalBackup}
|
||||||
disabled={isExportPending}
|
disabled={isExportPending}
|
||||||
|
experimentalSpinner={
|
||||||
|
isExportPending ? { 'aria-label': i18n('icu:loading') } : null
|
||||||
|
}
|
||||||
>
|
>
|
||||||
{isExportPending ? (
|
{i18n('icu:Preferences__internal__export-local-backup')}
|
||||||
<Spinner size="22px" svgSize="small" />
|
</AxoButton.Root>
|
||||||
) : (
|
|
||||||
i18n('icu:Preferences__internal__export-local-backup')
|
|
||||||
)}
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
</FlowingSettingsControl>
|
</FlowingSettingsControl>
|
||||||
|
|
||||||
@@ -306,8 +307,9 @@ export function PreferencesInternal({
|
|||||||
'Preferences__one-third-flow--align-right'
|
'Preferences__one-third-flow--align-right'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Button
|
<AxoButton.Root
|
||||||
variant={ButtonVariant.Secondary}
|
variant="secondary"
|
||||||
|
size="large"
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
setMessageCountBySchemaVersion(
|
setMessageCountBySchemaVersion(
|
||||||
await getMessageCountBySchemaVersion()
|
await getMessageCountBySchemaVersion()
|
||||||
@@ -317,7 +319,7 @@ export function PreferencesInternal({
|
|||||||
disabled={isExportPending}
|
disabled={isExportPending}
|
||||||
>
|
>
|
||||||
Fetch data
|
Fetch data
|
||||||
</Button>
|
</AxoButton.Root>
|
||||||
</div>
|
</div>
|
||||||
</FlowingSettingsControl>
|
</FlowingSettingsControl>
|
||||||
|
|
||||||
@@ -400,12 +402,13 @@ export function PreferencesInternal({
|
|||||||
'Preferences__one-third-flow--align-right'
|
'Preferences__one-third-flow--align-right'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Button
|
<AxoButton.Root
|
||||||
variant={ButtonVariant.Secondary}
|
variant="secondary"
|
||||||
|
size="large"
|
||||||
onClick={handleAddTestReceipt}
|
onClick={handleAddTestReceipt}
|
||||||
>
|
>
|
||||||
Add Test Receipt
|
Add Test Receipt
|
||||||
</Button>
|
</AxoButton.Root>
|
||||||
</div>
|
</div>
|
||||||
</FlowingSettingsControl>
|
</FlowingSettingsControl>
|
||||||
|
|
||||||
@@ -450,17 +453,19 @@ export function PreferencesInternal({
|
|||||||
{receipt.id.substring(0, 8)}...
|
{receipt.id.substring(0, 8)}...
|
||||||
</td>
|
</td>
|
||||||
<td style={{ padding: '8px' }}>
|
<td style={{ padding: '8px' }}>
|
||||||
<Button
|
<AxoButton.Root
|
||||||
variant={ButtonVariant.Secondary}
|
variant="secondary"
|
||||||
|
size="large"
|
||||||
onClick={() => handleGenerateReceipt(receipt)}
|
onClick={() => handleGenerateReceipt(receipt)}
|
||||||
disabled={isGeneratingReceipt}
|
disabled={isGeneratingReceipt}
|
||||||
|
experimentalSpinner={
|
||||||
|
isGeneratingReceipt
|
||||||
|
? { 'aria-label': i18n('icu:loading') }
|
||||||
|
: null
|
||||||
|
}
|
||||||
>
|
>
|
||||||
{isGeneratingReceipt ? (
|
Download
|
||||||
<Spinner size="16px" svgSize="small" />
|
</AxoButton.Root>
|
||||||
) : (
|
|
||||||
'Download'
|
|
||||||
)}
|
|
||||||
</Button>
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
))}
|
))}
|
||||||
@@ -486,12 +491,13 @@ export function PreferencesInternal({
|
|||||||
placeholder="SELECT * FROM items"
|
placeholder="SELECT * FROM items"
|
||||||
moduleClassName="Preferences__ReadonlySqlPlayground__Textarea"
|
moduleClassName="Preferences__ReadonlySqlPlayground__Textarea"
|
||||||
/>
|
/>
|
||||||
<Button
|
<AxoButton.Root
|
||||||
variant={ButtonVariant.Destructive}
|
variant="destructive"
|
||||||
|
size="large"
|
||||||
onClick={handleReadOnlySqlInputSubmit}
|
onClick={handleReadOnlySqlInputSubmit}
|
||||||
>
|
>
|
||||||
Run Query
|
Run Query
|
||||||
</Button>
|
</AxoButton.Root>
|
||||||
{readOnlySqlResults != null && (
|
{readOnlySqlResults != null && (
|
||||||
<AutoSizeTextArea
|
<AutoSizeTextArea
|
||||||
i18n={i18n}
|
i18n={i18n}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import {
|
|||||||
FlowingSettingsControl as FlowingControl,
|
FlowingSettingsControl as FlowingControl,
|
||||||
SettingsRow,
|
SettingsRow,
|
||||||
} from './PreferencesUtil.dom.js';
|
} from './PreferencesUtil.dom.js';
|
||||||
import { Button, ButtonSize, ButtonVariant } from './Button.dom.js';
|
import { ButtonVariant } from './Button.dom.js';
|
||||||
import {
|
import {
|
||||||
getOSAuthErrorString,
|
getOSAuthErrorString,
|
||||||
SIGNAL_BACKUPS_LEARN_MORE_URL,
|
SIGNAL_BACKUPS_LEARN_MORE_URL,
|
||||||
@@ -34,6 +34,7 @@ import type {
|
|||||||
PromptOSAuthResultType,
|
PromptOSAuthResultType,
|
||||||
} from '../util/os/promptOSAuthMain.main.js';
|
} from '../util/os/promptOSAuthMain.main.js';
|
||||||
import { ConfirmationDialog } from './ConfirmationDialog.dom.js';
|
import { ConfirmationDialog } from './ConfirmationDialog.dom.js';
|
||||||
|
import { AxoButton } from '../axo/AxoButton.dom.js';
|
||||||
|
|
||||||
const { noop } = lodash;
|
const { noop } = lodash;
|
||||||
|
|
||||||
@@ -129,12 +130,13 @@ export function PreferencesLocalBackups({
|
|||||||
'Preferences__one-third-flow--align-right'
|
'Preferences__one-third-flow--align-right'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Button
|
<AxoButton.Root
|
||||||
|
variant="secondary"
|
||||||
|
size="large"
|
||||||
onClick={pickLocalBackupFolder}
|
onClick={pickLocalBackupFolder}
|
||||||
variant={ButtonVariant.Secondary}
|
|
||||||
>
|
>
|
||||||
{i18n('icu:Preferences__local-backups-folder__change')}
|
{i18n('icu:Preferences__local-backups-folder__change')}
|
||||||
</Button>
|
</AxoButton.Root>
|
||||||
</div>
|
</div>
|
||||||
</FlowingControl>
|
</FlowingControl>
|
||||||
<FlowingControl>
|
<FlowingControl>
|
||||||
@@ -153,9 +155,13 @@ export function PreferencesLocalBackups({
|
|||||||
'Preferences__one-third-flow--align-right'
|
'Preferences__one-third-flow--align-right'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Button
|
<AxoButton.Root
|
||||||
className="Preferences--BackupsAuthButton"
|
variant="secondary"
|
||||||
|
size="large"
|
||||||
disabled={isAuthPending}
|
disabled={isAuthPending}
|
||||||
|
experimentalSpinner={
|
||||||
|
isAuthPending ? { 'aria-label': i18n('icu:loading') } : null
|
||||||
|
}
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
setAuthError(undefined);
|
setAuthError(undefined);
|
||||||
|
|
||||||
@@ -173,10 +179,9 @@ export function PreferencesLocalBackups({
|
|||||||
setIsAuthPending(false);
|
setIsAuthPending(false);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
variant={ButtonVariant.Secondary}
|
|
||||||
>
|
>
|
||||||
{i18n('icu:Preferences__view-key')}
|
{i18n('icu:Preferences__view-key')}
|
||||||
</Button>
|
</AxoButton.Root>
|
||||||
</div>
|
</div>
|
||||||
</FlowingControl>
|
</FlowingControl>
|
||||||
</SettingsRow>
|
</SettingsRow>
|
||||||
@@ -226,9 +231,13 @@ function LocalBackupsSetupFolderPicker({
|
|||||||
<div className="Preferences--LocalBackupsSetupScreenBody Preferences--LocalBackupsSetupScreenBody--folder">
|
<div className="Preferences--LocalBackupsSetupScreenBody Preferences--LocalBackupsSetupScreenBody--folder">
|
||||||
{i18n('icu:Preferences--local-backups-setup-folder-description')}
|
{i18n('icu:Preferences--local-backups-setup-folder-description')}
|
||||||
</div>
|
</div>
|
||||||
<Button onClick={pickLocalBackupFolder} variant={ButtonVariant.Primary}>
|
<AxoButton.Root
|
||||||
|
variant="primary"
|
||||||
|
size="large"
|
||||||
|
onClick={pickLocalBackupFolder}
|
||||||
|
>
|
||||||
{i18n('icu:Preferences__button--choose-folder')}
|
{i18n('icu:Preferences__button--choose-folder')}
|
||||||
</Button>
|
</AxoButton.Root>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -295,23 +304,23 @@ function LocalBackupsBackupKeyViewer({
|
|||||||
);
|
);
|
||||||
if (step === 'view') {
|
if (step === 'view') {
|
||||||
footerRight = (
|
footerRight = (
|
||||||
<Button
|
<AxoButton.Root
|
||||||
className="Preferences--LocalBackupsSetupScreenFooterButton"
|
variant="primary"
|
||||||
|
size="large"
|
||||||
onClick={() => setStep('confirm')}
|
onClick={() => setStep('confirm')}
|
||||||
variant={ButtonVariant.Primary}
|
|
||||||
>
|
>
|
||||||
{i18n('icu:Preferences--local-backups-setup-next')}
|
{i18n('icu:Preferences--local-backups-setup-next')}
|
||||||
</Button>
|
</AxoButton.Root>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
footerRight = (
|
footerRight = (
|
||||||
<Button
|
<AxoButton.Root
|
||||||
className="Preferences--LocalBackupsSetupScreenFooterButton"
|
variant="primary"
|
||||||
|
size="large"
|
||||||
onClick={onBackupKeyViewed}
|
onClick={onBackupKeyViewed}
|
||||||
variant={ButtonVariant.Primary}
|
|
||||||
>
|
>
|
||||||
{i18n('icu:Preferences--local-backups-view-backup-key-done')}
|
{i18n('icu:Preferences--local-backups-view-backup-key-done')}
|
||||||
</Button>
|
</AxoButton.Root>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -320,23 +329,23 @@ function LocalBackupsBackupKeyViewer({
|
|||||||
'icu:Preferences--local-backups-confirm-backup-key-description'
|
'icu:Preferences--local-backups-confirm-backup-key-description'
|
||||||
);
|
);
|
||||||
footerLeft = (
|
footerLeft = (
|
||||||
<button
|
<AxoButton.Root
|
||||||
className="Preferences--LocalBackupsSetupScreenFooterSeeKeyButton"
|
variant="borderless-primary"
|
||||||
|
size="large"
|
||||||
onClick={() => setStep('view')}
|
onClick={() => setStep('view')}
|
||||||
type="button"
|
|
||||||
>
|
>
|
||||||
{i18n('icu:Preferences--local-backups-see-backup-key-again')}
|
{i18n('icu:Preferences--local-backups-see-backup-key-again')}
|
||||||
</button>
|
</AxoButton.Root>
|
||||||
);
|
);
|
||||||
footerRight = (
|
footerRight = (
|
||||||
<Button
|
<AxoButton.Root
|
||||||
className="Preferences--LocalBackupsSetupScreenFooterButton"
|
variant="primary"
|
||||||
|
size="large"
|
||||||
disabled={!isBackupKeyConfirmed}
|
disabled={!isBackupKeyConfirmed}
|
||||||
onClick={() => setStep('caution')}
|
onClick={() => setStep('caution')}
|
||||||
variant={ButtonVariant.Primary}
|
|
||||||
>
|
>
|
||||||
{i18n('icu:Preferences--local-backups-setup-next')}
|
{i18n('icu:Preferences--local-backups-setup-next')}
|
||||||
</Button>
|
</AxoButton.Root>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -348,14 +357,15 @@ function LocalBackupsBackupKeyViewer({
|
|||||||
modalName="CallingAdhocCallInfo.UnknownContactInfo"
|
modalName="CallingAdhocCallInfo.UnknownContactInfo"
|
||||||
moduleClassName="Preferences--LocalBackupsConfirmKeyModal"
|
moduleClassName="Preferences--LocalBackupsConfirmKeyModal"
|
||||||
modalFooter={
|
modalFooter={
|
||||||
<Button
|
<AxoButton.Root
|
||||||
className="Preferences--LocalBackupsConfirmKeyModalButton"
|
variant="primary"
|
||||||
|
size="large"
|
||||||
onClick={onBackupKeyViewed}
|
onClick={onBackupKeyViewed}
|
||||||
>
|
>
|
||||||
{i18n(
|
{i18n(
|
||||||
'icu:Preferences__local-backups-confirm-key-modal-continue'
|
'icu:Preferences__local-backups-confirm-key-modal-continue'
|
||||||
)}
|
)}
|
||||||
</Button>
|
</AxoButton.Root>
|
||||||
}
|
}
|
||||||
onClose={() => setStep('confirm')}
|
onClose={() => setStep('confirm')}
|
||||||
padded={false}
|
padded={false}
|
||||||
@@ -391,14 +401,14 @@ function LocalBackupsBackupKeyViewer({
|
|||||||
</div>
|
</div>
|
||||||
{isStepViewOrReference && (
|
{isStepViewOrReference && (
|
||||||
<div className="Preferences--LocalBackupsSetupScreenPaneContent">
|
<div className="Preferences--LocalBackupsSetupScreenPaneContent">
|
||||||
<Button
|
<AxoButton.Root
|
||||||
className="Preferences--LocalBackupsSetupScreenCopyButton"
|
variant="secondary"
|
||||||
|
size="small"
|
||||||
|
symbol="copy"
|
||||||
onClick={onCopyBackupKey}
|
onClick={onCopyBackupKey}
|
||||||
size={ButtonSize.Small}
|
|
||||||
variant={ButtonVariant.Secondary}
|
|
||||||
>
|
>
|
||||||
{i18n('icu:Preferences__local-backups-copy-key')}
|
{i18n('icu:Preferences__local-backups-copy-key')}
|
||||||
</Button>
|
</AxoButton.Root>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import type { MutableRefObject } from 'react';
|
|||||||
import { AvatarColors } from '../types/Colors.std.js';
|
import { AvatarColors } from '../types/Colors.std.js';
|
||||||
import { AvatarEditor } from './AvatarEditor.dom.js';
|
import { AvatarEditor } from './AvatarEditor.dom.js';
|
||||||
import { AvatarPreview } from './AvatarPreview.dom.js';
|
import { AvatarPreview } from './AvatarPreview.dom.js';
|
||||||
import { Button, ButtonVariant } from './Button.dom.js';
|
import { ButtonVariant } from './Button.dom.js';
|
||||||
import { Input } from './Input.dom.js';
|
import { Input } from './Input.dom.js';
|
||||||
import { PanelRow } from './conversation/conversation-details/PanelRow.dom.js';
|
import { PanelRow } from './conversation/conversation-details/PanelRow.dom.js';
|
||||||
import { UsernameEditState } from '../state/ducks/usernameEnums.std.js';
|
import { UsernameEditState } from '../state/ducks/usernameEnums.std.js';
|
||||||
@@ -68,6 +68,7 @@ import type { ShowToastAction } from '../state/ducks/toast.preload.js';
|
|||||||
import type { EmojiParentKey, EmojiVariantKey } from './fun/data/emojis.std.js';
|
import type { EmojiParentKey, EmojiVariantKey } from './fun/data/emojis.std.js';
|
||||||
import type { FunEmojiSelection } from './fun/panels/FunPanelEmojis.dom.js';
|
import type { FunEmojiSelection } from './fun/panels/FunPanelEmojis.dom.js';
|
||||||
import { useConfirmDiscard } from '../hooks/useConfirmDiscard.dom.js';
|
import { useConfirmDiscard } from '../hooks/useConfirmDiscard.dom.js';
|
||||||
|
import { AxoButton } from '../axo/AxoButton.dom.js';
|
||||||
|
|
||||||
type ProfileEditorData = {
|
type ProfileEditorData = {
|
||||||
firstName: string;
|
firstName: string;
|
||||||
@@ -407,10 +408,12 @@ export function ProfileEditor({
|
|||||||
value={stagedProfile.familyName}
|
value={stagedProfile.familyName}
|
||||||
/>
|
/>
|
||||||
<div className="ProfileEditor__button-footer">
|
<div className="ProfileEditor__button-footer">
|
||||||
<Button onClick={handleBack} variant={ButtonVariant.Secondary}>
|
<AxoButton.Root variant="secondary" size="large" onClick={handleBack}>
|
||||||
{i18n('icu:cancel')}
|
{i18n('icu:cancel')}
|
||||||
</Button>
|
</AxoButton.Root>
|
||||||
<Button
|
<AxoButton.Root
|
||||||
|
variant="primary"
|
||||||
|
size="large"
|
||||||
disabled={shouldDisableSave}
|
disabled={shouldDisableSave}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (!stagedProfile.firstName) {
|
if (!stagedProfile.firstName) {
|
||||||
@@ -428,7 +431,7 @@ export function ProfileEditor({
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{i18n('icu:save')}
|
{i18n('icu:save')}
|
||||||
</Button>
|
</AxoButton.Root>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
@@ -513,10 +516,12 @@ export function ProfileEditor({
|
|||||||
})}
|
})}
|
||||||
|
|
||||||
<div className="ProfileEditor__button-footer">
|
<div className="ProfileEditor__button-footer">
|
||||||
<Button onClick={handleBack} variant={ButtonVariant.Secondary}>
|
<AxoButton.Root variant="secondary" size="large" onClick={handleBack}>
|
||||||
{i18n('icu:cancel')}
|
{i18n('icu:cancel')}
|
||||||
</Button>
|
</AxoButton.Root>
|
||||||
<Button
|
<AxoButton.Root
|
||||||
|
variant="primary"
|
||||||
|
size="large"
|
||||||
disabled={shouldDisableSave}
|
disabled={shouldDisableSave}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setFullBio({
|
setFullBio({
|
||||||
@@ -531,7 +536,7 @@ export function ProfileEditor({
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{i18n('icu:save')}
|
{i18n('icu:save')}
|
||||||
</Button>
|
</AxoButton.Root>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
@@ -714,15 +719,15 @@ export function ProfileEditor({
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<div className="ProfileEditor__EditPhotoContainer">
|
<div className="ProfileEditor__EditPhotoContainer">
|
||||||
<Button
|
<AxoButton.Root
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setEditState(ProfileEditorPage.BetterAvatar);
|
setEditState(ProfileEditorPage.BetterAvatar);
|
||||||
}}
|
}}
|
||||||
variant={ButtonVariant.Secondary}
|
variant="secondary"
|
||||||
className="ProfileEditor__EditPhoto"
|
size="small"
|
||||||
>
|
>
|
||||||
{i18n('icu:ProfileEditor--edit-photo')}
|
{i18n('icu:ProfileEditor--edit-photo')}
|
||||||
</Button>
|
</AxoButton.Root>
|
||||||
</div>
|
</div>
|
||||||
<PanelRow
|
<PanelRow
|
||||||
className="ProfileEditor__row"
|
className="ProfileEditor__row"
|
||||||
|
|||||||
@@ -43,6 +43,26 @@ const SpinnerVariants = {
|
|||||||
bg: tw('stroke-fill-secondary'),
|
bg: tw('stroke-fill-secondary'),
|
||||||
fg: tw('stroke-border-selected'),
|
fg: tw('stroke-border-selected'),
|
||||||
},
|
},
|
||||||
|
'axo-button-spinner-secondary': {
|
||||||
|
bg: tw('stroke-none'),
|
||||||
|
fg: tw('stroke-label-primary'),
|
||||||
|
},
|
||||||
|
'axo-button-spinner-on-color': {
|
||||||
|
bg: tw('stroke-none'),
|
||||||
|
fg: tw('stroke-label-primary-on-color'),
|
||||||
|
},
|
||||||
|
'axo-button-spinner-primary': {
|
||||||
|
bg: tw('stroke-none'),
|
||||||
|
fg: tw('stroke-color-label-primary'),
|
||||||
|
},
|
||||||
|
'axo-button-spinner-affirmative': {
|
||||||
|
bg: tw('stroke-none'),
|
||||||
|
fg: tw('stroke-color-label-affirmative'),
|
||||||
|
},
|
||||||
|
'axo-button-spinner-destructive': {
|
||||||
|
bg: tw('stroke-none'),
|
||||||
|
fg: tw('stroke-color-label-destructive'),
|
||||||
|
},
|
||||||
} as const satisfies Record<string, SpinnerVariantStyles>;
|
} as const satisfies Record<string, SpinnerVariantStyles>;
|
||||||
|
|
||||||
export type SpinnerVariant = keyof typeof SpinnerVariants;
|
export type SpinnerVariant = keyof typeof SpinnerVariants;
|
||||||
@@ -81,6 +101,7 @@ export function SpinnerV2({
|
|||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
className={tw('fill-none')}
|
className={tw('fill-none')}
|
||||||
|
aria-label={ariaLabel}
|
||||||
width={sizeInPixels}
|
width={sizeInPixels}
|
||||||
height={sizeInPixels}
|
height={sizeInPixels}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ import {
|
|||||||
} from '../state/ducks/usernameEnums.std.js';
|
} from '../state/ducks/usernameEnums.std.js';
|
||||||
import type { ReserveUsernameOptionsType } from '../state/ducks/username.preload.js';
|
import type { ReserveUsernameOptionsType } from '../state/ducks/username.preload.js';
|
||||||
import type { ShowToastAction } from '../state/ducks/toast.preload.js';
|
import type { ShowToastAction } from '../state/ducks/toast.preload.js';
|
||||||
|
|
||||||
import { AutoSizeInput } from './AutoSizeInput.dom.js';
|
import { AutoSizeInput } from './AutoSizeInput.dom.js';
|
||||||
import { ConfirmationDialog } from './ConfirmationDialog.dom.js';
|
import { ConfirmationDialog } from './ConfirmationDialog.dom.js';
|
||||||
import { Input } from './Input.dom.js';
|
import { Input } from './Input.dom.js';
|
||||||
@@ -34,6 +33,7 @@ import { Spinner } from './Spinner.dom.js';
|
|||||||
import { Modal } from './Modal.dom.js';
|
import { Modal } from './Modal.dom.js';
|
||||||
import { Button, ButtonVariant } from './Button.dom.js';
|
import { Button, ButtonVariant } from './Button.dom.js';
|
||||||
import { useConfirmDiscard } from '../hooks/useConfirmDiscard.dom.js';
|
import { useConfirmDiscard } from '../hooks/useConfirmDiscard.dom.js';
|
||||||
|
import { AxoButton } from '../axo/AxoButton.dom.js';
|
||||||
|
|
||||||
const { noop } = lodash;
|
const { noop } = lodash;
|
||||||
|
|
||||||
@@ -382,20 +382,25 @@ export function UsernameEditor({
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="UsernameEditor__button-footer">
|
<div className="UsernameEditor__button-footer">
|
||||||
<Button
|
<AxoButton.Root
|
||||||
|
variant="secondary"
|
||||||
|
size="large"
|
||||||
disabled={isConfirming}
|
disabled={isConfirming}
|
||||||
onClick={onCancel}
|
onClick={onCancel}
|
||||||
variant={ButtonVariant.Secondary}
|
|
||||||
>
|
>
|
||||||
{i18n('icu:cancel')}
|
{i18n('icu:cancel')}
|
||||||
</Button>
|
</AxoButton.Root>
|
||||||
<Button disabled={!canSave} onClick={onSave}>
|
<AxoButton.Root
|
||||||
{isConfirming ? (
|
variant="primary"
|
||||||
<Spinner size="20px" svgSize="small" direction="on-avatar" />
|
size="large"
|
||||||
) : (
|
disabled={!canSave}
|
||||||
i18n('icu:save')
|
onClick={onSave}
|
||||||
)}
|
experimentalSpinner={
|
||||||
</Button>
|
isConfirming ? { 'aria-label': i18n('icu:loading') } : null
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{i18n('icu:save')}
|
||||||
|
</AxoButton.Root>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{confirmDiscardModal}
|
{confirmDiscardModal}
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import type { PreferredBadgeSelectorType } from '../../../state/selectors/badges
|
|||||||
import type { LocalizerType } from '../../../types/I18N.std.js';
|
import type { LocalizerType } from '../../../types/I18N.std.js';
|
||||||
import type { ThemeType } from '../../../types/Util.std.js';
|
import type { ThemeType } from '../../../types/Util.std.js';
|
||||||
import { Input } from '../../Input.dom.js';
|
import { Input } from '../../Input.dom.js';
|
||||||
import { Button, ButtonVariant } from '../../Button.dom.js';
|
|
||||||
import { ConfirmationDialog } from '../../ConfirmationDialog.dom.js';
|
import { ConfirmationDialog } from '../../ConfirmationDialog.dom.js';
|
||||||
import type { ChatFolderSelection } from '../PreferencesSelectChatsDialog.dom.js';
|
import type { ChatFolderSelection } from '../PreferencesSelectChatsDialog.dom.js';
|
||||||
import { SettingsControl, SettingsRow } from '../../PreferencesUtil.dom.js';
|
import { SettingsControl, SettingsRow } from '../../PreferencesUtil.dom.js';
|
||||||
@@ -47,6 +46,7 @@ import {
|
|||||||
ItemContent,
|
ItemContent,
|
||||||
ItemTitle,
|
ItemTitle,
|
||||||
} from './PreferencesChatFolderItems.dom.js';
|
} from './PreferencesChatFolderItems.dom.js';
|
||||||
|
import { AxoButton } from '../../../axo/AxoButton.dom.js';
|
||||||
|
|
||||||
export type PreferencesEditChatFolderPageProps = Readonly<{
|
export type PreferencesEditChatFolderPageProps = Readonly<{
|
||||||
i18n: LocalizerType;
|
i18n: LocalizerType;
|
||||||
@@ -550,19 +550,21 @@ export function PreferencesEditChatFolderPage(
|
|||||||
title={i18n('icu:Preferences__EditChatFolderPage__Title')}
|
title={i18n('icu:Preferences__EditChatFolderPage__Title')}
|
||||||
actions={
|
actions={
|
||||||
<>
|
<>
|
||||||
<Button
|
<AxoButton.Root
|
||||||
variant={ButtonVariant.Secondary}
|
size="large"
|
||||||
|
variant="secondary"
|
||||||
onClick={handleDiscardAndBack}
|
onClick={handleDiscardAndBack}
|
||||||
>
|
>
|
||||||
{i18n('icu:Preferences__EditChatFolderPage__CancelButton')}
|
{i18n('icu:Preferences__EditChatFolderPage__CancelButton')}
|
||||||
</Button>
|
</AxoButton.Root>
|
||||||
<Button
|
<AxoButton.Root
|
||||||
variant={ButtonVariant.Primary}
|
size="large"
|
||||||
|
variant="primary"
|
||||||
onClick={handleSaveChangesAndBack}
|
onClick={handleSaveChangesAndBack}
|
||||||
disabled={!(isChanged && isValid)}
|
disabled={!(isChanged && isValid)}
|
||||||
>
|
>
|
||||||
{i18n('icu:Preferences__EditChatFolderPage__SaveButton')}
|
{i18n('icu:Preferences__EditChatFolderPage__SaveButton')}
|
||||||
</Button>
|
</AxoButton.Root>
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -214,7 +214,7 @@ describe('pnp/username', function (this: Mocha.Suite) {
|
|||||||
|
|
||||||
debug('saving username');
|
debug('saving username');
|
||||||
let state = await phone.expectStorageState('consistency check');
|
let state = await phone.expectStorageState('consistency check');
|
||||||
await profileEditor.locator('.module-Button >> "Save"').click();
|
await profileEditor.getByRole('button', { name: 'Save' }).click();
|
||||||
|
|
||||||
debug('checking the username is saved');
|
debug('checking the username is saved');
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ describe('storage service/notification profiles', function (this: Mocha.Suite) {
|
|||||||
|
|
||||||
const profileName = 'NewProfile';
|
const profileName = 'NewProfile';
|
||||||
debug('Starting Notification Profiles onboarding');
|
debug('Starting Notification Profiles onboarding');
|
||||||
await window.getByTestId('OnboardNotificationProfiles').click();
|
await window.getByRole('button', { name: 'Set up' }).click();
|
||||||
|
|
||||||
debug('Dismiss onboarding dialog');
|
debug('Dismiss onboarding dialog');
|
||||||
await window.getByRole('button', { name: 'Continue' }).click();
|
await window.getByRole('button', { name: 'Continue' }).click();
|
||||||
@@ -207,7 +207,7 @@ describe('storage service/notification profiles', function (this: Mocha.Suite) {
|
|||||||
await window.getByRole('button', { name: 'Notifications' }).click();
|
await window.getByRole('button', { name: 'Notifications' }).click();
|
||||||
|
|
||||||
debug('Open Notification Profiles list page');
|
debug('Open Notification Profiles list page');
|
||||||
await window.getByTestId('OnboardNotificationProfiles').click();
|
await window.getByRole('button', { name: 'Set up' }).click();
|
||||||
|
|
||||||
debug('Dismiss onboarding dialog');
|
debug('Dismiss onboarding dialog');
|
||||||
await window.getByRole('button', { name: 'Continue' }).click();
|
await window.getByRole('button', { name: 'Continue' }).click();
|
||||||
|
|||||||
Reference in New Issue
Block a user