Skip to content

Commit

Permalink
Update Sidebar - Refactor the Budget Name component (actualbudget#3593)
Browse files Browse the repository at this point in the history
* Initial Commit

Moved Budget Name to its own component for a cleaner Sidebar component.
Added pencil icon for editing budget name.
Removed Rename Budget from menu.

* Create 3593.md

* Fixed Menu Dropdown Arrow shrinks with long budget name

* Changes recommended by coderabbitai

* Fixed Lint issue

* Remove Help from Menu

* Remove menu from budget name and added Actual logo with menu

* Update VRTs

* Update VRTs

* Fix logo shrinking with long budget name issue

* Update 3593.md

* Removed Logo and pencil icon

* Update VRTs

* Removed unused classnames from SideBar and BudgetName component

* revert to upstream VRTs
  • Loading branch information
tlesicka authored Nov 7, 2024
1 parent 1f6977d commit aefd950
Show file tree
Hide file tree
Showing 3 changed files with 153 additions and 121 deletions.
142 changes: 142 additions & 0 deletions packages/desktop-client/src/components/sidebar/BudgetName.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import React, { type ReactNode, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useDispatch } from 'react-redux';

import { closeBudget } from 'loot-core/src/client/actions';
import * as Platform from 'loot-core/src/client/platform';

import { useMetadataPref } from '../../hooks/useMetadataPref';
import { useNavigate } from '../../hooks/useNavigate';
import { SvgExpandArrow } from '../../icons/v0';
import { theme } from '../../style';
import { Button } from '../common/Button2';
import { InitialFocus } from '../common/InitialFocus';
import { Input } from '../common/Input';
import { Menu } from '../common/Menu';
import { Popover } from '../common/Popover';
import { Text } from '../common/Text';
import { View } from '../common/View';

type BudgetNameProps = {
children?: ReactNode;
};

export function BudgetName({ children }: BudgetNameProps) {
const hasWindowButtons = !Platform.isBrowser && Platform.OS === 'mac';

return (
<View
style={{
paddingTop: 35,
height: 30,
flexDirection: 'row',
alignItems: 'center',
margin: '0 8px 23px 20px',
userSelect: 'none',
transition: 'padding .4s',
...(hasWindowButtons && {
paddingTop: 20,
justifyContent: 'flex-start',
}),
}}
>
<EditableBudgetName />

<View style={{ flex: 1, flexDirection: 'row' }} />

{children}
</View>
);
}

function EditableBudgetName() {
const { t } = useTranslation();
const [budgetName, setBudgetNamePref] = useMetadataPref('budgetName');
const dispatch = useDispatch();
const navigate = useNavigate();
const [menuOpen, setMenuOpen] = useState(false);
const triggerRef = useRef<HTMLButtonElement>(null);
const [editing, setEditing] = useState(false);

function onMenuSelect(type: string) {
setMenuOpen(false);

switch (type) {
case 'rename':
setEditing(true);
break;
case 'settings':
navigate('/settings');
break;
case 'close':
dispatch(closeBudget());
break;
default:
}
}

const items = [
{ name: 'rename', text: t('Rename budget') },
{ name: 'settings', text: t('Settings') },
{ name: 'close', text: t('Close file') },
];

if (editing) {
return (
<InitialFocus>
<Input
style={{
maxWidth: 'calc(100% - 23px)',
fontSize: 16,
fontWeight: 500,
}}
defaultValue={budgetName}
onEnter={e => {
const inputEl = e.target as HTMLInputElement;
const newBudgetName = inputEl.value;
if (newBudgetName.trim() !== '') {
setBudgetNamePref(newBudgetName);
setEditing(false);
}
}}
onBlur={() => setEditing(false)}
/>
</InitialFocus>
);
}

return (
<>
<Button
ref={triggerRef}
variant="bare"
style={{
color: theme.buttonNormalBorder,
fontSize: 16,
fontWeight: 500,
marginLeft: -5,
flex: '0 auto',
}}
onPress={() => setMenuOpen(true)}
>
<Text style={{ whiteSpace: 'nowrap', overflow: 'hidden' }}>
{budgetName || t('A budget has no name')}
</Text>
<SvgExpandArrow
width={7}
height={7}
style={{ flexShrink: 0, marginLeft: 5 }}
/>
</Button>

<Popover
triggerRef={triggerRef}
placement="bottom start"
isOpen={menuOpen}
onOpenChange={() => setMenuOpen(false)}
>
<Menu onMenuSelect={onMenuSelect} items={items} />
</Popover>
</>
);
}
126 changes: 5 additions & 121 deletions packages/desktop-client/src/components/sidebar/Sidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,23 @@
import React, { type CSSProperties, useRef, useState } from 'react';
import React, { type CSSProperties, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useDispatch } from 'react-redux';

import { css } from '@emotion/css';
import { Resizable } from 're-resizable';

import { closeBudget, replaceModal } from 'loot-core/src/client/actions';
import { replaceModal } from 'loot-core/src/client/actions';
import * as Platform from 'loot-core/src/client/platform';

import { useGlobalPref } from '../../hooks/useGlobalPref';
import { useLocalPref } from '../../hooks/useLocalPref';
import { useMetadataPref } from '../../hooks/useMetadataPref';
import { useNavigate } from '../../hooks/useNavigate';
import { useResizeObserver } from '../../hooks/useResizeObserver';
import { SvgExpandArrow } from '../../icons/v0';
import { SvgAdd } from '../../icons/v1';
import { styles, theme } from '../../style';
import { Button } from '../common/Button2';
import { InitialFocus } from '../common/InitialFocus';
import { Input } from '../common/Input';
import { Menu } from '../common/Menu';
import { Popover } from '../common/Popover';
import { Text } from '../common/Text';
import { View } from '../common/View';
import { useResponsive } from '../responsive/ResponsiveProvider';

import { Accounts } from './Accounts';
import { BudgetName } from './BudgetName';
import { PrimaryButtons } from './PrimaryButtons';
import { SecondaryButtons } from './SecondaryButtons';
import { useSidebar } from './SidebarProvider';
Expand Down Expand Up @@ -112,28 +104,11 @@ export function Sidebar() {
...styles.darkScrollbar,
})}
>
<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' }} />

<BudgetName>
{!sidebar.alwaysFloats && (
<ToggleButton isFloating={isFloating} onFloat={onFloat} />
)}
</View>
</BudgetName>

<View
style={{
Expand All @@ -157,94 +132,3 @@ export function Sidebar() {
</Resizable>
);
}

function EditableBudgetName() {
const { t } = useTranslation();
const dispatch = useDispatch();
const navigate = useNavigate();
const [budgetName, setBudgetNamePref] = useMetadataPref('budgetName');
const [editing, setEditing] = useState(false);
const [menuOpen, setMenuOpen] = useState(false);
const triggerRef = useRef(null);

function onMenuSelect(type: string) {
setMenuOpen(false);

switch (type) {
case 'rename':
setEditing(true);
break;
case 'settings':
navigate('/settings');
break;
case 'help':
window.open('https://actualbudget.org/docs/', '_blank');
break;
case 'close':
dispatch(closeBudget());
break;
default:
}
}

const items = [
{ name: 'rename', text: t('Rename budget') },
{ name: 'settings', text: t('Settings') },
{ name: 'close', text: t('Close file') },
];

if (editing) {
return (
<InitialFocus>
<Input
style={{
width: 160,
fontSize: 16,
fontWeight: 500,
}}
defaultValue={budgetName}
onEnter={async e => {
const inputEl = e.target as HTMLInputElement;
const newBudgetName = inputEl.value;
if (newBudgetName.trim() !== '') {
setBudgetNamePref(newBudgetName);
setEditing(false);
}
}}
onBlur={() => setEditing(false)}
/>
</InitialFocus>
);
}

return (
<>
<Button
ref={triggerRef}
variant="bare"
style={{
color: theme.buttonNormalBorder,
fontSize: 16,
fontWeight: 500,
marginLeft: -5,
flex: '0 auto',
}}
onPress={() => setMenuOpen(true)}
>
<Text style={{ whiteSpace: 'nowrap', overflow: 'hidden' }}>
{budgetName || t('A budget has no name')}
</Text>
<SvgExpandArrow width={7} height={7} style={{ marginLeft: 5 }} />
</Button>

<Popover
triggerRef={triggerRef}
placement="bottom start"
isOpen={menuOpen}
onOpenChange={() => setMenuOpen(false)}
>
<Menu onMenuSelect={onMenuSelect} items={items} />
</Popover>
</>
);
}
6 changes: 6 additions & 0 deletions upcoming-release-notes/3593.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
category: Enhancements
authors: [tlesicka]
---

Refactored Sidebar components. Budget rename input box is now responsive.

0 comments on commit aefd950

Please sign in to comment.