mirror of
https://github.com/ragestudio/comty.git
synced 2025-06-10 02:54:15 +00:00
commit
ea355e0613
@ -1,59 +1,99 @@
|
|||||||
import React from "react"
|
import React from "react"
|
||||||
import { Layout, Menu, Avatar } from "antd"
|
import { Menu, Avatar } from "antd"
|
||||||
|
import { Translation } from "react-i18next"
|
||||||
import classnames from "classnames"
|
import classnames from "classnames"
|
||||||
|
|
||||||
import config from "config"
|
import config from "config"
|
||||||
import { Icons, createIconRender } from "components/Icons"
|
import { Icons, createIconRender } from "components/Icons"
|
||||||
import { sidebarKeys as defaultSidebarItems } from "schemas/defaultSettings"
|
import { sidebarKeys as defaultSidebarItems } from "schemas/defaultSettings"
|
||||||
|
|
||||||
import sidebarItems from "schemas/routes.json"
|
import sidebarItems from "schemas/routes.json"
|
||||||
import { Translation } from "react-i18next"
|
|
||||||
|
|
||||||
import { SidebarEditor } from "./components"
|
|
||||||
import "./index.less"
|
import "./index.less"
|
||||||
|
|
||||||
const { Sider } = Layout
|
|
||||||
|
|
||||||
const onClickHandlers = {
|
const onClickHandlers = {
|
||||||
settings: (event) => {
|
settings: (event) => {
|
||||||
window.app.openSettings()
|
window.app.openSettings()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getSidebarComponents = () => {
|
||||||
|
const items = {}
|
||||||
|
|
||||||
|
sidebarItems.forEach((item, index) => {
|
||||||
|
items[item.id] = {
|
||||||
|
...item,
|
||||||
|
index,
|
||||||
|
content: (
|
||||||
|
<>
|
||||||
|
{createIconRender(item.icon)} {item.title}
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return items
|
||||||
|
}
|
||||||
|
|
||||||
|
const generateItems = () => {
|
||||||
|
const components = getSidebarComponents()
|
||||||
|
const itemsMap = []
|
||||||
|
const pathResolvers = {}
|
||||||
|
|
||||||
|
const keys = window.app?.settings.get("sidebarKeys") ?? defaultSidebarItems
|
||||||
|
|
||||||
|
// filter undefined components to avoid error
|
||||||
|
keys.filter((key) => {
|
||||||
|
if (typeof components[key] !== "undefined") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
keys.forEach((key, index) => {
|
||||||
|
const component = components[key]
|
||||||
|
|
||||||
|
try {
|
||||||
|
// avoid if item is duplicated
|
||||||
|
if (itemsMap.includes(component)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof component.path !== "undefined") {
|
||||||
|
pathResolvers[component.id] = component.path
|
||||||
|
}
|
||||||
|
|
||||||
|
itemsMap.push(component)
|
||||||
|
} catch (error) {
|
||||||
|
return console.log(error)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
itemsMap,
|
||||||
|
pathResolvers,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default class Sidebar extends React.Component {
|
export default class Sidebar extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props)
|
super(props)
|
||||||
|
|
||||||
this.controller = window.app["SidebarController"] = {
|
this.controller = window.app["SidebarController"] = {
|
||||||
toggleVisibility: this.toggleVisibility,
|
toggleVisibility: this.toggleVisibility,
|
||||||
toggleEdit: this.toggleEditMode,
|
|
||||||
toggleElevation: this.toggleElevation,
|
toggleElevation: this.toggleElevation,
|
||||||
attachElement: this.attachElement,
|
toggleCollapse: this.toggleCollapse,
|
||||||
isVisible: () => this.state.visible,
|
isVisible: () => this.state.visible,
|
||||||
isEditMode: () => this.state.visible,
|
|
||||||
isCollapsed: () => this.state.collapsed,
|
isCollapsed: () => this.state.collapsed,
|
||||||
}
|
}
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
editMode: false,
|
|
||||||
visible: false,
|
visible: false,
|
||||||
loading: true,
|
|
||||||
collapsed: window.app.settings.get("collapseOnLooseFocus") ?? false,
|
|
||||||
pathResolve: {},
|
|
||||||
menus: {},
|
|
||||||
extraItems: {
|
|
||||||
bottom: [],
|
|
||||||
top: [],
|
|
||||||
},
|
|
||||||
elevated: false,
|
elevated: false,
|
||||||
additionalElements: [],
|
collapsed: window.app.settings.get("collapseOnLooseFocus") ?? false,
|
||||||
|
pathResolvers: null,
|
||||||
|
menus: null,
|
||||||
}
|
}
|
||||||
|
|
||||||
window.app.eventBus.on("edit_sidebar", () => this.toggleEditMode())
|
|
||||||
|
|
||||||
window.app.eventBus.on("settingChanged.sidebar_collapse", (value) => {
|
|
||||||
this.toggleCollapse(value)
|
|
||||||
})
|
|
||||||
|
|
||||||
// handle sidedrawer open/close
|
// handle sidedrawer open/close
|
||||||
window.app.eventBus.on("sidedrawer.hasDrawers", () => {
|
window.app.eventBus.on("sidedrawer.hasDrawers", () => {
|
||||||
this.toggleElevation(true)
|
this.toggleElevation(true)
|
||||||
@ -66,112 +106,21 @@ export default class Sidebar extends React.Component {
|
|||||||
collapseDebounce = null
|
collapseDebounce = null
|
||||||
|
|
||||||
componentDidMount = async () => {
|
componentDidMount = async () => {
|
||||||
await this.loadSidebarItems()
|
await this.loadItems()
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.controller.toggleVisibility(true)
|
this.controller.toggleVisibility(true)
|
||||||
}, 100)
|
}, 100)
|
||||||
}
|
}
|
||||||
|
|
||||||
getStoragedKeys = () => {
|
loadItems = async () => {
|
||||||
return window.app.settings.get("sidebarKeys")
|
const generation = generateItems()
|
||||||
}
|
|
||||||
|
|
||||||
attachElement = (element) => {
|
|
||||||
this.setState({
|
|
||||||
additionalElements: [...this.state.additionalElements, element],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
appendItem = (item = {}) => {
|
|
||||||
const { position } = item
|
|
||||||
|
|
||||||
if (typeof position === "undefined" && typeof this.state.extraItems[position] === "undefined") {
|
|
||||||
console.error("Invalid position")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
const state = this.state.extraItems
|
|
||||||
|
|
||||||
state[position].push(item)
|
|
||||||
|
|
||||||
this.setState({ extraItems: state })
|
|
||||||
}
|
|
||||||
|
|
||||||
loadSidebarItems = () => {
|
|
||||||
const items = {}
|
|
||||||
const itemsMap = []
|
|
||||||
|
|
||||||
// parse all items from schema
|
|
||||||
sidebarItems.forEach((item, index) => {
|
|
||||||
items[item.id] = {
|
|
||||||
...item,
|
|
||||||
index,
|
|
||||||
content: (
|
|
||||||
<>
|
|
||||||
{createIconRender(item.icon)} {item.title}
|
|
||||||
</>
|
|
||||||
),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// filter undefined to avoid error
|
|
||||||
let keys = (this.getStoragedKeys() ?? defaultSidebarItems).filter((key) => {
|
|
||||||
if (typeof items[key] !== "undefined") {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// short items
|
|
||||||
keys.forEach((id, index) => {
|
|
||||||
const item = items[id]
|
|
||||||
|
|
||||||
if (item.locked) {
|
|
||||||
if (item.index !== index) {
|
|
||||||
keys = keys.move(index, item.index)
|
|
||||||
|
|
||||||
//update index
|
|
||||||
window.app.settings.set("sidebarKeys", keys)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// set items from scoped keys
|
|
||||||
keys.forEach((key, index) => {
|
|
||||||
const item = items[key]
|
|
||||||
|
|
||||||
try {
|
|
||||||
// avoid if item is duplicated
|
|
||||||
if (itemsMap.includes(item)) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
let valid = true
|
|
||||||
|
|
||||||
if (typeof item.requireState === "object") {
|
|
||||||
const { key, value } = item.requireState
|
|
||||||
//* TODO: check global state
|
|
||||||
}
|
|
||||||
|
|
||||||
// end validation
|
|
||||||
if (!valid) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof item.path !== "undefined") {
|
|
||||||
let resolvers = this.state.pathResolve ?? {}
|
|
||||||
resolvers[item.id] = item.path
|
|
||||||
this.setState({ pathResolve: resolvers })
|
|
||||||
}
|
|
||||||
|
|
||||||
itemsMap.push(item)
|
|
||||||
} catch (error) {
|
|
||||||
return console.log(error)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// update states
|
// update states
|
||||||
this.setState({ items, menus: itemsMap, loading: false })
|
await this.setState({
|
||||||
|
menus: generation.itemsMap,
|
||||||
|
pathResolvers: generation.pathResolvers,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
renderMenuItems(items) {
|
renderMenuItems(items) {
|
||||||
@ -184,29 +133,25 @@ export default class Sidebar extends React.Component {
|
|||||||
|
|
||||||
return items.map((item) => {
|
return items.map((item) => {
|
||||||
if (Array.isArray(item.children)) {
|
if (Array.isArray(item.children)) {
|
||||||
return (
|
return <Menu.SubMenu
|
||||||
<Menu.SubMenu
|
key={item.id}
|
||||||
key={item.id}
|
icon={handleRenderIcon(item.icon)}
|
||||||
icon={handleRenderIcon(item.icon)}
|
title={<span>
|
||||||
title={<span>
|
<Translation>
|
||||||
<Translation>
|
{t => t(item.title)}
|
||||||
{t => t(item.title)}
|
</Translation>
|
||||||
</Translation>
|
</span>}
|
||||||
</span>}
|
{...item.props}
|
||||||
{...item.props}
|
>
|
||||||
>
|
{this.renderMenuItems(item.children)}
|
||||||
{this.renderMenuItems(item.children)}
|
</Menu.SubMenu>
|
||||||
</Menu.SubMenu>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return <Menu.Item key={item.id} icon={handleRenderIcon(item.icon)} {...item.props}>
|
||||||
<Menu.Item key={item.id} icon={handleRenderIcon(item.icon)} {...item.props}>
|
<Translation>
|
||||||
<Translation>
|
{t => t(item.title ?? item.id)}
|
||||||
{t => t(item.title ?? item.id)}
|
</Translation>
|
||||||
</Translation>
|
</Menu.Item>
|
||||||
</Menu.Item>
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,27 +168,14 @@ export default class Sidebar extends React.Component {
|
|||||||
if (typeof onClickHandlers[e.key] === "function") {
|
if (typeof onClickHandlers[e.key] === "function") {
|
||||||
return onClickHandlers[e.key](e)
|
return onClickHandlers[e.key](e)
|
||||||
}
|
}
|
||||||
if (typeof this.state.pathResolve[e.key] !== "undefined") {
|
|
||||||
return window.app.setLocation(`/${this.state.pathResolve[e.key]}`, 150)
|
|
||||||
}
|
|
||||||
|
|
||||||
return window.app.setLocation(`/${e.key}`, 150)
|
if (typeof this.state.pathResolvers === "object") {
|
||||||
}
|
if (typeof this.state.pathResolvers[e.key] !== "undefined") {
|
||||||
|
return window.app.setLocation(`/${this.state.pathResolvers[e.key]}`, 150)
|
||||||
toggleEditMode = (to) => {
|
|
||||||
if (typeof to === "undefined") {
|
|
||||||
to = !this.state.editMode
|
|
||||||
}
|
|
||||||
|
|
||||||
if (to) {
|
|
||||||
window.app.eventBus.emit("clearAllOverlays")
|
|
||||||
} else {
|
|
||||||
if (this.itemsMap !== this.getStoragedKeys()) {
|
|
||||||
this.loadSidebarItems()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState({ editMode: to, collapsed: false })
|
return window.app.setLocation(`/${e.key}`, 150)
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleCollapse = (to) => {
|
toggleCollapse = (to) => {
|
||||||
@ -261,11 +193,12 @@ export default class Sidebar extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onMouseEnter = () => {
|
onMouseEnter = () => {
|
||||||
if (window.app.settings.is("collapseOnLooseFocus", false)) {
|
if (!this.state.visible) return
|
||||||
return false
|
|
||||||
}
|
if (window.app.settings.is("collapseOnLooseFocus", false)) return
|
||||||
|
|
||||||
clearTimeout(this.collapseDebounce)
|
clearTimeout(this.collapseDebounce)
|
||||||
|
|
||||||
this.collapseDebounce = null
|
this.collapseDebounce = null
|
||||||
|
|
||||||
if (this.state.collapsed) {
|
if (this.state.collapsed) {
|
||||||
@ -274,49 +207,29 @@ export default class Sidebar extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleMouseLeave = () => {
|
handleMouseLeave = () => {
|
||||||
if (window.app.settings.is("collapseOnLooseFocus", false)) {
|
if (!this.state.visible) return
|
||||||
return false
|
|
||||||
}
|
if (window.app.settings.is("collapseOnLooseFocus", false)) return
|
||||||
|
|
||||||
if (!this.state.collapsed) {
|
if (!this.state.collapsed) {
|
||||||
this.collapseDebounce = setTimeout(() => { this.toggleCollapse(true) }, window.app.settings.get("autoCollapseDelay") ?? 500)
|
this.collapseDebounce = setTimeout(() => { this.toggleCollapse(true) }, window.app.settings.get("autoCollapseDelay") ?? 500)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
renderExtraItems = (position) => {
|
|
||||||
return this.state.extraItems[position].map((item = {}) => {
|
|
||||||
if (typeof item.icon !== "undefined") {
|
|
||||||
if (typeof item.props !== "object") {
|
|
||||||
item.props = Object()
|
|
||||||
}
|
|
||||||
|
|
||||||
item.props["icon"] = createIconRender(item.icon)
|
|
||||||
}
|
|
||||||
|
|
||||||
return <Menu.Item key={item.id} {...item.props}>{item.children}</Menu.Item>
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
if (this.state.loading) return null
|
if (!this.state.menus) return null
|
||||||
|
|
||||||
const { user } = this.props
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Sider
|
<div
|
||||||
onMouseEnter={this.onMouseEnter}
|
onMouseEnter={this.onMouseEnter}
|
||||||
onMouseLeave={this.handleMouseLeave}
|
onMouseLeave={this.handleMouseLeave}
|
||||||
theme={this.props.theme}
|
|
||||||
width={this.state.editMode ? 400 : 200}
|
|
||||||
collapsed={this.state.editMode ? false : this.state.collapsed}
|
|
||||||
onCollapse={() => this.props.onCollapse()}
|
|
||||||
className={
|
className={
|
||||||
classnames(
|
classnames(
|
||||||
"sidebar",
|
"app_sidebar",
|
||||||
{
|
{
|
||||||
["edit_mode"]: this.state.editMode,
|
["collapsed"]: this.state.visible && this.state.collapsed,
|
||||||
|
["elevated"]: this.state.visible && this.state.elevated,
|
||||||
["hidden"]: !this.state.visible,
|
["hidden"]: !this.state.visible,
|
||||||
["elevated"]: this.state.elevated
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -327,70 +240,49 @@ export default class Sidebar extends React.Component {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{this.state.editMode && (
|
<div key="menu" className="app_sidebar_menu_wrapper">
|
||||||
<div style={{ height: "100%" }}>
|
<Menu selectable={true} mode="inline" onClick={this.handleClick}>
|
||||||
<SidebarEditor />
|
{this.renderMenuItems(this.state.menus)}
|
||||||
</div>
|
</Menu>
|
||||||
)}
|
</div>
|
||||||
|
|
||||||
{!this.state.editMode && (
|
<div key="bottom" className={classnames("app_sidebar_menu_wrapper", "bottom")}>
|
||||||
<div key="menu" className="app_sidebar_menu">
|
<Menu selectable={false} mode="inline" onClick={this.handleClick}>
|
||||||
<Menu selectable={true} mode="inline" theme={this.props.theme} onClick={this.handleClick}>
|
<Menu.Item key="search" icon={<Icons.Search />} overrideEvent="app.openSearcher" >
|
||||||
{this.renderMenuItems(this.state.menus)}
|
<Translation>
|
||||||
{this.renderExtraItems("top")}
|
{(t) => t("Search")}
|
||||||
</Menu>
|
</Translation>
|
||||||
</div>
|
</Menu.Item>
|
||||||
)}
|
<Menu.Item key="create" icon={<Icons.PlusCircle />} overrideEvent="app.openCreator" >
|
||||||
|
<Translation>
|
||||||
{!this.state.editMode && <div key="additionalElements" className="additionalElements">
|
{(t) => t("Create")}
|
||||||
{this.state.additionalElements}
|
</Translation>
|
||||||
</div>}
|
</Menu.Item>
|
||||||
|
<Menu.Item key="notifications" icon={<Icons.Bell />} overrideEvent="app.openNotifications">
|
||||||
{!this.state.editMode && (
|
<Translation>
|
||||||
<div key="bottom" className="app_sidebar_bottom">
|
{t => t("Notifications")}
|
||||||
<Menu selectable={false} mode="inline" theme={this.props.theme} onClick={this.handleClick}>
|
</Translation>
|
||||||
<Menu.Item key="search" icon={<Icons.Search />} overrideEvent="app.openSearcher" >
|
</Menu.Item>
|
||||||
|
<Menu.Item key="settings" icon={<Icons.Settings />}>
|
||||||
|
<Translation>
|
||||||
|
{t => t("Settings")}
|
||||||
|
</Translation>
|
||||||
|
</Menu.Item>
|
||||||
|
{
|
||||||
|
app.userData && <Menu.Item key="account" className="user_avatar">
|
||||||
|
<Avatar shape="square" src={app.userData?.avatar} />
|
||||||
|
</Menu.Item>
|
||||||
|
}
|
||||||
|
{
|
||||||
|
!app.userData && <Menu.Item key="login" icon={<Icons.LogIn />}>
|
||||||
<Translation>
|
<Translation>
|
||||||
{(t) => t("Search")}
|
{t => t("Login")}
|
||||||
</Translation>
|
</Translation>
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
<Menu.Item key="create" icon={<Icons.PlusCircle />} overrideEvent="app.openCreator" >
|
}
|
||||||
<Translation>
|
</Menu>
|
||||||
{(t) => t("Create")}
|
</div>
|
||||||
</Translation>
|
</div>
|
||||||
</Menu.Item>
|
|
||||||
<Menu.Item key="notifications" icon={<Icons.Bell />} overrideEvent="app.openNotifications">
|
|
||||||
<Translation>
|
|
||||||
{t => t("Notifications")}
|
|
||||||
</Translation>
|
|
||||||
</Menu.Item>
|
|
||||||
<Menu.Item key="settings" icon={<Icons.Settings />}>
|
|
||||||
<Translation>
|
|
||||||
{t => t("Settings")}
|
|
||||||
</Translation>
|
|
||||||
</Menu.Item>
|
|
||||||
|
|
||||||
{
|
|
||||||
user && <Menu.Item key="account">
|
|
||||||
<div className="user_avatar">
|
|
||||||
<Avatar shape="square" src={user?.avatar} />
|
|
||||||
</div>
|
|
||||||
</Menu.Item>
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
!user && <Menu.Item key="login" icon={<Icons.LogIn />}>
|
|
||||||
<Translation>
|
|
||||||
{t => t("Login")}
|
|
||||||
</Translation>
|
|
||||||
</Menu.Item>
|
|
||||||
}
|
|
||||||
|
|
||||||
{this.renderExtraItems("bottom")}
|
|
||||||
</Menu>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</Sider>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,18 +1,45 @@
|
|||||||
@import "theme/vars.less";
|
@import "theme/vars.less";
|
||||||
|
|
||||||
// SIDEBAR
|
.app_sidebar {
|
||||||
.ant-layout-sider {
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
|
|
||||||
background: var(--sidebar-background-color) !important;
|
|
||||||
background-color: var(--sidebar-background-color) !important;
|
|
||||||
|
|
||||||
border-radius: 0 @app_sidebar_borderRadius @app_sidebar_borderRadius 0;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
border: 1px solid var(--sidebar-background-color);
|
|
||||||
|
width: @app_sidebar_collapsed_width;
|
||||||
|
min-width: @app_sidebar_width;
|
||||||
|
|
||||||
|
height: 100vh;
|
||||||
|
|
||||||
|
padding: 10px 0;
|
||||||
|
|
||||||
transition: all 150ms ease-in-out;
|
transition: all 150ms ease-in-out;
|
||||||
|
|
||||||
|
background-color: var(--sidebar-background-color);
|
||||||
|
|
||||||
|
border-radius: 0 @app_sidebar_borderRadius @app_sidebar_borderRadius 0;
|
||||||
|
border: 1px solid var(--sidebar-background-color);
|
||||||
|
|
||||||
|
&.collapsed {
|
||||||
|
width: 80px;
|
||||||
|
min-width: 80px;
|
||||||
|
|
||||||
|
.app_sidebar_menu_wrapper {
|
||||||
|
.ant-menu {
|
||||||
|
.ant-menu-item:not(.user_avatar) {
|
||||||
|
.ant-menu-title-content {
|
||||||
|
animation: disappear 0.3s ease-out forwards;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&.hidden {
|
&.hidden {
|
||||||
flex: 0 !important;
|
flex: 0 !important;
|
||||||
min-width: 0 !important;
|
min-width: 0 !important;
|
||||||
@ -23,138 +50,128 @@
|
|||||||
&.elevated {
|
&.elevated {
|
||||||
box-shadow: 0 0 5px 4px rgba(0, 0, 0, 0.1) !important;
|
box-shadow: 0 0 5px 4px rgba(0, 0, 0, 0.1) !important;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.ant-menu-item {
|
.app_sidebar_header {
|
||||||
color: var(--background-color-contrast);
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
h1,
|
height: 17%;
|
||||||
h2,
|
|
||||||
h3,
|
padding: 10px 0;
|
||||||
h4,
|
|
||||||
h5,
|
.app_sidebar_header_logo {
|
||||||
h6,
|
display: flex;
|
||||||
span,
|
align-items: center;
|
||||||
p {
|
justify-content: center;
|
||||||
color: var(--background-color-contrast);
|
|
||||||
|
img {
|
||||||
|
user-select: none;
|
||||||
|
--webkit-user-select: none;
|
||||||
|
|
||||||
|
width: 80%;
|
||||||
|
max-height: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.collapsed {
|
||||||
|
img {
|
||||||
|
max-width: 40px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.ant-menu,
|
.app_sidebar_menu_wrapper {
|
||||||
.ant-menu ul {
|
height: 65%;
|
||||||
background: transparent !important;
|
width: 100%;
|
||||||
background-color: transparent !important;
|
|
||||||
|
|
||||||
border-right: 0 !important;
|
overflow: overlay;
|
||||||
}
|
overflow-x: hidden;
|
||||||
|
|
||||||
.sidebar .ant-layout-sider-children {
|
display: flex;
|
||||||
margin-top: 15px !important;
|
flex-direction: column;
|
||||||
margin-bottom: 15px !important;
|
|
||||||
|
|
||||||
background: transparent !important;
|
align-items: center;
|
||||||
background-color: transparent !important;
|
|
||||||
|
|
||||||
user-select: none;
|
transition: all 150ms ease-in-out;
|
||||||
--webkit-user-select: none;
|
|
||||||
|
|
||||||
transition: all 150ms ease-in-out;
|
&.bottom {
|
||||||
height: 100%;
|
position: absolute;
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
&.edit_mode .ant-layout-sider-children {
|
bottom: 0;
|
||||||
background: transparent !important;
|
left: 0;
|
||||||
background-color: transparent !important;
|
|
||||||
|
|
||||||
margin-top: 15px !important;
|
height: fit-content;
|
||||||
|
|
||||||
.app_sidebar_menu_wrapper {
|
padding-bottom: 30px;
|
||||||
opacity: 0;
|
}
|
||||||
height: 0;
|
|
||||||
overflow: hidden;
|
.ant-menu {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
transition: all 150ms ease-in-out;
|
||||||
|
|
||||||
|
.ant-menu-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
width: 90%;
|
||||||
|
|
||||||
|
padding: 0 10px !important;
|
||||||
|
margin: 5px 0 !important;
|
||||||
|
|
||||||
|
transition: all 150ms ease-in-out;
|
||||||
|
|
||||||
|
.ant-menu-title-content {
|
||||||
|
flex: 1;
|
||||||
|
text-overflow: clip;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.user_avatar {
|
||||||
|
.ant-menu-title-content {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: fit-content;
|
||||||
|
}
|
||||||
|
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg {
|
||||||
|
width: fit-content;
|
||||||
|
margin: 0 !important;
|
||||||
|
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.app_sidebar_menu_wrapper {
|
@keyframes disappear {
|
||||||
transition: all 450ms ease-in-out;
|
0% {
|
||||||
|
opacity: 1;
|
||||||
height: 100%;
|
width: 100%;
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.app_sidebar_header {
|
|
||||||
background: transparent !important;
|
|
||||||
background-color: transparent !important;
|
|
||||||
|
|
||||||
user-select: none;
|
|
||||||
--webkit-user-select: none;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
height: 15%;
|
|
||||||
margin-top: 5%;
|
|
||||||
margin-bottom: 5%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.app_sidebar_header_logo {
|
|
||||||
user-select: none;
|
|
||||||
--webkit-user-select: none;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
img {
|
|
||||||
user-select: none;
|
|
||||||
--webkit-user-select: none;
|
|
||||||
|
|
||||||
width: 80%;
|
|
||||||
max-height: 80px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&.collapsed {
|
95% {
|
||||||
img {
|
opacity: 0;
|
||||||
max-width: 40px;
|
width: 0px;
|
||||||
}
|
margin: 0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.app_sidebar_menu {
|
100% {
|
||||||
background: transparent !important;
|
opacity: 0;
|
||||||
background-color: transparent !important;
|
width: 0px;
|
||||||
|
margin: 0;
|
||||||
height: 65%;
|
flex: 0;
|
||||||
overflow: overlay;
|
|
||||||
overflow-x: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.app_sidebar_bottom {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
padding-bottom: 30px;
|
|
||||||
z-index: 50;
|
|
||||||
left: 0;
|
|
||||||
|
|
||||||
background: transparent !important;
|
|
||||||
background-color: transparent !important;
|
|
||||||
backdrop-filter: blur(10px);
|
|
||||||
--webkit-backdrop-filter: blur(10px);
|
|
||||||
|
|
||||||
width: 100%;
|
|
||||||
height: fit-content;
|
|
||||||
|
|
||||||
.ant-menu,
|
|
||||||
ul {
|
|
||||||
background: transparent !important;
|
|
||||||
background-color: transparent !important;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.user_avatar {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
padding: 0 !important;
|
|
||||||
}
|
}
|
@ -172,6 +172,29 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// fix menu colors
|
// fix menu colors
|
||||||
|
.ant-menu,
|
||||||
|
.ant-menu ul {
|
||||||
|
background: transparent !important;
|
||||||
|
background-color: transparent !important;
|
||||||
|
|
||||||
|
border-right: 0 !important;
|
||||||
|
|
||||||
|
.ant-menu-item {
|
||||||
|
color: var(--background-color-contrast);
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6,
|
||||||
|
span,
|
||||||
|
p {
|
||||||
|
color: var(--background-color-contrast);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.ant-menu-item {
|
.ant-menu-item {
|
||||||
color: var(--text-color);
|
color: var(--text-color);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
@ -391,6 +414,6 @@
|
|||||||
// fix adm cards
|
// fix adm cards
|
||||||
.adm-card {
|
.adm-card {
|
||||||
background: var(--background-color-accent);
|
background: var(--background-color-accent);
|
||||||
|
|
||||||
color: var(--text-color);
|
color: var(--text-color);
|
||||||
}
|
}
|
@ -119,29 +119,25 @@ html {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ant-layout,
|
|
||||||
.content_layout {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
max-height: 100vh;
|
|
||||||
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.app_layout {
|
.app_layout {
|
||||||
background-color: rgba(var(--layoutBackgroundColor), var(--backgroundColorTransparency)) !important;
|
|
||||||
backdrop-filter: blur(var(--backgroundBlur));
|
|
||||||
|
|
||||||
position: relative;
|
position: relative;
|
||||||
-webkit-overflow-scrolling: touch;
|
|
||||||
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
max-height: 100vh;
|
max-height: 100vh;
|
||||||
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
background-color: rgba(var(--layoutBackgroundColor), var(--backgroundColorTransparency)) !important;
|
||||||
|
backdrop-filter: blur(var(--backgroundBlur));
|
||||||
|
|
||||||
transition: all 150ms ease-in-out;
|
transition: all 150ms ease-in-out;
|
||||||
|
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
display: block;
|
display: block;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@ -164,6 +160,15 @@ html {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ant-layout,
|
||||||
|
.content_layout {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
max-height: 100vh;
|
||||||
|
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
.layout_page {
|
.layout_page {
|
||||||
position: relative;
|
position: relative;
|
||||||
-webkit-overflow-scrolling: touch;
|
-webkit-overflow-scrolling: touch;
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
//* Now this only works as an fallback for unset dynamic theme values
|
//* Now this only works as an fallback for unset dynamic theme values
|
||||||
|
|
||||||
|
@app_sidebar_collapsed_width: 80px;
|
||||||
|
@app_sidebar_width: 230px;
|
||||||
|
|
||||||
// borders & radius
|
// borders & radius
|
||||||
@app_sidebar_borderRadius: 18px;
|
@app_sidebar_borderRadius: 18px;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user