feat(open-authoring): add hover tooltip (#5567)
This commit is contained in:
parent
4183409e71
commit
1822815118
@ -41,6 +41,40 @@ const styles = {
|
||||
`,
|
||||
};
|
||||
|
||||
const TooltipText = styled.div`
|
||||
visibility: hidden;
|
||||
width: 321px;
|
||||
background-color: #555;
|
||||
color: #fff;
|
||||
text-align: unset;
|
||||
border-radius: 6px;
|
||||
padding: 5px;
|
||||
|
||||
/* Position the tooltip text */
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
top: 145%;
|
||||
left: 50%;
|
||||
margin-left: -320px;
|
||||
|
||||
/* Fade in tooltip */
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s;
|
||||
`;
|
||||
|
||||
const Tooltip = styled.div`
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
&:hover + ${TooltipText} {
|
||||
visibility: visible;
|
||||
opacity: 0.9;
|
||||
}
|
||||
`;
|
||||
|
||||
const TooltipContainer = styled.div`
|
||||
position: relative;
|
||||
`;
|
||||
|
||||
const DropdownButton = styled(StyledDropdownButton)`
|
||||
${styles.noOverflow}
|
||||
@media (max-width: 1200px) {
|
||||
@ -301,40 +335,64 @@ export class EditorToolbar extends React.Component {
|
||||
);
|
||||
};
|
||||
|
||||
renderStatusInfoTooltip = () => {
|
||||
const { t, currentStatus } = this.props;
|
||||
|
||||
const statusToLocaleKey = {
|
||||
[status.get('DRAFT')]: 'statusInfoTooltipDraft',
|
||||
[status.get('PENDING_REVIEW')]: 'statusInfoTooltipInReview',
|
||||
};
|
||||
|
||||
const statusKey = Object.keys(statusToLocaleKey).find(key => key === currentStatus);
|
||||
return (
|
||||
<TooltipContainer>
|
||||
<Tooltip>
|
||||
<Icon type="info-circle" size="small" className="tooltip" />
|
||||
</Tooltip>
|
||||
{statusKey && (
|
||||
<TooltipText>{t(`editor.editorToolbar.${statusToLocaleKey[statusKey]}`)}</TooltipText>
|
||||
)}
|
||||
</TooltipContainer>
|
||||
);
|
||||
};
|
||||
|
||||
renderWorkflowStatusControls = () => {
|
||||
const { isUpdatingStatus, onChangeStatus, currentStatus, t, useOpenAuthoring } = this.props;
|
||||
return (
|
||||
<ToolbarDropdown
|
||||
dropdownTopOverlap="40px"
|
||||
dropdownWidth="120px"
|
||||
renderButton={() => (
|
||||
<StatusButton>
|
||||
{isUpdatingStatus
|
||||
? t('editor.editorToolbar.updating')
|
||||
: t('editor.editorToolbar.setStatus')}
|
||||
</StatusButton>
|
||||
)}
|
||||
>
|
||||
<StatusDropdownItem
|
||||
label={t('editor.editorToolbar.draft')}
|
||||
onClick={() => onChangeStatus('DRAFT')}
|
||||
icon={currentStatus === status.get('DRAFT') ? 'check' : null}
|
||||
/>
|
||||
<StatusDropdownItem
|
||||
label={t('editor.editorToolbar.inReview')}
|
||||
onClick={() => onChangeStatus('PENDING_REVIEW')}
|
||||
icon={currentStatus === status.get('PENDING_REVIEW') ? 'check' : null}
|
||||
/>
|
||||
{useOpenAuthoring ? (
|
||||
''
|
||||
) : (
|
||||
<>
|
||||
<ToolbarDropdown
|
||||
dropdownTopOverlap="40px"
|
||||
dropdownWidth="120px"
|
||||
renderButton={() => (
|
||||
<StatusButton>
|
||||
{isUpdatingStatus
|
||||
? t('editor.editorToolbar.updating')
|
||||
: t('editor.editorToolbar.setStatus')}
|
||||
</StatusButton>
|
||||
)}
|
||||
>
|
||||
<StatusDropdownItem
|
||||
label={t('editor.editorToolbar.ready')}
|
||||
onClick={() => onChangeStatus('PENDING_PUBLISH')}
|
||||
icon={currentStatus === status.get('PENDING_PUBLISH') ? 'check' : null}
|
||||
label={t('editor.editorToolbar.draft')}
|
||||
onClick={() => onChangeStatus('DRAFT')}
|
||||
icon={currentStatus === status.get('DRAFT') ? 'check' : null}
|
||||
/>
|
||||
)}
|
||||
</ToolbarDropdown>
|
||||
<StatusDropdownItem
|
||||
label={t('editor.editorToolbar.inReview')}
|
||||
onClick={() => onChangeStatus('PENDING_REVIEW')}
|
||||
icon={currentStatus === status.get('PENDING_REVIEW') ? 'check' : null}
|
||||
/>
|
||||
{useOpenAuthoring ? (
|
||||
''
|
||||
) : (
|
||||
<StatusDropdownItem
|
||||
label={t('editor.editorToolbar.ready')}
|
||||
onClick={() => onChangeStatus('PENDING_PUBLISH')}
|
||||
icon={currentStatus === status.get('PENDING_PUBLISH') ? 'check' : null}
|
||||
/>
|
||||
)}
|
||||
</ToolbarDropdown>
|
||||
{useOpenAuthoring && this.renderStatusInfoTooltip()}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -4,21 +4,6 @@ import { fromJS } from 'immutable';
|
||||
|
||||
import { EditorToolbar } from '../EditorToolbar';
|
||||
|
||||
jest.mock('netlify-cms-ui-default', () => ({
|
||||
// eslint-disable-next-line react/display-name
|
||||
Icon: props => <mock-icon {...props} />,
|
||||
// eslint-disable-next-line react/display-name
|
||||
Dropdown: props => <mock-dropdown {...props} />,
|
||||
// eslint-disable-next-line react/display-name
|
||||
DropdownItem: props => <mock-dropdown-item {...props} />,
|
||||
// eslint-disable-next-line react/display-name
|
||||
StyledDropdownButton: props => <mock-dropdown-button {...props} />,
|
||||
colorsRaw: {},
|
||||
colors: {},
|
||||
components: {},
|
||||
buttons: {},
|
||||
zIndex: {},
|
||||
}));
|
||||
jest.mock('../../UI', () => ({
|
||||
// eslint-disable-next-line react/display-name
|
||||
SettingsDropdown: props => <mock-settings-dropdown {...props} />,
|
||||
@ -112,5 +97,19 @@ describe('EditorToolbar', () => {
|
||||
);
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
['draft', 'pending_review', 'pending_publish'].forEach(status => {
|
||||
it(`should render with status=${status},useOpenAuthoring=${useOpenAuthoring}`, () => {
|
||||
const { asFragment } = render(
|
||||
<EditorToolbar
|
||||
{...props}
|
||||
hasWorkflow={true}
|
||||
currentStatus={status}
|
||||
useOpenAuthoring={useOpenAuthoring}
|
||||
/>,
|
||||
);
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -131,6 +131,10 @@ const en = {
|
||||
deleteEntry: 'Delete entry',
|
||||
saving: 'Saving...',
|
||||
save: 'Save',
|
||||
statusInfoTooltipDraft:
|
||||
'Entry status is set to draft. To finalize and submit it for review, set the status to ‘In review’',
|
||||
statusInfoTooltipInReview:
|
||||
'Entry is being reviewed, no further actions are required. However, you can still make additional changes while it is being reviewed.',
|
||||
deleting: 'Deleting...',
|
||||
updating: 'Updating...',
|
||||
setStatus: 'Set status',
|
||||
|
@ -22,6 +22,7 @@ import iconH2 from './h2.svg';
|
||||
import iconHOptions from './h-options.svg';
|
||||
import iconHome from './home.svg';
|
||||
import iconImage from './image.svg';
|
||||
import iconInfoCircle from './info-circle.svg';
|
||||
import iconItalic from './italic.svg';
|
||||
import iconLink from './link.svg';
|
||||
import iconList from './list.svg';
|
||||
@ -72,6 +73,7 @@ const images = {
|
||||
hOptions: iconHOptions,
|
||||
home: iconHome,
|
||||
image: iconImage,
|
||||
'info-circle': iconInfoCircle,
|
||||
italic: iconItalic,
|
||||
link: iconLink,
|
||||
list: iconList,
|
||||
|
@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-info-circle" viewBox="0 0 16 16">
|
||||
<path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z"/>
|
||||
<path d="m8.93 6.588-2.29.287-.082.38.45.083c.294.07.352.176.288.469l-.738 3.468c-.194.897.105 1.319.808 1.319.545 0 1.178-.252 1.465-.598l.088-.416c-.2.176-.492.246-.686.246-.275 0-.375-.193-.304-.533L8.93 6.588zM9 4.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 474 B |
Loading…
x
Reference in New Issue
Block a user