Merge pull request #20501 from overleaf/rd-filetree-toolbar

Migrate the file tree toolbar to Bootstrap 5

GitOrigin-RevId: 00ebe585206bf163bf9a00aa56b52d43effd5605
This commit is contained in:
Rebeka Dekany 2024-09-25 15:46:17 +02:00 committed by Copybot
parent abb59e4603
commit ac74ba9e8c
8 changed files with 142 additions and 48 deletions

View file

@ -1076,6 +1076,7 @@
"progress_bar_percentage": "",
"project_approaching_file_limit": "",
"project_figure_modal": "",
"project_files": "",
"project_flagged_too_many_compiles": "",
"project_has_too_many_files": "",
"project_last_published_at": "",

View file

@ -1,23 +1,27 @@
import { useTranslation } from 'react-i18next'
import * as eventTracking from '../../../infrastructure/event-tracking'
import { Button } from 'react-bootstrap'
import Tooltip from '../../../shared/components/tooltip'
import Icon from '../../../shared/components/icon'
import { useFileTreeActionable } from '../contexts/file-tree-actionable'
import { useFileTreeData } from '@/shared/context/file-tree-data-context'
import OLTooltip from '@/features/ui/components/ol/ol-tooltip'
import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
import MaterialIcon from '@/shared/components/material-icon'
import OLButtonToolbar from '@/features/ui/components/ol/ol-button-toolbar'
function FileTreeToolbar() {
const { fileTreeReadOnly } = useFileTreeData()
const { t } = useTranslation()
if (fileTreeReadOnly) return null
return (
<div className="toolbar toolbar-filetree">
<OLButtonToolbar
className="toolbar toolbar-filetree"
aria-label={t('project_files')}
>
<FileTreeToolbarLeft />
<FileTreeToolbarRight />
</div>
</OLButtonToolbar>
)
}
@ -44,33 +48,54 @@ function FileTreeToolbarLeft() {
return (
<div className="toolbar-left">
<Tooltip
<OLTooltip
id="new-file"
description={t('new_file')}
overlayProps={{ placement: 'bottom' }}
>
<Button onClick={createWithAnalytics} bsStyle={null}>
<Icon type="file" fw accessibilityLabel={t('new_file')} />
</Button>
</Tooltip>
<Tooltip
<button className="btn" onClick={createWithAnalytics}>
<BootstrapVersionSwitcher
bs5={
<MaterialIcon
type="description"
accessibilityLabel={t('new_file')}
/>
}
bs3={<Icon type="file" fw accessibilityLabel={t('new_file')} />}
/>
</button>
</OLTooltip>
<OLTooltip
id="new-folder"
description={t('new_folder')}
overlayProps={{ placement: 'bottom' }}
>
<Button onClick={startCreatingFolder} bsStyle={null}>
<Icon type="folder" fw accessibilityLabel={t('new_folder')} />
</Button>
</Tooltip>
<Tooltip
<button className="btn" onClick={startCreatingFolder} tabIndex={-1}>
<BootstrapVersionSwitcher
bs5={
<MaterialIcon
type="folder"
accessibilityLabel={t('new_folder')}
/>
}
bs3={<Icon type="folder" fw accessibilityLabel={t('new_folder')} />}
/>
</button>
</OLTooltip>
<OLTooltip
id="upload"
description={t('upload')}
overlayProps={{ placement: 'bottom' }}
>
<Button onClick={uploadWithAnalytics}>
<Icon type="upload" fw accessibilityLabel={t('upload')} />
</Button>
</Tooltip>
<button className="btn" onClick={uploadWithAnalytics} tabIndex={-1}>
<BootstrapVersionSwitcher
bs5={
<MaterialIcon type="upload" accessibilityLabel={t('upload')} />
}
bs3={<Icon type="upload" fw accessibilityLabel={t('upload')} />}
/>
</button>
</OLTooltip>
</div>
)
}
@ -87,26 +112,36 @@ function FileTreeToolbarRight() {
return (
<div className="toolbar-right">
{canRename ? (
<Tooltip
<OLTooltip
id="rename"
description={t('rename')}
overlayProps={{ placement: 'bottom' }}
>
<Button onClick={startRenaming}>
<Icon type="pencil" fw accessibilityLabel={t('rename')} />
</Button>
</Tooltip>
<button className="btn" onClick={startRenaming} tabIndex={-1}>
<BootstrapVersionSwitcher
bs3={<Icon type="pencil" fw accessibilityLabel={t('rename')} />}
bs5={
<MaterialIcon type="edit" accessibilityLabel={t('rename')} />
}
/>
</button>
</OLTooltip>
) : null}
{canDelete ? (
<Tooltip
<OLTooltip
id="delete"
description={t('delete')}
overlayProps={{ placement: 'bottom' }}
>
<Button onClick={startDeleting}>
<Icon type="trash-o" fw accessibilityLabel={t('delete')} />
</Button>
</Tooltip>
<button className="btn" onClick={startDeleting} tabIndex={-1}>
<BootstrapVersionSwitcher
bs3={<Icon type="trash-o" fw accessibilityLabel={t('delete')} />}
bs5={
<MaterialIcon type="delete" accessibilityLabel={t('delete')} />
}
/>
</button>
</OLTooltip>
) : null}
</div>
)

View file

@ -11,7 +11,7 @@ import UntrashProjectsButton from './buttons/untrash-projects-button'
import DeleteLeaveProjectsButton from './buttons/delete-leave-projects-button'
import LeaveProjectsButton from './buttons/leave-projects-button'
import DeleteProjectsButton from './buttons/delete-projects-button'
import OlButtonToolbar from '@/features/ui/components/ol/ol-button-toolbar'
import OLButtonToolbar from '@/features/ui/components/ol/ol-button-toolbar'
import OlButtonGroup from '@/features/ui/components/ol/ol-button-group'
function ProjectTools() {
@ -19,7 +19,7 @@ function ProjectTools() {
const { filter, selectedProjects } = useProjectListContext()
return (
<OlButtonToolbar aria-label={t('toolbar_selected_projects')}>
<OLButtonToolbar aria-label={t('toolbar_selected_projects')}>
<OlButtonGroup
aria-label={t('toolbar_selected_projects_management_actions')}
>
@ -48,7 +48,7 @@ function ProjectTools() {
{selectedProjects.length === 1 &&
filter !== 'archived' &&
filter !== 'trashed' && <ProjectToolsMoreDropdownButton />}
</OlButtonToolbar>
</OLButtonToolbar>
)
}

View file

@ -10,7 +10,7 @@ type OLButtonToolbarProps = ButtonToolbarProps & {
bs3Props?: Record<string, unknown>
}
function OlButtonToolbar(props: OLButtonToolbarProps) {
function OLButtonToolbar(props: OLButtonToolbarProps) {
const { bs3Props, ...rest } = props
const bs3ButtonToolbarProps: BS3ButtonToolbarProps = {
@ -28,4 +28,4 @@ function OlButtonToolbar(props: OLButtonToolbarProps) {
)
}
export default OlButtonToolbar
export default OLButtonToolbar

View file

@ -50,14 +50,6 @@
flex-direction: column;
height: 100%;
.toolbar.toolbar-filetree {
@include toolbar-sm-height;
@include toolbar-alt-bg;
padding: 0 var(--spacing-03);
flex-shrink: 0;
}
> file-tree-root,
.file-tree-inner {
position: relative;

View file

@ -4,7 +4,9 @@
--toolbar-header-btn-border-color: var(--neutral-80);
--toolbar-btn-color: var(--white);
--toolbar-btn-hover-bg-color: var(--neutral-80);
--toolbar-btn-hover-color: var(--white);
--project-name-color: var(--neutral-40);
--toolbar-filetree-bg-color: var(--neutral-80);
--project-rename-link-color: var(--neutral-40);
--project-rename-link-color-hover: var(--neutral-20);
--editor-header-logo-background: url(../../../../../public/img/ol-brand/overleaf-o-white.svg)
@ -17,7 +19,9 @@
--toolbar-header-btn-border-color: var(--neutral-20);
--toolbar-btn-color: var(--neutral-70);
--toolbar-btn-hover-bg-color: var(--neutral-10);
--toolbar-btn-hover-color: var(--neutral-70);
--project-name-color: var(--neutral-70);
--toolbar-filetree-bg-color: var(--white);
--project-rename-link-color: var(--neutral-70);
--project-rename-link-color-hover: var(--neutral-70);
--editor-header-logo-background: url(../../../../../public/img/ol-brand/overleaf-o.svg)
@ -25,10 +29,8 @@
}
.toolbar {
--toolbar-height: 40px;
display: flex;
align-items: stretch;
align-items: center;
height: var(--toolbar-height);
min-height: var(--toolbar-height);
border-bottom: 1px solid var(--toolbar-border-color);
@ -58,6 +60,59 @@
.toolbar-right .back-to-editor-btn {
margin-right: var(--spacing-09);
display: flex;
align-items: center;
.toolbar-label {
margin-bottom: 0;
}
}
> a:focus,
button:focus {
outline: none;
}
> a:not(.btn),
> button,
.toolbar-left > a:not(.btn),
.toolbar-left > button,
.toolbar-right > a:not(.btn),
.toolbar-right > button:not(.back-to-editor-btn) {
display: inline-block;
color: var(--toolbar-btn-color);
background-color: transparent;
padding: var(--spacing-01);
line-height: 1;
height: 24px;
border-radius: var(--border-radius-base);
&.toolbar-header-back-projects {
padding: var(--spacing-02) var(--spacing-04) var(--spacing-02);
margin-bottom: var(--spacing-01);
}
&:hover {
text-shadow: none;
color: var(--toolbar-btn-hover-color);
background-color: transparent;
text-decoration: none;
}
&.active,
&:active {
.label {
display: none;
}
color: white;
background-color: var(--bg-info-01);
box-shadow: none;
&:hover {
color: white;
}
}
}
a.btn-full-height,
@ -140,6 +195,9 @@
}
&.toolbar-header {
--toolbar-height: 40px;
align-items: stretch;
background-color: var(--toolbar-header-bg-color);
position: absolute;
top: 0;
@ -184,6 +242,14 @@
}
}
.toolbar-filetree {
@include toolbar-sm-height;
background-color: var(--toolbar-filetree-bg-color);
padding: 0 var(--spacing-03);
flex-shrink: 0;
}
.editor-menu-icon {
&.material-symbols {
width: 1em;

View file

@ -37,7 +37,6 @@
// Optional: Group multiple button groups together for a toolbar
.btn-toolbar {
margin-left: -5px; // Offset the first child's margin
&:extend(.clearfix all);
.btn-group,

View file

@ -1541,6 +1541,7 @@
"project": "project",
"project_approaching_file_limit": "This project is approaching the file limit",
"project_figure_modal": "Project",
"project_files": "Project files",
"project_flagged_too_many_compiles": "This project has been flagged for compiling too often. The limit will be lifted shortly.",
"project_has_too_many_files": "This project has reached the 2000 file limit",
"project_last_published_at": "Your project was last published at",