Repository navigation
feat(borders): initial border blend implementation - #560
Conversation
|
This PR is exceptional and we really appreciate the work you put into both the code and documentation. Thank you. Two thoughts on API:
Hereβs what the would API look like in both cases: lipgloss.NewStyle().
Border(lipgloss.RoundedBorder()).
BorderForeground(
charmtone.Charple,
charmtone.Guac,
charmtone.Cherry,
).
BorderOptions(
lipgloss.WithBorderBlendWrap(),
lipgloss.WithBorderBlendOffset(4),
).
Width(50).
Height(8).
Render("Hello, world!")Also if you want to take a deeper pass on perf around borders after we merge this, go for it. In general the renderer has changed very little since I first put it together a few years ago and thereβs definitely room for improvement. |
Not opposed, though the only problem with variadic is that there is a potential that someone might provide 0 arguments. I assume in this situation, it's fine to have it be a no-op. As far as properties are concerned, we should probably still store them behind the scenes as separate properties to keep memory usage lower in the more common path. EDIT: other gotcha I just noticed, what about some of the
Given there wouldn't really be any other options that are structured in that way, will likely make the API feel a bit more weird. Especially because if we did, I'd think all other border options should also use a similar API, further segmenting the style API. |
|
All good points. In terms of API design, I'm hoping to avoid ambiguity when One thought is that we could introduce a new type for border blends: border := lipgloss.NewBorderBlend(
charmtone.Charple,
charmtone.Guac,
charmtone.Cherry,
).Wrap(true).Offset(4)
lipgloss.NewStyle().
Border(lipgloss.RoundedBorder()).
BorderForeground(border)If we don't go with something like this, what's the prescidence between |
Is it expected that this new type would implement the
Trying to put myself as a regular user, adding blending, it makes sense that adding blending effectively "takes over" the coloring, and with the appropriate warnings in the comment of the method (could also add to the
Not opposed to a new type, but trying to accept either (blend type or |
There was a problem hiding this comment.
this overall looks to me, thanks for the awesome PR!
one comment i have which might be a matter of preference is: I rather not have the wrap option.
e.g.:
BorderBlendForeground(
charmtone.Cherry,
charmtone.Charple,
charmtone.Guac,
charmtone.Charple,
charmtone.Sriracha,
).With using BorderBlendWrap, it'll repeat the sriracha color, right?
I think this rarely will have enough colors that it's worth not having control on how to "wrap", e.g. the caller can simply repeat the colors in the inverse order as they see fit (repeating the middle one or not).
Yes, it will duplicate all of the colors, just in reverse order. Removing wrap does simplify things and reduces added methods, will just have to ensure examples guide folks in the right direction so it's obvious that users should effectively do the same themselves. If that's cool with others, will update soon to remove wrap and further update examples & docs. |
|
That sounds good: we can remove the method now to reduce surface area. I might even just un-expose it for now, since the code is written so we can flip it on later if we feel the need (or if we don't, we can ultimately remove it). Also, do we need to make We're almost there, otherwise. Thanks for tolerating my persnickety comments. |
Signed-off-by: Liam Stanley <liam@liam.sh>
I've removed it for now to keep the code clean, since it should be easy to add back in the future if desired. Added some documentation as well to help drive users in the right direction on how to use the set method without the use of wrapping.
I've updated to both of these names, and all example code. |
meowgorithm
left a comment
There was a problem hiding this comment.
Looks good to me. Let get this in.
Changes
Style.BorderForegroundBlend(colors...)method for storing the palette the user wants to use for blending.Style.BorderForegroundBlendOffset(int)(see below).Style.BorderForegroundBlendOffset(int)method for controlling the offset where the gradient begins on the border.Get<X>()andUnset<X>()methods for the above 3 methods.Performance notes
Width()should be 30-50% less CPU usage, lot of allocs -> 0 allocs).Checklist before requesting a review
CONTRIBUTING.mdScreenshots
More screenshots and example code
Border on all sides
Border on bottom only
see notes below about "still internally generate a full blend of the full size"
Misc border types
double border:
normal border:
outer half block border:
ascii border:
Rotating/spinning border
Definitely increases CPU usage due to the FPS, but could be cool for temporary states in an application (e.g. for X seconds after typing, it updates the keeps rotating the border, and stops once the user stops typing or is inactive). The below example renders at 15FPS @ 5 cell advances per frame.
or blending the border with the background color (modifying the below code a little bit):
Code for this example can be found within
examples/blending/border-blend-rotationReviewer Notes
set()on the style, it won't correctly scale if the size fields change.