Skip to content
Snippets Groups Projects
Unverified Commit 1278746f authored by Jed Fox's avatar Jed Fox Committed by GitHub
Browse files

Further iteration on the sidebar design (#440)

parent 52f19ef8
No related branches found
No related tags found
No related merge requests found
...@@ -94,6 +94,7 @@ function SidebarWithData({ ...@@ -94,6 +94,7 @@ function SidebarWithData({
failedAccounts={failedAccounts} failedAccounts={failedAccounts}
updatedAccounts={updatedAccounts} updatedAccounts={updatedAccounts}
getBalanceQuery={queries.accountBalance} getBalanceQuery={queries.accountBalance}
getAllAccountBalance={queries.allAccountBalance}
getOnBudgetBalance={queries.budgetedAccountBalance} getOnBudgetBalance={queries.budgetedAccountBalance}
getOffBudgetBalance={queries.offbudgetAccountBalance} getOffBudgetBalance={queries.offbudgetAccountBalance}
onFloat={() => saveGlobalPrefs({ floatingSidebar: !floatingSidebar })} onFloat={() => saveGlobalPrefs({ floatingSidebar: !floatingSidebar })}
......
import React, { useState, useMemo, useCallback } from 'react'; import React, { useState, useMemo, useCallback, useEffect } from 'react';
import { RectButton } from 'react-native-gesture-handler'; import { RectButton } from 'react-native-gesture-handler';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import { useLocation, useHistory } from 'react-router'; import { useLocation } from 'react-router';
import { withRouter } from 'react-router-dom'; import { withRouter } from 'react-router-dom';
import { css } from 'glamor'; import { css } from 'glamor';
import { closeBudget } from 'loot-core/src/client/actions/budgets'; import { closeBudget } from 'loot-core/src/client/actions/budgets';
import Platform from 'loot-core/src/client/platform'; import Platform from 'loot-core/src/client/platform';
import PiggyBank from 'loot-design/src/svg/v1/PiggyBank';
import { styles, colors } from '../style'; import { styles, colors } from '../style';
import Add from '../svg/v1/Add'; import Add from '../svg/v1/Add';
import ChevronRight from '../svg/v1/CheveronRight'; import CheveronDown from '../svg/v1/CheveronDown';
import CheveronRight from '../svg/v1/CheveronRight';
import Cog from '../svg/v1/Cog'; import Cog from '../svg/v1/Cog';
import DotsHorizontalTriple from '../svg/v1/DotsHorizontalTriple'; import DotsHorizontalTriple from '../svg/v1/DotsHorizontalTriple';
import LoadBalancer from '../svg/v1/LoadBalancer';
import Reports from '../svg/v1/Reports'; import Reports from '../svg/v1/Reports';
import StoreFrontIcon from '../svg/v1/StoreFront';
import TuningIcon from '../svg/v1/Tuning';
import Wallet from '../svg/v1/Wallet'; import Wallet from '../svg/v1/Wallet';
import Wrench from '../svg/v1/Wrench';
import ArrowButtonLeft1 from '../svg/v2/ArrowButtonLeft1'; import ArrowButtonLeft1 from '../svg/v2/ArrowButtonLeft1';
import CalendarIcon from '../svg/v2/Calendar'; import CalendarIcon from '../svg/v2/Calendar';
import { import {
...@@ -35,9 +37,11 @@ import CellValue from './spreadsheet/CellValue'; ...@@ -35,9 +37,11 @@ import CellValue from './spreadsheet/CellValue';
export const SIDEBAR_WIDTH = 240; export const SIDEBAR_WIDTH = 240;
const fontWeight = 600;
function Item({ function Item({
children, children,
icon, Icon,
title, title,
style, style,
indent = 0, indent = 0,
...@@ -79,7 +83,7 @@ function Item({ ...@@ -79,7 +83,7 @@ function Item({
height: 20 height: 20
}} }}
> >
{icon} <Icon width={15} height={15} style={{ color: 'inherit' }} />
<Block style={{ marginLeft: 8 }}>{title}</Block> <Block style={{ marginLeft: 8 }}>{title}</Block>
<View style={{ flex: 1 }} /> <View style={{ flex: 1 }} />
{button} {button}
...@@ -108,6 +112,70 @@ function Item({ ...@@ -108,6 +112,70 @@ function Item({
); );
} }
function SecondaryItem({
Icon,
title,
style,
to,
exact,
onClick,
bold,
indent = 0
}) {
const hoverStyle = {
backgroundColor: colors.n2
};
const activeStyle = {
borderLeft: '4px solid ' + colors.p8,
paddingLeft: 14 - 4 + indent,
color: colors.p8,
fontWeight: bold ? fontWeight : null
};
const linkStyle = [
accountNameStyle,
{
color: colors.n9,
paddingLeft: 14 + indent,
fontWeight: bold ? fontWeight : null
},
{ ':hover': hoverStyle }
];
const content = (
<View
style={{
flexDirection: 'row',
alignItems: 'center',
height: 16
}}
>
{Icon && <Icon width={12} height={12} style={{ color: 'inherit' }} />}
<Block style={{ marginLeft: Icon ? 8 : 0, color: 'inherit' }}>
{title}
</Block>
</View>
);
return (
<View style={[{ flexShrink: 0 }, style]}>
{onClick ? (
<RectButton onClick={onClick}>
<View style={linkStyle}>{content}</View>
</RectButton>
) : (
<AnchorLink
style={linkStyle}
to={to}
exact={exact}
activeStyle={activeStyle}
>
{content}
</AnchorLink>
)}
</View>
);
}
let accountNameStyle = [ let accountNameStyle = [
{ {
marginTop: -2, marginTop: -2,
...@@ -179,7 +247,7 @@ function Account({ ...@@ -179,7 +247,7 @@ function Account({
// has unread transactions. The system does mark is read and // has unread transactions. The system does mark is read and
// unbolds it, but it still "flashes" bold so this just // unbolds it, but it still "flashes" bold so this just
// ignores it if it's active // ignores it if it's active
fontWeight: 'normal', fontWeight: (style && style.fontWeight) || 'normal',
'& .dot': { '& .dot': {
backgroundColor: colors.p8, backgroundColor: colors.p8,
transform: 'translateX(-4.5px)' transform: 'translateX(-4.5px)'
...@@ -218,7 +286,7 @@ function Account({ ...@@ -218,7 +286,7 @@ function Account({
} }
/> />
</AnchorLink> </AnchorLink>
</View>{' '} </View>
</View> </View>
</View> </View>
); );
...@@ -229,9 +297,11 @@ function Accounts({ ...@@ -229,9 +297,11 @@ function Accounts({
failedAccounts, failedAccounts,
updatedAccounts, updatedAccounts,
getAccountPath, getAccountPath,
allAccountsPath,
budgetedAccountPath, budgetedAccountPath,
offBudgetAccountPath, offBudgetAccountPath,
getBalanceQuery, getBalanceQuery,
getAllAccountBalance,
getOnBudgetBalance, getOnBudgetBalance,
getOffBudgetBalance, getOffBudgetBalance,
showClosedAccounts, showClosedAccounts,
...@@ -269,22 +339,25 @@ function Accounts({ ...@@ -269,22 +339,25 @@ function Accounts({
paddingTop: isDragging ? 15 : 0, paddingTop: isDragging ? 15 : 0,
marginTop: isDragging ? -15 : 0 marginTop: isDragging ? -15 : 0
}; };
} else if (i === length - 1) {
return {
paddingBottom: 15
};
} }
return null; return null;
}; };
return ( return (
<View> <View>
<Account
name="All accounts"
to={allAccountsPath}
query={getAllAccountBalance()}
style={{ fontWeight, marginTop: 15 }}
/>
{budgetedAccounts.length > 0 && ( {budgetedAccounts.length > 0 && (
<Account <Account
name="For budget" name="For budget"
to={budgetedAccountPath} to={budgetedAccountPath}
query={getOnBudgetBalance()} query={getOnBudgetBalance()}
style={{ marginTop: 15, color: colors.n6 }} style={{ fontWeight, marginTop: 13 }}
/> />
)} )}
...@@ -309,7 +382,7 @@ function Accounts({ ...@@ -309,7 +382,7 @@ function Accounts({
name="Off budget" name="Off budget"
to={offBudgetAccountPath} to={offBudgetAccountPath}
query={getOffBudgetBalance()} query={getOffBudgetBalance()}
style={{ color: colors.n6 }} style={{ fontWeight, marginTop: 13 }}
/> />
)} )}
...@@ -330,22 +403,12 @@ function Accounts({ ...@@ -330,22 +403,12 @@ function Accounts({
))} ))}
{closedAccounts.length > 0 && ( {closedAccounts.length > 0 && (
<View <SecondaryItem
style={[ style={{ marginTop: 15 }}
accountNameStyle, title={'Closed accounts' + (showClosedAccounts ? '' : '...')}
{
marginTop: 15,
color: colors.n6,
flexDirection: 'row',
userSelect: 'none',
alignItems: 'center',
flexShrink: 0
}
]}
onClick={onToggleClosedAccounts} onClick={onToggleClosedAccounts}
> bold
{'Closed Accounts' + (showClosedAccounts ? '' : '...')} />
</View>
)} )}
{showClosedAccounts && {showClosedAccounts &&
...@@ -360,6 +423,16 @@ function Accounts({ ...@@ -360,6 +423,16 @@ function Accounts({
onDrop={onReorder} onDrop={onReorder}
/> />
))} ))}
<SecondaryItem
style={{
marginTop: 15,
marginBottom: 9
}}
onClick={onAddAccount}
Icon={Add}
title="Add account"
/>
</View> </View>
); );
} }
...@@ -431,64 +504,49 @@ const MenuButton = withRouter(function MenuButton({ history }) { ...@@ -431,64 +504,49 @@ const MenuButton = withRouter(function MenuButton({ history }) {
function Tools() { function Tools() {
let [isOpen, setOpen] = useState(false); let [isOpen, setOpen] = useState(false);
let location = useLocation();
let history = useHistory();
let onToggle = useCallback(() => setOpen(open => !open), []); let onToggle = useCallback(() => setOpen(open => !open), []);
let location = useLocation();
let items = [ const isActive = ['/payees', '/rules', '/tools'].some(route =>
{ name: 'payees', text: 'Payees' }, location.pathname.startsWith(route)
{ name: 'rules', text: 'Rules' },
{ name: 'repair-splits', text: 'Repair split transactions' }
];
let onMenuSelect = useCallback(
type => {
switch (type) {
case 'payees':
history.push('/payees');
break;
case 'rules':
history.push('/rules');
break;
case 'repair-splits':
history.push('/tools/fix-splits', { locationPtr: history.location });
break;
default:
}
setOpen(false);
},
[history]
); );
useEffect(() => {
if (isActive) {
setOpen(true);
}
}, [location.pathname]);
return ( return (
<View style={{ flexShrink: 0 }}> <View style={{ flexShrink: 0 }}>
<Item <Item
title="More Tools" title="More"
icon={<Wrench width={15} height={15} style={{ color: 'inherit' }} />} Icon={isOpen ? CheveronDown : CheveronRight}
exact={true}
onClick={onToggle} onClick={onToggle}
style={{ pointerEvents: isOpen ? 'none' : 'auto' }} style={{ marginBottom: isOpen ? 8 : 0 }}
forceHover={isOpen} forceActive={!isOpen && isActive}
forceActive={['/payees', '/rules', '/tools'].some(route =>
location.pathname.startsWith(route)
)}
button={
<ChevronRight
width={12}
height={12}
style={{ color: colors.n6, marginRight: 6 }}
/>
}
/> />
{isOpen && ( {isOpen && (
<Tooltip <>
position="right" <SecondaryItem
offset={-8} title="Payees"
style={{ padding: 0 }} Icon={StoreFrontIcon}
onClose={onToggle} to="/payees"
> indent={15}
<Menu onMenuSelect={onMenuSelect} items={items} /> />
</Tooltip> <SecondaryItem
title="Rules"
Icon={TuningIcon}
to="/rules"
indent={15}
/>
<SecondaryItem
title="Repair split transactions"
Icon={LoadBalancer}
to="/tools/fix-splits"
indent={15}
/>
</>
)} )}
</View> </View>
); );
...@@ -501,6 +559,7 @@ export function Sidebar({ ...@@ -501,6 +559,7 @@ export function Sidebar({
failedAccounts, failedAccounts,
updatedAccounts, updatedAccounts,
getBalanceQuery, getBalanceQuery,
getAllAccountBalance,
getOnBudgetBalance, getOnBudgetBalance,
getOffBudgetBalance, getOffBudgetBalance,
showClosedAccounts, showClosedAccounts,
...@@ -589,46 +648,20 @@ export function Sidebar({ ...@@ -589,46 +648,20 @@ export function Sidebar({
</View> </View>
<View style={{ overflow: 'auto' }}> <View style={{ overflow: 'auto' }}>
<Item <Item title="Budget" Icon={Wallet} to="/budget" />
title="Budget" <Item title="Reports" Icon={Reports} to="/reports" />
icon={<Wallet width={15} height={15} style={{ color: 'inherit' }} />}
to="/budget"
/>
<Item
title="Reports"
icon={<Reports width={15} height={15} style={{ color: 'inherit' }} />}
to="/reports"
/>
<Item <Item title="Schedules" Icon={CalendarIcon} to="/schedules" />
title="Schedules"
icon={
<CalendarIcon width={15} height={15} style={{ color: 'inherit' }} />
}
to="/schedules"
/>
<Tools /> <Tools />
<Item <View
title="Accounts" style={{
to="/accounts" height: 1,
icon={ backgroundColor: colors.n3,
<PiggyBank width={15} height={15} style={{ color: 'inherit' }} /> marginTop: 15,
} flexShrink: 0
exact={true} }}
button={
<Button
bare
onClick={e => {
e.stopPropagation();
e.preventDefault();
onAddAccount();
}}
>
<Add width={12} height={12} style={{ color: colors.n6 }} />
</Button>
}
/> />
<Accounts <Accounts
...@@ -636,9 +669,11 @@ export function Sidebar({ ...@@ -636,9 +669,11 @@ export function Sidebar({
failedAccounts={failedAccounts} failedAccounts={failedAccounts}
updatedAccounts={updatedAccounts} updatedAccounts={updatedAccounts}
getAccountPath={account => `/accounts/${account.id}`} getAccountPath={account => `/accounts/${account.id}`}
allAccountsPath="/accounts"
budgetedAccountPath="/accounts/budgeted" budgetedAccountPath="/accounts/budgeted"
offBudgetAccountPath="/accounts/offbudget" offBudgetAccountPath="/accounts/offbudget"
getBalanceQuery={getBalanceQuery} getBalanceQuery={getBalanceQuery}
getAllAccountBalance={getAllAccountBalance}
getOnBudgetBalance={getOnBudgetBalance} getOnBudgetBalance={getOnBudgetBalance}
getOffBudgetBalance={getOffBudgetBalance} getOffBudgetBalance={getOffBudgetBalance}
showClosedAccounts={showClosedAccounts} showClosedAccounts={showClosedAccounts}
......
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