mirror of
https://github.com/fallenbagel/jellyseerr.git
synced 2026-01-02 20:58:56 -05:00
refactor: modal redesign and fix for transitions (#2987)
This commit is contained in:
@@ -12,7 +12,8 @@ interface AlertProps {
|
||||
|
||||
const Alert = ({ title, children, type }: AlertProps) => {
|
||||
let design = {
|
||||
bgColor: 'bg-yellow-600',
|
||||
bgColor:
|
||||
'border border-yellow-500 backdrop-blur bg-yellow-400 bg-opacity-20',
|
||||
titleColor: 'text-yellow-100',
|
||||
textColor: 'text-yellow-300',
|
||||
svg: <ExclamationIcon className="h-5 w-5" />,
|
||||
@@ -21,9 +22,10 @@ const Alert = ({ title, children, type }: AlertProps) => {
|
||||
switch (type) {
|
||||
case 'info':
|
||||
design = {
|
||||
bgColor: 'bg-indigo-600',
|
||||
titleColor: 'text-indigo-100',
|
||||
textColor: 'text-indigo-300',
|
||||
bgColor:
|
||||
'border border-indigo-500 backdrop-blur bg-indigo-400 bg-opacity-20',
|
||||
titleColor: 'text-gray-100',
|
||||
textColor: 'text-gray-300',
|
||||
svg: <InformationCircleIcon className="h-5 w-5" />,
|
||||
};
|
||||
break;
|
||||
|
||||
@@ -31,21 +31,27 @@ const Badge = (
|
||||
|
||||
switch (badgeType) {
|
||||
case 'danger':
|
||||
badgeStyle.push('bg-red-600 !text-red-100');
|
||||
badgeStyle.push(
|
||||
'bg-red-600 bg-opacity-80 border-red-500 border !text-red-100'
|
||||
);
|
||||
if (href) {
|
||||
badgeStyle.push('hover:bg-red-500');
|
||||
badgeStyle.push('hover:bg-red-500 bg-opacity-100');
|
||||
}
|
||||
break;
|
||||
case 'warning':
|
||||
badgeStyle.push('bg-yellow-500 !text-yellow-100');
|
||||
badgeStyle.push(
|
||||
'bg-yellow-500 bg-opacity-80 border-yellow-500 border !text-yellow-100'
|
||||
);
|
||||
if (href) {
|
||||
badgeStyle.push('hover:bg-yellow-400');
|
||||
badgeStyle.push('hover:bg-yellow-500 hover:bg-opacity-100');
|
||||
}
|
||||
break;
|
||||
case 'success':
|
||||
badgeStyle.push('bg-green-500 !text-green-100');
|
||||
badgeStyle.push(
|
||||
'bg-green-500 bg-opacity-80 border border-green-500 !text-green-100'
|
||||
);
|
||||
if (href) {
|
||||
badgeStyle.push('hover:bg-green-400');
|
||||
badgeStyle.push('hover:bg-green-500 hover:bg-opacity-100');
|
||||
}
|
||||
break;
|
||||
case 'dark':
|
||||
@@ -61,9 +67,11 @@ const Badge = (
|
||||
}
|
||||
break;
|
||||
default:
|
||||
badgeStyle.push('bg-indigo-500 !text-indigo-100');
|
||||
badgeStyle.push(
|
||||
'bg-indigo-500 bg-opacity-80 border border-indigo-500 !text-indigo-100'
|
||||
);
|
||||
if (href) {
|
||||
badgeStyle.push('hover:bg-indigo-400');
|
||||
badgeStyle.push('hover:bg-indigo-500 bg-opacity-100');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -51,22 +51,22 @@ function Button<P extends ElementTypes = 'button'>(
|
||||
switch (buttonType) {
|
||||
case 'primary':
|
||||
buttonStyle.push(
|
||||
'text-white bg-indigo-600 border-indigo-600 hover:bg-indigo-500 hover:border-indigo-500 focus:border-indigo-700 focus:ring-indigo active:bg-indigo-700 active:border-indigo-700'
|
||||
'text-white border border-indigo-500 bg-indigo-600 bg-opacity-80 hover:bg-opacity-100 hover:border-indigo-500 focus:border-indigo-700 focus:ring-indigo active:bg-opacity-100 active:border-indigo-700'
|
||||
);
|
||||
break;
|
||||
case 'danger':
|
||||
buttonStyle.push(
|
||||
'text-white bg-red-600 border-red-600 hover:bg-red-500 hover:border-red-500 focus:border-red-700 focus:ring-red active:bg-red-700 active:border-red-700'
|
||||
'text-white bg-red-600 bg-opacity-80 border-red-500 hover:bg-opacity-100 hover:border-red-500 focus:border-red-700 focus:ring-red active:bg-red-700 active:border-red-700'
|
||||
);
|
||||
break;
|
||||
case 'warning':
|
||||
buttonStyle.push(
|
||||
'text-white bg-yellow-500 border-yellow-500 hover:bg-yellow-400 hover:border-yellow-400 focus:border-yellow-700 focus:ring-yellow active:bg-yellow-700 active:border-yellow-700'
|
||||
'text-white border border-yellow-500 backdrop-blur bg-yellow-500 bg-opacity-80 hover:bg-opacity-100 hover:border-yellow-400 focus:border-yellow-700 focus:ring-yellow active:bg-opacity-100 active:border-yellow-700'
|
||||
);
|
||||
break;
|
||||
case 'success':
|
||||
buttonStyle.push(
|
||||
'text-white bg-green-500 border-green-500 hover:bg-green-400 hover:border-green-400 focus:border-green-700 focus:ring-green active:bg-green-700 active:border-green-700'
|
||||
'text-white bg-green-500 bg-opacity-80 border-green-500 hover:bg-opacity-100 hover:border-green-400 focus:border-green-700 focus:ring-green active:bg-opacity-100 active:border-green-700'
|
||||
);
|
||||
break;
|
||||
case 'ghost':
|
||||
@@ -76,7 +76,7 @@ function Button<P extends ElementTypes = 'button'>(
|
||||
break;
|
||||
default:
|
||||
buttonStyle.push(
|
||||
'text-gray-200 bg-gray-600 border-gray-600 hover:text-white hover:bg-gray-500 hover:border-gray-500 group-hover:text-white group-hover:bg-gray-500 group-hover:border-gray-500 focus:border-blue-300 focus:ring-blue active:text-gray-200 active:bg-gray-500 active:border-gray-500'
|
||||
'text-gray-200 bg-gray-800 bg-opacity-80 border-gray-600 hover:text-white hover:bg-gray-700 hover:border-gray-600 group-hover:text-white group-hover:bg-gray-700 group-hover:border-gray-600 focus:border-blue-300 focus:ring-blue active:text-gray-200 active:bg-gray-700 active:border-gray-600'
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -70,9 +70,9 @@ const ButtonWithDropdown = ({
|
||||
break;
|
||||
default:
|
||||
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-500 bg-opacity-80 hover:bg-opacity-100 hover:border-indigo-500 active:bg-indigo-700 active:border-indigo-700 focus:ring-blue';
|
||||
styleClasses.dropdownSideButtonClasses +=
|
||||
' bg-indigo-700 border-indigo-600 hover:bg-indigo-500 active:bg-indigo-700 focus:ring-blue';
|
||||
' bg-indigo-600 bg-opacity-80 border-indigo-500 hover:bg-opacity-100 active:bg-opacity-100 focus:ring-blue';
|
||||
styleClasses.dropdownClasses += ' bg-indigo-600 p-1';
|
||||
}
|
||||
|
||||
|
||||
@@ -12,9 +12,7 @@ const Header = ({ children, extraMargin = 0, subtext }: HeaderProps) => {
|
||||
className="mb-4 truncate text-2xl font-bold leading-7 text-gray-100 sm:overflow-visible sm:text-4xl sm:leading-9 md:mb-0"
|
||||
data-testid="page-header"
|
||||
>
|
||||
<span className="bg-gradient-to-br from-indigo-400 to-purple-400 bg-clip-text text-transparent">
|
||||
{children}
|
||||
</span>
|
||||
<span className="text-overseerr">{children}</span>
|
||||
</h2>
|
||||
{subtext && <div className="mt-2 text-gray-400">{subtext}</div>}
|
||||
</div>
|
||||
|
||||
@@ -13,6 +13,7 @@ import { useIntl } from 'react-intl';
|
||||
|
||||
interface ModalProps {
|
||||
title?: string;
|
||||
subTitle?: string;
|
||||
onCancel?: (e?: MouseEvent<HTMLElement>) => void;
|
||||
onOk?: (e?: MouseEvent<HTMLButtonElement>) => void;
|
||||
onSecondary?: (e?: MouseEvent<HTMLButtonElement>) => void;
|
||||
@@ -30,7 +31,6 @@ interface ModalProps {
|
||||
tertiaryButtonType?: ButtonType;
|
||||
disableScrollLock?: boolean;
|
||||
backgroundClickable?: boolean;
|
||||
iconSvg?: React.ReactNode;
|
||||
loading?: boolean;
|
||||
backdrop?: string;
|
||||
children?: React.ReactNode;
|
||||
@@ -40,6 +40,7 @@ const Modal = React.forwardRef<HTMLDivElement, ModalProps>(
|
||||
(
|
||||
{
|
||||
title,
|
||||
subTitle,
|
||||
onCancel,
|
||||
onOk,
|
||||
cancelText,
|
||||
@@ -50,7 +51,6 @@ const Modal = React.forwardRef<HTMLDivElement, ModalProps>(
|
||||
children,
|
||||
disableScrollLock,
|
||||
backgroundClickable = true,
|
||||
iconSvg,
|
||||
secondaryButtonType = 'default',
|
||||
secondaryDisabled = false,
|
||||
onSecondary,
|
||||
@@ -67,9 +67,9 @@ const Modal = React.forwardRef<HTMLDivElement, ModalProps>(
|
||||
const intl = useIntl();
|
||||
const modalRef = useRef<HTMLDivElement>(null);
|
||||
useClickOutside(modalRef, () => {
|
||||
typeof onCancel === 'function' && backgroundClickable
|
||||
? onCancel()
|
||||
: undefined;
|
||||
if (onCancel && backgroundClickable) {
|
||||
onCancel();
|
||||
}
|
||||
});
|
||||
useLockBodyScroll(true, disableScrollLock);
|
||||
|
||||
@@ -102,7 +102,7 @@ const Modal = React.forwardRef<HTMLDivElement, ModalProps>(
|
||||
</div>
|
||||
</Transition>
|
||||
<Transition
|
||||
className="hide-scrollbar relative inline-block w-full transform overflow-auto bg-gray-700 px-4 pt-5 pb-4 text-left align-bottom shadow-xl ring-1 ring-gray-500 transition-all sm:my-8 sm:max-w-3xl sm:rounded-lg sm:align-middle"
|
||||
className="hide-scrollbar relative inline-block w-full transform overflow-auto bg-gray-800 px-4 pt-4 pb-4 text-left align-bottom shadow-xl ring-1 ring-gray-700 transition-all sm:my-8 sm:max-w-3xl sm:rounded-lg sm:align-middle"
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
aria-labelledby="modal-headline"
|
||||
@@ -133,26 +133,36 @@ const Modal = React.forwardRef<HTMLDivElement, ModalProps>(
|
||||
className="absolute inset-0"
|
||||
style={{
|
||||
backgroundImage:
|
||||
'linear-gradient(180deg, rgba(55, 65, 81, 0.85) 0%, rgba(55, 65, 81, 1) 100%)',
|
||||
'linear-gradient(180deg, rgba(31, 41, 55, 0.75) 0%, rgba(31, 41, 55, 1) 100%)',
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div className="relative overflow-x-hidden p-0.5 sm:flex sm:items-center">
|
||||
{iconSvg && <div className="modal-icon">{iconSvg}</div>}
|
||||
<div className="relative -mx-4 overflow-x-hidden px-4 pt-0.5 sm:flex sm:items-center">
|
||||
<div
|
||||
className={`mt-3 truncate text-center text-white sm:mt-0 sm:text-left ${
|
||||
iconSvg ? 'sm:ml-4' : 'sm:mb-4'
|
||||
}`}
|
||||
className={`mt-3 truncate text-center text-white sm:mt-0 sm:text-left`}
|
||||
>
|
||||
{title && (
|
||||
<span
|
||||
className="truncate text-lg font-bold leading-6"
|
||||
id="modal-headline"
|
||||
data-testid="modal-title"
|
||||
>
|
||||
{title}
|
||||
</span>
|
||||
{(title || subTitle) && (
|
||||
<div className="flex flex-col space-y-1">
|
||||
{title && (
|
||||
<span
|
||||
className="text-overseerr truncate pb-0.5 text-2xl font-bold leading-6"
|
||||
id="modal-headline"
|
||||
data-testid="modal-title"
|
||||
>
|
||||
{title}
|
||||
</span>
|
||||
)}
|
||||
{subTitle && (
|
||||
<span
|
||||
className="truncate text-lg font-semibold leading-6 text-gray-200"
|
||||
id="modal-headline"
|
||||
data-testid="modal-title"
|
||||
>
|
||||
{subTitle}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -74,7 +74,7 @@ const SlideOver = ({
|
||||
<div className="hide-scrollbar flex h-full flex-col overflow-y-scroll rounded-lg bg-gray-800 bg-opacity-80 shadow-xl ring-1 ring-gray-700 backdrop-blur">
|
||||
<header className="space-y-1 border-b border-gray-700 py-4 px-4">
|
||||
<div className="flex items-center justify-between space-x-3">
|
||||
<h2 className="bg-gradient-to-br from-indigo-400 to-purple-400 bg-clip-text text-2xl font-bold leading-7 text-transparent">
|
||||
<h2 className="text-overseerr text-2xl font-bold leading-7">
|
||||
{title}
|
||||
</h2>
|
||||
<div className="flex h-7 items-center">
|
||||
@@ -89,7 +89,9 @@ const SlideOver = ({
|
||||
</div>
|
||||
{subText && (
|
||||
<div>
|
||||
<p className="leading-5 text-gray-300">{subText}</p>
|
||||
<p className="font-semibold leading-5 text-gray-300">
|
||||
{subText}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</header>
|
||||
|
||||
Reference in New Issue
Block a user