add channel staked amount indicator on channel thumbnails
This commit is contained in:
parent
d26d76fc70
commit
09b689ba1c
32 changed files with 404 additions and 86 deletions
|
@ -80,6 +80,7 @@
|
|||
"@reach/menu-button": "0.7.4",
|
||||
"@reach/rect": "^0.13.0",
|
||||
"@reach/tabs": "^0.1.5",
|
||||
"@reach/tooltip": "^0.12.1",
|
||||
"@reach/utils": "^0.12.1",
|
||||
"@sentry/browser": "^5.12.1",
|
||||
"@sentry/webpack-plugin": "^1.10.0",
|
||||
|
|
9
ui/component/channelStakedIndicator/index.js
Normal file
9
ui/component/channelStakedIndicator/index.js
Normal file
|
@ -0,0 +1,9 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { makeSelectClaimForUri } from 'lbry-redux';
|
||||
import ChannelStakedIndicator from './view';
|
||||
|
||||
const select = (state, props) => ({
|
||||
channelClaim: makeSelectClaimForUri(props.uri)(state),
|
||||
});
|
||||
|
||||
export default connect(select)(ChannelStakedIndicator);
|
110
ui/component/channelStakedIndicator/view.jsx
Normal file
110
ui/component/channelStakedIndicator/view.jsx
Normal file
|
@ -0,0 +1,110 @@
|
|||
// @flow
|
||||
import * as ICONS from 'constants/icons';
|
||||
import React from 'react';
|
||||
import classnames from 'classnames';
|
||||
import Icon from 'component/common/icon';
|
||||
import LbcSymbol from 'component/common/lbc-symbol';
|
||||
import Tooltip from 'component/common/tooltip';
|
||||
import CreditAmount from 'component/common/credit-amount';
|
||||
|
||||
type Props = {
|
||||
channelClaim: ChannelClaim,
|
||||
large?: boolean,
|
||||
};
|
||||
|
||||
function getChannelLevel(amount: number): number {
|
||||
let level = 1;
|
||||
|
||||
switch (true) {
|
||||
case amount >= 10 && amount < 1000:
|
||||
level = 2;
|
||||
break;
|
||||
case amount >= 1000 && amount < 10000:
|
||||
level = 3;
|
||||
break;
|
||||
case amount >= 10000 && amount < 500000:
|
||||
level = 4;
|
||||
break;
|
||||
case amount > 500000:
|
||||
level = 5;
|
||||
break;
|
||||
}
|
||||
|
||||
return level;
|
||||
}
|
||||
|
||||
function getChannelIcon(level: number): string {
|
||||
const icons = {
|
||||
'1': ICONS.CHANNEL_LEVEL_1,
|
||||
'2': ICONS.CHANNEL_LEVEL_2,
|
||||
'3': ICONS.CHANNEL_LEVEL_3,
|
||||
'4': ICONS.CHANNEL_LEVEL_4,
|
||||
'5': ICONS.CHANNEL_LEVEL_5,
|
||||
};
|
||||
|
||||
return icons[level] || ICONS.CHANNEL_LEVEL_1;
|
||||
}
|
||||
|
||||
function ChannelStakedIndicator(props: Props) {
|
||||
const { channelClaim, large = false } = props;
|
||||
|
||||
if (!channelClaim || !channelClaim.meta) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const amount = parseFloat(channelClaim.amount) + parseFloat(channelClaim.meta.support_amount) || 0;
|
||||
const isControlling = channelClaim && channelClaim.meta.is_controlling;
|
||||
const level = getChannelLevel(amount);
|
||||
const icon = getChannelIcon(level);
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
label={
|
||||
<div className="channel-staked__tooltip">
|
||||
<div className="channel-staked__tooltip-icons">
|
||||
<LevelIcon icon={icon} isControlling={isControlling} size={isControlling ? 14 : 10} />
|
||||
</div>
|
||||
|
||||
<div className="channel-staked__tooltip-text">
|
||||
<span>{__('Level %current_level%', { current_level: level })}</span>
|
||||
<div className="channel-staked__amount">
|
||||
<LbcSymbol postfix={<CreditAmount amount={amount} showLBC={false} />} size={14} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<div
|
||||
className={classnames('channel-staked__wrapper', {
|
||||
'channel-staked__wrapper--large': large,
|
||||
})}
|
||||
>
|
||||
<LevelIcon icon={icon} large={large} isControlling={isControlling} />
|
||||
</div>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
||||
type LevelIconProps = {
|
||||
isControlling: boolean,
|
||||
icon: string,
|
||||
large?: boolean,
|
||||
};
|
||||
|
||||
function LevelIcon(props: LevelIconProps) {
|
||||
const { large, isControlling, icon } = props;
|
||||
return (
|
||||
icon && (
|
||||
<Icon
|
||||
icon={icon}
|
||||
size={large ? 36 : 14}
|
||||
className={classnames('channel-staked__indicator', {
|
||||
'channel-staked__indicator--large': large,
|
||||
'channel-staked__indicator--controlling': isControlling,
|
||||
})}
|
||||
/>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export default ChannelStakedIndicator;
|
|
@ -4,6 +4,7 @@ import { parseURI } from 'lbry-redux';
|
|||
import classnames from 'classnames';
|
||||
import Gerbil from './gerbil.png';
|
||||
import FreezeframeWrapper from 'component/fileThumbnail/FreezeframeWrapper';
|
||||
import ChannelStakedIndicator from 'component/channelStakedIndicator';
|
||||
|
||||
type Props = {
|
||||
thumbnail: ?string,
|
||||
|
@ -14,9 +15,10 @@ type Props = {
|
|||
small?: boolean,
|
||||
allowGifs?: boolean,
|
||||
claim: ?ChannelClaim,
|
||||
doResolveUri: string => void,
|
||||
doResolveUri: (string) => void,
|
||||
isResolving: boolean,
|
||||
showDelayedMessage?: boolean,
|
||||
hideStakedIndicator?: boolean,
|
||||
};
|
||||
|
||||
function ChannelThumbnail(props: Props) {
|
||||
|
@ -32,6 +34,7 @@ function ChannelThumbnail(props: Props) {
|
|||
doResolveUri,
|
||||
isResolving,
|
||||
showDelayedMessage = false,
|
||||
hideStakedIndicator = false,
|
||||
} = props;
|
||||
const [thumbError, setThumbError] = React.useState(false);
|
||||
const shouldResolve = claim === undefined;
|
||||
|
@ -57,7 +60,11 @@ function ChannelThumbnail(props: Props) {
|
|||
}, [doResolveUri, shouldResolve, uri]);
|
||||
|
||||
if (channelThumbnail && channelThumbnail.endsWith('gif') && !allowGifs) {
|
||||
return <FreezeframeWrapper src={channelThumbnail} className={classnames('channel-thumbnail', className)} />;
|
||||
return (
|
||||
<FreezeframeWrapper src={channelThumbnail} className={classnames('channel-thumbnail', className)}>
|
||||
{!hideStakedIndicator && <ChannelStakedIndicator uri={uri} claim={claim} />}
|
||||
</FreezeframeWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -90,6 +97,7 @@ function ChannelThumbnail(props: Props) {
|
|||
)}
|
||||
</>
|
||||
)}
|
||||
{!hideStakedIndicator && <ChannelStakedIndicator uri={uri} claim={claim} />}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -36,9 +36,9 @@ type Props = {
|
|||
claimIsMine: boolean,
|
||||
pending?: boolean,
|
||||
reflectingProgress?: any, // fxme
|
||||
resolveUri: string => void,
|
||||
resolveUri: (string) => void,
|
||||
isResolvingUri: boolean,
|
||||
history: { push: string => void },
|
||||
history: { push: (string) => void },
|
||||
title: string,
|
||||
nsfw: boolean,
|
||||
placeholder: string,
|
||||
|
@ -56,18 +56,18 @@ type Props = {
|
|||
channelIsBlocked: boolean,
|
||||
isSubscribed: boolean,
|
||||
actions: boolean | Node | string | number,
|
||||
properties: boolean | Node | string | number | (Claim => Node),
|
||||
properties: boolean | Node | string | number | ((Claim) => Node),
|
||||
empty?: Node,
|
||||
onClick?: any => any,
|
||||
onClick?: (any) => any,
|
||||
hideBlock?: boolean,
|
||||
streamingUrl: ?string,
|
||||
getFile: string => void,
|
||||
customShouldHide?: Claim => boolean,
|
||||
getFile: (string) => void,
|
||||
customShouldHide?: (Claim) => boolean,
|
||||
showUnresolvedClaim?: boolean,
|
||||
showNullPlaceholder?: boolean,
|
||||
includeSupportAction?: boolean,
|
||||
hideActions?: boolean,
|
||||
renderActions?: Claim => ?Node,
|
||||
renderActions?: (Claim) => ?Node,
|
||||
wrapperElement?: string,
|
||||
hideRepostLabel?: boolean,
|
||||
repostUrl?: string,
|
||||
|
@ -144,7 +144,7 @@ const ClaimPreview = forwardRef<any, {}>((props: Props, ref: any) => {
|
|||
const navigateUrl = formatLbryUrlForWeb((claim && claim.canonical_url) || uri || '/');
|
||||
const navLinkProps = {
|
||||
to: navigateUrl,
|
||||
onClick: e => e.stopPropagation(),
|
||||
onClick: (e) => e.stopPropagation(),
|
||||
};
|
||||
|
||||
// do not block abandoned and nsfw claims if showUserBlocked is passed
|
||||
|
@ -156,7 +156,7 @@ const ClaimPreview = forwardRef<any, {}>((props: Props, ref: any) => {
|
|||
// This will be replaced once blocking is done at the wallet server level
|
||||
if (claim && !claimIsMine && !shouldHide && blackListedOutpoints) {
|
||||
shouldHide = blackListedOutpoints.some(
|
||||
outpoint =>
|
||||
(outpoint) =>
|
||||
(signingChannel && outpoint.txid === signingChannel.txid && outpoint.nout === signingChannel.nout) ||
|
||||
(outpoint.txid === claim.txid && outpoint.nout === claim.nout)
|
||||
);
|
||||
|
@ -165,19 +165,19 @@ const ClaimPreview = forwardRef<any, {}>((props: Props, ref: any) => {
|
|||
// or signing channel outpoint is in the filter list
|
||||
if (claim && !claimIsMine && !shouldHide && filteredOutpoints) {
|
||||
shouldHide = filteredOutpoints.some(
|
||||
outpoint =>
|
||||
(outpoint) =>
|
||||
(signingChannel && outpoint.txid === signingChannel.txid && outpoint.nout === signingChannel.nout) ||
|
||||
(outpoint.txid === claim.txid && outpoint.nout === claim.nout)
|
||||
);
|
||||
}
|
||||
// block stream claims
|
||||
if (claim && !shouldHide && !showUserBlocked && blockedChannelUris.length && signingChannel) {
|
||||
shouldHide = blockedChannelUris.some(blockedUri => blockedUri === signingChannel.permanent_url);
|
||||
shouldHide = blockedChannelUris.some((blockedUri) => blockedUri === signingChannel.permanent_url);
|
||||
}
|
||||
// block channel claims if we can't control for them in claim search
|
||||
// e.g. fetchRecommendedSubscriptions
|
||||
if (claim && isChannelUri && !shouldHide && !showUserBlocked && blockedChannelUris.length) {
|
||||
shouldHide = blockedChannelUris.some(blockedUri => blockedUri === claim.permanent_url);
|
||||
shouldHide = blockedChannelUris.some((blockedUri) => blockedUri === claim.permanent_url);
|
||||
}
|
||||
|
||||
if (!shouldHide && customShouldHide && claim) {
|
||||
|
@ -220,7 +220,7 @@ const ClaimPreview = forwardRef<any, {}>((props: Props, ref: any) => {
|
|||
if (isValid && !isResolvingUri && shouldFetch && uri) {
|
||||
resolveUri(uri);
|
||||
}
|
||||
}, [isValid, uri, isResolvingUri, shouldFetch]);
|
||||
}, [isValid, uri, isResolvingUri, shouldFetch, resolveUri]);
|
||||
|
||||
if (shouldHide && !showNullPlaceholder) {
|
||||
return null;
|
||||
|
@ -319,6 +319,10 @@ const ClaimPreview = forwardRef<any, {}>((props: Props, ref: any) => {
|
|||
<ClaimPreviewTitle uri={uri} />
|
||||
</NavLink>
|
||||
)}
|
||||
|
||||
{type !== 'small' && !isChannelUri && signingChannel && (
|
||||
<ChannelThumbnail uri={signingChannel.permanent_url} />
|
||||
)}
|
||||
</div>
|
||||
<ClaimPreviewSubtitle uri={uri} type={type} />
|
||||
{(pending || !!reflectingProgress) && <PublishPending uri={uri} />}
|
||||
|
|
|
@ -3,6 +3,7 @@ import React from 'react';
|
|||
import UriIndicator from 'component/uriIndicator';
|
||||
import DateTime from 'component/dateTime';
|
||||
import Button from 'component/button';
|
||||
import ChannelThumbnail from 'component/channelThumbnail';
|
||||
import { parseURI } from 'lbry-redux';
|
||||
|
||||
type Props = {
|
||||
|
@ -10,12 +11,13 @@ type Props = {
|
|||
claim: ?Claim,
|
||||
pending?: boolean,
|
||||
type: string,
|
||||
beginPublish: string => void,
|
||||
beginPublish: (string) => void,
|
||||
};
|
||||
|
||||
function ClaimPreviewSubtitle(props: Props) {
|
||||
const { pending, uri, claim, type, beginPublish } = props;
|
||||
const claimsInChannel = (claim && claim.meta.claims_in_channel) || 0;
|
||||
const channelUri = claim && claim.signing_channel && claim.signing_channel.permanent_url;
|
||||
|
||||
let isChannel;
|
||||
let name;
|
||||
|
@ -27,6 +29,7 @@ function ClaimPreviewSubtitle(props: Props) {
|
|||
<div className="media__subtitle">
|
||||
{claim ? (
|
||||
<React.Fragment>
|
||||
{!isChannel && channelUri && type !== 'small' && <ChannelThumbnail uri={channelUri} />}
|
||||
<UriIndicator uri={uri} link />{' '}
|
||||
{!pending &&
|
||||
claim &&
|
||||
|
|
|
@ -18,9 +18,9 @@ import ClaimRepostAuthor from 'component/claimRepostAuthor';
|
|||
type Props = {
|
||||
uri: string,
|
||||
claim: ?Claim,
|
||||
resolveUri: string => void,
|
||||
resolveUri: (string) => void,
|
||||
isResolvingUri: boolean,
|
||||
history: { push: string => void },
|
||||
history: { push: (string) => void },
|
||||
thumbnail: string,
|
||||
title: string,
|
||||
placeholder: boolean,
|
||||
|
@ -33,7 +33,7 @@ type Props = {
|
|||
nout: number,
|
||||
}>,
|
||||
blockedChannelUris: Array<string>,
|
||||
getFile: string => void,
|
||||
getFile: (string) => void,
|
||||
placeholder: boolean,
|
||||
streamingUrl: string,
|
||||
isMature: boolean,
|
||||
|
@ -66,7 +66,7 @@ function ClaimPreviewTile(props: Props) {
|
|||
|
||||
const navLinkProps = {
|
||||
to: navigateUrl,
|
||||
onClick: e => e.stopPropagation(),
|
||||
onClick: (e) => e.stopPropagation(),
|
||||
};
|
||||
|
||||
let isChannel;
|
||||
|
@ -80,13 +80,10 @@ function ClaimPreviewTile(props: Props) {
|
|||
}
|
||||
}
|
||||
|
||||
let channelUri;
|
||||
const signingChannel = claim && claim.signing_channel;
|
||||
let channelThumbnail;
|
||||
if (signingChannel) {
|
||||
channelThumbnail =
|
||||
// I should be able to just pass the the uri to <ChannelThumbnail /> but it wasn't working
|
||||
// Come back to me
|
||||
(signingChannel.value && signingChannel.value.thumbnail && signingChannel.value.thumbnail.url) || undefined;
|
||||
channelUri = signingChannel.permanent_url;
|
||||
}
|
||||
|
||||
function handleClick(e) {
|
||||
|
@ -112,7 +109,7 @@ function ClaimPreviewTile(props: Props) {
|
|||
// This will be replaced once blocking is done at the wallet server level
|
||||
if (claim && !shouldHide && blackListedOutpoints) {
|
||||
shouldHide = blackListedOutpoints.some(
|
||||
outpoint =>
|
||||
(outpoint) =>
|
||||
(signingChannel && outpoint.txid === signingChannel.txid && outpoint.nout === signingChannel.nout) ||
|
||||
(outpoint.txid === claim.txid && outpoint.nout === claim.nout)
|
||||
);
|
||||
|
@ -121,7 +118,7 @@ function ClaimPreviewTile(props: Props) {
|
|||
// or signing channel outpoint is in the filter list
|
||||
if (claim && !shouldHide && filteredOutpoints) {
|
||||
shouldHide = filteredOutpoints.some(
|
||||
outpoint =>
|
||||
(outpoint) =>
|
||||
(signingChannel && outpoint.txid === signingChannel.txid && outpoint.nout === signingChannel.nout) ||
|
||||
(outpoint.txid === claim.txid && outpoint.nout === claim.nout)
|
||||
);
|
||||
|
@ -129,12 +126,12 @@ function ClaimPreviewTile(props: Props) {
|
|||
|
||||
// block stream claims
|
||||
if (claim && !shouldHide && blockedChannelUris.length && signingChannel) {
|
||||
shouldHide = blockedChannelUris.some(blockedUri => blockedUri === signingChannel.permanent_url);
|
||||
shouldHide = blockedChannelUris.some((blockedUri) => blockedUri === signingChannel.permanent_url);
|
||||
}
|
||||
// block channel claims if we can't control for them in claim search
|
||||
// e.g. fetchRecommendedSubscriptions
|
||||
if (claim && isChannel && !shouldHide && blockedChannelUris.length) {
|
||||
shouldHide = blockedChannelUris.some(blockedUri => blockedUri === claim.permanent_url);
|
||||
shouldHide = blockedChannelUris.some((blockedUri) => blockedUri === claim.permanent_url);
|
||||
}
|
||||
|
||||
if (shouldHide) {
|
||||
|
@ -179,7 +176,12 @@ function ClaimPreviewTile(props: Props) {
|
|||
</NavLink>
|
||||
<NavLink {...navLinkProps}>
|
||||
<h2 className="claim-tile__title">
|
||||
<TruncatedText text={title || (claim && claim.name)} lines={2} />
|
||||
<TruncatedText text={title || (claim && claim.name)} lines={isChannel ? 1 : 2} />
|
||||
{isChannel && (
|
||||
<div className="claim-tile__about">
|
||||
<UriIndicator uri={uri} link />
|
||||
</div>
|
||||
)}
|
||||
</h2>
|
||||
</NavLink>
|
||||
<div>
|
||||
|
@ -191,7 +193,7 @@ function ClaimPreviewTile(props: Props) {
|
|||
) : (
|
||||
<React.Fragment>
|
||||
<UriIndicator uri={uri} link hideAnonymous>
|
||||
<ChannelThumbnail thumbnailPreview={channelThumbnail} />
|
||||
<ChannelThumbnail uri={channelUri} />
|
||||
</UriIndicator>
|
||||
|
||||
<div className="claim-tile__about">
|
||||
|
|
|
@ -47,7 +47,7 @@ function ClaimRepostAuthor(props: Props) {
|
|||
|
||||
return (
|
||||
<div className="claim-preview__repost-author">
|
||||
<Icon icon={ICONS.REPOST} size={10} />
|
||||
<Icon icon={ICONS.REPOST} size={10} className="claim-preview__repost-icon" />
|
||||
<I18nMessage tokens={{ repost_channel_link: <UriIndicator link uri={repostChannelUrl} /> }}>
|
||||
%repost_channel_link% reposted
|
||||
</I18nMessage>
|
||||
|
|
|
@ -20,6 +20,7 @@ import CommentsReplies from 'component/commentsReplies';
|
|||
import { useHistory } from 'react-router';
|
||||
import CommentCreate from 'component/commentCreate';
|
||||
import CommentMenuList from 'component/commentMenuList';
|
||||
import UriIndicator from 'component/uriIndicator';
|
||||
|
||||
type Props = {
|
||||
closeInlinePlayer: () => void,
|
||||
|
@ -33,7 +34,7 @@ type Props = {
|
|||
claimIsMine: boolean, // if you control the claim which this comment was posted on
|
||||
commentIsMine: boolean, // if this comment was signed by an owned channel
|
||||
updateComment: (string, string) => void,
|
||||
commentModBlock: string => void,
|
||||
commentModBlock: (string) => void,
|
||||
linkedComment?: any,
|
||||
myChannels: ?Array<ChannelClaim>,
|
||||
commentingEnabled: boolean,
|
||||
|
@ -105,7 +106,7 @@ function Comment(props: Props) {
|
|||
setCharCount(editedMessage.length);
|
||||
|
||||
// a user will try and press the escape key to cancel editing their comment
|
||||
const handleEscape = event => {
|
||||
const handleEscape = (event) => {
|
||||
if (event.keyCode === ESCAPE_KEY) {
|
||||
setEditing(false);
|
||||
}
|
||||
|
@ -180,11 +181,7 @@ function Comment(props: Props) {
|
|||
{!author ? (
|
||||
<span className="comment__author">{__('Anonymous')}</span>
|
||||
) : (
|
||||
<Button
|
||||
className="button--uri-indicator truncated-text comment__author"
|
||||
navigate={authorUri}
|
||||
label={author}
|
||||
/>
|
||||
<UriIndicator link uri={authorUri} />
|
||||
)}
|
||||
<Button
|
||||
className="comment__time"
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
// A housing for all of our icons. Mostly taken from https://github.com/feathericons/react-feather
|
||||
import * as ICONS from 'constants/icons';
|
||||
import React, { forwardRef } from 'react';
|
||||
// $FlowFixMe
|
||||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
type IconProps = {
|
||||
|
@ -12,6 +11,7 @@ type IconProps = {
|
|||
|
||||
type CustomProps = {
|
||||
size?: number,
|
||||
className?: string,
|
||||
};
|
||||
|
||||
// Returns a react component
|
||||
|
@ -1020,4 +1020,84 @@ export const icons = {
|
|||
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" />
|
||||
</g>
|
||||
),
|
||||
[ICONS.CHANNEL_LEVEL_1]: (props: CustomProps) => (
|
||||
<svg
|
||||
{...props}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 26 24"
|
||||
width={props.size || '18'}
|
||||
height={props.size || '18'}
|
||||
fill="currentColor"
|
||||
stroke="currentColor"
|
||||
strokeWidth="0"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
>
|
||||
<path d="M12 4.32001L14.025 8.02501C14.4776 8.85522 15.1598 9.53744 15.99 9.99001L19.68 12L15.975 14.025C15.1448 14.4776 14.4626 15.1598 14.01 15.99L12 19.68L9.97501 15.975C9.52419 15.1524 8.84761 14.4758 8.02501 14.025L4.32001 12L8.02501 9.97501C8.84761 9.52419 9.52419 8.84761 9.97501 8.02501L12 4.32001Z" />
|
||||
</svg>
|
||||
),
|
||||
[ICONS.CHANNEL_LEVEL_2]: (props: CustomProps) => (
|
||||
<svg
|
||||
{...props}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 26 24"
|
||||
width={props.size || '18'}
|
||||
height={props.size || '18'}
|
||||
fill="currentColor"
|
||||
stroke="currentColor"
|
||||
strokeWidth="0"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
>
|
||||
<path d="M15.705 7.31999L17.625 10.845C18.0591 11.6316 18.7099 12.2772 19.5 12.705L23.025 14.625L19.5 16.5C18.7154 16.9301 18.0701 17.5754 17.64 18.36L15.72 21.885L13.785 18.435C13.3625 17.6207 12.7106 16.9479 11.91 16.5L8.38499 14.64L11.91 12.705C12.7001 12.2772 13.3508 11.6316 13.785 10.845L15.705 7.31999ZM4.37999 4.31999C4.10558 4.81954 3.69454 5.23058 3.19499 5.50499L0.974991 6.67499L3.19499 7.88999C3.68451 8.14404 4.09453 8.5281 4.37999 8.99999L5.59499 11.22L6.80999 8.99999C7.0844 8.50045 7.49544 8.08941 7.99499 7.81499L10.215 6.59999L7.99499 5.44499C7.49544 5.17058 7.0844 4.75954 6.80999 4.25999L5.59499 2.05499L4.37999 4.31999Z" />
|
||||
</svg>
|
||||
),
|
||||
[ICONS.CHANNEL_LEVEL_3]: (props: CustomProps) => (
|
||||
<svg
|
||||
{...props}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
width={props.size || '18'}
|
||||
height={props.size || '18'}
|
||||
fill="currentColor"
|
||||
stroke="currentColor"
|
||||
strokeWidth="0"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
>
|
||||
<path d="M12 7.95L13.92 11.475C14.3519 12.2672 15.0028 12.9181 15.795 13.35L19.32 15.27L15.795 17.19C15.0104 17.6201 14.3651 18.2654 13.935 19.05L12 22.59L10.08 19.065C9.64989 18.2804 9.00456 17.6351 8.22 17.205L4.68 15.27L8.205 13.35C8.99718 12.9181 9.64814 12.2672 10.08 11.475L12 7.95ZM3.57 3.705C3.29213 4.2198 2.8698 4.64213 2.355 4.92L0 6.18L2.34 7.5C2.8548 7.77788 3.27713 8.2002 3.555 8.715L4.815 10.95L6.075 8.655C6.36202 8.16237 6.78348 7.76173 7.29 7.5L9.585 6.24L7.29 4.92C6.7752 4.64213 6.35287 4.2198 6.075 3.705L4.815 1.41L3.57 3.705ZM17.625 3.825C17.3305 4.36309 16.8881 4.80555 16.35 5.1L13.935 6.42L16.35 7.74C16.8881 8.03446 17.3305 8.47692 17.625 9.015L18.945 11.43L20.265 9C20.5595 8.46191 21.0019 8.01946 21.54 7.725L24 6.42L21.54 5.1C21.0019 4.80555 20.5595 4.36309 20.265 3.825L18.945 1.41L17.625 3.825Z" />
|
||||
</svg>
|
||||
),
|
||||
[ICONS.CHANNEL_LEVEL_4]: (props: CustomProps) => (
|
||||
<svg
|
||||
{...props}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
width={props.size || '18'}
|
||||
height={props.size || '18'}
|
||||
fill="currentColor"
|
||||
stroke="currentColor"
|
||||
strokeWidth="0"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
>
|
||||
<path d="M4.5 6.375L5.64 8.46C5.89614 8.92861 6.28139 9.31386 6.75 9.57L8.835 10.71L6.75 11.85C6.28139 12.1061 5.89614 12.4914 5.64 12.96L4.5 15L3.285 12.96C3.02886 12.4914 2.64361 12.1061 2.175 11.85L0.0899963 10.71L2.175 9.57C2.64361 9.31386 3.02886 8.92861 3.285 8.46L4.5 6.375ZM17.67 10.125C17.3718 10.6692 16.9242 11.1168 16.38 11.415L13.875 12.75L16.32 14.085C16.8642 14.3832 17.3118 14.8308 17.61 15.375L18.945 17.82L20.28 15.375C20.5782 14.8308 21.0258 14.3832 21.57 14.085L24 12.75L21.555 11.415C21.0108 11.1168 20.5632 10.6692 20.265 10.125L18.93 7.68L17.67 10.125ZM8.49 21C8.93984 21.2454 9.30955 21.6152 9.555 22.065L10.65 24L11.745 21.99C11.9975 21.5699 12.3608 21.2274 12.795 21L14.805 19.905L12.795 18.75C12.3451 18.5046 11.9754 18.1348 11.73 17.685L10.65 15.69L9.555 17.7C9.30955 18.1498 8.93984 18.5196 8.49 18.765L6.48 19.86L8.49 21ZM12.9 4.68C13.2986 4.8985 13.6265 5.22638 13.845 5.625L14.82 7.41L15.795 5.625C16.0135 5.22638 16.3414 4.8985 16.74 4.68L18.525 3.705L16.74 2.73C16.3414 2.5115 16.0135 2.18362 15.795 1.785L14.82 0L13.845 1.785C13.6265 2.18362 13.2986 2.5115 12.9 2.73L11.115 3.705L12.9 4.68Z" />
|
||||
</svg>
|
||||
),
|
||||
[ICONS.CHANNEL_LEVEL_5]: (props: CustomProps) => (
|
||||
<svg
|
||||
{...props}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
width={props.size || '18'}
|
||||
height={props.size || '18'}
|
||||
fill="currentColor"
|
||||
stroke="currentColor"
|
||||
strokeWidth="0"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
>
|
||||
<path d="M12 4.89L13.875 8.31C14.291 9.07838 14.9216 9.70903 15.69 10.125L19.11 12L15.69 13.875C14.9216 14.291 14.291 14.9216 13.875 15.69L12 19.11L10.125 15.69C9.70903 14.9216 9.07838 14.291 8.31 13.875L4.89 12L8.31 10.125C9.07838 9.70903 9.70903 9.07838 10.125 8.31L12 4.89ZM3 1.89C2.76692 2.36024 2.3952 2.74767 1.935 3L0 4.005L1.935 5.055C2.38429 5.28744 2.75483 5.64753 3 6.09L4.05 8.025L5.1 6.09C5.33543 5.65943 5.68943 5.30543 6.12 5.07L8.055 4.02L6.09 3C5.65943 2.76457 5.30543 2.41057 5.07 1.98L4.005 0L3 1.89ZM18.975 1.89C18.7396 2.32057 18.3856 2.67457 17.955 2.91L16.02 3.96L17.955 5.01C18.3856 5.24543 18.7396 5.59943 18.975 6.03L20.025 7.965L21 6.09C21.2354 5.65943 21.5894 5.30543 22.02 5.07L24 4.005L22.065 3C21.6114 2.75957 21.2404 2.38858 21 1.935L19.995 0L18.975 1.89ZM3 17.91C2.76457 18.3406 2.41057 18.6946 1.98 18.93L0 19.995L1.935 21.045C2.36557 21.2804 2.71957 21.6344 2.955 22.065L4.005 24L5.055 22.065C5.28744 21.6157 5.64753 21.2452 6.09 21L8.025 19.95L6.09 18.9C5.65943 18.6646 5.30543 18.3106 5.07 17.88L4.02 15.945L3 17.91ZM18.975 17.91C18.7396 18.3406 18.3856 18.6946 17.955 18.93L16.02 19.98L17.955 21.03C18.3856 21.2654 18.7396 21.6194 18.975 22.05L20.025 23.985L21.075 22.05C21.3104 21.6194 21.6644 21.2654 22.095 21.03L24.03 19.98L22.095 18.93C21.6644 18.6946 21.3104 18.3406 21.075 17.91L20.025 15.975L18.975 17.91Z" />
|
||||
</svg>
|
||||
),
|
||||
};
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// @flow
|
||||
import type { Node } from 'react';
|
||||
import * as ICONS from 'constants/icons';
|
||||
import React from 'react';
|
||||
import classnames from 'classnames';
|
||||
|
@ -8,8 +9,8 @@ type Props = {
|
|||
withText?: boolean,
|
||||
isTitle?: boolean,
|
||||
size?: number,
|
||||
prefix?: string | number,
|
||||
postfix?: string | number,
|
||||
prefix?: string | number | Node,
|
||||
postfix?: string | number | Node,
|
||||
};
|
||||
|
||||
const LbcSymbol = (props: Props) => {
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
// @flow
|
||||
import type { Node } from 'react';
|
||||
import React from 'react';
|
||||
import ReachTooltip from '@reach/tooltip';
|
||||
import '@reach/tooltip/styles.css';
|
||||
|
||||
type Props = {
|
||||
label: string | Node,
|
||||
|
@ -10,11 +12,7 @@ type Props = {
|
|||
function Tooltip(props: Props) {
|
||||
const { children, label } = props;
|
||||
|
||||
if (typeof label !== 'string') {
|
||||
return children;
|
||||
}
|
||||
|
||||
return <span title={label}>{children}</span>;
|
||||
return <ReachTooltip label={label}>{children}</ReachTooltip>;
|
||||
}
|
||||
|
||||
export default Tooltip;
|
||||
|
|
|
@ -23,7 +23,6 @@ $transition-duration: 300ms;
|
|||
top: 0;
|
||||
left: 0;
|
||||
pointer-events: none;
|
||||
z-index: $base-zindex + 1;
|
||||
vertical-align: top;
|
||||
opacity: 0;
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ import classnames from 'classnames';
|
|||
import PropTypes from 'prop-types';
|
||||
import Freezeframe from './FreezeframeLite';
|
||||
|
||||
const FreezeframeWrapper = props => {
|
||||
const FreezeframeWrapper = (props) => {
|
||||
const imgRef = React.useRef();
|
||||
const freezeframe = React.useRef();
|
||||
// eslint-disable-next-line
|
||||
|
|
|
@ -70,17 +70,17 @@ type Props = {
|
|||
index: number,
|
||||
length: number,
|
||||
location: { pathname: string },
|
||||
push: string => void,
|
||||
push: (string) => void,
|
||||
state: {},
|
||||
replaceState: ({}, string, string) => void,
|
||||
listen: any => () => void,
|
||||
listen: (any) => () => void,
|
||||
},
|
||||
uri: string,
|
||||
title: string,
|
||||
welcomeVersion: number,
|
||||
hasNavigated: boolean,
|
||||
setHasNavigated: () => void,
|
||||
setReferrer: string => void,
|
||||
setReferrer: (string) => void,
|
||||
hasUnclaimedRefereeReward: boolean,
|
||||
homepageData: any,
|
||||
};
|
||||
|
@ -95,7 +95,7 @@ function PrivateRoute(props: PrivateRouteProps) {
|
|||
return (
|
||||
<Route
|
||||
{...rest}
|
||||
render={props =>
|
||||
render={(props) =>
|
||||
isAuthenticated || !IS_WEB ? (
|
||||
<Component {...props} />
|
||||
) : (
|
||||
|
@ -220,7 +220,7 @@ function AppRouter(props: Props) {
|
|||
<Route
|
||||
key={dynamicRouteProps.route}
|
||||
path={dynamicRouteProps.route}
|
||||
component={routerProps => <DiscoverPage {...routerProps} dynamicRouteProps={dynamicRouteProps} />}
|
||||
component={(routerProps) => <DiscoverPage {...routerProps} dynamicRouteProps={dynamicRouteProps} />}
|
||||
/>
|
||||
))}
|
||||
|
||||
|
|
|
@ -9,11 +9,10 @@ type Props = {
|
|||
channelUri: ?string,
|
||||
link: ?boolean,
|
||||
claim: ?Claim,
|
||||
|
||||
hideAnonymous: boolean,
|
||||
// Lint thinks we aren't using these, even though we are.
|
||||
// Possibly because the resolve function is an arrow function that is passed in props?
|
||||
resolveUri: string => void,
|
||||
resolveUri: (string) => void,
|
||||
uri: string,
|
||||
// to allow for other elements to be nested within the UriIndicator
|
||||
children: ?Node,
|
||||
|
|
|
@ -28,7 +28,7 @@ export default function WunderbarSuggestion(props: Props) {
|
|||
>
|
||||
{isChannel ? <ChannelThumbnail uri={uri} /> : <FileThumbnail uri={uri} />}
|
||||
<span className="wunderbar__suggestion-label">
|
||||
<div>{claim.value.title}</div>
|
||||
<div className="wunderbar__suggestion-title">{claim.value.title}</div>
|
||||
<div className="wunderbar__suggestion-name">
|
||||
{isChannel ? claim.name : (claim.signing_channel && claim.signing_channel.name) || __('Anonymous')}
|
||||
</div>
|
||||
|
|
|
@ -131,3 +131,8 @@ export const BEST = 'Best';
|
|||
export const CREATOR_LIKE = 'CreatorLike';
|
||||
export const CHEF = 'Chef';
|
||||
export const ANONYMOUS = 'Anonymous';
|
||||
export const CHANNEL_LEVEL_1 = 'ChannelLevel1';
|
||||
export const CHANNEL_LEVEL_2 = 'ChannelLevel2';
|
||||
export const CHANNEL_LEVEL_3 = 'ChannelLevel3';
|
||||
export const CHANNEL_LEVEL_4 = 'ChannelLevel4';
|
||||
export const CHANNEL_LEVEL_5 = 'ChannelLevel5';
|
||||
|
|
|
@ -21,6 +21,7 @@ import ChannelEdit from 'component/channelEdit';
|
|||
import classnames from 'classnames';
|
||||
import HelpLink from 'component/common/help-link';
|
||||
import ClaimSupportButton from 'component/claimSupportButton';
|
||||
import ChannelStakedIndicator from 'component/channelStakedIndicator';
|
||||
|
||||
export const PAGE_VIEW_QUERY = `view`;
|
||||
const ABOUT_PAGE = `about`;
|
||||
|
@ -42,7 +43,7 @@ type Props = {
|
|||
txid: string,
|
||||
nout: number,
|
||||
}>,
|
||||
fetchSubCount: string => void,
|
||||
fetchSubCount: (string) => void,
|
||||
subCount: number,
|
||||
pending: boolean,
|
||||
youtubeChannels: ?Array<{ channel_claim_id: string, sync_status: string, transfer_state: string }>,
|
||||
|
@ -93,7 +94,7 @@ function ChannelPage(props: Props) {
|
|||
|
||||
if (claim && blackListedOutpoints) {
|
||||
channelIsBlackListed = blackListedOutpoints.some(
|
||||
outpoint => outpoint.txid === claim.txid && outpoint.nout === claim.nout
|
||||
(outpoint) => outpoint.txid === claim.txid && outpoint.nout === claim.nout
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -171,8 +172,12 @@ function ChannelPage(props: Props) {
|
|||
uri={uri}
|
||||
obscure={channelIsBlocked}
|
||||
allowGifs
|
||||
hideStakedIndicator
|
||||
/>
|
||||
<h1 className="channel__title">{title || '@' + channelName}</h1>
|
||||
<h1 className="channel__title">
|
||||
{title || '@' + channelName}
|
||||
<ChannelStakedIndicator uri={uri} large />
|
||||
</h1>
|
||||
<div className="channel__meta">
|
||||
<span>
|
||||
{formattedSubCount} {subCount !== 1 ? __('Followers') : __('Follower')}
|
||||
|
@ -198,6 +203,7 @@ function ChannelPage(props: Props) {
|
|||
</div>
|
||||
<div className="channel-cover__gradient" />
|
||||
</header>
|
||||
|
||||
<Tabs onChange={onTabChange} index={tabIndex}>
|
||||
<TabList className="tabs__list--channel-page">
|
||||
<Tab disabled={editing}>{__('Content')}</Tab>
|
||||
|
|
|
@ -17,22 +17,25 @@ type State = { search: SearchState };
|
|||
|
||||
export const selectState = (state: State): SearchState => state.search;
|
||||
|
||||
export const selectSearchValue: (state: State) => string = createSelector(selectState, state => state.searchQuery);
|
||||
export const selectSearchValue: (state: State) => string = createSelector(selectState, (state) => state.searchQuery);
|
||||
|
||||
export const selectSearchOptions: (state: State) => SearchOptions = createSelector(selectState, state => state.options);
|
||||
export const selectSearchOptions: (state: State) => SearchOptions = createSelector(
|
||||
selectState,
|
||||
(state) => state.options
|
||||
);
|
||||
|
||||
export const selectIsSearching: (state: State) => boolean = createSelector(selectState, state => state.searching);
|
||||
export const selectIsSearching: (state: State) => boolean = createSelector(selectState, (state) => state.searching);
|
||||
|
||||
export const selectSearchUrisByQuery: (state: State) => { [string]: Array<string> } = createSelector(
|
||||
selectState,
|
||||
state => state.urisByQuery
|
||||
(state) => state.urisByQuery
|
||||
);
|
||||
|
||||
export const makeSelectSearchUris = (query: string): ((state: State) => Array<string>) =>
|
||||
// replace statement below is kind of ugly, and repeated in doSearch action
|
||||
createSelector(
|
||||
selectSearchUrisByQuery,
|
||||
byQuery => byQuery[query ? query.replace(/^lbry:\/\//i, '').replace(/\//, ' ') : query]
|
||||
(byQuery) => byQuery[query ? query.replace(/^lbry:\/\//i, '').replace(/\//, ' ') : query]
|
||||
);
|
||||
|
||||
// Creates a query string based on the state in the search reducer
|
||||
|
@ -82,7 +85,7 @@ export const makeSelectRecommendedContentForUri = (uri: string) =>
|
|||
|
||||
let searchUris = searchUrisByQuery[searchQuery];
|
||||
if (searchUris) {
|
||||
searchUris = searchUris.filter(searchUri => searchUri !== currentUri);
|
||||
searchUris = searchUris.filter((searchUri) => searchUri !== currentUri);
|
||||
recommendedContent = searchUris;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,10 +50,10 @@
|
|||
@import 'component/spinner';
|
||||
@import 'component/splash';
|
||||
@import 'component/status-bar';
|
||||
@import 'component/subscriptions';
|
||||
@import 'component/syntax-highlighter';
|
||||
@import 'component/table';
|
||||
@import 'component/tabs';
|
||||
@import 'component/tooltip';
|
||||
@import 'component/txo-list';
|
||||
@import 'component/tags';
|
||||
@import 'component/wunderbar';
|
||||
|
|
|
@ -61,6 +61,7 @@ $metadata-z-index: 1;
|
|||
|
||||
.channel-thumbnail {
|
||||
display: flex;
|
||||
position: relative;
|
||||
height: 5rem;
|
||||
width: 5rem;
|
||||
background-size: cover;
|
||||
|
@ -166,7 +167,7 @@ $metadata-z-index: 1;
|
|||
// Quick hack to get this to work
|
||||
// We should have a generic style for "header with button next to it"
|
||||
.button {
|
||||
margin-left: var(--spacing-m);
|
||||
margin-left: var(--spacing-xs);
|
||||
}
|
||||
|
||||
@media (max-width: $breakpoint-small) {
|
||||
|
@ -351,3 +352,59 @@ $metadata-z-index: 1;
|
|||
margin-bottom: var(--spacing-l);
|
||||
}
|
||||
}
|
||||
|
||||
.channel-staked__tooltip {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.channel-staked__tooltip-text {
|
||||
margin-left: var(--spacing-xs);
|
||||
font-size: var(--font-xsmall);
|
||||
|
||||
.icon--LBC {
|
||||
opacity: 0.7;
|
||||
margin-top: -2px;
|
||||
}
|
||||
}
|
||||
|
||||
.channel-staked__wrapper {
|
||||
display: flex;
|
||||
position: absolute;
|
||||
bottom: -0.9rem;
|
||||
left: -0.9rem;
|
||||
padding: 0.25rem;
|
||||
background-color: var(--color-card-background);
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.channel-staked__wrapper--large {
|
||||
position: relative;
|
||||
background-color: transparent;
|
||||
display: inline-block;
|
||||
bottom: auto;
|
||||
left: auto;
|
||||
top: var(--spacing-xs);
|
||||
margin-left: var(--spacing-s);
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.channel-staked__indicator {
|
||||
margin-left: 2px;
|
||||
z-index: 3;
|
||||
fill: var(--color-gray-3);
|
||||
}
|
||||
|
||||
.channel-staked__indicator--controlling {
|
||||
fill: #00eaff;
|
||||
}
|
||||
|
||||
.channel-staked__amount {
|
||||
display: inline-block;
|
||||
font-size: var(--font-xxsmall);
|
||||
margin-left: var(--spacing-s);
|
||||
|
||||
.credit-amount {
|
||||
color: var(--color-gray-3);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -169,6 +169,11 @@
|
|||
.channel-thumbnail {
|
||||
@include handleChannelGif(4rem);
|
||||
}
|
||||
|
||||
.media__subtitle {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
||||
.claim-preview--pending {
|
||||
|
@ -242,6 +247,11 @@
|
|||
|
||||
.claim-preview-info {
|
||||
align-items: flex-start;
|
||||
|
||||
.channel-thumbnail {
|
||||
@include handleChannelGif(1.4rem);
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.claim-preview-info,
|
||||
|
@ -425,10 +435,6 @@
|
|||
&:nth-child(3n + 1) {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.channel-thumbnail {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: $breakpoint-small) {
|
||||
|
@ -526,11 +532,11 @@
|
|||
transform: translateY(calc(var(--spacing-xs) * -1));
|
||||
font-size: var(--font-xsmall);
|
||||
color: var(--color-text-subtitle);
|
||||
}
|
||||
|
||||
.icon {
|
||||
.claim-preview__repost-icon {
|
||||
margin-right: var(--spacing-xxs);
|
||||
margin-bottom: -1px; // Offset it slightly because it doesn't look aligned next to all lowercase text + the @ from a channel
|
||||
}
|
||||
}
|
||||
|
||||
.claim-tile__repost-author {
|
||||
|
|
|
@ -204,6 +204,7 @@ $thumbnailWidthSmall: 0rem;
|
|||
opacity: 0.5;
|
||||
white-space: nowrap;
|
||||
height: 100%;
|
||||
margin-left: var(--spacing-xs);
|
||||
|
||||
&:focus {
|
||||
@include linkFocus;
|
||||
|
|
|
@ -46,10 +46,6 @@
|
|||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
> .button:only-child {
|
||||
margin-left: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.header__buttons {
|
||||
|
@ -133,6 +129,7 @@
|
|||
|
||||
.header__navigation-item--balance {
|
||||
@extend .button--link;
|
||||
margin-left: var(--spacing-m);
|
||||
}
|
||||
|
||||
.header__navigation-item--forward {
|
||||
|
|
|
@ -40,8 +40,10 @@
|
|||
color: var(--color-text-subtitle);
|
||||
font-size: var(--font-small);
|
||||
|
||||
svg {
|
||||
stroke: var(--color-text-subtitle);
|
||||
.channel-thumbnail {
|
||||
display: inline-block;
|
||||
@include handleChannelGif(1rem);
|
||||
margin-right: var(--spacing-xs);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
.subscriptions__suggested {
|
||||
animation: expand 0.2s;
|
||||
position: relative;
|
||||
}
|
8
ui/scss/component/_tooltip.scss
Normal file
8
ui/scss/component/_tooltip.scss
Normal file
|
@ -0,0 +1,8 @@
|
|||
[data-reach-tooltip] {
|
||||
border-radius: var(--border-radius);
|
||||
background-color: var(--color-tooltip-bg);
|
||||
color: var(--color-tooltip-text);
|
||||
border: none;
|
||||
padding: var(--spacing-s);
|
||||
overflow: hidden;
|
||||
}
|
|
@ -170,6 +170,9 @@
|
|||
font-size: var(--font-small);
|
||||
min-width: 0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.wunderbar__suggestion-title {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
--color-thumbnail-background: var(--color-gray-5);
|
||||
--color-comment-threadline: #434b54;
|
||||
--color-comment-threadline-hover: var(--color-gray-4);
|
||||
--color-tooltip-bg: #2f3337;
|
||||
|
||||
// Text
|
||||
--color-text: #d8d8d8;
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
--color-comment-threadline: var(--color-gray-1);
|
||||
--color-comment-threadline-hover: var(--color-gray-4);
|
||||
--color-thumbnail-background: var(--color-gray-1);
|
||||
--color-tooltip-bg: #222;
|
||||
--color-tooltip-text: #fafafa;
|
||||
|
||||
// Icons
|
||||
--color-follow-bg: #ffd4da;
|
||||
|
|
20
yarn.lock
20
yarn.lock
|
@ -1493,6 +1493,19 @@
|
|||
"@reach/utils" "^0.2.3"
|
||||
warning "^4.0.2"
|
||||
|
||||
"@reach/tooltip@^0.12.1":
|
||||
version "0.12.1"
|
||||
resolved "https://registry.yarnpkg.com/@reach/tooltip/-/tooltip-0.12.1.tgz#76f8e2337aa7dda20928ec4bbca247d39b4326af"
|
||||
integrity sha512-9qk7WcgAjN/2tFEHN3Oi1m7BrSsL+MBFTFaxTaNqQacXYIKO3jNVFzLxkDVgyFP82h6EMJ5CkAJjOMi4aNyicQ==
|
||||
dependencies:
|
||||
"@reach/auto-id" "0.12.1"
|
||||
"@reach/portal" "0.12.1"
|
||||
"@reach/rect" "0.12.1"
|
||||
"@reach/utils" "0.12.1"
|
||||
"@reach/visually-hidden" "0.12.0"
|
||||
prop-types "^15.7.2"
|
||||
tslib "^2.0.0"
|
||||
|
||||
"@reach/utils@0.12.1", "@reach/utils@^0.12.1":
|
||||
version "0.12.1"
|
||||
resolved "https://registry.yarnpkg.com/@reach/utils/-/utils-0.12.1.tgz#02b9c15ba5cddf23e16f2d2ca77aef98a9702607"
|
||||
|
@ -1519,6 +1532,13 @@
|
|||
version "0.7.4"
|
||||
resolved "https://registry.yarnpkg.com/@reach/utils/-/utils-0.7.4.tgz#cdd0cff8c57445ce9c2b11204e6a62868f1093a1"
|
||||
|
||||
"@reach/visually-hidden@0.12.0":
|
||||
version "0.12.0"
|
||||
resolved "https://registry.yarnpkg.com/@reach/visually-hidden/-/visually-hidden-0.12.0.tgz#c6c39f0bf292ae97a480ba3ed32e8a6149e852d4"
|
||||
integrity sha512-VXtyR36WOS0FHmFQ/BzfswwPyBXICl/YjmTPtx/I0Vy5C6djjhD9kDsE+h/FpHzP3ugTdqdqiPBVElIZTSwOSA==
|
||||
dependencies:
|
||||
tslib "^2.0.0"
|
||||
|
||||
"@samverschueren/stream-to-observable@^0.3.0":
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz#ecdf48d532c58ea477acfcab80348424f8d0662f"
|
||||
|
|
Loading…
Reference in a new issue