mirror of
https://github.com/ragestudio/comty.git
synced 2025-06-09 10:34:17 +00:00
rework navmenu to use header
This commit is contained in:
parent
846114cbbf
commit
874a755dc3
@ -1,27 +1,52 @@
|
||||
import React from "react"
|
||||
import classnames from "classnames"
|
||||
import { Motion, spring } from "react-motion"
|
||||
|
||||
import useLayoutInterface from "hooks/useLayoutInterface"
|
||||
|
||||
import "./index.less"
|
||||
|
||||
export default (props) => {
|
||||
const [visible, setVisible] = React.useState(false)
|
||||
const [render, setRender] = React.useState(null)
|
||||
|
||||
const headerInterface = {
|
||||
toggle: (to) => setVisible((prevValue) => to ?? !prevValue),
|
||||
}
|
||||
|
||||
React.useEffect(() => {
|
||||
app.layout.header = headerInterface
|
||||
}, [])
|
||||
|
||||
return <div
|
||||
className={classnames(
|
||||
"page_header",
|
||||
{
|
||||
["visible"]: visible,
|
||||
useLayoutInterface("header", {
|
||||
render: (component, options) => {
|
||||
if (component === null) {
|
||||
return setRender(null)
|
||||
}
|
||||
)}
|
||||
|
||||
return setRender({
|
||||
component,
|
||||
options
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
return <Motion
|
||||
style={{
|
||||
y: spring(render ? 0 : 100,),
|
||||
}}
|
||||
>
|
||||
{String(window.location.pathname).toTitleCase()}
|
||||
</div>
|
||||
{({ y, height }) => {
|
||||
return <div
|
||||
className={classnames(
|
||||
"page_header_wrapper",
|
||||
{
|
||||
["hidden"]: !render,
|
||||
}
|
||||
)}
|
||||
style={{
|
||||
WebkitTransform: `translateY(-${y}px)`,
|
||||
transform: `translateY(-${y}px)`,
|
||||
}}
|
||||
>
|
||||
{
|
||||
render?.component && React.cloneElement(
|
||||
render?.component,
|
||||
render?.options?.props ?? {}
|
||||
)
|
||||
}
|
||||
</div>
|
||||
}}
|
||||
</Motion>
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
.page_header {
|
||||
.page_header_wrapper {
|
||||
position: sticky;
|
||||
|
||||
z-index: 100;
|
||||
@ -6,26 +6,24 @@
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
|
||||
overflow: hidden;
|
||||
|
||||
// hidden values
|
||||
padding: 0;
|
||||
opacity: 0;
|
||||
height: 0px;
|
||||
width: 100%;
|
||||
|
||||
transition: all 150ms ease-in-out;
|
||||
margin-bottom: 20px;
|
||||
padding: 5px;
|
||||
|
||||
backdrop-filter: blur(10px);
|
||||
|
||||
&.visible {
|
||||
opacity: 1;
|
||||
height: 50px;
|
||||
padding: 20px;
|
||||
background-color: rgba(var(--background-color-accent-values), 0.8);
|
||||
|
||||
border-radius: 12px;
|
||||
border: 1px solid var(--border-color);
|
||||
|
||||
overflow: hidden;
|
||||
|
||||
&.hidden {
|
||||
opacity: 0;
|
||||
height: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
@ -4,30 +4,8 @@ import * as antd from "antd"
|
||||
|
||||
import "./index.less"
|
||||
|
||||
const NavMenu = (props) => {
|
||||
const handleOnClickItem = (event) => {
|
||||
return props.onClickItem(event.key)
|
||||
}
|
||||
|
||||
return <div className="navmenu_wrapper">
|
||||
<div className="card">
|
||||
{
|
||||
props.header && <div className="card_header">
|
||||
{props.header}
|
||||
</div>
|
||||
}
|
||||
|
||||
<antd.Menu
|
||||
mode="inline"
|
||||
selectedKeys={[props.activeKey]}
|
||||
onClick={handleOnClickItem}
|
||||
items={props.items}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
const NavMenuMobile = (props) => {
|
||||
export default (props) => {
|
||||
function handleClickItem(item) {
|
||||
if (item.children && Array.isArray(item.children)) {
|
||||
return false
|
||||
@ -38,7 +16,7 @@ const NavMenuMobile = (props) => {
|
||||
|
||||
return <div
|
||||
className={classnames(
|
||||
"__mobile__navmenu_wrapper",
|
||||
"navmenu_wrapper",
|
||||
)}
|
||||
>
|
||||
{
|
||||
@ -56,7 +34,7 @@ const NavMenuMobile = (props) => {
|
||||
<antd.Button
|
||||
key={item.key}
|
||||
className={classnames(
|
||||
"__mobile__navmenu_item",
|
||||
"navmenu_item",
|
||||
item.key === props.activeKey && "active",
|
||||
)}
|
||||
type="ghost"
|
||||
@ -65,6 +43,14 @@ const NavMenuMobile = (props) => {
|
||||
<div className="icon">
|
||||
{item.icon}
|
||||
</div>
|
||||
|
||||
{
|
||||
props.renderNames && <div className="label">
|
||||
<p>
|
||||
{item.label ?? item.id}
|
||||
</p>
|
||||
</div>
|
||||
}
|
||||
</antd.Button>
|
||||
</antd.Dropdown>
|
||||
}
|
||||
@ -72,7 +58,7 @@ const NavMenuMobile = (props) => {
|
||||
return <antd.Button
|
||||
key={item.key}
|
||||
className={classnames(
|
||||
"__mobile__navmenu_item",
|
||||
"navmenu_item",
|
||||
item.key === props.activeKey && "active",
|
||||
)}
|
||||
onClick={() => handleClickItem(item)}
|
||||
@ -82,10 +68,16 @@ const NavMenuMobile = (props) => {
|
||||
<div className="icon">
|
||||
{item.icon}
|
||||
</div>
|
||||
|
||||
{
|
||||
props.renderNames && <div className="label">
|
||||
<p>
|
||||
{item.label ?? item.id}
|
||||
</p>
|
||||
</div>
|
||||
}
|
||||
</antd.Button>
|
||||
})
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
export default app.isMobile ? NavMenuMobile : NavMenu
|
||||
}
|
@ -1,64 +1,6 @@
|
||||
@import "theme/vars.less";
|
||||
|
||||
.navmenu_wrapper {
|
||||
position: relative;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
||||
.card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
background-color: var(--background-color-accent);
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
|
||||
width: 100%;
|
||||
|
||||
h1,
|
||||
h2 {
|
||||
width: fit-content;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.card_header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
margin-bottom: 10px;
|
||||
|
||||
view-transition-name: main-header;
|
||||
|
||||
h1 {
|
||||
view-transition-name: main-header-text;
|
||||
}
|
||||
}
|
||||
|
||||
&.content {
|
||||
position: relative;
|
||||
|
||||
transform: translateY(-30px);
|
||||
padding-top: 35px;
|
||||
|
||||
z-index: 45;
|
||||
}
|
||||
}
|
||||
|
||||
&.card:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.__mobile__navmenu_wrapper {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
@ -66,9 +8,10 @@
|
||||
|
||||
width: 100%;
|
||||
|
||||
.__mobile__navmenu_item {
|
||||
.navmenu_item {
|
||||
font-size: 0.7rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-direction: row;
|
||||
|
||||
align-items: center;
|
||||
|
||||
@ -82,10 +25,16 @@
|
||||
color: var(--colorPrimary);
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.icon {
|
||||
margin: 0;
|
||||
line-height: 1rem;
|
||||
font-size: 1.5rem;
|
||||
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.label {
|
||||
|
@ -72,6 +72,8 @@ export class PagePanelWithNavMenu extends React.Component {
|
||||
|
||||
if (app.isMobile) {
|
||||
app.layout.top_bar.shouldUseTopBarSpacer(true)
|
||||
} else {
|
||||
app.layout.header.render(null)
|
||||
}
|
||||
}
|
||||
|
||||
@ -119,7 +121,10 @@ export class PagePanelWithNavMenu extends React.Component {
|
||||
|
||||
const componentProps = tab.props ?? this.props.tabProps
|
||||
|
||||
return React.createElement(tab.component, componentProps)
|
||||
return React.createElement(tab.component, {
|
||||
...componentProps,
|
||||
ref: this.primaryPanelRef,
|
||||
})
|
||||
}
|
||||
|
||||
replaceQueryTypeToCurrentTab = () => {
|
||||
@ -186,16 +191,23 @@ export class PagePanelWithNavMenu extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const panels = [
|
||||
return <>
|
||||
{
|
||||
children: <>
|
||||
<NavMenu
|
||||
header={this.props.navMenuHeader}
|
||||
activeKey={this.state.activeTab}
|
||||
items={this.getItems(this.props.tabs)}
|
||||
onClickItem={(key) => this.handleTabChange(key)}
|
||||
/>
|
||||
app.isMobile && app.layout.top_bar.render(<NavMenu
|
||||
activeKey={this.state.activeTab}
|
||||
items={this.getItems(this.props.tabs)}
|
||||
onClickItem={(key) => this.handleTabChange(key)}
|
||||
/>)
|
||||
}
|
||||
|
||||
{
|
||||
!app.isMobile && app.layout.header.render(<NavMenu
|
||||
header={this.props.navMenuHeader}
|
||||
activeKey={this.state.activeTab}
|
||||
items={this.getItems(this.props.tabs)}
|
||||
onClickItem={(key) => this.handleTabChange(key)}
|
||||
renderNames
|
||||
>
|
||||
{
|
||||
Array.isArray(this.state.renders) && [
|
||||
this.state.renders.map((render, index) => {
|
||||
@ -206,98 +218,14 @@ export class PagePanelWithNavMenu extends React.Component {
|
||||
})
|
||||
]
|
||||
}
|
||||
</>
|
||||
},
|
||||
{
|
||||
props: {
|
||||
ref: this.primaryPanelRef,
|
||||
className: this.props.transition ? "fade-opacity-enter" : undefined,
|
||||
},
|
||||
children: this.renderActiveTab()
|
||||
},
|
||||
]
|
||||
|
||||
if (app.isMobile) {
|
||||
delete panels[0]
|
||||
}
|
||||
|
||||
if (this.props.extraPanel) {
|
||||
panels.push(this.props.extraPanel)
|
||||
}
|
||||
|
||||
return <>
|
||||
{
|
||||
app.isMobile && app.layout.top_bar.render(<NavMenu
|
||||
activeKey={this.state.activeTab}
|
||||
items={this.getItems(this.props.tabs)}
|
||||
onClickItem={(key) => this.handleTabChange(key)}
|
||||
/>)
|
||||
</NavMenu>)
|
||||
}
|
||||
|
||||
{
|
||||
this.renderActiveTab()
|
||||
}
|
||||
<PagePanels
|
||||
primaryPanelClassName={this.props.primaryPanelClassName}
|
||||
panels={panels}
|
||||
masked={this.props.masked}
|
||||
no_top_padding={this.props.no_top_padding}
|
||||
/>
|
||||
</>
|
||||
}
|
||||
}
|
||||
|
||||
export default class PagePanels extends React.Component {
|
||||
generateGridStyle = () => {
|
||||
switch (this.props.panels.length) {
|
||||
case 1: {
|
||||
return {
|
||||
gridTemplateColumns: "1fr",
|
||||
}
|
||||
}
|
||||
case 2: {
|
||||
return {
|
||||
gridTemplateColumns: "1fr 3fr",
|
||||
}
|
||||
}
|
||||
case 3: {
|
||||
return {
|
||||
gridTemplateColumns: "0.5fr 1fr 0.5fr",
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
if (!this.props.panels) {
|
||||
return null
|
||||
}
|
||||
|
||||
return <div
|
||||
className={classnames(
|
||||
"pagePanels",
|
||||
{
|
||||
["masked"]: this.props.masked,
|
||||
["withTopPadding"]: !!!this.props.no_top_padding
|
||||
}
|
||||
)}
|
||||
style={this.generateGridStyle()}
|
||||
>
|
||||
{
|
||||
this.props.panels[0] && <Panel
|
||||
{...this.props.panels[0]}
|
||||
align="left"
|
||||
/>
|
||||
}
|
||||
{
|
||||
this.props.panels[1] && <Panel
|
||||
{...this.props.panels[1]}
|
||||
className={this.props.primaryPanelClassName}
|
||||
align="center"
|
||||
/>
|
||||
}
|
||||
{
|
||||
this.props.panels[2] && <Panel
|
||||
{...this.props.panels[2]}
|
||||
align="right"
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
}
|
||||
export default PagePanelWithNavMenu
|
@ -53,12 +53,8 @@ html {
|
||||
}
|
||||
|
||||
.pagePanels {
|
||||
display: grid;
|
||||
|
||||
grid-template-columns: 1fr 3fr;
|
||||
grid-template-rows: 1fr;
|
||||
grid-column-gap: 20px;
|
||||
grid-row-gap: 0px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
width: 100%;
|
||||
|
||||
|
@ -2,7 +2,15 @@ import React from "react"
|
||||
import classnames from "classnames"
|
||||
import { Layout } from "antd"
|
||||
|
||||
import { Sidebar, Drawer, Sidedrawer, BottomBar, TopBar, ToolsBar } from "components/Layout"
|
||||
import {
|
||||
Sidebar,
|
||||
Drawer,
|
||||
Sidedrawer,
|
||||
BottomBar,
|
||||
TopBar,
|
||||
ToolsBar,
|
||||
Header,
|
||||
} from "components/Layout"
|
||||
|
||||
import BackgroundDecorator from "components/BackgroundDecorator"
|
||||
|
||||
@ -27,6 +35,7 @@ const DesktopLayout = (props) => {
|
||||
<Drawer />
|
||||
<Sidebar />
|
||||
<Sidedrawer />
|
||||
|
||||
<Layout.Content
|
||||
id="content_layout"
|
||||
className={classnames(
|
||||
@ -35,6 +44,8 @@ const DesktopLayout = (props) => {
|
||||
"fade-transverse-active",
|
||||
)}
|
||||
>
|
||||
<Header />
|
||||
|
||||
{
|
||||
props.children && React.cloneElement(props.children, props)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user