mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Merge pull request #21226 from overleaf/rd-history-filetree
Migrate the history file tree to Bootstrap 5 GitOrigin-RevId: bb5443d91992ff7241ed5c8bb467fa553e55bb0f
This commit is contained in:
parent
d0b5c2f307
commit
200e7a75f0
5 changed files with 188 additions and 49 deletions
|
@ -4,6 +4,8 @@ import HistoryFileTreeItem from './history-file-tree-item'
|
||||||
import iconTypeFromName from '../../../file-tree/util/icon-type-from-name'
|
import iconTypeFromName from '../../../file-tree/util/icon-type-from-name'
|
||||||
import Icon from '../../../../shared/components/icon'
|
import Icon from '../../../../shared/components/icon'
|
||||||
import type { FileDiff } from '../../services/types/file'
|
import type { FileDiff } from '../../services/types/file'
|
||||||
|
import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
|
||||||
|
import MaterialIcon from '@/shared/components/material-icon'
|
||||||
|
|
||||||
type HistoryFileTreeDocProps = {
|
type HistoryFileTreeDocProps = {
|
||||||
file: FileDiff
|
file: FileDiff
|
||||||
|
@ -34,10 +36,20 @@ function HistoryFileTreeDoc({
|
||||||
name={name}
|
name={name}
|
||||||
operation={'operation' in file ? file.operation : undefined}
|
operation={'operation' in file ? file.operation : undefined}
|
||||||
icons={
|
icons={
|
||||||
|
<BootstrapVersionSwitcher
|
||||||
|
bs3={
|
||||||
<Icon
|
<Icon
|
||||||
type={iconTypeFromName(name)}
|
type={iconTypeFromName(name)}
|
||||||
fw
|
fw
|
||||||
className="spaced file-tree-icon"
|
className="file-tree-icon"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
bs5={
|
||||||
|
<MaterialIcon
|
||||||
|
type={iconTypeFromName(name)}
|
||||||
|
className="file-tree-icon"
|
||||||
|
/>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -6,6 +6,8 @@ import HistoryFileTreeFolderList from './history-file-tree-folder-list'
|
||||||
|
|
||||||
import Icon from '../../../../shared/components/icon'
|
import Icon from '../../../../shared/components/icon'
|
||||||
import type { HistoryDoc, HistoryFileTree } from '../../utils/file-tree'
|
import type { HistoryDoc, HistoryFileTree } from '../../utils/file-tree'
|
||||||
|
import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
|
||||||
|
import MaterialIcon from '@/shared/components/material-icon'
|
||||||
|
|
||||||
type HistoryFileTreeFolderProps = {
|
type HistoryFileTreeFolderProps = {
|
||||||
name: string
|
name: string
|
||||||
|
@ -41,6 +43,8 @@ function HistoryFileTreeFolder({
|
||||||
})
|
})
|
||||||
|
|
||||||
const icons = (
|
const icons = (
|
||||||
|
<BootstrapVersionSwitcher
|
||||||
|
bs3={
|
||||||
<>
|
<>
|
||||||
<button
|
<button
|
||||||
onClick={() => setExpanded(!expanded)}
|
onClick={() => setExpanded(!expanded)}
|
||||||
|
@ -59,6 +63,26 @@ function HistoryFileTreeFolder({
|
||||||
className="file-tree-folder-icon"
|
className="file-tree-folder-icon"
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
|
}
|
||||||
|
bs5={
|
||||||
|
<>
|
||||||
|
<button
|
||||||
|
onClick={() => setExpanded(!expanded)}
|
||||||
|
aria-label={expanded ? t('collapse') : t('expand')}
|
||||||
|
className="history-file-tree-folder-button"
|
||||||
|
>
|
||||||
|
<MaterialIcon
|
||||||
|
type={expanded ? 'expand_more' : 'chevron_right'}
|
||||||
|
className="file-tree-expand-icon"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
<MaterialIcon
|
||||||
|
type={expanded ? 'folder_open' : 'folder'}
|
||||||
|
className="file-tree-folder-icon"
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
/>
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -71,7 +95,12 @@ function HistoryFileTreeFolder({
|
||||||
aria-label={name}
|
aria-label={name}
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
onClick={() => setExpanded(!expanded)}
|
onClick={() => setExpanded(!expanded)}
|
||||||
onKeyDown={() => setExpanded(!expanded)}
|
onKeyDown={event => {
|
||||||
|
if (event.key === 'Enter' || event.key === ' ') {
|
||||||
|
event.preventDefault()
|
||||||
|
setExpanded(!expanded)
|
||||||
|
}
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<HistoryFileTreeItem name={name} icons={icons} />
|
<HistoryFileTreeItem name={name} icons={icons} />
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
import type { ReactNode } from 'react'
|
import type { ReactNode } from 'react'
|
||||||
import type { FileOperation } from '../../services/types/file-operation'
|
import type { FileOperation } from '../../services/types/file-operation'
|
||||||
import Tag from '@/shared/components/tag'
|
import OLTag from '@/features/ui/components/ol/ol-tag'
|
||||||
|
|
||||||
type FileTreeItemProps = {
|
type FileTreeItemProps = {
|
||||||
name: string
|
name: string
|
||||||
|
@ -26,7 +26,7 @@ export default function HistoryFileTreeItem({
|
||||||
{name}
|
{name}
|
||||||
</div>
|
</div>
|
||||||
{operation && (
|
{operation && (
|
||||||
<Tag className="history-file-tree-item-badge">{operation}</Tag>
|
<OLTag className="history-file-tree-item-badge">{operation}</OLTag>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -114,16 +114,8 @@
|
||||||
line-height: var(--file-tree-line-height);
|
line-height: var(--file-tree-line-height);
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
&:focus {
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.entity {
|
.entity {
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
|
||||||
&:focus {
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.entity > .entity-name > button {
|
.entity > .entity-name > button {
|
||||||
|
@ -131,10 +123,6 @@
|
||||||
border: 0;
|
border: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|
||||||
&:focus {
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.item-name-button {
|
&.item-name-button {
|
||||||
color: inherit;
|
color: inherit;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -157,10 +145,6 @@
|
||||||
text-overflow: clip;
|
text-overflow: clip;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:focus {
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
|
|
||||||
@include fake-full-width-bg(transparent);
|
@include fake-full-width-bg(transparent);
|
||||||
|
@ -219,11 +203,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.material-symbols.folder-open,
|
|
||||||
.material-symbols.fa-folder {
|
|
||||||
color: var(--content-disabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
.material-symbols.toggle {
|
.material-symbols.toggle {
|
||||||
width: 24px;
|
width: 24px;
|
||||||
padding: var(--spacing-03);
|
padding: var(--spacing-03);
|
||||||
|
|
|
@ -359,7 +359,7 @@ history-root {
|
||||||
}
|
}
|
||||||
|
|
||||||
.history-version-label-tooltip {
|
.history-version-label-tooltip {
|
||||||
padding: 6px;
|
padding: var(--spacing-03);
|
||||||
text-align: initial;
|
text-align: initial;
|
||||||
|
|
||||||
.history-version-label-tooltip-row {
|
.history-version-label-tooltip-row {
|
||||||
|
@ -433,6 +433,125 @@ history-root {
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
.history-error {
|
.history-file-tree {
|
||||||
padding: 16px;
|
display: flex !important; // To work around jQuery layout's inline styles
|
||||||
|
flex-direction: column;
|
||||||
|
max-height: 100%;
|
||||||
|
|
||||||
|
ul.history-file-tree-list {
|
||||||
|
margin: 0;
|
||||||
|
overflow: hidden auto;
|
||||||
|
|
||||||
|
.history-file-tree-item > ul,
|
||||||
|
ul[role='tree'] {
|
||||||
|
margin-left: var(--spacing-08);
|
||||||
|
}
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
min-height: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
line-height: var(--file-tree-line-height);
|
||||||
|
position: relative;
|
||||||
|
margin-left: var(--spacing-04);
|
||||||
|
|
||||||
|
.history-file-tree-item {
|
||||||
|
color: var(--file-tree-item-color);
|
||||||
|
cursor: pointer;
|
||||||
|
white-space: nowrap;
|
||||||
|
user-select: none;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
@include fake-full-width-bg(transparent);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--file-tree-item-hover-bg);
|
||||||
|
|
||||||
|
// When the entity is a subfolder, the DOM element is "indented" via margin-left. This makes the
|
||||||
|
// element not fill the entire file-tree width (as it's spaced from the left-hand side via margin)
|
||||||
|
// and, in consequence, the background gets clipped. The ::before pseudo-selector is used to fill
|
||||||
|
// the empty space.
|
||||||
|
@include fake-full-width-bg(var(--file-tree-item-hover-bg));
|
||||||
|
}
|
||||||
|
|
||||||
|
.history-file-tree-folder-button {
|
||||||
|
padding: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
background: transparent;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.history-file-tree-item-name-wrapper {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.history-file-tree-item-name {
|
||||||
|
margin-right: var(--spacing-02);
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
flex-grow: 1;
|
||||||
|
white-space: pre;
|
||||||
|
|
||||||
|
&.strikethrough {
|
||||||
|
text-decoration: line-through;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.history-file-tree-item-badge {
|
||||||
|
text-transform: capitalize;
|
||||||
|
font-weight: normal;
|
||||||
|
margin-right: var(--spacing-05);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--neutral-20) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.material-symbols {
|
||||||
|
color: var(--content-disabled);
|
||||||
|
|
||||||
|
&.file-tree-icon {
|
||||||
|
margin-right: var(--spacing-02);
|
||||||
|
margin-left: var(--spacing-04);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.file-tree-folder-icon {
|
||||||
|
margin-right: var(--spacing-02);
|
||||||
|
vertical-align: sub;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.file-tree-expand-icon {
|
||||||
|
margin-left: var(--spacing-04);
|
||||||
|
vertical-align: sub;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
li.selected > .history-file-tree-item {
|
||||||
|
color: var(--file-tree-item-selected-color);
|
||||||
|
background-color: var(--file-tree-item-selected-bg);
|
||||||
|
font-weight: bold;
|
||||||
|
|
||||||
|
> div > .material-symbols,
|
||||||
|
> button > .material-symbols,
|
||||||
|
> .material-symbols,
|
||||||
|
.material-symbols {
|
||||||
|
color: var(--file-tree-item-selected-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
@include fake-full-width-bg(var(--file-tree-item-selected-bg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.history-error {
|
||||||
|
padding: var(--spacing-06);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue