mirror of
https://github.com/Stremio/stremio-web.git
synced 2026-03-11 21:27:05 +00:00
Merge pull request #149 from Stremio/placeholders
Video/Stream placeholders
This commit is contained in:
commit
5e59cd3e7b
17 changed files with 216 additions and 159 deletions
33
src/common/SearchBar/SearchBar.js
Normal file
33
src/common/SearchBar/SearchBar.js
Normal 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;
|
||||
|
|
@ -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;
|
||||
3
src/common/SearchBar/SearchBarPlaceholder/index.js
Normal file
3
src/common/SearchBar/SearchBarPlaceholder/index.js
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
const SearchBarPlaceholder = require('./SearchBarPlaceholder');
|
||||
|
||||
module.exports = SearchBarPlaceholder;
|
||||
25
src/common/SearchBar/SearchBarPlaceholder/styles.less
Normal file
25
src/common/SearchBar/SearchBarPlaceholder/styles.less
Normal 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);
|
||||
}
|
||||
}
|
||||
3
src/common/SearchBar/index.js
Normal file
3
src/common/SearchBar/index.js
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
const SearchBar = require('./SearchBar');
|
||||
|
||||
module.exports = SearchBar;
|
||||
41
src/common/SearchBar/styles.less
Normal file
41
src/common/SearchBar/styles.less
Normal 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -14,6 +14,7 @@ const { HorizontalNavBar, VerticalNavBar } = require('./NavBar');
|
|||
const PaginationInput = require('./PaginationInput');
|
||||
const PlayIconCircleCentered = require('./PlayIconCircleCentered');
|
||||
const Popup = require('./Popup');
|
||||
const SearchBar = require('./SearchBar');
|
||||
const SharePrompt = require('./SharePrompt');
|
||||
const Slider = require('./Slider');
|
||||
const TextInput = require('./TextInput');
|
||||
|
|
@ -51,6 +52,7 @@ module.exports = {
|
|||
PaginationInput,
|
||||
PlayIconCircleCentered,
|
||||
Popup,
|
||||
SearchBar,
|
||||
SharePrompt,
|
||||
Slider,
|
||||
TextInput,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ const React = require('react');
|
|||
const PropTypes = require('prop-types');
|
||||
const { useRouteFocused } = require('stremio-router');
|
||||
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 useAddons = require('./useAddons');
|
||||
const useSelectableInputs = require('./useSelectableInputs');
|
||||
|
|
@ -103,16 +103,12 @@ const Addons = ({ urlParams, queryParams }) => {
|
|||
/>
|
||||
))}
|
||||
<div className={styles['spacing']} />
|
||||
<label className={styles['search-bar-container']}>
|
||||
<TextInput
|
||||
className={styles['search-input']}
|
||||
type={'text'}
|
||||
placeholder={'Search addons'}
|
||||
value={search}
|
||||
onChange={searchInputOnChange}
|
||||
/>
|
||||
<Icon className={styles['icon']} icon={'ic_search'} />
|
||||
</label>
|
||||
<SearchBar
|
||||
className={styles['search-bar']}
|
||||
title={'Search addons'}
|
||||
value={search}
|
||||
onChange={searchInputOnChange}
|
||||
/>
|
||||
</div>
|
||||
{
|
||||
addons.selectable.catalogs.length === 0 && addons.catalog_resource === null ?
|
||||
|
|
|
|||
|
|
@ -85,48 +85,10 @@
|
|||
flex: 1;
|
||||
}
|
||||
|
||||
.search-bar-container {
|
||||
.search-bar {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 1;
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
const React = require('react');
|
||||
const PropTypes = require('prop-types');
|
||||
const classnames = require('classnames');
|
||||
const Icon = require('stremio-icons/dom');
|
||||
const PlayIconCircleCentered = require('stremio/common/PlayIconCircleCentered');
|
||||
const styles = require('./styles');
|
||||
|
||||
const StreamPlaceholder = ({ className }) => {
|
||||
|
|
@ -14,9 +14,7 @@ const StreamPlaceholder = ({ className }) => {
|
|||
<div className={styles['description-container']} />
|
||||
<div className={styles['description-container']} />
|
||||
</div>
|
||||
<div className={styles['play-icon-container']}>
|
||||
<Icon className={styles['play-icon']} icon={'ic_play'} />
|
||||
</div>
|
||||
<PlayIconCircleCentered className={styles['play-icon']} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
background-color: var(--color-placeholder);
|
||||
padding: 0.5rem 1rem;
|
||||
|
||||
.addon-container {
|
||||
flex: none;
|
||||
padding: 0.5rem;
|
||||
|
||||
.addon-name {
|
||||
width: 5rem;
|
||||
height: 2rem;
|
||||
background-color: var(--color-placeholder);
|
||||
background-color: var(--color-placeholder-background);
|
||||
}
|
||||
}
|
||||
|
||||
.info-container {
|
||||
flex: 1;
|
||||
padding: 0.5rem;
|
||||
margin: 0.5rem 1rem;
|
||||
|
||||
.description-container {
|
||||
height: 1.2rem;
|
||||
background-color: var(--color-placeholder);
|
||||
background-color: var(--color-placeholder-background);
|
||||
|
||||
&:nth-child(1) {
|
||||
width: 80%;
|
||||
|
|
@ -34,17 +38,17 @@
|
|||
}
|
||||
}
|
||||
|
||||
.play-icon-container {
|
||||
.play-icon {
|
||||
flex: none;
|
||||
width: 5rem;
|
||||
width: 3.5rem;
|
||||
height: 5rem;
|
||||
padding: 1.5rem;
|
||||
|
||||
.play-icon {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
fill: var(--color-placeholder);
|
||||
.play-icon-circle-centered-background {
|
||||
fill: none;
|
||||
}
|
||||
|
||||
.play-icon-circle-centered-icon {
|
||||
fill: var(--color-placeholder-background);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8,13 +8,16 @@ const SeasonsBarPlaceholder = ({ className }) => {
|
|||
return (
|
||||
<div className={classnames(className, styles['seasons-bar-placeholder-container'])}>
|
||||
<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 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 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>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,35 +1,58 @@
|
|||
.seasons-bar-placeholder-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
padding: 1rem;
|
||||
|
||||
.prev-season-button, .next-season-button {
|
||||
flex: none;
|
||||
width: 4rem;
|
||||
height: 4rem;
|
||||
padding: 1rem;
|
||||
background-color: var(--color-placeholder);
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
width: 6.5rem;
|
||||
height: 3.5rem;
|
||||
padding: 0.5rem;
|
||||
|
||||
&>:first-child {
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
.icon {
|
||||
flex: none;
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
fill: var(--color-placeholder);
|
||||
width: 1.5rem;
|
||||
height: 1.5rem;
|
||||
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 {
|
||||
flex: 1;
|
||||
align-self: stretch;
|
||||
flex: 0 1 auto;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 0 1rem;
|
||||
background-color: var(--color-placeholder);
|
||||
|
||||
.seasons-popup-label {
|
||||
width: 50%;
|
||||
height: 1.2rem;
|
||||
background-color: var(--color-placeholder);
|
||||
max-height: 1.2em;
|
||||
font-weight: 500;
|
||||
color: var(--color-placeholder-text);
|
||||
}
|
||||
|
||||
.seasons-popup-icon {
|
||||
flex: none;
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
margin-left: 1rem;
|
||||
fill: var(--color-placeholder-background);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
const React = require('react');
|
||||
const PropTypes = require('prop-types');
|
||||
const classnames = require('classnames');
|
||||
const Icon = require('stremio-icons/dom');
|
||||
const styles = require('./styles');
|
||||
|
||||
const VideoPlaceholder = ({ className }) => {
|
||||
|
|
@ -11,9 +10,6 @@ const VideoPlaceholder = ({ className }) => {
|
|||
<div className={styles['name-container']} />
|
||||
<div className={styles['released-container']} />
|
||||
</div>
|
||||
<div className={styles['next-icon-container']}>
|
||||
<Icon className={styles['next-icon']} icon={'ic_arrow_thin_right'} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2,37 +2,25 @@
|
|||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
background-color: var(--color-placeholder);
|
||||
padding: 0.5rem 1rem;
|
||||
|
||||
.info-container {
|
||||
flex: 1;
|
||||
padding: 0.5rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
height: 3rem;
|
||||
margin: 0.5rem 1rem;
|
||||
|
||||
.name-container {
|
||||
width: 80%;
|
||||
height: 1.2rem;
|
||||
background: var(--color-placeholder);
|
||||
background: var(--color-placeholder-background);
|
||||
}
|
||||
|
||||
.released-container {
|
||||
width: 40%;
|
||||
height: 1.2rem;
|
||||
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);
|
||||
height: 1rem;
|
||||
background: var(--color-placeholder-background);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +1,8 @@
|
|||
const React = require('react');
|
||||
const PropTypes = require('prop-types');
|
||||
const classnames = require('classnames');
|
||||
const Icon = require('stremio-icons/dom');
|
||||
const Image = require('stremio/common/Image');
|
||||
const TextInput = require('stremio/common/TextInput');
|
||||
const SearchBar = require('stremio/common/SearchBar');
|
||||
const SeasonsBar = require('./SeasonsBar');
|
||||
const Video = require('./Video');
|
||||
const useSelectableSeasons = require('./useSelectableSeasons');
|
||||
|
|
@ -30,6 +29,7 @@ const VideosList = ({ className, metaResource }) => {
|
|||
!metaResource || metaResource.content.type === 'Loading' ?
|
||||
<React.Fragment>
|
||||
<SeasonsBar.Placeholder className={styles['seasons-bar']} />
|
||||
<SearchBar.Placeholder className={styles['search-bar']} title={'Search videos'} />
|
||||
<div className={styles['videos-scroll-container']}>
|
||||
<Video.Placeholder />
|
||||
<Video.Placeholder />
|
||||
|
|
@ -57,16 +57,12 @@ const VideosList = ({ className, metaResource }) => {
|
|||
:
|
||||
null
|
||||
}
|
||||
<label title={'Search videos'} className={styles['search-bar-container']}>
|
||||
<TextInput
|
||||
className={styles['search-input']}
|
||||
type={'text'}
|
||||
placeholder={'Search videos'}
|
||||
value={search}
|
||||
onChange={searchInputOnChange}
|
||||
/>
|
||||
<Icon className={styles['icon']} icon={'ic_search'} />
|
||||
</label>
|
||||
<SearchBar
|
||||
className={styles['search-bar']}
|
||||
title={'Search videos'}
|
||||
value={search}
|
||||
onChange={searchInputOnChange}
|
||||
/>
|
||||
<div className={styles['videos-container']}>
|
||||
{
|
||||
videosForSeason
|
||||
|
|
|
|||
|
|
@ -37,51 +37,14 @@
|
|||
align-self: stretch;
|
||||
}
|
||||
|
||||
.search-bar-container {
|
||||
.search-bar {
|
||||
flex: none;
|
||||
align-self: stretch;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
height: 3.5rem;
|
||||
padding: 0 1rem;
|
||||
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 {
|
||||
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 {
|
||||
|
|
|
|||
Loading…
Reference in a new issue