remove channelTooltip component
This commit is contained in:
parent
fdd755d83b
commit
aa60d99fcd
7 changed files with 6 additions and 377 deletions
|
@ -1,32 +0,0 @@
|
||||||
import { connect } from 'react-redux';
|
|
||||||
|
|
||||||
import {
|
|
||||||
doResolveUri,
|
|
||||||
makeSelectTitleForUri,
|
|
||||||
makeSelectThumbnailForUri,
|
|
||||||
makeSelectClaimForUri,
|
|
||||||
makeSelectIsUriResolving,
|
|
||||||
makeSelectMetadataItemForUri,
|
|
||||||
} from 'lbry-redux';
|
|
||||||
|
|
||||||
import ChannelTooltip from './view';
|
|
||||||
|
|
||||||
const select = (state, props) => {
|
|
||||||
return {
|
|
||||||
uri: props.uri,
|
|
||||||
claim: makeSelectClaimForUri(props.uri)(state),
|
|
||||||
title: makeSelectTitleForUri(props.uri)(state),
|
|
||||||
thumbnail: makeSelectThumbnailForUri(props.uri)(state),
|
|
||||||
description: makeSelectMetadataItemForUri(props.uri, 'description')(state),
|
|
||||||
isResolvingUri: makeSelectIsUriResolving(props.uri)(state),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const perform = dispatch => ({
|
|
||||||
resolveUri: uri => dispatch(doResolveUri(uri)),
|
|
||||||
});
|
|
||||||
|
|
||||||
export default connect(
|
|
||||||
select,
|
|
||||||
perform
|
|
||||||
)(ChannelTooltip);
|
|
|
@ -1,41 +0,0 @@
|
||||||
// Defualt function used by reach-ui tooltip componment,
|
|
||||||
// slightly modify to register current direction:
|
|
||||||
// https://github.com/reach/reach-ui/blob/f0c8c5c467be46c202148ee69b1ba789b57d5e60/packages/tooltip/src/index.js#L478
|
|
||||||
|
|
||||||
// feels awkward when it's perfectly aligned w/ the trigger
|
|
||||||
const OFFSET = 8;
|
|
||||||
|
|
||||||
const positionDefault = (triggerRect, tooltipRect, currentDirection, setDirection) => {
|
|
||||||
const styles = {
|
|
||||||
left: `${triggerRect.left + window.pageXOffset}px`,
|
|
||||||
top: `${triggerRect.top + triggerRect.height + window.pageYOffset}px`,
|
|
||||||
};
|
|
||||||
|
|
||||||
const collisions = {
|
|
||||||
top: triggerRect.top - tooltipRect.height < 0,
|
|
||||||
right: window.innerWidth < triggerRect.left + tooltipRect.width,
|
|
||||||
bottom: window.innerHeight < triggerRect.bottom + tooltipRect.height + OFFSET,
|
|
||||||
left: triggerRect.left - tooltipRect.width < 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
const directionRight = collisions.right && !collisions.left;
|
|
||||||
const directionUp = collisions.bottom && !collisions.top;
|
|
||||||
|
|
||||||
const direction = directionUp ? 'top' : 'bottom';
|
|
||||||
|
|
||||||
if (direction !== currentDirection) {
|
|
||||||
setDirection(direction);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
...styles,
|
|
||||||
left: directionRight
|
|
||||||
? `${triggerRect.right - tooltipRect.width + window.pageXOffset}px`
|
|
||||||
: `${triggerRect.left + window.pageXOffset}px`,
|
|
||||||
top: directionUp
|
|
||||||
? `${triggerRect.top - OFFSET - tooltipRect.height + window.pageYOffset}px`
|
|
||||||
: `${triggerRect.top + OFFSET + triggerRect.height + window.pageYOffset}px`,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export default positionDefault;
|
|
|
@ -1,173 +0,0 @@
|
||||||
// @flow
|
|
||||||
import * as React from 'react';
|
|
||||||
import classnames from 'classnames';
|
|
||||||
import ChannelThumbnail from 'component/channelThumbnail';
|
|
||||||
import TruncatedText from 'component/common/truncated-text';
|
|
||||||
|
|
||||||
// Tooltip components
|
|
||||||
import Portal from '@reach/portal';
|
|
||||||
import getPostion from './position.js';
|
|
||||||
import { useTooltip, TooltipPopup } from '@reach/tooltip';
|
|
||||||
|
|
||||||
// Tooltip base styles
|
|
||||||
import '@reach/tooltip/styles.css';
|
|
||||||
|
|
||||||
const ARROW_SIZE = 10;
|
|
||||||
|
|
||||||
type ChannelTooltipProps = {
|
|
||||||
uri: string,
|
|
||||||
claim: ?Claim,
|
|
||||||
title: ?string,
|
|
||||||
children: any,
|
|
||||||
resolveUri: string => void,
|
|
||||||
description: ?string,
|
|
||||||
isResolvingUri: boolean,
|
|
||||||
};
|
|
||||||
|
|
||||||
type LabelProps = {
|
|
||||||
uri: string,
|
|
||||||
title: ?string,
|
|
||||||
claimId: string,
|
|
||||||
channelName: string,
|
|
||||||
description: ?string,
|
|
||||||
};
|
|
||||||
|
|
||||||
type TriangleTooltipProps = {
|
|
||||||
label: any,
|
|
||||||
children: any,
|
|
||||||
ariaLabel: ?string,
|
|
||||||
};
|
|
||||||
|
|
||||||
function TriangleTooltip(props: TriangleTooltipProps) {
|
|
||||||
const { label, children, ariaLabel } = props;
|
|
||||||
|
|
||||||
// get the props from useTooltip
|
|
||||||
const [trigger, tooltip] = useTooltip();
|
|
||||||
|
|
||||||
// Tooltip direction
|
|
||||||
const [direction, setDirection] = React.useState('bottom');
|
|
||||||
|
|
||||||
// destructure off what we need to position the triangle
|
|
||||||
const { isVisible, triggerRect } = tooltip;
|
|
||||||
|
|
||||||
let arrowTop;
|
|
||||||
|
|
||||||
// Top
|
|
||||||
if (direction === 'top') {
|
|
||||||
arrowTop = triggerRect && triggerRect.bottom - (triggerRect.height + ARROW_SIZE) + window.scrollY;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bottom
|
|
||||||
if (direction === 'bottom') {
|
|
||||||
arrowTop = triggerRect && triggerRect.bottom + window.scrollY;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<React.Fragment>
|
|
||||||
{React.cloneElement(children, trigger)}
|
|
||||||
{isVisible && (
|
|
||||||
// The Triangle. We position it relative to the trigger, not the popup
|
|
||||||
// so that collisions don't have a triangle pointing off to nowhere.
|
|
||||||
// Using a Portal may seem a little extreme, but we can keep the
|
|
||||||
// positioning logic simpler here instead of needing to consider
|
|
||||||
// the popup's position relative to the trigger and collisions
|
|
||||||
<Portal>
|
|
||||||
<span
|
|
||||||
className={classnames('channel-tooltip__arrow', `channel-tooltip__arrow--${direction}`)}
|
|
||||||
style={{
|
|
||||||
position: 'absolute',
|
|
||||||
top: arrowTop,
|
|
||||||
left: triggerRect && triggerRect.left - ARROW_SIZE + triggerRect.width / 2,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Portal>
|
|
||||||
)}
|
|
||||||
<TooltipPopup
|
|
||||||
{...tooltip}
|
|
||||||
label={label}
|
|
||||||
ariaLabel={ariaLabel}
|
|
||||||
className={'channel-tooltip'}
|
|
||||||
position={(triggerRect, tooltipRect) => getPostion(triggerRect, tooltipRect, direction, setDirection)}
|
|
||||||
/>
|
|
||||||
</React.Fragment>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const ChannelTooltipLabel = (props: LabelProps) => {
|
|
||||||
const { uri, title, claimId, description, channelName } = props;
|
|
||||||
const channelUrl = `${channelName}#${claimId}`;
|
|
||||||
const formatedName = channelName.replace('@', '');
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={'channel-tooltip__content'}>
|
|
||||||
<div className={'channel-tooltip__profile'}>
|
|
||||||
<ChannelThumbnail uri={uri} />
|
|
||||||
<div className={'channel-tooltip__info'}>
|
|
||||||
<h2 className={'channel-tooltip__title'}>
|
|
||||||
<TruncatedText lines={1}>{title || formatedName}</TruncatedText>
|
|
||||||
</h2>
|
|
||||||
<h3 className={'channel-tooltip__url'}>
|
|
||||||
<TruncatedText lines={1}>{channelUrl}</TruncatedText>
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{description && (
|
|
||||||
<div className={'channel-tooltip__description'}>
|
|
||||||
<div>
|
|
||||||
<TruncatedText lines={2}>{description}</TruncatedText>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
<div className={'channel-tooltip__stats'} />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
class ChannelTooltip extends React.Component<ChannelTooltipProps> {
|
|
||||||
componentDidMount() {
|
|
||||||
this.resolve(this.props);
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidUpdate() {
|
|
||||||
this.resolve(this.props);
|
|
||||||
}
|
|
||||||
|
|
||||||
resolve = (props: ChannelTooltipProps) => {
|
|
||||||
const { isResolvingUri, resolveUri, claim, uri } = props;
|
|
||||||
|
|
||||||
if (!isResolvingUri && claim === undefined && uri) {
|
|
||||||
resolveUri(uri);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { uri, claim, children, title, description } = this.props;
|
|
||||||
|
|
||||||
if (!uri || !claim) {
|
|
||||||
return children;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { claim_id: claimId, name: channelName } = claim;
|
|
||||||
|
|
||||||
// Generate aria-label
|
|
||||||
const ariaLabel = title || channelName;
|
|
||||||
|
|
||||||
const label = (
|
|
||||||
<ChannelTooltipLabel
|
|
||||||
uri={uri}
|
|
||||||
title={title}
|
|
||||||
claimId={claimId}
|
|
||||||
channelName={channelName}
|
|
||||||
description={description}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<TriangleTooltip label={label} ariaLabel={ariaLabel}>
|
|
||||||
{children}
|
|
||||||
</TriangleTooltip>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default ChannelTooltip;
|
|
|
@ -2,12 +2,9 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import PreviewLink from 'component/previewLink';
|
import PreviewLink from 'component/previewLink';
|
||||||
import ChannelTooltip from 'component/channelTooltip';
|
|
||||||
import { parseURI } from 'lbry-redux';
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
uri: string,
|
uri: string,
|
||||||
link?: boolean,
|
|
||||||
title: ?string,
|
title: ?string,
|
||||||
claim: StreamClaim,
|
claim: StreamClaim,
|
||||||
children: React.Node,
|
children: React.Node,
|
||||||
|
@ -67,7 +64,7 @@ class ClaimLink extends React.Component<Props> {
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { uri, link, claim, title, className, autoEmbed, children, isResolvingUri } = this.props;
|
const { uri, claim, title, className, autoEmbed, children, isResolvingUri } = this.props;
|
||||||
const isUnresolved = (!isResolvingUri && !claim) || !claim;
|
const isUnresolved = (!isResolvingUri && !claim) || !claim;
|
||||||
const isBlacklisted = this.isClaimBlackListed();
|
const isBlacklisted = this.isClaimBlackListed();
|
||||||
|
|
||||||
|
@ -76,29 +73,11 @@ class ClaimLink extends React.Component<Props> {
|
||||||
}
|
}
|
||||||
|
|
||||||
const { name: claimName } = claim;
|
const { name: claimName } = claim;
|
||||||
const { isChannel, path } = parseURI(uri);
|
|
||||||
const isChannelClaim = isChannel && !path;
|
|
||||||
const showPreview = autoEmbed === true && !isUnresolved;
|
const showPreview = autoEmbed === true && !isUnresolved;
|
||||||
|
|
||||||
const innerContent = (
|
|
||||||
<Button
|
|
||||||
label={children}
|
|
||||||
title={!isChannelClaim ? title || claimName : undefined}
|
|
||||||
button={link ? 'link' : undefined}
|
|
||||||
className={className}
|
|
||||||
navigate={uri}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
const wrappedLink = (
|
|
||||||
<ChannelTooltip uri={uri}>
|
|
||||||
<span>{innerContent}</span>
|
|
||||||
</ChannelTooltip>
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
{isChannelClaim ? wrappedLink : innerContent}
|
<Button label={children} title={title || claimName} button={'link'} navigate={uri} className={className} />
|
||||||
{showPreview && <PreviewLink uri={uri} />}
|
{showPreview && <PreviewLink uri={uri} />}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
|
|
|
@ -44,7 +44,7 @@ class ExternalLink extends React.PureComponent<Props> {
|
||||||
// Return local link if protocol is lbry uri
|
// Return local link if protocol is lbry uri
|
||||||
if (protocol && protocol[0] === 'lbry:' && isURIValid(href)) {
|
if (protocol && protocol[0] === 'lbry:' && isURIValid(href)) {
|
||||||
element = (
|
element = (
|
||||||
<ClaimLink uri={href} autoEmbed={embed} link>
|
<ClaimLink uri={href} autoEmbed={embed}>
|
||||||
{children}
|
{children}
|
||||||
</ClaimLink>
|
</ClaimLink>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// @flow
|
// @flow
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ClaimLink from 'component/claimLink';
|
import Button from 'component/button';
|
||||||
import { buildURI } from 'lbry-redux';
|
import { buildURI } from 'lbry-redux';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
@ -60,9 +60,9 @@ class UriIndicator extends React.PureComponent<Props> {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ClaimLink uri={channelLink} className={'button--uri-indicator'}>
|
<Button className="button--uri-indicator" navigate={channelLink}>
|
||||||
{inner}
|
{inner}
|
||||||
</ClaimLink>
|
</Button>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -150,107 +150,3 @@
|
||||||
margin-left: -5px;
|
margin-left: -5px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Channel-tooltip
|
|
||||||
|
|
||||||
.channel-tooltip {
|
|
||||||
color: $lbry-black;
|
|
||||||
background-color: $lbry-white;
|
|
||||||
width: 20rem;
|
|
||||||
border: none;
|
|
||||||
border-radius: var(--card-radius);
|
|
||||||
z-index: 2;
|
|
||||||
|
|
||||||
html[data-mode='dark'] & {
|
|
||||||
color: mix($lbry-white, $lbry-gray-3, 50%);
|
|
||||||
background-color: mix($lbry-black, $lbry-gray-3, 90%);
|
|
||||||
}
|
|
||||||
|
|
||||||
box-shadow: 0px 2px 10px -2px black;
|
|
||||||
}
|
|
||||||
|
|
||||||
.channel-tooltip__content {
|
|
||||||
width: 100%;
|
|
||||||
margin: 0;
|
|
||||||
display: block;
|
|
||||||
word-break: break-all;
|
|
||||||
word-wrap: break-word;
|
|
||||||
white-space: pre-wrap;
|
|
||||||
|
|
||||||
.channel-thumbnail {
|
|
||||||
left: 0;
|
|
||||||
position: relative;
|
|
||||||
flex-shrink: 0;
|
|
||||||
text-align: center;
|
|
||||||
display: flex;
|
|
||||||
max-width: 5rem;
|
|
||||||
max-height: 5rem;
|
|
||||||
margin-right: 1rem;
|
|
||||||
box-shadow: 0px 2px 10px -2px $lbry-black;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.channel-tooltip__arrow {
|
|
||||||
width: 0;
|
|
||||||
height: 0;
|
|
||||||
border-left: 10px solid transparent;
|
|
||||||
border-right: 10px solid transparent;
|
|
||||||
|
|
||||||
html[data-mode='dark'] & {
|
|
||||||
z-index: 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.channel-tooltip__arrow--top {
|
|
||||||
border-top: 10px solid $lbry-gray-5;
|
|
||||||
border-bottom: 0;
|
|
||||||
|
|
||||||
html[data-mode='dark'] & {
|
|
||||||
z-index: 3;
|
|
||||||
border-top: 10px solid mix($lbry-black, $lbry-gray-3, 90%);
|
|
||||||
border-bottom: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.channel-tooltip__arrow--bottom {
|
|
||||||
border-top: 0;
|
|
||||||
border-bottom: 10px solid $lbry-gray-5;
|
|
||||||
|
|
||||||
html[data-mode='dark'] & {
|
|
||||||
z-index: 3;
|
|
||||||
border-top: 0;
|
|
||||||
border-bottom: 10px solid mix($lbry-black, $lbry-gray-3, 90%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.channel-tooltip__profile {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.channel-tooltip__description {
|
|
||||||
padding: 1rem;
|
|
||||||
visibility: visible;
|
|
||||||
border-top: 1px solid rgba($lbry-gray-4, 0.4);
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
html[data-mode='dark'] & {
|
|
||||||
border-top: 1px solid rgba($lbry-black, 0.8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.channel-tooltip__info {
|
|
||||||
}
|
|
||||||
|
|
||||||
.channel-tooltip__title {
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 1.4rem;
|
|
||||||
line-height: 1.5em;
|
|
||||||
visibility: visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
.channel-tooltip__url {
|
|
||||||
font-size: 1rem;
|
|
||||||
visibility: visible;
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue