diff --git a/packages/desktop-client/src/components/ManageRules.js b/packages/desktop-client/src/components/ManageRules.js index 2dc1b21da882ad4d176964ffd336a5ec6d8f5d9e..9b1f229908fa842fc29573b324bebe0d2cd8cfbf 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 <Text style={{ color: colors.p4 }}>(empty)</Text>; + return <Text style={valueStyle}>(empty)</Text>; } else if (value.length === 1) { return ( <Text> - [<Text style={{ color: colors.p4 }}>{formatValue(value[0])}</Text>] + [<Text style={valueStyle}>{formatValue(value[0])}</Text>] </Text> ); } @@ -148,10 +151,10 @@ export function Value({ } let numHidden = value.length - displayed.length; return ( - <Text style={{ color: colors.n3 }}> + <Text style={{ color: theme.tableText }}> [ {displayed.map((v, i) => { - let text = <Text style={{ color: colors.p4 }}>{formatValue(v)}</Text>; + let text = <Text style={valueStyle}>{formatValue(v)}</Text>; let spacing; if (inline) { spacing = i !== 0 ? ' ' : ''; @@ -174,9 +177,9 @@ export function Value({ ); })} {numHidden > 0 && ( - <Text style={{ color: colors.p4 }}> + <Text style={valueStyle}> - <LinkButton onClick={onExpand} style={{ color: colors.p4 }}> + <LinkButton onClick={onExpand} style={valueStyle}> {numHidden} more items... </LinkButton> {!inline && <br />} @@ -189,12 +192,12 @@ export function Value({ // An "in between" type return ( <Text> - <Text style={{ color: colors.p4 }}>{formatValue(value.num1)}</Text> and{' '} - <Text style={{ color: colors.p4 }}>{formatValue(value.num2)}</Text> + <Text style={valueStyle}>{formatValue(value.num1)}</Text> and{' '} + <Text style={valueStyle}>{formatValue(value.num2)}</Text> </Text> ); } else { - return <Text style={{ color: colors.p4 }}>{formatValue(value)}</Text>; + return <Text style={valueStyle}>{formatValue(value)}</Text>; } } @@ -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 && <Text style={{ color: colors.n3 }}>{prefix} </Text>} - <Text style={{ color: colors.p4 }}>{mapField(field, options)}</Text>{' '} - <Text style={{ color: colors.n3 }}>{friendlyOp(op)}</Text>{' '} + {prefix && <Text>{prefix} </Text>} + <Text style={valueStyle}>{mapField(field, options)}</Text>{' '} + <Text>{friendlyOp(op)}</Text>{' '} <Value value={value} field={field} inline={inline} /> </View> ); @@ -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' ? ( <> - <Text style={{ color: colors.n3 }}>{friendlyOp(op)}</Text>{' '} - <Text style={{ color: colors.p4 }}>{mapField(field, options)}</Text>{' '} - <Text style={{ color: colors.n3 }}>to </Text> + <Text>{friendlyOp(op)}</Text>{' '} + <Text style={valueStyle}>{mapField(field, options)}</Text>{' '} + <Text>to </Text> <Value value={value} field={field} /> </> ) : op === 'link-schedule' ? ( <> - <Text style={{ color: colors.n3 }}>{friendlyOp(op)}</Text>{' '} - <ScheduleValue value={value} /> + <Text>{friendlyOp(op)}</Text> <ScheduleValue value={value} /> </> ) : null} </View> @@ -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 ( <Row height="auto" - borderColor={borderColor} - backgroundColor={ - selected ? colors.selected : backgroundFocus ? colors.hover : 'white' - } - style={{ fontSize: 13, zIndex: selected ? 101 : 'auto' }} + style={{ + fontSize: 13, + zIndex: selected ? 101 : 'auto', + borderColor, + backgroundColor: selected + ? theme.tableRowBackgroundHighlight + : backgroundFocus + ? theme.tableRowBackgroundHover + : theme.tableBackground, + }} collapsed="true" onMouseEnter={() => onHover && onHover(rule.id)} onMouseLeave={() => onHover && onHover(null)} @@ -314,14 +323,14 @@ let Rule = memo(({ rule, hovered, selected, onHover, onEditRule }) => { selected={selected} /> - <Cell name="stage" width={50} plain style={{ color: colors.n5 }}> + <Cell name="stage" width={50} plain style={{ color: theme.tableText }}> {rule.stage && ( <View style={{ alignSelf: 'flex-start', margin: 5, - backgroundColor: colors.b10, - color: colors.b1, + backgroundColor: theme.pillBackgroundSelected, + color: theme.pillTextSelected, borderRadius: 4, padding: '3px 5px', }} @@ -352,7 +361,9 @@ let Rule = memo(({ rule, hovered, selected, onHover, onEditRule }) => { </View> <Text> - <ArrowRight color={colors.n4} style={{ width: 12, height: 12 }} /> + <ArrowRight + style={{ width: 12, height: 12, color: theme.tableText }} + /> </Text> <View @@ -705,7 +716,7 @@ function ManageRulesContent({ isModal, payeeId, setLoading }) { > <View style={{ - color: colors.n4, + color: theme.pageTextLight, flexDirection: 'row', alignItems: 'center', width: '50%', @@ -750,7 +761,7 @@ function ManageRulesContent({ isModal, payeeId, setLoading }) { style={{ paddingBlock: 15, paddingInline: isModal ? 13 : 0, - borderTop: isModal && '1px solid ' + colors.border, + borderTop: isModal && '1px solid ' + theme.pillBorder, flexShrink: 0, }} > diff --git a/packages/desktop-client/src/components/common/Input.tsx b/packages/desktop-client/src/components/common/Input.tsx index 2b09d772aa0aa4e79c786a4986f008a7eb21294f..c55c6ac15acfdab8e08143c201a8dbd9a9efb4e7 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<HTMLInputElement> & { diff --git a/packages/desktop-client/src/components/common/Menu.tsx b/packages/desktop-client/src/components/common/Menu.tsx index 59ad018bf64a134a39ef845768686dca7e28b483..06d7d472c82568c88f6a19a64cddac6c995d10c3 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 <Text style={{ fontSize: 10, color: colors.n6 }}>{keyName}</Text>; + return ( + <Text style={{ fontSize: 10, color: theme.menuKeybindingText }}> + {keyName} + </Text> + ); } type MenuItem = { @@ -106,7 +110,7 @@ export default function Menu({ if (item === Menu.line) { return ( <View key={idx} style={{ margin: '3px 0px' }}> - <View style={{ borderTop: '1px solid ' + colors.n10 }} /> + <View style={{ borderTop: '1px solid ' + theme.menuBorder }} /> </View> ); } else if (item.type === Menu.label) { @@ -114,7 +118,7 @@ export default function Menu({ <Text key={item.name} style={{ - color: colors.n6, + color: theme.altMenuItemTextHeader, fontSize: 11, lineHeight: '1em', textTransform: 'uppercase', @@ -145,10 +149,14 @@ export default function Menu({ : -3, flexDirection: 'row', alignItems: 'center', + color: theme.menuItemText, }, - item.disabled && { color: colors.n7 }, + item.disabled && { color: theme.buttonBareDisabledText }, !item.disabled && - hoveredIndex === idx && { backgroundColor: colors.n10 }, + hoveredIndex === idx && { + backgroundColor: theme.menuItemBackgroundHover, + color: theme.menuItemTextHover, + }, ]} onMouseEnter={() => 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 863c4208e9bbd258d4b8917dd3ffaba85c2ca498..99515a201007f5cf85831134227bb55f7da19ce9 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 && ( <View style={{ - color: colors.n2, flex: 1, alignSelf: 'center', textAlign: 'center', @@ -193,7 +194,7 @@ const Modal = ({ style={{ padding: '10px 10px' }} aria-label="Close" > - <Delete width={10} /> + <Delete width={10} style={{ color: 'inherit' }} /> </Button> )} </View> @@ -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 = ({ > <AnimatedLoading style={{ width: 20, height: 20 }} - color={colors.n1} + color={theme.pageText} /> </View> )} diff --git a/packages/desktop-client/src/components/common/Select.tsx b/packages/desktop-client/src/components/common/Select.tsx index e3d57c91a26788e115722eb1aef3a4c84f934759..fb1b984d066aea3700422a09b57223991652fc28 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<Value extends string> = { + bare?: boolean; options: Array<[Value, string]>; value: Value; defaultLabel?: string; @@ -37,6 +38,7 @@ type SelectProps<Value extends string> = { */ export default function Select<Value extends string>({ + bare, options, value, defaultLabel = '', @@ -47,19 +49,38 @@ export default function Select<Value extends string>({ disabledKeys = [], }: SelectProps<Value>) { 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 ( <ListboxInput value={value} onChange={onChange} - style={{ lineHeight: '1em', ...wrapperStyle }} + style={{ + color: bare ? 'inherit' : theme.formInputText, + backgroundColor: bare ? 'transparent' : theme.cardBackground, + borderRadius: styles.menuBorderRadius, + border: bare ? 'none' : '1px solid ' + theme.formInputBorder, + lineHeight: '1em', + ...wrapperStyle, + }} > <ListboxButton - {...css([ - { borderWidth: 0, padding: '2px 5px', borderRadius: 4 }, - style, - ])} - arrow={<ExpandArrow style={{ width: arrowSize, height: arrowSize }} />} + {...css([{ borderWidth: 0, padding: 5, borderRadius: 4 }, style])} + arrow={ + <ExpandArrow + style={{ + width: arrowSize, + height: arrowSize, + color: 'inherit', + }} + /> + } > <span style={{ @@ -68,14 +89,34 @@ export default function Select<Value extends string>({ textOverflow: 'ellipsis', whiteSpace: 'nowrap', maxWidth: `calc(100% - ${arrowSize + 5}px)`, - minHeight: '18px', alignItems: 'center', + minHeight: checkHeight, }} > {targetOption.length !== 0 ? targetOption[0][1] : defaultLabel} </span> </ListboxButton> - <ListboxPopover style={{ zIndex: 10000, outline: 0, borderRadius: 4 }}> + <ListboxPopover + style={{ + zIndex: 10000, + outline: 0, + borderRadius: styles.menuBorderRadius, + backgroundColor: theme.menuBackground, + color: theme.menuItemText, + boxShadow: styles.cardShadow, + border: '1px solid ' + theme.menuBorder, + }} + {...css({ + '[data-reach-listbox-option]': { + background: theme.menuItemBackground, + color: theme.menuItemText, + }, + '[data-reach-listbox-option][data-current-nav]': { + background: theme.menuItemBackgroundHover, + color: theme.menuItemTextHover, + }, + })} + > {!line ? ( <ListboxList style={{ maxHeight: 250, overflowY: 'auto' }}> {options.map(([value, label]) => ( @@ -103,7 +144,7 @@ export default function Select<Value extends string>({ 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 3397be89c2c270ef4de54fce6f0c56b6a5f2c263..f503c1032f9b074346f8dd8e1be7779d2a946da1 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 }) { <Button type="bare" style={[ - { backgroundColor: colors.n10, marginBottom: 5 }, + { backgroundColor: theme.altbuttonMenuBackground, marginBottom: 5 }, style, selected && { - color: 'white', - '&,:hover,:active': { backgroundColor: colors.b4 }, + color: theme.buttonNormalSelectedText, + '&,:hover,:active': { + backgroundColor: theme.buttonNormalSelectedBackground, + color: theme.buttonNormalSelectedText, + }, }, ]} onClick={onClick} @@ -170,47 +173,50 @@ function ConfigureField({ return ( <Tooltip position="bottom-left" - style={{ padding: 15 }} + style={{ padding: 15, color: theme.altmenuItemTextHeader }} width={275} onClose={() => dispatch({ type: 'close' })} > <FocusScope> <View style={{ marginBottom: 10 }}> - {field === 'amount' || field === 'date' ? ( - <Select - options={ - field === 'amount' - ? [ - ['amount', 'Amount'], - ['amount-inflow', 'Amount (inflow)'], - ['amount-outflow', 'Amount (outflow)'], - ] - : field === 'date' - ? [ - ['date', 'Date'], - ['month', 'Month'], - ['year', 'Year'], - ] - : null - } - value={subfield} - onChange={sub => { - setSubfield(sub); - - if (sub === 'month' || sub === 'year') { - dispatch({ type: 'set-op', op: 'is' }); + <Stack direction="row" align="flex-start"> + {field === 'amount' || field === 'date' ? ( + <Select + options={ + field === 'amount' + ? [ + ['amount', 'Amount'], + ['amount-inflow', 'Amount (inflow)'], + ['amount-outflow', 'Amount (outflow)'], + ] + : field === 'date' + ? [ + ['date', 'Date'], + ['month', 'Month'], + ['year', 'Year'], + ] + : null } - }} - style={{ borderWidth: 1 }} - /> - ) : ( - titleFirst(mapField(field)) - )} + value={subfield} + onChange={sub => { + setSubfield(sub); + + if (sub === 'month' || sub === 'year') { + dispatch({ type: 'set-op', op: 'is' }); + } + }} + style={{ borderWidth: 1 }} + /> + ) : ( + titleFirst(mapField(field)) + )} + <View style={{ flex: 1 }} /> + </Stack> </View> <View style={{ - color: colors.n4, + color: theme.pageTextLight, marginBottom: 10, }} > @@ -494,7 +500,7 @@ function FilterExpression({ <View style={[ { - backgroundColor: colors.n9, + backgroundColor: theme.pillBackground, borderRadius: 4, flexDirection: 'row', alignItems: 'center', @@ -512,13 +518,13 @@ function FilterExpression({ > <div style={{ paddingBlock: 1, paddingLeft: 5, paddingRight: 2 }}> {customName ? ( - <Text style={{ color: colors.p4 }}>{customName}</Text> + <Text style={{ color: theme.pageTextPositive }}>{customName}</Text> ) : ( <> - <Text style={{ color: colors.p4 }}> + <Text style={{ color: theme.pageTextPositive }}> {mapField(field, options)} </Text>{' '} - <Text style={{ color: colors.n3 }}>{friendlyOp(op, null)}</Text>{' '} + <Text>{friendlyOp(op, null)}</Text>{' '} <Value value={value} field={field} diff --git a/packages/desktop-client/src/components/filters/SavedFilters.js b/packages/desktop-client/src/components/filters/SavedFilters.js index 38b16ce506cbcf56ecf4342370f3a3803c074a11..782ebcef8b94fbc89c145c3be06e85d1df6dd218 100644 --- a/packages/desktop-client/src/components/filters/SavedFilters.js +++ b/packages/desktop-client/src/components/filters/SavedFilters.js @@ -3,7 +3,7 @@ import React, { useState, useRef, useEffect } from 'react'; import { send, sendCatch } from 'loot-core/src/platform/client/fetch'; import ExpandArrow from '../../icons/v0/ExpandArrow'; -import { colors } from '../../style'; +import { theme } from '../../style'; import Button from '../common/Button'; import Menu from '../common/Menu'; import MenuTooltip from '../common/MenuTooltip'; @@ -219,7 +219,7 @@ function SavedFilterMenuButton({ )} {err && ( <Stack direction="row" align="center" style={{ padding: 10 }}> - <Text style={{ color: colors.r4 }}>{err}</Text> + <Text style={{ color: theme.errorText }}>{err}</Text> </Stack> )} </MenuTooltip> @@ -264,7 +264,7 @@ function SavedFilterMenuButton({ export function CondOpMenu({ conditionsOp, onCondOpChange, filters }) { return ( filters.length > 1 && ( - <Text style={{ color: colors.n4, marginTop: 11, marginRight: 5 }}> + <Text style={{ color: theme.pageText, marginTop: 11, marginRight: 5 }}> <FieldSelect style={{ display: 'inline-flex' }} fields={[ diff --git a/packages/desktop-client/src/components/forms.tsx b/packages/desktop-client/src/components/forms.tsx index e60252b5f9666b3a8fd7c299718597025023fb53..8bcf156102c77845be1640a883a36b160bc0cb1d 100644 --- a/packages/desktop-client/src/components/forms.tsx +++ b/packages/desktop-client/src/components/forms.tsx @@ -2,7 +2,7 @@ import React, { type ReactNode, type HTMLProps } from 'react'; import { css, type CSSProperties } from 'glamor'; -import { colors } from '../style'; +import { theme } from '../style'; import Text from './common/Text'; import View from './common/View'; @@ -19,7 +19,7 @@ export const SectionLabel = ({ title, style }: SectionLabelProps) => { { fontWeight: 500, textTransform: 'uppercase', - color: colors.b3, + color: theme.altFormLabelText, marginBottom: 5, lineHeight: '1em', }, @@ -40,7 +40,9 @@ type FormLabelProps = { export const FormLabel = ({ style, title, id, htmlFor }: FormLabelProps) => { return ( - <Text style={[{ fontSize: 13, marginBottom: 3, color: colors.n3 }, style]}> + <Text + style={[{ fontSize: 13, marginBottom: 3, color: theme.tableText }, style]} + > <label htmlFor={htmlFor} id={id}> {title} </label> @@ -78,20 +80,20 @@ export const Checkbox = (props: CheckboxProps) => { height: 15, appearance: 'none', outline: 0, - border: '1px solid #d0d0d0', + border: '1px solid ' + theme.formInputBorder, borderRadius: 4, display: 'flex', alignItems: 'center', justifyContent: 'center', - color: 'white', - backgroundColor: 'white', + color: theme.tableBackground, + backgroundColor: theme.tableBackground, ':checked': { - border: '1px solid ' + colors.b6, - backgroundColor: colors.b6, + border: '1px solid ' + theme.altformInputBorderSelected, + backgroundColor: theme.tableTextEditingBackground, '::after': { display: 'block', background: - colors.b6 + + theme.tableTextEditingBackground + // eslint-disable-next-line rulesdir/typography ' url(\'data:image/svg+xml; utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path fill="white" d="M0 11l2-2 5 5L18 3l2 2L7 18z"/></svg>\') 9px 9px', width: 9, @@ -106,14 +108,14 @@ export const Checkbox = (props: CheckboxProps) => { bottom: -5, left: -5, right: -5, - border: '2px solid ' + colors.b5, + border: '2px solid ' + theme.altformInputBorderSelected, borderRadius: 6, content: ' ', }, }, }, ], - props.style, + props.styles, )} /> ); diff --git a/packages/desktop-client/src/components/modals/EditRule.js b/packages/desktop-client/src/components/modals/EditRule.js index fba46b0c34f31aabba19cb68c33fe63bd0a911af..644d2024759535d7f6dcb0527d863e75fd237c1d 100644 --- a/packages/desktop-client/src/components/modals/EditRule.js +++ b/packages/desktop-client/src/components/modals/EditRule.js @@ -29,7 +29,7 @@ import useSelected, { SelectedProvider } from '../../hooks/useSelected'; import AddIcon from '../../icons/v0/Add'; import SubtractIcon from '../../icons/v0/Subtract'; import InformationOutline from '../../icons/v1/InformationOutline'; -import { colors } from '../../style'; +import { theme } from '../../style'; import Button from '../common/Button'; import Modal from '../common/Modal'; import Select from '../common/Select'; @@ -78,12 +78,12 @@ function getTransactionFields(conditions, actions) { export function FieldSelect({ fields, style, value, onChange }) { return ( - <View style={style}> + <View style={[{ color: theme.pageTextPositive }, style]}> <Select + bare options={fields} value={value} onChange={value => onChange('field', value)} - style={{ color: colors.p4 }} /> </View> ); @@ -93,6 +93,7 @@ export function OpSelect({ ops, type, style, + wrapperStyle, value, formatOp = friendlyOp, onChange, @@ -110,11 +111,13 @@ export function OpSelect({ return ( <Select + bare options={ops.map(op => [op, formatOp(op, type)])} value={value} onChange={value => onChange('op', value)} line={line} - style={style} + style={[{ minHeight: '1px' }, ...style]} + wrapperStyle={wrapperStyle} /> ); } @@ -129,7 +132,7 @@ function EditorButtons({ onAdd, onDelete, style }) { style={{ padding: 7 }} aria-label="Delete entry" > - <SubtractIcon style={{ width: 8, height: 8 }} /> + <SubtractIcon style={{ width: 8, height: 8, color: 'inherit' }} /> </Button> )} {onAdd && ( @@ -139,7 +142,7 @@ function EditorButtons({ onAdd, onDelete, style }) { style={{ padding: 7 }} aria-label="Add entry" > - <AddIcon style={{ width: 10, height: 10 }} /> + <AddIcon style={{ width: 10, height: 10, color: 'inherit' }} /> </Button> )} </> @@ -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:{' '} - <DisplayId type="payees" id={schedule._payee} noneColor={colors.n5} /> + <DisplayId + type="payees" + id={schedule._payee} + noneColor={theme.altpageTextSubdued} + /> </Text> <Text style={{ margin: '0 5px' }}> — </Text> <Text style={{ flexShrink: 0 }}> @@ -334,7 +341,12 @@ function ActionEditor({ ops, action, editorStyle, onChange, onDelete, onAdd }) { </> ) : op === 'link-schedule' ? ( <> - <View style={{ padding: '5px 10px', color: colors.p4 }}> + <View + style={{ + padding: '5px 10px', + color: theme.pageTextPositive, + }} + > {friendlyOp(op)} </View> <ScheduleDescription id={value || null} /> @@ -361,7 +373,7 @@ function StageInfo() { onMouseLeave={() => setOpen(false)} > <InformationOutline - style={{ width: 11, height: 11, color: colors.n4 }} + style={{ width: 11, height: 11, color: theme.pageTextLight }} /> </View> {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, }} > <View @@ -774,9 +788,7 @@ export default function EditRule({ padding: '0 20px', }} > - <Text style={{ color: colors.n4, marginRight: 15 }}> - Stage of rule: - </Text> + <Text style={{ marginRight: 15 }}>Stage of rule:</Text> <Stack direction="row" align="center" spacing={1}> <StageButton @@ -805,7 +817,7 @@ export default function EditRule({ <View innerRef={scrollableEl} style={{ - borderBottom: '1px solid ' + colors.border, + borderBottom: '1px solid ' + theme.tableBorder, padding: 20, overflow: 'auto', maxHeight: 'calc(100% - 300px)', @@ -813,7 +825,7 @@ export default function EditRule({ > <View style={{ flexShrink: 0 }}> <View style={{ marginBottom: 30 }}> - <Text style={{ color: colors.n4, marginBottom: 15 }}> + <Text style={{ marginBottom: 15 }}> If <FieldSelect data-testid="conditions-op" @@ -837,7 +849,7 @@ export default function EditRule({ /> </View> - <Text style={{ color: colors.n4, marginBottom: 15 }}> + <Text style={{ marginBottom: 15 }}> Then apply these actions: </Text> <View style={{ flex: 1 }}> @@ -879,7 +891,7 @@ export default function EditRule({ marginBottom: 12, }} > - <Text style={{ color: colors.n4, marginBottom: 0 }}> + <Text style={{ color: theme.pageTextLight, marginBottom: 0 }}> This rule applies to these transactions: </Text> @@ -895,7 +907,7 @@ export default function EditRule({ <SimpleTransactionsTable transactions={transactions} fields={getTransactionFields(conditions, actions)} - style={{ border: '1px solid ' + colors.border }} + style={{ border: '1px solid ' + theme.tableBorder }} /> <Stack diff --git a/packages/desktop-client/src/components/select/RecurringSchedulePicker.js b/packages/desktop-client/src/components/select/RecurringSchedulePicker.js index 89e9ea370a207d4332a4ef21b26b78ff29b02a5e..83c80ca6425146e823087b27e71bbe140924fe8e 100644 --- a/packages/desktop-client/src/components/select/RecurringSchedulePicker.js +++ b/packages/desktop-client/src/components/select/RecurringSchedulePicker.js @@ -7,7 +7,7 @@ import { getRecurringDescription } from 'loot-core/src/shared/schedules'; import AddIcon from '../../icons/v0/Add'; import SubtractIcon from '../../icons/v0/Subtract'; -import { colors } from '../../style'; +import { colors, theme } from '../../style'; import Button from '../common/Button'; import Input from '../common/Input'; import Select from '../common/Select'; @@ -208,10 +208,7 @@ function MonthlyPatterns({ config, dispatch }) { } disabledKeys={['-']} wrapperStyle={{ flex: 1, marginRight: 10 }} - style={{ - borderWidth: 1, - width: '100%', - }} + style={{ minHeight: '1px', width: '100%' }} /> <Select options={[ @@ -223,7 +220,7 @@ function MonthlyPatterns({ config, dispatch }) { onChange={value => updateRecurrence(recurrence, 'type', value)} disabledKeys={['-']} wrapperStyle={{ flex: 1, marginRight: 10 }} - style={{ borderWidth: 1, width: '100%' }} + style={{ minHeight: '1px', width: '100%' }} /> <Button type="bare" @@ -325,14 +322,21 @@ function RecurringScheduleTooltip({ config: currentConfig, onClose, onSave }) { defaultValue={config.interval || 1} /> <Select + bare options={FREQUENCY_OPTIONS.map(opt => [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) ? ( - <Button onClick={() => dispatch({ type: 'add-recurrence' })}> + <Button + style={{ + backgroundColor: theme.tableBackground, + ':hover': { backgroundColor: theme.tableBackground }, + }} + onClick={() => dispatch({ type: 'add-recurrence' })} + > Add specific days </Button> ) : null} diff --git a/packages/desktop-client/src/components/sort.js b/packages/desktop-client/src/components/sort.js index be4fa3d242d9ab767e20749e6d022b8c4ec4f1f7..768cb855f63dc80420a1211acd0886260882d222 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 b8d7a458782e0d3b6f9071762028d890440dd802..d6ee64c4d170f6e26b4e4a22e729ae21db0d5907 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<typeof View> & { contentStyle?: CSSProperties; }; export const Field = forwardRef<HTMLDivElement, FieldProps>(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 ( <View innerRef={ref} @@ -228,6 +211,8 @@ export function Cell({ // the border color is manually passed in. if (oldBorderColor) { borderColor = oldBorderColor; + } else { + borderColor = theme.tableBorder; } const widthStyle = width === 'flex' ? { flex: 1, flexBasis: 0 } : { width }; @@ -338,8 +323,8 @@ type RowProps = ComponentProps<typeof View> & { 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 ( <CellProvider - backgroundColor={shouldHighlight ? colors.y9 : backgroundColor} - borderColor={shouldHighlight ? colors.y8 : borderColor} + backgroundColor={ + shouldHighlight ? theme.tableRowBackgroundHighlight : backgroundColor + } + borderColor={shouldHighlight ? theme.tableBorderSelected : borderColor} > <View innerRef={rowRef} @@ -408,14 +395,13 @@ export function Row({ } const inputCellStyle = { - backgroundColor: 'white', padding: '5px 3px', margin: '0 1px', }; const readonlyInputStyle = { backgroundColor: 'transparent', - '::selection': { backgroundColor: '#d9d9d9' }, + '::selection': { backgroundColor: theme.formInputTextReadOnlySelection }, }; type InputValueProps = ComponentProps<typeof Input> & { @@ -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<HTMLDivElement, CellButtonProps>( - ({ 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<HTMLDivElement, CellButtonProps>( 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<ComponentProps<typeof Cell>, 'children'> & { export function SelectCell({ focused, selected, - partial, style, onSelect, onEdit, @@ -700,26 +723,24 @@ export function SelectCell({ > {() => ( <CellButton - style={[ - { - width: 12, - height: 12, - border: '1px solid ' + colors.n8, - borderRadius: 3, - justifyContent: 'center', - alignItems: 'center', - - ':focus': { - border: '1px solid ' + colors.b5, - boxShadow: '0 1px 2px ' + colors.b5, - }, - }, - selected && { - backgroundColor: partial ? colors.b9 : colors.b5, - borderColor: partial ? colors.b9 : colors.b5, - color: 'white', + style={{ + width: 12, + height: 12, + justifyContent: 'center', + alignItems: 'center', + borderRadius: 3, + border: selected + ? '1px solid ' + theme.altformInputBorderSelected + : '1px solid ' + theme.formInputBorder, + color: theme.tableBackground, + backgroundColor: selected + ? theme.tableTextEditingBackground + : theme.tableBackground, + ':focus': { + border: '1px solid ' + theme.altformInputBorderSelected, + boxShadow: '0 1px 2px ' + theme.altformInputShadowSelected, }, - ]} + }} onEdit={onEdit} onSelect={onSelect} clickBehavior="none" @@ -817,26 +838,22 @@ export function TableHeader({ }: TableHeaderProps) { return ( <View - style={ - version === 'v2' && { - borderRadius: '6px 6px 0 0', - overflow: 'hidden', - flexShrink: 0, - } - } + style={{ + borderRadius: '6px 6px 0 0', + overflow: 'hidden', + flexShrink: 0, + }} > <Row - backgroundColor="white" - borderColor={colors.border} collapsed={true} {...rowProps} - style={[ - { zIndex: 200 }, - version === 'v2' - ? { color: colors.n4, fontWeight: 500 } - : { color: colors.n4 }, - rowProps.style, - ]} + style={{ + color: theme.tableHeaderText, + backgroundColor: theme.tableHeaderBackground, + zIndex: 200, + fontWeight: 500, + ...rowProps.style, + }} > {headers ? headers.map(header => { @@ -870,10 +887,14 @@ export function SelectedItemsButton({ name, keyHandlers, items, onSelect }) { <Button type="bare" - style={{ color: colors.b3 }} + style={{ color: theme.pageTextPositive }} onClick={() => setMenuOpen(true)} > - <ExpandArrow width={8} height={8} style={{ marginRight: 5 }} /> + <ExpandArrow + width={8} + height={8} + style={{ marginRight: 5, color: theme.pageText }} + /> {selectedItems.size} {name} </Button> @@ -881,7 +902,7 @@ export function SelectedItemsButton({ name, keyHandlers, items, onSelect }) { <Tooltip position="bottom-right" width={200} - style={{ padding: 0 }} + style={{ padding: 0, backgroundColor: 'transparent' }} onClose={() => setMenuOpen(false)} > <Menu @@ -962,7 +983,7 @@ export const Table = forwardRef<TableHandleRef, TableProps>( contentHeader, loading, rowHeight = ROW_HEIGHT, - backgroundColor = TABLE_BACKGROUND_COLOR, + backgroundColor = theme.tableHeaderBackground, renderItem, renderEmpty, getItemKey, @@ -1133,7 +1154,7 @@ export const Table = forwardRef<TableHandleRef, TableProps>( justifyContent: 'center', alignItems: 'center', fontStyle: 'italic', - color: colors.n6, + color: theme.tableText, flex: 1, }} > @@ -1154,7 +1175,7 @@ export const Table = forwardRef<TableHandleRef, TableProps>( }, ]} > - <AnimatedLoading width={25} color={colors.n1} /> + <AnimatedLoading width={25} color={theme.tableText} /> </View> ); } @@ -1177,7 +1198,6 @@ export const Table = forwardRef<TableHandleRef, TableProps>( > {headers && ( <TableHeader - version={version} height={rowHeight} {...(Array.isArray(headers) ? { headers } : { children: headers })} /> @@ -1218,7 +1238,6 @@ export const Table = forwardRef<TableHandleRef, TableProps>( ? 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 83488b45ccddddb28cd361e8981dcb0ff6ffd457..059558b2b74f05f60984e08a9a4578e6a2dbfb63 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 d7db23f5a56222df976d11e6dabfe7884b34f5bf..c171270bfa287c98ffa3e16d595b28f4c4e5ffbb 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 ( - <Row> + <Row style={{ color: theme.tableText }}> <SelectCell exposed={true} focused={false} diff --git a/packages/desktop-client/src/components/transactions/TransactionList.js b/packages/desktop-client/src/components/transactions/TransactionList.js index 96c4445b0127d1251488b830e6d1bf3dfa4d993d..908d6f025e4d307dfb686c8119d6b5c5179fd163 100644 --- a/packages/desktop-client/src/components/transactions/TransactionList.js +++ b/packages/desktop-client/src/components/transactions/TransactionList.js @@ -11,6 +11,7 @@ import { } from 'loot-core/src/shared/transactions'; import { getChangedValues, applyChanges } from 'loot-core/src/shared/util'; +import { theme } from '../../style'; import { usePushModal } from '../../util/router-tools'; import { TransactionTable } from './TransactionsTable'; @@ -198,7 +199,7 @@ export default function TransactionList({ onAddSplit={onAddSplit} onManagePayees={onManagePayees} onCreatePayee={onCreatePayee} - style={{ backgroundColor: 'white' }} + style={{ backgroundColor: theme.tableBackground }} onNavigateToTransferAccount={onNavigateToTransferAccount} onNavigateToSchedule={onNavigateToSchedule} onSort={onSort} diff --git a/packages/desktop-client/src/components/transactions/TransactionsTable.js b/packages/desktop-client/src/components/transactions/TransactionsTable.js index 7c901b5c23530565c573f2894173270789d57a2a..12a6f45fa73f02931860fc24e3368afb2336470c 100644 --- a/packages/desktop-client/src/components/transactions/TransactionsTable.js +++ b/packages/desktop-client/src/components/transactions/TransactionsTable.js @@ -53,7 +53,7 @@ import CheveronDown from '../../icons/v1/CheveronDown'; import ArrowsSynchronize from '../../icons/v2/ArrowsSynchronize'; import CalendarIcon from '../../icons/v2/Calendar'; import Hyperlink2 from '../../icons/v2/Hyperlink2'; -import { styles, colors } from '../../style'; +import { styles, theme } from '../../style'; import AccountAutocomplete from '../autocomplete/AccountAutocomplete'; import CategoryAutocomplete from '../autocomplete/CategorySelect'; import PayeeAutocomplete from '../autocomplete/PayeeAutocomplete'; @@ -266,12 +266,11 @@ const TransactionHeader = memo( return ( <Row - borderColor={colors.n9} - backgroundColor="white" style={{ - color: colors.n4, fontWeight: 300, zIndex: 200, + color: theme.tableHeaderText, + backgroundColor: theme.tableBackground, }} > <SelectCell @@ -418,19 +417,6 @@ function StatusCell({ let isClearedField = status === 'cleared' || status == null; let statusProps = getStatusProps(status); - let props = { - color: - status === 'cleared' - ? colors.g5 - : status === 'missed' - ? colors.r6 - : status === 'due' - ? colors.y5 - : selected - ? colors.b7 - : colors.n7, - }; - function onSelect() { if (isClearedField) { onUpdate('cleared', !(status === 'cleared')); @@ -449,11 +435,12 @@ function StatusCell({ style={[ { padding: 3, + backgroundColor: 'transparent', border: '1px solid transparent', borderRadius: 50, ':focus': { - border: '1px solid ' + props.color, - boxShadow: `0 1px 2px ${props.color}`, + border: '1px solid ' + theme.formInputBorderSelected, + boxShadow: '0 1px 2px ' + theme.formInputBorderSelected, }, cursor: isClearedField ? 'pointer' : 'default', }, @@ -467,7 +454,7 @@ function StatusCell({ style: { width: 13, height: 13, - color: props.color, + color: statusProps.color, marginTop: status === 'due' ? -1 : 0, }, })} @@ -499,7 +486,7 @@ function HeaderCell({ whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', - color: colors.n4, + color: theme.tableHeaderText, fontWeight: 300, marginLeft: marginLeft, marginRight: marginRight, @@ -550,7 +537,7 @@ function PayeeCell({ name="payee" textAlign="flex" value={payeeId} - valueStyle={[valueStyle, inherited && { color: colors.n8 }]} + valueStyle={[valueStyle, inherited && { color: theme.tableTextInactive }]} exposed={focused} onExpose={name => !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 ( <Row - borderColor={borderColor} - backgroundColor={ - selected - ? colors.selected - : backgroundFocus - ? colors.hover - : isPreview - ? '#fcfcfc' - : backgroundColor - } highlighted={highlighted} style={[ + { + backgroundColor: selected + ? theme.tableRowBackgroundHighlight + : backgroundFocus + ? theme.tableRowBackgroundHover + : theme.tableBackground, + }, + highlighted || selected + ? { color: theme.tableRowBackgroundHighlightText } + : { color: theme.tableText }, style, - isPreview && { color: colors.n5, fontStyle: 'italic' }, + isPreview && { + color: theme.tableTextInactive, + fontStyle: 'italic', + }, _unmatched && { opacity: 0.5 }, ]} onMouseEnter={() => onHover && onHover(transaction.id)} > {isChild && ( <Field - borderColor="transparent" + /* Checkmark blank placeholder for Child transaction */ width={110} style={{ width: 110, - backgroundColor: colors.n11, - borderBottomWidth: 0, + backgroundColor: theme.tableRowBackgroundHover, + border: 0, // known z-order issue, bottom border for parent transaction hidden }} /> )} + {isChild && showAccount && ( <Field - borderColor="transparent" + /* Account blank placeholder for Child transaction */ style={{ flex: 1, - backgroundColor: colors.n11, - opacity: 0, + backgroundColor: theme.tableRowBackgroundHover, + border: 0, }} /> )} + {/* Checkmark - for Child transaction + between normal Date and Payee or Account and Payee if needed */} {isTemporaryId(transaction.id) ? ( isChild ? ( <DeleteCell @@ -874,6 +867,7 @@ const Transaction = memo(function Transaction(props) { ) ) : ( <SelectCell + /* Checkmark field for non-child transaction */ exposed={hovered || selected || editing} focused={focusedField === 'select'} onSelect={e => { @@ -884,14 +878,14 @@ const Transaction = memo(function Transaction(props) { style={[isChild && { borderLeftWidth: 1 }]} value={ matched && ( - <Hyperlink2 style={{ width: 13, height: 13, color: colors.n7 }} /> + <Hyperlink2 style={{ width: 13, height: 13, color: 'inherit' }} /> ) } /> )} - {!isChild && ( <CustomCell + /* Date field for non-child transaction */ name="date" width={110} textAlign="flex" @@ -929,6 +923,7 @@ const Transaction = memo(function Transaction(props) { {!isChild && showAccount && ( <CustomCell + /* Account field for non-child transaction */ name="account" width="flex" textAlign="flex" @@ -975,6 +970,7 @@ const Transaction = memo(function Transaction(props) { )} {(() => ( <PayeeCell + /* Payee field for all transactions */ id={id} payeeId={payeeId} accountId={accountId} @@ -998,6 +994,7 @@ const Transaction = memo(function Transaction(props) { ))()} {isPreview ? ( + /* Notes field for all transactions */ <Cell name="notes" width="flex" /> ) : ( <InputCell @@ -1017,26 +1014,13 @@ const Transaction = memo(function Transaction(props) { )} {isPreview ? ( + // Category field for preview transactions <Cell width="flex" style={{ alignItems: 'flex-start' }} exposed={true}> {() => ( <View style={{ - color: - notes === 'missed' - ? colors.r6 - : notes === 'due' - ? colors.y4 - : selected - ? colors.b5 - : colors.n6, - backgroundColor: - notes === 'missed' - ? colors.r10 - : notes === 'due' - ? colors.y9 - : selected - ? colors.b8 - : colors.n10, + color: statusProps.color, + backgroundColor: statusProps.backgroundColor, margin: '0 5px', padding: '3px 7px', borderRadius: 4, @@ -1048,6 +1032,7 @@ const Transaction = memo(function Transaction(props) { </Cell> ) : isParent ? ( <Cell + /* Category field (Split button) for parent transactions */ name="category" width="flex" focused={focusedField === 'category'} @@ -1055,14 +1040,13 @@ const Transaction = memo(function Transaction(props) { plain > <CellButton + bare style={{ alignSelf: 'flex-start', - color: colors.n6, borderRadius: 4, - transition: 'none', - '&:hover': { - backgroundColor: 'rgba(100, 100, 100, .15)', - color: colors.n5, + border: '1px solid transparent', // so it doesn't shift on hover + ':hover': { + border: '1px solid ' + theme.buttonNormalBorder, }, }} disabled={isTemporaryId(transaction.id)} @@ -1082,6 +1066,7 @@ const Transaction = memo(function Transaction(props) { {isParent && ( <CheveronDown style={{ + color: 'inherit', width: 14, height: 14, transition: 'transform .08s', @@ -1097,6 +1082,8 @@ const Transaction = memo(function Transaction(props) { </Cell> ) : isBudgetTransfer || isOffBudget || isPreview ? ( <InputCell + /* Category field for transfer and off-budget transactions + (NOT preview, it is covered first) */ name="category" width="flex" exposed={focusedField === 'category'} @@ -1112,11 +1099,7 @@ const Transaction = memo(function Transaction(props) { : '' } valueStyle={valueStyle} - style={{ - fontStyle: 'italic', - color: '#c0c0c0', - fontWeight: 300, - }} + style={{ fontStyle: 'italic', fontWeight: 300 }} inputProps={{ readOnly: true, style: { fontStyle: 'italic' }, @@ -1124,6 +1107,7 @@ const Transaction = memo(function Transaction(props) { /> ) : ( <CustomCell + /* Category field for normal and child transactions */ name="category" width="flex" textAlign="flex" @@ -1143,9 +1127,10 @@ const Transaction = memo(function Transaction(props) { valueStyle={ !categoryId ? { + // uncategorized transaction fontStyle: 'italic', fontWeight: 300, - color: colors.p8, + color: theme.formInputTextHighlight, } : valueStyle } @@ -1182,6 +1167,7 @@ const Transaction = memo(function Transaction(props) { )} <InputCell + /* Debit field for all transactions */ type="input" width={90} name="debit" @@ -1203,6 +1189,7 @@ const Transaction = memo(function Transaction(props) { /> <InputCell + /* Credit field for all transactions */ type="input" width={85} name="credit" @@ -1225,9 +1212,12 @@ const Transaction = memo(function Transaction(props) { {showBalance && ( <Cell + /* Balance field for all transactions */ name="balance" value={balance == null || isChild ? '' : integerToCurrency(balance)} - valueStyle={{ color: balance < 0 ? colors.r4 : colors.g4 }} + valueStyle={{ + color: balance < 0 ? theme.errorText : theme.noticeText, + }} style={[styles.tnum, amountStyle]} width={88} textAlign="right" @@ -1237,6 +1227,7 @@ const Transaction = memo(function Transaction(props) { {showCleared && ( <StatusCell + /* Icon field for all transactions */ id={id} focused={focusedField === 'cleared'} selected={selected} @@ -1352,9 +1343,9 @@ function NewTransaction({ return ( <View style={{ - borderBottom: '1px solid #ebebeb', + borderBottom: '1px solid ' + theme.tableBorderHover, paddingBottom: 6, - backgroundColor: 'white', + backgroundColor: theme.tableBackground, }} data-testid="new-transaction" onKeyDown={e => { @@ -1569,7 +1560,13 @@ function TransactionTableInner({ return ( <View innerRef={containerRef} - style={[{ flex: 1, cursor: 'default' }, props.style]} + style={[ + { + flex: 1, + cursor: 'default', + }, + props.style, + ]} > <View> <TransactionHeader @@ -1650,7 +1647,7 @@ function TransactionTableInner({ left: 0, right: 0, height: 20, - backgroundColor: 'red', + backgroundColor: theme.errorText, boxShadow: '0 0 6px rgba(0, 0, 0, .20)', }} /> diff --git a/packages/desktop-client/src/style/styles.ts b/packages/desktop-client/src/style/styles.ts index 3355656908a443a2c42fb656f0f892a16fed93a0..0aa951ef22b624a9052782901de5960bb3b7f944 100644 --- a/packages/desktop-client/src/style/styles.ts +++ b/packages/desktop-client/src/style/styles.ts @@ -1,12 +1,23 @@ +import type { CSSProperties } from 'glamor'; import { keyframes } from 'glamor'; import * as Platform from 'loot-core/src/client/platform'; import tokens from '../tokens'; -import * as colors from './colors'; - export const styles = { + incomeHeaderHeight: 70, + cardShadow: '0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24)', + monthRightPadding: 5, + menuBorderRadius: 4, + altMenuMaxHeight: 250, + altMenuText: { + fontSize: 13, + }, + altMenuHeaderText: { + fontSize: 13, + fontWeight: 700, + }, veryLargeText: { fontSize: 30, fontWeight: 600, @@ -22,9 +33,6 @@ export const styles = { }, smallText: { fontSize: 13, - [`@media (min-width: ${tokens.breakpoint_small})`]: { - // lineHeight: 21 // TODO: This seems like trouble, but what's the right value? - }, }, verySmallText: { fontSize: 13, @@ -39,16 +47,6 @@ export const styles = { paddingTop: 36, }, }, - pageHeader: { - fontSize: 25, - borderBottomWidth: 5, - borderStyle: 'solid', - display: 'inline', - flex: 0, - marginTop: 40, - marginBottom: 20, - paddingBottom: 5, - }, pageContent: { paddingLeft: 2, paddingRight: 2, @@ -78,26 +76,11 @@ export const styles = { fontFeatureSettings: '"tnum"', }, notFixed: { fontFeatureSettings: '' }, - header: { - headerStyle: { - backgroundColor: 'white', - borderBottomWidth: 1, - borderBottomColor: colors.n9, - elevation: 0, - }, - headerTintColor: colors.n1, - headerTitleStyle: { - color: colors.n1, - fontSize: 15, - fontWeight: 600, - }, - headerBackTitle: null, - }, text: { fontSize: 16, // lineHeight: 22.4 // TODO: This seems like trouble, but what's the right value? }, - textColor: colors.n1, + delayedFadeIn: { animationName: keyframes({ '0%': { opacity: 0 }, @@ -108,13 +91,17 @@ export const styles = { animationDelay: '0.5s', }, // Dynamically set - lightScrollbar: undefined, - darkScrollbar: undefined, - scrollbarWidth: undefined, + lightScrollbar: null as CSSProperties | null, + darkScrollbar: null as CSSProperties | null, + scrollbarWidth: null as number | null, }; let hiddenScrollbars = false; +// need both styles defined for primary and secondary colors +// e.g. transaction table and sidebar +// lightScrollbar => primary +// darkScrollbar => secondary function onScrollbarChange() { styles.lightScrollbar = !hiddenScrollbars && { '& ::-webkit-scrollbar': { diff --git a/packages/desktop-client/src/style/themes/dark.ts b/packages/desktop-client/src/style/themes/dark.ts index 9f26952e5501f4a316e1a28a9144446827da4c42..426b63f0ccc90c84a1a345c04b3c6139d8004161 100644 --- a/packages/desktop-client/src/style/themes/dark.ts +++ b/packages/desktop-client/src/style/themes/dark.ts @@ -8,8 +8,9 @@ export const pageBackgroundLineTop = colorPalette.purple400; export const pageBackgroundLineMid = colorPalette.navy900; export const pageBackgroundLineBottom = colorPalette.navy150; export const pageText = colorPalette.navy150; +export const pageTextLight = pageText; export const pageTextSubdued = colorPalette.navy500; -export const pageTextPositive = colorPalette.purple400; +export const pageTextPositive = colorPalette.purple200; export const pageTextLink = colorPalette.purple400; export const modalBackground = colorPalette.gray800; export const modalBorder = colorPalette.navy600; @@ -52,9 +53,10 @@ export const menuItemBackgroundHover = colorPalette.navy500; export const menuItemText = colorPalette.navy100; export const menuItemTextHover = colorPalette.navy50; export const menuItemTextSelected = colorPalette.navy200; -export const menuItemTextHeader = colorPalette.purple400; +export const menuItemTextHeader = colorPalette.purple300; export const menuBorder = colorPalette.navy800; export const menuBorderHover = colorPalette.purple400; +export const menuKeybindingText = colorPalette.navy500; export const altMenuBackground = colorPalette.navy700; export const altMenuItemBackground = colorPalette.navy700; export const altMenuItemBackgroundHover = colorPalette.navy600; @@ -99,6 +101,10 @@ export const buttonNormalBackgroundHover = colorPalette.navy600; export const buttonNormalBorder = colorPalette.navy300; export const buttonNormalShadow = 'rgba(0, 0, 0, 0.4)'; +export const altbuttonMenuBackground = buttonNormalBackground; +export const buttonNormalSelectedText = colorPalette.white; +export const buttonNormalSelectedBackground = colorPalette.purple600; + export const buttonNormalDisabledText = colorPalette.navy500; export const buttonNormalDisabledBackground = colorPalette.navy800; export const buttonNormalDisabledBorder = colorPalette.navy500; @@ -134,8 +140,10 @@ export const formInputTextPlaceholderSelected = colorPalette.navy100; export const formInputTextSelection = colorPalette.navy800; export const formInputShadowSelected = colorPalette.purple200; export const formInputTextHighlight = colorPalette.purple400; + export const pillBackground = colorPalette.navy600; export const pillText = colorPalette.navy200; +export const pillTextHighlighted = colorPalette.purple500; export const pillBorder = colorPalette.navy700; export const pillBackgroundSelected = colorPalette.purple600; export const pillTextSelected = colorPalette.navy150; diff --git a/packages/desktop-client/src/style/themes/light.ts b/packages/desktop-client/src/style/themes/light.ts index 9752e6591fc4301a8abd6a34c720930e2c0c4f88..ae839db164a6417bd5160ff7f7513e22ca940b78 100644 --- a/packages/desktop-client/src/style/themes/light.ts +++ b/packages/desktop-client/src/style/themes/light.ts @@ -8,8 +8,10 @@ export const pageBackgroundLineTop = colorPalette.white; export const pageBackgroundLineMid = colorPalette.navy100; export const pageBackgroundLineBottom = colorPalette.blue150; export const pageText = '#272630'; +export const pageTextLight = colorPalette.navy600; export const pageTextSubdued = colorPalette.navy300; -export const pageTextPositive = colorPalette.purple500; +export const altpageTextSubdued = colorPalette.navy500; +export const pageTextPositive = colorPalette.purple600; export const pageTextLink = colorPalette.blue600; export const modalBackground = colorPalette.white; export const modalBorder = colorPalette.white; @@ -17,20 +19,21 @@ export const cardBackground = colorPalette.white; export const cardBorder = colorPalette.purple500; export const cardShadow = colorPalette.navy700; export const tableBackground = colorPalette.white; -export const tableRowBackgroundHover = colorPalette.blue100; +export const tableRowBackgroundHover = colorPalette.navy50; export const tableText = colorPalette.navy700; +export const altTableText = colorPalette.navy400; export const tableTextSelected = colorPalette.navy700; export const tableTextHover = colorPalette.navy900; export const tableTextEditing = colorPalette.navy50; -export const tableTextEditingBackground = colorPalette.purple500; -export const tableTextInactive = colorPalette.navy300; -export const tableHeaderText = colorPalette.navy500; +export const tableTextEditingBackground = colorPalette.blue500; +export const tableTextInactive = colorPalette.navy200; +export const tableHeaderText = colorPalette.navy600; export const tableHeaderBackground = colorPalette.navy50; -export const tableBorder = colorPalette.navy150; +export const tableBorder = colorPalette.navy100; export const tableBorderSelected = colorPalette.purple500; export const tableBorderHover = colorPalette.purple400; export const tableBorderSeparator = colorPalette.navy400; -export const tableRowBackgroundHighlight = colorPalette.purple100; +export const tableRowBackgroundHighlight = colorPalette.blue150; export const tableRowBackgroundHighlightText = colorPalette.navy700; export const tableRowHeaderBackground = colorPalette.navy50; export const tableRowHeaderText = colorPalette.navy800; @@ -46,22 +49,23 @@ export const sidebarItemTextSelected = colorPalette.purple300; export const sidebarItemTextHover = colorPalette.navy50; export const tooltipBackground = colorPalette.navy50; export const tooltipBorder = colorPalette.navy50; -export const menuBackground = colorPalette.navy50; +export const menuBackground = colorPalette.white; export const menuItemBackground = colorPalette.navy50; -export const menuItemBackgroundHover = colorPalette.navy150; -export const menuItemText = colorPalette.navy800; -export const menuItemTextHover = colorPalette.navy800; -export const menuItemTextSelected = colorPalette.navy800; +export const menuItemBackgroundHover = colorPalette.navy100; +export const menuItemText = colorPalette.navy900; +export const menuItemTextHover = menuItemText; +export const menuItemTextSelected = menuItemText; export const menuItemTextHeader = colorPalette.purple600; export const menuBorder = colorPalette.navy100; export const menuBorderHover = colorPalette.purple100; +export const menuKeybindingText = colorPalette.navy400; export const altMenuBackground = colorPalette.blue800; export const altMenuItemBackground = colorPalette.blue800; export const altMenuItemBackgroundHover = colorPalette.blue700; export const altMenuItemText = colorPalette.navy100; export const altMenuItemTextHover = colorPalette.navy50; export const altMenuItemTextSelected = colorPalette.purple300; -export const altMenuItemTextHeader = colorPalette.purple300; +export const altMenuItemTextHeader = colorPalette.navy400; export const altMenuBorder = colorPalette.blue700; export const altMenuBorderHover = colorPalette.purple300; export const mobileNavBackground = colorPalette.white; @@ -99,7 +103,11 @@ export const buttonNormalBackgroundHover = buttonNormalBackground; export const buttonNormalBorder = colorPalette.navy150; export const buttonNormalShadow = 'rgba(0, 0, 0, 0.2)'; -export const buttonNormalDisabledText = colorPalette.navy400; +export const altbuttonMenuBackground = colorPalette.navy100; +export const buttonNormalSelectedText = colorPalette.white; +export const buttonNormalSelectedBackground = colorPalette.blue600; + +export const buttonNormalDisabledText = colorPalette.navy300; export const buttonNormalDisabledBackground = buttonNormalBackground; export const buttonNormalDisabledBorder = buttonNormalBorder; @@ -112,7 +120,7 @@ export const buttonBareDisabledText = buttonNormalDisabledText; export const buttonBareDisabledBackground = buttonBareBackground; export const noticeBackground = colorPalette.green50; -export const noticeText = colorPalette.green500; +export const noticeText = colorPalette.green600; export const noticeAccent = colorPalette.green200; export const warningBackground = colorPalette.orange200; export const warningText = colorPalette.orange800; @@ -121,22 +129,29 @@ export const errorBackground = colorPalette.red50; export const errorText = colorPalette.red500; export const errorAccent = colorPalette.red200; export const formLabelText = colorPalette.blue500; +export const altFormLabelText = colorPalette.blue700; export const formInputBackground = colorPalette.navy50; export const formInputBackgroundSelected = colorPalette.white; export const formInputBackgroundSelection = colorPalette.purple500; -export const formInputBorder = colorPalette.navy300; +export const formInputBorder = colorPalette.navy150; export const formInputTextReadOnlySelection = colorPalette.navy50; export const formInputBorderSelected = colorPalette.purple500; -export const formInputText = colorPalette.navy700; +export const altformInputBorderSelected = colorPalette.blue500; +export const formInputText = colorPalette.navy900; export const formInputTextSelected = colorPalette.navy50; export const formInputTextPlaceholder = colorPalette.navy300; export const formInputTextPlaceholderSelected = colorPalette.navy200; export const formInputTextSelection = colorPalette.navy100; export const formInputShadowSelected = colorPalette.purple300; -export const formInputTextHighlight = colorPalette.purple500; +export const altformInputShadowSelected = colorPalette.blue300; +export const formInputTextHighlight = colorPalette.purple200; + export const pillBackground = colorPalette.navy150; export const pillText = colorPalette.navy800; +export const pillTextHighlighted = colorPalette.purple600; export const pillBorder = colorPalette.navy150; -export const pillBackgroundSelected = colorPalette.purple150; -export const pillTextSelected = colorPalette.navy700; +export const pillBackgroundSelected = colorPalette.blue150; +export const pillTextSelected = colorPalette.blue900; export const pillBorderSelected = colorPalette.purple500; +export const altPillBackground = colorPalette.navy100; +export const altPillText = colorPalette.navy900; diff --git a/upcoming-release-notes/1436.md b/upcoming-release-notes/1436.md new file mode 100644 index 0000000000000000000000000000000000000000..8220b328fb444ae07f359b98c9718ccb3c21432b --- /dev/null +++ b/upcoming-release-notes/1436.md @@ -0,0 +1,5 @@ +--- +category: Enhancements +authors: [biohzrddd, carkom] +--- +Phase one of dark theme, to include filters/rules/transaction tables \ No newline at end of file