New: Add button to close side bar

Closes #7757
This commit is contained in:
Mark McDowall 2025-10-01 20:14:30 -07:00
parent a4f210855e
commit 9484904f60
No known key found for this signature in database
4 changed files with 71 additions and 27 deletions

View file

@ -1,5 +1,4 @@
.header {
z-index: 3;
display: flex;
align-items: center;
flex: 0 0 auto;

View file

@ -7,6 +7,40 @@
transform: translateX(0);
}
.sidebarHeader {
display: flex;
align-items: center;
justify-content: space-between;
height: $headerHeight;
}
.logoContainer {
display: flex;
align-items: center;
padding-left: 20px;
}
.logoLink {
line-height: 0;
}
.logo {
width: 32px;
height: 32px;
}
.sidebarCloseButton {
composes: button from '~Components/Link/IconButton.css';
margin-right: 15px;
color: #e1e2e3;
text-align: center;
&:hover {
color: var(--sonarrBlue);
}
}
.sidebar {
display: flex;
flex-direction: column;

View file

@ -1,8 +1,13 @@
// This file is automatically generated.
// Please do not change this file!
interface CssExports {
'logo': string;
'logoContainer': string;
'logoLink': string;
'sidebar': string;
'sidebarCloseButton': string;
'sidebarContainer': string;
'sidebarHeader': string;
}
export const cssExports: CssExports;
export default cssExports;

View file

@ -1,4 +1,3 @@
import classNames from 'classnames';
import React, {
useCallback,
useEffect,
@ -11,6 +10,8 @@ import { useDispatch } from 'react-redux';
import { useLocation } from 'react-router';
import QueueStatus from 'Activity/Queue/Status/QueueStatus';
import { IconName } from 'Components/Icon';
import IconButton from 'Components/Link/IconButton';
import Link from 'Components/Link/Link';
import OverlayScroller from 'Components/Scroller/OverlayScroller';
import Scroller from 'Components/Scroller/Scroller';
import usePrevious from 'Helpers/Hooks/usePrevious';
@ -230,10 +231,6 @@ function PageSidebar({ isSidebarVisible, isSmallScreen }: PageSidebarProps) {
transition: 'none',
transform: isSidebarVisible ? 0 : SIDEBAR_WIDTH * -1,
});
const [sidebarStyle, setSidebarStyle] = useState({
top: dimensions.headerHeight,
height: `${window.innerHeight - HEADER_HEIGHT}px`,
});
const urlBase = window.Sonarr.urlBase;
const pathname = urlBase
@ -299,22 +296,6 @@ function PageSidebar({ isSidebarVisible, isSmallScreen }: PageSidebarProps) {
dispatch(setIsSidebarVisible({ isSidebarVisible: false }));
}, [dispatch]);
const handleWindowScroll = useCallback(() => {
const windowScroll =
window.scrollY == null
? document.documentElement.scrollTop
: window.scrollY;
const sidebarTop = Math.max(HEADER_HEIGHT - windowScroll, 0);
const sidebarHeight = window.innerHeight - sidebarTop;
if (isSmallScreen) {
setSidebarStyle({
top: `${sidebarTop}px`,
height: `${sidebarHeight}px`,
});
}
}, [isSmallScreen]);
const handleTouchStart = useCallback(
(event: TouchEvent) => {
const touches = event.touches;
@ -396,10 +377,13 @@ function PageSidebar({ isSidebarVisible, isSmallScreen }: PageSidebarProps) {
touchStartY.current = null;
}, []);
const handleSidebarClosePress = useCallback(() => {
dispatch(setIsSidebarVisible({ isSidebarVisible: false }));
}, [dispatch]);
useEffect(() => {
if (isSmallScreen) {
window.addEventListener('click', handleWindowClick, { capture: true });
window.addEventListener('scroll', handleWindowScroll);
window.addEventListener('touchstart', handleTouchStart);
window.addEventListener('touchmove', handleTouchMove);
window.addEventListener('touchend', handleTouchEnd);
@ -408,7 +392,6 @@ function PageSidebar({ isSidebarVisible, isSmallScreen }: PageSidebarProps) {
return () => {
window.removeEventListener('click', handleWindowClick, { capture: true });
window.removeEventListener('scroll', handleWindowScroll);
window.removeEventListener('touchstart', handleTouchStart);
window.removeEventListener('touchmove', handleTouchMove);
window.removeEventListener('touchend', handleTouchEnd);
@ -417,7 +400,6 @@ function PageSidebar({ isSidebarVisible, isSmallScreen }: PageSidebarProps) {
}, [
isSmallScreen,
handleWindowClick,
handleWindowScroll,
handleTouchStart,
handleTouchMove,
handleTouchEnd,
@ -456,13 +438,37 @@ function PageSidebar({ isSidebarVisible, isSmallScreen }: PageSidebarProps) {
return (
<div
ref={sidebarRef}
className={classNames(styles.sidebarContainer)}
className={styles.sidebarContainer}
style={containerStyle}
>
{isSmallScreen ? (
<div className={styles.sidebarHeader}>
<div className={styles.logoContainer}>
<Link className={styles.logoLink} to="/">
<img
className={styles.logo}
src={`${window.Sonarr.urlBase}/Content/Images/logo.svg`}
alt="Sonarr Logo"
/>
</Link>
</div>
<IconButton
className={styles.sidebarCloseButton}
name={icons.CLOSE}
aria-label={translate('Close')}
size={20}
onPress={handleSidebarClosePress}
/>
</div>
) : null}
<ScrollerComponent
className={styles.sidebar}
scrollDirection="vertical"
style={sidebarStyle}
style={{
height: `${window.innerHeight - HEADER_HEIGHT}px`,
}}
>
<div>
{LINKS.map((link) => {