mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-11-13 21:53:43 +01:00
Merge pull request #22787 from overleaf/mj-ide-rail
[web] Create rail tabbed layout GitOrigin-RevId: be54a224087aad8e6e2762d9c26463e37aecd9aa
This commit is contained in:
committed by
Copybot
parent
539e96c62b
commit
849275c4b8
@@ -3,15 +3,13 @@ import classNames from 'classnames'
|
||||
import { HorizontalResizeHandle } from '@/features/ide-react/components/resize/horizontal-resize-handle'
|
||||
import PdfPreview from '@/features/pdf-preview/components/pdf-preview'
|
||||
import { Editor } from './editor'
|
||||
import { RailLayout } from './rail'
|
||||
|
||||
export default function MainLayout() {
|
||||
return (
|
||||
<div className="ide-redesign-main">
|
||||
<div className="ide-skeleton-block">Toolbar</div>
|
||||
<div className="ide-redesign-body">
|
||||
<div className="ide-skeleton-block ide-redesign-full-height">
|
||||
Left menu
|
||||
</div>
|
||||
<PanelGroup
|
||||
autoSaveId="ide-redesign-outer-layout"
|
||||
direction="horizontal"
|
||||
@@ -19,17 +17,7 @@ export default function MainLayout() {
|
||||
'ide-panel-group-resizing': false,
|
||||
})}
|
||||
>
|
||||
<Panel
|
||||
id="ide-redesign-sidebar-panel"
|
||||
order={1}
|
||||
defaultSize={15}
|
||||
minSize={5}
|
||||
maxSize={80}
|
||||
>
|
||||
<div className="ide-skeleton-block ide-redesign-full-height">
|
||||
Side bar
|
||||
</div>
|
||||
</Panel>
|
||||
<RailLayout />
|
||||
<HorizontalResizeHandle
|
||||
resizable
|
||||
hitAreaMargins={{ coarse: 0, fine: 0 }}
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
import { ReactElement, useCallback, useState } from 'react'
|
||||
import { Nav, NavLink, Tab, TabContainer } from 'react-bootstrap-5'
|
||||
import MaterialIcon, {
|
||||
AvailableUnfilledIcon,
|
||||
} from '@/shared/components/material-icon'
|
||||
import { Panel } from 'react-resizable-panels'
|
||||
|
||||
type RailElement = {
|
||||
icon: AvailableUnfilledIcon
|
||||
key: string
|
||||
component: ReactElement
|
||||
}
|
||||
|
||||
const RAIL_TABS: RailElement[] = [
|
||||
// NOTE: The file tree **MUST** be the first (i.e. default) tab in the list
|
||||
// since the file tree is responsible for opening the initial document.
|
||||
{
|
||||
key: 'file-tree',
|
||||
icon: 'description',
|
||||
component: <>File tree</>,
|
||||
},
|
||||
{
|
||||
key: 'integrations',
|
||||
icon: 'integration_instructions',
|
||||
component: <>Integrations</>,
|
||||
},
|
||||
{
|
||||
key: 'review-panel',
|
||||
icon: 'rate_review',
|
||||
component: <>Review panel</>,
|
||||
},
|
||||
{
|
||||
key: 'chat',
|
||||
icon: 'forum',
|
||||
component: <>Chat</>,
|
||||
},
|
||||
{
|
||||
key: 'errors',
|
||||
icon: 'report',
|
||||
component: <>Errors</>,
|
||||
},
|
||||
]
|
||||
|
||||
export const RailLayout = () => {
|
||||
const [selectedTab, setSelectedTab] = useState<string | undefined>(
|
||||
RAIL_TABS[0]?.key
|
||||
)
|
||||
return (
|
||||
<TabContainer
|
||||
mountOnEnter // Only render when necessary (so that we can lazy load tab content)
|
||||
unmountOnExit={false} // TODO: Should we unmount the tabs when they're not used?
|
||||
transition={false}
|
||||
defaultActiveKey={selectedTab}
|
||||
onSelect={useCallback(key => setSelectedTab(key ?? undefined), [])}
|
||||
id="ide-rail-tabs"
|
||||
>
|
||||
<div className="ide-rail">
|
||||
<Nav defaultActiveKey={RAIL_TABS[0]?.key} className="flex-column">
|
||||
{RAIL_TABS.map(({ icon, key }) => (
|
||||
<RailTab
|
||||
active={selectedTab === key}
|
||||
key={key}
|
||||
eventKey={key}
|
||||
icon={icon}
|
||||
/>
|
||||
))}
|
||||
</Nav>
|
||||
</div>
|
||||
<Panel
|
||||
id="ide-redesign-sidebar-panel"
|
||||
order={1}
|
||||
defaultSize={15}
|
||||
minSize={5}
|
||||
maxSize={80}
|
||||
>
|
||||
<div className="ide-rail-content">
|
||||
<Tab.Content>
|
||||
{RAIL_TABS.map(({ key, component }) => (
|
||||
<Tab.Pane eventKey={key} key={key}>
|
||||
{component}
|
||||
</Tab.Pane>
|
||||
))}
|
||||
</Tab.Content>
|
||||
</div>
|
||||
</Panel>
|
||||
</TabContainer>
|
||||
)
|
||||
}
|
||||
|
||||
const RailTab = ({
|
||||
icon,
|
||||
eventKey,
|
||||
active,
|
||||
}: {
|
||||
icon: AvailableUnfilledIcon
|
||||
eventKey: string
|
||||
active: boolean
|
||||
}) => {
|
||||
return (
|
||||
<NavLink eventKey={eventKey} className="ide-rail-tab-link">
|
||||
<MaterialIcon
|
||||
className="ide-rail-tab-link-icon"
|
||||
type={icon}
|
||||
unfilled={!active}
|
||||
/>
|
||||
</NavLink>
|
||||
)
|
||||
}
|
||||
@@ -7,6 +7,7 @@
|
||||
@import 'sidebar-v2-dash-pane';
|
||||
@import 'editor/ide';
|
||||
@import 'editor/ide-redesign';
|
||||
@import 'editor/rail';
|
||||
@import 'editor/toolbar';
|
||||
@import 'editor/online-users';
|
||||
@import 'editor/hotkeys';
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
:root {
|
||||
--ide-rail-background: #fff;
|
||||
--ide-rail-color: var(--neutral-90);
|
||||
--ide-rail-link-background: #fff;
|
||||
--ide-rail-link-active-background: var(--neutral-10);
|
||||
--ide-rail-link-active-indicator-background: var(--neutral-90);
|
||||
}
|
||||
|
||||
.ide-rail-tab-link {
|
||||
border-radius: 12px;
|
||||
display: block;
|
||||
height: 48px;
|
||||
width: 48px;
|
||||
text-align: center;
|
||||
padding: 0;
|
||||
color: var(--ide-rail-color);
|
||||
background-color: var(--ide-rail-link-background);
|
||||
position: relative;
|
||||
overflow-y: hidden;
|
||||
|
||||
.ide-rail-tab-link-icon {
|
||||
line-height: 48px;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
&.active {
|
||||
color: var(--ide-rail-color);
|
||||
background-color: var(--ide-rail-link-active-background);
|
||||
|
||||
&::after {
|
||||
$indicator-height: 3px;
|
||||
|
||||
border-radius: 12px;
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: -$indicator-height;
|
||||
left: 25%;
|
||||
box-sizing: border-box;
|
||||
width: 50%;
|
||||
height: $indicator-height * 2;
|
||||
border: $indicator-height solid
|
||||
var(--ide-rail-link-active-indicator-background);
|
||||
background-color: var(--ide-rail-link-active-indicator-background);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ide-rail {
|
||||
height: 100%;
|
||||
padding: var(--spacing-02);
|
||||
background: var(--ide-rail-background);
|
||||
}
|
||||
|
||||
.ide-rail-content {
|
||||
height: 100%;
|
||||
border: 1px solid var(--border-divider);
|
||||
}
|
||||
Reference in New Issue
Block a user