feat: addon placeholder

This commit is contained in:
Timothy Z. 2024-12-18 17:07:19 +02:00
parent 8fefc66521
commit 4b22bda09c
4 changed files with 173 additions and 6 deletions

View file

@ -0,0 +1,122 @@
/* Copyright (C) 2017-2024 Smart code 203358507 */
@import (reference) '~stremio/common/screen-sizes.less';
@placeholder-opacity: 0.1;
@padding: 1.5rem;
@small-padding: 1rem;
@logo-size: 8rem;
.placeholder-pill(@width: 100%, @height: 1.3rem) {
background-color: var(--primary-foreground-color);
border-radius: var(--border-radius);
opacity: @placeholder-opacity;
width: @width;
height: @height;
}
.placeholder-logo(@size: @logo-size) {
width: @size;
height: @size;
border-radius: 50%;
background-color: var(--primary-foreground-color);
opacity: @placeholder-opacity;
}
.addon-container {
display: flex;
flex-direction: row;
align-items: flex-start;
padding: @padding;
border-radius: var(--border-radius);
background-color: var(--overlay-color);
cursor: inherit;
.content {
display: flex;
flex: 1;
.logo-container {
flex: none;
.placeholder-logo(@logo-size);
}
.info-container {
display: flex;
flex-direction: column;
gap: 0.5rem;
padding: @small-padding;
flex: 1;
.placeholder-pill:nth-child(1) {
.placeholder-pill(40%);
}
.placeholder-pill:nth-child(2) {
.placeholder-pill(60%);
}
.placeholder-pill:nth-child(3) {
.placeholder-pill(80%);
}
}
}
.buttons-container {
flex: none;
display: flex;
flex-direction: column;
gap: @small-padding;
width: 30%;
max-width: 18rem;
.action-buttons-container {
display: flex;
flex-direction: row;
gap: @small-padding;
.placeholder-pill:nth-child(1), .placeholder-pill:nth-child(2) {
.placeholder-pill(50%, 3.5rem);
}
}
.placeholder-pill:last-child {
.placeholder-pill(100%, 3.5rem);
}
}
}
@media screen and (max-width: @minimum) {
.addon-container {
flex-direction: column;
align-items: stretch;
padding: 1rem;
width: 100%;
gap: 1rem;
.content {
flex-direction: row;
width: 100%;
.logo-container {
.placeholder-logo(6rem);
margin: 0 auto;
}
.info-container {
padding: 0.5rem;
width: 100%;
}
}
.buttons-container {
flex-direction: column;
align-items: stretch;
width: 100%;
gap: 0.5rem;
max-width: none;
.action-buttons-container {
display: none;
}
}
}
}

View file

@ -0,0 +1,33 @@
// Copyright (C) 2017-2024 Smart code 203358507
import React from 'react';
import classnames from 'classnames';
import styles from './AddonPlaceholder.less';
type Props = {
className?: string;
};
export const AddonPlaceholder = ({ className }: Props) => {
return (
<div className={classnames(className, styles['addon-container'])}>
<div className={styles['content']}>
<div className={styles['logo-container']}>
<div className={styles['placeholder-logo']} />
</div>
<div className={styles['info-container']}>
<div className={styles['placeholder-pill']} />
<div className={styles['placeholder-pill']} />
<div className={styles['placeholder-pill']} />
</div>
</div>
<div className={styles['buttons-container']}>
<div className={styles['action-buttons-container']}>
<div className={styles['placeholder-pill']} />
<div className={styles['placeholder-pill']} />
</div>
<div className={styles['placeholder-pill']} />
</div>
</div>
);
};

View file

@ -0,0 +1,7 @@
// Copyright (C) 2017-2024 Smart code 203358507
import { AddonPlaceholder } from './AddonPlaceholder';
export {
AddonPlaceholder
};

View file

@ -12,6 +12,7 @@ const useRemoteAddons = require('./useRemoteAddons');
const useAddonDetailsTransportUrl = require('./useAddonDetailsTransportUrl');
const useSelectableInputs = require('./useSelectableInputs');
const styles = require('./styles');
const { AddonPlaceholder } = require('./AddonPlaceholder');
const Addons = ({ urlParams, queryParams }) => {
const { t } = useTranslation();
@ -94,7 +95,7 @@ const Addons = ({ urlParams, queryParams }) => {
<div className={styles['spacing']} />
<Button className={styles['add-button-container']} title={t('ADD_ADDON')} onClick={openAddAddonModal}>
<Icon className={styles['icon']} name={'add'} />
<div className={styles['add-button-label']}>{ t('ADD_ADDON') }</div>
<div className={styles['add-button-label']}>{t('ADD_ADDON')}</div>
</Button>
<SearchBar
className={styles['search-bar']}
@ -150,8 +151,10 @@ const Addons = ({ urlParams, queryParams }) => {
</div>
:
remoteAddons.catalog.content.type === 'Loading' ?
<div className={styles['message-container']}>
Loading!
<div className={styles['addons-list-container']}>
{Array.from({ length: 6 }).map((_, index) => (
<AddonPlaceholder key={index} className={styles['addon']} />
))}
</div>
:
<div className={styles['addons-list-container']}>
@ -179,8 +182,10 @@ const Addons = ({ urlParams, queryParams }) => {
}
</div>
:
<div className={styles['message-container']}>
No select
<div className={styles['addons-list-container']}>
{Array.from({ length: 6 }).map((_, index) => (
<AddonPlaceholder key={index} className={styles['addon']} />
))}
</div>
}
</div>
@ -205,7 +210,7 @@ const Addons = ({ urlParams, queryParams }) => {
title={t('ADD_ADDON')}
buttons={addAddonModalButtons}
onCloseRequest={closeAddAddonModal}>
<div className={styles['notice']}>{ t('ADD_ADDON_DESCRIPTION') }</div>
<div className={styles['notice']}>{t('ADD_ADDON_DESCRIPTION')}</div>
<TextInput
ref={addAddonUrlInputRef}
className={styles['addon-url-input']}