feat: icons group component

This commit is contained in:
higorgoulart 2025-11-04 19:23:39 -03:00
parent 852f478f1e
commit 3b2d1f365c
7 changed files with 78 additions and 52 deletions

View file

@ -6,7 +6,7 @@ const classnames = require('classnames');
const MetaItem = require('stremio/components/MetaItem');
const { t } = require('i18next');
const DiscItem = ({ id, watched, selected, toggleWatched, select, ...props }) => {
const DiscItem = ({ id, watched, selected, toggleWatched, ...props }) => {
const options = React.useMemo(() => {
return [

View file

@ -8,7 +8,7 @@
@width-mobile: 3rem;
.ratings-container {
.group-container {
display: flex;
flex-direction: row;
align-items: center;
@ -17,6 +17,8 @@
border-radius: 2rem;
height: @height;
width: fit-content;
margin-bottom: 1rem;
margin-right: 1rem;
.icon-container {
display: flex;
@ -45,7 +47,7 @@
}
@media @phone-landscape {
.ratings-container {
.group-container {
height: @height-mobile;
.icon-container {

View file

@ -0,0 +1,36 @@
// Copyright (C) 2017-2023 Smart code 203358507
import classNames from 'classnames';
import React from 'react';
import Icon from '@stremio/stremio-icons/react';
import styles from './IconsGroup.less';
type GroupItem = {
icon: string;
filled?: string;
disabled?: boolean;
className?: string;
onClick?: () => void;
};
type Props = {
items: GroupItem[];
className?: string;
};
const IconsGroup = ({ items, className }: Props) => {
return (
<div className={classNames(styles['group-container'], className)}>
{items.map((item, index) => (
<div key={index}
className={classNames(styles['icon-container'], item.className, { [styles['disabled']]: item.disabled })}
onClick={item.onClick}
>
<Icon name={item.icon} className={styles['icon']} />
</div>
))}
</div>
);
};
export default IconsGroup;

View file

@ -0,0 +1,6 @@
// Copyright (C) 2017-2023 Smart code 203358507
import IconsGroup from './IconsGroup';
export { IconsGroup };

View file

@ -8,6 +8,7 @@ const { useTranslation } = require('react-i18next');
const { default: Icon } = require('@stremio/stremio-icons/react');
const { default: Button } = require('stremio/components/Button');
const { default: Image } = require('stremio/components/Image');
const { IconsGroup } = require('stremio/components/IconsGroup');
const ModalDialog = require('stremio/components/ModalDialog');
const SharePrompt = require('stremio/components/SharePrompt');
const CONSTANTS = require('stremio/common/CONSTANTS');
@ -98,6 +99,16 @@ const MetaPreview = React.forwardRef(({ className, compact, name, logo, backgrou
const renderLogoFallback = React.useCallback(() => (
<div className={styles['logo-placeholder']}>{name}</div>
), [name]);
const libAndWatchedGroup = React.useMemo(() => [
{
icon: inLibrary ? 'remove-from-library' : 'add-to-library',
onClick: typeof toggleInLibrary === 'function' ? toggleInLibrary : null,
},
{
icon: watched ? 'eye-off' : 'eye',
onClick: typeof toggleWatched === 'function' ? toggleWatched : undefined,
},
], [inLibrary, watched, toggleInLibrary, toggleWatched]);
return (
<div className={classnames(className, styles['meta-preview-container'], { [styles['compact']]: compact })} ref={ref}>
{
@ -209,30 +220,9 @@ const MetaPreview = React.forwardRef(({ className, compact, name, logo, backgrou
null
}
{
typeof toggleInLibrary === 'function' ?
<ActionButton
className={styles['action-button']}
icon={inLibrary ? 'remove-from-library' : 'add-to-library'}
label={inLibrary ? t('REMOVE_FROM_LIB') : t('ADD_TO_LIB')}
tooltip={compact}
tabIndex={compact ? -1 : 0}
onClick={toggleInLibrary}
/>
:
null
}
{
typeof toggleWatched === 'function' ?
<ActionButton
className={styles['action-button']}
icon={watched ? 'eye-off' : 'eye'}
label={watched ? t('CTX_MARK_UNWATCHED') : t('CTX_MARK_WATCHED')}
tooltip={compact}
tabIndex={compact ? -1 : 0}
onClick={toggleWatched}
/>
:
null
typeof toggleInLibrary === 'function' && typeof toggleWatched === 'function'
? <IconsGroup items={libAndWatchedGroup} />
: null
}
{
typeof showHref === 'string' && compact ?
@ -247,13 +237,9 @@ const MetaPreview = React.forwardRef(({ className, compact, name, logo, backgrou
null
}
{
!compact && ratingInfo !== null ?
<Ratings
ratingInfo={ratingInfo}
className={styles['ratings']}
/>
:
null
!compact && ratingInfo !== null
? <Ratings ratingInfo={ratingInfo} />
: null
}
{
linksGroups.has(CONSTANTS.SHARE_LINK_CATEGORY) && !compact ?

View file

@ -2,9 +2,7 @@
import React, { useMemo } from 'react';
import useRating from './useRating';
import styles from './Ratings.less';
import Icon from '@stremio/stremio-icons/react';
import classNames from 'classnames';
import { IconsGroup } from 'stremio/components/IconsGroup';
type Props = {
metaId?: string;
@ -15,17 +13,20 @@ type Props = {
const Ratings = ({ ratingInfo, className }: Props) => {
const { onLiked, onLoved, liked, loved } = useRating(ratingInfo);
const disabled = useMemo(() => ratingInfo?.type !== 'Ready', [ratingInfo]);
const items = useMemo(() => [
{
icon: liked ? 'thumbs-up' : 'thumbs-up-outline',
disabled,
onClick: onLiked,
},
{
icon: loved ? 'heart' : 'heart-outline',
disabled,
onClick: onLoved,
},
], [liked, loved, disabled, onLiked, onLoved]);
return (
<div className={classNames(styles['ratings-container'], className)}>
<div className={classNames(styles['icon-container'], { [styles['disabled']]: disabled })} onClick={onLiked}>
<Icon name={liked ? 'thumbs-up' : 'thumbs-up-outline'} className={styles['icon']} />
</div>
<div className={classNames(styles['icon-container'], { [styles['disabled']]: disabled })} onClick={onLoved}>
<Icon name={loved ? 'heart' : 'heart-outline'} className={styles['icon']} />
</div>
</div>
);
return <IconsGroup items={items} className={className} />;
};
export default Ratings;

View file

@ -208,11 +208,6 @@
}
}
}
.ratings {
margin-bottom: 1rem;
margin-right: 1rem;
}
}
.share-prompt {