Rework Button component to pass its label via children content

This commit is contained in:
ErickSkrauch 2020-07-22 14:20:10 +03:00
parent 993d0cdedb
commit d84497ac28
No known key found for this signature in database
GPG Key ID: 669339FCBB30EE0E
17 changed files with 175 additions and 152 deletions

View File

@ -120,23 +120,12 @@ export class AccountSwitcher extends React.Component<Props> {
))}
{allowAdd ? (
<Link to="/login" onClick={this.props.onAfterAction}>
<Button
color={COLOR_WHITE}
data-testid="add-account"
block
small
className={styles.addAccount}
label={
<Message key="addAccount" defaultMessage="Add account">
{(message) => (
<span>
<div className={styles.addIcon} />
{message}
</span>
)}
</Message>
}
/>
<Button color={COLOR_WHITE} data-testid="add-account" block small className={styles.addAccount}>
<span>
<div className={styles.addIcon} />
<Message key="addAccount" defaultMessage="Add account" />
</span>
</Button>
</Link>
) : null}
</div>

View File

@ -1,15 +1,11 @@
import React from 'react';
import { defineMessages, FormattedMessage as Message } from 'react-intl';
import { FormattedMessage as Message } from 'react-intl';
import { Button } from 'app/components/ui/form';
import { FooterMenu } from 'app/components/footerMenu';
import appName from './appName.intl';
import styles from './appInfo.scss';
const messages = defineMessages({
goToAuth: 'Go to auth',
});
export default class AppInfo extends React.Component<{
name?: string;
description?: string;
@ -51,7 +47,9 @@ export default class AppInfo extends React.Component<{
)}
</div>
<div className={styles.goToAuth}>
<Button onClick={onGoToAuth} label={messages.goToAuth} />
<Button onClick={onGoToAuth}>
<Message key="goToAuth" defaultMessage="Go to auth" />
</Button>
</div>
<div className={styles.footer}>

View File

@ -1,5 +1,5 @@
import React, { MouseEventHandler } from 'react';
import { defineMessages, FormattedMessage as Message } from 'react-intl';
import { FormattedMessage as Message } from 'react-intl';
import { Helmet } from 'react-helmet-async';
import { connect } from 'app/functions';
@ -8,10 +8,6 @@ import copy from 'app/services/copy';
import styles from './finish.scss';
const messages = defineMessages({
copy: 'Copy',
});
interface Props {
appName: string;
code?: string;
@ -58,7 +54,9 @@ class Finish extends React.Component<Props> {
<div className={styles.codeContainer}>
<div className={styles.code}>{code}</div>
</div>
<Button color="green" small label={messages.copy} onClick={this.onCopyClick} />
<Button color="green" small onClick={this.onCopyClick}>
<Message key="copy" defaultMessage="Copy" />
</Button>
</div>
) : (
<div className={styles.description}>

View File

@ -120,7 +120,9 @@ const ContactFormPopup: ComponentType<Props> = ({ initEmail = '', onSubmit, onCl
/>
</div>
<Button label={<Message key="send" defaultMessage="Send" />} block type="submit" disabled={isLoading} />
<Button block type="submit" disabled={isLoading}>
<Message key="send" defaultMessage="Send" />
</Button>
</Form>
</Popup>
);

View File

@ -30,7 +30,9 @@ const SuccessContactFormPopup: ComponentType<Props> = ({ email, onClose }) => (
</div>
<div className={styles.footer}>
<Button label={<Message key="close" defaultMessage="Close" />} block onClick={onClose} />
<Button block onClick={onClose}>
<Message key="close" defaultMessage="Close" />
</Button>
</div>
</Popup>
);

View File

@ -15,7 +15,6 @@ import ApplicationsList from './list';
const labels = defineMessages({
addNew: 'Add new',
authorization: 'Authorization',
});
type Props = {
@ -123,10 +122,11 @@ function Loader({ noApps }: { noApps: boolean }) {
<LinkButton
to="/dev/applications/new"
data-e2e="newApp"
label={labels.addNew}
color={COLOR_GREEN}
className={styles.emptyStateActionButton}
/>
>
<Message {...labels.addNew} />
</LinkButton>
</div>
</div>
);
@ -145,12 +145,9 @@ function Guest() {
</div>
</div>
<LinkButton
to="/login"
label={labels.authorization}
color={COLOR_BLUE}
className={styles.emptyStateActionButton}
/>
<LinkButton to="/login" color={COLOR_BLUE} className={styles.emptyStateActionButton}>
<Message key="authorization" defaultMessage="Authorization" />
</LinkButton>
</div>
);
}

View File

@ -20,10 +20,7 @@ const messages = defineMessages({
minecraftServer: 'Minecraft server',
creatingApplication: 'Creating an application',
createApplication: 'Create application',
updatingApplication: 'Updating an application',
updateApplication: 'Update application',
});
type TypeToForm = Record<
@ -115,12 +112,13 @@ export default class ApplicationForm extends React.Component<{
</div>
{!!FormComponent && (
<Button
color={COLOR_GREEN}
block
label={isUpdate ? messages.updateApplication : messages.createApplication}
type="submit"
/>
<Button color={COLOR_GREEN} block type="submit">
{isUpdate ? (
<Message key="updateApplication" defaultMessage="Update application" />
) : (
<Message key="createApplication" defaultMessage="Create application" />
)}
</Button>
)}
</div>
</Form>

View File

@ -16,15 +16,15 @@ const ACTION_DELETE = 'delete';
const actionButtons = [
{
type: ACTION_REVOKE_TOKENS,
label: messages.revokeAllTokens,
label: <Message {...messages.revokeAllTokens} />,
},
{
type: ACTION_RESET_SECRET,
label: messages.resetClientSecret,
label: <Message {...messages.resetClientSecret} />,
},
{
type: ACTION_DELETE,
label: messages.delete,
label: <Message {...messages.delete} />,
},
];
@ -122,13 +122,14 @@ export default class ApplicationItem extends React.Component<
{actionButtons.map(({ type, label }) => (
<Button
key={type}
label={label}
color={COLOR_BLACK}
className={styles.appActionButton}
disabled={!!selectedAction && selectedAction !== type}
onClick={this.onActionButtonClick(type)}
small
/>
>
{label}
</Button>
))}
</div>
@ -160,12 +161,13 @@ export default class ApplicationItem extends React.Component<
</div>
<div className={styles.appActionsButtons}>
<Button
label={messages.cancel}
color={COLOR_BLACK}
className={styles.appActionButton}
onClick={this.onActionButtonClick(null)}
small
/>
>
<Message {...messages.cancel} />
</Button>
<div className={styles.continueActionButtonWrapper}>
{isActionPerforming ? (
<div className={styles.performingAction}>
@ -193,12 +195,13 @@ export default class ApplicationItem extends React.Component<
</div>
<div className={styles.appActionsButtons}>
<Button
label={messages.cancel}
color={COLOR_BLACK}
className={styles.appActionButton}
onClick={this.onActionButtonClick(null)}
small
/>
>
<Message {...messages.cancel} />
</Button>
<div className={styles.continueActionButtonWrapper}>
{isActionPerforming ? (
<div className={styles.performingAction}>
@ -206,13 +209,14 @@ export default class ApplicationItem extends React.Component<
</div>
) : (
<Button
label={messages.delete}
color={COLOR_RED}
className={styles.appActionButton}
onClick={this.onSubmitDelete}
data-testid="delete-app"
small
/>
>
<Message {...messages.delete} />
</Button>
)}
</div>
</div>

View File

@ -49,10 +49,11 @@ export default class ApplicationsList extends React.Component<Props, State> {
<LinkButton
to="/dev/applications/new"
data-e2e="newApp"
label={messages.addNew}
color={COLOR_GREEN}
className={styles.appsListAddNewAppBtn}
/>
>
<Message {...messages.addNew} />
</LinkButton>
</div>
<div className={styles.appsListContainer}>
{applications.map((app) => (

View File

@ -1,6 +1,7 @@
import React, { ReactNode } from 'react';
import { defineMessages, FormattedMessage as Message } from 'react-intl';
import { Helmet } from 'react-helmet-async';
import { SlideMotion } from 'app/components/ui/motion';
import { ScrollIntoView } from 'app/components/ui/scroll';
import { Input, Button, Form, FormModel, FormError } from 'app/components/ui/form';
@ -39,8 +40,6 @@ interface FormStepParams {
}
const labels = defineMessages({
changeEmailButton: 'Change Email',
sendEmailButton: 'Send Email',
codePlaceholder: 'Paste the code here',
newEmailPlaceholder: 'Enter new Email',
});
@ -107,12 +106,13 @@ export default class ChangeEmail extends React.Component<Props, State> {
{this.renderStepForms()}
<Button
color="violet"
type="submit"
block
label={this.isLastStep() ? labels.changeEmailButton : labels.sendEmailButton}
/>
<Button color="violet" type="submit" block>
{this.isLastStep() ? (
<Message key="changeEmailButton" defaultMessage="Change Email" />
) : (
<Message key="sendEmailButton" defaultMessage="Send Email" />
)}
</Button>
</div>
<div className={helpLinks.helpLinks}>

View File

@ -7,7 +7,6 @@ import { BackButton } from '../ProfileForm';
import styles from '../profileForm.scss';
const labels = defineMessages({
changePasswordButton: 'Change password',
newPasswordLabel: 'New password:',
repeatNewPasswordLabel: 'Repeat the password:',
logoutOnAllDevices: 'Logout on all devices',
@ -99,7 +98,9 @@ export default class ChangePassword extends React.Component<Props> {
</div>
</div>
<Button color="green" block label={labels.changePasswordButton} type="submit" />
<Button color="green" block type="submit">
<Message key="changePasswordButton" defaultMessage="Change password" />
</Button>
</div>
</div>
</Form>

View File

@ -1,15 +1,11 @@
import React from 'react';
import { defineMessages, FormattedMessage as Message } from 'react-intl';
import { FormattedMessage as Message } from 'react-intl';
import { Helmet } from 'react-helmet-async';
import { Input, Button, Form, FormModel } from 'app/components/ui/form';
import { BackButton } from 'app/components/profile/ProfileForm';
import styles from '../profileForm.scss';
const labels = defineMessages({
changeUsernameButton: 'Change nickname',
});
interface Props {
username: string;
form: FormModel;
@ -72,7 +68,9 @@ export default class ChangeUsername extends React.Component<Props> {
</div>
</div>
<Button color="green" block label={labels.changeUsernameButton} type="submit" />
<Button color="green" block type="submit">
<Message key="changeUsernameButton" defaultMessage="Change nickname" />
</Button>
</div>
</div>
</Form>

View File

@ -7,7 +7,6 @@ import mfaStyles from './mfa.scss';
const messages = defineMessages({
codePlaceholder: 'Enter the code here',
disable: 'Disable',
});
export default class MfaDisableForm extends React.Component<{
@ -49,7 +48,9 @@ export default class MfaDisableForm extends React.Component<{
</div>
</div>
<Button type="submit" color="green" block label={messages.disable} />
<Button type="submit" color="green" block>
<Message key="disable" defaultMessage="Disable" />
</Button>
</Form>
);
}

View File

@ -1,4 +1,6 @@
import React from 'react';
import { FormattedMessage as Message, defineMessages } from 'react-intl';
import { Button, FormModel } from 'app/components/ui/form';
import styles from 'app/components/profile/profileForm.scss';
import Stepper from 'app/components/ui/stepper';
@ -7,7 +9,6 @@ import { ScrollIntoView } from 'app/components/ui/scroll';
import logger from 'app/services/logger';
import { getSecret, enable as enableMFA } from 'app/services/api/mfa';
import { Form } from 'app/components/ui/form';
import { defineMessages } from 'react-intl';
import Context from '../Context';
import Instructions from './instructions';
@ -105,7 +106,9 @@ export default class MfaEnable extends React.PureComponent<Props, State> {
{this.renderStepForms()}
<Button color="green" onClick={buttonAction} loading={isLoading} block label={buttonLabel} />
<Button color="green" onClick={buttonAction} loading={isLoading} block>
<Message {...buttonLabel} />
</Button>
</div>
</div>
);

View File

@ -37,7 +37,9 @@ const PasswordRequestForm: ComponentType<Props> = ({ form, onSubmit }) => (
/>
</div>
<Button type="submit" color="green" label={<Message key="continue" defaultMessage="Continue" />} block />
<Button type="submit" color="green" block>
<Message key="continue" defaultMessage="Continue" />
</Button>
</Form>
</Popup>
);

View File

@ -6,38 +6,77 @@ import Button from './Button';
storiesOf('UI/Form', module).add('Button', () => (
<>
<div>
<Button label="Green Button" /> <Button label="Blue Button" color="blue" />{' '}
<Button label="DarkBlue Button" color="darkBlue" /> <Button label="Violet Button" color="violet" />{' '}
<Button label="LightViolet Button" color="lightViolet" /> <Button label="Orange Button" color="orange" />{' '}
<Button label="Red Button" color="red" /> <Button label="Black Button" color="black" />{' '}
<Button label="White Button" color="white" />
<Button>Green Button</Button> <Button color="blue">Blue Button</Button>{' '}
<Button color="darkBlue">DarkBlue Button</Button> <Button color="violet">Violet Button</Button>{' '}
<Button color="lightViolet">LightViolet Button</Button> <Button color="orange">Orange Button</Button>{' '}
<Button color="red">Red Button</Button> <Button color="black">Black Button</Button>{' '}
<Button color="white">White Button</Button>
</div>
<div>
<h2>Disabled buttons</h2>
<Button disabled label="Green Button" /> <Button disabled label="Blue Button" color="blue" />{' '}
<Button disabled label="DarkBlue Button" color="darkBlue" />{' '}
<Button disabled label="Violet Button" color="violet" />{' '}
<Button disabled label="LightViolet Button" color="lightViolet" />{' '}
<Button disabled label="Orange Button" color="orange" /> <Button disabled label="Red Button" color="red" />{' '}
<Button disabled label="Black Button" color="black" />{' '}
<Button disabled label="White Button" color="white" />
<Button disabled>Green Button</Button>
<Button disabled color="blue">
Blue Button
</Button>{' '}
<Button disabled color="darkBlue">
DarkBlue Button
</Button>{' '}
<Button disabled color="violet">
Violet Button
</Button>{' '}
<Button disabled color="lightViolet">
LightViolet Button
</Button>{' '}
<Button disabled color="orange">
Orange Button
</Button>{' '}
<Button disabled color="red">
Red Button
</Button>{' '}
<Button disabled color="black">
Black Button
</Button>{' '}
<Button disabled color="white">
White Button
</Button>
</div>
<div>
<h2>Button sizes</h2>
<Button label="Default button" /> <Button label="Small button" small /> <br />
<Button>Default button</Button> <Button small>Small button</Button> <br />
<br />
<Button label="Block button" block />
<Button block>Block button</Button>
<br />
<Button label="Small block button" small block />
<Button small block>
Small block button
</Button>
</div>
<div>
<h2>Loading button</h2>
<Button loading label="Green Button" /> <Button loading label="Blue Button" color="blue" />{' '}
<Button loading label="DarkBlue Button" color="darkBlue" />{' '}
<Button loading label="Violet Button" color="violet" />{' '}
<Button loading label="LightViolet Button" color="lightViolet" />{' '}
<Button loading label="Orange Button" color="orange" /> <Button loading label="Red Button" color="red" />{' '}
<Button loading label="Black Button" color="black" /> <Button loading label="White Button" color="white" />
<Button loading>Green Button</Button>{' '}
<Button loading color="blue">
Blue Button
</Button>{' '}
<Button loading color="darkBlue">
DarkBlue Button
</Button>{' '}
<Button loading color="violet">
Violet Button
</Button>{' '}
<Button loading color="lightViolet">
LightViolet Button
</Button>{' '}
<Button loading color="orange">
Orange Button
</Button>{' '}
<Button loading color="red">
Red Button
</Button>{' '}
<Button loading color="black">
Black Button
</Button>{' '}
<Button loading color="white">
White Button
</Button>
</div>
</>
));

View File

@ -1,55 +1,45 @@
import React from 'react';
import React, { ComponentType } from 'react';
import clsx from 'clsx';
import { COLOR_GREEN } from 'app/components/ui';
import { MessageDescriptor } from 'react-intl';
import { Color } from 'app/components/ui';
import buttons from '../buttons.scss';
import FormComponent from './FormComponent';
export default class Button extends FormComponent<
{
// TODO: drop MessageDescriptor support. It should be React.ReactNode only
label: string | MessageDescriptor | React.ReactElement;
block?: boolean;
small?: boolean;
loading?: boolean;
className?: string;
color?: Color;
disabled?: boolean;
component?: string | React.ComponentType<any>;
} & React.ButtonHTMLAttributes<HTMLButtonElement>
> {
render() {
const {
color = COLOR_GREEN,
block,
small,
disabled,
className,
loading,
label,
component: ComponentProp = 'button',
...restProps
} = this.props;
return (
<ComponentProp
className={clsx(
buttons[color],
{
[buttons.loading]: loading,
[buttons.block]: block,
[buttons.smallButton]: small,
[buttons.disabled]: disabled,
},
className,
)}
disabled={disabled}
{...restProps}
>
{typeof label === 'object' && React.isValidElement(label) ? label : this.formatMessage(label)}
</ComponentProp>
);
}
interface Props extends React.ButtonHTMLAttributes<HTMLButtonElement> {
block?: boolean;
small?: boolean;
loading?: boolean;
className?: string;
color?: Color;
disabled?: boolean;
component?: string | React.ComponentType<any>;
}
const Button: ComponentType<Props> = ({
color = COLOR_GREEN,
block,
small,
disabled,
className,
loading,
component: ComponentProp = 'button',
...restProps
}) => (
<ComponentProp
className={clsx(
buttons[color],
{
[buttons.loading]: loading,
[buttons.block]: block,
[buttons.smallButton]: small,
[buttons.disabled]: disabled,
},
className,
)}
disabled={disabled}
{...restProps}
/>
);
export default Button;