Skip to content

Commit

Permalink
Improve discoverability of unsaved settings (#20153)
Browse files Browse the repository at this point in the history
DES-195

The purpose of this change is to (1) reduce the overwhelming use of green on the settings UI in general and (2) to make unsaved sections more focused and discoverable and focused when trying to quit Settings without saving so that it's easier to find.

---------

Co-authored-by: Daniël van der Winden <danielvanderwinden@ghost.org>
  • Loading branch information
peterzimon and dvdwinden committed May 23, 2024
1 parent 277e169 commit d9390d2
Show file tree
Hide file tree
Showing 18 changed files with 71 additions and 53 deletions.
11 changes: 9 additions & 2 deletions apps/admin-x-design-system/src/global/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React, {HTMLProps} from 'react';
import clsx from 'clsx';
import {LoadingIndicator, LoadingIndicatorColor, LoadingIndicatorSize} from './LoadingIndicator';

export type ButtonColor = 'clear' | 'grey' | 'black' | 'green' | 'red' | 'white' | 'outline';
export type ButtonColor = 'clear' | 'light-grey' | 'grey' | 'black' | 'green' | 'red' | 'white' | 'outline';
export type ButtonSize = 'sm' | 'md';

export interface ButtonProps extends Omit<HTMLProps<HTMLButtonElement>, 'label' | 'size' | 'children'> {
Expand Down Expand Up @@ -75,6 +75,13 @@ const Button: React.FC<ButtonProps> = ({
loadingIndicatorColor = 'light';
iconColorClass = iconColorClass || 'text-white';
break;
case 'light-grey':
className = clsx(
link ? 'text-grey-800 hover:text-green-400 dark:text-white' : `bg-grey-200 text-black dark:bg-grey-900 dark:text-white ${!disabled && 'hover:!bg-grey-300 dark:hover:!bg-grey-800'}`,
className
);
loadingIndicatorColor = 'dark';
break;
case 'grey':
className = clsx(
link ? 'text-black hover:text-grey-800 dark:text-white' : `bg-grey-100 text-black dark:bg-grey-900 dark:text-white ${!disabled && 'hover:!bg-grey-300 dark:hover:!bg-grey-800'}`,
Expand Down Expand Up @@ -114,7 +121,7 @@ const Button: React.FC<ButtonProps> = ({
break;
default:
className = clsx(
link ? ' text-black hover:text-grey-800 dark:text-white' : `text-black dark:text-white dark:hover:bg-grey-900 ${!disabled && 'hover:bg-grey-200'}`,
link ? ' text-black hover:text-grey-800 dark:text-white' : `text-grey-900 dark:text-white dark:hover:bg-grey-900 ${!disabled && 'hover:bg-grey-200 hover:text-black'}`,
(outlineOnMobile && !link) && 'border border-grey-300 hover:border-transparent md:border-transparent',
className
);
Expand Down
25 changes: 8 additions & 17 deletions apps/admin-x-design-system/src/global/ButtonGroup.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ export const Default: Story = {
}
};

export const Small: Story = {
args: {
buttons: defaultButtons,
link: false,
size: 'sm'
}
};

const linkButtons: ButtonProps[] = [
{
label: 'Cancel',
Expand All @@ -50,21 +58,4 @@ export const LinkButtons: Story = {
buttons: linkButtons,
link: true
}
};

export const WithBackground: Story = {
args: {
buttons: linkButtons,
link: true,
clearBg: false
}
};

export const SmallWithBackground: Story = {
args: {
buttons: linkButtons,
link: true,
clearBg: false,
size: 'sm'
}
};
4 changes: 2 additions & 2 deletions apps/admin-x-design-system/src/global/ButtonGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export interface ButtonGroupProps {
const ButtonGroup: React.FC<ButtonGroupProps> = ({size = 'md', buttons, link, linkWithPadding, clearBg = true, outlineOnMobile, className}) => {
let groupColorClasses = clsx(
'flex items-center justify-start rounded',
link ? 'gap-4' : 'gap-3',
link ? 'gap-4' : 'gap-2',
className
);

Expand All @@ -33,7 +33,7 @@ const ButtonGroup: React.FC<ButtonGroupProps> = ({size = 'md', buttons, link, li
return (
<div className={groupColorClasses}>
{buttons.map(({key, ...props}) => (
<Button key={key} link={link} linkWithPadding={linkWithPadding} {...props} />
<Button key={key} link={link} linkWithPadding={linkWithPadding} size={size} {...props} />
))}
</div>
);
Expand Down
50 changes: 35 additions & 15 deletions apps/admin-x-design-system/src/settings/SettingGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ const SettingGroup = forwardRef<HTMLDivElement, SettingGroupProps>(function Sett

styles += ' border-grey-250 dark:border-grey-925';

// The links visible before editing
const viewButtons: ButtonProps[] = [];

if (!hideEditButton) {
Expand All @@ -89,7 +90,7 @@ const SettingGroup = forwardRef<HTMLDivElement, SettingGroupProps>(function Sett
{
label,
key: 'edit',
color: 'green',
color: 'clear',
onClick: handleEdit
}
);
Expand All @@ -104,6 +105,7 @@ const SettingGroup = forwardRef<HTMLDivElement, SettingGroupProps>(function Sett
);
}

// The buttons that show when you are editing
const editButtons: ButtonProps[] = [
{
label: 'Cancel',
Expand All @@ -119,9 +121,10 @@ const SettingGroup = forwardRef<HTMLDivElement, SettingGroupProps>(function Sett
}
editButtons.push(
{
label,
label: label,
key: 'save',
color: 'green',
color: saveState === 'unsaved' ? 'green' : 'light-grey',
disabled: saveState !== 'unsaved',
onClick: handleSave
}
);
Expand Down Expand Up @@ -151,18 +154,35 @@ const SettingGroup = forwardRef<HTMLDivElement, SettingGroupProps>(function Sett
styles
);

return (
<div className={containerClasses} data-testid={testId}>
<div ref={ref} className='absolute' id={navid && navid}></div>
{customHeader ? customHeader :
<SettingGroupHeader beta={beta} description={description} title={title!}>
{customButtons ? customButtons :
(onEditingChange && <ButtonGroup buttons={isEditing ? editButtons : viewButtons} link linkWithPadding />)}
</SettingGroupHeader>
}
{children}
</div>
);
if (!isEditing) {
return (
<div className={containerClasses} data-testid={testId}>
<div ref={ref} className='absolute' id={navid && navid}></div>
{customHeader ? customHeader :
<SettingGroupHeader beta={beta} description={description} title={title!}>
{customButtons ? customButtons :
(onEditingChange && <ButtonGroup buttons={isEditing ? editButtons : viewButtons} className={isEditing ? 'mt-[-5px] ' : '-mr-1 mt-[-5px]'} size='sm' />)
}
</SettingGroupHeader>
}
{children}
</div>
);
} else {
return (
<div className={containerClasses} data-testid={testId}>
<div ref={ref} className='absolute' id={navid && navid}></div>
{customHeader ? customHeader :
<SettingGroupHeader beta={beta} description={description} title={title!}>
{customButtons ? customButtons :
(onEditingChange && <ButtonGroup buttons={isEditing ? editButtons : viewButtons} className={isEditing ? 'mt-[-5px] ' : '-mr-1 mt-[-5px]'} size='sm' />)
}
</SettingGroupHeader>
}
{children}
</div>
);
}
});

export default SettingGroup;
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ const SettingGroupHeader: React.FC<SettingGroupHeaderProps> = ({title, descripti
{(title || description) &&
<div>
<Heading level={5}>{title}{beta && <sup className='ml-0.5 text-[10px] font-semibold uppercase tracking-wide'>Beta</sup>}</Heading>
{description && <p className="mt-1 hidden max-w-lg group-[.is-not-editing]/setting-group:!visible group-[.is-not-editing]/setting-group:!block md:!visible md:!block">{description}</p>}
{description && <p className="mt-1 hidden max-w-md group-[.is-not-editing]/setting-group:!visible group-[.is-not-editing]/setting-group:!block md:!visible md:!block">{description}</p>}
</div>
}
<div className='-mt-0.5'>
<div>
{children}
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const CodeInjection: React.FC<{ keywords: string[] }> = ({keywords}) => {
customHeader={
<div className='z-10 flex items-start justify-between'>
<SettingGroupHeader description='Add custom code to your publication.' title='Code injection' />
<Button color='green' label='Open' link linkWithPadding onClick={() => {
<Button className='mt-[-5px]' color='clear' label='Open' size='sm' onClick={() => {
NiceModal.show(CodeModal);
}} />
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const History: React.FC<{ keywords: string[] }> = ({keywords}) => {

return (
<TopLevelGroup
customButtons={<Button color='green' label='View history' link linkWithPadding onClick={openHistoryModal}/>}
customButtons={<Button className='mt-[-5px]' color='clear' label='View history' size='sm' onClick={openHistoryModal}/>}
description="View system event log"
keywords={keywords}
navid='history'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ const Integrations: React.FC<{ keywords: string[] }> = ({keywords}) => {
] as const;

const buttons = (
<Button className='hidden md:!visible md:!block' color='green' label='Add custom integration' link linkWithPadding onClick={() => {
<Button className='mt-[-5px] hidden md:!visible md:!block' color='clear' label='Add custom integration' size='sm' onClick={() => {
updateRoute('integrations/new');
setSelectedTab('custom');
}} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ const Labs: React.FC<{ keywords: string[] }> = ({keywords}) => {
<SettingGroupHeader description='This is a testing ground for new or experimental features. They may change, break or inexplicably disappear at any time.' title='Labs' />
{
!isOpen ?
<Button color='green' label='Open' link linkWithPadding onClick={() => {
<Button className='mt-[-5px]' color='clear' label='Open' size='sm' onClick={() => {
setIsOpen(true);
}} /> :
<Button color='green' label='Close' link linkWithPadding onClick={() => {
<Button className='mt-[-5px]' color='grey' label='Close' size='sm' onClick={() => {
setIsOpen(false);
}} />
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ const Newsletters: React.FC<{ keywords: string[] }> = ({keywords}) => {
}, [verifyEmailToken, handleError, verifyEmail]);

const buttons = (
<Button color='green' label='Add newsletter' link linkWithPadding onClick={() => {
<Button className='mt-[-5px]' color='clear' label='Add newsletter' size='sm' onClick={() => {
openNewsletterModal();
}} />
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ const Users: React.FC<{ keywords: string[], highlight?: boolean }> = ({keywords,
};

const buttons = (
<Button color='green' label='Invite people' link={true} linkWithPadding onClick={() => {
<Button className='mt-[-5px]' color='clear' label='Invite people' size='sm' linkWithPadding onClick={() => {
showInviteModal();
}} />
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ const Offers: React.FC<{ keywords: string[] }> = ({keywords}) => {

return (
<TopLevelGroup
customButtons={<Button color='green' disabled={!checkStripeEnabled(settings, config)} label={offerButtonText} link linkWithPadding onClick={offerButtonLink}/>}
customButtons={<Button className='mt-[-5px]' color='clear' disabled={!checkStripeEnabled(settings, config)} label={offerButtonText} size='sm' onClick={offerButtonLink}/>}
description={<>Create discounts & coupons to boost new subscriptions. {allOffers.length === 0 && <><a className='text-green' href="https://ghost.org/help/offers" rel="noopener noreferrer" target="_blank">{descriptionButtonText}</a></>}</>}
keywords={keywords}
navid='offers'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ const Recommendations: React.FC<{ keywords: string[] }> = ({keywords}) => {
};

const buttons = (
<Button className='hidden md:!visible md:!block' color='green' label='Add recommendation' link={true} onClick={() => {
<Button className='mt-[-5px] hidden md:!visible md:!block' color='clear' label='Add recommendation' size='sm' onClick={() => {
openAddNewRecommendationModal();
}} />
);
Expand All @@ -130,7 +130,7 @@ const Recommendations: React.FC<{ keywords: string[] }> = ({keywords}) => {
onSave={handleSave}
>
<div className='flex justify-center rounded border border-green px-4 py-2 md:hidden'>
<Button color='green' label='Add recommendation' link onClick={() => {
<Button color='light-grey' label='Add recommendation' link onClick={() => {
openAddNewRecommendationModal();
}} />
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const EmbedSignupForm: React.FC<{ keywords: string[] }> = ({keywords}) => {

return (
<TopLevelGroup
customButtons={<Button color='green' label='Embed' link onClick={openPreviewModal}/>}
customButtons={<Button className='mt-[-5px]' color='clear' label='Embed' size='sm' onClick={openPreviewModal}/>}
description="Grow your audience from anywhere on the web"
keywords={keywords}
navid='embed-signup-form'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const Portal: React.FC<{ keywords: string[] }> = ({keywords}) => {

return (
<TopLevelGroup
customButtons={<Button color='green' disabled={membersSignupAccess === 'none'} label='Customize' link linkWithPadding onClick={openPreviewModal}/>}
customButtons={<Button className='mt-[-5px]' color='clear' disabled={membersSignupAccess === 'none'} label='Customize' size='sm' onClick={openPreviewModal}/>}
description="Customize members modal signup flow"
keywords={keywords}
navid='portal'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const AnnouncementBar: React.FC<{ keywords: string[] }> = ({keywords}) => {

return (
<TopLevelGroup
customButtons={<Button color='green' label='Customize' link linkWithPadding onClick={openModal}/>}
customButtons={<Button className='mt-[-5px]' color='clear' label='Customize' size='sm' onClick={openModal}/>}
description="Highlight important updates or offers"
keywords={keywords}
navid='announcement-bar'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const DesignSetting: React.FC<{ keywords: string[] }> = ({keywords}) => {

return (
<TopLevelGroup
customButtons={<Button color='green' label='Customize' link linkWithPadding onClick={openPreviewModal}/>}
customButtons={<Button className='mt-[-5px]' color='clear' label='Customize' size='sm' onClick={openPreviewModal}/>}
description="Customize the theme, colors, and layout of your site"
keywords={keywords}
navid='design'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const Navigation: React.FC<{ keywords: string[] }> = ({keywords}) => {

return (
<TopLevelGroup
customButtons={<Button color='green' label='Customize' link linkWithPadding onClick={openPreviewModal}/>}
customButtons={<Button className='mt-[-5px]' color='clear' label='Customize' size='sm' onClick={openPreviewModal}/>}
description="Set up primary and secondary menus"
keywords={keywords}
navid='navigation'
Expand Down

0 comments on commit d9390d2

Please sign in to comment.