Skip to content
Snippets Groups Projects
Unverified Commit f129b07d authored by Yusef Ouda's avatar Yusef Ouda Committed by GitHub
Browse files

Adds ability to resize sidebar (#2993)

* Adds ability to resize sidebar

* Adds release notes

* Changes to feature

* lint

* change translateX to use % for both states

* vrt

* set max sidebar width, cleanup

* set min and max widths

* min width to 200px

* changes resizable sidebar to use re-resizable instead off css resize

* vrt

* vrt
parent f1caf21d
No related branches found
No related tags found
No related merge requests found
......@@ -47,6 +47,7 @@
"memoize-one": "^6.0.0",
"pikaday": "1.8.2",
"promise-retry": "^2.0.1",
"re-resizable": "^6.9.17",
"react": "18.2.0",
"react-aria-components": "^1.2.1",
"react-dnd": "^16.0.1",
......
import React, { useRef, useState } from 'react';
import { useDispatch } from 'react-redux';
import { Resizable } from 're-resizable';
import {
closeBudget,
moveAccount,
......@@ -12,9 +14,11 @@ import { useAccounts } from '../../hooks/useAccounts';
import { useGlobalPref } from '../../hooks/useGlobalPref';
import { useLocalPref } from '../../hooks/useLocalPref';
import { useNavigate } from '../../hooks/useNavigate';
import { useResizeObserver } from '../../hooks/useResizeObserver';
import { SvgExpandArrow } from '../../icons/v0';
import { SvgReports, SvgWallet } from '../../icons/v1';
import { SvgCalendar } from '../../icons/v2';
import { useResponsive } from '../../ResponsiveProvider';
import { styles, theme } from '../../style';
import { Button } from '../common/Button';
import { InitialFocus } from '../common/InitialFocus';
......@@ -30,20 +34,28 @@ import { useSidebar } from './SidebarProvider';
import { ToggleButton } from './ToggleButton';
import { Tools } from './Tools';
export const SIDEBAR_WIDTH = 240;
export function Sidebar() {
const hasWindowButtons = !Platform.isBrowser && Platform.OS === 'mac';
const dispatch = useDispatch();
const sidebar = useSidebar();
const accounts = useAccounts();
const { width } = useResponsive();
const [showClosedAccounts, setShowClosedAccountsPref] = useLocalPref(
'ui.showClosedAccounts',
);
const [isFloating = false, setFloatingSidebarPref] =
useGlobalPref('floatingSidebar');
const [_sidebarWidth, setSidebarWidth] = useLocalPref('sidebarWidth');
const DEFAULT_SIDEBAR_WIDTH = 240;
const MAX_SIDEBAR_WIDTH = width / 3;
const MIN_SIDEBAR_WIDTH = 200;
const sidebarWidth = Math.min(
MAX_SIDEBAR_WIDTH,
Math.max(MIN_SIDEBAR_WIDTH, _sidebarWidth || DEFAULT_SIDEBAR_WIDTH),
);
async function onReorder(
id: string,
dropPos: 'top' | 'bottom',
......@@ -70,72 +82,96 @@ export function Sidebar() {
setShowClosedAccountsPref(!showClosedAccounts);
};
const containerRef = useResizeObserver(rect => {
setSidebarWidth(rect.width);
});
return (
<View
style={{
width: SIDEBAR_WIDTH,
color: theme.sidebarItemText,
backgroundColor: theme.sidebarBackground,
'& .float': {
opacity: isFloating ? 1 : 0,
transition: 'opacity .25s, width .25s',
width: hasWindowButtons || isFloating ? null : 0,
},
'&:hover .float': {
opacity: 1,
width: hasWindowButtons ? null : 'auto',
},
flex: 1,
...styles.darkScrollbar,
<Resizable
defaultSize={{
width: sidebarWidth,
height: '100%',
}}
maxWidth={MAX_SIDEBAR_WIDTH}
minWidth={MIN_SIDEBAR_WIDTH}
enable={{
top: false,
right: true,
bottom: false,
left: false,
topRight: false,
bottomRight: false,
bottomLeft: false,
topLeft: false,
}}
>
<View
innerRef={containerRef}
style={{
paddingTop: 35,
height: 30,
flexDirection: 'row',
alignItems: 'center',
margin: '0 8px 23px 20px',
transition: 'padding .4s',
...(hasWindowButtons && {
paddingTop: 20,
justifyContent: 'flex-start',
}),
color: theme.sidebarItemText,
height: '100%',
backgroundColor: theme.sidebarBackground,
'& .float': {
opacity: isFloating ? 1 : 0,
transition: 'opacity .25s, width .25s',
width: hasWindowButtons || isFloating ? null : 0,
},
'&:hover .float': {
opacity: 1,
width: hasWindowButtons ? null : 'auto',
},
flex: 1,
...styles.darkScrollbar,
}}
>
<EditableBudgetName />
<View
style={{
paddingTop: 35,
height: 30,
flexDirection: 'row',
alignItems: 'center',
margin: '0 8px 23px 20px',
transition: 'padding .4s',
...(hasWindowButtons && {
paddingTop: 20,
justifyContent: 'flex-start',
}),
}}
>
<EditableBudgetName />
<View style={{ flex: 1, flexDirection: 'row' }} />
<View style={{ flex: 1, flexDirection: 'row' }} />
{!sidebar.alwaysFloats && (
<ToggleButton isFloating={isFloating} onFloat={onFloat} />
)}
</View>
{!sidebar.alwaysFloats && (
<ToggleButton isFloating={isFloating} onFloat={onFloat} />
)}
</View>
<View style={{ overflow: 'auto' }}>
<Item title="Budget" Icon={SvgWallet} to="/budget" />
<Item title="Reports" Icon={SvgReports} to="/reports" />
<View style={{ overflow: 'auto' }}>
<Item title="Budget" Icon={SvgWallet} to="/budget" />
<Item title="Reports" Icon={SvgReports} to="/reports" />
<Item title="Schedules" Icon={SvgCalendar} to="/schedules" />
<Item title="Schedules" Icon={SvgCalendar} to="/schedules" />
<Tools />
<Tools />
<View
style={{
height: 1,
backgroundColor: theme.sidebarItemBackgroundHover,
marginTop: 15,
flexShrink: 0,
}}
/>
<View
style={{
height: 1,
backgroundColor: theme.sidebarItemBackgroundHover,
marginTop: 15,
flexShrink: 0,
}}
/>
<Accounts
onAddAccount={onAddAccount}
onToggleClosedAccounts={onToggleClosedAccounts}
onReorder={onReorder}
/>
<Accounts
onAddAccount={onAddAccount}
onToggleClosedAccounts={onToggleClosedAccounts}
onReorder={onReorder}
/>
</View>
</View>
</View>
</Resizable>
);
}
......
......@@ -4,7 +4,7 @@ import { useGlobalPref } from '../../hooks/useGlobalPref';
import { useResponsive } from '../../ResponsiveProvider';
import { View } from '../common/View';
import { SIDEBAR_WIDTH, Sidebar } from './Sidebar';
import { Sidebar } from './Sidebar';
import { useSidebar } from './SidebarProvider';
export function FloatableSidebar() {
......@@ -42,10 +42,8 @@ export function FloatableSidebar() {
: '0 15px 30px 0 rgba(0,0,0,0.25), 0 3px 15px 0 rgba(0,0,0,.5)',
transform: `translateY(${!sidebarShouldFloat ? -12 : 0}px)
translateX(${
sidebarShouldFloat && sidebar.hidden
? -SIDEBAR_WIDTH
: 0
}px)`,
sidebarShouldFloat && sidebar.hidden ? '-100' : '0'
}%)`,
transition:
'transform .5s, box-shadow .5s, border-radius .5s, bottom .5s',
}}
......
......@@ -53,6 +53,7 @@ export type LocalPrefs = Partial<
reportsViewLegend: boolean;
reportsViewSummary: boolean;
reportsViewLabel: boolean;
sidebarWidth: number;
'mobile.showSpentColumn': boolean;
} & Record<`flags.${FeatureFlag}`, boolean>
>;
......
---
category: Features
authors: [YusefOuda]
---
Adds ability to resize sidebar.
......@@ -100,6 +100,7 @@ __metadata:
memoize-one: "npm:^6.0.0"
pikaday: "npm:1.8.2"
promise-retry: "npm:^2.0.1"
re-resizable: "npm:^6.9.17"
react: "npm:18.2.0"
react-aria-components: "npm:^1.2.1"
react-dnd: "npm:^16.0.1"
......@@ -15469,6 +15470,16 @@ __metadata:
languageName: node
linkType: hard
 
"re-resizable@npm:^6.9.17":
version: 6.9.17
resolution: "re-resizable@npm:6.9.17"
peerDependencies:
react: ^16.13.1 || ^17.0.0 || ^18.0.0
react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0
checksum: 768c3a0fe39d6916caf4e003240d326d62c4d7512c7d3115cc2a98085416fdba80097afdbb93df57b69543c41ce56b33589f2fea6987cd5149faa83cf11c8ba1
languageName: node
linkType: hard
"react-aria-components@npm:^1.2.1":
version: 1.2.1
resolution: "react-aria-components@npm:1.2.1"
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment