Skip to content

Conversation

@rodrigost23
Copy link
Contributor

Description

This PR adds month headers to expenses list. I was having trouble going through a long list of expenses, hope this would make it a little more neat.

Demo

image

Checklist

  • I have read CONTRIBUTING.md in its entirety
  • I have performed a self-review of my own code
  • I have added unit tests to cover my changes
  • The last commit successfully passed pre-commit checks
  • Any AI code was thoroughly reviewed by me

Copy link
Collaborator

@krokosik krokosik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this idea, but I need to sit on it for a while since this is a significant UI change in the most frequently used part of the app. Currently, I think it's too intrusive and I would make it more minimal, but don't have the bandwidth rn for desig thinking, so this PR might have to wait a bit. Apologies

return (
<>
{expenses.map((e) => {
{expenses.reduce((acc, e, idx, arr) => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can call reduce with type params like reduce<JSX.Element[]> and don't make the linter upset with using as :)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

with that being set, I believe a map is more semantically aligned with JSX operations like this.
You can simply return a react fragment with an optional header instead

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, just changed to reduce to be able to compare with the previous item easily, in order to detect if the item is the first one in the month

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this idea, but I need to sit on it for a while since this is a significant UI change in the most frequently used part of the app. Currently, I think it's too intrusive and I would make it more minimal, but don't have the bandwidth rn for desig thinking, so this PR might have to wait a bit. Apologies

Of course, that sounds totally fair. And I only added the header without even styling it :) .

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, fair point. But I think keeping a let variable outside would be preferred.

@FelixDz
Copy link
Contributor

FelixDz commented Nov 6, 2025

Currently, I think it's too intrusive and I would make it more minimal

I agree with this, scanning through the expenses should stay easy and as uncluttered as possible. However I think having months headers also helps.

Some design principles can help adding this without drawing too much attention to it, like :

  • setting the text uppercase, but smaller
  • give it a dimmer color (like the one of the expense date or details)
  • add a very thin and dim horizontal separator helping separating months
  • center the month text, as it would help scanning through the expenses and through the months altogether since they are not in the same alignment

I can take some time soon to make an example if this helps. Maybe also try to dive in the code and try to design the changes building on your PR if you prefer @rodrigost23 ?

@rodrigost23 rodrigost23 force-pushed the expenses-month-headers branch from c59220f to acacb49 Compare November 7, 2025 20:03
@rodrigost23
Copy link
Contributor Author

rodrigost23 commented Nov 7, 2025

@FelixDz Thanks for your ideas. I just updated the PR addressing @krokosik's concern about using map instead of reduce, and also applied a little styling to the headers:
 

I'm not sure if using a separator and/or centering the text is any better, though:

Anyway, I just feel like not having some sort of separation between months or years, just makes it very hard to find expenses by skimming.

@FelixDz
Copy link
Contributor

FelixDz commented Nov 8, 2025

Nice work!
For the separator / centered text, I had this in mind:
Months-headers

Changes made:

  • months are on the separator (like in some chatting apps), taking less vertical space in a place where information density is crucial
  • I made them even dimmer to keep focus on the expenses
  • I also reduced spacing that appeared between each month header and the first expense in it

I tried to setup a dev version of the project yesterday, but I'm not a (pro) developer and am struggling a bit with this for the moment. So those images are the best I can do for now, sorry for that. Anyway your proposed version is already very satisfying and does a great job helping to find the expenses in my opinion.

@rodrigost23
Copy link
Contributor Author

I tried to code your mockup:

image image
Click to see code
        return (
          <React.Fragment key={e.id}>
            {isFirstOfMonth && (
              <div className="mt-8 mb-2 flex flex-row items-center justify-start gap-3">
                <Separator className="flex-1 bg-gray-800" />
                <div className="text-xs font-medium text-gray-700 uppercase">
                  {new Intl.DateTimeFormat(i18n.language, {
                    month: 'long',
                    year: 'numeric',
                  }).format(currentDate)}
                </div>
                <Separator className="flex-1 bg-gray-800" />
              </div>
            )}
            <Link
              href={`/${isGroup ? 'groups' : 'balances'}/${contactId}/expenses/${e.id}`}
              className="flex items-center justify-between py-2"
            >
              {isSettlement && <Settlement e={e} userId={userId} />}
              {isCurrencyConversion && <CurrencyConversion e={e} userId={userId} />}
              {!isSettlement && !isCurrencyConversion && <Expense e={e} userId={userId} />}
            </Link>
          </React.Fragment>
        );

Alternative:

image image

@FelixDz
Copy link
Contributor

FelixDz commented Nov 9, 2025

Very nice! Both versions are highly usable in my opinion, I don't have a preference, do you? And what do you think @krokosik ?

Also, maybe the padding around the months headers can be reduced a bit, since the display space here is quite critical as @krokosik stated? Maybe try to almost preserve the original spacing between expenses and insert the headers "in between"? Unless you find this spacing important to clearly separate months?

Sorry again to be of no help on the code side of this, I didn't have time to solve my dev env setup issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants