kopia lustrzana https://gitlab.com/soapbox-pub/soapbox
Improve zap-pay-request
rodzic
cfaaa43e04
commit
07fec136be
|
@ -1,48 +1,64 @@
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
import { themes } from './useZapButtonStyles';
|
import { shortNumberFormat } from 'soapbox/utils/numbers';
|
||||||
|
|
||||||
interface IZapButton {
|
interface IButton {
|
||||||
|
/** Whether this button expands the width of its container. */
|
||||||
|
block?: boolean;
|
||||||
|
/** Elements inside the <button> */
|
||||||
|
children?: React.ReactNode;
|
||||||
/** Extra class names for the button. */
|
/** Extra class names for the button. */
|
||||||
className?: string;
|
className?: string;
|
||||||
|
/** Prevent the button from being clicked. */
|
||||||
|
disabled?: boolean;
|
||||||
|
/** Specifies the icon element as 'svg' or 'img'. */
|
||||||
|
iconElement?: 'svg' | 'img';
|
||||||
/** URL to an SVG icon to render inside the button. */
|
/** URL to an SVG icon to render inside the button. */
|
||||||
icon?: string;
|
icon?: string;
|
||||||
/** Action when the button is clicked. */
|
/** Action when the button is clicked. */
|
||||||
onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void;
|
onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void;
|
||||||
/** Text inside the button. Takes precedence over `children`. */
|
/** Amount of sats. */
|
||||||
text?: React.ReactNode;
|
amount?: number;
|
||||||
/** Styles the button visually with a predefined theme. */
|
/** Makes the button into a navlink, if provided. */
|
||||||
theme?: keyof typeof themes;
|
to?: string;
|
||||||
|
/** Change the button style if it is selected. */
|
||||||
|
selected: boolean;
|
||||||
/** Whether this button should submit a form by default. */
|
/** Whether this button should submit a form by default. */
|
||||||
type?: 'button' | 'submit';
|
type?: 'button' | 'submit';
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Customizable button element with various themes. */
|
/** Customizable button element. */
|
||||||
const ZapButton = React.forwardRef<HTMLButtonElement, IZapButton>((props, ref): JSX.Element => {
|
const ZapButton = React.forwardRef<HTMLButtonElement, IButton>((props, ref): JSX.Element => {
|
||||||
const {
|
const {
|
||||||
|
disabled = false,
|
||||||
icon,
|
icon,
|
||||||
onClick,
|
onClick,
|
||||||
theme = 'secondary',
|
selected,
|
||||||
text,
|
to,
|
||||||
|
amount,
|
||||||
type = 'button',
|
type = 'button',
|
||||||
className,
|
className,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const renderButton = () => (
|
const renderButton = () => (
|
||||||
<button
|
<button
|
||||||
|
disabled={disabled}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
type={type}
|
type={type}
|
||||||
data-testid='button'
|
data-testid='button'
|
||||||
>
|
>
|
||||||
<div className={clsx(className, { 'flex flex-col items-center w-12 !box-border place-content-center border font-medium p-2 rounded-xl focus:outline-none focus:ring-2 focus:ring-offset-2 appearance-none transition-all sm:w-20 sm:p-4': true,
|
<div className={clsx(className, { 'flex flex-col items-center w-14 !box-border place-content-center border font-medium p-2 rounded-xl focus:outline-none focus:ring-2 focus:ring-offset-2 appearance-none transition-all sm:p-4 sm:w-20': true,
|
||||||
[`${themes[theme]}`]: true })}
|
'select-none disabled:opacity-75 disabled:cursor-default': disabled,
|
||||||
|
'bg-primary-500 hover:bg-primary-400 dark:hover:bg-primary-600 border-transparent focus:bg-primary-500 text-gray-100 focus:ring-primary-300': selected,
|
||||||
|
'border border-solid bg-transparent border-gray-400 dark:border-gray-800 hover:border-primary-300 dark:hover:border-primary-700 focus:border-primary-500 text-gray-900 dark:text-gray-100 focus:ring-primary-500': !selected })}
|
||||||
>
|
>
|
||||||
<img className='w-16' src={icon} alt='stack coin' />
|
<img className='w-16' src={icon} alt='stack coin' />
|
||||||
<span className='text-base sm:text-2xl'>
|
<span className='text-base sm:text-2xl'>
|
||||||
<p>
|
<p>
|
||||||
{text}
|
{shortNumberFormat(amount)}
|
||||||
</p>
|
</p>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
|
@ -50,6 +66,14 @@ const ZapButton = React.forwardRef<HTMLButtonElement, IZapButton>((props, ref):
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (to) {
|
||||||
|
return (
|
||||||
|
<Link to={to} tabIndex={-1} className='inline-flex'>
|
||||||
|
{renderButton()}
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return renderButton();
|
return renderButton();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,9 @@ const ZapPayRequestForm = ({ account, status, onClose }: IZapPayRequestForm) =>
|
||||||
const [zapComment, setZapComment] = useState('');
|
const [zapComment, setZapComment] = useState('');
|
||||||
// amount in millisatoshi
|
// amount in millisatoshi
|
||||||
const [zapAmount, setZapAmount] = useState(50);
|
const [zapAmount, setZapAmount] = useState(50);
|
||||||
|
const ZAP_AMOUNTS = [50, 200, 1_000, 3_000, 5_000];
|
||||||
|
const ZAP_ICONS = [coinIcon, coinStack, pileCoin, moneyBag, chestIcon];
|
||||||
|
|
||||||
|
|
||||||
const handleSubmit = async (e?: React.FormEvent<Element>) => {
|
const handleSubmit = async (e?: React.FormEvent<Element>) => {
|
||||||
e?.preventDefault();
|
e?.preventDefault();
|
||||||
|
@ -81,11 +84,7 @@ const ZapPayRequestForm = ({ account, status, onClose }: IZapPayRequestForm) =>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|
||||||
<div className='flex justify-center '>
|
<div className='flex justify-center '>
|
||||||
<ZapButton onClick={() => setZapAmount(50)} className='m-1' theme={zapAmount === 50 ? 'primary' : 'muted'} icon={coinIcon} text='50' />
|
{ZAP_AMOUNTS.map((amount, i) => <ZapButton onClick={() => setZapAmount(amount)} className='m-0.5 sm:m-1' selected={zapAmount === amount} icon={ZAP_ICONS[i]} amount={amount} />)}
|
||||||
<ZapButton onClick={() => setZapAmount(200)} className='m-1' theme={zapAmount === 200 ? 'primary' : 'muted'} icon={coinStack} text='200' />
|
|
||||||
<ZapButton onClick={() => setZapAmount(1_000)} className='m-1' theme={zapAmount === 1_000 ? 'primary' : 'muted'} icon={pileCoin} text='1K' />
|
|
||||||
<ZapButton onClick={() => setZapAmount(3_000)} className='m-1' theme={zapAmount === 3_000 ? 'primary' : 'muted'} icon={moneyBag} text='3K' />
|
|
||||||
<ZapButton onClick={() => setZapAmount(5_000)} className='m-1' theme={zapAmount === 5_000 ? 'primary' : 'muted'} icon={chestIcon} text='5K' />
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Stack space={2}>
|
<Stack space={2}>
|
||||||
|
|
Ładowanie…
Reference in New Issue