feat: improve 2fa styles based on feedback (#635)
* feat: improve 2fa styles based on feedback * fix: preferences panes and dialogs electron compatibility * fix: no horizontal line when opening two factor activation * feat: improve two factor activation styles * feat: further 2fa style improvements * feat: padding 2fa widgets * feat: add padding between QR code and content * feat: refresh 2fa after passcode confirmation * feat: don't autocomplete passwords for DecoratedInput
This commit is contained in:
@@ -10,6 +10,7 @@ interface Props {
|
||||
text?: string;
|
||||
placeholder?: string;
|
||||
onChange?: (text: string) => void;
|
||||
autocomplete?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -24,30 +25,47 @@ export const DecoratedInput: FunctionalComponent<Props> = ({
|
||||
text,
|
||||
placeholder = '',
|
||||
onChange,
|
||||
autocomplete = false,
|
||||
}) => {
|
||||
const base =
|
||||
'rounded py-1.5 px-3 text-input my-1 h-8 flex flex-row items-center gap-4';
|
||||
const baseClasses =
|
||||
'rounded py-1.5 px-3 text-input my-1 h-8 flex flex-row items-center';
|
||||
const stateClasses = disabled
|
||||
? 'no-border bg-grey-5'
|
||||
: 'border-solid border-1 border-gray-300';
|
||||
const classes = `${base} ${stateClasses} ${className}`;
|
||||
const classes = `${baseClasses} ${stateClasses} ${className}`;
|
||||
|
||||
const inputBaseClasses = 'w-full no-border color-black focus:shadow-none';
|
||||
const inputStateClasses = disabled ? 'overflow-ellipsis' : '';
|
||||
return (
|
||||
<div className={`${classes} focus-within:ring-info`}>
|
||||
{left}
|
||||
{left?.map((leftChild, idx, arr) => (
|
||||
<>
|
||||
{leftChild}
|
||||
{idx < arr.length - 1 && <div className="min-w-3 min-h-1" />}
|
||||
</>
|
||||
))}
|
||||
{left !== undefined && <div className="min-w-7 min-h-1" />}
|
||||
<div className="flex-grow">
|
||||
<input
|
||||
type={type}
|
||||
className="w-full no-border color-black focus:shadow-none"
|
||||
className={`${inputBaseClasses} ${inputStateClasses}`}
|
||||
disabled={disabled}
|
||||
value={text}
|
||||
placeholder={placeholder}
|
||||
onChange={(e) =>
|
||||
onChange && onChange((e.target as HTMLInputElement).value)
|
||||
}
|
||||
data-lpignore={type !== 'password' ? true : false}
|
||||
autocomplete={autocomplete ? 'on' : 'off'}
|
||||
/>
|
||||
</div>
|
||||
{right}
|
||||
{right !== undefined && <div className="min-w-7 min-h-1" />}
|
||||
{right?.map((rightChild, idx, arr) => (
|
||||
<>
|
||||
{rightChild}
|
||||
{idx < arr.length - 1 && <div className="min-w-3 min-h-1" />}
|
||||
</>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -26,6 +26,7 @@ import UserIcon from '../../icons/ic-user.svg';
|
||||
import CopyIcon from '../../icons/ic-copy.svg';
|
||||
import DownloadIcon from '../../icons/ic-download.svg';
|
||||
import InfoIcon from '../../icons/ic-info.svg';
|
||||
import CheckIcon from '../../icons/ic-check.svg';
|
||||
|
||||
import { toDirective } from './utils';
|
||||
import { FunctionalComponent } from 'preact';
|
||||
@@ -58,6 +59,7 @@ const ICONS = {
|
||||
copy: CopyIcon,
|
||||
download: DownloadIcon,
|
||||
info: InfoIcon,
|
||||
check: CheckIcon
|
||||
};
|
||||
|
||||
export type IconType = keyof typeof ICONS;
|
||||
|
||||
@@ -10,6 +10,15 @@ interface Props {
|
||||
className?: string;
|
||||
|
||||
icon: IconType;
|
||||
|
||||
iconClassName?: string;
|
||||
|
||||
/**
|
||||
* Button tooltip
|
||||
*/
|
||||
title: string;
|
||||
|
||||
focusable: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -18,18 +27,20 @@ interface Props {
|
||||
*/
|
||||
export const IconButton: FunctionComponent<Props> = ({
|
||||
onClick,
|
||||
className,
|
||||
className = '',
|
||||
icon,
|
||||
title,
|
||||
focusable,
|
||||
}) => {
|
||||
const click = (e: MouseEvent) => {
|
||||
e.preventDefault();
|
||||
onClick();
|
||||
};
|
||||
const focusableClass = focusable ? '' : 'focus:shadow-none';
|
||||
return (
|
||||
<button
|
||||
className={`no-border cursor-pointer bg-transparent hover:brightness-130 p-0 ${
|
||||
className ?? ''
|
||||
}`}
|
||||
title={title}
|
||||
className={`no-border cursor-pointer bg-transparent flex flex-row items-center hover:brightness-130 p-0 ${focusableClass} ${className}`}
|
||||
onClick={click}
|
||||
>
|
||||
<Icon type={icon} />
|
||||
|
||||
@@ -23,7 +23,7 @@ export const Switch: FunctionalComponent<SwitchProps> = (
|
||||
const className = props.className ?? '';
|
||||
return (
|
||||
<label
|
||||
className={`sn-component flex justify-between items-center cursor-pointer hover:bg-contrast px-3 ${className}`}
|
||||
className={`sn-component flex justify-between items-center cursor-pointer px-3 ${className}`}
|
||||
>
|
||||
{props.children}
|
||||
<CustomCheckboxContainer
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import { FunctionComponent } from 'preact';
|
||||
import { AlertDialog, AlertDialogDescription, AlertDialogLabel } from '@node_modules/@reach/alert-dialog';
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogDescription,
|
||||
AlertDialogLabel,
|
||||
} from '@node_modules/@reach/alert-dialog';
|
||||
import { useRef } from '@node_modules/preact/hooks';
|
||||
import { IconButton } from '@/components/IconButton';
|
||||
|
||||
@@ -28,11 +32,11 @@ export const ModalDialogLabel: FunctionComponent<{
|
||||
closeDialog: () => void;
|
||||
}> = ({ children, closeDialog }) => (
|
||||
<AlertDialogLabel className="">
|
||||
<div className="px-4 pt-4 pb-3 flex flex-row">
|
||||
<div className="flex-grow color-black text-lg font-bold">
|
||||
{children}
|
||||
</div>
|
||||
<div className="px-4 py-4 flex flex-row items-center">
|
||||
<div className="flex-grow color-black text-lg font-bold">{children}</div>
|
||||
<IconButton
|
||||
focusable={true}
|
||||
title="Close"
|
||||
className="color-grey-1 h-5 w-5"
|
||||
icon="close"
|
||||
onClick={() => closeDialog()}
|
||||
@@ -42,16 +46,28 @@ export const ModalDialogLabel: FunctionComponent<{
|
||||
</AlertDialogLabel>
|
||||
);
|
||||
|
||||
export const ModalDialogDescription: FunctionComponent = ({ children }) => (
|
||||
<AlertDialogDescription className="px-4 py-4">
|
||||
{children}
|
||||
</AlertDialogDescription>
|
||||
);
|
||||
export const ModalDialogDescription: FunctionComponent<{ className?: string }> =
|
||||
({ children, className = '' }) => (
|
||||
<AlertDialogDescription
|
||||
className={`px-4 py-4 flex flex-row items-center ${className}`}
|
||||
>
|
||||
{children}
|
||||
</AlertDialogDescription>
|
||||
);
|
||||
|
||||
export const ModalDialogButtons: FunctionComponent = ({ children }) => (
|
||||
<>
|
||||
<hr className="h-1px bg-border no-border m-0" />
|
||||
<div className="px-4 py-4 flex flex-row justify-end gap-3">{children}</div>
|
||||
<div className="px-4 py-4 flex flex-row justify-end items-center">
|
||||
{children != undefined && Array.isArray(children)
|
||||
? children.map((child, idx, arr) => (
|
||||
<>
|
||||
{child}
|
||||
{idx < arr.length - 1 ? <div className="min-w-3" /> : undefined}
|
||||
</>
|
||||
))
|
||||
: children}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user