Simplify FileCard & FileTile styles #2011

Merged
neb-b merged 2 commits from simple into master 2018-10-09 21:22:34 +02:00
18 changed files with 130 additions and 317 deletions

View file

@ -12,6 +12,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).
* Make tooltip smarter ([#1979](https://github.com/lbryio/lbry-desktop/pull/1979)) * Make tooltip smarter ([#1979](https://github.com/lbryio/lbry-desktop/pull/1979))
* Change channel pages to have 48 items instead of 10 ([#2002](https://github.com/lbryio/lbry-desktop/pull/2002)) * Change channel pages to have 48 items instead of 10 ([#2002](https://github.com/lbryio/lbry-desktop/pull/2002))
* Update to https ([#2016](https://github.com/lbryio/lbry-desktop/pull/2016)) * Update to https ([#2016](https://github.com/lbryio/lbry-desktop/pull/2016))
* Simplify FileCard and FileTile component styling ([#2011](https://github.com/lbryio/lbry-desktop/pull/2011))
### Fixed ### Fixed
* Invite table cutoff with large number of invites ([#1985](https://github.com/lbryio/lbry-desktop/pull/1985)) * Invite table cutoff with large number of invites ([#1985](https://github.com/lbryio/lbry-desktop/pull/1985))

View file

@ -60,32 +60,13 @@ class ChannelTile extends React.PureComponent<Props> {
> >
<CardMedia title={channelName} thumbnail={null} /> <CardMedia title={channelName} thumbnail={null} />
<div className="file-tile__info"> <div className="file-tile__info">
{isResolvingUri && ( {isResolvingUri && <div className="file-tile__title">{__('Loading...')}</div>}
<div
className={classnames({
'card__title--small': size !== 'large',
'card__title--large': size === 'large',
})}
>
{__('Loading...')}
</div>
)}
{!isResolvingUri && ( {!isResolvingUri && (
<React.Fragment> <React.Fragment>
<div <div className="file-tile__title">
className={classnames({
'card__title--file': size === 'regular',
'card__title--x-small': size === 'small',
'card__title--large': size === 'large',
})}
>
<TruncatedText text={channelName || uri} lines={1} /> <TruncatedText text={channelName || uri} lines={1} />
</div> </div>
<div <div className="card__subtitle">
className={classnames('card__subtitle', {
'card__subtitle--large': size === 'large',
})}
>
{totalItems > 0 && ( {totalItems > 0 && (
<span> <span>
{totalItems} {totalItems === 1 ? 'file' : 'files'} {totalItems} {totalItems === 1 ? 'file' : 'files'}

View file

@ -14,6 +14,7 @@ type Props = {
icon: string, icon: string,
tooltip?: string, // tooltip direction tooltip?: string, // tooltip direction
iconColor?: string, iconColor?: string,
size?: number,
}; };
class IconComponent extends React.PureComponent<Props> { class IconComponent extends React.PureComponent<Props> {
@ -42,7 +43,7 @@ class IconComponent extends React.PureComponent<Props> {
}; };
render() { render() {
const { icon, tooltip, iconColor } = this.props; const { icon, tooltip, iconColor, size } = this.props;
const Icon = FeatherIcons[icon]; const Icon = FeatherIcons[icon];
if (!Icon) { if (!Icon) {
@ -54,16 +55,17 @@ class IconComponent extends React.PureComponent<Props> {
color = this.getIconColor(iconColor); color = this.getIconColor(iconColor);
} }
let size = 14; let iconSize = size || 14;
// Arrow icons are quite a bit smaller than the other icons we use
if (icon === icons.ARROW_LEFT || icon === icons.ARROW_RIGHT) { if (icon === icons.ARROW_LEFT || icon === icons.ARROW_RIGHT) {
size = 20; iconSize = 20;
} }
let tooltipText; let tooltipText;
if (tooltip) { if (tooltip) {
tooltipText = this.getTooltip(icon); tooltipText = this.getTooltip(icon);
} }
const inner = <Icon size={size} className="icon" color={color} />; const inner = <Icon size={iconSize} className="icon" color={color} />;
return tooltipText ? ( return tooltipText ? (
<Tooltip icon body={tooltipText} direction={tooltip}> <Tooltip icon body={tooltipText} direction={tooltip}>

View file

@ -91,18 +91,16 @@ class FileCard extends React.PureComponent<Props> {
onContextMenu={handleContextMenu} onContextMenu={handleContextMenu}
> >
<CardMedia thumbnail={thumbnail} /> <CardMedia thumbnail={thumbnail} />
<div className="card__title-identity"> <div className="card__title card__title--file-card">
<div className="card__title--small card__title--file-card"> <TruncatedText text={title} lines={2} />
<TruncatedText text={title} lines={2} /> </div>
</div> <div className="card__subtitle">
<div className="card__subtitle"> {pending ? <div>Pending...</div> : <UriIndicator uri={uri} link />}
{pending ? <div>Pending...</div> : <UriIndicator uri={uri} link />} </div>
</div> <div className="card__file-properties">
<div className="card__file-properties"> {showPrice && <FilePrice hideFree uri={uri} />}
{showPrice && <FilePrice hideFree uri={uri} />} {isRewardContent && <Icon iconColor="red" icon={icons.FEATURED} />}
{isRewardContent && <Icon iconColor="red" icon={icons.FEATURED} />} {fileInfo && <Icon icon={icons.LOCAL} />}
{fileInfo && <Icon icon={icons.LOCAL} />}
</div>
</div> </div>
</section> </section>
); );

View file

@ -108,36 +108,14 @@ class FileTile extends React.PureComponent<Props> {
> >
<CardMedia title={title || name} thumbnail={thumbnail} /> <CardMedia title={title || name} thumbnail={thumbnail} />
<div className="file-tile__info"> <div className="file-tile__info">
{isResolvingUri && ( {isResolvingUri && <div className="file-tile__title">{__('Loading...')}</div>}
<div
className={classnames({
'card__title--small': size !== 'large',
'card__title--large': size === 'large',
})}
>
{__('Loading...')}
</div>
)}
{!isResolvingUri && ( {!isResolvingUri && (
<React.Fragment> <React.Fragment>
<div <div className="file-tile__title">
className={classnames({
'card__title--file': size === 'regular',
'card__title--x-small': size === 'small',
'card__title--large': size === 'large',
})}
>
<TruncatedText text={title || name} lines={size === 'small' ? 2 : 3} /> <TruncatedText text={title || name} lines={size === 'small' ? 2 : 3} />
</div> </div>
<div <div className="card__subtitle">
className={classnames('card__subtitle', { {showUri ? uri : <UriIndicator uri={uri} link />}
'card__subtitle--x-small': size === 'small',
'card__subtitle--large': size === 'large',
})}
>
<span className="file-tile__channel">
{showUri ? uri : <UriIndicator uri={uri} link />}
</span>
</div> </div>
<div className="card__file-properties"> <div className="card__file-properties">
<FilePrice hideFree uri={uri} /> <FilePrice hideFree uri={uri} />
@ -145,12 +123,7 @@ class FileTile extends React.PureComponent<Props> {
{showLocal && isDownloaded && <Icon icon={icons.LOCAL} />} {showLocal && isDownloaded && <Icon icon={icons.LOCAL} />}
</div> </div>
{displayDescription && ( {displayDescription && (
<div <div className="card__subtext">
className={classnames('card__subtext', {
'card__subtext--small': size !== 'small',
'card__subtext--large': size === 'large',
})}
>
<TruncatedText text={description} lines={size === 'large' ? 4 : 3} /> <TruncatedText text={description} lines={size === 'large' ? 4 : 3} />
</div> </div>
)} )}

View file

@ -101,7 +101,7 @@ class ActiveShapeShift extends React.PureComponent<Props> {
)} )}
{shiftState === statuses.RECEIVED && ( {shiftState === statuses.RECEIVED && (
<div className="card__content--extra-vertical-space"> <div>
<p> <p>
{__('ShapeShift has received your payment! Sending the funds to your LBRY wallet.')} {__('ShapeShift has received your payment! Sending the funds to your LBRY wallet.')}
</p> </p>
@ -110,7 +110,7 @@ class ActiveShapeShift extends React.PureComponent<Props> {
)} )}
{shiftState === statuses.COMPLETE && ( {shiftState === statuses.COMPLETE && (
<div className="card__content--extra-vertical-space"> <div>
<p>{__('Transaction complete! You should see the new LBC in your wallet.')}</p> <p>{__('Transaction complete! You should see the new LBC in your wallet.')}</p>
</div> </div>
)} )}

View file

@ -2,7 +2,6 @@
import React from 'react'; import React from 'react';
import Button from 'component/button'; import Button from 'component/button';
import { buildURI } from 'lbry-redux'; import { buildURI } from 'lbry-redux';
import classnames from 'classnames';
import type { Claim } from 'types/claim'; import type { Claim } from 'types/claim';
type Props = { type Props = {
@ -59,17 +58,7 @@ class UriIndicator extends React.PureComponent<Props> {
channelLink = link ? buildURI({ channelName, claimId: channelClaimId }) : false; channelLink = link ? buildURI({ channelName, claimId: channelClaimId }) : false;
} }
const inner = ( const inner = <span className="channel-name">{channelName}</span>;
<span>
<span
className={classnames('channel-name', {
'button-text no-underline': link,
})}
>
{channelName}
</span>{' '}
</span>
);
if (!channelLink) { if (!channelLink) {
return inner; return inner;

View file

@ -80,7 +80,7 @@ class ChannelPage extends React.PureComponent<Props> {
return ( return (
<Page notContained> <Page notContained>
<section className="card__channel-info card__channel-info--large"> <section>
<h1> <h1>
{name} {name}
{fetching && <BusyIndicator />} {fetching && <BusyIndicator />}

View file

@ -183,21 +183,20 @@ class FilePage extends React.Component<Props> {
))} ))}
<div className="card__content"> <div className="card__content">
<div className="card__title-identity--file"> <div className="card__title__space-between">
<h1 className="card__title card__title--file">{title}</h1> <h1>{title}</h1>
<div className="card__title-identity-icons"> <div className="card__title-identity-icons">
{isRewardContent && <Icon iconColor="red" tooltip="bottom" icon={icons.FEATURED} />} {isRewardContent && (
<Icon size={20} iconColor="red" tooltip="bottom" icon={icons.FEATURED} />
)}
<FilePrice filePage uri={normalizeURI(uri)} /> <FilePrice filePage uri={normalizeURI(uri)} />
</div> </div>
</div> </div>
<span className="card__subtitle card__subtitle--file"> <span className="card__subtitle">
{__('Published on')}&nbsp; <UriIndicator uri={uri} link /> {__('published on')}{' '}
<DateTime block={height} show={DateTime.SHOW_DATE} /> <DateTime block={height} show={DateTime.SHOW_DATE} />
</span> </span>
{metadata.nsfw && <div>NSFW</div>} {metadata.nsfw && <div>NSFW</div>}
<div className="card__channel-info">
<UriIndicator uri={uri} link />
</div>
<div className="card__actions card__actions--no-margin card__actions--between"> <div className="card__actions card__actions--no-margin card__actions--between">
<div className="card__actions"> <div className="card__actions">
{claimIsMine ? ( {claimIsMine ? (
@ -221,17 +220,14 @@ class FilePage extends React.Component<Props> {
onClick={() => openModal({ id: MODALS.SEND_TIP }, { uri })} onClick={() => openModal({ id: MODALS.SEND_TIP }, { uri })}
/> />
)} )}
<Button {speechShareable && (
button="alt" <Button
icon={icons.GLOBE} button="alt"
label={__('Share')} icon={icons.GLOBE}
onClick={() => label={__('Share')}
openModal( onClick={() => openModal({ id: MODALS.SOCIAL_SHARE }, { uri })}
{ id: MODALS.SOCIAL_SHARE }, />
{ uri, speechShareable: speechShareable } )}
)
}
/>
</div> </div>
<div className="card__actions"> <div className="card__actions">
@ -239,7 +235,7 @@ class FilePage extends React.Component<Props> {
<FileActions uri={uri} claimId={claim.claim_id} /> <FileActions uri={uri} claimId={claim.claim_id} />
</div> </div>
</div> </div>
<FormRow padded> <FormRow>
<ToolTip direction="right" body={__('Automatically download and play free content.')}> <ToolTip direction="right" body={__('Automatically download and play free content.')}>
<FormField <FormField
name="autoplay" name="autoplay"
@ -250,7 +246,7 @@ class FilePage extends React.Component<Props> {
/> />
</ToolTip> </ToolTip>
</FormRow> </FormRow>
<div className="card__content--extra-padding"> <div className="card__content">
<FileDetails uri={uri} /> <FileDetails uri={uri} />
</div> </div>
</div> </div>

View file

@ -258,7 +258,7 @@ p {
} }
.credit-amount { .credit-amount {
font-size: 10px; font-size: 0.9em;
white-space: nowrap; white-space: nowrap;
} }

View file

@ -31,3 +31,4 @@
@import 'component/_dat-gui.scss'; @import 'component/_dat-gui.scss';
@import 'component/_item-list.scss'; @import 'component/_item-list.scss';
@import 'component/_time.scss'; @import 'component/_time.scss';
@import 'component/_icon.scss';

View file

@ -160,6 +160,7 @@ button:disabled {
.btn--uri-indicator { .btn--uri-indicator {
transition: color var(--animation-duration) var(--animation-style); transition: color var(--animation-duration) var(--animation-style);
display: inline-block;
&:hover { &:hover {
color: var(--btn-color-inverse); color: var(--btn-color-inverse);

View file

@ -6,10 +6,18 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
max-width: var(--card-max-width); max-width: var(--card-max-width);
} white-space: normal;
.card > h1 { .card__media {
word-wrap: break-word; padding-top: var(--video-aspect-ratio);
}
// Text that is shown if a piece of content has no thumbnail
// We need to do this because the thumbnail uses padding-top: var(--video-aspect-ratio); for dynamic height
// this lets the text sit in the middle instead of the bottom
.card__media-text {
margin-top: calc(var(--video-aspect-ratio) * -1);
}
} }
.card--section { .card--section {
@ -20,25 +28,25 @@
} }
.card--small { .card--small {
white-space: normal; font-size: 13px;
}
.card__media { .card__media {
padding-top: var(--video-aspect-ratio); background-size: cover;
} background-repeat: no-repeat;
background-position: 50% 50%;
background-color: var(--color-placeholder);
}
.card__media-text { .card__media--no-img {
// for the weird padding required for dynamic height display: flex;
// this lets the text sit in the middle instead of the bottom justify-content: center;
margin-top: calc(var(--video-aspect-ratio) * -1); align-items: center;
} position: relative;
}
.channel-name { .card__media--nsfw {
font-size: 12px; background-color: var(--color-error);
@media only screen and (min-width: $medium-breakpoint) {
font-size: 14px;
}
}
} }
.card--link { .card--link {
@ -66,31 +74,29 @@
pointer-events: none; pointer-events: none;
} }
.card__media { .card__title {
background-size: cover; font-size: 1.5em;
background-repeat: no-repeat;
background-position: 50% 50%;
background-color: var(--color-placeholder);
}
.card__media--no-img {
display: flex;
justify-content: center;
align-items: center;
position: relative;
}
.card__media--nsfw {
background-color: var(--color-error);
}
.card__title-identity {
color: var(--text-color); color: var(--text-color);
padding-top: $spacing-vertical * 1/3;
@media (min-width: $large-breakpoint) {
font-size: 1.7em;
}
} }
.card__title-identity--file { .card__title--file-card {
// FileCard is slightly different where the title is only slightly bigger than the subtitle
// Slightly bigger than 2 lines for consistent channel placement
font-size: 1.1em;
height: 4em;
@media only screen and (min-width: $large-breakpoint) {
font-size: 1.3em;
}
}
.card__title__space-between {
display: flex; display: flex;
align-items: center;
justify-content: space-between; justify-content: space-between;
.icon { .icon {
@ -104,73 +110,26 @@
align-self: flex-start; align-self: flex-start;
} }
.card__title {
font-size: 18px;
color: var(--text-color);
font-family: 'metropolis-semibold';
}
.card__title--small {
font-size: 12px;
line-height: 12px;
@media only screen and (min-width: $medium-breakpoint) {
font-size: 14px;
line-height: 14px;
}
}
.card__title--x-small {
font-size: 12px;
line-height: 12px;
}
.card__title--large {
font-size: 22px;
}
.card__title--file {
font-family: 'metropolis-bold';
font-size: 28px;
margin-bottom: 0;
padding-top: 0;
padding-bottom: 5px;
font-size: 18px;
}
.card__title--file-card {
padding-top: $spacing-vertical * 1/3;
// height is the same height that two lines of title fill
// doing this so content below the title is inline accross the row
height: 30px;
@media only screen and (min-width: $medium-breakpoint) {
height: 36px;
}
}
.card__subtitle { .card__subtitle {
margin: 0;
font-size: 14px;
color: var(--card-text-color); color: var(--card-text-color);
font-size: 1em;
line-height: 1em;
@media (min-width: $large-breakpoint) {
font-size: 1.2em;
}
} }
.card__subtitle--x-small { .card__subtext-title {
font-size: 12px; font-size: 1.1em;
&:not(:first-of-type) {
margin-top: $spacing-vertical * 3/2;
}
} }
.card__subtitle--large { .card__subtext {
font-size: 18px; font-size: 0.85em;
padding-bottom: $spacing-vertical * 1/3;
}
.card__subtitle-price {
padding-top: $spacing-vertical * 1/3;
}
.card__title--small + .card__subtitle,
.card__title--x-small + .card__subtitle {
padding-top: $spacing-vertical * 1/3;
} }
.card__meta { .card__meta {
@ -185,11 +144,6 @@
align-items: center; align-items: center;
padding-top: $spacing-vertical * 1/3; padding-top: $spacing-vertical * 1/3;
color: var(--card-text-color); color: var(--card-text-color);
.icon + .icon,
.credit-amount + .icon {
margin-left: $spacing-vertical * 1/3;
}
} }
// .card-media__internal__links should always be inside a card // .card-media__internal__links should always be inside a card
@ -201,57 +155,10 @@
} }
} }
.card--small {
.card-media__internal-links {
top: $spacing-vertical * 1/3;
right: $spacing-vertical * 1/3;
}
}
// Channel info with buttons on the right side
.card__channel-info {
display: flex;
justify-content: space-between;
align-items: center;
padding: $spacing-width 0 0;
}
.card__channel-info--large {
padding: 0;
}
.card__content { .card__content {
margin-top: $spacing-vertical * 2/3; margin-top: $spacing-vertical * 2/3;
} }
.card__content--extra-padding {
margin-top: $spacing-vertical * 3/2;
}
.card__subtext-title {
color: var(--text-color);
font-size: calc(var(--font-size-subtext-multiple) * 1.2em);
&:not(:first-of-type) {
margin-top: $spacing-vertical * 3/2;
}
}
.card__subtext {
font-size: calc(var(--font-size-subtext-multiple) * 1em);
padding-top: $spacing-vertical * 1/3;
word-break: break-word;
font-family: 'metropolis-medium';
}
.card__subtext--small {
font-size: calc(var(--font-size-subtext-multiple) * 0.8em);
}
.card__subtext--large {
font-size: calc(var(--font-size-subtext-multiple) * 0.9em);
}
.card__actions { .card__actions {
margin-top: $spacing-vertical * 2/3; margin-top: $spacing-vertical * 2/3;
display: flex; display: flex;
@ -463,43 +370,3 @@
padding: $spacing-vertical * 1/3; padding: $spacing-vertical * 1/3;
margin: $spacing-vertical * 1/3 0; margin: $spacing-vertical * 1/3 0;
} }
.card__media--autothumb {
color: red !important;
}
.card__media {
&.card__media--autothumb.purple {
background-color: #9c27b0;
}
&.card__media--autothumb.red {
background-color: #e53935;
}
&.card__media--autothumb.pink {
background-color: #e91e63;
}
&.card__media--autothumb.indigo {
background-color: #3f51b5;
}
&.card__media--autothumb.blue {
background-color: #2196f3;
}
&.card__media--autothumb.light-blue {
background-color: #039be5;
}
&.card__media--autothumb.cyan {
background-color: #00acc1;
}
&.card__media--autothumb.teal {
background-color: #009688;
}
&.card__media--autothumb.green {
background-color: #43a047;
}
&.card__media--autothumb.yellow {
background-color: #ffeb3b;
}
&.card__media--autothumb.orange {
background-color: #ffa726;
}
}

View file

@ -4,7 +4,3 @@
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;
} }
.channel-indicator__icon--invalid {
color: var(--color-error);
}

View file

@ -95,10 +95,6 @@
&.content__empty--nsfw { &.content__empty--nsfw {
background-color: var(--color-nsfw); background-color: var(--color-nsfw);
} }
.card__media-text {
margin-top: calc(var(--video-aspect-ratio) * -1);
}
} }
img { img {

View file

@ -22,25 +22,32 @@
.file-tile { .file-tile {
display: flex; display: flex;
font-size: 14px;
padding-top: $spacing-vertical; padding-top: $spacing-vertical;
.card__media { .card__media {
height: var(--file-tile-media-height); height: var(--file-tile-media-height);
flex: 0 0 var(--file-tile-media-width); flex: 0 0 var(--file-tile-media-width);
} }
}
.card__subtitle { .file-tile--small {
line-height: 1; font-size: 12px;
display: flex;
align-items: center; .card__media {
height: var(--file-tile-media-height-small);
flex: 0 0 var(--file-tile-media-width-small);
} }
} }
.file-tile__channel { .file-tile--large {
padding-right: $spacing-width * 1/4; font-size: 16px;
} }
.file-tile.file-tile--small { .file-tile__title {
}
.file-tile--small {
padding-top: $spacing-vertical * 2/3; padding-top: $spacing-vertical * 2/3;
.card__media { .card__media {
@ -49,7 +56,7 @@
} }
} }
.file-tile.file-tile--large { .file-tile--large {
.card__media { .card__media {
height: var(--file-tile-media-height-large); height: var(--file-tile-media-height-large);
flex: 0 0 var(--file-tile-media-width-large); flex: 0 0 var(--file-tile-media-width-large);

View file

@ -0,0 +1,6 @@
// Icons with icons directly following should have a margin-right for proper spacing
// Same for prices on cards
.icon + .icon,
.credit-amount + .icon {
margin-left: $spacing-vertical * 1/3;
}

View file

@ -39,7 +39,6 @@
/* Paragraphs */ /* Paragraphs */
p { p {
margin: $spacing-vertical * 2/3 0;
white-space: pre-line; white-space: pre-line;
} }