mirror of
https://github.com/ragestudio/comty.git
synced 2025-06-09 18:44:16 +00:00
rework navmenu to use header
This commit is contained in:
parent
5d4809e574
commit
f207ebb037
@ -1,27 +1,52 @@
|
|||||||
import React from "react"
|
import React from "react"
|
||||||
import classnames from "classnames"
|
import classnames from "classnames"
|
||||||
|
import { Motion, spring } from "react-motion"
|
||||||
|
|
||||||
|
import useLayoutInterface from "hooks/useLayoutInterface"
|
||||||
|
|
||||||
import "./index.less"
|
import "./index.less"
|
||||||
|
|
||||||
export default (props) => {
|
export default (props) => {
|
||||||
const [visible, setVisible] = React.useState(false)
|
const [render, setRender] = React.useState(null)
|
||||||
|
|
||||||
const headerInterface = {
|
useLayoutInterface("header", {
|
||||||
toggle: (to) => setVisible((prevValue) => to ?? !prevValue),
|
render: (component, options) => {
|
||||||
}
|
if (component === null) {
|
||||||
|
return setRender(null)
|
||||||
React.useEffect(() => {
|
|
||||||
app.layout.header = headerInterface
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
return <div
|
|
||||||
className={classnames(
|
|
||||||
"page_header",
|
|
||||||
{
|
|
||||||
["visible"]: visible,
|
|
||||||
}
|
}
|
||||||
)}
|
|
||||||
|
return setRender({
|
||||||
|
component,
|
||||||
|
options
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return <Motion
|
||||||
|
style={{
|
||||||
|
y: spring(render ? 0 : 100,),
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{String(window.location.pathname).toTitleCase()}
|
{({ y, height }) => {
|
||||||
</div>
|
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;
|
position: sticky;
|
||||||
|
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
@ -6,26 +6,24 @@
|
|||||||
top: 0;
|
top: 0;
|
||||||
left: 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%;
|
width: 100%;
|
||||||
|
|
||||||
transition: all 150ms ease-in-out;
|
margin-bottom: 20px;
|
||||||
|
padding: 5px;
|
||||||
|
|
||||||
backdrop-filter: blur(10px);
|
backdrop-filter: blur(10px);
|
||||||
|
|
||||||
&.visible {
|
background-color: rgba(var(--background-color-accent-values), 0.8);
|
||||||
opacity: 1;
|
|
||||||
height: 50px;
|
border-radius: 12px;
|
||||||
padding: 20px;
|
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"
|
import "./index.less"
|
||||||
|
|
||||||
const NavMenu = (props) => {
|
|
||||||
const handleOnClickItem = (event) => {
|
|
||||||
return props.onClickItem(event.key)
|
|
||||||
}
|
|
||||||
|
|
||||||
return <div className="navmenu_wrapper">
|
export default (props) => {
|
||||||
<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) => {
|
|
||||||
function handleClickItem(item) {
|
function handleClickItem(item) {
|
||||||
if (item.children && Array.isArray(item.children)) {
|
if (item.children && Array.isArray(item.children)) {
|
||||||
return false
|
return false
|
||||||
@ -38,7 +16,7 @@ const NavMenuMobile = (props) => {
|
|||||||
|
|
||||||
return <div
|
return <div
|
||||||
className={classnames(
|
className={classnames(
|
||||||
"__mobile__navmenu_wrapper",
|
"navmenu_wrapper",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
@ -56,7 +34,7 @@ const NavMenuMobile = (props) => {
|
|||||||
<antd.Button
|
<antd.Button
|
||||||
key={item.key}
|
key={item.key}
|
||||||
className={classnames(
|
className={classnames(
|
||||||
"__mobile__navmenu_item",
|
"navmenu_item",
|
||||||
item.key === props.activeKey && "active",
|
item.key === props.activeKey && "active",
|
||||||
)}
|
)}
|
||||||
type="ghost"
|
type="ghost"
|
||||||
@ -65,6 +43,14 @@ const NavMenuMobile = (props) => {
|
|||||||
<div className="icon">
|
<div className="icon">
|
||||||
{item.icon}
|
{item.icon}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{
|
||||||
|
props.renderNames && <div className="label">
|
||||||
|
<p>
|
||||||
|
{item.label ?? item.id}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
</antd.Button>
|
</antd.Button>
|
||||||
</antd.Dropdown>
|
</antd.Dropdown>
|
||||||
}
|
}
|
||||||
@ -72,7 +58,7 @@ const NavMenuMobile = (props) => {
|
|||||||
return <antd.Button
|
return <antd.Button
|
||||||
key={item.key}
|
key={item.key}
|
||||||
className={classnames(
|
className={classnames(
|
||||||
"__mobile__navmenu_item",
|
"navmenu_item",
|
||||||
item.key === props.activeKey && "active",
|
item.key === props.activeKey && "active",
|
||||||
)}
|
)}
|
||||||
onClick={() => handleClickItem(item)}
|
onClick={() => handleClickItem(item)}
|
||||||
@ -82,10 +68,16 @@ const NavMenuMobile = (props) => {
|
|||||||
<div className="icon">
|
<div className="icon">
|
||||||
{item.icon}
|
{item.icon}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{
|
||||||
|
props.renderNames && <div className="label">
|
||||||
|
<p>
|
||||||
|
{item.label ?? item.id}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
</antd.Button>
|
</antd.Button>
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
export default app.isMobile ? NavMenuMobile : NavMenu
|
|
@ -1,64 +1,6 @@
|
|||||||
@import "theme/vars.less";
|
@import "theme/vars.less";
|
||||||
|
|
||||||
.navmenu_wrapper {
|
.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;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
|
||||||
@ -66,9 +8,10 @@
|
|||||||
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
.__mobile__navmenu_item {
|
.navmenu_item {
|
||||||
|
font-size: 0.7rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: row;
|
||||||
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
@ -82,10 +25,16 @@
|
|||||||
color: var(--colorPrimary);
|
color: var(--colorPrimary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
line-height: 1rem;
|
line-height: 1rem;
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
|
|
||||||
|
font-size: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.label {
|
.label {
|
||||||
|
@ -72,6 +72,8 @@ export class PagePanelWithNavMenu extends React.Component {
|
|||||||
|
|
||||||
if (app.isMobile) {
|
if (app.isMobile) {
|
||||||
app.layout.top_bar.shouldUseTopBarSpacer(true)
|
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
|
const componentProps = tab.props ?? this.props.tabProps
|
||||||
|
|
||||||
return React.createElement(tab.component, componentProps)
|
return React.createElement(tab.component, {
|
||||||
|
...componentProps,
|
||||||
|
ref: this.primaryPanelRef,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
replaceQueryTypeToCurrentTab = () => {
|
replaceQueryTypeToCurrentTab = () => {
|
||||||
@ -186,16 +191,23 @@ export class PagePanelWithNavMenu extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const panels = [
|
return <>
|
||||||
{
|
{
|
||||||
children: <>
|
app.isMobile && app.layout.top_bar.render(<NavMenu
|
||||||
<NavMenu
|
activeKey={this.state.activeTab}
|
||||||
header={this.props.navMenuHeader}
|
items={this.getItems(this.props.tabs)}
|
||||||
activeKey={this.state.activeTab}
|
onClickItem={(key) => this.handleTabChange(key)}
|
||||||
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) && [
|
Array.isArray(this.state.renders) && [
|
||||||
this.state.renders.map((render, index) => {
|
this.state.renders.map((render, index) => {
|
||||||
@ -206,98 +218,14 @@ export class PagePanelWithNavMenu extends React.Component {
|
|||||||
})
|
})
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
</>
|
</NavMenu>)
|
||||||
},
|
}
|
||||||
{
|
|
||||||
props: {
|
{
|
||||||
ref: this.primaryPanelRef,
|
this.renderActiveTab()
|
||||||
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)}
|
|
||||||
/>)
|
|
||||||
}
|
}
|
||||||
<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 {
|
export default PagePanelWithNavMenu
|
||||||
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>
|
|
||||||
}
|
|
||||||
}
|
|
@ -53,12 +53,8 @@ html {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.pagePanels {
|
.pagePanels {
|
||||||
display: grid;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
grid-template-columns: 1fr 3fr;
|
|
||||||
grid-template-rows: 1fr;
|
|
||||||
grid-column-gap: 20px;
|
|
||||||
grid-row-gap: 0px;
|
|
||||||
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
|
@ -2,7 +2,15 @@ import React from "react"
|
|||||||
import classnames from "classnames"
|
import classnames from "classnames"
|
||||||
import { Layout } from "antd"
|
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"
|
import BackgroundDecorator from "components/BackgroundDecorator"
|
||||||
|
|
||||||
@ -27,6 +35,7 @@ const DesktopLayout = (props) => {
|
|||||||
<Drawer />
|
<Drawer />
|
||||||
<Sidebar />
|
<Sidebar />
|
||||||
<Sidedrawer />
|
<Sidedrawer />
|
||||||
|
|
||||||
<Layout.Content
|
<Layout.Content
|
||||||
id="content_layout"
|
id="content_layout"
|
||||||
className={classnames(
|
className={classnames(
|
||||||
@ -35,6 +44,8 @@ const DesktopLayout = (props) => {
|
|||||||
"fade-transverse-active",
|
"fade-transverse-active",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
<Header />
|
||||||
|
|
||||||
{
|
{
|
||||||
props.children && React.cloneElement(props.children, props)
|
props.children && React.cloneElement(props.children, props)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user