mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-25 11:55:03 +03:00
Renamed chrome header component in AdminX
refs. https://github.com/TryGhost/Team/issues/3354
This commit is contained in:
parent
011db27650
commit
d87994d210
@ -1,98 +0,0 @@
|
|||||||
import type {Meta, StoryObj} from '@storybook/react';
|
|
||||||
|
|
||||||
import Button from './Button';
|
|
||||||
import ButtonGroup from './ButtonGroup';
|
|
||||||
import DesktopChrome from './DesktopChrome';
|
|
||||||
import URLSelect from './URLSelect';
|
|
||||||
import {SelectOption} from './Select';
|
|
||||||
|
|
||||||
const meta = {
|
|
||||||
title: 'Global / Chrome / Desktop',
|
|
||||||
component: DesktopChrome,
|
|
||||||
tags: ['autodocs']
|
|
||||||
} satisfies Meta<typeof DesktopChrome>;
|
|
||||||
|
|
||||||
export default meta;
|
|
||||||
type Story = StoryObj<typeof DesktopChrome>;
|
|
||||||
|
|
||||||
export const Default: Story = {
|
|
||||||
args: {
|
|
||||||
children: (
|
|
||||||
<div className='flex items-center justify-center p-10 text-sm text-grey-500'>
|
|
||||||
Window contents
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const Small: Story = {
|
|
||||||
args: {
|
|
||||||
children: (
|
|
||||||
<div className='flex items-center justify-center p-10 text-sm text-grey-500'>
|
|
||||||
Window contents
|
|
||||||
</div>
|
|
||||||
),
|
|
||||||
size: 'sm'
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const WithBorder: Story = {
|
|
||||||
args: {
|
|
||||||
children: (
|
|
||||||
<div className='flex items-center justify-center p-10 text-sm text-grey-500'>
|
|
||||||
Window contents
|
|
||||||
</div>
|
|
||||||
),
|
|
||||||
border: true
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const Empty: Story = {
|
|
||||||
args: {
|
|
||||||
children: (
|
|
||||||
<div className='flex items-center justify-center p-10 text-sm text-grey-500'>
|
|
||||||
Window contents
|
|
||||||
</div>
|
|
||||||
),
|
|
||||||
toolbarLeft: <></>
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const WithTitle: Story = {
|
|
||||||
args: {
|
|
||||||
children: (
|
|
||||||
<div className='flex items-center justify-center p-10 text-sm text-grey-500'>
|
|
||||||
Window contents
|
|
||||||
</div>
|
|
||||||
),
|
|
||||||
toolbarCenter: 'Hello title'
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const selectOptions: SelectOption[] = [
|
|
||||||
{value: 'homepage', label: 'Homepage'},
|
|
||||||
{value: 'post', label: 'Post'},
|
|
||||||
{value: 'page', label: 'Page'},
|
|
||||||
{value: 'tag-archive', label: 'Tag archive'},
|
|
||||||
{value: 'author-archive', label: 'Author archive'}
|
|
||||||
];
|
|
||||||
|
|
||||||
export const CustomToolbar: Story = {
|
|
||||||
args: {
|
|
||||||
children: (
|
|
||||||
<div className='flex items-center justify-center p-10 text-sm text-grey-500'>
|
|
||||||
Window contents
|
|
||||||
</div>
|
|
||||||
),
|
|
||||||
toolbarLeft: <Button icon='arrow-left' link={true} size='sm' />,
|
|
||||||
toolbarCenter: <URLSelect options={selectOptions} onSelect={(value: string) => {
|
|
||||||
alert(value);
|
|
||||||
}} />,
|
|
||||||
toolbarRight: <ButtonGroup
|
|
||||||
buttons={[
|
|
||||||
{icon: 'laptop', link: true, size: 'sm'},
|
|
||||||
{icon: 'mobile', link: true, size: 'sm', iconColorClass: 'text-grey-500'}
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,74 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
export type DesktopChromeSize = 'sm' | 'md';
|
|
||||||
|
|
||||||
interface DesktopChromeProps {
|
|
||||||
size?: DesktopChromeSize;
|
|
||||||
toolbarLeft?: React.ReactNode;
|
|
||||||
toolbarCenter?: React.ReactNode;
|
|
||||||
toolbarRight?: React.ReactNode;
|
|
||||||
children?: React.ReactNode;
|
|
||||||
chromeClasses?: string;
|
|
||||||
toolbarClasses?: string;
|
|
||||||
contentClasses?: string;
|
|
||||||
border?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
const DesktopChrome: React.FC<DesktopChromeProps> = ({
|
|
||||||
size = 'md',
|
|
||||||
toolbarLeft = '',
|
|
||||||
toolbarCenter = '',
|
|
||||||
toolbarRight = '',
|
|
||||||
children,
|
|
||||||
chromeClasses = '',
|
|
||||||
toolbarClasses = '',
|
|
||||||
contentClasses = '',
|
|
||||||
border = false
|
|
||||||
}) => {
|
|
||||||
let containerSize = size === 'sm' ? 'min-h-[32px] p-2' : 'min-h-[48px] p-3';
|
|
||||||
const trafficLightSize = size === 'sm' ? 'w-[6px] h-[6px]' : 'w-[10px] h-[10px]';
|
|
||||||
const trafficLightWidth = size === 'sm' ? 36 : 56;
|
|
||||||
let trafficLightContainerStyle = size === 'sm' ? 'gap-[5px] ' : 'gap-2 ';
|
|
||||||
trafficLightContainerStyle += `w-[${trafficLightWidth}px]`;
|
|
||||||
|
|
||||||
contentClasses += ' grow';
|
|
||||||
|
|
||||||
const trafficLights = (
|
|
||||||
<div className={`absolute left-4 flex h-full items-center ${trafficLightContainerStyle}`}>
|
|
||||||
<div className={`rounded-full bg-grey-500 ${trafficLightSize}`}></div>
|
|
||||||
<div className={`rounded-full bg-grey-500 ${trafficLightSize}`}></div>
|
|
||||||
<div className={`rounded-full bg-grey-500 ${trafficLightSize}`}></div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={`flex h-full grow-0 flex-col ${border ? 'rounded-sm border border-grey-100' : ''} ${chromeClasses}`}>
|
|
||||||
<header className={`relative flex items-center justify-center bg-grey-50 ${containerSize} ${toolbarClasses}`}>
|
|
||||||
{toolbarLeft ?
|
|
||||||
<div className='absolute left-4 flex h-full items-center'>
|
|
||||||
{toolbarLeft}
|
|
||||||
</div>
|
|
||||||
:
|
|
||||||
trafficLights
|
|
||||||
}
|
|
||||||
<div className='flex grow justify-center'>
|
|
||||||
{(typeof toolbarCenter === 'string') ?
|
|
||||||
(<span className='text-sm font-bold'>{toolbarCenter}</span>)
|
|
||||||
:
|
|
||||||
(<>{toolbarCenter}</>)
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
{toolbarRight &&
|
|
||||||
<div className='absolute right-4 flex h-full items-center'>
|
|
||||||
{toolbarRight}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</header>
|
|
||||||
<section className={contentClasses}>
|
|
||||||
{children}
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default DesktopChrome;
|
|
@ -0,0 +1,61 @@
|
|||||||
|
import type {Meta, StoryObj} from '@storybook/react';
|
||||||
|
|
||||||
|
import Button from './Button';
|
||||||
|
import ButtonGroup from './ButtonGroup';
|
||||||
|
import DesktopChromeHeader from './DesktopChromeHeader';
|
||||||
|
import URLSelect from './URLSelect';
|
||||||
|
import {SelectOption} from './Select';
|
||||||
|
|
||||||
|
const meta = {
|
||||||
|
title: 'Global / Chrome / Desktop Header',
|
||||||
|
component: DesktopChromeHeader,
|
||||||
|
tags: ['autodocs']
|
||||||
|
} satisfies Meta<typeof DesktopChromeHeader>;
|
||||||
|
|
||||||
|
export default meta;
|
||||||
|
type Story = StoryObj<typeof DesktopChromeHeader>;
|
||||||
|
|
||||||
|
export const Default: Story = {
|
||||||
|
args: {}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Small: Story = {
|
||||||
|
args: {
|
||||||
|
size: 'sm'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Empty: Story = {
|
||||||
|
args: {
|
||||||
|
toolbarLeft: <></>
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const WithTitle: Story = {
|
||||||
|
args: {
|
||||||
|
toolbarCenter: 'Hello title'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const selectOptions: SelectOption[] = [
|
||||||
|
{value: 'homepage', label: 'Homepage'},
|
||||||
|
{value: 'post', label: 'Post'},
|
||||||
|
{value: 'page', label: 'Page'},
|
||||||
|
{value: 'tag-archive', label: 'Tag archive'},
|
||||||
|
{value: 'author-archive', label: 'Author archive'}
|
||||||
|
];
|
||||||
|
|
||||||
|
export const CustomToolbar: Story = {
|
||||||
|
args: {
|
||||||
|
toolbarLeft: <Button icon='arrow-left' link={true} size='sm' />,
|
||||||
|
toolbarCenter: <URLSelect options={selectOptions} onSelect={(value: string) => {
|
||||||
|
alert(value);
|
||||||
|
}} />,
|
||||||
|
toolbarRight: <ButtonGroup
|
||||||
|
buttons={[
|
||||||
|
{icon: 'laptop', link: true, size: 'sm'},
|
||||||
|
{icon: 'mobile', link: true, size: 'sm', iconColorClass: 'text-grey-500'}
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
};
|
@ -0,0 +1,59 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
export type DesktopChromeHeaderSize = 'sm' | 'md';
|
||||||
|
|
||||||
|
interface DesktopChromeHeaderProps {
|
||||||
|
size?: DesktopChromeHeaderSize;
|
||||||
|
toolbarLeft?: React.ReactNode;
|
||||||
|
toolbarCenter?: React.ReactNode;
|
||||||
|
toolbarRight?: React.ReactNode;
|
||||||
|
toolbarClasses?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const DesktopChromeHeader: React.FC<DesktopChromeHeaderProps> = ({
|
||||||
|
size = 'md',
|
||||||
|
toolbarLeft = '',
|
||||||
|
toolbarCenter = '',
|
||||||
|
toolbarRight = '',
|
||||||
|
toolbarClasses = ''
|
||||||
|
}) => {
|
||||||
|
let containerSize = size === 'sm' ? 'min-h-[32px] p-2' : 'min-h-[48px] p-3';
|
||||||
|
const trafficLightSize = size === 'sm' ? 'w-[6px] h-[6px]' : 'w-[10px] h-[10px]';
|
||||||
|
const trafficLightWidth = size === 'sm' ? 36 : 56;
|
||||||
|
let trafficLightContainerStyle = size === 'sm' ? 'gap-[5px] ' : 'gap-2 ';
|
||||||
|
trafficLightContainerStyle += `w-[${trafficLightWidth}px]`;
|
||||||
|
|
||||||
|
const trafficLights = (
|
||||||
|
<div className={`absolute left-4 flex h-full items-center ${trafficLightContainerStyle}`}>
|
||||||
|
<div className={`rounded-full bg-grey-500 ${trafficLightSize}`}></div>
|
||||||
|
<div className={`rounded-full bg-grey-500 ${trafficLightSize}`}></div>
|
||||||
|
<div className={`rounded-full bg-grey-500 ${trafficLightSize}`}></div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<header className={`relative flex items-center justify-center bg-grey-50 ${containerSize} ${toolbarClasses}`}>
|
||||||
|
{toolbarLeft ?
|
||||||
|
<div className='absolute left-4 flex h-full items-center'>
|
||||||
|
{toolbarLeft}
|
||||||
|
</div>
|
||||||
|
:
|
||||||
|
trafficLights
|
||||||
|
}
|
||||||
|
<div className='flex grow justify-center'>
|
||||||
|
{(typeof toolbarCenter === 'string') ?
|
||||||
|
(<span className='text-sm font-bold'>{toolbarCenter}</span>)
|
||||||
|
:
|
||||||
|
(<>{toolbarCenter}</>)
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
{toolbarRight &&
|
||||||
|
<div className='absolute right-4 flex h-full items-center'>
|
||||||
|
{toolbarRight}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</header>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DesktopChromeHeader;
|
@ -1,5 +1,5 @@
|
|||||||
import ButtonGroup from './ButtonGroup';
|
import ButtonGroup from './ButtonGroup';
|
||||||
import DesktopChrome from './DesktopChrome';
|
import DesktopChromeHeader from './DesktopChromeHeader';
|
||||||
import Heading from './Heading';
|
import Heading from './Heading';
|
||||||
import Modal from './Modal';
|
import Modal from './Modal';
|
||||||
import NiceModal, {useModal} from '@ebay/nice-modal-react';
|
import NiceModal, {useModal} from '@ebay/nice-modal-react';
|
||||||
@ -81,16 +81,17 @@ export const PreviewModalContent: React.FC<PreviewModalProps> = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
preview = (
|
preview = (
|
||||||
<DesktopChrome
|
<>
|
||||||
chromeClasses='bg-grey-50'
|
<div className='bg-grey-50 p-2 pl-3'>
|
||||||
|
<DesktopChromeHeader
|
||||||
toolbarCenter={toolbarCenter}
|
toolbarCenter={toolbarCenter}
|
||||||
toolbarClasses='m-2'
|
|
||||||
toolbarRight={toolbarRight}
|
toolbarRight={toolbarRight}
|
||||||
>
|
/>
|
||||||
<div className='flex h-full items-center justify-center bg-grey-50 text-sm text-grey-400'>
|
</div>
|
||||||
|
<div className='flex h-full grow items-center justify-center bg-grey-50 text-sm text-grey-400'>
|
||||||
{preview}
|
{preview}
|
||||||
</div>
|
</div>
|
||||||
</DesktopChrome>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user