mirror of
https://github.com/Vendicated/Vencord.git
synced 2025-01-11 10:26:21 +00:00
Still WIP Book Tabs
This commit is contained in:
parent
93c694757e
commit
17bcf33139
2 changed files with 77 additions and 58 deletions
|
@ -6,33 +6,38 @@
|
||||||
|
|
||||||
import { classes } from "@utils/misc";
|
import { classes } from "@utils/misc";
|
||||||
import { findByCode, findByProps } from "@webpack";
|
import { findByCode, findByProps } from "@webpack";
|
||||||
import { Button, Menu, Popout, React, TabBar } from "@webpack/common";
|
import { Button, Clickable, Menu, Popout, React, TabBar } from "@webpack/common";
|
||||||
|
import { Fragment } from "react";
|
||||||
|
|
||||||
import { SvgOverFlowIcon } from "../icons/overFlowIcon";
|
import { SvgOverFlowIcon } from "../icons/overFlowIcon";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export function NoteBookTabs({ tabs, selectedTabId, onSelectTab }) {
|
export function NoteBookTabs({ tabs, selectedTabId, onSelectTab }) {
|
||||||
const tabBarRef = React.useRef<HTMLDivElement>(null);
|
const tabBarRef = React.useRef<HTMLDivElement>(null);
|
||||||
const widthRef = React.useRef<number>(0);
|
const widthRef = React.useRef<number>(0);
|
||||||
const tabWidthMapRef = React.useRef(new Map());
|
const tabWidthMapRef = React.useRef(new Map());
|
||||||
const [overflowedTabs, setOverflowedTabs] = React.useState([]);
|
const [overflowedTabs, setOverflowedTabs] = React.useState([]);
|
||||||
const { tabBar } = findByProps("tabBar");
|
const { tabBar, tabBarItem } = findByProps("tabBar");
|
||||||
const { forwardRef } = findByProps("forwardRef");
|
const { forwardRef } = findByProps("forwardRef");
|
||||||
|
|
||||||
const calculateOverflowedTabs = React.useCallback(() => {
|
const calculateOverflowedTabs = React.useCallback(() => {
|
||||||
if (tabBarRef.current == null) return;
|
if (!tabBarRef.current) return;
|
||||||
const overflowed = [];
|
|
||||||
let totalWidth = tabBarRef.current.getBoundingClientRect().width;
|
let totalWidth = tabBarRef.current.getBoundingClientRect().width;
|
||||||
|
|
||||||
|
overflowedTabs.length = 0;
|
||||||
|
|
||||||
if (totalWidth !== widthRef.current) {
|
if (totalWidth !== widthRef.current) {
|
||||||
for (const tab of Object.keys(tabs)) {
|
for (const tab of Object.keys(tabs)) {
|
||||||
if (tab !== selectedTabId) {
|
if (tab !== selectedTabId) {
|
||||||
const tabWidth = tabWidthMapRef.current.get(tab)?.width || 0;
|
const tabWidth = tabWidthMapRef.current.get(tab)?.width || 0;
|
||||||
totalWidth -= tabWidth;
|
totalWidth -= tabWidth;
|
||||||
if (totalWidth < 0) overflowed.push(tab);
|
if (tab !== selectedTabId && totalWidth < 0) overflowedTabs.push(tab);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setOverflowedTabs(overflowed);
|
setOverflowedTabs(overflowedTabs);
|
||||||
widthRef.current = totalWidth;
|
// widthRef.current = totalWidth;
|
||||||
}
|
}
|
||||||
}, [tabs, selectedTabId]);
|
}, [tabs, selectedTabId]);
|
||||||
|
|
||||||
|
@ -48,6 +53,17 @@ export function NoteBookTabs({ tabs, selectedTabId, onSelectTab }) {
|
||||||
};
|
};
|
||||||
}, [calculateOverflowedTabs]);
|
}, [calculateOverflowedTabs]);
|
||||||
|
|
||||||
|
const TabItem = React.forwardRef(({ id, selected, onClick, children }) => (
|
||||||
|
<Clickable
|
||||||
|
className={classes(tabBarItem)}
|
||||||
|
data-tab-id={id}
|
||||||
|
// innerRef={ref}
|
||||||
|
onClick={onClick}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</Clickable>
|
||||||
|
));
|
||||||
|
|
||||||
const renderOverflowMenu = React.useCallback(({ closePopout }) => {
|
const renderOverflowMenu = React.useCallback(({ closePopout }) => {
|
||||||
return (
|
return (
|
||||||
<Menu.Menu
|
<Menu.Menu
|
||||||
|
@ -85,47 +101,47 @@ export function NoteBookTabs({ tabs, selectedTabId, onSelectTab }) {
|
||||||
look="brand"
|
look="brand"
|
||||||
className={classes("vc-notebook-tabbar-bar", "vc-notebook-tabbar")}
|
className={classes("vc-notebook-tabbar-bar", "vc-notebook-tabbar")}
|
||||||
>
|
>
|
||||||
{
|
{Object.keys(tabs).map(tab => {
|
||||||
Object.keys(tabs).map(tab => {
|
if (!overflowedTabs.includes(tab)) {
|
||||||
if (!overflowedTabs.includes(tab)) {
|
return (
|
||||||
return (
|
<TabItem
|
||||||
<forwardRef
|
id={tab}
|
||||||
id={tab}
|
selected={selectedTabId === tab}
|
||||||
selected={selectedTabId === tab}
|
className={classes("vc-notebook-tabbar-bar-item", "vc-notebook-tabbar-item")}
|
||||||
ref={ref => {
|
ref={ref => {
|
||||||
const width = ref?.getBoundingClientRect().width || 0;
|
const width = ref?.getBoundingClientRect().width || tabWidthMapRef.current.get(tab.id) || 0;
|
||||||
tabWidthMapRef.current.set(tab, { node: ref, width });
|
tabWidthMapRef.current.set(tab, width);
|
||||||
|
|
||||||
}}
|
}}
|
||||||
onClick={selectedTabId !== tab ? () => onSelectTab(tab) : undefined}
|
// onClick={selectedTabId !== tab && onSelectTab(tab)}
|
||||||
>
|
>
|
||||||
<TabBar.Item key={tab} id={tab} className={classes("vc-notebook-tabbar-bar-item", "vc-notebook-tabbar-item")}>
|
{tab}
|
||||||
{tab}
|
</TabItem>
|
||||||
</TabBar.Item>
|
);
|
||||||
</forwardRef>
|
}
|
||||||
);
|
})
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
{overflowedTabs.length > 0 && (
|
{overflowedTabs.length > 0 && (
|
||||||
<Popout
|
<Fragment>
|
||||||
renderPopout={renderOverflowMenu}
|
<Popout
|
||||||
position="bottom"
|
renderPopout={renderOverflowMenu}
|
||||||
align="right"
|
position="bottom"
|
||||||
spacing={0}
|
align="right"
|
||||||
>
|
spacing={0}
|
||||||
{() => (
|
>
|
||||||
<Button
|
{() => (
|
||||||
className={"vc-notebook-overflow-chevron"}
|
<Button
|
||||||
size={Button.Sizes.ICON}
|
className={"vc-notebook-overflow-chevron"}
|
||||||
look={Button.Looks.BLANK}
|
size={Button.Sizes.ICON}
|
||||||
>
|
look={Button.Looks.BLANK}
|
||||||
<SvgOverFlowIcon />
|
>
|
||||||
</Button>
|
<SvgOverFlowIcon />
|
||||||
)
|
</Button>
|
||||||
}
|
)
|
||||||
|
}
|
||||||
|
|
||||||
</Popout>
|
</Popout>
|
||||||
|
</Fragment>
|
||||||
)}
|
)}
|
||||||
</TabBar>
|
</TabBar>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -30,20 +30,6 @@ $modifier: var(--background-modifier-accent);
|
||||||
transform: scale(1);
|
transform: scale(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.vc-notebook-tabbar {
|
|
||||||
margin: 0;
|
|
||||||
padding: 10px 20px 0;
|
|
||||||
background-color: var(--background-tertiary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.vc-notebook-tabbar-item {
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vc-notebook-display-left {
|
|
||||||
flex: auto;
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vc-notebook-flex {
|
.vc-notebook-flex {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
@ -63,6 +49,11 @@ $modifier: var(--background-modifier-accent);
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.vc-notebook-display-left {
|
||||||
|
flex: auto;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
.vc-help-markdown {
|
.vc-help-markdown {
|
||||||
margin-top: 6px;
|
margin-top: 6px;
|
||||||
}
|
}
|
||||||
|
@ -82,6 +73,18 @@ $modifier: var(--background-modifier-accent);
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.vc-notebook-tabbar {
|
||||||
|
overflow: hidden;
|
||||||
|
margin: 0;
|
||||||
|
padding: 10px 20px 0;
|
||||||
|
background-color: var(--background-tertiary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.vc-notebook-tabbar-item {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.vc-notebook-tabbar-bar {
|
.vc-notebook-tabbar-bar {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
|
|
Loading…
Reference in a new issue