AdminX dark mode updates (#18056)

refs. https://github.com/TryGhost/Product/issues/3349

- modals in AdminX were not prepared for dark mode
This commit is contained in:
Peter Zimon 2023-09-11 12:30:58 +03:00 committed by GitHub
parent 3755384b66
commit 8064dda566
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 65 additions and 58 deletions

View File

@ -1 +1 @@
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" stroke-width="1.5"><path d="M5.25 12.373h-3" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="round"></path><path d="m5.25 15.373-1.5 1.5" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="round"></path><path d="m5.25 9.373-1.5-1.5" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="round"></path><path d="M18.75 12.373h3" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="round"></path><path d="m18.75 15.373 1.5 1.5" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="round"></path><path d="m18.75 9.373 1.5-1.5" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="round"></path><path d="M8.25 9.373v-4.5A3.762 3.762 0 0 1 12 1.123h0a3.761 3.761 0 0 1 3.75 3.75v5.25a3.763 3.763 0 0 1-2.25 3.435 3.709 3.709 0 0 1-1.5.315" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="round"></path><path d="M15.75 14.623v4.5a3.76 3.76 0 0 1-3.75 3.75h0a3.761 3.761 0 0 1-3.75-3.75v-4.5a3.762 3.762 0 0 1 3.75-3.75" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="round"></path></svg> <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" stroke-width="1.5"><path d="M5.25 12.373h-3" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="m5.25 15.373-1.5 1.5" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="m5.25 9.373-1.5-1.5" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M18.75 12.373h3" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="m18.75 15.373 1.5 1.5" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="m18.75 9.373 1.5-1.5" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M8.25 9.373v-4.5A3.762 3.762 0 0 1 12 1.123h0a3.761 3.761 0 0 1 3.75 3.75v5.25a3.763 3.763 0 0 1-2.25 3.435 3.709 3.709 0 0 1-1.5.315" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M15.75 14.623v4.5a3.76 3.76 0 0 1-3.75 3.75h0a3.761 3.761 0 0 1-3.75-3.75v-4.5a3.762 3.762 0 0 1 3.75-3.75" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path></svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -47,7 +47,7 @@ const Breadcrumbs: React.FC<BreadcrumbsProps> = ({
return ( return (
<div className={containerClassName}> <div className={containerClassName}>
{backIcon && {backIcon &&
<Button className='mr-6' icon='arrow-left' size='sm' link onClick={onBack} /> <Button className='mr-6' icon='arrow-left' iconColorClass='dark:text-white' size='sm' link onClick={onBack} />
} }
{items.map((item) => { {items.map((item) => {
const bcItem = (i === allItems - 1 ? const bcItem = (i === allItems - 1 ?
@ -56,7 +56,7 @@ const Breadcrumbs: React.FC<BreadcrumbsProps> = ({
<> <>
<button <button
key={`bc-${i}`} key={`bc-${i}`}
className={`${itemClassName} ${item.onClick && '-mx-1 cursor-pointer rounded-sm px-1 py-px hover:bg-grey-100'}`} className={`${itemClassName} ${item.onClick && '-mx-1 cursor-pointer rounded-sm px-1 py-px hover:bg-grey-100 dark:hover:bg-grey-900'}`}
type="button" type="button"
onClick={item.onClick} onClick={item.onClick}
> >

View File

@ -78,7 +78,7 @@ const Heading: React.FC<Heading1to5Props | Heading6Props | HeadingLabelProps> =
className = clsx( className = clsx(
styles, styles,
'dark:text-white', !grey && 'dark:text-white',
className className
); );

View File

@ -68,7 +68,7 @@ interface IconProps {
* - all icons must have all it's children color value set `currentColor` * - all icons must have all it's children color value set `currentColor`
* - all strokes must be paths and _NOT_ outlined objects. Stroke width should be set to 1.5px * - all strokes must be paths and _NOT_ outlined objects. Stroke width should be set to 1.5px
*/ */
const Icon: React.FC<IconProps> = ({name, size = 'md', colorClass = 'text-black', className = ''}) => { const Icon: React.FC<IconProps> = ({name, size = 'md', colorClass = '', className = ''}) => {
const {SvgComponent} = useDynamicSVGImport(name); const {SvgComponent} = useDynamicSVGImport(name);
let styles = ''; let styles = '';

View File

@ -44,7 +44,7 @@ const ListItem: React.FC<ListItemProps> = ({
const listItemClasses = clsx( const listItemClasses = clsx(
'group/list-item flex items-center justify-between', 'group/list-item flex items-center justify-between',
bgOnHover && 'hover:bg-gradient-to-r hover:from-white hover:to-grey-50 dark:hover:from-black dark:hover:to-grey-950', bgOnHover && 'hover:bg-gradient-to-r hover:from-white hover:to-grey-50 dark:hover:from-black dark:hover:to-grey-950',
separator ? 'border-b border-grey-100 last-of-type:border-b-transparent hover:border-grey-200 dark:border-grey-800 dark:hover:border-grey-700' : 'border-y border-transparent hover:border-grey-200 first-of-type:hover:border-t-transparent dark:hover:border-grey-700', separator ? 'border-b border-grey-100 last-of-type:border-b-transparent hover:border-grey-200 dark:border-grey-900 dark:hover:border-grey-800' : 'border-y border-transparent hover:border-grey-200 first-of-type:hover:border-t-transparent dark:hover:border-grey-800',
className className
); );

View File

@ -30,7 +30,7 @@ const Menu: React.FC<MenuProps> = ({
<Popover position={position} trigger={trigger} closeOnItemClick> <Popover position={position} trigger={trigger} closeOnItemClick>
<div className="flex min-w-[160px] flex-col justify-stretch py-1" role="none"> <div className="flex min-w-[160px] flex-col justify-stretch py-1" role="none">
{items.map(item => ( {items.map(item => (
<button key={item.id} className="mx-1 block cursor-pointer rounded-[2.5px] px-4 py-1.5 text-left text-sm hover:bg-grey-100" type="button" onClick={item.onClick}>{item.label}</button> <button key={item.id} className="mx-1 block cursor-pointer rounded-[2.5px] px-4 py-1.5 text-left text-sm hover:bg-grey-100 dark:hover:bg-grey-800" type="button" onClick={item.onClick}>{item.label}</button>
))} ))}
</div> </div>
</Popover> </Popover>

View File

@ -65,7 +65,7 @@ const Popover: React.FC<PopoverProps> = ({
let className = ''; let className = '';
className = clsx( className = clsx(
'fixed z-50 mt-2 origin-top-right rounded bg-white shadow-md ring-1 ring-[rgba(0,0,0,0.01)] focus:outline-none', 'fixed z-50 mt-2 origin-top-right rounded bg-white shadow-md ring-1 ring-[rgba(0,0,0,0.01)] focus:outline-none dark:bg-grey-900 dark:text-white',
className className
); );

View File

@ -4,7 +4,10 @@ interface SeparatorProps {
className?: string; className?: string;
} }
const Separator: React.FC<SeparatorProps> = ({className = 'border-grey-200 dark:border-grey-800'}) => { const Separator: React.FC<SeparatorProps> = ({className}) => {
if (!className) {
className = 'border-grey-200 dark:border-grey-600';
}
return <hr className={className} />; return <hr className={className} />;
}; };

View File

@ -34,7 +34,7 @@ const DefaultContainer: React.FC<SortableItemContainerProps> = ({
<div <div
ref={setRef} ref={setRef}
className={clsx( className={clsx(
'group flex w-full items-center gap-3 bg-white py-1', 'group flex w-full items-center gap-3 bg-white py-1 dark:bg-black',
separator && 'border-b border-grey-200', separator && 'border-b border-grey-200',
isDragging && 'opacity-75' isDragging && 'opacity-75'
)} )}

View File

@ -6,8 +6,8 @@ interface MobileChromeProps {
const MobileChrome: React.FC<MobileChromeProps & React.HTMLAttributes<HTMLDivElement>> = ({children, ...props}) => { const MobileChrome: React.FC<MobileChromeProps & React.HTMLAttributes<HTMLDivElement>> = ({children, ...props}) => {
return ( return (
<div className='flex h-[775px] w-[380px] flex-col rounded-3xl bg-white p-2 shadow-xl' {...props}> <div className='flex h-[775px] w-[380px] flex-col rounded-3xl bg-white p-2 shadow-xl dark:bg-grey-900' {...props}>
<div className='w-100 h-100 grow overflow-auto rounded-2xl border border-grey-100'> <div className='w-100 h-100 grow overflow-auto rounded-2xl border border-grey-100 dark:border-grey-950'>
{children} {children}
</div> </div>
</div> </div>

View File

@ -58,7 +58,7 @@ const Form: React.FC<FormProps> = ({
if (grouped) { if (grouped) {
classes = clsx( classes = clsx(
classes, classes,
'rounded-sm border border-grey-200 p-4 md:p-7' 'rounded-sm border border-grey-200 p-4 dark:border-grey-900 md:p-7'
); );
} }

View File

@ -43,7 +43,7 @@ const TextArea: React.FC<TextAreaProps> = ({
let styles = clsx( let styles = clsx(
'peer order-2 rounded-sm border px-3 py-2 dark:text-white', 'peer order-2 rounded-sm border px-3 py-2 dark:text-white',
clearBg ? 'bg-transparent' : 'bg-grey-75 dark:bg-grey-900', clearBg ? 'bg-transparent' : 'bg-grey-75 dark:bg-grey-950',
error ? 'border-red' : 'border-grey-500 placeholder:text-grey-500 hover:border-grey-700 focus:border-grey-800 dark:border-grey-800 dark:placeholder:text-grey-800 dark:hover:border-grey-700 dark:focus:border-grey-500', error ? 'border-red' : 'border-grey-500 placeholder:text-grey-500 hover:border-grey-700 focus:border-grey-800 dark:border-grey-800 dark:placeholder:text-grey-800 dark:hover:border-grey-700 dark:focus:border-grey-500',
title && 'mt-2', title && 'mt-2',
fontStyle === 'mono' && 'font-mono text-sm', fontStyle === 'mono' && 'font-mono text-sm',

View File

@ -67,7 +67,7 @@ const Toggle: React.FC<ToggleProps> = ({
let toggleBgClass; let toggleBgClass;
switch (toggleBg) { switch (toggleBg) {
case 'stripetest': case 'stripetest':
toggleBgClass = 'checked:bg-[#EC6803]'; toggleBgClass = 'checked:bg-[#EC6803] dark:checked:bg-[#EC6803]';
break; break;
case 'green': case 'green':
@ -75,7 +75,7 @@ const Toggle: React.FC<ToggleProps> = ({
break; break;
default: default:
toggleBgClass = 'checked:bg-black'; toggleBgClass = 'checked:bg-black dark:checked:bg-green';
break; break;
} }
@ -83,7 +83,7 @@ const Toggle: React.FC<ToggleProps> = ({
<div> <div>
<div className={`group flex items-start gap-2 dark:text-white ${direction === 'rtl' && 'justify-between'} ${separator && 'pb-2'}`}> <div className={`group flex items-start gap-2 dark:text-white ${direction === 'rtl' && 'justify-between'} ${separator && 'pb-2'}`}>
<input checked={checked} <input checked={checked}
className={`${toggleBgClass} appearance-none rounded-full bg-grey-300 transition after:absolute after:ml-0.5 after:mt-0.5 after:rounded-full after:border-none after:bg-white after:transition-[background-color_0.2s,transform_0.2s] after:content-[''] checked:after:absolute checked:after:rounded-full checked:after:border-none checked:after:bg-white checked:after:transition-[background-color_0.2s,transform_0.2s] checked:after:content-[''] hover:cursor-pointer group-hover:opacity-80 dark:bg-grey-800 dark:checked:bg-green ${sizeStyles} ${direction === 'rtl' && ' order-2'}`} className={`${toggleBgClass} appearance-none rounded-full bg-grey-300 transition after:absolute after:ml-0.5 after:mt-0.5 after:rounded-full after:border-none after:bg-white after:transition-[background-color_0.2s,transform_0.2s] after:content-[''] checked:after:absolute checked:after:rounded-full checked:after:border-none checked:after:bg-white checked:after:transition-[background-color_0.2s,transform_0.2s] checked:after:content-[''] hover:cursor-pointer group-hover:opacity-80 dark:bg-grey-800 ${sizeStyles} ${direction === 'rtl' && ' order-2'}`}
id={id} id={id}
role="switch" role="switch"
type="checkbox" type="checkbox"

View File

@ -247,7 +247,7 @@ const Modal: React.FC<ModalProps> = ({
<div className={clsx( <div className={clsx(
'pointer-events-none fixed inset-0 z-0', 'pointer-events-none fixed inset-0 z-0',
(backDrop && !formSheet) && 'bg-[rgba(98,109,121,0.2)] backdrop-blur-[3px]', (backDrop && !formSheet) && 'bg-[rgba(98,109,121,0.2)] backdrop-blur-[3px]',
formSheet && 'bg-[rgba(98,109,121,0.05)]' formSheet && 'bg-[rgba(98,109,121,0.08)]'
)}></div> )}></div>
<section className={modalClasses} data-testid={testId} style={modalStyles}> <section className={modalClasses} data-testid={testId} style={modalStyles}>
<div className={contentClasses}> <div className={contentClasses}>

View File

@ -117,7 +117,8 @@ export const PreviewModalContent: React.FC<PreviewModalProps> = ({
/>; />;
} }
const unSelectedIconColorClass = 'text-grey-500'; const selectedIconColorClass = 'text-black dark:text-green';
const unSelectedIconColorClass = 'text-grey-500 dark:text-grey-600';
const toolbarRight = deviceSelector && ( const toolbarRight = deviceSelector && (
<ButtonGroup <ButtonGroup
buttons={[ buttons={[
@ -127,7 +128,7 @@ export const PreviewModalContent: React.FC<PreviewModalProps> = ({
hideLabel: true, hideLabel: true,
link: true, link: true,
size: 'sm', size: 'sm',
iconColorClass: (view === 'desktop' ? 'text-black' : unSelectedIconColorClass), iconColorClass: (view === 'desktop' ? selectedIconColorClass : unSelectedIconColorClass),
onClick: onSelectDesktopView || (() => { onClick: onSelectDesktopView || (() => {
setView('desktop'); setView('desktop');
}) })
@ -138,7 +139,7 @@ export const PreviewModalContent: React.FC<PreviewModalProps> = ({
hideLabel: true, hideLabel: true,
link: true, link: true,
size: 'sm', size: 'sm',
iconColorClass: (view === 'mobile' ? 'text-black' : unSelectedIconColorClass), iconColorClass: (view === 'mobile' ? selectedIconColorClass : unSelectedIconColorClass),
onClick: onSelectMobileView || (() => { onClick: onSelectMobileView || (() => {
setView('mobile'); setView('mobile');
}) })
@ -149,9 +150,10 @@ export const PreviewModalContent: React.FC<PreviewModalProps> = ({
let previewBgClass = ''; let previewBgClass = '';
if (previewBgColor === 'grey') { if (previewBgColor === 'grey') {
previewBgClass = 'bg-grey-50'; previewBgClass = 'bg-grey-50 dark:bg-black';
} else if (previewBgColor === 'greygradient') { } else if (previewBgColor === 'greygradient') {
previewBgClass = 'bg-gradient-to-tr from-white to-[#f9f9fa]'; previewBgClass = 'bg-gradient-to-tr from-white to-[#f9f9fa]';
previewBgClass = 'bg-gradient-to-tr from-grey-950 to-black';
} }
const containerClasses = clsx( const containerClasses = clsx(
@ -216,7 +218,7 @@ export const PreviewModalContent: React.FC<PreviewModalProps> = ({
{preview} {preview}
</div> </div>
{sidebar && {sidebar &&
<div className='relative flex h-full w-full flex-col border-l border-grey-100 md:w-auto md:basis-[400px]'> <div className='relative flex h-full w-full flex-col border-l border-grey-100 dark:border-grey-900 md:w-auto md:basis-[400px]'>
{sidebarHeader ? sidebarHeader : ( {sidebarHeader ? sidebarHeader : (
<div className='flex max-h-[74px] items-center justify-between gap-3 px-7 py-5'> <div className='flex max-h-[74px] items-center justify-between gap-3 px-7 py-5'>
<Heading level={titleHeadingLevel}>{title}</Heading> <Heading level={titleHeadingLevel}>{title}</Heading>

View File

@ -4,12 +4,14 @@ import clsx from 'clsx';
interface StripeButtonProps { interface StripeButtonProps {
label?: React.ReactNode; label?: React.ReactNode;
className?: string;
} }
const StripeButton: React.FC<StripeButtonProps | ButtonProps> = ({label, ...props}) => { const StripeButton: React.FC<StripeButtonProps | ButtonProps> = ({label, className, ...props}) => {
const classNames = clsx( const classNames = clsx(
'cursor-pointer rounded-md bg-[#625BF6] font-semibold text-white transition-all hover:opacity-90', 'cursor-pointer rounded-md bg-[#625BF6] font-semibold text-white transition-all hover:opacity-90',
label ? 'px-5 py-2 text-sm' : 'px-6 py-[9px]' label ? 'px-5 py-2 text-sm' : 'px-6 py-[9px]',
className
); );
if (!label) { if (!label) {

View File

@ -39,7 +39,7 @@ const HistoryAvatar: React.FC<{action: Action}> = ({action}) => {
labelColor='white' labelColor='white'
size='md' size='md'
/> />
<div className='absolute -bottom-1 -right-1 flex items-center justify-center rounded-full border border-grey-100 bg-white p-1 shadow-sm'> <div className='absolute -bottom-1 -right-1 flex items-center justify-center rounded-full border border-grey-100 bg-white p-1 shadow-sm dark:border-grey-900 dark:bg-black'>
<HistoryIcon action={action} /> <HistoryIcon action={action} />
</div> </div>
</div> </div>
@ -96,7 +96,7 @@ const HistoryActionDescription: React.FC<{action: Action}> = ({action}) => {
return <> return <>
{group.slice(0, 1).toUpperCase()}{group.slice(1)} {group.slice(0, 1).toUpperCase()}{group.slice(1)}
{group !== key && <span className='text-xs'> <code className='mb-1 bg-white text-grey-800'>({key})</code></span>} {group !== key && <span className='text-xs'> <code className='mb-1 bg-white text-grey-800 dark:bg-grey-900 dark:text-white'>({key})</code></span>}
</>; </>;
} else if (action.resource?.title || action.resource?.name || action.context.primary_name) { } else if (action.resource?.title || action.resource?.name || action.context.primary_name) {
const linkTarget = getLinkTarget(action); const linkTarget = getLinkTarget(action);

View File

@ -19,10 +19,10 @@ const APIKeyField: React.FC<APIKeyFieldProps> = ({label, text = '', hint, onRege
return <> return <>
<div className='p-0 pr-4 text-sm text-grey-600 md:py-1'>{label}</div> <div className='p-0 pr-4 text-sm text-grey-600 md:py-1'>{label}</div>
<div className='group/api-keys relative mb-3 overflow-hidden rounded py-1 text-sm hover:bg-grey-50 md:mb-0 md:p-1'> <div className='group/api-keys relative mb-3 overflow-hidden rounded py-1 text-sm hover:bg-grey-50 dark:hover:bg-grey-900 md:mb-0 md:p-1'>
{text} {text}
{hint} {hint}
<div className='visible absolute right-0 top-[50%] flex translate-y-[-50%] gap-1 bg-white pl-1 text-sm group-hover/api-keys:visible md:invisible'> <div className='visible absolute right-0 top-[50%] flex translate-y-[-50%] gap-1 bg-white pl-1 text-sm group-hover/api-keys:visible dark:bg-black md:invisible'>
{onRegenerate && <Button color='outline' label='Regenerate' size='sm' onClick={onRegenerate} />} {onRegenerate && <Button color='outline' label='Regenerate' size='sm' onClick={onRegenerate} />}
<Button color='outline' label={copied ? 'Copied' : 'Copy'} size='sm' onClick={copyText} /> <Button color='outline' label={copied ? 'Copied' : 'Copy'} size='sm' onClick={copyText} />
</div> </div>

View File

@ -99,7 +99,7 @@ const PinturaModal = NiceModal.create(() => {
title='Pintura' title='Pintura'
/> />
<div className='mt-7'> <div className='mt-7'>
<div className='mb-7 flex flex-col items-stretch justify-between gap-4 rounded-sm bg-grey-75 p-4 md:flex-row md:p-7'> <div className='mb-7 flex flex-col items-stretch justify-between gap-4 rounded-sm bg-grey-75 p-4 dark:bg-grey-950 md:flex-row md:p-7'>
<div className='md:basis-1/2'> <div className='md:basis-1/2'>
<p className='mb-4 font-bold'>Add advanced image editing to Ghost, with Pintura</p> <p className='mb-4 font-bold'>Add advanced image editing to Ghost, with Pintura</p>
<p className='mb-4 text-sm'>Pintura is a powerful JavaScript image editor that allows you to crop, rotate, annotate and modify images directly inside Ghost.</p> <p className='mb-4 text-sm'>Pintura is a powerful JavaScript image editor that allows you to crop, rotate, annotate and modify images directly inside Ghost.</p>

View File

@ -102,7 +102,7 @@ const ZapierModal = NiceModal.create(() => {
title={ title={
<div className='flex flex-col gap-4 md:flex-row md:items-center'> <div className='flex flex-col gap-4 md:flex-row md:items-center'>
<div className='flex shrink-0 flex-nowrap items-center gap-2'> <div className='flex shrink-0 flex-nowrap items-center gap-2'>
<img className='h-8 w-8 object-contain' role='presentation' src={`${adminRoot}${template.ghostImage}`} /> <img className='h-8 w-8 object-contain dark:invert' role='presentation' src={`${adminRoot}${template.ghostImage}`} />
<ArrowRightIcon className='h-3 w-3' /> <ArrowRightIcon className='h-3 w-3' />
<img className='h-8 w-8 object-contain' role='presentation' src={`${adminRoot}${template.appImage}`} /> <img className='h-8 w-8 object-contain' role='presentation' src={`${adminRoot}${template.appImage}`} />
</div> </div>

View File

@ -30,7 +30,7 @@ const ImportModalContent = () => {
}); });
}} }}
> >
<div className="cursor-pointer bg-grey-100 p-10 text-center"> <div className="cursor-pointer bg-grey-75 p-10 text-center dark:bg-grey-950">
{uploading ? 'Uploading ...' : 'Select a JSON or zip file'} {uploading ? 'Uploading ...' : 'Select a JSON or zip file'}
</div> </div>
</FileUpload>; </FileUpload>;

View File

@ -40,8 +40,8 @@ const LockSite: React.FC<{ keywords: string[] }> = ({keywords}) => {
<span>Your site is password protected</span> <span>Your site is password protected</span>
</div> </div>
) : ( ) : (
<div className='flex items-center gap-1 text-grey-900'> <div className='flex items-center gap-1 text-grey-900 dark:text-grey-400'>
<Icon colorClass='text-black' name='lock-unlocked' size='sm' /> <Icon colorClass='text-black dark:text-white' name='lock-unlocked' size='sm' />
<span>Your site is not password protected</span> <span>Your site is not password protected</span>
</div> </div>
) )

View File

@ -57,8 +57,8 @@ const RoleSelector: React.FC<UserDetailProps> = ({user, setUserData}) => {
return ( return (
<> <>
<Heading level={6}>Role</Heading> <Heading level={6}>Role</Heading>
<div className='flex h-[295px] flex-col items-center justify-center gap-3 bg-grey-75 px-10 py-20 text-center text-sm text-grey-800'> <div className='flex h-[295px] flex-col items-center justify-center gap-3 bg-grey-75 px-10 py-20 text-center text-sm text-grey-800 dark:bg-grey-950 dark:text-white'>
<Icon colorClass='text-grey-800' name='crown' size='lg' /> <Icon colorClass='text-grey-800 dark:text-white' name='crown' size='lg' />
This user is the owner of the site. To change their role, you need to transfer the ownership first. This user is the owner of the site. To change their role, you need to transfer the ownership first.
</div> </div>
</> </>

View File

@ -86,7 +86,7 @@ const LookAndFeel: React.FC<{
{defaultButtonIcons.map(icon => ( {defaultButtonIcons.map(icon => (
<button className={clsx('border p-3', currentIcon === icon.value ? 'border-green' : 'border-transparent')} type="button" onClick={() => updateSetting('portal_button_icon', icon.value)}> <button className={clsx('border p-3', currentIcon === icon.value ? 'border-green' : 'border-transparent')} type="button" onClick={() => updateSetting('portal_button_icon', icon.value)}>
<icon.Component className={`h-5 w-5 ${currentIcon === icon.value ? 'text-green' : 'text-black opacity-70 transition-all hover:opacity-100'}`} /> <icon.Component className={`h-5 w-5 ${currentIcon === icon.value ? 'text-green' : 'text-black opacity-70 transition-all hover:opacity-100 dark:text-white'}`} />
</button> </button>
))} ))}
<div className={clsx('relative w-[46px] border', currentIcon === uploadedIcon ? 'border-green' : 'border-transparent')}> <div className={clsx('relative w-[46px] border', currentIcon === uploadedIcon ? 'border-green' : 'border-transparent')}>
@ -103,7 +103,7 @@ const LookAndFeel: React.FC<{
onImageClick={() => uploadedIcon && updateSetting('portal_button_icon', uploadedIcon)} onImageClick={() => uploadedIcon && updateSetting('portal_button_icon', uploadedIcon)}
onUpload={handleImageUpload} onUpload={handleImageUpload}
> >
<Icon name='upload' size='md' /> <Icon className='dark:text-white' name='upload' size='md' />
</ImageUpload> </ImageUpload>
</div> </div>
</div> </div>

View File

@ -134,12 +134,12 @@ const Connect: React.FC = () => {
onChange={e => setTestMode(e.target.checked)} onChange={e => setTestMode(e.target.checked)}
/> />
</div> </div>
<Heading level={6} grey>Step 1 <span className='text-black'>Generate secure key</span></Heading> <Heading level={6} grey>Step 1 <span className='text-black dark:text-white'>Generate secure key</span></Heading>
<div className='mb-4 mt-2'> <div className='mb-4 mt-2'>
Click on the <strong>Connect with Stripe</strong> button to generate a secure key that connects your Ghost site with Stripe. Click on the <strong>Connect with Stripe</strong> button to generate a secure key that connects your Ghost site with Stripe.
</div> </div>
<StripeButton href={stripeConnectUrl} tag='a' target='_blank' /> <StripeButton href={stripeConnectUrl} tag='a' target='_blank' />
<Heading className='mb-2 mt-8' level={6} grey>Step 2 <span className='text-black'>Paste secure key</span></Heading> <Heading className='mb-2 mt-8' level={6} grey>Step 2 <span className='text-black dark:text-white'>Paste secure key</span></Heading>
<TextArea clearBg={false} error={Boolean(error)} hint={error || undefined} placeholder='Paste your secure key here' onChange={onTokenChange}></TextArea> <TextArea clearBg={false} error={Boolean(error)} hint={error || undefined} placeholder='Paste your secure key here' onChange={onTokenChange}></TextArea>
{submitEnabled && <Button className='mt-5' color='green' label='Save Stripe settings' onClick={onSubmit} />} {submitEnabled && <Button className='mt-5' color='green' label='Save Stripe settings' onClick={onSubmit} />}
</div> </div>
@ -185,24 +185,24 @@ const Connected: React.FC<{onClose?: () => void}> = ({onClose}) => {
return ( return (
<section> <section>
<div className='flex items-center justify-between'> <div className='flex items-center justify-between'>
<Button disabled={isFetchingMembers} icon='link-broken' label='Disconnect' link onClick={openDisconnectStripeModal} /> <Button className='dark:text-white' disabled={isFetchingMembers} icon='link-broken' iconColorClass='dark:text-white' label='Disconnect' link onClick={openDisconnectStripeModal} />
<Button icon='close' label='Close' size='sm' hideLabel link onClick={onClose} /> <Button icon='close' iconColorClass='dark:text-white' label='Close' size='sm' hideLabel link onClick={onClose} />
</div> </div>
<div className='my-20 flex flex-col items-center'> <div className='my-20 flex flex-col items-center'>
<div className='relative h-20 w-[200px]'> <div className='relative h-20 w-[200px]'>
<img alt='Ghost Logo' className='absolute left-10 h-16 w-16' src={GhostLogo} /> <img alt='Ghost Logo' className='absolute left-10 h-16 w-16' src={GhostLogo} />
<img alt='Stripe Logo' className='absolute right-10 h-16 w-16 rounded-2xl shadow-[-1.5px_0_0_1.5px_#fff]' src={StripeLogo} /> <img alt='Stripe Logo' className='absolute right-10 h-16 w-16 rounded-2xl shadow-[-1.5px_0_0_1.5px_#fff] dark:shadow-[-1.5px_0_0_1.5px_black]' src={StripeLogo} />
</div> </div>
<Heading className='text-center' level={3}>You are connected with Stripe!{stripeConnectLivemode ? null : ' (Test mode)'}</Heading> <Heading className='text-center' level={3}>You are connected with Stripe!{stripeConnectLivemode ? null : ' (Test mode)'}</Heading>
<div className='mt-1'>Connected to <strong>Dummy</strong></div> <div className='mt-1'>Connected to <strong>Dummy</strong></div>
</div> </div>
<div className='flex flex-col items-center'> <div className='flex flex-col items-center'>
<Heading level={6}>Read next</Heading> <Heading level={6}>Read next</Heading>
<a className='w-100 mt-5 flex flex-col items-stretch justify-between border border-grey-200 transition-all hover:border-grey-400 md:flex-row' href="https://ghost.org/resources/managing-your-stripe-account/?ref=admin" rel="noopener noreferrer" target="_blank"> <a className='w-100 mt-5 flex flex-col items-stretch justify-between rounded-sm border border-grey-200 transition-all hover:border-grey-400 dark:border-grey-900 md:flex-row' href="https://ghost.org/resources/managing-your-stripe-account/?ref=admin" rel="noopener noreferrer" target="_blank">
<div className='order-2 p-4 md:order-1'> <div className='order-2 p-4 md:order-1'>
<div className='font-bold'>How to setup and manage your Stripe account</div> <div className='font-bold'>How to setup and manage your Stripe account</div>
<div className='mt-1 text-sm text-grey-800'>Learn how to configure your Stripe account to work with Ghost, from custom branding to payment receipt emails.</div> <div className='mt-1 text-sm text-grey-800 dark:text-grey-500'>Learn how to configure your Stripe account to work with Ghost, from custom branding to payment receipt emails.</div>
<div className='mt-3 flex items-center gap-1 text-sm text-grey-800'> <div className='mt-3 flex items-center gap-1 text-sm text-grey-800 dark:text-grey-500'>
<img alt='Ghost Logo' className='h-4 w-4' src={GhostLogoPink} /> <img alt='Ghost Logo' className='h-4 w-4' src={GhostLogoPink} />
<strong>Ghost Resources</strong> <strong>Ghost Resources</strong>
<span>&middot;</span> <span>&middot;</span>

View File

@ -230,7 +230,7 @@ const TierDetailModalContent: React.FC<{tier?: Tier}> = ({tier}) => {
/> />
</div> </div>
<div className="relative mt-0.5 flex items-center gap-3"> <div className="relative mt-0.5 flex items-center gap-3">
<Icon name='check' size='sm' /> <Icon className='dark:text-white' name='check' size='sm' />
<TextField <TextField
className='grow' className='grow'
containerClassName='w-100' containerClassName='w-100'

View File

@ -82,15 +82,15 @@ const TierDetailPreview: React.FC<TierDetailPreviewProps> = ({tier, isFreeTier})
: 0; : 0;
return ( return (
<div className="mt-1"> <div>
<div className="flex items-baseline justify-between"> <div className="flex items-baseline justify-between">
<Heading className="pb-2" level={6} grey>{isFreeTier ? 'Free membership preview' : 'Tier preview'}</Heading> <Heading className="pb-2" level={6} grey>{isFreeTier ? 'Free membership preview' : 'Tier preview'}</Heading>
{!isFreeTier && <div className="flex gap-1"> {!isFreeTier && <div className="flex gap-1">
<Button className={`${showingYearly === true ? 'text-grey-500' : 'text-grey-900'}`} label="Monthly" link onClick={() => setShowingYearly(false)} /> <Button className={`${showingYearly === true ? 'text-grey-500' : 'text-grey-900 dark:text-white'}`} label="Monthly" link unstyled onClick={() => setShowingYearly(false)} />
<Button className={`ml-2 ${showingYearly === true ? 'text-grey-900' : 'text-grey-500'}`} label="Yearly" link onClick={() => setShowingYearly(true)} /> <Button className={`ml-2 ${showingYearly === true ? 'text-grey-900 dark:text-white' : 'text-grey-500'}`} label="Yearly" link unstyled onClick={() => setShowingYearly(true)} />
</div>} </div>}
</div> </div>
<div className='border border-grey-200'> <div className='rounded-sm border border-grey-200 bg-white dark:border-transparent'>
<div className="flex-column relative flex min-h-[200px] w-full max-w-[420px] scale-90 items-start justify-stretch rounded bg-white p-4"> <div className="flex-column relative flex min-h-[200px] w-full max-w-[420px] scale-90 items-start justify-stretch rounded bg-white p-4">
<div className="min-h-[56px] w-full"> <div className="min-h-[56px] w-full">
<h4 className={`-mt-1 mb-0 w-full break-words text-lg font-semibold leading-tight text-pink ${!name && 'opacity-30'}`}>{name || 'Bronze'}</h4> <h4 className={`-mt-1 mb-0 w-full break-words text-lg font-semibold leading-tight text-pink ${!name && 'opacity-30'}`}>{name || 'Bronze'}</h4>

View File

@ -75,7 +75,7 @@ const Sidebar: React.FC<{
<div className='font-semibold'>Change theme</div> <div className='font-semibold'>Change theme</div>
<div className='font-sm text-grey-700'>Current theme: {activeTheme?.name}</div> <div className='font-sm text-grey-700'>Current theme: {activeTheme?.name}</div>
</div> </div>
<Icon className='mr-2 transition-all group-hover:translate-x-2' name='chevron-right' size='sm' /> <Icon className='mr-2 transition-all group-hover:translate-x-2 dark:text-white' name='chevron-right' size='sm' />
</button> </button>
</div> </div>
</StickyFooter> </StickyFooter>

View File

@ -182,7 +182,7 @@ const ThemeToolbar: React.FC<ThemeToolbarProps> = ({
</div>; </div>;
return (<> return (<>
<PageHeader containerClassName='bg-white' left={left} right={right} /> <PageHeader containerClassName='bg-white dark:bg-black' left={left} right={right} />
<div className='px-[8vmin] md:hidden'> <div className='px-[8vmin] md:hidden'>
<TabView <TabView
border={false} border={false}

View File

@ -14,7 +14,7 @@ const NavigationEditForm: React.FC<{
itemSeparator={false} itemSeparator={false}
renderItem={item => ( renderItem={item => (
<NavigationItemEditor <NavigationItemEditor
action={<Button className='self-center' icon="trash" size='sm' onClick={() => navigation.removeItem(item.id)} />} action={<Button className='self-center' icon="trash" iconColorClass='dark:text-white' size='sm' onClick={() => navigation.removeItem(item.id)} />}
baseUrl={baseUrl} baseUrl={baseUrl}
clearError={key => navigation.clearError(item.id, key)} clearError={key => navigation.clearError(item.id, key)}
item={item} item={item}

View File

@ -78,7 +78,7 @@ const ThemePreview: React.FC<{
buttons={[ buttons={[
{ {
icon: 'laptop', icon: 'laptop',
iconColorClass: (previewMode === 'desktop' ? 'text-black' : 'text-grey-500'), iconColorClass: (previewMode === 'desktop' ? 'text-black dark:text-green' : 'text-grey-500 dark:text-grey-600'),
link: true, link: true,
size: 'sm', size: 'sm',
onClick: () => { onClick: () => {
@ -87,7 +87,7 @@ const ThemePreview: React.FC<{
}, },
{ {
icon: 'mobile', icon: 'mobile',
iconColorClass: (previewMode === 'mobile' ? 'text-black' : 'text-grey-500'), iconColorClass: (previewMode === 'mobile' ? 'text-black dark:text-green' : 'text-grey-500 dark:text-grey-600'),
link: true, link: true,
size: 'sm', size: 'sm',
onClick: () => { onClick: () => {
@ -106,8 +106,8 @@ const ThemePreview: React.FC<{
return ( return (
<div className='absolute inset-0 z-[100]'> <div className='absolute inset-0 z-[100]'>
<PageHeader containerClassName='bg-grey-50 z-[100]' left={left} right={right} sticky={false} /> <PageHeader containerClassName='bg-grey-50 dark:bg-black z-[100]' left={left} right={right} sticky={false} />
<div className='flex h-[calc(100%-74px)] grow flex-col items-center justify-center bg-grey-50'> <div className='flex h-[calc(100%-74px)] grow flex-col items-center justify-center bg-grey-50 dark:bg-black'>
{previewMode === 'desktop' ? {previewMode === 'desktop' ?
<DesktopChrome> <DesktopChrome>
<iframe className='h-full w-full' <iframe className='h-full w-full'