feat(preferences): 2FA activation dialog with mocked state (#605)

This commit is contained in:
Gorjan Petrovski
2021-07-27 11:32:07 +02:00
committed by GitHub
parent a0dbe6cedd
commit 84bb17ba1d
31 changed files with 845 additions and 278 deletions

View File

@@ -0,0 +1,28 @@
import { FunctionComponent } from 'preact';
const baseClass = `rounded px-4 py-1.75 font-bold text-sm fit-content cursor-pointer`;
const normalClass = `${baseClass} bg-default color-text border-solid border-gray-300 border-1 \
focus:bg-contrast hover:bg-contrast`;
const primaryClass = `${baseClass} no-border bg-info color-info-contrast hover:brightness-130 \
focus:brightness-130`;
export const Button: FunctionComponent<{
className?: string;
type: 'normal' | 'primary';
label: string;
onClick: () => void;
}> = ({ type, label, className = '', onClick }) => {
const buttonClass = type === 'primary' ? primaryClass : normalClass;
return (
<button
className={`${buttonClass} ${className}`}
onClick={(e) => {
onClick();
e.preventDefault();
}}
>
{label}
</button>
);
};

View File

@@ -0,0 +1,38 @@
import { FunctionComponent } from 'preact';
export const CircleProgress: FunctionComponent<{
percent: number;
className?: string;
}> = ({ percent, className = '' }) => {
const size = 16;
const ratioStrokeRadius = 0.25;
const outerRadius = size / 2;
const radius = outerRadius * (1 - ratioStrokeRadius);
const stroke = outerRadius - radius;
const circumference = radius * 2 * Math.PI;
const offset = circumference - (percent / 100) * circumference;
const transition = `transition: 0.35s stroke-dashoffset;`;
const transform = `transform: rotate(-90deg);`;
const transformOrigin = `transform-origin: 50% 50%;`;
const dasharray = `stroke-dasharray: ${circumference} ${circumference};`;
const dashoffset = `stroke-dashoffset: ${offset};`;
const style = `${transition} ${transform} ${transformOrigin} ${dasharray} ${dashoffset}`;
return (
<div className="h-5 w-5 min-w-5 min-h-5">
<svg viewBox={`0 0 ${size} ${size}`}>
<circle
stroke="#086DD6"
stroke-width={stroke}
fill="transparent"
r={radius}
cx="50%"
cy="50%"
style={style}
/>
</svg>
</div>
);
};

View File

@@ -0,0 +1,27 @@
import { FunctionalComponent } from 'preact';
import { useEffect, useState } from 'preact/hooks';
import { CircleProgress } from './CircleProgress';
/**
* Circular progress bar which runs in a specified time interval
* @param time - time interval in ms
*/
export const CircleProgressTime: FunctionalComponent<{ time: number }> = ({
time,
}) => {
const [percent, setPercent] = useState(0);
const interval = time / 100;
useEffect(() => {
const tick = setInterval(() => {
if (percent === 100) {
setPercent(0);
} else {
setPercent(percent + 1);
}
}, interval);
return () => {
clearInterval(tick);
};
});
return <CircleProgress percent={percent} />;
};

View File

@@ -26,12 +26,12 @@ export const DecoratedInput: FunctionalComponent<Props> = ({
const classes = `${base} ${stateClasses} ${className}`;
return (
<div className={classes}>
<div className={`${classes} focus-within:ring-info`}>
{left}
<div className="flex-grow">
<input
type="text"
className="w-full no-border color-black"
className="w-full no-border color-black focus:shadow-none"
disabled={disabled}
value={text}
/>

View File

@@ -25,6 +25,7 @@ import ThemesIcon from '../../icons/ic-themes.svg';
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 { toDirective } from './utils';
import { FunctionalComponent } from 'preact';
@@ -56,6 +57,7 @@ const ICONS = {
user: UserIcon,
copy: CopyIcon,
download: DownloadIcon,
info: InfoIcon,
};
export type IconType = keyof typeof ICONS;

View File

@@ -27,7 +27,7 @@ export const IconButton: FunctionComponent<Props> = ({
};
return (
<button
className={`no-border bg-transparent hover:brightness-130 p-0 ${
className={`no-border cursor-pointer bg-transparent hover:brightness-130 p-0 ${
className ?? ''
}`}
onClick={click}