How to simplify styling? #117
Replies: 18 comments 42 replies
-
It would also be great to use more self explaining names. For example "modal" instead of "persistent" (see #132). |
Beta Was this translation helpful? Give feedback.
-
If the 💡 Idea 3: "Apply"ui.label().apply(tailwind.margin_top(4).text_blue_600) |
Beta Was this translation helpful? Give feedback.
-
I think the apply function is a great idea |
Beta Was this translation helpful? Give feedback.
-
Interesting discussion! Here are a few thoughts and observed pain points:
That's what I had in mind so far. Hope this helps ;-) |
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
-
Thanks for your thoughtful, in depth analysis. I'll try to summarize all high level requirements we have got so far. Ordered by priority. This is open to discussion, of course. Please point out if I missed something or you want to rearrange the priority:
In my opinion requirements like pre-configured themes, galleries and maybe something like nicegui-fiddle (analog to js-fiddle) is out of scope for this discussion. After we agree on the main requirements I may get easier to find the right API... |
Beta Was this translation helpful? Give feedback.
-
💡 Idea 4: "Builder Pattern for Looks"I created the branch https://github.com/zauberzeug/nicegui/tree/looks where I made some first experiments with a possible API: Lines 1 to 23 in a3b3f48 Everything in this approach is discussable. Please feel free to provide feedback and suggestions. I've already some remarks of my one:
|
Beta Was this translation helpful? Give feedback.
-
In order to keep an overview I updated previous comments and added markers for easier reference of proposed ideas. And I've got another one, a bit contrary to the builder patterns so far: 💡 Idea 5: "Literal Keyword Arguments"Although I'm a fan of the builder pattern for creating user interfaces, it can get quite lengthy. And I personally find @rodja's idea 4 a bit difficult to read: Where does one aspect begin and where does it end? Therefore I thought about making good old strings more accessible and discoverable: Color = Literal['red', 'green', 'blue']
Gap = Literal['small', 'medium', 'large']
def look(*,
color: Color = ...,
background_color: Color = ...,
gap: Gap = ...,
width_px: float = ...,
width_rem: float = ...,
width_percent: float = ...):
...
look(color='blue', background_color='blue', gap='large', width_percent=50) Advantages:
|
Beta Was this translation helpful? Give feedback.
-
Here is how I see the main approches to the problem:
|
Beta Was this translation helpful? Give feedback.
-
💡 Idea 6: "Builder Pattern with Literal Keyword Arguments to Access Styles, Classes and Props"What about a combination of idea 4 and 5: Color = Literal['red', 'green', 'blue']
Gap = Literal['small', 'medium', 'large']
class Style:
def color(self, color: Color) -> 'Style':
return self
def background_color(self, color: Color) -> 'Style':
return self
def gap(self, name: Gap = ..., *, px: float = ..., percent: float = ...) -> 'Style':
return self
style = Style()
style.color('red').background_color('blue').gap(px=2) This divides the option space into separate methods like (4), but might be shorter and easier to read. "Literal keyword arguments" (5) provide auto-completion for pre-defined strings. And we still have multiple options for, e.g., gap dimensions: literal name, px or percent. But it's all in one method, thus visually easier to grasp. And having single methods per aspect allows overloading them, e.g. to support a pre-defined color name or any other arbitrary string. In contrast to using @overload
def color(self, color: Color) -> 'Style':
...
def color(self, color: str) -> 'Style':
return self |
Beta Was this translation helpful? Give feedback.
-
💡 Idea 7: "Layout Builder"When taking Idea 6: "Builder Pattern with Literal Keyword Arguments to Access Styles, Classes and Props" to improve Idea 4: "Builder Pattern for Looks" we get a shorter, more readable API. While Idea 6 exposes the underlying styles API (and probably could also expose props and classes in a similar way), the here proposed "Layout Builder" deviates from Quasar/Tailwind/CSS to provide a simpler, more accessible API for those who do not know or want to use all the subtle details of web development. Thanks to @smojef who made these different approaches clear. I experimented with an implementation of such a system on the branch layout_builder. But it's far from complete. There are some inconsistencies and lots of decisions to be made. If we go forward with it. Here are some example on how specific aspects could look like in such an API: ui.icon('star').layout.color('yellow', '8').size('medium').align.center() Here, with ui.row().layout.align.children(main_axis='evenly', cross_axis='center'):
... For groups the with ui.layout().row().size(width='2/3`):
... The element The above snippets are just examples on what could be done. Overall this will be a huge undertaking. Not only in writing the code, but also documentation. Maybe it can be build out in stages (postponing grids, tables, cards). In my opinion it's not either "Idea 6" or "Idea 7". If Idea 6 really works for props and classes too, we should definitely implement it. The benefits are obvious and the existing implementation of NiceGUI is not altered. But I feel it does not come true on the requirement "As a developer not familiar with the web technologies, I want an easy way to discover and understand style, layout and props." For this, we would need something like the here proposed Layout Builder. What do you think? |
Beta Was this translation helpful? Give feedback.
-
I created a class that implements all the properties of Tailwind's Typography system, experimenting with what a Styling constructor would look like.
To use: btn = (
Typography(ui.button("Test"))
.text_align("center")
.font_weight("bold")
.text_transform("uppercase")
.element
)
label = (
Typography(ui.label("Test"))
.font_family("mono")
.font_size("4xl")
.font_weight("bold")
.text_color("neutral-700")
.font_smoothing("antialiased")
.element
)
(
Typography(ui.label("No Save Reference"))
.font_weight("bold")
.text_color("teal-600")
)
def my_label(text: str):
return (
Typography(ui.label(text))
.text_align("center")
.font_weight("bold")
.text_transform("uppercase")
.text_color("yellow-500")
.text_decoration("underline")
.text_decoration_color("zinc-700")
.element
)
|
Beta Was this translation helpful? Give feedback.
-
I converted the Layout Builder branch (Idea 7) into the draft pull request #364. I think we should further discuss the specifics of a possible Layout Builder implementation there. |
Beta Was this translation helpful? Give feedback.
-
Personally Im a big fan of writing css like |
Beta Was this translation helpful? Give feedback.
-
After implementing the new |
Beta Was this translation helpful? Give feedback.
-
Please share the talk recording after the conference, would love to watch it
…On Mon, Sep 18, 2023, 1:13 AM Rodja Trappe ***@***.***> wrote:
I am also impressed by how NiceGui team brainstormed on various options
and converged to an optimal solution quickly
Thanks! @falkoschindler <https://github.com/falkoschindler> will have a
talk about this at PyCon Ireland this November 😀
—
Reply to this email directly, view it on GitHub
<#117 (reply in thread)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AACQRSC366BVFENB62CDXD3X27KBLANCNFSM6AAAAAARAVM6VE>
.
You are receiving this because you commented.Message ID:
***@***.***>
|
Beta Was this translation helpful? Give feedback.
-
There are some defaults that might need to be changed. E.g. a ui.html element currently doesn't show links as blue / underlined without styling it: {
color: blue;
text-decoration: underline;
} |
Beta Was this translation helpful? Give feedback.
-
I think i'll make this part of my Link class by adding:
and an option for adding red and blue links in the create function. That way i get mediawiki compatible link display which makes sense for most of my applications. |
Beta Was this translation helpful? Give feedback.
-
While it's great to have Tailwind and Quasar classes at hand to do all kinds of styling. It's quite hard to discover. If one is not working regularly with these libs, constant documentation lookup can not be avoided.
Maybe we find a nice API to make styling more discoverable. Here some ideas to get started:
💡 Idea 1: "Format Property"
My first Idea was a
format
property wich would return aFormat
object. This can then be used in a builder pattern like this:One disadvantage would be the huge number of properties and functions of the
Format
object. Maybe it's to much to be helpful.To reduce the amount of suggestions, we could provide a
tailwind
, and aquasar
property instead offormat
. Another trick may be to introduce sub objects liketext_color
which then provideblue_600
and the like.Another problem with this approach may be that styling can not easily be shared between elements.
💡 Idea 2: "Operator Overloading"
It feels strange at first, but utilising operators could be nice. The inspiration comes from the
/
operator in pathlib. Applied to styling it could look like this:Beta Was this translation helpful? Give feedback.
All reactions