Merge pull request #149 from Stremio/placeholders

Video/Stream placeholders
This commit is contained in:
Nikola Hristov 2020-04-02 17:45:12 +03:00 committed by GitHub
commit 5e59cd3e7b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 216 additions and 159 deletions

View file

@ -0,0 +1,33 @@
const React = require('react');
const PropTypes = require('prop-types');
const classnames = require('classnames');
const Icon = require('stremio-icons/dom');
const TextInput = require('stremio/common/TextInput');
const SearchBarPlaceholder = require('./SearchBarPlaceholder');
const styles = require('./styles');
const SearchBar = ({ className, title, value, onChange }) => {
return (
<label title={title} className={classnames(className, styles['search-bar-container'])}>
<TextInput
className={styles['search-input']}
type={'text'}
placeholder={title}
value={value}
onChange={onChange}
/>
<Icon className={styles['icon']} icon={'ic_search'} />
</label>
);
};
SearchBar.Placeholder = SearchBarPlaceholder;
SearchBar.propTypes = {
className: PropTypes.string,
title: PropTypes.string,
value: PropTypes.string,
onChange: PropTypes.func
};
module.exports = SearchBar;

View file

@ -0,0 +1,21 @@
const React = require('react');
const PropTypes = require('prop-types');
const classnames = require('classnames');
const Icon = require('stremio-icons/dom');
const styles = require('./styles');
const SearchBarPlaceholder = ({ className, title }) => {
return (
<div className={classnames(className, styles['search-bar-container'])}>
<div className={styles['search-input']}>{title}</div>
<Icon className={styles['icon']} icon={'ic_search'} />
</div>
);
};
SearchBarPlaceholder.propTypes = {
className: PropTypes.string,
title: PropTypes.string
};
module.exports = SearchBarPlaceholder;

View file

@ -0,0 +1,3 @@
const SearchBarPlaceholder = require('./SearchBarPlaceholder');
module.exports = SearchBarPlaceholder;

View file

@ -0,0 +1,25 @@
.search-bar-container {
display: flex;
flex-direction: row;
align-items: center;
height: 3.5rem;
padding: 0 1rem;
border-radius: 3.5rem;
border: var(--focus-outline-size) solid transparent;
background-color: var(--color-placeholder-background);
.search-input {
flex: 1;
max-height: 1.2em;
margin-right: 1rem;
font-size: 1.1rem;
color: var(--color-placeholder-text);
}
.icon {
flex: none;
width: 1.5rem;
height: 1.5rem;
fill: var(--color-placeholder-background);
}
}

View file

@ -0,0 +1,3 @@
const SearchBar = require('./SearchBar');
module.exports = SearchBar;

View file

@ -0,0 +1,41 @@
@import (reference) '~stremio-colors/dist/less/stremio-colors.less';
.search-bar-container {
display: flex;
flex-direction: row;
align-items: center;
height: 3.5rem;
padding: 0 1rem;
border-radius: 3.5rem;
border: var(--focus-outline-size) solid transparent;
background-color: @color-background;
cursor: text;
&:hover, &:focus-within {
background-color: @color-background-light1;
}
&:focus-within {
border: var(--focus-outline-size) solid @color-surface-light5;
}
.search-input {
flex: 1;
margin-right: 1rem;
font-size: 1.1rem;
color: @color-surface-light5;
&::placeholder {
max-height: 1.2em;
opacity: 1;
color: @color-secondaryvariant1-light1-90;
}
}
.icon {
flex: none;
width: 1.5rem;
height: 1.5rem;
fill: @color-secondaryvariant1-90;
}
}

View file

@ -14,6 +14,7 @@ const { HorizontalNavBar, VerticalNavBar } = require('./NavBar');
const PaginationInput = require('./PaginationInput'); const PaginationInput = require('./PaginationInput');
const PlayIconCircleCentered = require('./PlayIconCircleCentered'); const PlayIconCircleCentered = require('./PlayIconCircleCentered');
const Popup = require('./Popup'); const Popup = require('./Popup');
const SearchBar = require('./SearchBar');
const SharePrompt = require('./SharePrompt'); const SharePrompt = require('./SharePrompt');
const Slider = require('./Slider'); const Slider = require('./Slider');
const TextInput = require('./TextInput'); const TextInput = require('./TextInput');
@ -51,6 +52,7 @@ module.exports = {
PaginationInput, PaginationInput,
PlayIconCircleCentered, PlayIconCircleCentered,
Popup, Popup,
SearchBar,
SharePrompt, SharePrompt,
Slider, Slider,
TextInput, TextInput,

View file

@ -2,7 +2,7 @@ const React = require('react');
const PropTypes = require('prop-types'); const PropTypes = require('prop-types');
const { useRouteFocused } = require('stremio-router'); const { useRouteFocused } = require('stremio-router');
const Icon = require('stremio-icons/dom'); const Icon = require('stremio-icons/dom');
const { AddonDetailsModal, Button, Image, Multiselect, MainNavBars, TextInput, SharePrompt, ModalDialog, useBinaryState } = require('stremio/common'); const { AddonDetailsModal, Button, Image, Multiselect, MainNavBars, TextInput, SearchBar, SharePrompt, ModalDialog, useBinaryState } = require('stremio/common');
const Addon = require('./Addon'); const Addon = require('./Addon');
const useAddons = require('./useAddons'); const useAddons = require('./useAddons');
const useSelectableInputs = require('./useSelectableInputs'); const useSelectableInputs = require('./useSelectableInputs');
@ -103,16 +103,12 @@ const Addons = ({ urlParams, queryParams }) => {
/> />
))} ))}
<div className={styles['spacing']} /> <div className={styles['spacing']} />
<label className={styles['search-bar-container']}> <SearchBar
<TextInput className={styles['search-bar']}
className={styles['search-input']} title={'Search addons'}
type={'text'} value={search}
placeholder={'Search addons'} onChange={searchInputOnChange}
value={search} />
onChange={searchInputOnChange}
/>
<Icon className={styles['icon']} icon={'ic_search'} />
</label>
</div> </div>
{ {
addons.selectable.catalogs.length === 0 && addons.catalog_resource === null ? addons.selectable.catalogs.length === 0 && addons.catalog_resource === null ?

View file

@ -85,48 +85,10 @@
flex: 1; flex: 1;
} }
.search-bar-container { .search-bar {
flex-grow: 0; flex-grow: 0;
flex-shrink: 1; flex-shrink: 1;
flex-basis: 18rem; flex-basis: 18rem;
display: flex;
flex-direction: row;
align-items: center;
height: 3.5rem;
padding: 0 1rem;
border-radius: 2.3rem;
border: var(--focus-outline-size) solid transparent;
background-color: @color-background;
cursor: text;
&:hover, &:focus-within {
background-color: @color-background-light2;
}
&:focus-within {
border: var(--focus-outline-size) solid @color-surface-light5;
}
.search-input {
flex: 1;
margin-right: 1rem;
font-size: 1.1rem;
color: @color-surface-light5;
&::placeholder {
max-height: 1.2em;
opacity: 1;
color: @color-secondaryvariant1-light1-90;
}
}
.icon {
flex: none;
width: 1.5rem;
height: 1.5rem;
fill: @color-secondaryvariant1;
}
} }
} }

View file

@ -1,7 +1,7 @@
const React = require('react'); const React = require('react');
const PropTypes = require('prop-types'); const PropTypes = require('prop-types');
const classnames = require('classnames'); const classnames = require('classnames');
const Icon = require('stremio-icons/dom'); const PlayIconCircleCentered = require('stremio/common/PlayIconCircleCentered');
const styles = require('./styles'); const styles = require('./styles');
const StreamPlaceholder = ({ className }) => { const StreamPlaceholder = ({ className }) => {
@ -14,9 +14,7 @@ const StreamPlaceholder = ({ className }) => {
<div className={styles['description-container']} /> <div className={styles['description-container']} />
<div className={styles['description-container']} /> <div className={styles['description-container']} />
</div> </div>
<div className={styles['play-icon-container']}> <PlayIconCircleCentered className={styles['play-icon']} />
<Icon className={styles['play-icon']} icon={'ic_play'} />
</div>
</div> </div>
); );
}; };

View file

@ -1,27 +1,31 @@
:import('~stremio/common/PlayIconCircleCentered/styles.less') {
play-icon-circle-centered-background: background;
play-icon-circle-centered-icon: icon;
}
.stream-placeholder-container { .stream-placeholder-container {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
background-color: var(--color-placeholder); padding: 0.5rem 1rem;
.addon-container { .addon-container {
flex: none; flex: none;
padding: 0.5rem;
.addon-name { .addon-name {
width: 5rem; width: 5rem;
height: 2rem; height: 2rem;
background-color: var(--color-placeholder); background-color: var(--color-placeholder-background);
} }
} }
.info-container { .info-container {
flex: 1; flex: 1;
padding: 0.5rem; margin: 0.5rem 1rem;
.description-container { .description-container {
height: 1.2rem; height: 1.2rem;
background-color: var(--color-placeholder); background-color: var(--color-placeholder-background);
&:nth-child(1) { &:nth-child(1) {
width: 80%; width: 80%;
@ -34,17 +38,17 @@
} }
} }
.play-icon-container { .play-icon {
flex: none; flex: none;
width: 5rem; width: 3.5rem;
height: 5rem; height: 5rem;
padding: 1.5rem;
.play-icon { .play-icon-circle-centered-background {
display: block; fill: none;
width: 100%; }
height: 100%;
fill: var(--color-placeholder); .play-icon-circle-centered-icon {
fill: var(--color-placeholder-background);
} }
} }
} }

View file

@ -8,13 +8,16 @@ const SeasonsBarPlaceholder = ({ className }) => {
return ( return (
<div className={classnames(className, styles['seasons-bar-placeholder-container'])}> <div className={classnames(className, styles['seasons-bar-placeholder-container'])}>
<div className={styles['prev-season-button']}> <div className={styles['prev-season-button']}>
<Icon className={styles['icon']} icon={'ic_arrow_left'} /> <Icon className={styles['icon']} icon={'ic_arrow_thin_left'} />
<div className={styles['label']}>Prev</div>
</div> </div>
<div className={styles['seasons-popup-label-container']}> <div className={styles['seasons-popup-label-container']}>
<div className={styles['seasons-popup-label']} /> <div className={styles['seasons-popup-label']}>Season 1</div>
<Icon className={styles['seasons-popup-icon']} icon={'ic_arrow_thin_down'} />
</div> </div>
<div className={styles['next-season-button']}> <div className={styles['next-season-button']}>
<Icon className={styles['icon']} icon={'ic_arrow_right'} /> <div className={styles['label']}>Next</div>
<Icon className={styles['icon']} icon={'ic_arrow_thin_right'} />
</div> </div>
</div> </div>
); );

View file

@ -1,35 +1,58 @@
.seasons-bar-placeholder-container { .seasons-bar-placeholder-container {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
justify-content: space-between;
padding: 1rem;
.prev-season-button, .next-season-button { .prev-season-button, .next-season-button {
flex: none; flex: none;
width: 4rem; display: flex;
height: 4rem; flex-direction: row;
padding: 1rem; align-items: center;
background-color: var(--color-placeholder); width: 6.5rem;
height: 3.5rem;
padding: 0.5rem;
&>:first-child {
margin-right: 0.5rem;
}
.icon { .icon {
flex: none;
display: block; display: block;
width: 100%; width: 1.5rem;
height: 100%; height: 1.5rem;
fill: var(--color-placeholder); fill: var(--color-placeholder-background);
}
.label {
flex: 1;
max-height: 1.2em;
font-weight: 500;
text-align: center;
color: var(--color-placeholder-text);
} }
} }
.seasons-popup-label-container { .seasons-popup-label-container {
flex: 1; flex: 0 1 auto;
align-self: stretch;
display: flex; display: flex;
flex-direction: row;
align-items: center; align-items: center;
justify-content: center;
margin: 0 1rem; margin: 0 1rem;
background-color: var(--color-placeholder);
.seasons-popup-label { .seasons-popup-label {
width: 50%; max-height: 1.2em;
height: 1.2rem; font-weight: 500;
background-color: var(--color-placeholder); color: var(--color-placeholder-text);
}
.seasons-popup-icon {
flex: none;
width: 1rem;
height: 1rem;
margin-left: 1rem;
fill: var(--color-placeholder-background);
} }
} }
} }

View file

@ -1,7 +1,6 @@
const React = require('react'); const React = require('react');
const PropTypes = require('prop-types'); const PropTypes = require('prop-types');
const classnames = require('classnames'); const classnames = require('classnames');
const Icon = require('stremio-icons/dom');
const styles = require('./styles'); const styles = require('./styles');
const VideoPlaceholder = ({ className }) => { const VideoPlaceholder = ({ className }) => {
@ -11,9 +10,6 @@ const VideoPlaceholder = ({ className }) => {
<div className={styles['name-container']} /> <div className={styles['name-container']} />
<div className={styles['released-container']} /> <div className={styles['released-container']} />
</div> </div>
<div className={styles['next-icon-container']}>
<Icon className={styles['next-icon']} icon={'ic_arrow_thin_right'} />
</div>
</div> </div>
); );
}; };

View file

@ -2,37 +2,25 @@
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
background-color: var(--color-placeholder); padding: 0.5rem 1rem;
.info-container { .info-container {
flex: 1; flex: 1;
padding: 0.5rem; display: flex;
flex-direction: column;
justify-content: space-between;
height: 3rem;
margin: 0.5rem 1rem;
.name-container { .name-container {
width: 80%; width: 80%;
height: 1.2rem; height: 1.2rem;
background: var(--color-placeholder); background: var(--color-placeholder-background);
} }
.released-container { .released-container {
width: 40%; height: 1rem;
height: 1.2rem; background: var(--color-placeholder-background);
margin-top: 0.5rem;
background: var(--color-placeholder);
}
}
.next-icon-container {
flex: none;
width: 2rem;
height: 2.5rem;
padding: 0.5rem;
.next-icon {
display: block;
width: 100%;
height: 100%;
fill: var(--color-placeholder);
} }
} }
} }

View file

@ -1,9 +1,8 @@
const React = require('react'); const React = require('react');
const PropTypes = require('prop-types'); const PropTypes = require('prop-types');
const classnames = require('classnames'); const classnames = require('classnames');
const Icon = require('stremio-icons/dom');
const Image = require('stremio/common/Image'); const Image = require('stremio/common/Image');
const TextInput = require('stremio/common/TextInput'); const SearchBar = require('stremio/common/SearchBar');
const SeasonsBar = require('./SeasonsBar'); const SeasonsBar = require('./SeasonsBar');
const Video = require('./Video'); const Video = require('./Video');
const useSelectableSeasons = require('./useSelectableSeasons'); const useSelectableSeasons = require('./useSelectableSeasons');
@ -30,6 +29,7 @@ const VideosList = ({ className, metaResource }) => {
!metaResource || metaResource.content.type === 'Loading' ? !metaResource || metaResource.content.type === 'Loading' ?
<React.Fragment> <React.Fragment>
<SeasonsBar.Placeholder className={styles['seasons-bar']} /> <SeasonsBar.Placeholder className={styles['seasons-bar']} />
<SearchBar.Placeholder className={styles['search-bar']} title={'Search videos'} />
<div className={styles['videos-scroll-container']}> <div className={styles['videos-scroll-container']}>
<Video.Placeholder /> <Video.Placeholder />
<Video.Placeholder /> <Video.Placeholder />
@ -57,16 +57,12 @@ const VideosList = ({ className, metaResource }) => {
: :
null null
} }
<label title={'Search videos'} className={styles['search-bar-container']}> <SearchBar
<TextInput className={styles['search-bar']}
className={styles['search-input']} title={'Search videos'}
type={'text'} value={search}
placeholder={'Search videos'} onChange={searchInputOnChange}
value={search} />
onChange={searchInputOnChange}
/>
<Icon className={styles['icon']} icon={'ic_search'} />
</label>
<div className={styles['videos-container']}> <div className={styles['videos-container']}>
{ {
videosForSeason videosForSeason

View file

@ -37,51 +37,14 @@
align-self: stretch; align-self: stretch;
} }
.search-bar-container { .search-bar {
flex: none; flex: none;
align-self: stretch; align-self: stretch;
display: flex;
flex-direction: row;
align-items: center;
height: 3.5rem;
padding: 0 1rem;
margin: 0 1.5rem 1rem 1.5rem; margin: 0 1.5rem 1rem 1.5rem;
border-radius: 3.5rem;
border: var(--focus-outline-size) solid transparent;
background-color: @color-background;
cursor: text;
&:first-child { &:first-child {
margin-top: 1rem; margin-top: 1rem;
} }
&:hover, &:focus-within {
background-color: @color-background-light1;
}
&:focus-within {
border: var(--focus-outline-size) solid @color-surface-light5;
}
.search-input {
flex: 1;
margin-right: 1rem;
font-size: 1.1rem;
color: @color-surface-light5;
&::placeholder {
max-height: 1.2em;
opacity: 1;
color: @color-secondaryvariant1-light1-90;
}
}
.icon {
flex: none;
width: 1.5rem;
height: 1.5rem;
fill: @color-secondaryvariant1-90;
}
} }
.videos-container { .videos-container {