refactor: button to allow html attributes & refactor class names (#956)

This commit is contained in:
Aman Harwara
2022-03-28 17:41:54 +05:30
committed by GitHub
parent 3ca7102fd0
commit aba1e35a1d
31 changed files with 117 additions and 90 deletions

View File

@@ -130,7 +130,7 @@ export const ConfirmPassword: FunctionComponent<Props> = observer(
label={
isRegistering ? 'Creating account...' : 'Create account & sign in'
}
type="primary"
variant="primary"
onClick={handleConfirmFormSubmit}
disabled={isRegistering}
/>

View File

@@ -122,7 +122,7 @@ export const CreateAccount: FunctionComponent<Props> = observer(
<Button
className="btn-w-full mt-1"
label="Next"
type="primary"
variant="primary"
onClick={handleRegisterFormSubmit}
/>
</form>

View File

@@ -171,7 +171,7 @@ export const SignInPane: FunctionComponent<Props> = observer(
<Button
className="btn-w-full mt-1 mb-3"
label={isSigningIn ? 'Signing in...' : 'Sign in'}
type="primary"
variant="primary"
onClick={handleSignInFormSubmit}
disabled={isSigningIn}
/>

View File

@@ -196,7 +196,7 @@ export const AttachedFilesPopover: FunctionComponent<Props> = observer(
: 'No files found in this account'}
</div>
<Button
type="normal"
variant="normal"
onClick={handleAttachFilesClick}
onBlur={closeOnBlur}
>

View File

@@ -1,60 +1,79 @@
import { JSXInternal } from 'preact/src/jsx';
import TargetedEvent = JSXInternal.TargetedEvent;
import TargetedMouseEvent = JSXInternal.TargetedMouseEvent;
import { ComponentChildren, FunctionComponent, Ref } from 'preact';
import { forwardRef } from 'preact/compat';
const baseClass = `rounded px-4 py-1.75 font-bold text-sm fit-content`;
type ButtonType = 'normal' | 'primary' | 'danger';
type ButtonVariant = 'normal' | 'primary';
const buttonClasses: { [type in ButtonType]: string } = {
normal: `${baseClass} bg-default color-text border-solid border-main border-1 focus:bg-contrast hover:bg-contrast`,
primary: `${baseClass} no-border bg-info color-info-contrast hover:brightness-130 focus:brightness-130`,
danger: `${baseClass} bg-default color-danger border-solid border-main border-1 focus:bg-contrast hover:bg-contrast`,
const getClassName = (
variant: ButtonVariant,
danger: boolean,
disabled: boolean
) => {
const borders =
variant === 'normal' ? 'border-solid border-main border-1' : 'no-border';
const cursor = disabled ? 'cursor-not-allowed' : 'cursor-pointer';
let colors =
variant === 'normal'
? 'bg-default color-text'
: 'bg-info color-info-contrast';
let focusHoverStates =
variant === 'normal'
? 'focus:bg-contrast hover:bg-contrast'
: 'hover:brightness-130 focus:brightness-130';
if (danger) {
colors =
variant === 'normal'
? 'bg-default color-danger'
: 'bg-danger color-info-contrast';
}
if (disabled) {
colors =
variant === 'normal'
? 'bg-default color-grey-2'
: 'bg-grey-2 color-info-contrast';
focusHoverStates =
variant === 'normal'
? 'focus:bg-default hover:bg-default'
: 'focus:brightness-default hover:brightness-default';
}
return `${baseClass} ${colors} ${borders} ${focusHoverStates} ${cursor}`;
};
type ButtonProps = {
type ButtonProps = JSXInternal.HTMLAttributes<HTMLButtonElement> & {
children?: ComponentChildren;
className?: string;
type: ButtonType;
variant?: ButtonVariant;
dangerStyle?: boolean;
label?: string;
onClick: (
event:
| TargetedEvent<HTMLFormElement>
| TargetedMouseEvent<HTMLButtonElement>
) => void;
onBlur?: (event: FocusEvent) => void;
disabled?: boolean;
};
export const Button: FunctionComponent<ButtonProps> = forwardRef(
(
{
type,
variant = 'normal',
label,
className = '',
onBlur,
onClick,
dangerStyle: danger = false,
disabled = false,
children,
...props
}: ButtonProps,
ref: Ref<HTMLButtonElement>
) => {
const buttonClass = buttonClasses[type];
const cursorClass = disabled ? 'cursor-default' : 'cursor-pointer';
return (
<button
className={`${buttonClass} ${cursorClass} ${className}`}
onBlur={onBlur}
onClick={(e) => {
onClick(e);
e.preventDefault();
}}
type="button"
className={`${getClassName(variant, danger, disabled)} ${className}`}
disabled={disabled}
ref={ref}
{...props}
>
{label ?? children}
</button>

View File

@@ -111,7 +111,7 @@ export const FilePreviewModal: FunctionComponent<Props> = ({
<div className="flex items-center">
{objectUrl && (
<Button
type="primary"
variant="primary"
className="mr-4"
onClick={() => {
application
@@ -151,7 +151,7 @@ export const FilePreviewModal: FunctionComponent<Props> = ({
</div>
<div className="flex items-center">
<Button
type="primary"
variant="primary"
className="mr-3"
onClick={() => {
getObjectUrl();
@@ -160,7 +160,7 @@ export const FilePreviewModal: FunctionComponent<Props> = ({
Try again
</Button>
<Button
type="normal"
variant="normal"
onClick={() => {
application.getAppState().files.downloadFile(file);
}}
@@ -176,7 +176,7 @@ export const FilePreviewModal: FunctionComponent<Props> = ({
application.
</div>
<Button
type="primary"
variant="primary"
onClick={() => {
application.getAppState().files.downloadFile(file);
}}

View File

@@ -120,7 +120,7 @@ export const Extensions: FunctionComponent<{
<div className="min-h-2" />
<Button
className="min-w-20"
type="normal"
variant="normal"
label="Install"
onClick={() => submitExtensionUrl(customUrl)}
/>

View File

@@ -102,7 +102,7 @@ export const Listed = observer(({ application }: Props) => {
<Text>Create a free Listed author account to get started.</Text>
<Button
className="mt-3"
type="normal"
variant="normal"
disabled={requestingAccount}
label={
requestingAccount ? 'Creating account...' : 'Create new author'

View File

@@ -39,7 +39,7 @@ export const Authentication: FunctionComponent<{
and enable end-to-end encryption.
</Text>
<Button
type="primary"
variant="primary"
label="Create free account"
onClick={clickRegister}
className="mb-3"

View File

@@ -50,7 +50,7 @@ export const Credentials: FunctionComponent<Props> = observer(
</Text>
<Button
className="min-w-20 mt-3"
type="normal"
variant="normal"
label="Change email"
onClick={() => {
setIsChangeEmailDialogOpen(true);
@@ -64,7 +64,7 @@ export const Credentials: FunctionComponent<Props> = observer(
</Text>
<Button
className="min-w-20 mt-3"
type="normal"
variant="normal"
label="Change password"
onClick={presentPasswordWizard}
/>

View File

@@ -27,14 +27,14 @@ const SignOutView: FunctionComponent<{
<div className="flex flex-row">
<Button
className="mr-3"
type="normal"
variant="normal"
label="Sign out other sessions"
onClick={() => {
appState.accountMenu.setOtherSessionsSignOut(true);
}}
/>
<Button
type="normal"
variant="normal"
label="Manage sessions"
onClick={() => appState.openSessionsModal()}
/>
@@ -48,7 +48,7 @@ const SignOutView: FunctionComponent<{
</Text>
<div className="min-h-3" />
<Button
type="danger"
dangerStyle={true}
label="Sign out workspace"
onClick={() => {
appState.accountMenu.setSigningOut(true);
@@ -76,7 +76,7 @@ const ClearSessionDataView: FunctionComponent<{
</Text>
<div className="min-h-3" />
<Button
type="danger"
dangerStyle={true}
label="Clear workspace"
onClick={() => {
appState.accountMenu.setSigningOut(true);

View File

@@ -55,7 +55,7 @@ export const Sync: FunctionComponent<Props> = observer(
</Text>
<Button
className="min-w-20 mt-3"
type="normal"
variant="normal"
label="Sync now"
disabled={isSyncingInProgress}
onClick={doSynchronization}

View File

@@ -169,7 +169,7 @@ export const ChangeEmail: FunctionalComponent<Props> = ({
<ModalDialogButtons className="px-4.5">
<Button
className="min-w-20"
type="primary"
variant="primary"
label={submitButtonTitle}
onClick={handleSubmit}
/>

View File

@@ -2,8 +2,6 @@ import { FunctionalComponent } from 'preact';
import { Subtitle } from '@/components/Preferences/components';
import { DecoratedInput } from '@/components/DecoratedInput';
import { Button } from '@/components/Button';
import { JSXInternal } from '@node_modules/preact/src/jsx';
import TargetedEvent = JSXInternal.TargetedEvent;
import { useEffect, useState } from 'preact/hooks';
import { WebApplication } from '@/ui_models/application';
import { AppState } from '@/ui_models/app_state';
@@ -40,9 +38,7 @@ export const OfflineSubscription: FunctionalComponent<IProps> = observer(
);
};
const handleSubscriptionCodeSubmit = async (
event: TargetedEvent<HTMLFormElement, Event>
) => {
const handleSubscriptionCodeSubmit = async (event: Event) => {
event.preventDefault();
const result = await application.features.setOfflineFeaturesCode(
@@ -117,7 +113,7 @@ export const OfflineSubscription: FunctionalComponent<IProps> = observer(
)}
{hasUserPreviouslyStoredCode && (
<Button
type="danger"
dangerStyle={true}
label="Remove offline key"
onClick={() => {
handleRemoveClick();
@@ -127,13 +123,9 @@ export const OfflineSubscription: FunctionalComponent<IProps> = observer(
{!hasUserPreviouslyStoredCode && !isSuccessfullyActivated && (
<Button
label={'Submit'}
type="primary"
variant="primary"
disabled={activationCode === ''}
onClick={(event) =>
handleSubscriptionCodeSubmit(
event as TargetedEvent<HTMLFormElement>
)
}
onClick={(event) => handleSubscriptionCodeSubmit(event)}
/>
)}
</form>

View File

@@ -46,7 +46,7 @@ export const NoSubscription: FunctionalComponent<{
{application.hasAccount() && (
<Button
className="min-w-20 mt-3"
type="primary"
variant="primary"
label="Subscribe"
onClick={onPurchaseClick}
/>

View File

@@ -81,7 +81,7 @@ export const SubscriptionInformation = observer(
<StatusText subscriptionState={subscriptionState} />
<Button
className="min-w-20 mt-3 mr-3"
type="normal"
variant="normal"
label="Manage subscription"
onClick={manageSubscription}
/>

View File

@@ -201,7 +201,7 @@ export const DataBackups = observer(({ application, appState }: Props) => {
)}
<Button
type="normal"
variant="normal"
onClick={downloadDataArchive}
label="Download backup"
className="mt-2"
@@ -212,7 +212,7 @@ export const DataBackups = observer(({ application, appState }: Props) => {
<div class="flex flex-row items-center mt-3">
<Button
type="normal"
variant="normal"
label="Import backup"
onClick={handleImportFile}
/>

View File

@@ -222,7 +222,7 @@ export const CloudBackupProvider: FunctionComponent<Props> = ({
{shouldShowEnableButton && (
<div>
<Button
type="normal"
variant="normal"
label="Enable"
className={`px-1 text-xs min-w-40 ${additionalClass}`}
onClick={installIntegration}
@@ -235,13 +235,13 @@ export const CloudBackupProvider: FunctionComponent<Props> = ({
<div className={'flex flex-col items-end'}>
<Button
className={`min-w-40 mb-2 ${additionalClass}`}
type="normal"
variant="normal"
label="Perform Backup"
onClick={performBackupNow}
/>
<Button
className="min-w-40"
type="normal"
variant="normal"
label="Disable"
onClick={disable}
/>

View File

@@ -56,7 +56,7 @@ export const ConfirmCustomExtension: FunctionComponent<{
<div className="flex flex-row">
<Button
className="min-w-20"
type="normal"
variant="normal"
label="Cancel"
onClick={() => callback(false)}
/>
@@ -65,7 +65,7 @@ export const ConfirmCustomExtension: FunctionComponent<{
<Button
className="min-w-20"
type="normal"
variant="normal"
label="Install"
onClick={() => callback(true)}
/>

View File

@@ -104,7 +104,7 @@ export const ExtensionItem: FunctionComponent<ExtensionItemProps> = ({
<div className="flex flex-row">
<Button
className="min-w-20"
type="normal"
variant="normal"
label="Uninstall"
onClick={() => uninstall(extension)}
/>

View File

@@ -224,7 +224,7 @@ export const PasscodeLock = observer(({ application, appState }: Props) => {
<Button
label="Add passcode"
onClick={handleAddPassCode}
type="primary"
variant="primary"
/>
)}
</>
@@ -258,13 +258,13 @@ export const PasscodeLock = observer(({ application, appState }: Props) => {
/>
<div className="min-h-2" />
<Button
type="primary"
variant="primary"
onClick={submitPasscodeForm}
label="Set Passcode"
className="mr-3"
/>
<Button
type="normal"
variant="normal"
onClick={() => setShowPasscodeForm(false)}
label="Cancel"
/>
@@ -276,13 +276,13 @@ export const PasscodeLock = observer(({ application, appState }: Props) => {
<Text>Passcode lock is enabled.</Text>
<div className="flex flex-row mt-3">
<Button
type="normal"
variant="normal"
label="Change Passcode"
onClick={changePasscodePressed}
className="mr-3"
/>
<Button
type="danger"
dangerStyle={true}
label="Remove Passcode"
onClick={removePasscodePressed}
/>

View File

@@ -107,7 +107,7 @@ export const Protections: FunctionalComponent<Props> = ({ application }) => {
{protectionsDisabledUntil && (
<Button
className="mt-3"
type="primary"
variant="primary"
label="End Unprotected Access"
onClick={enableProtections}
/>

View File

@@ -78,13 +78,13 @@ export const SaveSecretKey: FunctionComponent<{
<ModalDialogButtons>
<Button
className="min-w-20"
type="normal"
variant="normal"
label="Back"
onClick={() => act.openScanQRCode()}
/>
<Button
className="min-w-20"
type="primary"
variant="primary"
label="Next"
onClick={() => act.openVerification()}
/>

View File

@@ -63,13 +63,13 @@ export const ScanQRCode: FunctionComponent<{
<ModalDialogButtons>
<Button
className="min-w-20"
type="normal"
variant="normal"
label="Cancel"
onClick={() => act.cancelActivation()}
/>
<Button
className="min-w-20"
type="primary"
variant="primary"
label="Next"
onClick={() => act.openSaveSecretKey()}
/>

View File

@@ -27,7 +27,7 @@ export const TwoFactorSuccess: FunctionComponent<{
<ModalDialogButtons>
<Button
className="min-w-20"
type="primary"
variant="primary"
label="Finish"
onClick={act.finishActivation}
/>

View File

@@ -65,13 +65,13 @@ export const Verification: FunctionComponent<{
)}
<Button
className="min-w-20"
type="normal"
variant="normal"
label="Back"
onClick={act.openSaveSecretKey}
/>
<Button
className="min-w-20"
type="primary"
variant="primary"
label="Next"
onClick={act.enable2FA}
/>

View File

@@ -204,7 +204,7 @@ export const CreateAccount: FunctionComponent<Props> = observer(
</div>
<Button
className="py-2.5 xs:mb-4"
type="primary"
variant="primary"
label={
isCreatingAccount ? 'Creating account...' : 'Create account'
}

View File

@@ -151,7 +151,7 @@ export const SignIn: FunctionComponent<Props> = observer(
</div>
<Button
className={`${isSigningIn ? 'min-w-30' : 'min-w-24'} py-2.5 mb-5`}
type="primary"
variant="primary"
label={isSigningIn ? 'Signing in...' : 'Sign in'}
onClick={handleSignIn}
disabled={isSigningIn}

View File

@@ -46,7 +46,7 @@ export const RevisionContentLocked: FunctionComponent<{
. Learn more about our other plans to upgrade your history capacity.
</div>
<Button
type="primary"
variant="primary"
label="Discover plans"
onClick={() => {
if (window.plansUrl) {

View File

@@ -292,7 +292,7 @@ export const RevisionHistoryModal: FunctionComponent<RevisionHistoryModalProps>
label="Close"
onClick={dismissModal}
ref={closeButtonRef}
type="normal"
variant="normal"
/>
</div>
{selectedRevision && (
@@ -301,7 +301,7 @@ export const RevisionHistoryModal: FunctionComponent<RevisionHistoryModalProps>
<Button
className="py-1.35 mr-2.5"
onClick={deleteSelectedRevision}
type="normal"
variant="normal"
>
{isDeletingRevision ? (
<div className="sk-spinner my-1 w-3 h-3 spinner-info" />
@@ -314,13 +314,13 @@ export const RevisionHistoryModal: FunctionComponent<RevisionHistoryModalProps>
className="py-1.35 mr-2.5"
label="Restore as a copy"
onClick={restoreAsCopy}
type="normal"
variant="normal"
/>
<Button
className="py-1.35"
label="Restore version"
onClick={restore}
type="primary"
variant="primary"
/>
</div>
)}