parent
82130a1612
commit
bd98842434
@ -0,0 +1,81 @@
|
||||
import classNames from 'classnames';
|
||||
import React from 'react';
|
||||
import InlineSVG from 'react-inlinesvg';
|
||||
|
||||
import { Text } from 'soapbox/components/ui';
|
||||
import { shortNumberFormat } from 'soapbox/utils/numbers';
|
||||
|
||||
const COLORS = {
|
||||
accent: 'text-accent-300 hover:text-accent-300 dark:hover:text-accent-300',
|
||||
success: 'text-success-600 hover:text-success-600 dark:hover:text-success-600',
|
||||
'': '',
|
||||
};
|
||||
|
||||
const FILL_COLORS = {
|
||||
accent: 'fill-accent-300 hover:fill-accent-300',
|
||||
'': '',
|
||||
};
|
||||
|
||||
type Color = keyof typeof COLORS;
|
||||
type FillColor = keyof typeof FILL_COLORS;
|
||||
|
||||
interface IStatusActionCounter {
|
||||
count: number,
|
||||
}
|
||||
|
||||
/** Action button numerical counter, eg "5" likes */
|
||||
const StatusActionCounter: React.FC<IStatusActionCounter> = ({ count = 0 }): JSX.Element => {
|
||||
return (
|
||||
<Text size='xs' weight='semibold' theme='inherit'>
|
||||
{shortNumberFormat(count)}
|
||||
</Text>
|
||||
);
|
||||
};
|
||||
|
||||
interface IStatusActionButton extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
||||
iconClassName?: string,
|
||||
icon: string,
|
||||
count?: number,
|
||||
active?: boolean,
|
||||
color?: Color,
|
||||
fill?: FillColor,
|
||||
}
|
||||
|
||||
const StatusActionButton = React.forwardRef((props: IStatusActionButton, ref: React.ForwardedRef<HTMLButtonElement>): JSX.Element => {
|
||||
const { icon, className, iconClassName, active, color = '', fill = '', count = 0, ...filteredProps } = props;
|
||||
|
||||
return (
|
||||
<button
|
||||
ref={ref}
|
||||
type='button'
|
||||
className={classNames(
|
||||
'group flex items-center p-1 space-x-0.5 rounded-full',
|
||||
'text-gray-400 hover:text-gray-600 dark:hover:text-white',
|
||||
'bg-white dark:bg-transparent',
|
||||
{
|
||||
[COLORS[color]]: active,
|
||||
},
|
||||
className,
|
||||
)}
|
||||
{...filteredProps}
|
||||
>
|
||||
<InlineSVG
|
||||
src={icon}
|
||||
className={classNames(
|
||||
'p-1 rounded-full box-content',
|
||||
'group-focus:outline-none group-focus:ring-2 group-focus:ring-offset-2 dark:ring-offset-0 group-focus:ring-primary-500',
|
||||
{
|
||||
[FILL_COLORS[fill]]: active,
|
||||
},
|
||||
iconClassName,
|
||||
)}
|
||||
/>
|
||||
|
||||
{(count || null) && (
|
||||
<StatusActionCounter count={count} />
|
||||
)}
|
||||
</button>
|
||||
);
|
||||
});
|
||||
|
||||
export default StatusActionButton;
|
@ -1,77 +0,0 @@
|
||||
import classNames from 'classnames';
|
||||
import React from 'react';
|
||||
|
||||
import { IconButton } from 'soapbox/components/ui';
|
||||
import { shortNumberFormat } from 'soapbox/utils/numbers';
|
||||
|
||||
interface IStatusActionCounter {
|
||||
count: number,
|
||||
className?: string,
|
||||
}
|
||||
|
||||
/** Action button numerical counter, eg "5" likes */
|
||||
const StatusActionCounter: React.FC<IStatusActionCounter> = ({ count = 0, className }): JSX.Element => {
|
||||
return (
|
||||
<span className={classNames('text-xs font-semibold text-gray-400 group-hover:text-gray-600 dark:group-hover:text-white', className)}>
|
||||
{shortNumberFormat(count)}
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
interface IStatusAction {
|
||||
title?: string,
|
||||
}
|
||||
|
||||
/** Status action container element */
|
||||
const StatusAction: React.FC<IStatusAction> = ({ title, children }) => {
|
||||
return (
|
||||
<div title={title} className='group flex items-center space-x-0.5 p-1 rounded-full focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500'>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
interface IStatusActionButton {
|
||||
icon: string,
|
||||
onClick: () => void,
|
||||
count?: number,
|
||||
active?: boolean,
|
||||
title?: string,
|
||||
}
|
||||
|
||||
/** Action button (eg "Like") for a Status */
|
||||
const StatusActionButton: React.FC<IStatusActionButton> = ({ icon, title, active = false, onClick, count = 0 }): JSX.Element => {
|
||||
|
||||
const handleClick: React.EventHandler<React.MouseEvent> = (e) => {
|
||||
onClick();
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
};
|
||||
|
||||
return (
|
||||
<StatusAction title={title}>
|
||||
<IconButton
|
||||
title={title}
|
||||
src={icon}
|
||||
onClick={handleClick}
|
||||
className={classNames('text-gray-400 group-hover:text-gray-600 dark:group-hover:text-white', {
|
||||
'text-accent-300 group-hover:text-accent-300 dark:group-hover:text-accent-300': active,
|
||||
// TODO: repost button
|
||||
// 'text-success-600 hover:text-success-600': active,
|
||||
})}
|
||||
iconClassName={classNames({
|
||||
'fill-accent-300': active,
|
||||
})}
|
||||
/>
|
||||
|
||||
{(count || null) && (
|
||||
<StatusActionCounter
|
||||
className={classNames({ 'text-accent-300 group-hover:text-accent-300': active })}
|
||||
count={count}
|
||||
/>
|
||||
)}
|
||||
</StatusAction>
|
||||
);
|
||||
};
|
||||
|
||||
export { StatusAction, StatusActionButton, StatusActionCounter };
|
Loading…
Reference in new issue