Various AdminX mobile refinements (#18017)

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

- AdminX settings had a couple of minor bugs related to responsive styles
This commit is contained in:
Peter Zimon 2023-09-07 17:39:30 +03:00 committed by GitHub
parent 2b248c1f5a
commit 608795d45a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 80 additions and 76 deletions

View File

@ -51,7 +51,7 @@ function App({ghostVersion, officialThemes, zapierTemplates, externalNavigate}:
{/* Sidebar */} {/* Sidebar */}
<div className="sticky top-[-42px] z-20 min-w-[260px] grow-0 md:top-[-52px] tablet:fixed tablet:top-[8vmin] tablet:basis-[260px]"> <div className="sticky top-[-42px] z-20 min-w-[260px] grow-0 md:top-[-52px] tablet:fixed tablet:top-[8vmin] tablet:basis-[260px]">
<div className='h-[84px]'> <div className='-mx-6 h-[84px] bg-white px-6 tablet:m-0 tablet:bg-transparent tablet:p-0'>
<Heading>Settings</Heading> <Heading>Settings</Heading>
</div> </div>
<div className="relative mt-[-32px] w-full overflow-x-hidden after:absolute after:inset-x-0 after:top-0 after:hidden after:h-[40px] after:bg-gradient-to-b after:from-white after:to-transparent after:content-[''] tablet:w-[260px] tablet:after:!visible tablet:after:!block"> <div className="relative mt-[-32px] w-full overflow-x-hidden after:absolute after:inset-x-0 after:top-0 after:hidden after:h-[40px] after:bg-gradient-to-b after:from-white after:to-transparent after:content-[''] tablet:w-[260px] tablet:after:!visible tablet:after:!block">
@ -59,7 +59,7 @@ function App({ghostVersion, officialThemes, zapierTemplates, externalNavigate}:
</div> </div>
</div> </div>
<div className="relative flex-auto pt-[3vmin] tablet:ml-[300px] tablet:pt-[85px]"> <div className="relative flex-auto pt-[3vmin] tablet:ml-[300px] tablet:pt-[85px]">
<div className='pointer-events-none fixed inset-x-0 top-0 z-[5] h-[80px] bg-gradient-to-t from-transparent to-white to-60%'></div> <div className='pointer-events-none fixed inset-x-0 top-0 z-[5] hidden h-[80px] bg-gradient-to-t from-transparent to-white to-60% tablet:!visible tablet:!block'></div>
<Settings /> <Settings />
</div> </div>
</div> </div>

View File

@ -27,7 +27,7 @@ const Table: React.FC<TableProps> = ({children, borderTop, hint, hintSeparator,
return ( return (
<> <>
<div> <div className='w-full overflow-x-scroll'>
{pageTitle && <Heading>{pageTitle}</Heading>} {pageTitle && <Heading>{pageTitle}</Heading>}
<table className={tableClasses}> <table className={tableClasses}>
<tbody> <tbody>
@ -40,7 +40,7 @@ const Table: React.FC<TableProps> = ({children, borderTop, hint, hintSeparator,
<div className="flex justify-between"> <div className="flex justify-between">
<Hint>{hint}</Hint> <Hint>{hint}</Hint>
{/* // TODO: Finish pagination component */} {/* // TODO: Finish pagination component */}
{/* <div className={`mt-1 flex items-center gap-2 text-xs text-grey-700`}>Showing 1-5 of 15 {/* <div className={`mt-1 flex items-center gap-2 text-xs text-grey-700`}>Showing 1-5 of 15
<button type='button'><Icon colorClass="text-green" name='chevron-left' size="xs" /> <button type='button'><Icon colorClass="text-green" name='chevron-left' size="xs" />
</button> </button>
<button type="button"><Icon colorClass="text-green" name='chevron-right' size="xs" /></button> <button type="button"><Icon colorClass="text-green" name='chevron-right' size="xs" /></button>

View File

@ -11,7 +11,7 @@ const TableHead: React.FC<HTMLProps<HTMLTableCellElement>> = ({className, childr
return ( return (
<td className={tableCellClasses} {...props}> <td className={tableCellClasses} {...props}>
<Heading level={6}>{children}</Heading> <Heading className='whitespace-nowrap' level={6}>{children}</Heading>
</td> </td>
); );
}; };

View File

@ -37,7 +37,7 @@ const TableRow: React.FC<TableRowProps> = ({id, action, hideActions, className,
{children} {children}
{action && {action &&
<td className={`px-6 py-3`}> <td className={`px-6 py-3`}>
<div className={`flex items-center justify-end ${hideActions ? 'invisible group-hover/table-row:visible' : ''}`}> <div className={`visible flex items-center justify-end ${hideActions ? 'group-hover/table-row:visible md:invisible' : ''}`}>
{action} {action}
</div> </div>
</td> </td>

View File

@ -123,7 +123,7 @@ const ImageUpload: React.FC<ImageUploadProps> = ({
height: (unstyled ? '' : height) height: (unstyled ? '' : height)
} }
} unstyled={unstyled} onUpload={onUpload}> } unstyled={unstyled} onUpload={onUpload}>
<span>{children}</span> <span className='text-center'>{children}</span>
</FileUpload> </FileUpload>
); );
} }

View File

@ -55,7 +55,7 @@ const TextField: React.FC<TextFieldProps> = ({
const enabledBorderClasses = border && 'border-grey-500 hover:border-grey-700 focus:border-black'; const enabledBorderClasses = border && 'border-grey-500 hover:border-grey-700 focus:border-black';
const textFieldClasses = !unstyled && clsx( const textFieldClasses = !unstyled && clsx(
'peer order-2 h-10 w-full py-2', 'peer order-2 h-8 w-full py-1 text-sm md:h-10 md:py-2 md:text-base',
border && 'border-b', border && 'border-b',
!border && '-mb-1.5', !border && '-mb-1.5',
clearBg ? 'bg-transparent' : 'bg-grey-75 px-[10px]', clearBg ? 'bg-transparent' : 'bg-grey-75 px-[10px]',
@ -87,7 +87,7 @@ const TextField: React.FC<TextFieldProps> = ({
'order-3', 'order-3',
border && 'border-b', border && 'border-b',
!border && '-mb-1.5', !border && '-mb-1.5',
(typeof (rightPlaceholder) === 'string') ? 'h-10 py-2 text-right text-grey-500' : 'h-10', (typeof (rightPlaceholder) === 'string') ? 'h-8 py-1 text-right text-sm text-grey-500 md:h-10 md:py-2 md:text-base' : 'h-10',
error && border ? `border-red` : `${disabled ? disabledBorderClasses : rightPHEnabledBorderClasses}` error && border ? `border-red` : `${disabled ? disabledBorderClasses : rightPHEnabledBorderClasses}`
); );

View File

@ -166,7 +166,7 @@ const SettingGroup: React.FC<SettingGroupProps> = ({
'relative flex-col gap-6 rounded', 'relative flex-col gap-6 rounded',
border && 'border p-5 md:p-7', border && 'border p-5 md:p-7',
!checkVisible(keywords) ? 'hidden' : 'flex', !checkVisible(keywords) ? 'hidden' : 'flex',
highlight && 'before:pointer-events-none before:absolute before:inset-[1px] before:z-20 before:animate-setting-highlight-fade-out before:rounded before:shadow-[0_0_0_3px_rgba(48,207,67,0.45)]', highlight && 'before:pointer-events-none before:absolute before:inset-[1px] before:animate-setting-highlight-fade-out before:rounded before:shadow-[0_0_0_3px_rgba(48,207,67,0.45)]',
!isEditing && 'is-not-editing group', !isEditing && 'is-not-editing group',
styles styles
); );

View File

@ -95,13 +95,13 @@ const CustomIntegrationModalContent: React.FC<{integration: Integration}> = ({in
} }
}} }}
> >
<div className='mt-7 flex w-full gap-7'> <div className='mt-7 flex w-full flex-col gap-7 md:flex-row'>
<div> <div>
<ImageUpload <ImageUpload
height='120px' height='100px'
id='custom-integration-icon' id='custom-integration-icon'
imageURL={formState.icon_image || undefined} imageURL={formState.icon_image || undefined}
width='120px' width='100px'
onDelete={() => updateForm(state => ({...state, icon_image: null}))} onDelete={() => updateForm(state => ({...state, icon_image: null}))}
onUpload={async (file) => { onUpload={async (file) => {
const imageUrl = getImageUrl(await uploadImage({file})); const imageUrl = getImageUrl(await uploadImage({file}));

View File

@ -31,68 +31,68 @@ const WebhooksTable: React.FC<{integration: Integration}> = ({integration}) => {
}); });
}; };
return <Table> return (<div>
<TableRow bgOnHover={false}> <Table>
<TableHead>{integration.webhooks?.length || 0} {integration.webhooks?.length === 1 ? 'webhook' : 'webhooks'}</TableHead> <TableRow bgOnHover={false}>
<TableHead>Last triggered</TableHead> <TableHead>{integration.webhooks?.length || 0} {integration.webhooks?.length === 1 ? 'webhook' : 'webhooks'}</TableHead>
<TableHead /> <TableHead>Last triggered</TableHead>
</TableRow> <TableHead />
{integration.webhooks?.map(webhook => (
<TableRow
action={
<Button color='red' label='Delete' link onClick={(e) => {
e?.stopPropagation();
handleDelete(webhook.id);
}} />
}
hideActions
onClick={() => {
NiceModal.show(WebhookModal, {
webhook,
integrationId:
integration.id
});
}}
>
<TableCell className='w-1/2'>
<div className='text-sm font-semibold'>{webhook.name}</div>
<div className='grid grid-cols-[max-content_1fr] gap-x-1 text-xs leading-snug'>
<span className='text-grey-600'>Event:</span>
<span>{getWebhookEventLabel(webhook.event)}</span>
<span className='text-grey-600'>URL:</span>
<span>{webhook.target_url}</span>
</div>
</TableCell>
<TableCell className='w-1/2 text-sm'>
{webhook.last_triggered_at && new Date(webhook.last_triggered_at).toLocaleString('default', {
weekday: 'short',
month: 'short',
day: 'numeric',
year: 'numeric',
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
})}
</TableCell>
</TableRow> </TableRow>
))} {integration.webhooks?.map(webhook => (
<TableRow bgOnHover={false} separator={false}> <TableRow
<TableCell colSpan={3}> action={
<Button <Button color='red' label='Delete' link onClick={(e) => {
color='green' e?.stopPropagation();
icon='add' handleDelete(webhook.id);
iconColorClass='text-green' }} />
label='Add webhook' }
size='sm' hideActions
link
onClick={() => { onClick={() => {
NiceModal.show(WebhookModal, { NiceModal.show(WebhookModal, {
integrationId: integration.id webhook,
integrationId:
integration.id
}); });
}} /> }}
</TableCell> >
</TableRow> <TableCell className='w-1/2'>
</Table>; <div className='text-sm font-semibold'>{webhook.name}</div>
<div className='grid grid-cols-[max-content_1fr] gap-x-1 text-xs leading-snug'>
<span className='text-grey-600'>Event:</span>
<span>{getWebhookEventLabel(webhook.event)}</span>
<span className='text-grey-600'>URL:</span>
<span>{webhook.target_url}</span>
</div>
</TableCell>
<TableCell className='w-1/2 text-sm'>
{webhook.last_triggered_at && new Date(webhook.last_triggered_at).toLocaleString('default', {
weekday: 'short',
month: 'short',
day: 'numeric',
year: 'numeric',
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
})}
</TableCell>
</TableRow>
))}
</Table>
<div className='mt-5'>
<Button
color='green'
icon='add'
iconColorClass='text-green'
label='Add webhook'
size='sm'
link
onClick={() => {
NiceModal.show(WebhookModal, {
integrationId: integration.id
});
}} />
</div>
</div>);
}; };
export default WebhooksTable; export default WebhooksTable;

View File

@ -338,8 +338,12 @@ const Sidebar: React.FC<{
<Toggle <Toggle
checked={newsletter.show_badge} checked={newsletter.show_badge}
direction='rtl' direction='rtl'
hint='Show youre a part of the indie publishing movement with a small badge in the footer' label={
label='Promote independent publishing' <div className='flex flex-col gap-0.5'>
<span className='text-sm md:text-base'>Promote independent publishing</span>
<span className='text-[11px] leading-tight text-grey-700 md:text-xs md:leading-tight'>Show youre a part of the indie publishing movement with a small badge in the footer</span>
</div>
}
labelStyle='value' labelStyle='value'
onChange={e => updateNewsletter({show_badge: e.target.checked})} onChange={e => updateNewsletter({show_badge: e.target.checked})}
/> />

View File

@ -11,7 +11,7 @@ import useRouting from '../../../hooks/useRouting';
const Preview: React.FC = () => { const Preview: React.FC = () => {
return ( return (
<div className='rounded-md bg-grey-100 text-grey-600'> <div className='hidden rounded-md bg-grey-100 text-grey-600 tablet:!visible tablet:!block'>
preview preview
</div> </div>
); );
@ -111,7 +111,7 @@ const EmbedSignupFormModal = NiceModal.create(() => {
title='' title=''
topRightContent='close' topRightContent='close'
> >
<div className='grid grid-cols-[5.5fr_2.5fr] gap-6 pb-8'> <div className='grid grid-cols-1 gap-6 pb-8 md:grid-cols-[5.5fr_2.5fr]'>
<Preview /> <Preview />
<Sidebar /> <Sidebar />
</div> </div>

View File

@ -217,7 +217,7 @@ const AnnouncementBarModal: React.FC = () => {
selectedURL={selectedPreviewTab} selectedURL={selectedPreviewTab}
sidebar={sidebar} sidebar={sidebar}
testId='announcement-bar-modal' testId='announcement-bar-modal'
title='Announcement bar' title='Announcement'
titleHeadingLevel={5} titleHeadingLevel={5}
onOk={async () => { onOk={async () => {
if (await handleSave()) { if (await handleSave()) {