Skip to content

Commit

Permalink
ui: improve balance spacing, coloring and grouping (#691)
Browse files Browse the repository at this point in the history
* chore: continue loop on errors in setIntervalDebounced

* ui(balance): improve displaying balance value in BTC

* chore: use cursor-pointer style class where applicable

* ui(style): use only css to style bitcoin amount

* refactor: add frozen flag to balance component

* ui(balance): align colors with copy

* ui(balance): deemphasize symbol on zero balance

* test(balance): use testid to get balance element
  • Loading branch information
theborakompanioni authored Nov 13, 2023
1 parent df81804 commit 821b227
Show file tree
Hide file tree
Showing 13 changed files with 272 additions and 113 deletions.
72 changes: 72 additions & 0 deletions src/components/Balance.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
:root {
--jam-balance-color: #212529;
--jam-balance-deemphasize-color: #9eacba;
}

:root[data-theme='dark'] {
--jam-balance-color: #ffffff;
--jam-balance-deemphasize-color: #555c62;
}

.frozen {
--jam-balance-color: #0d6efd;
--jam-balance-deemphasize-color: #7eb2ff;
}

:root[data-theme='dark'] .frozen {
--jam-balance-color: #1372ff;
--jam-balance-deemphasize-color: #1153b5;
}

.balance {
color: var(--jam-balance-color);
}

.frozenSymbol {
order: -2;
}

.bitcoinSymbol {
padding-right: 0.1em;
order: -1;
}

.satsSymbol {
padding-right: 0.1em;
order: 6;
}

.hideSymbol {
padding-left: 0.1em;
color: var(--jam-balance-deemphasize-color);
}

.bitcoinAmount .fractionalPart :nth-child(3)::before,
.bitcoinAmount .fractionalPart :nth-child(6)::before {
content: '\202F';
}

/** Integer Part **/
.bitcoinAmount[data-integer-part-is-zero="true"] .integerPart,
/** Decimal Point **/
.bitcoinAmount[data-integer-part-is-zero="true"] .decimalPoint,
.bitcoinAmount[data-fractional-part-starts-with-zero="true"] .decimalPoint,
/** Fractional Part **/
.bitcoinAmount[data-integer-part-is-zero="false"] .fractionalPart,
.bitcoinAmount[data-integer-part-is-zero="true"] .fractionalPart :nth-child(1):is(span[data-digit="0"]),
.bitcoinAmount[data-integer-part-is-zero="true"] .fractionalPart :nth-child(1):is(span[data-digit="0"]) + span[data-digit="0"],
.bitcoinAmount[data-integer-part-is-zero="true"] .fractionalPart :nth-child(1):is(span[data-digit="0"]) + span[data-digit="0"] + span[data-digit="0"],
.bitcoinAmount[data-integer-part-is-zero="true"] .fractionalPart :nth-child(1):is(span[data-digit="0"]) + span[data-digit="0"] + span[data-digit="0"] + span[data-digit="0"],
.bitcoinAmount[data-integer-part-is-zero="true"] .fractionalPart :nth-child(1):is(span[data-digit="0"]) + span[data-digit="0"] + span[data-digit="0"] + span[data-digit="0"] + span[data-digit="0"],
.bitcoinAmount[data-integer-part-is-zero="true"] .fractionalPart :nth-child(1):is(span[data-digit="0"]) + span[data-digit="0"] + span[data-digit="0"] + span[data-digit="0"] + span[data-digit="0"] + span[data-digit="0"],
.bitcoinAmount[data-integer-part-is-zero="true"] .fractionalPart :nth-child(1):is(span[data-digit="0"]) + span[data-digit="0"] + span[data-digit="0"] + span[data-digit="0"] + span[data-digit="0"] + span[data-digit="0"] + span[data-digit="0"],
.bitcoinAmount[data-integer-part-is-zero="true"] .fractionalPart :nth-child(1):is(span[data-digit="0"]) + span[data-digit="0"] + span[data-digit="0"] + span[data-digit="0"] + span[data-digit="0"] + span[data-digit="0"] + span[data-digit="0"] + span[data-digit="0"],
/** Symbol */
.bitcoinAmount[data-raw-value="0"] + .bitcoinSymbol {
color: var(--jam-balance-deemphasize-color);
}

.satsAmount[data-raw-value='0'],
.satsAmount[data-raw-value='0'] + .satsSymbol {
color: var(--jam-balance-deemphasize-color);
}
70 changes: 35 additions & 35 deletions src/components/Balance.test.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { act } from 'react-dom/test-utils'
import { render } from '@testing-library/react'
import user from '@testing-library/user-event'
import { render, screen } from '../testUtils'
import { act } from 'react-dom/test-utils'
import { screen } from '../testUtils'
import { BTC, SATS } from '../utils'

import Balance from './Balance'

describe('<Balance />', () => {
Expand All @@ -13,164 +13,164 @@ describe('<Balance />', () => {

it('should render BTC using satscomma formatting', () => {
render(<Balance valueString={'123.456'} convertToUnit={BTC} showBalance={true} />)
expect(screen.getByText(`123.45 600 000`)).toBeInTheDocument()
expect(screen.getByTestId('bitcoin-amount').dataset.formattedValue).toBe(`123.45600000`)
})

it('should hide balance for BTC by default', () => {
render(<Balance valueString={'123.456'} convertToUnit={BTC} />)
expect(screen.getByText(`*****`)).toBeInTheDocument()
expect(screen.queryByText(`123.45 600 000`)).not.toBeInTheDocument()
expect(screen.queryByTestId('bitcoin-amount')).not.toBeInTheDocument()
})

it('should hide balance for SATS by default', () => {
render(<Balance valueString={'123'} convertToUnit={SATS} />)
expect(screen.getByText(`*****`)).toBeInTheDocument()
expect(screen.queryByText(`123`)).not.toBeInTheDocument()
expect(screen.queryByTestId(`sats-amount`)).not.toBeInTheDocument()
})

it('should render a string BTC value correctly as BTC', () => {
render(<Balance valueString={'123.03224961'} convertToUnit={BTC} showBalance={true} />)
expect(screen.getByText(`123.03 224 961`)).toBeInTheDocument()
expect(screen.getByTestId('bitcoin-amount').dataset.formattedValue).toBe(`123.03224961`)
})

it('should render a string BTC value correctly as SATS', () => {
render(<Balance valueString={'123.03224961'} convertToUnit={SATS} showBalance={true} />)
expect(screen.getByText(`12,303,224,961`)).toBeInTheDocument()
expect(screen.getByTestId(`sats-amount`)).toHaveTextContent(`12,303,224,961`)
})

it('should render a zero string BTC value correctly as BTC', () => {
render(<Balance valueString={'0.00000000'} convertToUnit={BTC} showBalance={true} />)
expect(screen.getByText(`0.00 000 000`)).toBeInTheDocument()
expect(screen.getByTestId('bitcoin-amount').dataset.formattedValue).toBe(`0.00000000`)
})

it('should render a zero string BTC value correctly as SATS', () => {
render(<Balance valueString={'0.00000000'} convertToUnit={SATS} showBalance={true} />)
expect(screen.getByText(`0`)).toBeInTheDocument()
expect(screen.getByTestId(`sats-amount`)).toHaveTextContent(`0`)
})

it('should render a large string BTC value correctly as BTC', () => {
render(<Balance valueString={'20999999.97690000'} convertToUnit={BTC} showBalance={true} />)
expect(screen.getByText(`20,999,999.97 690 000`)).toBeInTheDocument()
expect(screen.getByTestId('bitcoin-amount').dataset.formattedValue).toBe(`20,999,999.97690000`)
})

it('should render a large string BTC value correctly as SATS', () => {
render(<Balance valueString={'20999999.97690000'} convertToUnit={SATS} showBalance={true} />)
expect(screen.getByText(`2,099,999,997,690,000`)).toBeInTheDocument()
expect(screen.getByTestId(`sats-amount`)).toHaveTextContent(`2,099,999,997,690,000`)
})

it('should render a max string BTC value correctly as BTC', () => {
render(<Balance valueString={'21000000.00000000'} convertToUnit={BTC} showBalance={true} />)
expect(screen.getByText(`21,000,000.00 000 000`)).toBeInTheDocument()
expect(screen.getByTestId('bitcoin-amount').dataset.formattedValue).toBe(`21,000,000.00000000`)
})

it('should render a max string BTC value correctly as SATS', () => {
render(<Balance valueString={'21000000.00000000'} convertToUnit={SATS} showBalance={true} />)
expect(screen.getByText(`2,100,000,000,000,000`)).toBeInTheDocument()
expect(screen.getByTestId(`sats-amount`)).toHaveTextContent(`2,100,000,000,000,000`)
})

it('should render a string SATS value correctly as SATS', () => {
render(<Balance valueString={'43000'} convertToUnit={SATS} showBalance={true} />)
expect(screen.getByText(`43,000`)).toBeInTheDocument()
expect(screen.getByTestId(`sats-amount`)).toHaveTextContent(`43,000`)
})

it('should render a string SATS value correctly as BTC', () => {
render(<Balance valueString={'43000'} convertToUnit={BTC} showBalance={true} />)
expect(screen.getByText(`0.00 043 000`)).toBeInTheDocument()
expect(screen.getByTestId('bitcoin-amount').dataset.formattedValue).toBe(`0.00043000`)
})

it('should render a zero string SATS value correctly as BTC', () => {
render(<Balance valueString={'0'} convertToUnit={BTC} showBalance={true} />)
expect(screen.getByText(`0.00 000 000`)).toBeInTheDocument()
expect(screen.getByTestId('bitcoin-amount').dataset.formattedValue).toBe(`0.00000000`)
})

it('should render a zero string SATS value correctly as SATS', () => {
render(<Balance valueString={'0'} convertToUnit={SATS} showBalance={true} />)
expect(screen.getByText(`0`)).toBeInTheDocument()
expect(screen.getByTestId(`sats-amount`)).toHaveTextContent(`0`)
})

it('should render a large string SATS value correctly as BTC', () => {
render(<Balance valueString={'2099999997690000'} convertToUnit={BTC} showBalance={true} />)
expect(screen.getByText(`20,999,999.97 690 000`)).toBeInTheDocument()
expect(screen.getByTestId('bitcoin-amount').dataset.formattedValue).toBe(`20,999,999.97690000`)
})

it('should render a large string SATS value correctly as SATS', () => {
render(<Balance valueString={'2099999997690000'} convertToUnit={SATS} showBalance={true} />)
expect(screen.getByText(`2,099,999,997,690,000`)).toBeInTheDocument()
expect(screen.getByTestId(`sats-amount`)).toHaveTextContent(`2,099,999,997,690,000`)
})

it('should render a max string SATS value correctly as BTC', () => {
render(<Balance valueString={'2100000000000000'} convertToUnit={BTC} showBalance={true} />)
expect(screen.getByText(`21,000,000.00 000 000`)).toBeInTheDocument()
expect(screen.getByTestId('bitcoin-amount').dataset.formattedValue).toBe(`21,000,000.00000000`)
})

it('should render a max string SATS value correctly as SATS', () => {
render(<Balance valueString={'2100000000000000'} convertToUnit={SATS} showBalance={true} />)
expect(screen.getByText(`2,100,000,000,000,000`)).toBeInTheDocument()
expect(screen.getByTestId(`sats-amount`)).toHaveTextContent(`2,100,000,000,000,000`)
})

it('should toggle visibility of initially hidden balance on click by default', () => {
render(<Balance valueString={`21`} convertToUnit={SATS} showBalance={false} />)
expect(screen.queryByText(`21`)).not.toBeInTheDocument()
expect(screen.queryByTestId(`sats-amount`)).not.toBeInTheDocument()
expect(screen.getByText(`*****`)).toBeInTheDocument()

act(() => {
user.click(screen.getByText(`*****`))
})

expect(screen.getByText(`21`)).toBeInTheDocument()
expect(screen.getByTestId(`sats-amount`)).toBeInTheDocument()
expect(screen.queryByText(`*****`)).not.toBeInTheDocument()

act(() => {
user.click(screen.getByText(`21`))
user.click(screen.getByTestId(`sats-amount`))
})

expect(screen.queryByText(`21`)).not.toBeInTheDocument()
expect(screen.queryByTestId(`sats-amount`)).not.toBeInTheDocument()
expect(screen.getByText(`*****`)).toBeInTheDocument()
})

it('should NOT toggle visibility of initially hidden balance on click when disabled via flag', () => {
render(<Balance valueString={`21`} convertToUnit={SATS} showBalance={false} enableVisibilityToggle={false} />)
expect(screen.queryByText(`21`)).not.toBeInTheDocument()
expect(screen.queryByTestId(`sats-amount`)).not.toBeInTheDocument()
expect(screen.getByText(`*****`)).toBeInTheDocument()

act(() => {
user.click(screen.getByText(`*****`))
})

expect(screen.queryByText(`21`)).not.toBeInTheDocument()
expect(screen.queryByTestId(`sats-amount`)).not.toBeInTheDocument()
expect(screen.getByText(`*****`)).toBeInTheDocument()
})

it('should NOT toggle visibility of initially visible balance on click by default', () => {
render(<Balance valueString={`21`} convertToUnit={SATS} showBalance={true} />)
expect(screen.getByText(`21`)).toBeInTheDocument()
expect(screen.getByTestId(`sats-amount`)).toBeInTheDocument()
expect(screen.queryByText(`*****`)).not.toBeInTheDocument()

act(() => {
user.click(screen.getByText(`21`))
user.click(screen.getByTestId(`sats-amount`))
})

expect(screen.getByText(`21`)).toBeInTheDocument()
expect(screen.getByTestId(`sats-amount`)).toBeInTheDocument()
expect(screen.queryByText(`*****`)).not.toBeInTheDocument()
})

it('should toggle visibility of initially visible balance on click when enabled via flag', () => {
render(<Balance valueString={`21`} convertToUnit={SATS} showBalance={true} enableVisibilityToggle={true} />)
expect(screen.getByText(`21`)).toBeInTheDocument()
expect(screen.getByTestId(`sats-amount`)).toBeInTheDocument()
expect(screen.queryByText(`*****`)).not.toBeInTheDocument()

act(() => {
user.click(screen.getByText(`21`))
user.click(screen.getByTestId(`sats-amount`))
})

expect(screen.queryByText(`21`)).not.toBeInTheDocument()
expect(screen.queryByTestId(`sats-amount`)).not.toBeInTheDocument()
expect(screen.getByText(`*****`)).toBeInTheDocument()

act(() => {
user.click(screen.getByText(`*****`))
})

expect(screen.getByText(`21`)).toBeInTheDocument()
expect(screen.getByTestId(`sats-amount`)).toBeInTheDocument()
expect(screen.queryByText(`*****`)).not.toBeInTheDocument()
})
})
Loading

0 comments on commit 821b227

Please sign in to comment.