mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-01-20 22:42:53 -05:00
Moved themes out of design settings
This commit is contained in:
parent
0a1d5fe4b7
commit
598c27c7cb
7 changed files with 54 additions and 51 deletions
|
@ -6,7 +6,7 @@ export interface DesktopChromeProps {
|
|||
|
||||
const DesktopChrome: React.FC<DesktopChromeProps & React.HTMLAttributes<HTMLDivElement>> = ({children, ...props}) => {
|
||||
return (
|
||||
<div className='flex h-full w-full flex-col px-5' {...props}>
|
||||
<div className='flex h-full w-full flex-col px-8' {...props}>
|
||||
<div className="h-full w-full overflow-hidden rounded-t-[4px] shadow-sm">
|
||||
{children}
|
||||
</div>
|
||||
|
|
|
@ -28,7 +28,7 @@ const PageHeader: React.FC<PageHeaderProps> = ({
|
|||
children
|
||||
}) => {
|
||||
const containerClasses = clsx(
|
||||
'z-50 h-22 min-h-[92px] p-8 px-6 tablet:px-12',
|
||||
'z-50 h-22 min-h-[92px] p-8',
|
||||
!children && 'flex items-center justify-between gap-3',
|
||||
sticky && 'sticky top-0',
|
||||
containerClassName
|
||||
|
|
|
@ -167,6 +167,7 @@ const Sidebar: React.FC = () => {
|
|||
|
||||
<SettingNavSection isVisible={checkVisible(Object.values(siteSearchKeywords).flat())} title="Site">
|
||||
<NavItem icon='palette' keywords={siteSearchKeywords.design} navid='design' title="Design & branding" onClick={handleSectionClick} />
|
||||
<NavItem icon='palette' keywords={siteSearchKeywords.theme} navid='theme' title="Change theme" onClick={handleSectionClick} />
|
||||
<NavItem icon='navigation' keywords={siteSearchKeywords.navigation} navid='navigation' title="Navigation" onClick={handleSectionClick} />
|
||||
<NavItem icon='megaphone' keywords={siteSearchKeywords.announcementBar} navid='announcement-bar' title="Announcement bar" onClick={handleSectionClick} />
|
||||
</SettingNavSection>
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
import React from 'react';
|
||||
import TopLevelGroup from '../../TopLevelGroup';
|
||||
import {Button, withErrorBoundary} from '@tryghost/admin-x-design-system';
|
||||
import {useRouting} from '@tryghost/admin-x-framework/routing';
|
||||
|
||||
const ChangeTheme: React.FC<{ keywords: string[] }> = ({keywords}) => {
|
||||
const {updateRoute} = useRouting();
|
||||
const openPreviewModal = () => {
|
||||
updateRoute('design/change-theme');
|
||||
};
|
||||
|
||||
return (
|
||||
<TopLevelGroup
|
||||
customButtons={<Button className='mt-[-5px]' color='clear' label='Open' size='sm' onClick={openPreviewModal}/>}
|
||||
description="Browse and install official themes or upload one"
|
||||
keywords={keywords}
|
||||
navid='theme'
|
||||
testId='theme'
|
||||
title="Change theme"
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default withErrorBoundary(ChangeTheme, 'Branding and design');
|
|
@ -1,4 +1,5 @@
|
|||
import AnnouncementBar from './AnnouncementBar';
|
||||
import ChangeTheme from './ChangeTheme';
|
||||
import DesignSetting from './DesignSetting';
|
||||
import Navigation from './Navigation';
|
||||
import React from 'react';
|
||||
|
@ -6,6 +7,7 @@ import SearchableSection from '../../SearchableSection';
|
|||
|
||||
export const searchKeywords = {
|
||||
design: ['site', 'logo', 'cover', 'colors', 'fonts', 'background', 'themes', 'appearance', 'style', 'design & branding', 'design and branding'],
|
||||
theme: ['theme', 'template', 'upload'],
|
||||
navigation: ['site', 'navigation', 'menus', 'primary', 'secondary', 'links'],
|
||||
announcementBar: ['site', 'announcement bar', 'important', 'banner']
|
||||
};
|
||||
|
@ -15,6 +17,7 @@ const SiteSettings: React.FC = () => {
|
|||
<>
|
||||
<SearchableSection keywords={Object.values(searchKeywords).flat()} title="Site">
|
||||
<DesignSetting keywords={searchKeywords.design} />
|
||||
<ChangeTheme keywords={searchKeywords.theme} />
|
||||
<Navigation keywords={searchKeywords.navigation} />
|
||||
<AnnouncementBar keywords={searchKeywords.announcementBar} />
|
||||
</SearchableSection>
|
||||
|
|
|
@ -6,7 +6,7 @@ import React, {useEffect, useState} from 'react';
|
|||
import ThemeInstalledModal from './theme/ThemeInstalledModal';
|
||||
import ThemePreview from './theme/ThemePreview';
|
||||
import useQueryParams from '../../../hooks/useQueryParams';
|
||||
import {Breadcrumbs, Button, ConfirmationModal, FileUpload, LimitModal, Modal, PageHeader, TabView, showToast} from '@tryghost/admin-x-design-system';
|
||||
import {Button, ConfirmationModal, FileUpload, LimitModal, Modal, PageHeader, TabView, showToast} from '@tryghost/admin-x-design-system';
|
||||
import {HostLimitError, useLimiter} from '../../../hooks/useLimiter';
|
||||
import {InstalledTheme, Theme, ThemesInstallResponseType, isDefaultOrLegacyTheme, useActivateTheme, useBrowseThemes, useInstallTheme, useUploadTheme} from '@tryghost/admin-x-framework/api/themes';
|
||||
import {JSONError} from '@tryghost/admin-x-framework/errors';
|
||||
|
@ -54,11 +54,11 @@ const ThemeToolbar: React.FC<ThemeToolbarProps> = ({
|
|||
setCurrentTab,
|
||||
themes
|
||||
}) => {
|
||||
const modal = useModal();
|
||||
const {updateRoute} = useRouting();
|
||||
const {mutateAsync: uploadTheme} = useUploadTheme();
|
||||
const limiter = useLimiter();
|
||||
const handleError = useHandleError();
|
||||
const refParam = useQueryParams().getParam('ref');
|
||||
|
||||
const [uploadConfig, setUploadConfig] = useState<{enabled: boolean; error?: string}>();
|
||||
|
||||
|
@ -80,11 +80,7 @@ const ThemeToolbar: React.FC<ThemeToolbarProps> = ({
|
|||
}, [limiter]);
|
||||
|
||||
const onClose = () => {
|
||||
if (refParam) {
|
||||
updateRoute(`design/edit?ref=${refParam}`);
|
||||
} else {
|
||||
updateRoute('design/edit');
|
||||
}
|
||||
updateRoute('/');
|
||||
};
|
||||
|
||||
const onThemeUpload = async (file: File) => {
|
||||
|
@ -169,7 +165,7 @@ const ThemeToolbar: React.FC<ThemeToolbarProps> = ({
|
|||
title,
|
||||
prompt,
|
||||
fatalErrors,
|
||||
onRetry: async (modal) => {
|
||||
onRetry: async () => {
|
||||
modal?.remove();
|
||||
handleUpload();
|
||||
}
|
||||
|
@ -219,17 +215,18 @@ const ThemeToolbar: React.FC<ThemeToolbarProps> = ({
|
|||
};
|
||||
|
||||
const left =
|
||||
<Breadcrumbs
|
||||
activeItemClassName='hidden md:!block md:!visible'
|
||||
itemClassName='hidden md:!block md:!visible'
|
||||
items={[
|
||||
{label: 'Design', onClick: onClose},
|
||||
{label: 'Change theme'}
|
||||
<div className='hidden md:!visible md:!block'>
|
||||
<TabView
|
||||
border={false}
|
||||
selectedTab={currentTab}
|
||||
tabs={[
|
||||
{id: 'official', title: 'Official themes'},
|
||||
{id: 'installed', title: 'Installed'}
|
||||
]}
|
||||
separatorClassName='hidden md:!block md:!visible'
|
||||
backIcon
|
||||
onBack={onClose}
|
||||
/>;
|
||||
onTabChange={(id: string) => {
|
||||
setCurrentTab(id);
|
||||
}} />
|
||||
</div>;
|
||||
|
||||
const handleUpload = () => {
|
||||
if (uploadConfig?.enabled) {
|
||||
|
@ -250,19 +247,11 @@ const ThemeToolbar: React.FC<ThemeToolbarProps> = ({
|
|||
|
||||
const right =
|
||||
<div className='flex items-center gap-14'>
|
||||
<div className='hidden md:!visible md:!block'>
|
||||
<TabView
|
||||
border={false}
|
||||
selectedTab={currentTab}
|
||||
tabs={[
|
||||
{id: 'official', title: 'Official themes'},
|
||||
{id: 'installed', title: 'Installed'}
|
||||
]}
|
||||
onTabChange={(id: string) => {
|
||||
setCurrentTab(id);
|
||||
}} />
|
||||
</div>
|
||||
<div className='flex items-center gap-3'>
|
||||
<Button label='Close' onClick={() => {
|
||||
modal.remove();
|
||||
onClose();
|
||||
}} />
|
||||
<Button color='black' label='Upload theme' loading={isUploading} onClick={handleUpload} />
|
||||
</div>
|
||||
</div>;
|
||||
|
@ -372,11 +361,7 @@ const ChangeThemeModal: React.FC<ChangeThemeModalProps> = ({source, themeRef}) =
|
|||
});
|
||||
}
|
||||
confirmModal?.remove();
|
||||
if (refParam) {
|
||||
updateRoute(`design/edit?ref=${refParam}`);
|
||||
} else {
|
||||
updateRoute('design/edit');
|
||||
}
|
||||
updateRoute('');
|
||||
} catch (e) {
|
||||
handleError(e);
|
||||
}
|
||||
|
@ -457,11 +442,7 @@ const ChangeThemeModal: React.FC<ChangeThemeModalProps> = ({source, themeRef}) =
|
|||
prompt,
|
||||
installedTheme: installedTheme!,
|
||||
onActivate: () => {
|
||||
if (refParam) {
|
||||
updateRoute(`design/edit?ref=${refParam}`);
|
||||
} else {
|
||||
updateRoute('design/edit');
|
||||
}
|
||||
updateRoute('');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -470,11 +451,7 @@ const ChangeThemeModal: React.FC<ChangeThemeModalProps> = ({source, themeRef}) =
|
|||
return (
|
||||
<Modal
|
||||
afterClose={() => {
|
||||
if (refParam) {
|
||||
updateRoute(`design/edit?ref=${refParam}`);
|
||||
} else {
|
||||
updateRoute('design/edit');
|
||||
}
|
||||
updateRoute('');
|
||||
}}
|
||||
animate={false}
|
||||
cancelLabel=''
|
||||
|
@ -500,7 +477,7 @@ const ChangeThemeModal: React.FC<ChangeThemeModalProps> = ({source, themeRef}) =
|
|||
setSelectedTheme(null);
|
||||
}}
|
||||
onClose={() => {
|
||||
updateRoute('design/edit');
|
||||
updateRoute('');
|
||||
}}
|
||||
onInstall={onInstall} />
|
||||
}
|
||||
|
|
|
@ -34,7 +34,6 @@ const ThemePreview: React.FC<{
|
|||
isInstalling,
|
||||
installedTheme,
|
||||
onBack,
|
||||
onClose,
|
||||
onInstall
|
||||
}) => {
|
||||
const [previewMode, setPreviewMode] = useState('desktop');
|
||||
|
@ -101,7 +100,6 @@ const ThemePreview: React.FC<{
|
|||
containerClassName='whitespace-nowrap'
|
||||
itemClassName='hidden md:!block md:!visible'
|
||||
items={[
|
||||
{label: 'Design', onClick: onClose},
|
||||
{label: 'Change theme', onClick: onBack},
|
||||
{label: selectedTheme.name}
|
||||
]}
|
||||
|
@ -163,7 +161,7 @@ const ThemePreview: React.FC<{
|
|||
return (
|
||||
<div className='absolute inset-0 z-[100]'>
|
||||
<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 dark:bg-black'>
|
||||
<div className='flex h-[calc(100%-92px)] grow flex-col items-center justify-center bg-grey-50 dark:bg-black'>
|
||||
{previewMode === 'desktop' ?
|
||||
<DesktopChrome>
|
||||
<iframe
|
||||
|
|
Loading…
Add table
Reference in a new issue