First pass at Hoverable component

next-interactions
Alex Gleason 2022-04-01 13:31:08 -05:00
rodzic 69de2aad55
commit 1742236074
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 7211D1F99744FBB7
3 zmienionych plików z 60 dodań i 12 usunięć

Wyświetl plik

@ -19,7 +19,7 @@ import SoapboxPropTypes from 'soapbox/utils/soapbox_prop_types';
import { openModal } from '../actions/modals';
import { IconButton, Text } from './ui';
import { IconButton, Text, Hoverable } from './ui';
const messages = defineMessages({
@ -547,7 +547,6 @@ class StatusActionBar extends ImmutablePureComponent {
render() {
const { status, intl, allowedEmoji, emojiSelectorFocused, handleEmojiSelectorUnfocus, features, me } = this.props;
const { emojiSelectorVisible } = this.state;
const publicStatus = ['public', 'unlisted'].includes(status.get('visibility'));
@ -664,18 +663,17 @@ class StatusActionBar extends ImmutablePureComponent {
{reblogCount !== 0 && <Text size='xs' theme='muted' role='presentation' onClick={this.handleOpenReblogsModal}>{reblogCount}</Text>}
</div>
<div
<Hoverable
ref={this.setRef}
className='flex relative items-center space-x-0.5 p-1 rounded-full focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500'
onMouseEnter={this.handleLikeButtonHover}
onMouseLeave={this.handleLikeButtonLeave}
component={(
<EmojiSelector
onReact={this.handleReact}
focused={emojiSelectorFocused}
onUnfocus={handleEmojiSelectorUnfocus}
/>
)}
>
<EmojiSelector
onReact={this.handleReact}
visible={features.emojiReacts && emojiSelectorVisible}
focused={emojiSelectorFocused}
onUnfocus={handleEmojiSelectorUnfocus}
/>
<IconButton
className={classNames({
'text-gray-400 hover:text-gray-600 dark:hover:text-white': !meEmojiReact,
@ -698,7 +696,7 @@ class StatusActionBar extends ImmutablePureComponent {
<span className='detailed-status__link'>{emojiReactCount}</span>
)
)}
</div>
</Hoverable>
{shareButton}

Wyświetl plik

@ -0,0 +1,49 @@
import Portal from '@reach/portal';
import React, { useState, useRef } from 'react';
interface IHoverable {
component: React.Component,
}
/** Wrapper to render a given component when hovered */
const Hoverable: React.FC<IHoverable> = ({
component,
children,
}): JSX.Element => {
const [portalActive, setPortalActive] = useState(false);
const ref = useRef<HTMLDivElement>(null);
const handleMouseEnter = () => {
setPortalActive(true);
};
const handleMouseLeave = () => {
setPortalActive(false);
};
const setPortalPosition = (): React.CSSProperties => {
if (!ref.current) return {};
const { top, height, left, width } = ref.current.getBoundingClientRect();
return {
top: top + height,
left,
width,
};
};
return (
<div
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
ref={ref}
>
{children}
{portalActive && <Portal><div className='fixed' style={setPortalPosition()}>{component}</div></Portal>}
</div>
);
};
export default Hoverable;

Wyświetl plik

@ -7,6 +7,7 @@ export { default as EmojiSelector } from './emoji-selector/emoji-selector';
export { default as Form } from './form/form';
export { default as FormActions } from './form-actions/form-actions';
export { default as FormGroup } from './form-group/form-group';
export { default as Hoverable } from './hoverable/hoverable';
export { default as HStack } from './hstack/hstack';
export { default as Icon } from './icon/icon';
export { default as IconButton } from './icon-button/icon-button';