I agree with you. I like the way packages are isolated from each other, meaning that to understand a package it is usually by definition a good start to simply read what is there. Smaller packages mean more bite-sized chunks of the program. And I think the discipline of slicing up your program this way is very, very good for the design, and often makes the tests easier to write to by significantly shrinking the surface of what your tests have to "fake" in order to test your code. I think it's just a whole heapin' helpin' o' benefits.
However, I feel myself to be in the minority on this one. To which I basically shrug and write my code with lots of relatively small packages. It really only affects code you're working on, or that your team is working on. Things you pull in as libraries and have no direct interaction with don't matter too much on this front.
If packages are too small it can get hard to understand the code if your not familiar with the structure yet. Working from bottom to top level can work but might also be different because you are missing context for the low level packages to make sense.
In general I found larger packages tend to produce more direct / pragmatic code with less indirection which is usually easier to understand, even though it also feels wrong to me from a theoretical standpoint.
"If packages are too small it can get hard to understand the code if your not familiar with the structure yet."
I solve that with describing the context of the package in the opening prose section. I think this section is underused in every language community I've seen, even though all the automated doc systems support a top-level summary/contextualization/etc.
I think that an advantage of small packages is precisely that it is easier to understand if you're not familiar with the structure yet, by isolating how much structure you have to understand. Large packages, or languages with loose barriers, force you to eat huge swathes of the project at once to understand the code. Small packages are both bite-sized on their own, and also the packages that use the small packages often allow you to gloss over the used package while you're learning that package.
I don't end up with much indirection caused by the package boundaries. (Where there are interfaces I would usually have them anyhow for testing purposes.)
This tends for me to be one of those places where I wonder if I'm just doing something really different than most people. Another example is all the many people over the years who have tried to convince me, with varying level of politeness, that testing code should only use the external interfaces, or dire consequences like having to rewrite all the testing code if I tweak the package will happen. All my testing code uses private interfaces unless there's a really good reason not to, and maybe once in ten years have I had a serious rewrite of the test code come up. The threatened problems don't seem to happen to me. (And I am pretty sure I'd notice them if they did, although I guess I can't completely discount the possibility that I'm just too oblivious somehow.)
Certainly, if they cause you trouble, either because your style is different, or your problem domain is different, or whatever reason, don't use small packages.
However, I feel myself to be in the minority on this one. To which I basically shrug and write my code with lots of relatively small packages. It really only affects code you're working on, or that your team is working on. Things you pull in as libraries and have no direct interaction with don't matter too much on this front.