mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Fix flickering and arrows position
Signed-off-by: DmitriyNoa <dmytro.zharkov@gmail.com>
This commit is contained in:
parent
411c28d969
commit
1d79392668
@ -49,6 +49,7 @@ const getComponent = (dockStore: DockStore) => (
|
|||||||
selectedTab={dockStore.selectedTab}
|
selectedTab={dockStore.selectedTab}
|
||||||
autoFocus={true}
|
autoFocus={true}
|
||||||
onChangeTab={noop}
|
onChangeTab={noop}
|
||||||
|
dockStore={dockStore}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -97,6 +97,11 @@ export interface DockTabCloseEvent {
|
|||||||
tabId: TabId; // closed tab id
|
tabId: TabId; // closed tab id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface DockTabsNumberEvent {
|
||||||
|
currentTabsNumber: number; // number of open tabs
|
||||||
|
previousTabsNumber: number;
|
||||||
|
}
|
||||||
|
|
||||||
interface Dependencies {
|
interface Dependencies {
|
||||||
storage: StorageHelper<DockStorageState>
|
storage: StorageHelper<DockStorageState>
|
||||||
}
|
}
|
||||||
@ -160,6 +165,10 @@ export class DockStore implements DockStorageState {
|
|||||||
this.dependencies.storage.merge({ selectedTabId: tabId });
|
this.dependencies.storage.merge({ selectedTabId: tabId });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@computed get tabsNumber() : number {
|
||||||
|
return this.tabs.length;
|
||||||
|
}
|
||||||
|
|
||||||
@computed get selectedTab() {
|
@computed get selectedTab() {
|
||||||
return this.tabs.find(tab => tab.id === this.selectedTabId);
|
return this.tabs.find(tab => tab.id === this.selectedTabId);
|
||||||
}
|
}
|
||||||
@ -224,6 +233,15 @@ export class DockStore implements DockStorageState {
|
|||||||
}), reactionOpts);
|
}), reactionOpts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onTabsNumberChange(callback: (evt: DockTabsNumberEvent) => void) {
|
||||||
|
return reaction(() => this.tabsNumber, ((currentTabsNumber, previousTabsNumber) => {
|
||||||
|
callback({
|
||||||
|
currentTabsNumber,
|
||||||
|
previousTabsNumber,
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
hasTabs() {
|
hasTabs() {
|
||||||
return this.tabs.length > 0;
|
return this.tabs.length > 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,17 +8,18 @@ import { Icon } from "../icon";
|
|||||||
import { Tabs } from "../tabs/tabs";
|
import { Tabs } from "../tabs/tabs";
|
||||||
import { DockTab } from "./dock-tab";
|
import { DockTab } from "./dock-tab";
|
||||||
import type { DockTab as DockTabModel } from "./dock-store/dock.store";
|
import type { DockTab as DockTabModel } from "./dock-store/dock.store";
|
||||||
import { TabKind } from "./dock-store/dock.store";
|
import { TabKind, DockStore } from "./dock-store/dock.store";
|
||||||
import { TerminalTab } from "./terminal-tab";
|
import { TerminalTab } from "./terminal-tab";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
tabs: DockTabModel[]
|
tabs: DockTabModel[]
|
||||||
|
dockStore: DockStore;
|
||||||
autoFocus: boolean
|
autoFocus: boolean
|
||||||
selectedTab: DockTabModel
|
selectedTab: DockTabModel
|
||||||
onChangeTab: (tab: DockTabModel) => void
|
onChangeTab: (tab: DockTabModel) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DockTabs = ({ tabs, autoFocus, selectedTab, onChangeTab }: Props) => {
|
export const DockTabs = ({ tabs, autoFocus, selectedTab, onChangeTab, dockStore }: Props) => {
|
||||||
const elem = useRef(null);
|
const elem = useRef(null);
|
||||||
const contentElem = useRef(null);
|
const contentElem = useRef(null);
|
||||||
const [contentWidth, setContentWidth] = useState(0);
|
const [contentWidth, setContentWidth] = useState(0);
|
||||||
@ -27,7 +28,7 @@ export const DockTabs = ({ tabs, autoFocus, selectedTab, onChangeTab }: Props) =
|
|||||||
const scrollStep = 200;
|
const scrollStep = 200;
|
||||||
|
|
||||||
const scrollToRight = (): void => {
|
const scrollToRight = (): void => {
|
||||||
if(!elem || scrollPosition + scrollStep > contentWidth) return;
|
if(!elem || scrollPosition === contentWidth) return;
|
||||||
const scroll = scrollPosition + scrollStep;
|
const scroll = scrollPosition + scrollStep;
|
||||||
|
|
||||||
setScrollPosition(scroll);
|
setScrollPosition(scroll);
|
||||||
@ -35,6 +36,14 @@ export const DockTabs = ({ tabs, autoFocus, selectedTab, onChangeTab }: Props) =
|
|||||||
elem.current.scrollLeft = scroll;
|
elem.current.scrollLeft = scroll;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const updateStateValues = () => {
|
||||||
|
if(!elem || !contentElem) return;
|
||||||
|
|
||||||
|
setContentWidth(contentElem.current.clientWidth);
|
||||||
|
setContainerWidth(elem.current.clientWidth);
|
||||||
|
setScrollPosition(elem.current.scrollLeft);
|
||||||
|
};
|
||||||
|
|
||||||
const scrollToLeft = (): void => {
|
const scrollToLeft = (): void => {
|
||||||
if(!elem) return;
|
if(!elem) return;
|
||||||
const scroll = scrollPosition - scrollStep;
|
const scroll = scrollPosition - scrollStep;
|
||||||
@ -47,13 +56,15 @@ export const DockTabs = ({ tabs, autoFocus, selectedTab, onChangeTab }: Props) =
|
|||||||
const isScrollableRight = (): boolean => {
|
const isScrollableRight = (): boolean => {
|
||||||
if(!elem || !contentElem) return false;
|
if(!elem || !contentElem) return false;
|
||||||
|
|
||||||
return contentWidth > containerWidth && scrollPosition < contentWidth - containerWidth;
|
// check if element with tabs is wider than the parent element
|
||||||
|
// check if scroll at the end of scrollable area.
|
||||||
|
return contentElem.current?.clientWidth > containerWidth && scrollPosition < contentElem.current?.clientWidth - elem.current?.clientWidth;
|
||||||
};
|
};
|
||||||
|
|
||||||
const isScrollableLeft = (): boolean => {
|
const isScrollableLeft = (): boolean => {
|
||||||
if(!elem || !contentElem) return false;
|
if(!elem || !contentElem) return false;
|
||||||
|
|
||||||
return scrollPosition > scrollStep;
|
return scrollPosition > 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateScrollPosition = ( evt: UIEvent<HTMLDivElement>): void => {
|
const updateScrollPosition = ( evt: UIEvent<HTMLDivElement>): void => {
|
||||||
@ -65,11 +76,7 @@ export const DockTabs = ({ tabs, autoFocus, selectedTab, onChangeTab }: Props) =
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onWindowResize = (): void => {
|
const onWindowResize = (): void => {
|
||||||
if(!elem || !contentElem) return;
|
updateStateValues();
|
||||||
|
|
||||||
setContentWidth(contentElem.current.clientWidth);
|
|
||||||
setContainerWidth(elem.current.clientWidth);
|
|
||||||
setScrollPosition(elem.current.scrollLeft);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderTab = (tab?: DockTabModel) => {
|
const renderTab = (tab?: DockTabModel) => {
|
||||||
@ -93,17 +100,18 @@ export const DockTabs = ({ tabs, autoFocus, selectedTab, onChangeTab }: Props) =
|
|||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if(!elem || !contentElem) return;
|
updateStateValues();
|
||||||
|
|
||||||
setContentWidth(contentElem.current.clientWidth);
|
|
||||||
setContainerWidth(elem.current.clientWidth);
|
|
||||||
setScrollPosition(elem.current.scrollLeft);
|
|
||||||
|
|
||||||
// update values in store on scroll
|
// update values in store on scroll
|
||||||
elem.current.addEventListener("scroll", updateScrollPosition);
|
elem.current.addEventListener("scroll", updateScrollPosition);
|
||||||
|
|
||||||
// update current values on resize to show/hide scroll
|
// update current values on resize to show/hide scroll
|
||||||
window.addEventListener("resize", onWindowResize);
|
window.addEventListener("resize", onWindowResize);
|
||||||
|
|
||||||
|
// update scroll state if tabs numbers has changed
|
||||||
|
dockStore.onTabsNumberChange(() => {
|
||||||
|
updateStateValues();
|
||||||
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -60,6 +60,10 @@
|
|||||||
|
|
||||||
.tabs-wrapper {
|
.tabs-wrapper {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
position: relative;
|
||||||
|
padding: 0 $padding*2.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab-content {
|
.tab-content {
|
||||||
@ -83,7 +87,7 @@
|
|||||||
|
|
||||||
.tabs-control {
|
.tabs-control {
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
position: relative;
|
width: 100%;
|
||||||
|
|
||||||
&::-webkit-scrollbar {
|
&::-webkit-scrollbar {
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
@ -100,20 +104,6 @@
|
|||||||
&:hover::-webkit-scrollbar-thumb {
|
&:hover::-webkit-scrollbar-thumb {
|
||||||
background: var(--scrollBarColor);
|
background: var(--scrollBarColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab-control {
|
|
||||||
position: absolute;
|
|
||||||
z-index: 9999;
|
|
||||||
}
|
|
||||||
|
|
||||||
.scroll-left {
|
|
||||||
left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.right {
|
|
||||||
right: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.DockTab.active {
|
.DockTab.active {
|
||||||
@ -123,4 +113,18 @@
|
|||||||
color: var(--terminalWhite);
|
color: var(--terminalWhite);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tab-control {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 9999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll-left {
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll-right {
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -157,6 +157,7 @@ class NonInjectedDock extends React.Component<Props & Dependencies> {
|
|||||||
selectedTab={selectedTab}
|
selectedTab={selectedTab}
|
||||||
autoFocus={isOpen}
|
autoFocus={isOpen}
|
||||||
onChangeTab={this.onChangeTab}
|
onChangeTab={this.onChangeTab}
|
||||||
|
dockStore={dockStore}
|
||||||
/>
|
/>
|
||||||
<div className="toolbar flex gaps align-center box grow">
|
<div className="toolbar flex gaps align-center box grow">
|
||||||
<div className="dock-menu box grow">
|
<div className="dock-menu box grow">
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user