mobile view

This commit is contained in:
Sean Yesmunt 2019-12-18 00:27:08 -05:00
parent 3709ec8fc6
commit 86cfa746de
42 changed files with 891 additions and 453 deletions

View file

@ -2,6 +2,7 @@
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="ui.js" async></script>
<link rel="stylesheet" href="font/font.css" />
<title>LBRY</title>

View file

@ -2,6 +2,7 @@
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="/public/ui.js" async></script>
<link rel="icon" type="image/png" href="/public/favicon.png" />

View file

@ -202,36 +202,30 @@ const ClaimPreview = forwardRef<any, {}>((props: Props, ref: any) => {
) : (
<CardMedia thumbnail={thumbnail} />
)}
<div className="claim-preview-metadata">
<div className="claim-preview-info">
<div className="claim-preview-title">
{claim ? <TruncatedText text={title || claim.name} lines={1} /> : <span>{__('Nothing here')}</span>}
<div className="claim-preview__text">
<div className="claim-preview-metadata">
<div className="claim-preview-info">
<div className="claim-preview-title">
{claim ? <TruncatedText text={title || claim.name} lines={2} /> : <span>{__('Nothing here')}</span>}
</div>
{!isChannel && claim && <FileProperties uri={uri} />}
</div>
{!pending && (
<React.Fragment>
{hideActions ? null : actions !== undefined ? (
actions
) : (
<div className="card__actions--inline">
{isChannel && !channelIsBlocked && !claimIsMine && (
<SubscribeButton uri={uri.startsWith('lbry://') ? uri : `lbry://${uri}`} />
)}
{!hideBlock && isChannel && !isSubscribed && !claimIsMine && (
<BlockButton uri={uri.startsWith('lbry://') ? uri : `lbry://${uri}`} />
)}
{!isChannel && claim && <FileProperties uri={uri} />}
</div>
)}
</React.Fragment>
)}
</div>
<div className="claim-preview-properties">
<div className="media__subtitle">
{!isResolvingUri && (
<div>
{claim ? (
<UriIndicator uri={uri} link addTooltip={includeChannelTooltip} />
<React.Fragment>
<UriIndicator uri={uri} link addTooltip={includeChannelTooltip} />{' '}
{pending
? __('Pending...')
: claim &&
(isChannel ? (
type !== 'inline' && `${claimsInChannel} ${__('publishes')}`
) : (
<DateTime timeAgo uri={uri} />
))}
</React.Fragment>
) : (
<Fragment>
<div>{__('Publish something and claim this spot!')}</div>
@ -244,21 +238,27 @@ const ClaimPreview = forwardRef<any, {}>((props: Props, ref: any) => {
</div>
</Fragment>
)}
<div>
{pending ? (
<div>{__('Pending...')}</div>
) : (
claim &&
(isChannel ? (
type !== 'inline' && `${claimsInChannel} ${__('publishes')}`
) : (
<DateTime timeAgo uri={uri} />
))
)}
</div>
</div>
)}
</div>
</div>
<div className="claim-preview__actions">
{!pending && (
<React.Fragment>
{hideActions ? null : actions !== undefined ? (
actions
) : (
<div className="card__actions--inline">
{isChannel && !channelIsBlocked && !claimIsMine && (
<SubscribeButton uri={uri.startsWith('lbry://') ? uri : `lbry://${uri}`} />
)}
{!hideBlock && isChannel && !isSubscribed && !claimIsMine && (
<BlockButton uri={uri.startsWith('lbry://') ? uri : `lbry://${uri}`} />
)}
</div>
)}
</React.Fragment>
)}
{properties !== undefined ? properties : <ClaimTags uri={uri} type={type} />}
</div>
</div>

View file

@ -322,4 +322,11 @@ export const icons = {
<path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z" />
</g>
),
[ICONS.MENU]: buildIcon(
<g>
<line x1="3" y1="12" x2="21" y2="12" />
<line x1="3" y1="6" x2="21" y2="6" />
<line x1="3" y1="18" x2="21" y2="18" />
</g>
),
};

View file

@ -12,6 +12,7 @@ import { FILE_WRAPPER_CLASS } from 'page/file/view';
import Draggable from 'react-draggable';
import Tooltip from 'component/common/tooltip';
import { onFullscreenChange } from 'util/full-screen';
import useIsMobile from 'effects/use-is-mobile';
type Props = {
mediaType: string,
@ -50,6 +51,7 @@ export default function FileViewer(props: Props) {
mediaType,
contentType,
} = props;
const isMobile = useIsMobile();
const [playTime, setPlayTime] = useState();
const [fileViewerRect, setFileViewerRect] = usePersistedState('inline-file-viewer:rect');
const [position, setPosition] = usePersistedState('floating-file-viewer:position', {
@ -125,7 +127,7 @@ export default function FileViewer(props: Props) {
}
const hidePlayer =
!isPlaying || !uri || (!inline && (!floatingPlayerEnabled || !['audio', 'video'].includes(mediaType)));
!isPlaying || !uri || (!inline && (isMobile || !floatingPlayerEnabled || !['audio', 'video'].includes(mediaType)));
if (hidePlayer) {
return null;

View file

@ -1,9 +1,10 @@
import * as SETTINGS from 'constants/settings';
import * as MODALS from 'constants/modal_types';
import { connect } from 'react-redux';
import { selectBalance, formatCredits } from 'lbry-redux';
import { selectUserVerifiedEmail, selectGetSyncErrorMessage } from 'lbryinc';
import { doSetClientSetting } from 'redux/actions/settings';
import { doSignOut } from 'redux/actions/app';
import { doSignOut, doOpenModal } from 'redux/actions/app';
import { makeSelectClientSetting } from 'redux/selectors/settings';
import Header from './view';
@ -21,6 +22,7 @@ const select = state => ({
const perform = dispatch => ({
setClientSetting: (key, value) => dispatch(doSetClientSetting(key, value)),
signOut: () => dispatch(doSignOut()),
openMobileNavigation: () => dispatch(doOpenModal(MODALS.MOBILE_NAVIGATION)),
});
export default connect(

View file

@ -27,6 +27,7 @@ type Props = {
authHeader: boolean,
syncError: ?string,
signOut: () => void,
openMobileNavigation: () => void,
};
const Header = (props: Props) => {
@ -41,6 +42,7 @@ const Header = (props: Props) => {
authHeader,
signOut,
syncError,
openMobileNavigation,
} = props;
const authenticated = Boolean(email);
@ -201,6 +203,16 @@ const Header = (props: Props) => {
</div>
)
)}
{!authenticated && (
<Button
button="primary"
label={__('Sign In')}
className="header__menu--mobile"
onClick={() => history.push(`/$/${PAGES.AUTH}`)}
/>
)}
<Button onClick={openMobileNavigation} icon={ICONS.MENU} iconSize={24} className="header__menu--mobile" />
</div>
</header>
);

View file

@ -53,36 +53,38 @@ class InviteList extends React.PureComponent<Props> {
</div>
</div>
<table className="table section">
<thead>
<tr>
<th>{__('Invitee Email')}</th>
<th>{__('Invite Status')}</th>
<th>{__('Reward')}</th>
</tr>
</thead>
<tbody>
{invitees.map(invitee => (
<tr key={invitee.email}>
<td>{invitee.email}</td>
<td>
<span>{invitee.invite_accepted ? __('Accepted') : __('Not Accepted')}</span>
</td>
<td>
{invitee.invite_reward_claimed && (
<React.Fragment>
<span>{__('Claimed')}</span>
<Icon icon={ICONS.COMPLETE} />
</React.Fragment>
)}
{!invitee.invite_reward_claimed &&
(invitee.invite_reward_claimable ? <span>{__('Claimable')}</span> : __('Unclaimable'))}
</td>
<div className="table__wrapper">
<table className="table section">
<thead>
<tr>
<th>{__('Invitee Email')}</th>
<th>{__('Invite Status')}</th>
<th>{__('Reward')}</th>
</tr>
))}
</tbody>
</table>
</thead>
<tbody>
{invitees.map(invitee => (
<tr key={invitee.email}>
<td>{invitee.email}</td>
<td>
<span>{invitee.invite_accepted ? __('Accepted') : __('Not Accepted')}</span>
</td>
<td>
{invitee.invite_reward_claimed && (
<React.Fragment>
<span>{__('Claimed')}</span>
<Icon icon={ICONS.COMPLETE} />
</React.Fragment>
)}
{!invitee.invite_reward_claimed &&
(invitee.invite_reward_claimable ? <span>{__('Claimable')}</span> : __('Unclaimable'))}
</td>
</tr>
))}
</tbody>
</table>
</div>
</section>
);
}

View file

@ -2,7 +2,7 @@
import type { Node } from 'react';
import React, { Fragment } from 'react';
import classnames from 'classnames';
import SideBar from 'component/sideBar';
import SideNavigation from 'component/sideNavigation';
import Header from 'component/header';
export const MAIN_CLASS = 'main';
@ -24,7 +24,7 @@ function Page(props: Props) {
<Header authHeader={authPage} />
<div className={classnames('main-wrapper__inner')}>
<main className={classnames(MAIN_CLASS, className, { 'main--full-width': authPage })}>{children}</main>
{!authPage && <SideBar obscureSideBar={obscureSideBar} />}
{!authPage && <SideNavigation obscureSideBar={obscureSideBar} />}
</div>
</Fragment>
);

View file

@ -37,26 +37,28 @@ const RewardListClaimed = (props: Props) => {
</div>
</header>
<table className="table table--rewards">
<thead>
<tr>
<th>{__('Title')}</th>
<th>{__('Amount')}</th>
<th>{__('Transaction')}</th>
<th>{__('Date')}</th>
</tr>
</thead>
<tbody>
{rewards.reverse().map(reward => (
<tr key={reward.id}>
<td>{reward.reward_title}</td>
<td>{reward.reward_amount}</td>
<td>{reward.transaction_id && <ButtonTransaction id={reward.transaction_id} />}</td>
<td>{moment(reward.created_at).format('LLL')}</td>
<div className="table__wrapper">
<table className="table table--rewards">
<thead>
<tr>
<th>{__('Title')}</th>
<th>{__('Amount')}</th>
<th>{__('Transaction')}</th>
<th>{__('Date')}</th>
</tr>
))}
</tbody>
</table>
</thead>
<tbody>
{rewards.reverse().map(reward => (
<tr key={reward.id}>
<td>{reward.reward_title}</td>
<td>{reward.reward_amount}</td>
<td>{reward.transaction_id && <ButtonTransaction id={reward.transaction_id} />}</td>
<td>{moment(reward.created_at).format('LLL')}</td>
</tr>
))}
</tbody>
</table>
</div>
</section>
);
};

View file

@ -2,21 +2,22 @@ import * as SETTINGS from 'constants/settings';
import { connect } from 'react-redux';
import { selectSubscriptions } from 'redux/selectors/subscriptions';
import { selectFollowedTags } from 'lbry-redux';
import { selectUserEmail, selectUploadCount } from 'lbryinc';
import SideBar from './view';
import { selectUploadCount, selectUserVerifiedEmail } from 'lbryinc';
import { makeSelectClientSetting } from 'redux/selectors/settings';
import { doSignOut } from 'redux/actions/app';
import SideNavigation from './view';
const select = state => ({
subscriptions: selectSubscriptions(state),
followedTags: selectFollowedTags(state),
language: makeSelectClientSetting(SETTINGS.LANGUAGE)(state), // trigger redraw on language change
email: selectUserEmail(state),
uploadCount: selectUploadCount(state),
email: selectUserVerifiedEmail(state),
});
const perform = () => ({});
export default connect(
select,
perform
)(SideBar);
{
doSignOut,
}
)(SideNavigation);

View file

@ -13,30 +13,53 @@ type Props = {
email: ?string,
obscureSideBar: boolean,
uploadCount: number,
sticky: boolean,
showAllLinks: boolean,
doSignOut: () => void,
};
function SideBar(props: Props) {
const { subscriptions, followedTags, obscureSideBar, uploadCount } = props;
function buildLink(path, label, icon, guide) {
const {
subscriptions,
followedTags,
obscureSideBar,
uploadCount,
doSignOut,
email,
sticky = true,
showAllLinks = false,
} = props;
const isAuthenticated = Boolean(email);
function buildLink(path, label, icon, onClick) {
return {
navigate: path ? `$/${path}` : '/',
label,
icon,
guide,
onClick,
};
}
const Wrapper = ({ children }: any) =>
sticky ? (
<StickyBox offsetTop={100} offsetBottom={20}>
{children}
</StickyBox>
) : (
<div>{children}</div>
);
return obscureSideBar ? (
<StickyBox offsetTop={100} offsetBottom={20}>
<Wrapper>
<div className="card navigation--placeholder">
<div className="wrap">
<h2>LBRY</h2>
<p>{__('The best decentralized content platform on the web.')}</p>
</div>
</div>
</StickyBox>
</Wrapper>
) : (
<StickyBox offsetTop={100} offsetBottom={20}>
<Wrapper>
<nav className="navigation">
<ul className="navigation-links">
{[
@ -70,15 +93,47 @@ function SideBar(props: Props) {
<Button {...linkProps} className="navigation-link" activeClass="navigation-link--active" />
</li>
))}
{showAllLinks &&
[
{
...buildLink(PAGES.WALLET, __('Wallet'), ICONS.WALLET),
},
{
...buildLink(PAGES.REWARDS, __('Rewards'), ICONS.FEATURED),
},
{
...buildLink(PAGES.ACCOUNT, __('Overview'), ICONS.OVERVIEW),
},
{
...buildLink(PAGES.PUBLISH, __('Publish'), ICONS.PUBLISH),
},
{
...buildLink(PAGES.SETTINGS, __('Settings'), ICONS.SETTINGS),
},
{
...buildLink(PAGES.HELP, __('Help'), ICONS.HELP),
},
{
...(isAuthenticated ? { ...buildLink(PAGES.AUTH, __('Sign Out'), ICONS.SIGN_OUT, doSignOut) } : {}),
},
].map(linkProps => (
<li key={linkProps.navigate}>
<Button {...linkProps} className="navigation-link" activeClass="navigation-link--active" />
</li>
))}
<li>
<Button
navigate={`/$/${PAGES.FOLLOWING}`}
label={__('Customize')}
icon={ICONS.EDIT}
className="navigation-link"
activeClass="navigation-link--active"
/>
</li>
</ul>
<Button
navigate={`/$/${PAGES.FOLLOWING}`}
label={__('Customize')}
icon={ICONS.EDIT}
className="navigation-link"
activeClass="navigation-link--active"
/>
<section className="navigation-links__inline">
<ul className="navigation-links--small tags--vertical">
{followedTags.map(({ name }, key) => (
@ -101,7 +156,7 @@ function SideBar(props: Props) {
</ul>
</section>
</nav>
</StickyBox>
</Wrapper>
);
}

View file

@ -32,7 +32,7 @@ function TransactionListTable(props: Props) {
<h2 className="main--empty empty">{emptyMessage || __('No transactions.')}</h2>
)}
{!!transactionList.length && (
<React.Fragment>
<div className="table__wrapper">
<table className="table table--transactions">
<thead>
<tr>
@ -55,7 +55,7 @@ function TransactionListTable(props: Props) {
))}
</tbody>
</table>
</React.Fragment>
</div>
)}
</React.Fragment>
);

View file

@ -33,3 +33,4 @@ export const WALLET_SEND = 'wallet_send';
export const WALLET_RECEIVE = 'wallet_receive';
export const CREATE_CHANNEL = 'create_channel';
export const YOUTUBE_WELCOME = 'youtube_welcome';
export const MOBILE_NAVIGATION = 'mobile_navigation';

View file

@ -0,0 +1,6 @@
import useMedia from './use-media';
export default function useIsMobile() {
const isMobile = useMedia(['(min-width: 901px)'], [false], true);
return isMobile;
}

34
ui/effects/use-media.js Normal file
View file

@ -0,0 +1,34 @@
import { useState, useEffect } from 'react';
// https://usehooks.com/useMedia/
export default function useMedia(queries, values, defaultValue) {
// Array containing a media query list for each query
const mediaQueryLists = queries.map(q => window.matchMedia(q));
// Function that gets value based on matching media query
const getValue = () => {
// Get index of first media query that matches
const index = mediaQueryLists.findIndex(mql => mql.matches);
// Return related value or defaultValue if none
return typeof values[index] !== 'undefined' ? values[index] : defaultValue;
};
// State and setter for matched value
const [value, setValue] = useState(getValue);
useEffect(
() => {
// Event listener callback
// Note: By defining getValue outside of useEffect we ensure that it has ...
// ... current values of hook args (as this hook callback is created once on mount).
const handler = () => setValue(getValue);
// Set a listener for each media query with above handler as callback.
mediaQueryLists.forEach(mql => mql.addListener(handler));
// Remove listeners on cleanup
return () => mediaQueryLists.forEach(mql => mql.removeListener(handler));
},
[] // Empty array ensures effect is only run on mount and unmount
);
return value;
}

View file

@ -57,7 +57,7 @@ export class Modal extends React.PureComponent<ModalProps> {
overlayClassName="modal-overlay"
>
{title && <h1 className="card__title card__title--deprecated">{title}</h1>}
{type === 'card' && <Button button="close" icon={ICONS.REMOVE} onClick={onAborted} />}
{type === 'card' && <Button iconSize={24} button="close" icon={ICONS.REMOVE} onClick={onAborted} />}
{children}
{type === 'custom' || type === 'card' ? null : ( // custom modals define their own buttons
<div className="card__actions">

View file

@ -0,0 +1,11 @@
import { connect } from 'react-redux';
import { doHideModal, doSignOut } from 'redux/actions/app';
import ModalMobileNavigation from './view';
export default connect(
null,
{
doHideModal,
doSignOut,
}
)(ModalMobileNavigation);

View file

@ -0,0 +1,18 @@
// @flow
import React from 'react';
import { Modal } from 'modal/modal';
import SideNavigation from 'component/sideNavigation';
type Props = {
doHideModal: () => void,
};
export default function ModalMobileNavigation(props: Props) {
const { doHideModal } = props;
return (
<Modal type="card" isOpen contentLabel={__('Navigation')} onAborted={doHideModal}>
<SideNavigation sticky={false} showAllLinks />
</Modal>
);
}

View file

@ -1,6 +1,6 @@
import { connect } from 'react-redux';
import { selectModal } from 'redux/selectors/app';
import { doOpenModal } from 'redux/actions/app';
import { doOpenModal, doHideModal } from 'redux/actions/app';
import { selectError } from 'lbry-redux';
import ModalRouter from './view';
@ -11,6 +11,7 @@ const select = (state, props) => ({
const perform = dispatch => ({
openModal: props => dispatch(doOpenModal(props)),
hideModal: props => dispatch(doHideModal(props)),
});
export default connect(

View file

@ -1,5 +1,6 @@
// @flow
import React from 'react';
import { withRouter } from 'react-router';
import * as MODALS from 'constants/modal_types';
import ModalError from 'modal/modalError';
import ModalDownloading from 'modal/modalDownloading';
@ -31,14 +32,22 @@ import ModalWalletSend from 'modal/modalWalletSend';
import ModalWalletReceive from 'modal/modalWalletReceive';
import ModalYoutubeWelcome from 'modal/modalYoutubeWelcome';
import ModalCreateChannel from 'modal/modalChannelCreate';
import ModalMobileNavigation from 'modal/modalMobileNavigation';
type Props = {
modal: { id: string, modalProps: {} },
error: { message: string },
location: { pathname: string },
hideModal: () => void,
};
function ModalRouter(props: Props) {
const { modal, error } = props;
const { modal, error, location, hideModal } = props;
const { pathname } = location;
React.useEffect(() => {
hideModal();
}, [pathname, hideModal]);
if (error) {
return <ModalError {...error} />;
@ -111,9 +120,11 @@ function ModalRouter(props: Props) {
return <ModalYoutubeWelcome />;
case MODALS.CREATE_CHANNEL:
return <ModalCreateChannel {...modalProps} />;
case MODALS.MOBILE_NAVIGATION:
return <ModalMobileNavigation {...modalProps} />;
default:
return null;
}
}
export default ModalRouter;
export default withRouter(ModalRouter);

View file

@ -210,66 +210,68 @@ class HelpPage extends React.PureComponent<Props, State> {
</div>
</header>
<table className="table table--stretch">
<tbody>
<tr>
<td>{__('App')}</td>
<td>{this.state.uiVersion}</td>
</tr>
<tr>
<td>{__('Daemon (lbrynet)')}</td>
<td>{ver ? ver.lbrynet_version : __('Loading...')}</td>
</tr>
<tr>
<td>{__('Connected Email')}</td>
<td>
{user && user.primary_email ? (
<React.Fragment>
{user.primary_email}{' '}
<Button
button="link"
href={`https://lbry.com/list/edit/${accessToken}`}
label={__('Update mailing preferences')}
/>
</React.Fragment>
) : (
<React.Fragment>
<span className="empty">{__('none')} </span>
<Button button="link" onClick={() => doAuth()} label={__('set email')} />
</React.Fragment>
)}
</td>
</tr>
<tr>
<td>{__('Reward Eligible')}</td>
<td>{user && user.is_reward_approved ? __('Yes') : __('No')}</td>
</tr>
<tr>
<td>{__('Platform')}</td>
<td>{platform}</td>
</tr>
<tr>
<td>{__('Installation ID')}</td>
<td>{this.state.lbryId}</td>
</tr>
<tr>
<td>{__('Access Token')}</td>
<td>
{this.state.accessTokenHidden && (
<Button button="link" label={__('View')} onClick={this.showAccessToken} />
)}
{!this.state.accessTokenHidden && accessToken && (
<div>
<p>{accessToken}</p>
<div className="help--warning">
{__('This is equivalent to a password. Do not post or share this.')}
<div className="table__wrapper">
<table className="table table--stretch">
<tbody>
<tr>
<td>{__('App')}</td>
<td>{this.state.uiVersion}</td>
</tr>
<tr>
<td>{__('Daemon (lbrynet)')}</td>
<td>{ver ? ver.lbrynet_version : __('Loading...')}</td>
</tr>
<tr>
<td>{__('Connected Email')}</td>
<td>
{user && user.primary_email ? (
<React.Fragment>
{user.primary_email}{' '}
<Button
button="link"
href={`https://lbry.com/list/edit/${accessToken}`}
label={__('Update mailing preferences')}
/>
</React.Fragment>
) : (
<React.Fragment>
<span className="empty">{__('none')} </span>
<Button button="link" onClick={() => doAuth()} label={__('set email')} />
</React.Fragment>
)}
</td>
</tr>
<tr>
<td>{__('Reward Eligible')}</td>
<td>{user && user.is_reward_approved ? __('Yes') : __('No')}</td>
</tr>
<tr>
<td>{__('Platform')}</td>
<td>{platform}</td>
</tr>
<tr>
<td>{__('Installation ID')}</td>
<td>{this.state.lbryId}</td>
</tr>
<tr>
<td>{__('Access Token')}</td>
<td>
{this.state.accessTokenHidden && (
<Button button="link" label={__('View')} onClick={this.showAccessToken} />
)}
{!this.state.accessTokenHidden && accessToken && (
<div>
<p>{accessToken}</p>
<div className="help--warning">
{__('This is equivalent to a password. Do not post or share this.')}
</div>
</div>
</div>
)}
</td>
</tr>
</tbody>
</table>
)}
</td>
</tr>
</tbody>
</table>
</div>
</section>
</Page>
);

View file

@ -32,6 +32,10 @@
color: var(--color-button-primary-text);
background-color: var(--color-button-primary-bg);
}
@media (max-width: $breakpoint-small) {
padding: var(--spacing-medium) var(--spacing-small);
}
}
.button--download-link {

View file

@ -5,6 +5,10 @@
border-radius: var(--card-radius);
box-shadow: var(--card-box-shadow) var(--color-box-shadow);
overflow: hidden;
@media (max-width: $breakpoint-small) {
margin-bottom: var(--spacing-medium);
}
}
.card--disabled {
@ -72,12 +76,19 @@
.card__list {
column-count: 2;
column-gap: var(--spacing-medium);
column-gap: var(--spacing-large);
display: block;
.card {
display: inline-block;
margin: 0 0 var(--spacing-medium);
margin: 0 0 var(--spacing-large);
}
@media (max-width: $breakpoint-small) {
column-count: 1;
.card {
display: block;
}
}
}

View file

@ -2,6 +2,7 @@ $cover-z-index: 0;
$metadata-z-index: 1;
.channel-cover {
position: relative;
background-image: linear-gradient(to right, #637ad2, #318794 80%);
display: flex;
align-items: flex-end;
@ -49,6 +50,10 @@ $metadata-z-index: 1;
box-shadow: 0px 8px 40px -3px #000;
left: var(--spacing-medium);
top: 4rem;
@media (max-width: $breakpoint-small) {
display: none;
}
}
.channel-thumbnail__custom {
@ -99,6 +104,10 @@ $metadata-z-index: 1;
padding-bottom: var(--spacing-medium);
min-width: 0;
width: 100%;
@media (max-width: $breakpoint-small) {
padding-left: var(--spacing-medium);
}
}
.channel__title {

View file

@ -34,6 +34,12 @@
margin-bottom: 0;
padding: 0 var(--spacing-medium);
padding-right: var(--spacing-large);
@media (max-width: $breakpoint-small) {
font-size: var(--font-small);
padding: 0 var(--spacing-small);
padding-right: var(--spacing-large);
}
}
.claim-list__conjuction {
@ -49,6 +55,10 @@
& > * {
margin-left: var(--spacing-small);
}
@media (max-width: $breakpoint-small) {
display: none;
}
}
.claim-preview {
@ -67,6 +77,17 @@
flex-shrink: 0;
margin-right: var(--spacing-medium);
}
@media (max-width: $breakpoint-small) {
.media__thumb {
position: absolute;
z-index: 0;
opacity: 0.1;
right: 0;
top: var(--spacing-small);
bottom: var(--spacing-small);
}
}
}
.claim-preview--large {
@ -118,6 +139,27 @@
width: var(--channel-thumbnail-width--small);
height: var(--channel-thumbnail-width--small);
}
.claim-preview__actions {
align-self: flex-end;
margin-top: 0;
margin-bottom: auto;
justify-content: flex-end;
width: auto;
}
.claim-preview__text {
width: 100%;
flex-direction: row;
justify-content: space-between;
}
}
.claim-preview__text {
width: 100%;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.claim-preview-title {
@ -145,10 +187,14 @@
justify-content: space-between;
}
.claim-preview-actions {
.claim-preview__actions {
align-self: flex-end;
display: flex;
justify-content: space-evenly;
justify-content: space-between;
margin-top: auto;
width: 100%;
}
.claim-preview__button {
margin-left: 2rem;
}

View file

@ -13,7 +13,7 @@
margin-right: var(--spacing-small);
}
@media (max-width: 600px) {
@media (max-width: $breakpoint-xsmall) {
display: none;
}
}

View file

@ -121,6 +121,11 @@ fieldset-group {
margin-bottom: var(--spacing-small);
}
.form-field__help + .checkbox,
.form-field__help + .radio {
margin-top: var(--spacing-large);
}
.form-field__conjuction {
padding-top: 1rem;
}

View file

@ -34,22 +34,19 @@
max-width: var(--page-max-width);
height: calc(var(--header-height) - 1px);
display: flex;
align-items: center;
margin: auto;
padding: 0 var(--spacing-large);
@media (max-width: $breakpoint-small) {
padding: var(--spacing-small);
}
}
.header__navigation {
flex: 1;
display: flex;
align-items: center;
&:last-of-type {
width: var(--side-nav-width);
@media (max-width: 600px) {
display: none;
}
}
}
.header__menu {
@ -61,6 +58,23 @@
> .button:only-child {
margin-left: auto;
}
@media (max-width: $breakpoint-small) {
display: none;
}
}
.header__menu--mobile {
display: none;
@media (max-width: $breakpoint-small) {
display: block;
margin-left: var(--spacing-medium);
svg {
stroke: var(--color-text);
}
}
}
.header__menu--with-balance {
@ -111,17 +125,3 @@
width: 2rem;
}
}
.header__navigation-item--right-action {
align-self: flex-end;
margin-left: auto;
padding: 0 var(--spacing-small);
}
@media (max-width: 600px) {
.header__navigation-item--back,
.header__navigation-item--forward,
.header__navigation-item--right-action {
display: none;
}
}

View file

@ -16,6 +16,10 @@
margin-right: auto;
margin-top: var(--header-height);
padding: var(--spacing-large);
@media (max-width: $breakpoint-small) {
padding: var(--spacing-small);
}
}
.main {
@ -23,7 +27,7 @@
width: calc(100% - var(--side-nav-width) - var(--spacing-large));
margin-right: var(--spacing-main-padding);
@media (max-width: 600px) {
@media (max-width: $breakpoint-small) {
width: 100%;
margin-right: 0;
margin-left: 0;
@ -45,6 +49,14 @@
.grid-area--related {
width: calc(47.5% - var(--spacing-large));
}
@media (max-width: $breakpoint-small) {
.grid-area--related,
.grid-area--info {
margin-right: 0;
width: 100%;
}
}
}
.main--auth-page {

View file

@ -38,6 +38,11 @@
transform: translateY(-130%);
font-size: var(--font-xsmall);
color: var(--color-text-subtitle);
@media (max-width: $breakpoint-small) {
position: static;
transform: none;
}
}
.media__uri--inline {

View file

@ -24,8 +24,25 @@
box-shadow: none;
}
@media (min-width: 501px) {
min-width: 500px;
@media (max-width: $breakpoint-small) {
width: 100%;
height: 100%;
margin-bottom: 0;
border-radius: 0;
.navigation {
width: 100%;
display: block;
padding: var(--spacing-large);
.navigation-links:not(.navigation-links--small) {
.navigation-link {
font-size: var(--font-large);
border-bottom: 1px solid var(--color-gray-3);
padding: var(--spacing-medium) 0;
}
}
}
}
}

View file

@ -2,7 +2,7 @@
width: var(--side-nav-width);
font-size: var(--font-body);
@media (max-width: 600px) {
@media (max-width: $breakpoint-small) {
display: none;
}
}

View file

@ -1,3 +1,7 @@
.table__wrapper {
overflow-x: auto;
}
.table__header {
display: flex;
justify-content: space-between;
@ -17,6 +21,10 @@
@extend .table__header-text;
display: flex;
justify-content: space-between;
@media (max-width: $breakpoint-small) {
flex-wrap: wrap;
}
}
.table--help {

View file

@ -8,10 +8,6 @@
z-index: 1;
font-size: var(--font-small);
@media (max-width: 600px) {
margin-right: 0;
}
> .icon {
top: 0;
left: var(--spacing-small);
@ -30,6 +26,10 @@
fieldset-section {
width: 15rem;
}
@media (max-width: $breakpoint-small) {
display: none;
}
}
.wunderbar__active-suggestion {

View file

@ -10,6 +10,10 @@
.yrbl {
height: 20rem;
margin-right: var(--spacing-large);
@media (max-width: $breakpoint-small) {
height: 10rem;
}
}
.yrbl__content {

View file

@ -55,6 +55,10 @@
display: inline-block;
font-weight: var(--font-weight-bold);
font-size: var(--font-heading);
@media (max-width: $breakpoint-small) {
font-size: var(--font-title);
}
}
.section__subtitle--status {
@ -87,3 +91,13 @@
.section__body {
margin-top: var(--spacing-medium);
}
@media (max-width: $breakpoint-small) {
.section__actions {
flex-wrap: wrap;
.button {
margin-bottom: var(--spacing-small);
}
}
}

View file

@ -18,6 +18,10 @@
padding-left: calc(var(--channel-thumbnail-width) + var(--spacing-large));
padding-right: var(--spacing-medium);
height: 4rem;
@media (max-width: $breakpoint-small) {
padding-left: var(--spacing-medium);
}
}
.tab {

View file

@ -133,6 +133,19 @@ a {
margin-right: 1.5rem;
}
}
@media (max-width: $breakpoint-small) {
flex-direction: column;
& > * {
margin: 0;
width: 100%;
&:first-child {
margin-right: 0;
}
}
}
}
.hidden {

View file

@ -2,8 +2,8 @@
$spacing-vertical: 2rem;
$spacing-width: 36px;
$medium-breakpoint: 1279px;
$large-breakpoint: 1921px;
$breakpoint-xsmall: 600px;
$breakpoint-small: 900px;
:root {
// Width & spacing
@ -62,3 +62,9 @@ $large-breakpoint: 1921px;
--tag-height: 1.5rem;
}
@media (max-width: $breakpoint-small) {
:root {
--font-base: 16px;
}
}

View file

@ -134,11 +134,11 @@ var Konami = function(callback) {
konami.removeEvent(document, 'touchstart', this.touchstartHandler);
},
check_direction: function() {
x_magnitude = Math.abs(this.start_x - this.stop_x);
y_magnitude = Math.abs(this.start_y - this.stop_y);
x = this.start_x - this.stop_x < 0 ? 'RIGHT' : 'LEFT';
y = this.start_y - this.stop_y < 0 ? 'DOWN' : 'UP';
result = x_magnitude > y_magnitude ? x : y;
var x_magnitude = Math.abs(this.start_x - this.stop_x);
var y_magnitude = Math.abs(this.start_y - this.stop_y);
var x = this.start_x - this.stop_x < 0 ? 'RIGHT' : 'LEFT';
var y = this.start_y - this.stop_y < 0 ? 'DOWN' : 'UP';
var result = x_magnitude > y_magnitude ? x : y;
result = this.tap === true ? 'TAP' : result;
return result;
},

585
yarn.lock

File diff suppressed because it is too large Load diff