refactor(css): add styles targeting SVG button/modal icons (#1464)

* refactor(css): add global classes for common icon types

* refactor(css): target child SVGs instead of creating new icon classes

* fix: fix ButtonWithDropdown style class spacing
pull/1496/head
TheCatLady 4 years ago committed by GitHub
parent 079645c2c7
commit 3e5e9c0ad1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -247,7 +247,7 @@ const CollectionDetails: React.FC<CollectionDetailsProps> = ({
title={intl.formatMessage( title={intl.formatMessage(
is4k ? messages.requestcollection4k : messages.requestcollection is4k ? messages.requestcollection4k : messages.requestcollection
)} )}
iconSvg={<DuplicateIcon className="w-6 h-6" />} iconSvg={<DuplicateIcon />}
> >
<p> <p>
{intl.formatMessage( {intl.formatMessage(
@ -339,7 +339,7 @@ const CollectionDetails: React.FC<CollectionDetailsProps> = ({
}} }}
text={ text={
<> <>
<DownloadIcon className="w-5 h-5 mr-1" /> <DownloadIcon />
<span> <span>
{intl.formatMessage( {intl.formatMessage(
hasRequestable hasRequestable
@ -364,7 +364,7 @@ const CollectionDetails: React.FC<CollectionDetailsProps> = ({
setIs4k(true); setIs4k(true);
}} }}
> >
<DownloadIcon className="w-5 h-5 mr-1" /> <DownloadIcon />
<span> <span>
{intl.formatMessage(messages.requestcollection4k)} {intl.formatMessage(messages.requestcollection4k)}
</span> </span>

@ -81,16 +81,14 @@ function Button<P extends ElementTypes = 'button'>(
switch (buttonSize) { switch (buttonSize) {
case 'sm': case 'sm':
buttonStyle.push('px-2.5 py-1.5 text-xs'); buttonStyle.push('px-2.5 py-1.5 text-xs button-sm');
break;
case 'md':
buttonStyle.push('px-4 py-2 text-sm');
break; break;
case 'lg': case 'lg':
buttonStyle.push('px-6 py-3 text-base'); buttonStyle.push('px-6 py-3 text-base button-lg');
break; break;
case 'md':
default: default:
buttonStyle.push('px-4 py-2 text-sm'); buttonStyle.push('px-4 py-2 text-sm button-md');
} }
buttonStyle.push(className ?? ''); buttonStyle.push(className ?? '');

@ -19,16 +19,16 @@ const DropdownItem: React.FC<DropdownItemProps> = ({
buttonType = 'primary', buttonType = 'primary',
...props ...props
}) => { }) => {
let styleClass = ''; let styleClass = 'button-md text-white';
switch (buttonType) { switch (buttonType) {
case 'ghost': case 'ghost':
styleClass = styleClass +=
'text-white bg-gray-700 hover:bg-gray-600 hover:text-white focus:border-gray-500 focus:text-white'; ' bg-gray-700 hover:bg-gray-600 focus:border-gray-500 focus:text-white';
break; break;
default: default:
styleClass = styleClass +=
'text-white bg-indigo-600 hover:bg-indigo-500 hover:text-white focus:border-indigo-700 focus:text-white'; ' bg-indigo-600 hover:bg-indigo-500 focus:border-indigo-700 focus:text-white';
} }
return ( return (
<a <a
@ -60,9 +60,9 @@ const ButtonWithDropdown: React.FC<ButtonWithDropdownProps> = ({
useClickOutside(buttonRef, () => setIsOpen(false)); useClickOutside(buttonRef, () => setIsOpen(false));
const styleClasses = { const styleClasses = {
mainButtonClasses: 'text-white border', mainButtonClasses: 'button-md text-white border',
dropdownSideButtonClasses: 'border', dropdownSideButtonClasses: 'button-md border',
dropdownClasses: '', dropdownClasses: 'button-md',
}; };
switch (buttonType) { switch (buttonType) {
@ -70,14 +70,14 @@ const ButtonWithDropdown: React.FC<ButtonWithDropdownProps> = ({
styleClasses.mainButtonClasses += styleClasses.mainButtonClasses +=
' bg-transparent border-gray-600 hover:border-gray-200 focus:border-gray-100 active:border-gray-100'; ' bg-transparent border-gray-600 hover:border-gray-200 focus:border-gray-100 active:border-gray-100';
styleClasses.dropdownSideButtonClasses = styleClasses.mainButtonClasses; styleClasses.dropdownSideButtonClasses = styleClasses.mainButtonClasses;
styleClasses.dropdownClasses = 'bg-gray-700'; styleClasses.dropdownClasses += ' bg-gray-700';
break; break;
default: default:
styleClasses.mainButtonClasses += styleClasses.mainButtonClasses +=
' bg-indigo-600 border-indigo-600 hover:bg-indigo-500 hover:border-indigo-500 active:bg-indigo-700 active:border-indigo-700 focus:ring-blue'; ' bg-indigo-600 border-indigo-600 hover:bg-indigo-500 hover:border-indigo-500 active:bg-indigo-700 active:border-indigo-700 focus:ring-blue';
styleClasses.dropdownSideButtonClasses += styleClasses.dropdownSideButtonClasses +=
' bg-indigo-700 border-indigo-600 hover:bg-indigo-500 active:bg-indigo-700 focus:ring-blue'; ' bg-indigo-700 border-indigo-600 hover:bg-indigo-500 active:bg-indigo-700 focus:ring-blue';
styleClasses.dropdownClasses = 'bg-indigo-600'; styleClasses.dropdownClasses += ' bg-indigo-600';
} }
return ( return (
@ -100,11 +100,7 @@ const ButtonWithDropdown: React.FC<ButtonWithDropdownProps> = ({
aria-label="Expand" aria-label="Expand"
onClick={() => setIsOpen((state) => !state)} onClick={() => setIsOpen((state) => !state)}
> >
{dropdownIcon ? ( {dropdownIcon ? dropdownIcon : <ChevronDownIcon />}
dropdownIcon
) : (
<ChevronDownIcon className="w-5 h-5" />
)}
</button> </button>
<Transition <Transition
show={isOpen} show={isOpen}

@ -108,11 +108,7 @@ const Modal: React.FC<ModalProps> = ({
}} }}
> >
<div className="sm:flex sm:items-center"> <div className="sm:flex sm:items-center">
{iconSvg && ( {iconSvg && <div className="modal-icon">{iconSvg}</div>}
<div className="flex items-center justify-center flex-shrink-0 w-12 h-12 mx-auto text-white bg-gray-600 rounded-full sm:mx-0 sm:h-10 sm:w-10">
{iconSvg}
</div>
)}
<div <div
className={`mt-3 text-center sm:mt-0 sm:text-left ${ className={`mt-3 text-center sm:mt-0 sm:text-left ${
iconSvg ? 'sm:ml-4' : 'sm:mb-4' iconSvg ? 'sm:ml-4' : 'sm:mb-4'

@ -22,7 +22,7 @@ const PlayButton: React.FC<PlayButtonProps> = ({ links }) => {
text={ text={
<> <>
{links[0].svg} {links[0].svg}
{links[0].text} <span>{links[0].text}</span>
</> </>
} }
onClick={() => { onClick={() => {
@ -40,7 +40,7 @@ const PlayButton: React.FC<PlayButtonProps> = ({ links }) => {
buttonType="ghost" buttonType="ghost"
> >
{link.svg} {link.svg}
{link.text} <span>{link.text}</span>
</ButtonWithDropdown.Item> </ButtonWithDropdown.Item>
); );
})} })}

@ -28,7 +28,7 @@ const MovieGenreSlider: React.FC = () => {
<Link href="/discover/movies/genres"> <Link href="/discover/movies/genres">
<a className="slider-title"> <a className="slider-title">
<span>{intl.formatMessage(messages.moviegenres)}</span> <span>{intl.formatMessage(messages.moviegenres)}</span>
<ArrowCircleRightIcon className="w-6 h-6 ml-2" /> <ArrowCircleRightIcon />
</a> </a>
</Link> </Link>
</div> </div>

@ -28,7 +28,7 @@ const TvGenreSlider: React.FC = () => {
<Link href="/discover/tv/genres"> <Link href="/discover/tv/genres">
<a className="slider-title"> <a className="slider-title">
<span>{intl.formatMessage(messages.tvgenres)}</span> <span>{intl.formatMessage(messages.tvgenres)}</span>
<ArrowCircleRightIcon className="w-6 h-6 ml-2" /> <ArrowCircleRightIcon />
</a> </a>
</Link> </Link>
</div> </div>

@ -67,7 +67,7 @@ const Discover: React.FC = () => {
<Link href="/requests?filter=all"> <Link href="/requests?filter=all">
<a className="slider-title"> <a className="slider-title">
<span>{intl.formatMessage(messages.recentrequests)}</span> <span>{intl.formatMessage(messages.recentrequests)}</span>
<ArrowCircleRightIcon className="w-6 h-6 ml-2" /> <ArrowCircleRightIcon />
</a> </a>
</Link> </Link>
</div> </div>

@ -41,7 +41,7 @@ const SearchInput: React.FC = () => {
className="absolute inset-y-0 p-1 m-auto text-gray-400 transition border-none outline-none right-2 h-7 w-7 focus:outline-none focus:border-none hover:text-white" className="absolute inset-y-0 p-1 m-auto text-gray-400 transition border-none outline-none right-2 h-7 w-7 focus:outline-none focus:border-none hover:text-white"
onClick={() => clear()} onClick={() => clear()}
> >
<XCircleIcon className="w-5 h-5" /> <XCircleIcon />
</button> </button>
)} )}
</div> </div>

@ -104,8 +104,10 @@ const LocalLogin: React.FC<LocalLoginProps> = ({ revalidate }) => {
<span className="inline-flex rounded-md shadow-sm"> <span className="inline-flex rounded-md shadow-sm">
<Link href="/resetpassword" passHref> <Link href="/resetpassword" passHref>
<Button as="a" buttonType="ghost"> <Button as="a" buttonType="ghost">
<SupportIcon className="w-5 h-5 mr-1" /> <SupportIcon />
{intl.formatMessage(messages.forgotpassword)} <span>
{intl.formatMessage(messages.forgotpassword)}
</span>
</Button> </Button>
</Link> </Link>
</span> </span>
@ -115,10 +117,12 @@ const LocalLogin: React.FC<LocalLoginProps> = ({ revalidate }) => {
type="submit" type="submit"
disabled={isSubmitting || !isValid} disabled={isSubmitting || !isValid}
> >
<LoginIcon className="w-5 h-5 mr-1" /> <LoginIcon />
{isSubmitting <span>
? intl.formatMessage(messages.signingin) {isSubmitting
: intl.formatMessage(messages.signin)} ? intl.formatMessage(messages.signingin)
: intl.formatMessage(messages.signin)}
</span>
</Button> </Button>
</span> </span>
</div> </div>

@ -139,7 +139,7 @@ const MediaSlider: React.FC<MediaSliderProps> = ({
<Link href={linkUrl}> <Link href={linkUrl}>
<a className="slider-title"> <a className="slider-title">
<span>{title}</span> <span>{title}</span>
<ArrowCircleRightIcon className="w-6 h-6 ml-2" /> <ArrowCircleRightIcon />
</a> </a>
</Link> </Link>
) : ( ) : (

@ -116,7 +116,7 @@ const MovieDetails: React.FC<MovieDetailsProps> = ({ movie }) => {
mediaLinks.push({ mediaLinks.push({
text: intl.formatMessage(messages.playonplex), text: intl.formatMessage(messages.playonplex),
url: data.mediaInfo?.plexUrl, url: data.mediaInfo?.plexUrl,
svg: <PlayIcon className="w-5 h-5 mr-1" />, svg: <PlayIcon />,
}); });
} }
@ -129,7 +129,7 @@ const MovieDetails: React.FC<MovieDetailsProps> = ({ movie }) => {
mediaLinks.push({ mediaLinks.push({
text: intl.formatMessage(messages.play4konplex), text: intl.formatMessage(messages.play4konplex),
url: data.mediaInfo?.plexUrl4k, url: data.mediaInfo?.plexUrl4k,
svg: <PlayIcon className="w-5 h-5 mr-1" />, svg: <PlayIcon />,
}); });
} }
@ -142,7 +142,7 @@ const MovieDetails: React.FC<MovieDetailsProps> = ({ movie }) => {
mediaLinks.push({ mediaLinks.push({
text: intl.formatMessage(messages.watchtrailer), text: intl.formatMessage(messages.watchtrailer),
url: trailerUrl, url: trailerUrl,
svg: <FilmIcon className="w-5 h-5 mr-1" />, svg: <FilmIcon />,
}); });
} }
@ -280,7 +280,7 @@ const MovieDetails: React.FC<MovieDetailsProps> = ({ movie }) => {
className="w-full sm:mb-0" className="w-full sm:mb-0"
buttonType="success" buttonType="success"
> >
<CheckCircleIcon className="w-5 h-5 mr-1" /> <CheckCircleIcon />
<span>{intl.formatMessage(messages.markavailable)}</span> <span>{intl.formatMessage(messages.markavailable)}</span>
</Button> </Button>
</div> </div>
@ -294,7 +294,7 @@ const MovieDetails: React.FC<MovieDetailsProps> = ({ movie }) => {
className="w-full sm:mb-0" className="w-full sm:mb-0"
buttonType="success" buttonType="success"
> >
<CheckCircleIcon className="w-5 h-5 mr-1" /> <CheckCircleIcon />
<span> <span>
{intl.formatMessage(messages.mark4kavailable)} {intl.formatMessage(messages.mark4kavailable)}
</span> </span>
@ -333,7 +333,7 @@ const MovieDetails: React.FC<MovieDetailsProps> = ({ movie }) => {
className="block mb-2 last:mb-0" className="block mb-2 last:mb-0"
> >
<Button buttonType="ghost" className="w-full"> <Button buttonType="ghost" className="w-full">
<ExternalLinkIcon className="w-5 h-5 mr-1" /> <ExternalLinkIcon />
<span>{intl.formatMessage(messages.openradarr)}</span> <span>{intl.formatMessage(messages.openradarr)}</span>
</Button> </Button>
</a> </a>
@ -345,7 +345,7 @@ const MovieDetails: React.FC<MovieDetailsProps> = ({ movie }) => {
rel="noreferrer" rel="noreferrer"
> >
<Button buttonType="ghost" className="w-full"> <Button buttonType="ghost" className="w-full">
<ExternalLinkIcon className="w-5 h-5 mr-1" /> <ExternalLinkIcon />
<span>{intl.formatMessage(messages.openradarr4k)}</span> <span>{intl.formatMessage(messages.openradarr4k)}</span>
</Button> </Button>
</a> </a>
@ -359,10 +359,10 @@ const MovieDetails: React.FC<MovieDetailsProps> = ({ movie }) => {
confirmText={intl.formatMessage(globalMessages.areyousure)} confirmText={intl.formatMessage(globalMessages.areyousure)}
className="w-full" className="w-full"
> >
<DocumentRemoveIcon className="w-5 h-5 mr-1" /> <DocumentRemoveIcon />
{intl.formatMessage(messages.manageModalClearMedia)} <span>{intl.formatMessage(messages.manageModalClearMedia)}</span>
</ConfirmButton> </ConfirmButton>
<div className="mt-2 text-sm text-gray-400"> <div className="mt-3 text-xs text-gray-400">
{intl.formatMessage(messages.manageModalClearMediaWarning)} {intl.formatMessage(messages.manageModalClearMediaWarning)}
</div> </div>
</div> </div>
@ -470,7 +470,7 @@ const MovieDetails: React.FC<MovieDetailsProps> = ({ movie }) => {
<Link href={`/movie/${data.id}/crew`}> <Link href={`/movie/${data.id}/crew`}>
<a className="flex items-center text-gray-400 transition duration-300 hover:text-gray-100"> <a className="flex items-center text-gray-400 transition duration-300 hover:text-gray-100">
<span>{intl.formatMessage(messages.viewfullcrew)}</span> <span>{intl.formatMessage(messages.viewfullcrew)}</span>
<ArrowCircleRightIcon className="inline-block w-5 h-5 ml-1" /> <ArrowCircleRightIcon className="inline-block w-5 h-5 ml-1.5" />
</a> </a>
</Link> </Link>
</div> </div>
@ -653,7 +653,7 @@ const MovieDetails: React.FC<MovieDetailsProps> = ({ movie }) => {
<Link href="/movie/[movieId]/cast" as={`/movie/${data.id}/cast`}> <Link href="/movie/[movieId]/cast" as={`/movie/${data.id}/cast`}>
<a className="slider-title"> <a className="slider-title">
<span>{intl.formatMessage(messages.cast)}</span> <span>{intl.formatMessage(messages.cast)}</span>
<ArrowCircleRightIcon className="w-6 h-6 ml-2" /> <ArrowCircleRightIcon />
</a> </a>
</Link> </Link>
</div> </div>

@ -49,12 +49,14 @@ const PlexLoginButton: React.FC<PlexLoginButtonProps> = ({
disabled={loading || isProcessing} disabled={loading || isProcessing}
className="plex-button" className="plex-button"
> >
<LoginIcon className="w-5 h-5 mr-1" /> <LoginIcon />
{loading <span>
? intl.formatMessage(globalMessages.loading) {loading
: isProcessing ? intl.formatMessage(globalMessages.loading)
? intl.formatMessage(messages.signingin) : isProcessing
: intl.formatMessage(messages.signinwithplex)} ? intl.formatMessage(messages.signingin)
: intl.formatMessage(messages.signinwithplex)}
</span>
</button> </button>
</span> </span>
); );

@ -125,8 +125,8 @@ const RegionSelector: React.FC<RegionSelectorProps> = ({
}) })
: intl.formatMessage(messages.regionDefault)} : intl.formatMessage(messages.regionDefault)}
</span> </span>
<span className="absolute inset-y-0 right-0 flex items-center pr-2 pointer-events-none"> <span className="absolute inset-y-0 right-0 flex items-center pr-2 text-gray-500 pointer-events-none">
<ChevronDownIcon className="w-5 h-5 text-gray-500" /> <ChevronDownIcon />
</span> </span>
</Listbox.Button> </Listbox.Button>
</span> </span>

@ -95,42 +95,42 @@ const RequestBlock: React.FC<RequestBlockProps> = ({ request, onUpdate }) => {
<div className="flex flex-wrap flex-shrink-0 ml-2"> <div className="flex flex-wrap flex-shrink-0 ml-2">
{request.status === MediaRequestStatus.PENDING && ( {request.status === MediaRequestStatus.PENDING && (
<> <>
<span className="mr-1"> <Button
<Button buttonType="success"
buttonType="success" buttonSize="sm"
onClick={() => updateRequest('approve')} className="mr-1"
disabled={isUpdating} onClick={() => updateRequest('approve')}
> disabled={isUpdating}
<CheckIcon className="w-4 h-4" /> >
</Button> <CheckIcon />
</span> </Button>
<span className="mr-1"> <Button
<Button buttonType="danger"
buttonType="danger" buttonSize="sm"
onClick={() => updateRequest('decline')} className="mr-1"
disabled={isUpdating} onClick={() => updateRequest('decline')}
> disabled={isUpdating}
<XIcon className="w-4 h-4" /> >
</Button> <XIcon />
</span> </Button>
<span> <Button
<Button buttonType="primary"
buttonType="primary" buttonSize="sm"
onClick={() => setShowEditModal(true)} onClick={() => setShowEditModal(true)}
disabled={isUpdating} disabled={isUpdating}
> >
<PencilIcon className="w-4 h-4" /> <PencilIcon />
</Button> </Button>
</span>
</> </>
)} )}
{request.status !== MediaRequestStatus.PENDING && ( {request.status !== MediaRequestStatus.PENDING && (
<Button <Button
buttonType="danger" buttonType="danger"
buttonSize="sm"
onClick={() => deleteRequest()} onClick={() => deleteRequest()}
disabled={isUpdating} disabled={isUpdating}
> >
<TrashIcon className="w-4 h-4" /> <TrashIcon />
</Button> </Button>
)} )}
</div> </div>

@ -132,7 +132,7 @@ const RequestButton: React.FC<RequestButtonProps> = ({
setEditRequest(false); setEditRequest(false);
setShowRequestModal(true); setShowRequestModal(true);
}, },
svg: <DownloadIcon className="w-5 h-5 mr-1" />, svg: <DownloadIcon />,
}); });
} }
@ -151,7 +151,7 @@ const RequestButton: React.FC<RequestButtonProps> = ({
setEditRequest(false); setEditRequest(false);
setShowRequest4kModal(true); setShowRequest4kModal(true);
}, },
svg: <DownloadIcon className="w-5 h-5 mr-1" />, svg: <DownloadIcon />,
}); });
} }
@ -168,7 +168,7 @@ const RequestButton: React.FC<RequestButtonProps> = ({
setEditRequest(true); setEditRequest(true);
setShowRequestModal(true); setShowRequestModal(true);
}, },
svg: <InformationCircleIcon className="w-5 h-5 mr-1" />, svg: <InformationCircleIcon />,
}); });
} }
@ -185,7 +185,7 @@ const RequestButton: React.FC<RequestButtonProps> = ({
setEditRequest(true); setEditRequest(true);
setShowRequest4kModal(true); setShowRequest4kModal(true);
}, },
svg: <InformationCircleIcon className="w-5 h-5 mr-1" />, svg: <InformationCircleIcon />,
}); });
} }
@ -201,7 +201,7 @@ const RequestButton: React.FC<RequestButtonProps> = ({
action: () => { action: () => {
modifyRequest(activeRequest, 'approve'); modifyRequest(activeRequest, 'approve');
}, },
svg: <CheckIcon className="w-5 h-5 mr-1" />, svg: <CheckIcon />,
}, },
{ {
id: 'decline-request', id: 'decline-request',
@ -209,7 +209,7 @@ const RequestButton: React.FC<RequestButtonProps> = ({
action: () => { action: () => {
modifyRequest(activeRequest, 'decline'); modifyRequest(activeRequest, 'decline');
}, },
svg: <XIcon className="w-5 h-5 mr-1" />, svg: <XIcon />,
} }
); );
} }
@ -229,7 +229,7 @@ const RequestButton: React.FC<RequestButtonProps> = ({
action: () => { action: () => {
modifyRequests(activeRequests, 'approve'); modifyRequests(activeRequests, 'approve');
}, },
svg: <CheckIcon className="w-5 h-5 mr-1" />, svg: <CheckIcon />,
}, },
{ {
id: 'decline-request-batch', id: 'decline-request-batch',
@ -239,7 +239,7 @@ const RequestButton: React.FC<RequestButtonProps> = ({
action: () => { action: () => {
modifyRequests(activeRequests, 'decline'); modifyRequests(activeRequests, 'decline');
}, },
svg: <XIcon className="w-5 h-5 mr-1" />, svg: <XIcon />,
} }
); );
} }
@ -256,7 +256,7 @@ const RequestButton: React.FC<RequestButtonProps> = ({
action: () => { action: () => {
modifyRequest(active4kRequest, 'approve'); modifyRequest(active4kRequest, 'approve');
}, },
svg: <CheckIcon className="w-5 h-5 mr-1" />, svg: <CheckIcon />,
}, },
{ {
id: 'decline-4k-request', id: 'decline-4k-request',
@ -264,7 +264,7 @@ const RequestButton: React.FC<RequestButtonProps> = ({
action: () => { action: () => {
modifyRequest(active4kRequest, 'decline'); modifyRequest(active4kRequest, 'decline');
}, },
svg: <XIcon className="w-5 h-5 mr-1" />, svg: <XIcon />,
} }
); );
} }
@ -284,7 +284,7 @@ const RequestButton: React.FC<RequestButtonProps> = ({
action: () => { action: () => {
modifyRequests(active4kRequests, 'approve'); modifyRequests(active4kRequests, 'approve');
}, },
svg: <CheckIcon className="w-5 h-5 mr-1" />, svg: <CheckIcon />,
}, },
{ {
id: 'decline-4k-request-batch', id: 'decline-4k-request-batch',
@ -294,7 +294,7 @@ const RequestButton: React.FC<RequestButtonProps> = ({
action: () => { action: () => {
modifyRequests(active4kRequests, 'decline'); modifyRequests(active4kRequests, 'decline');
}, },
svg: <XIcon className="w-5 h-5 mr-1" />, svg: <XIcon />,
} }
); );
} }
@ -315,7 +315,7 @@ const RequestButton: React.FC<RequestButtonProps> = ({
setEditRequest(false); setEditRequest(false);
setShowRequestModal(true); setShowRequestModal(true);
}, },
svg: <DownloadIcon className="w-5 h-5 mr-1" />, svg: <DownloadIcon />,
}); });
} }
@ -338,7 +338,7 @@ const RequestButton: React.FC<RequestButtonProps> = ({
setEditRequest(false); setEditRequest(false);
setShowRequest4kModal(true); setShowRequest4kModal(true);
}, },
svg: <DownloadIcon className="w-5 h-5 mr-1" />, svg: <DownloadIcon />,
}); });
} }
@ -376,8 +376,8 @@ const RequestButton: React.FC<RequestButtonProps> = ({
<ButtonWithDropdown <ButtonWithDropdown
text={ text={
<> <>
{buttonOne.svg ?? null} {buttonOne.svg}
{buttonOne.text} <span>{buttonOne.text}</span>
</> </>
} }
onClick={buttonOne.action} onClick={buttonOne.action}
@ -390,7 +390,7 @@ const RequestButton: React.FC<RequestButtonProps> = ({
key={`request-option-${button.id}`} key={`request-option-${button.id}`}
> >
{button.svg} {button.svg}
{button.text} <span>{button.text}</span>
</ButtonWithDropdown.Item> </ButtonWithDropdown.Item>
)) ))
: null} : null}

@ -62,16 +62,15 @@ const RequestCardError: React.FC<RequestCardErrorProps> = ({ mediaId }) => {
{intl.formatMessage(messages.mediaerror)} {intl.formatMessage(messages.mediaerror)}
</div> </div>
{hasPermission(Permission.MANAGE_REQUESTS) && mediaId && ( {hasPermission(Permission.MANAGE_REQUESTS) && mediaId && (
<div className="mt-4"> <Button
<Button buttonType="danger"
buttonType="danger" buttonSize="sm"
buttonSize="sm" className="mt-4"
onClick={() => deleteRequest()} onClick={() => deleteRequest()}
> >
<TrashIcon className="w-5 h-5 mr-1" /> <TrashIcon />
<span>{intl.formatMessage(messages.deleterequest)}</span> <span>{intl.formatMessage(messages.deleterequest)}</span>
</Button> </Button>
</div>
)} )}
</div> </div>
</div> </div>
@ -240,31 +239,27 @@ const RequestCard: React.FC<RequestCardProps> = ({ request, onTitleData }) => {
</div> </div>
{requestData.status === MediaRequestStatus.PENDING && {requestData.status === MediaRequestStatus.PENDING &&
hasPermission(Permission.MANAGE_REQUESTS) && ( hasPermission(Permission.MANAGE_REQUESTS) && (
<div className="flex items-end flex-1"> <div className="flex items-end flex-1 space-x-2">
<span className="mr-2"> <Button
<Button buttonType="success"
buttonType="success" buttonSize="sm"
buttonSize="sm" onClick={() => modifyRequest('approve')}
onClick={() => modifyRequest('approve')} >
> <CheckIcon style={{ marginRight: '0' }} />
<CheckIcon className="w-4 h-4 mr-0 sm:mr-1" /> <span className="hidden ml-1.5 sm:block">
<span className="hidden sm:block"> {intl.formatMessage(globalMessages.approve)}
{intl.formatMessage(globalMessages.approve)} </span>
</span> </Button>
</Button> <Button
</span> buttonType="danger"
<span> buttonSize="sm"
<Button onClick={() => modifyRequest('decline')}
buttonType="danger" >
buttonSize="sm" <XIcon style={{ marginRight: '0' }} />
onClick={() => modifyRequest('decline')} <span className="hidden ml-1.5 sm:block">
> {intl.formatMessage(globalMessages.decline)}
<XIcon className="w-4 h-4 mr-0 sm:mr-1" /> </span>
<span className="hidden sm:block"> </Button>
{intl.formatMessage(globalMessages.decline)}
</span>
</Button>
</span>
</div> </div>
)} )}
</div> </div>

@ -73,7 +73,7 @@ const RequestItemError: React.FC<RequestItemErroProps> = ({
buttonSize="sm" buttonSize="sm"
onClick={() => deleteRequest()} onClick={() => deleteRequest()}
> >
<TrashIcon className="w-5 h-5 mr-1" /> <TrashIcon />
<span>{intl.formatMessage(messages.deleterequest)}</span> <span>{intl.formatMessage(messages.deleterequest)}</span>
</Button> </Button>
</div> </div>
@ -373,10 +373,10 @@ const RequestItem: React.FC<RequestItemProps> = ({
onClick={() => retryRequest()} onClick={() => retryRequest()}
> >
<RefreshIcon <RefreshIcon
className={`w-5 h-5 mr-1 ${isRetrying ? 'animate-spin' : ''}`} className={isRetrying ? 'animate-spin' : ''}
style={{ animationDirection: 'reverse' }} style={{ animationDirection: 'reverse' }}
/> />
<span className="block"> <span>
{intl.formatMessage( {intl.formatMessage(
isRetrying ? globalMessages.retrying : globalMessages.retry isRetrying ? globalMessages.retrying : globalMessages.retry
)} )}
@ -390,10 +390,8 @@ const RequestItem: React.FC<RequestItemProps> = ({
confirmText={intl.formatMessage(globalMessages.areyousure)} confirmText={intl.formatMessage(globalMessages.areyousure)}
className="w-full" className="w-full"
> >
<TrashIcon className="w-5 h-5 mr-1" /> <TrashIcon />
<span className="block"> <span>{intl.formatMessage(messages.deleterequest)}</span>
{intl.formatMessage(messages.deleterequest)}
</span>
</ConfirmButton> </ConfirmButton>
)} )}
{requestData.status === MediaRequestStatus.PENDING && {requestData.status === MediaRequestStatus.PENDING &&
@ -405,10 +403,8 @@ const RequestItem: React.FC<RequestItemProps> = ({
buttonType="success" buttonType="success"
onClick={() => modifyRequest('approve')} onClick={() => modifyRequest('approve')}
> >
<CheckIcon className="w-5 h-5 mr-1" /> <CheckIcon />
<span className="block"> <span>{intl.formatMessage(globalMessages.approve)}</span>
{intl.formatMessage(globalMessages.approve)}
</span>
</Button> </Button>
</span> </span>
<span className="w-full"> <span className="w-full">
@ -417,10 +413,8 @@ const RequestItem: React.FC<RequestItemProps> = ({
buttonType="danger" buttonType="danger"
onClick={() => modifyRequest('decline')} onClick={() => modifyRequest('decline')}
> >
<XIcon className="w-5 h-5 mr-1" /> <XIcon />
<span className="block"> <span>{intl.formatMessage(globalMessages.decline)}</span>
{intl.formatMessage(globalMessages.decline)}
</span>
</Button> </Button>
</span> </span>
</div> </div>
@ -436,10 +430,8 @@ const RequestItem: React.FC<RequestItemProps> = ({
buttonType="primary" buttonType="primary"
onClick={() => setShowEditModal(true)} onClick={() => setShowEditModal(true)}
> >
<PencilIcon className="w-5 h-5 mr-1" /> <PencilIcon />
<span className="block"> <span>{intl.formatMessage(messages.editrequest)}</span>
{intl.formatMessage(messages.editrequest)}
</span>
</Button> </Button>
</span> </span>
)} )}
@ -451,10 +443,8 @@ const RequestItem: React.FC<RequestItemProps> = ({
confirmText={intl.formatMessage(globalMessages.areyousure)} confirmText={intl.formatMessage(globalMessages.areyousure)}
className="w-full" className="w-full"
> >
<XIcon className="w-5 h-5 mr-1" /> <XIcon />
<span className="block"> <span>{intl.formatMessage(messages.cancelRequest)}</span>
{intl.formatMessage(messages.cancelRequest)}
</span>
</ConfirmButton> </ConfirmButton>
)} )}
</div> </div>

@ -1,10 +1,7 @@
/* eslint-disable react-hooks/exhaustive-deps */ /* eslint-disable react-hooks/exhaustive-deps */
import { Listbox, Transition } from '@headlessui/react'; import { Listbox, Transition } from '@headlessui/react';
import { import { AdjustmentsIcon } from '@heroicons/react/outline';
AdjustmentsIcon, import { CheckIcon, ChevronDownIcon } from '@heroicons/react/solid';
CheckIcon,
ChevronDownIcon,
} from '@heroicons/react/solid';
import { isEqual } from 'lodash'; import { isEqual } from 'lodash';
import dynamic from 'next/dynamic'; import dynamic from 'next/dynamic';
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
@ -274,7 +271,7 @@ const AdvancedRequester: React.FC<AdvancedRequesterProps> = ({
return ( return (
<> <>
<div className="flex items-center mb-2 font-bold tracking-wider"> <div className="flex items-center mb-2 font-bold tracking-wider">
<AdjustmentsIcon className="w-5 h-5 mr-1" /> <AdjustmentsIcon className="w-5 h-5 mr-1.5" />
{intl.formatMessage(messages.advancedoptions)} {intl.formatMessage(messages.advancedoptions)}
</div> </div>
<div className="p-4 bg-gray-600 rounded-md shadow"> <div className="p-4 bg-gray-600 rounded-md shadow">
@ -522,8 +519,8 @@ const AdvancedRequester: React.FC<AdvancedRequesterProps> = ({
({selectedUser.email}) ({selectedUser.email})
</span> </span>
</span> </span>
<span className="absolute inset-y-0 right-0 flex items-center pr-2 pointer-events-none"> <span className="absolute inset-y-0 right-0 flex items-center pr-2 text-gray-500 pointer-events-none">
<ChevronDownIcon className="w-5 h-5 text-gray-500" /> <ChevronDownIcon />
</span> </span>
</Listbox.Button> </Listbox.Button>
</span> </span>

@ -236,7 +236,7 @@ const MovieRequestModal: React.FC<RequestModalProps> = ({
} }
secondaryButtonType="danger" secondaryButtonType="danger"
cancelText={intl.formatMessage(globalMessages.close)} cancelText={intl.formatMessage(globalMessages.close)}
iconSvg={<DownloadIcon className="w-6 h-6" />} iconSvg={<DownloadIcon />}
> >
{isOwner {isOwner
? intl.formatMessage(messages.pendingapproval) ? intl.formatMessage(messages.pendingapproval)
@ -294,7 +294,7 @@ const MovieRequestModal: React.FC<RequestModalProps> = ({
) )
} }
okButtonType={'primary'} okButtonType={'primary'}
iconSvg={<DownloadIcon className="w-6 h-6" />} iconSvg={<DownloadIcon />}
> >
{hasAutoApprove && !quota?.movie.restricted && ( {hasAutoApprove && !quota?.movie.restricted && (
<div className="mt-6"> <div className="mt-6">

@ -52,7 +52,7 @@ const SearchByNameModal: React.FC<SearchByNameModalProps> = ({
okText={intl.formatMessage(globalMessages.next)} okText={intl.formatMessage(globalMessages.next)}
okDisabled={!tvdbId} okDisabled={!tvdbId}
okButtonType="primary" okButtonType="primary"
iconSvg={<DownloadIcon className="w-6 h-6" />} iconSvg={<DownloadIcon />}
> >
<Alert <Alert
title={intl.formatMessage(messages.notvdbiddescription)} title={intl.formatMessage(messages.notvdbiddescription)}

@ -419,7 +419,7 @@ const TvRequestModal: React.FC<RequestModalProps> = ({
? intl.formatMessage(globalMessages.back) ? intl.formatMessage(globalMessages.back)
: intl.formatMessage(globalMessages.cancel) : intl.formatMessage(globalMessages.cancel)
} }
iconSvg={<DownloadIcon className="w-6 h-6" />} iconSvg={<DownloadIcon />}
> >
{editRequest {editRequest
? isOwner ? isOwner

@ -124,8 +124,10 @@ const ResetPassword: React.FC = () => {
type="submit" type="submit"
disabled={isSubmitting || !isValid} disabled={isSubmitting || !isValid}
> >
<AtSymbolIcon className="w-5 h-5 mr-1" /> <AtSymbolIcon />
{intl.formatMessage(messages.emailresetlink)} <span>
{intl.formatMessage(messages.emailresetlink)}
</span>
</Button> </Button>
</span> </span>
</div> </div>

@ -32,7 +32,7 @@ const CopyButton: React.FC<{ textToCopy: string }> = ({ textToCopy }) => {
}} }}
className="relative inline-flex items-center px-4 py-2 -ml-px text-sm font-medium leading-5 text-white transition duration-150 ease-in-out bg-indigo-600 border border-gray-500 hover:bg-indigo-500 focus:outline-none focus:ring-blue focus:border-blue-300 active:bg-gray-100 active:text-gray-700" className="relative inline-flex items-center px-4 py-2 -ml-px text-sm font-medium leading-5 text-white transition duration-150 ease-in-out bg-indigo-600 border border-gray-500 hover:bg-indigo-500 focus:outline-none focus:ring-blue focus:border-blue-300 active:bg-gray-100 active:text-gray-700"
> >
<ClipboardCopyIcon className="w-5 h-5 text-white" /> <ClipboardCopyIcon />
</button> </button>
); );
}; };

@ -2,6 +2,7 @@ import { QuestionMarkCircleIcon, RefreshIcon } from '@heroicons/react/solid';
import axios from 'axios'; import axios from 'axios';
import { Field, Form, Formik } from 'formik'; import { Field, Form, Formik } from 'formik';
import dynamic from 'next/dynamic'; import dynamic from 'next/dynamic';
import Link from 'next/link';
import React, { useState } from 'react'; import React, { useState } from 'react';
import { defineMessages, useIntl } from 'react-intl'; import { defineMessages, useIntl } from 'react-intl';
import { useToasts } from 'react-toast-notifications'; import { useToasts } from 'react-toast-notifications';
@ -263,18 +264,25 @@ const NotificationsWebhook: React.FC = () => {
}} }}
className="mr-2" className="mr-2"
> >
<RefreshIcon className="w-5 h-5 mr-1" /> <RefreshIcon />
{intl.formatMessage(messages.resetPayload)} <span>{intl.formatMessage(messages.resetPayload)}</span>
</Button> </Button>
<a <Link
href="https://docs.overseerr.dev/using-overseerr/notifications/webhooks#template-variables" href="https://docs.overseerr.dev/using-overseerr/notifications/webhooks#template-variables"
target="_blank" passHref
rel="noreferrer"
className="inline-flex items-center justify-center font-medium leading-5 text-white transition duration-150 ease-in-out bg-indigo-600 border border-transparent rounded-md focus:outline-none hover:bg-indigo-500 focus:border-indigo-700 focus:ring-indigo active:bg-indigo-700 disabled:opacity-50 px-2.5 py-1.5 text-xs"
> >
<QuestionMarkCircleIcon className="w-5 h-5 mr-1" /> <Button
{intl.formatMessage(messages.templatevariablehelp)} as="a"
</a> buttonSize="sm"
target="_blank"
rel="noreferrer"
>
<QuestionMarkCircleIcon />
<span>
{intl.formatMessage(messages.templatevariablehelp)}
</span>
</Button>
</Link>
</div> </div>
</div> </div>
</div> </div>

@ -357,13 +357,7 @@ const RadarrModal: React.FC<RadarrModalProps> = ({
values.is4k ? messages.edit4kradarr : messages.editradarr values.is4k ? messages.edit4kradarr : messages.editradarr
) )
} }
iconSvg={ iconSvg={!radarr ? <PlusIcon /> : <PencilIcon />}
!radarr ? (
<PlusIcon className="w-6 h-6" />
) : (
<PencilIcon className="w-6 h-6" />
)
}
> >
<div className="mb-6"> <div className="mb-6">
<div className="form-row"> <div className="form-row">

@ -71,7 +71,7 @@ const Release: React.FC<ReleaseProps> = ({
> >
<Modal <Modal
onCancel={() => setModalOpen(false)} onCancel={() => setModalOpen(false)}
iconSvg={<DocumentTextIcon className="w-6 h-6" />} iconSvg={<DocumentTextIcon />}
title={intl.formatMessage(messages.versionChangelog)} title={intl.formatMessage(messages.versionChangelog)}
cancelText={intl.formatMessage(globalMessages.close)} cancelText={intl.formatMessage(globalMessages.close)}
okText={intl.formatMessage(messages.viewongithub)} okText={intl.formatMessage(messages.viewongithub)}
@ -112,8 +112,8 @@ const Release: React.FC<ReleaseProps> = ({
</div> </div>
<div className="flex-1 text-center sm:text-right"> <div className="flex-1 text-center sm:text-right">
<Button buttonType="primary" onClick={() => setModalOpen(true)}> <Button buttonType="primary" onClick={() => setModalOpen(true)}>
<DocumentTextIcon className="w-5 h-5 mr-1" /> <DocumentTextIcon />
{intl.formatMessage(messages.viewchangelog)} <span>{intl.formatMessage(messages.viewchangelog)}</span>
</Button> </Button>
</div> </div>
</div> </div>

@ -181,13 +181,13 @@ const SettingsJobs: React.FC = () => {
<Table.TD alignText="right"> <Table.TD alignText="right">
{job.running ? ( {job.running ? (
<Button buttonType="danger" onClick={() => cancelJob(job)}> <Button buttonType="danger" onClick={() => cancelJob(job)}>
<StopIcon className="w-5 h-5 mr-1" /> <StopIcon />
{intl.formatMessage(messages.canceljob)} <span>{intl.formatMessage(messages.canceljob)}</span>
</Button> </Button>
) : ( ) : (
<Button buttonType="primary" onClick={() => runJob(job)}> <Button buttonType="primary" onClick={() => runJob(job)}>
<PlayIcon className="w-5 h-5 mr-1" /> <PlayIcon className="w-5 h-5 mr-1" />
{intl.formatMessage(messages.runnow)} <span>{intl.formatMessage(messages.runnow)}</span>
</Button> </Button>
)} )}
</Table.TD> </Table.TD>
@ -226,8 +226,8 @@ const SettingsJobs: React.FC = () => {
<Table.TD>{formatBytes(cache.stats.vsize)}</Table.TD> <Table.TD>{formatBytes(cache.stats.vsize)}</Table.TD>
<Table.TD alignText="right"> <Table.TD alignText="right">
<Button buttonType="danger" onClick={() => flushCache(cache)}> <Button buttonType="danger" onClick={() => flushCache(cache)}>
<TrashIcon className="w-5 h-5 mr-1" /> <TrashIcon />
{intl.formatMessage(messages.flushcache)} <span>{intl.formatMessage(messages.flushcache)}</span>
</Button> </Button>
</Table.TD> </Table.TD>
</tr> </tr>

@ -142,7 +142,7 @@ const SettingsLogs: React.FC = () => {
> >
<Modal <Modal
title={intl.formatMessage(messages.logDetails)} title={intl.formatMessage(messages.logDetails)}
iconSvg={<DocumentSearchIcon className="w-6 h-6" />} iconSvg={<DocumentSearchIcon />}
onCancel={() => setActiveLog(null)} onCancel={() => setActiveLog(null)}
cancelText={intl.formatMessage(globalMessages.close)} cancelText={intl.formatMessage(globalMessages.close)}
onOk={() => (activeLog ? copyLogString(activeLog) : undefined)} onOk={() => (activeLog ? copyLogString(activeLog) : undefined)}
@ -243,13 +243,7 @@ const SettingsLogs: React.FC = () => {
buttonType={refreshInterval ? 'default' : 'primary'} buttonType={refreshInterval ? 'default' : 'primary'}
onClick={() => toggleLogs()} onClick={() => toggleLogs()}
> >
<span> {refreshInterval ? <PauseIcon /> : <PlayIcon />}
{refreshInterval ? (
<PauseIcon className="w-5 h-5 mr-1" />
) : (
<PlayIcon className="w-5 h-5 mr-1" />
)}
</span>
<span> <span>
{intl.formatMessage( {intl.formatMessage(
refreshInterval ? messages.pauseLogs : messages.resumeLogs refreshInterval ? messages.pauseLogs : messages.resumeLogs
@ -335,7 +329,7 @@ const SettingsLogs: React.FC = () => {
onClick={() => setActiveLog(row)} onClick={() => setActiveLog(row)}
className="mr-2" className="mr-2"
> >
<DocumentSearchIcon className="w-5 h-5 text-white" /> <DocumentSearchIcon />
</Button> </Button>
)} )}
<Button <Button
@ -343,7 +337,7 @@ const SettingsLogs: React.FC = () => {
buttonSize="sm" buttonSize="sm"
onClick={() => copyLogString(row)} onClick={() => copyLogString(row)}
> >
<ClipboardCopyIcon className="w-5 h-5 text-white" /> <ClipboardCopyIcon />
</Button> </Button>
</Table.TD> </Table.TD>
</tr> </tr>

@ -205,7 +205,7 @@ const SettingsMain: React.FC = () => {
}} }}
className="relative inline-flex items-center px-4 py-2 -ml-px text-sm font-medium leading-5 text-white transition duration-150 ease-in-out bg-indigo-600 border border-gray-500 rounded-r-md hover:bg-indigo-500 focus:outline-none focus:ring-blue focus:border-blue-300 active:bg-gray-100 active:text-gray-700" className="relative inline-flex items-center px-4 py-2 -ml-px text-sm font-medium leading-5 text-white transition duration-150 ease-in-out bg-indigo-600 border border-gray-500 rounded-r-md hover:bg-indigo-500 focus:outline-none focus:ring-blue focus:border-blue-300 active:bg-gray-100 active:text-gray-700"
> >
<RefreshIcon className="w-5 h-5" /> <RefreshIcon />
</button> </button>
</div> </div>
</div> </div>

@ -435,9 +435,7 @@ const SettingsPlex: React.FC<SettingsPlexProps> = ({ onComplete }) => {
className="relative inline-flex items-center px-4 py-2 -ml-px text-sm font-medium leading-5 text-white transition duration-150 ease-in-out bg-indigo-600 border border-gray-500 rounded-r-md hover:bg-indigo-500 focus:outline-none focus:ring-blue focus:border-blue-300 active:bg-gray-100 active:text-gray-700" className="relative inline-flex items-center px-4 py-2 -ml-px text-sm font-medium leading-5 text-white transition duration-150 ease-in-out bg-indigo-600 border border-gray-500 rounded-r-md hover:bg-indigo-500 focus:outline-none focus:ring-blue focus:border-blue-300 active:bg-gray-100 active:text-gray-700"
> >
<RefreshIcon <RefreshIcon
className={`w-5 h-5 ${ className={isRefreshingPresets ? 'animate-spin' : ''}
isRefreshingPresets ? 'animate-spin' : ''
}`}
style={{ animationDirection: 'reverse' }} style={{ animationDirection: 'reverse' }}
/> />
</button> </button>
@ -530,7 +528,7 @@ const SettingsPlex: React.FC<SettingsPlexProps> = ({ onComplete }) => {
<div className="section"> <div className="section">
<Button onClick={() => syncLibraries()} disabled={isSyncing}> <Button onClick={() => syncLibraries()} disabled={isSyncing}>
<RefreshIcon <RefreshIcon
className={`w-5 h-5 mr-1 ${isSyncing ? 'animate-spin' : ''}`} className={isSyncing ? 'animate-spin' : ''}
style={{ animationDirection: 'reverse' }} style={{ animationDirection: 'reverse' }}
/> />
{isSyncing {isSyncing
@ -606,14 +604,14 @@ const SettingsPlex: React.FC<SettingsPlexProps> = ({ onComplete }) => {
<div className="flex-1 text-right"> <div className="flex-1 text-right">
{!dataSync?.running && ( {!dataSync?.running && (
<Button buttonType="warning" onClick={() => startScan()}> <Button buttonType="warning" onClick={() => startScan()}>
<SearchIcon className="w-5 h-5 mr-1" /> <SearchIcon />
{intl.formatMessage(messages.startscan)} {intl.formatMessage(messages.startscan)}
</Button> </Button>
)} )}
{dataSync?.running && ( {dataSync?.running && (
<Button buttonType="danger" onClick={() => cancelScan()}> <Button buttonType="danger" onClick={() => cancelScan()}>
<XIcon className="w-5 h-5 mr-1" /> <XIcon />
{intl.formatMessage(messages.cancelscan)} {intl.formatMessage(messages.cancelscan)}
</Button> </Button>
)} )}

@ -139,8 +139,8 @@ const ServerInstance: React.FC<ServerInstanceProps> = ({
onClick={() => onEdit()} onClick={() => onEdit()}
className="relative inline-flex items-center justify-center flex-1 w-0 py-4 -mr-px text-sm font-medium leading-5 text-gray-200 transition duration-150 ease-in-out border border-transparent rounded-bl-lg hover:text-white focus:outline-none focus:ring-blue focus:border-gray-500 focus:z-10" className="relative inline-flex items-center justify-center flex-1 w-0 py-4 -mr-px text-sm font-medium leading-5 text-gray-200 transition duration-150 ease-in-out border border-transparent rounded-bl-lg hover:text-white focus:outline-none focus:ring-blue focus:border-gray-500 focus:z-10"
> >
<PencilIcon className="w-5 h-5 mr-2" /> <PencilIcon />
{intl.formatMessage(globalMessages.edit)} <span>{intl.formatMessage(globalMessages.edit)}</span>
</button> </button>
</div> </div>
<div className="flex flex-1 w-0 -ml-px"> <div className="flex flex-1 w-0 -ml-px">
@ -148,8 +148,8 @@ const ServerInstance: React.FC<ServerInstanceProps> = ({
onClick={() => onDelete()} onClick={() => onDelete()}
className="relative inline-flex items-center justify-center flex-1 w-0 py-4 text-sm font-medium leading-5 text-gray-200 transition duration-150 ease-in-out border border-transparent rounded-br-lg hover:text-white focus:outline-none focus:ring-blue focus:border-gray-500 focus:z-10" className="relative inline-flex items-center justify-center flex-1 w-0 py-4 text-sm font-medium leading-5 text-gray-200 transition duration-150 ease-in-out border border-transparent rounded-br-lg hover:text-white focus:outline-none focus:ring-blue focus:border-gray-500 focus:z-10"
> >
<TrashIcon className="w-5 h-5 mr-2" /> <TrashIcon />
{intl.formatMessage(globalMessages.delete)} <span>{intl.formatMessage(globalMessages.delete)}</span>
</button> </button>
</div> </div>
</div> </div>
@ -265,7 +265,7 @@ const SettingsServices: React.FC = () => {
}) })
} }
title="Delete Server" title="Delete Server"
iconSvg={<TrashIcon className="w-6 h-6" />} iconSvg={<TrashIcon />}
> >
{intl.formatMessage(messages.deleteserverconfirm)} {intl.formatMessage(messages.deleteserverconfirm)}
</Modal> </Modal>
@ -341,8 +341,8 @@ const SettingsServices: React.FC = () => {
setEditRadarrModal({ open: true, radarr: null }) setEditRadarrModal({ open: true, radarr: null })
} }
> >
<PlusIcon className="w-5 h-5 mr-1" /> <PlusIcon />
{intl.formatMessage(messages.addradarr)} <span>{intl.formatMessage(messages.addradarr)}</span>
</Button> </Button>
</div> </div>
</li> </li>
@ -431,8 +431,8 @@ const SettingsServices: React.FC = () => {
setEditSonarrModal({ open: true, sonarr: null }) setEditSonarrModal({ open: true, sonarr: null })
} }
> >
<PlusIcon className="w-5 h-5 mr-1" /> <PlusIcon />
{intl.formatMessage(messages.addsonarr)} <span>{intl.formatMessage(messages.addsonarr)}</span>
</Button> </Button>
</div> </div>
</li> </li>

@ -388,13 +388,7 @@ const SonarrModal: React.FC<SonarrModalProps> = ({
values.is4k ? messages.edit4ksonarr : messages.editsonarr values.is4k ? messages.edit4ksonarr : messages.editsonarr
) )
} }
iconSvg={ iconSvg={!sonarr ? <PlusIcon /> : <PencilIcon />}
!sonarr ? (
<PlusIcon className="w-6 h-6" />
) : (
<PencilIcon className="w-6 h-6" />
)
}
> >
<div className="mb-6"> <div className="mb-6">
<div className="form-row"> <div className="form-row">

@ -39,7 +39,7 @@ const StatusChecker: React.FC = () => {
show={data.commitTag !== process.env.commitTag} show={data.commitTag !== process.env.commitTag}
> >
<Modal <Modal
iconSvg={<SparklesIcon className="w-6 h-6" />} iconSvg={<SparklesIcon />}
title={intl.formatMessage(messages.newversionavailable)} title={intl.formatMessage(messages.newversionavailable)}
onOk={() => location.reload()} onOk={() => location.reload()}
okText={intl.formatMessage(messages.reloadOverseerr)} okText={intl.formatMessage(messages.reloadOverseerr)}

@ -10,6 +10,7 @@ import { useIsTouch } from '../../hooks/useIsTouch';
import { Permission, useUser } from '../../hooks/useUser'; import { Permission, useUser } from '../../hooks/useUser';
import globalMessages from '../../i18n/globalMessages'; import globalMessages from '../../i18n/globalMessages';
import { withProperties } from '../../utils/typeHelpers'; import { withProperties } from '../../utils/typeHelpers';
import Button from '../Common/Button';
import CachedImage from '../Common/CachedImage'; import CachedImage from '../Common/CachedImage';
import RequestModal from '../RequestModal'; import RequestModal from '../RequestModal';
import Transition from '../Transition'; import Transition from '../Transition';
@ -229,18 +230,18 @@ const TitleCard: React.FC<TitleCardProps> = ({
<div className="absolute bottom-0 left-0 right-0 flex justify-between px-2 py-2"> <div className="absolute bottom-0 left-0 right-0 flex justify-between px-2 py-2">
{hasPermission(Permission.REQUEST) && {hasPermission(Permission.REQUEST) &&
(!currentStatus || currentStatus === MediaStatus.UNKNOWN) && ( (!currentStatus || currentStatus === MediaStatus.UNKNOWN) && (
<button <Button
buttonType="primary"
buttonSize="sm"
onClick={(e) => { onClick={(e) => {
e.preventDefault(); e.preventDefault();
setShowRequestModal(true); setShowRequestModal(true);
}} }}
className="flex items-center justify-center w-full text-white transition duration-150 ease-in-out bg-indigo-600 rounded-md h-7 hover:bg-indigo-500 focus:border-indigo-700 focus:ring-indigo active:bg-indigo-700" className="w-full h-7"
> >
<DownloadIcon className="w-4 h-4 mr-1" /> <DownloadIcon />
<span className="text-xs"> <span>{intl.formatMessage(globalMessages.request)}</span>
{intl.formatMessage(globalMessages.request)} </Button>
</span>
</button>
)} )}
</div> </div>
</div> </div>

@ -50,7 +50,7 @@ const Toast: React.FC<ToastProps> = ({
onClick={() => onDismiss()} onClick={() => onDismiss()}
className="inline-flex text-gray-400 transition duration-150 ease-in-out focus:outline-none focus:text-gray-500" className="inline-flex text-gray-400 transition duration-150 ease-in-out focus:outline-none focus:text-gray-500"
> >
<XIcon className="w-5 h-5" /> <XIcon />
</button> </button>
</div> </div>
</div> </div>

@ -124,7 +124,7 @@ const TvDetails: React.FC<TvDetailsProps> = ({ tv }) => {
mediaLinks.push({ mediaLinks.push({
text: intl.formatMessage(messages.playonplex), text: intl.formatMessage(messages.playonplex),
url: data.mediaInfo?.plexUrl, url: data.mediaInfo?.plexUrl,
svg: <PlayIcon className="w-5 h-5 mr-1" />, svg: <PlayIcon />,
}); });
} }
@ -137,7 +137,7 @@ const TvDetails: React.FC<TvDetailsProps> = ({ tv }) => {
mediaLinks.push({ mediaLinks.push({
text: intl.formatMessage(messages.play4konplex), text: intl.formatMessage(messages.play4konplex),
url: data.mediaInfo?.plexUrl4k, url: data.mediaInfo?.plexUrl4k,
svg: <PlayIcon className="w-5 h-5 mr-1" />, svg: <PlayIcon />,
}); });
} }
@ -150,7 +150,7 @@ const TvDetails: React.FC<TvDetailsProps> = ({ tv }) => {
mediaLinks.push({ mediaLinks.push({
text: intl.formatMessage(messages.watchtrailer), text: intl.formatMessage(messages.watchtrailer),
url: trailerUrl, url: trailerUrl,
svg: <FilmIcon className="w-5 h-5 mr-1" />, svg: <FilmIcon />,
}); });
} }
@ -316,7 +316,7 @@ const TvDetails: React.FC<TvDetailsProps> = ({ tv }) => {
className="w-full sm:mb-0" className="w-full sm:mb-0"
buttonType="success" buttonType="success"
> >
<CheckCircleIcon className="w-5 h-5 mr-1" /> <CheckCircleIcon />
<span>{intl.formatMessage(messages.markavailable)}</span> <span>{intl.formatMessage(messages.markavailable)}</span>
</Button> </Button>
</div> </div>
@ -330,14 +330,14 @@ const TvDetails: React.FC<TvDetailsProps> = ({ tv }) => {
className="w-full sm:mb-0" className="w-full sm:mb-0"
buttonType="success" buttonType="success"
> >
<CheckCircleIcon className="w-5 h-5 mr-1" /> <CheckCircleIcon />
<span> <span>
{intl.formatMessage(messages.mark4kavailable)} {intl.formatMessage(messages.mark4kavailable)}
</span> </span>
</Button> </Button>
</div> </div>
)} )}
<div className="mt-3 text-xs text-gray-300"> <div className="mt-3 text-xs text-gray-400">
{intl.formatMessage(messages.allseasonsmarkedavailable)} {intl.formatMessage(messages.allseasonsmarkedavailable)}
</div> </div>
</div> </div>
@ -372,7 +372,7 @@ const TvDetails: React.FC<TvDetailsProps> = ({ tv }) => {
className="block mb-2 last:mb-0" className="block mb-2 last:mb-0"
> >
<Button buttonType="ghost" className="w-full"> <Button buttonType="ghost" className="w-full">
<ExternalLinkIcon className="w-5 h-5 mr-1" /> <ExternalLinkIcon />
<span>{intl.formatMessage(messages.opensonarr)}</span> <span>{intl.formatMessage(messages.opensonarr)}</span>
</Button> </Button>
</a> </a>
@ -384,7 +384,7 @@ const TvDetails: React.FC<TvDetailsProps> = ({ tv }) => {
rel="noreferrer" rel="noreferrer"
> >
<Button buttonType="ghost" className="w-full"> <Button buttonType="ghost" className="w-full">
<ExternalLinkIcon className="w-5 h-5 mr-1" /> <ExternalLinkIcon />
<span>{intl.formatMessage(messages.opensonarr4k)}</span> <span>{intl.formatMessage(messages.opensonarr4k)}</span>
</Button> </Button>
</a> </a>
@ -398,10 +398,10 @@ const TvDetails: React.FC<TvDetailsProps> = ({ tv }) => {
confirmText={intl.formatMessage(globalMessages.areyousure)} confirmText={intl.formatMessage(globalMessages.areyousure)}
className="w-full" className="w-full"
> >
<DocumentRemoveIcon className="w-5 h-5 mr-1" /> <DocumentRemoveIcon />
{intl.formatMessage(messages.manageModalClearMedia)} <span>{intl.formatMessage(messages.manageModalClearMedia)}</span>
</ConfirmButton> </ConfirmButton>
<div className="mt-2 text-sm text-gray-400"> <div className="mt-3 text-xs text-gray-400">
{intl.formatMessage(messages.manageModalClearMediaWarning)} {intl.formatMessage(messages.manageModalClearMediaWarning)}
</div> </div>
</div> </div>
@ -522,7 +522,7 @@ const TvDetails: React.FC<TvDetailsProps> = ({ tv }) => {
<Link href={`/tv/${data.id}/crew`}> <Link href={`/tv/${data.id}/crew`}>
<a className="flex items-center text-gray-400 transition duration-300 hover:text-gray-100"> <a className="flex items-center text-gray-400 transition duration-300 hover:text-gray-100">
<span>{intl.formatMessage(messages.viewfullcrew)}</span> <span>{intl.formatMessage(messages.viewfullcrew)}</span>
<ArrowCircleRightIcon className="inline-block w-5 h-5 ml-1" /> <ArrowCircleRightIcon className="inline-block w-5 h-5 ml-1.5" />
</a> </a>
</Link> </Link>
</div> </div>
@ -679,7 +679,7 @@ const TvDetails: React.FC<TvDetailsProps> = ({ tv }) => {
<Link href="/tv/[tvId]/cast" as={`/tv/${data.id}/cast`}> <Link href="/tv/[tvId]/cast" as={`/tv/${data.id}/cast`}>
<a className="slider-title"> <a className="slider-title">
<span>{intl.formatMessage(messages.cast)}</span> <span>{intl.formatMessage(messages.cast)}</span>
<ArrowCircleRightIcon className="w-6 h-6 ml-2" /> <ArrowCircleRightIcon />
</a> </a>
</Link> </Link>
</div> </div>

@ -85,7 +85,7 @@ const BulkEditModal: React.FC<BulkEditProps> = ({
return ( return (
<Modal <Modal
title={intl.formatMessage(messages.edituser)} title={intl.formatMessage(messages.edituser)}
iconSvg={<PencilIcon className="w-6 h-6" />} iconSvg={<PencilIcon />}
onOk={() => { onOk={() => {
updateUsers(); updateUsers();
}} }}

@ -273,7 +273,7 @@ const UserList: React.FC = () => {
okButtonType="danger" okButtonType="danger"
onCancel={() => setDeleteModal({ isOpen: false })} onCancel={() => setDeleteModal({ isOpen: false })}
title={intl.formatMessage(messages.deleteuser)} title={intl.formatMessage(messages.deleteuser)}
iconSvg={<TrashIcon className="w-6 h-6" />} iconSvg={<TrashIcon />}
> >
{intl.formatMessage(messages.deleteconfirm)} {intl.formatMessage(messages.deleteconfirm)}
</Modal> </Modal>
@ -335,7 +335,7 @@ const UserList: React.FC = () => {
return ( return (
<Modal <Modal
title={intl.formatMessage(messages.createuser)} title={intl.formatMessage(messages.createuser)}
iconSvg={<UserAddIcon className="w-6 h-6" />} iconSvg={<UserAddIcon />}
onOk={() => handleSubmit()} onOk={() => handleSubmit()}
okText={ okText={
isSubmitting isSubmitting
@ -451,8 +451,8 @@ const UserList: React.FC = () => {
buttonType="primary" buttonType="primary"
onClick={() => setCreateModal({ isOpen: true })} onClick={() => setCreateModal({ isOpen: true })}
> >
<UserAddIcon className="w-5 h-5 mr-1" /> <UserAddIcon />
{intl.formatMessage(messages.createlocaluser)} <span>{intl.formatMessage(messages.createlocaluser)}</span>
</Button> </Button>
<Button <Button
className="flex-grow outline lg:mr-2" className="flex-grow outline lg:mr-2"
@ -460,8 +460,8 @@ const UserList: React.FC = () => {
disabled={isImporting} disabled={isImporting}
onClick={() => importFromPlex()} onClick={() => importFromPlex()}
> >
<InboxInIcon className="w-5 h-5 mr-1" /> <InboxInIcon />
{intl.formatMessage(messages.importfromplex)} <span>{intl.formatMessage(messages.importfromplex)}</span>
</Button> </Button>
</div> </div>
<div className="flex flex-grow mb-2 lg:mb-0 lg:flex-grow-0"> <div className="flex flex-grow mb-2 lg:mb-0 lg:flex-grow-0">
@ -523,8 +523,8 @@ const UserList: React.FC = () => {
onClick={() => setShowBulkEditModal(true)} onClick={() => setShowBulkEditModal(true)}
disabled={selectedUsers.length === 0} disabled={selectedUsers.length === 0}
> >
<PencilIcon className="w-5 h-5 mr-1" /> <PencilIcon />
{intl.formatMessage(messages.bulkedit)} <span>{intl.formatMessage(messages.bulkedit)}</span>
</Button> </Button>
)} )}
</Table.TH> </Table.TH>

@ -93,8 +93,8 @@ const ProfileHeader: React.FC<ProfileHeaderProps> = ({
passHref passHref
> >
<Button as="a"> <Button as="a">
<CogIcon className="w-5 h-5 mr-1" /> <CogIcon />
{intl.formatMessage(messages.settings)} <span>{intl.formatMessage(messages.settings)}</span>
</Button> </Button>
</Link> </Link>
) : ( ) : (
@ -106,8 +106,8 @@ const ProfileHeader: React.FC<ProfileHeaderProps> = ({
passHref passHref
> >
<Button as="a"> <Button as="a">
<UserIcon className="w-5 h-5 mr-1" /> <UserIcon />
{intl.formatMessage(messages.profile)} <span>{intl.formatMessage(messages.profile)}</span>
</Button> </Button>
</Link> </Link>
) )

@ -237,7 +237,7 @@ const UserProfile: React.FC = () => {
<Link href={`/users/${user?.id}/requests?filter=all`}> <Link href={`/users/${user?.id}/requests?filter=all`}>
<a className="slider-title"> <a className="slider-title">
<span>{intl.formatMessage(messages.recentrequests)}</span> <span>{intl.formatMessage(messages.recentrequests)}</span>
<ArrowCircleRightIcon className="w-6 h-6 ml-2" /> <ArrowCircleRightIcon />
</a> </a>
</Link> </Link>
</div> </div>

@ -74,6 +74,10 @@ a.slider-title {
@apply hover:text-white; @apply hover:text-white;
} }
a.slider-title svg {
@apply w-6 h-6 ml-2;
}
.media-page { .media-page {
@apply relative px-4 -mx-4 bg-center bg-cover; @apply relative px-4 -mx-4 bg-center bg-cover;
margin-top: calc(-4rem - env(safe-area-inset-top)); margin-top: calc(-4rem - env(safe-area-inset-top));
@ -281,6 +285,23 @@ select.short {
@apply w-min; @apply w-min;
} }
button svg,
.button-md svg {
@apply w-5 h-5 mr-2 last:mr-0;
}
.button-sm svg {
@apply w-4 h-4 mr-1.5 last:w-5 last:h-5 last:mr-0;
}
.modal-icon {
@apply flex items-center justify-center flex-shrink-0 w-12 h-12 mx-auto text-white bg-gray-600 rounded-full sm:mx-0 sm:h-10 sm:w-10;
}
.modal-icon svg {
@apply w-6 h-6;
}
.protocol { .protocol {
@apply inline-flex items-center px-3 text-gray-100 bg-gray-600 border border-r-0 border-gray-500 cursor-default rounded-l-md sm:text-sm; @apply inline-flex items-center px-3 text-gray-100 bg-gray-600 border border-r-0 border-gray-500 cursor-default rounded-l-md sm:text-sm;
} }

@ -60,6 +60,8 @@ module.exports = {
}, },
variants: { variants: {
cursor: ['disabled'], cursor: ['disabled'],
width: ['first', 'last', 'responsive'],
height: ['first', 'last', 'responsive'],
padding: ['first', 'last', 'responsive'], padding: ['first', 'last', 'responsive'],
borderWidth: ['first', 'last'], borderWidth: ['first', 'last'],
margin: ['first', 'last', 'responsive'], margin: ['first', 'last', 'responsive'],

Loading…
Cancel
Save