From 27a31c7b68711de52cf5a8ffb0a480b1f37fe2bb Mon Sep 17 00:00:00 2001 From: Neil <55785687+carkom@users.noreply.github.com> Date: Mon, 7 Aug 2023 19:04:33 +0100 Subject: [PATCH] Dark mode filters/rules/transactions (#1436) --- .../src/components/ManageRules.js | 75 ++++---- .../src/components/common/Input.tsx | 5 +- .../src/components/common/Menu.tsx | 20 +- .../src/components/common/Modal.tsx | 13 +- .../src/components/common/Select.tsx | 61 ++++++- .../src/components/filters/FiltersMenu.js | 84 +++++---- .../src/components/filters/SavedFilters.js | 6 +- .../desktop-client/src/components/forms.tsx | 24 +-- .../src/components/modals/EditRule.js | 56 +++--- .../select/RecurringSchedulePicker.js | 20 +- .../desktop-client/src/components/sort.js | 4 +- .../desktop-client/src/components/table.tsx | 171 ++++++++++-------- .../desktop-client/src/components/tooltips.js | 5 +- .../transactions/SimpleTransactionsTable.js | 4 +- .../transactions/TransactionList.js | 3 +- .../transactions/TransactionsTable.js | 147 ++++++++------- packages/desktop-client/src/style/styles.ts | 55 +++--- .../desktop-client/src/style/themes/dark.ts | 12 +- .../desktop-client/src/style/themes/light.ts | 55 ++++-- upcoming-release-notes/1436.md | 5 + 20 files changed, 472 insertions(+), 353 deletions(-) create mode 100644 upcoming-release-notes/1436.md diff --git a/packages/desktop-client/src/components/ManageRules.js b/packages/desktop-client/src/components/ManageRules.js index 2dc1b21da88..9b1f229908f 100644 --- a/packages/desktop-client/src/components/ManageRules.js +++ b/packages/desktop-client/src/components/ManageRules.js @@ -29,7 +29,7 @@ import useSelected, { SelectedProvider, } from '../hooks/useSelected'; import ArrowRight from '../icons/v0/RightArrow2'; -import { colors } from '../style'; +import { theme } from '../style'; import Button from './common/Button'; import ExternalLink from './common/ExternalLink'; @@ -40,6 +40,9 @@ import Text from './common/Text'; import View from './common/View'; import { SelectCell, Row, Field, Cell, CellButton, TableHeader } from './table'; +let valueStyle = { + color: theme.pageTextPositive, +}; let SchedulesQuery = liveQueryContext(q('schedules').select('*')); export function Value({ @@ -133,11 +136,11 @@ export function Value({ if (Array.isArray(value)) { if (value.length === 0) { - return (empty); + return (empty); } else if (value.length === 1) { return ( - [{formatValue(value[0])}] + [{formatValue(value[0])}] ); } @@ -148,10 +151,10 @@ export function Value({ } let numHidden = value.length - displayed.length; return ( - + [ {displayed.map((v, i) => { - let text = {formatValue(v)}; + let text = {formatValue(v)}; let spacing; if (inline) { spacing = i !== 0 ? ' ' : ''; @@ -174,9 +177,9 @@ export function Value({ ); })} {numHidden > 0 && ( - +    - + {numHidden} more items... {!inline &&
} @@ -189,12 +192,12 @@ export function Value({ // An "in between" type return ( - {formatValue(value.num1)} and{' '} - {formatValue(value.num2)} + {formatValue(value.num1)} and{' '} + {formatValue(value.num2)} ); } else { - return {formatValue(value)}; + return {formatValue(value)}; } } @@ -213,7 +216,8 @@ function ConditionExpression({ { display: 'block', maxWidth: '100%', - backgroundColor: colors.n10, + color: theme.altPillText, + backgroundColor: theme.altPillBackground, borderRadius: 4, padding: '3px 5px', whiteSpace: 'nowrap', @@ -223,9 +227,9 @@ function ConditionExpression({ style, ]} > - {prefix && {prefix} } - {mapField(field, options)}{' '} - {friendlyOp(op)}{' '} + {prefix && {prefix} } + {mapField(field, options)}{' '} + {friendlyOp(op)}{' '} ); @@ -261,7 +265,8 @@ function ActionExpression({ field, op, value, options, style }) { { display: 'block', maxWidth: '100%', - backgroundColor: colors.n10, + color: theme.altPillText, + backgroundColor: theme.altPillBackground, borderRadius: 4, padding: '3px 5px', whiteSpace: 'nowrap', @@ -273,15 +278,14 @@ function ActionExpression({ field, op, value, options, style }) { > {op === 'set' ? ( <> - {friendlyOp(op)}{' '} - {mapField(field, options)}{' '} - to + {friendlyOp(op)}{' '} + {mapField(field, options)}{' '} + to ) : op === 'link-schedule' ? ( <> - {friendlyOp(op)}{' '} - + {friendlyOp(op)} ) : null} @@ -290,17 +294,22 @@ function ActionExpression({ field, op, value, options, style }) { let Rule = memo(({ rule, hovered, selected, onHover, onEditRule }) => { let dispatchSelected = useSelectedDispatch(); - let borderColor = selected ? colors.b8 : colors.border; + let borderColor = selected ? theme.tableBorderSelected : 'none'; let backgroundFocus = hovered; return ( onHover && onHover(rule.id)} onMouseLeave={() => onHover && onHover(null)} @@ -314,14 +323,14 @@ let Rule = memo(({ rule, hovered, selected, onHover, onEditRule }) => { selected={selected} /> - + {rule.stage && ( { - + diff --git a/packages/desktop-client/src/components/common/Input.tsx b/packages/desktop-client/src/components/common/Input.tsx index 2b09d772aa0..c55c6ac15ac 100644 --- a/packages/desktop-client/src/components/common/Input.tsx +++ b/packages/desktop-client/src/components/common/Input.tsx @@ -9,11 +9,12 @@ import { type HTMLPropsWithStyle } from '../../types/utils'; export const defaultInputStyle = { outline: 0, - backgroundColor: 'white', + backgroundColor: theme.tableBackground, + color: theme.formInputText, margin: 0, padding: 5, borderRadius: 4, - border: '1px solid #d0d0d0', + border: '1px solid ' + theme.formInputBorder, }; type InputProps = HTMLPropsWithStyle & { diff --git a/packages/desktop-client/src/components/common/Menu.tsx b/packages/desktop-client/src/components/common/Menu.tsx index 59ad018bf64..06d7d472c82 100644 --- a/packages/desktop-client/src/components/common/Menu.tsx +++ b/packages/desktop-client/src/components/common/Menu.tsx @@ -6,7 +6,7 @@ import { useState, } from 'react'; -import { colors } from '../../style'; +import { theme } from '../../style'; import Text from './Text'; import View from './View'; @@ -16,7 +16,11 @@ type KeybindingProps = { }; function Keybinding({ keyName }: KeybindingProps) { - return {keyName}; + return ( + + {keyName} + + ); } type MenuItem = { @@ -106,7 +110,7 @@ export default function Menu({ if (item === Menu.line) { return ( - + ); } else if (item.type === Menu.label) { @@ -114,7 +118,7 @@ export default function Menu({ setHoveredIndex(idx)} onMouseLeave={() => setHoveredIndex(null)} diff --git a/packages/desktop-client/src/components/common/Modal.tsx b/packages/desktop-client/src/components/common/Modal.tsx index 863c4208e9b..99515a20100 100644 --- a/packages/desktop-client/src/components/common/Modal.tsx +++ b/packages/desktop-client/src/components/common/Modal.tsx @@ -11,7 +11,7 @@ import hotkeys from 'hotkeys-js'; import AnimatedLoading from '../../icons/AnimatedLoading'; import Delete from '../../icons/v0/Delete'; -import { styles, colors } from '../../style'; +import { styles, theme } from '../../style'; import tokens from '../../tokens'; import Button from './Button'; @@ -124,7 +124,9 @@ const Modal = ({ minWidth: '100%', minHeight: 0, borderRadius: 4, - backgroundColor: 'white', + //border: '1px solid ' + theme.modalBorder, + color: theme.pageText, + backgroundColor: theme.modalBackground, opacity: isHidden ? 0 : 1, [`@media (min-width: ${tokens.breakpoint_small})`]: { minWidth: tokens.breakpoint_small, @@ -146,7 +148,6 @@ const Modal = ({ {showTitle && ( - + )} @@ -211,7 +212,7 @@ const Modal = ({ left: 0, right: 0, bottom: 0, - backgroundColor: 'rgba(255, 255, 255, .6)', + backgroundColor: theme.pageBackground, alignItems: 'center', justifyContent: 'center', zIndex: 1000, @@ -219,7 +220,7 @@ const Modal = ({ > )} diff --git a/packages/desktop-client/src/components/common/Select.tsx b/packages/desktop-client/src/components/common/Select.tsx index e3d57c91a26..fb1b984d066 100644 --- a/packages/desktop-client/src/components/common/Select.tsx +++ b/packages/desktop-client/src/components/common/Select.tsx @@ -8,9 +8,10 @@ import { import { type CSSProperties, css } from 'glamor'; import ExpandArrow from '../../icons/v0/ExpandArrow'; -import { colors } from '../../style'; +import { theme, styles } from '../../style'; type SelectProps = { + bare?: boolean; options: Array<[Value, string]>; value: Value; defaultLabel?: string; @@ -37,6 +38,7 @@ type SelectProps = { */ export default function Select({ + bare, options, value, defaultLabel = '', @@ -47,19 +49,38 @@ export default function Select({ disabledKeys = [], }: SelectProps) { const arrowSize = 7; + const checkHeight = !style + ? '18px' + : style.minHeight + ? style.minHeight + : !style[0] + ? '18px' + : style[0].minHeight ?? '18px'; const targetOption = options.filter(option => option[0] === value); return ( } + {...css([{ borderWidth: 0, padding: 5, borderRadius: 4 }, style])} + arrow={ + + } > ({ textOverflow: 'ellipsis', whiteSpace: 'nowrap', maxWidth: `calc(100% - ${arrowSize + 5}px)`, - minHeight: '18px', alignItems: 'center', + minHeight: checkHeight, }} > {targetOption.length !== 0 ? targetOption[0][1] : defaultLabel} - + {!line ? ( {options.map(([value, label]) => ( @@ -103,7 +144,7 @@ export default function Select({ style={{ padding: '2px', marginTop: 5, - borderTop: '1px solid ' + colors.n10, + borderTop: '1px solid ' + theme.menuBorder, }} /> {options.slice(line, options.length).map(([value, label]) => ( diff --git a/packages/desktop-client/src/components/filters/FiltersMenu.js b/packages/desktop-client/src/components/filters/FiltersMenu.js index 3397be89c2c..f503c1032f9 100644 --- a/packages/desktop-client/src/components/filters/FiltersMenu.js +++ b/packages/desktop-client/src/components/filters/FiltersMenu.js @@ -25,7 +25,7 @@ import { titleFirst } from 'loot-core/src/shared/util'; import DeleteIcon from '../../icons/v0/Delete'; import SettingsSliderAlternate from '../../icons/v2/SettingsSliderAlternate'; -import { colors } from '../../style'; +import { theme } from '../../style'; import Button from '../common/Button'; import Menu from '../common/Menu'; import Select from '../common/Select'; @@ -96,11 +96,14 @@ function OpButton({ op, selected, style, onClick }) { )} {onAdd && ( @@ -139,7 +142,7 @@ function EditorButtons({ onAdd, onDelete, style }) { style={{ padding: 7 }} aria-label="Add entry" > - + )} @@ -152,7 +155,7 @@ function FieldError({ type }) { style={{ fontSize: 12, textAlign: 'center', - color: colors.r5, + color: theme.errorText, marginBottom: 5, }} > @@ -277,7 +280,11 @@ function ScheduleDescription({ id }) { }} > Payee:{' '} - +
@@ -334,7 +341,12 @@ function ActionEditor({ ops, action, editorStyle, onChange, onDelete, onAdd }) { ) : op === 'link-schedule' ? ( <> - + {friendlyOp(op)} @@ -361,7 +373,7 @@ function StageInfo() { onMouseLeave={() => setOpen(false)} > {open && ( @@ -369,7 +381,7 @@ function StageInfo() { position="bottom-left" style={{ padding: 10, - color: colors.n4, + color: theme.pageTextLight, maxWidth: 450, lineHeight: 1.5, }} @@ -390,8 +402,8 @@ function StageButton({ selected, children, style, onSelect }) { style={[ { fontSize: 'inherit' }, selected && { - backgroundColor: colors.b9, - ':hover': { backgroundColor: colors.b9 }, + backgroundColor: theme.pillBackgroundSelected, + ':hover': { backgroundColor: theme.pillBackgroundSelected }, }, style, ]} @@ -743,7 +755,8 @@ export default function EditRule({ } let editorStyle = { - backgroundColor: colors.n10, + color: theme.altPillText, + backgroundColor: theme.altPillBackground, borderRadius: 4, }; @@ -764,6 +777,7 @@ export default function EditRule({ flexShrink: 0, flexBasis: 'auto', overflow: 'hidden', + color: theme.pageTextLight, }} > - - Stage of rule: - + Stage of rule: - + If - + Then apply these actions: @@ -879,7 +891,7 @@ export default function EditRule({ marginBottom: 12, }} > - + This rule applies to these transactions: @@ -895,7 +907,7 @@ export default function EditRule({ [opt.id, opt.name])} value={config.frequency} onChange={value => updateField('frequency', value)} - style={{ borderWidth: 1, height: 27.5 }} + style={{ border: '1px solid ' + theme.formInputBorder, height: 27.5 }} /> {config.frequency === 'monthly' && (config.patterns == null || config.patterns.length === 0) ? ( - ) : null} diff --git a/packages/desktop-client/src/components/sort.js b/packages/desktop-client/src/components/sort.js index be4fa3d242d..768cb855f63 100644 --- a/packages/desktop-client/src/components/sort.js +++ b/packages/desktop-client/src/components/sort.js @@ -9,7 +9,7 @@ import React, { } from 'react'; import { useDrag, useDrop } from 'react-dnd'; -import { colors } from '../style'; +import { theme } from '../style'; import View from './common/View'; @@ -123,7 +123,7 @@ export function DropHighlight({ pos, offset = {} }) { right: 2, borderRadius: 3, height: 3, - background: `linear-gradient(90deg, ${colors.b4} 0%, ${colors.b5} 100%)`, + background: theme.pageTextLink, zIndex: 10000, pointerEvents: 'none', }, diff --git a/packages/desktop-client/src/components/table.tsx b/packages/desktop-client/src/components/table.tsx index b8d7a458782..d6ee64c4d17 100644 --- a/packages/desktop-client/src/components/table.tsx +++ b/packages/desktop-client/src/components/table.tsx @@ -28,7 +28,7 @@ import AnimatedLoading from '../icons/AnimatedLoading'; import DeleteIcon from '../icons/v0/Delete'; import ExpandArrow from '../icons/v0/ExpandArrow'; import Checkmark from '../icons/v1/Checkmark'; -import { styles, colors } from '../style'; +import { styles, theme } from '../style'; import Button from './common/Button'; import Input from './common/Input'; @@ -48,7 +48,6 @@ import useSheetValue from './spreadsheet/useSheetValue'; import { Tooltip, IntersectionBoundary } from './tooltips'; export const ROW_HEIGHT = 32; -const TABLE_BACKGROUND_COLOR = colors.n11; function fireBlur(onBlur, e) { if (document.hasFocus()) { @@ -63,8 +62,8 @@ function fireBlur(onBlur, e) { } const CellContext = createContext({ - backgroundColor: 'white', - borderColor: colors.n9, + backgroundColor: theme.tableBackground, + borderColor: theme.tableBorder, }); type CellProviderProps = { @@ -96,26 +95,10 @@ type FieldProps = ComponentProps & { contentStyle?: CSSProperties; }; export const Field = forwardRef(function Field( - { - width, - name, - borderColor: oldBorderColor, - truncate = true, - children, - style, - contentStyle, - ...props - }, + { width, name, truncate = true, children, style, contentStyle, ...props }, ref, ) { let { backgroundColor, borderColor } = useContext(CellContext); - - // TODO: Get rid of this. Go through and remove all the places where - // the border color is manually passed in. - if (oldBorderColor) { - borderColor = oldBorderColor; - } - return ( & { highlighted?: boolean; }; export function Row({ - backgroundColor = 'white', - borderColor = colors.border, + backgroundColor = theme.tableBackground, + borderColor = theme.tableBorder, inset = 0, collapsed, focused, @@ -378,8 +363,10 @@ export function Row({ return ( & { @@ -605,6 +591,8 @@ export function DeleteCell({ onDelete, style, ...props }: DeleteCellProps) { type CellButtonProps = { style?: CSSProperties; + primary?: boolean; + bare?: boolean; disabled?: boolean; clickBehavior?: string; onSelect?: (e) => void; @@ -612,7 +600,19 @@ type CellButtonProps = { children: ReactNode; }; export const CellButton = forwardRef( - ({ style, disabled, clickBehavior, onSelect, onEdit, children }, ref) => { + ( + { + style, + primary, + bare, + disabled, + clickBehavior, + onSelect, + onEdit, + children, + }, + ref, + ) => { // This represents a cell that acts like a button: it's clickable, // focusable, etc. The reason we don't use a button is because the // full behavior is undesirable: we really don't want stuff like @@ -645,10 +645,34 @@ export const CellButton = forwardRef( alignItems: 'center', cursor: 'default', transition: 'box-shadow .15s', - ':focus': { - outline: 0, - boxShadow: `0 0 0 3px white, 0 0 0 5px ${colors.b5}`, - }, + backgroundColor: bare + ? 'transparent' + : disabled // always use disabled before primary since we can have a disabled primary button + ? theme.buttonNormalDisabledBackground + : primary + ? theme.buttonPrimaryBackground + : theme.buttonNormalBackground, + border: bare + ? 'none' + : '1px solid ' + + (disabled + ? theme.buttonNormalDisabledBorder + : primary + ? theme.buttonPrimaryBorder + : theme.buttonNormalBorder), + color: bare + ? 'inherit' + : disabled + ? theme.buttonNormalDisabledText + : primary + ? theme.buttonPrimaryText + : theme.buttonNormalText, + ':focus': bare + ? null + : { + outline: 0, + boxShadow: `1px 1px 2px ${theme.buttonNormalShadow}`, + }, }, style, ]} @@ -679,7 +703,6 @@ type SelectCellProps = Omit, 'children'> & { export function SelectCell({ focused, selected, - partial, style, onSelect, onEdit, @@ -700,26 +723,24 @@ export function SelectCell({ > {() => ( {headers ? headers.map(header => { @@ -870,10 +887,14 @@ export function SelectedItemsButton({ name, keyHandlers, items, onSelect }) { @@ -881,7 +902,7 @@ export function SelectedItemsButton({ name, keyHandlers, items, onSelect }) { setMenuOpen(false)} > ( contentHeader, loading, rowHeight = ROW_HEIGHT, - backgroundColor = TABLE_BACKGROUND_COLOR, + backgroundColor = theme.tableHeaderBackground, renderItem, renderEmpty, getItemKey, @@ -1133,7 +1154,7 @@ export const Table = forwardRef( justifyContent: 'center', alignItems: 'center', fontStyle: 'italic', - color: colors.n6, + color: theme.tableText, flex: 1, }} > @@ -1154,7 +1175,7 @@ export const Table = forwardRef( }, ]} > - + ); } @@ -1177,7 +1198,6 @@ export const Table = forwardRef( > {headers && ( @@ -1218,7 +1238,6 @@ export const Table = forwardRef( ? getScrollOffset(height, initialScrollTo.current) : 0 } - version={version} animated={animated} overscanCount={5} onItemsRendered={onItemsRendered} diff --git a/packages/desktop-client/src/components/tooltips.js b/packages/desktop-client/src/components/tooltips.js index 83488b45ccd..059558b2b74 100644 --- a/packages/desktop-client/src/components/tooltips.js +++ b/packages/desktop-client/src/components/tooltips.js @@ -3,7 +3,7 @@ import ReactDOM from 'react-dom'; import { css } from 'glamor'; -import { styles } from '../style'; +import { styles, theme } from '../style'; export const IntersectionBoundary = createContext(); @@ -299,7 +299,8 @@ export class Tooltip extends Component { width, ...styles.shadowLarge, borderRadius: 4, - backgroundColor: 'white', + backgroundColor: theme.menuBackground, + color: theme.menuItemText, // opacity: 0, // transition: 'transform .1s, opacity .1s', // transitionTimingFunction: 'ease-out' diff --git a/packages/desktop-client/src/components/transactions/SimpleTransactionsTable.js b/packages/desktop-client/src/components/transactions/SimpleTransactionsTable.js index d7db23f5a56..c171270bfa2 100644 --- a/packages/desktop-client/src/components/transactions/SimpleTransactionsTable.js +++ b/packages/desktop-client/src/components/transactions/SimpleTransactionsTable.js @@ -15,7 +15,7 @@ import { integerToCurrency } from 'loot-core/src/shared/util'; import { useSelectedItems, useSelectedDispatch } from '../../hooks/useSelected'; import ArrowsSynchronize from '../../icons/v2/ArrowsSynchronize'; -import { styles } from '../../style'; +import { theme, styles } from '../../style'; import { Table, Row, Field, Cell, SelectCell } from '../table'; import DisplayId from '../util/DisplayId'; @@ -47,7 +47,7 @@ const TransactionRow = memo(function TransactionRow({ let dispatchSelected = useSelectedDispatch(); return ( - + !isPreview && onEdit(id, name)} onUpdate={async value => { @@ -684,7 +671,6 @@ const Transaction = memo(function Transaction(props) { let { transaction: originalTransaction, editing, - backgroundColor = 'white', showAccount, showBalance, showCleared, @@ -812,7 +798,6 @@ const Transaction = memo(function Transaction(props) { } let isChild = transaction.is_child; - let borderColor = selected ? colors.b8 : colors.border; let isBudgetTransfer = transferAcct && transferAcct.offbudget === 0; let isOffBudget = account && account.offbudget === 1; @@ -820,48 +805,56 @@ const Transaction = memo(function Transaction(props) { let backgroundFocus = hovered || focusedField === 'select'; let amountStyle = hideFraction ? { letterSpacing: -0.5 } : null; + let statusProps = getStatusProps(notes); + return ( onHover && onHover(transaction.id)} > {isChild && (