Merge pull request #33932 from overleaf/mg-select-style
Replace text label with icon in "Select style" toolbar button GitOrigin-RevId: 52b93a29db47e99609a90294e53abe1057a6c71d
This commit is contained in:
@@ -2113,7 +2113,6 @@
|
||||
"toolbar_bold": "",
|
||||
"toolbar_bulleted_list": "",
|
||||
"toolbar_change_editor_mode": "",
|
||||
"toolbar_choose_section_heading_level": "",
|
||||
"toolbar_code_visual_editor_switch": "",
|
||||
"toolbar_decrease_indent": "",
|
||||
"toolbar_editor": "",
|
||||
@@ -2138,7 +2137,7 @@
|
||||
"toolbar_numbered_list": "",
|
||||
"toolbar_redo": "",
|
||||
"toolbar_search_file": "",
|
||||
"toolbar_select_style": "",
|
||||
"toolbar_section_heading_level": "",
|
||||
"toolbar_selected_projects": "",
|
||||
"toolbar_selected_projects_management_actions": "",
|
||||
"toolbar_selected_projects_remove": "",
|
||||
|
||||
@@ -15,6 +15,7 @@ export const ToolbarButtonMenu: FC<
|
||||
label: string
|
||||
icon: React.ReactNode
|
||||
orientation?: 'vertical' | 'horizontal'
|
||||
className?: string
|
||||
disabled?: boolean
|
||||
disablePopover?: boolean
|
||||
altCommand?: (view: EditorView) => void
|
||||
@@ -25,6 +26,7 @@ export const ToolbarButtonMenu: FC<
|
||||
id,
|
||||
label,
|
||||
orientation = 'vertical',
|
||||
className,
|
||||
altCommand,
|
||||
onToggle,
|
||||
disabled,
|
||||
@@ -35,6 +37,18 @@ export const ToolbarButtonMenu: FC<
|
||||
const { open, onToggle: handleToggle, ref } = useDropdown()
|
||||
const view = useCodeMirrorViewContext()
|
||||
|
||||
useEffect(() => {
|
||||
if (!open) return
|
||||
|
||||
const onResize = () => {
|
||||
handleToggle(false)
|
||||
}
|
||||
window.addEventListener('resize', onResize)
|
||||
return () => {
|
||||
window.removeEventListener('resize', onResize)
|
||||
}
|
||||
}, [open, handleToggle])
|
||||
|
||||
useEffect(() => {
|
||||
if (disablePopover && open) {
|
||||
handleToggle(false)
|
||||
@@ -48,9 +62,12 @@ export const ToolbarButtonMenu: FC<
|
||||
const button = (
|
||||
<button
|
||||
type="button"
|
||||
className="ol-cm-toolbar-button"
|
||||
className={classNames('ol-cm-toolbar-button', className)}
|
||||
aria-label={label}
|
||||
aria-disabled={disabled}
|
||||
aria-haspopup="menu"
|
||||
aria-expanded={open}
|
||||
aria-controls={`${id}-menu`}
|
||||
onMouseDown={event => {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
|
||||
+30
-100
@@ -1,4 +1,3 @@
|
||||
import classnames from 'classnames'
|
||||
import {
|
||||
useCodeMirrorStateContext,
|
||||
useCodeMirrorViewContext,
|
||||
@@ -7,15 +6,12 @@ import {
|
||||
findCurrentSectionHeadingLevel,
|
||||
setSectionHeadingLevel,
|
||||
} from '../../extensions/toolbar/sections'
|
||||
import { useCallback, useMemo, useRef } from 'react'
|
||||
import OLOverlay from '@/shared/components/ol/ol-overlay'
|
||||
import OLPopover from '@/shared/components/ol/ol-popover'
|
||||
import useEventListener from '../../../../shared/hooks/use-event-listener'
|
||||
import useDropdown from '../../../../shared/hooks/use-dropdown'
|
||||
import { useMemo } from 'react'
|
||||
import { emitToolbarEvent } from '../../extensions/toolbar/utils/analytics'
|
||||
import MaterialIcon from '@/shared/components/material-icon'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import OLTooltip from '@/shared/components/ol/ol-tooltip'
|
||||
import { ToolbarButtonMenu } from './button-menu'
|
||||
import OLListGroupItem from '@/shared/components/ol/ol-list-group-item'
|
||||
|
||||
const levels = new Map([
|
||||
['text', 'Normal text'],
|
||||
@@ -33,107 +29,41 @@ export const SectionHeadingDropdown = () => {
|
||||
const view = useCodeMirrorViewContext()
|
||||
const { t } = useTranslation()
|
||||
|
||||
const { open: overflowOpen, onToggle: setOverflowOpen } = useDropdown()
|
||||
|
||||
useEventListener(
|
||||
'resize',
|
||||
useCallback(() => {
|
||||
setOverflowOpen(false)
|
||||
}, [setOverflowOpen])
|
||||
)
|
||||
|
||||
const toggleButtonRef = useRef<HTMLButtonElement | null>(null)
|
||||
|
||||
const currentLevel = useMemo(
|
||||
() => findCurrentSectionHeadingLevel(state),
|
||||
[state]
|
||||
)
|
||||
|
||||
const currentLabel = currentLevel
|
||||
? (levels.get(currentLevel.level) ?? currentLevel.level)
|
||||
: '---'
|
||||
|
||||
return (
|
||||
<>
|
||||
<OLTooltip
|
||||
id="section-heading-dropdown-tooltip"
|
||||
description={t('toolbar_select_style')}
|
||||
overlayProps={{ placement: 'bottom' }}
|
||||
>
|
||||
<button
|
||||
ref={toggleButtonRef}
|
||||
type="button"
|
||||
id="section-heading-menu-button"
|
||||
aria-haspopup="true"
|
||||
aria-controls="section-heading-menu"
|
||||
aria-label={t('toolbar_choose_section_heading_level')}
|
||||
className="ol-cm-toolbar-menu-toggle"
|
||||
onMouseDown={event => event.preventDefault()}
|
||||
onClick={() => setOverflowOpen(!overflowOpen)}
|
||||
>
|
||||
<span>{currentLabel}</span>
|
||||
<ToolbarButtonMenu
|
||||
id="section-heading-menu-button"
|
||||
label={t('toolbar_section_heading_level')}
|
||||
className="ol-cm-toolbar-button-wide"
|
||||
icon={
|
||||
<>
|
||||
<MaterialIcon
|
||||
type="text_fields"
|
||||
style={{ transform: 'scaleX(-1)' }}
|
||||
/>
|
||||
<MaterialIcon type="expand_more" />
|
||||
</button>
|
||||
</OLTooltip>
|
||||
|
||||
{overflowOpen && (
|
||||
<OLOverlay
|
||||
show
|
||||
onHide={() => setOverflowOpen(false)}
|
||||
transition={false}
|
||||
container={view.dom}
|
||||
containerPadding={0}
|
||||
placement="bottom"
|
||||
rootClose
|
||||
target={toggleButtonRef.current}
|
||||
popperConfig={{
|
||||
modifiers: [
|
||||
{
|
||||
name: 'offset',
|
||||
options: {
|
||||
offset: [0, 1],
|
||||
},
|
||||
},
|
||||
],
|
||||
</>
|
||||
}
|
||||
>
|
||||
{levelsEntries.map(([level, label]) => (
|
||||
<OLListGroupItem
|
||||
role="menuitem"
|
||||
key={level}
|
||||
active={level === currentLevel?.level}
|
||||
onClick={() => {
|
||||
emitToolbarEvent(view, 'section-level-change')
|
||||
setSectionHeadingLevel(view, level)
|
||||
view.focus()
|
||||
}}
|
||||
className={`ol-cm-section-heading-menu-item section-level-${level}`}
|
||||
>
|
||||
<OLPopover
|
||||
id="popover-toolbar-section-heading"
|
||||
className="ol-cm-toolbar-menu-popover"
|
||||
>
|
||||
<div
|
||||
className="ol-cm-toolbar-menu"
|
||||
id="section-heading-menu"
|
||||
role="menu"
|
||||
aria-labelledby="section-heading-menu-button"
|
||||
>
|
||||
{levelsEntries.map(([level, label]) => (
|
||||
<button
|
||||
type="button"
|
||||
role="menuitem"
|
||||
key={level}
|
||||
onClick={() => {
|
||||
emitToolbarEvent(view, 'section-level-change')
|
||||
setSectionHeadingLevel(view, level)
|
||||
view.focus()
|
||||
setOverflowOpen(false)
|
||||
}}
|
||||
className={classnames(
|
||||
'ol-cm-toolbar-menu-item',
|
||||
`section-level-${level}`,
|
||||
{
|
||||
'ol-cm-toolbar-menu-item-active':
|
||||
level === currentLevel?.level,
|
||||
}
|
||||
)}
|
||||
>
|
||||
{label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</OLPopover>
|
||||
</OLOverlay>
|
||||
)}
|
||||
</>
|
||||
{label}
|
||||
</OLListGroupItem>
|
||||
))}
|
||||
</ToolbarButtonMenu>
|
||||
)
|
||||
}
|
||||
|
||||
+24
-78
@@ -102,8 +102,29 @@ const toolbarTheme = EditorView.theme({
|
||||
color: 'var(--toolbar-btn-color)',
|
||||
borderColor: 'var(--editor-toolbar-bg)',
|
||||
background: 'none',
|
||||
'&.active': {
|
||||
backgroundColor: 'rgba(125, 125, 125, 0.1)',
|
||||
color: 'inherit',
|
||||
},
|
||||
'&:hover, &:focus': {
|
||||
backgroundColor: 'rgba(125, 125, 125, 0.2)',
|
||||
color: 'inherit',
|
||||
},
|
||||
'&.ol-cm-section-heading-menu-item': {
|
||||
border: 'none',
|
||||
padding: '4px 12px',
|
||||
height: '40px',
|
||||
fontSize: '14px',
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
'&.section-level-section': {
|
||||
fontSize: '1.44em',
|
||||
},
|
||||
'&.section-level-subsection': {
|
||||
fontSize: '1.2em',
|
||||
},
|
||||
'&.section-level-text': {
|
||||
fontWeight: 'normal',
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -174,6 +195,9 @@ const toolbarTheme = EditorView.theme({
|
||||
fontWeight: 700,
|
||||
},
|
||||
},
|
||||
'.ol-cm-toolbar-button.ol-cm-toolbar-button-wide': {
|
||||
width: 'auto',
|
||||
},
|
||||
'&.overall-theme-dark .ol-cm-toolbar-button': {
|
||||
opacity: 0.8,
|
||||
'&:hover, &:focus, &:active, &.active': {
|
||||
@@ -198,84 +222,6 @@ const toolbarTheme = EditorView.theme({
|
||||
display: 'flex',
|
||||
},
|
||||
},
|
||||
'.ol-cm-toolbar-menu-toggle': {
|
||||
background: 'transparent',
|
||||
border: 'none',
|
||||
color: 'inherit',
|
||||
borderRadius: 'var(--border-radius-base)',
|
||||
opacity: 0.8,
|
||||
width: '120px',
|
||||
fontSize: '13px',
|
||||
fontWeight: '700',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
padding: '5px 6px',
|
||||
'&:hover, &:focus, &.active': {
|
||||
backgroundColor: 'rgba(125, 125, 125, 0.1)',
|
||||
opacity: '1',
|
||||
color: 'inherit',
|
||||
},
|
||||
'& .caret': {
|
||||
marginTop: '0',
|
||||
},
|
||||
},
|
||||
'.ol-cm-toolbar-menu-popover': {
|
||||
border: 'none',
|
||||
borderRadius: '0',
|
||||
borderBottomLeftRadius: '4px',
|
||||
borderBottomRightRadius: '4px',
|
||||
boxShadow: '0 2px 5px rgb(0 0 0 / 20%)',
|
||||
backgroundColor: 'var(--editor-toolbar-bg)',
|
||||
color: 'var(--toolbar-btn-color)',
|
||||
padding: '0',
|
||||
'&.bottom': {
|
||||
marginTop: '1px',
|
||||
},
|
||||
'&.top': {
|
||||
marginBottom: '1px',
|
||||
},
|
||||
'& .arrow, & .popover-arrow': {
|
||||
display: 'none',
|
||||
},
|
||||
'& .popover-content, & > .popover-body': {
|
||||
padding: '0',
|
||||
color: 'inherit',
|
||||
},
|
||||
'& .ol-cm-toolbar-menu': {
|
||||
minWidth: '120px',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
boxSizing: 'border-box',
|
||||
fontSize: '14px',
|
||||
},
|
||||
'& .ol-cm-toolbar-menu-item': {
|
||||
border: 'none',
|
||||
background: 'none',
|
||||
padding: '4px 12px',
|
||||
height: '40px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
fontWeight: 'bold',
|
||||
color: 'inherit',
|
||||
'&.ol-cm-toolbar-menu-item-active': {
|
||||
backgroundColor: 'rgba(125, 125, 125, 0.1)',
|
||||
},
|
||||
'&:hover': {
|
||||
backgroundColor: 'rgba(125, 125, 125, 0.2)',
|
||||
color: 'inherit',
|
||||
},
|
||||
'&.section-level-section': {
|
||||
fontSize: '1.44em',
|
||||
},
|
||||
'&.section-level-subsection': {
|
||||
fontSize: '1.2em',
|
||||
},
|
||||
'&.section-level-body': {
|
||||
fontWeight: 'normal',
|
||||
},
|
||||
},
|
||||
},
|
||||
'&.overall-theme-dark .ol-cm-toolbar-table-grid': {
|
||||
'& td.active': {
|
||||
outlineColor: 'white',
|
||||
|
||||
@@ -2727,7 +2727,6 @@
|
||||
"toolbar_bold": "Bold",
|
||||
"toolbar_bulleted_list": "Bulleted list",
|
||||
"toolbar_change_editor_mode": "Change editor mode: Code / Visual",
|
||||
"toolbar_choose_section_heading_level": "Choose section heading level",
|
||||
"toolbar_code_visual_editor_switch": "Code and visual editor switch",
|
||||
"toolbar_decrease_indent": "Decrease indent",
|
||||
"toolbar_editor": "Editor tools",
|
||||
@@ -2752,7 +2751,7 @@
|
||||
"toolbar_numbered_list": "Numbered list",
|
||||
"toolbar_redo": "Redo",
|
||||
"toolbar_search_file": "Search file",
|
||||
"toolbar_select_style": "Select style",
|
||||
"toolbar_section_heading_level": "Section heading level",
|
||||
"toolbar_selected_projects": "Selected projects",
|
||||
"toolbar_selected_projects_management_actions": "Selected projects management actions",
|
||||
"toolbar_selected_projects_remove": "Remove selected projects",
|
||||
|
||||
+2
-2
@@ -68,14 +68,14 @@ describe('<CodeMirrorEditor/> toolbar in Rich Text mode', function () {
|
||||
mountEditor('hi')
|
||||
cy.get('.cm-content').should('have.text', 'hi')
|
||||
|
||||
clickToolbarButton('Choose section heading level')
|
||||
clickToolbarButton('Section heading level')
|
||||
cy.findByRole('menu').within(() => {
|
||||
cy.findByText('Subsection').click()
|
||||
})
|
||||
cy.get('.cm-content').should('have.text', 'hi')
|
||||
cy.get('.ol-cm-command-subsection').should('have.length', 1)
|
||||
|
||||
clickToolbarButton('Choose section heading level')
|
||||
clickToolbarButton('Section heading level')
|
||||
cy.findByRole('menu').within(() => {
|
||||
cy.findByText('Normal text').click()
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user