section_styling_appearance.py 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. from nicegui import events, ui
  2. from ..windows import browser_window, python_window
  3. from . import (
  4. add_style_documentation,
  5. colors_documentation,
  6. dark_mode_documentation,
  7. doc,
  8. element_filter_documentation,
  9. query_documentation,
  10. )
  11. doc.title('Styling & Appearance')
  12. @doc.demo('Styling', '''
  13. NiceGUI uses the [Quasar Framework](https://quasar.dev/) version 1.0 and hence has its full design power.
  14. Each NiceGUI element provides a `props` method whose content is passed [to the Quasar component](https://justpy.io/quasar_tutorial/introduction/#props-of-quasar-components):
  15. Have a look at [the Quasar documentation](https://quasar.dev/vue-components/button#design) for all styling props.
  16. Props with a leading `:` can contain JavaScript expressions that are evaluated on the client.
  17. You can also apply [Tailwind CSS](https://tailwindcss.com/) utility classes with the `classes` method.
  18. If you really need to apply CSS, you can use the `style` method. Here the delimiter is `;` instead of a blank space.
  19. All three functions also provide `remove` and `replace` parameters in case the predefined look is not wanted in a particular styling.
  20. ''')
  21. def design_demo():
  22. ui.radio(['x', 'y', 'z'], value='x').props('inline color=green')
  23. ui.button(icon='touch_app').props('outline round').classes('shadow-lg')
  24. ui.label('Stylish!').style('color: #6E93D6; font-size: 200%; font-weight: 300')
  25. doc.text('Try styling NiceGUI elements!', '''
  26. Try out how
  27. [Tailwind CSS classes](https://tailwindcss.com/),
  28. [Quasar props](https://justpy.io/quasar_tutorial/introduction/#props-of-quasar-components),
  29. and CSS styles affect NiceGUI elements.
  30. ''')
  31. @doc.ui
  32. def styling_demo():
  33. with ui.row():
  34. ui.label('Select an element from those available and start styling it!').classes('mx-auto my-auto')
  35. select_element = ui.select({
  36. ui.label: 'ui.label',
  37. ui.checkbox: 'ui.checkbox',
  38. ui.switch: 'ui.switch',
  39. ui.input: 'ui.input',
  40. ui.textarea: 'ui.textarea',
  41. ui.button: 'ui.button',
  42. }, value=ui.button, on_change=lambda: live_demo_ui.refresh()).props('dense')
  43. @ui.refreshable
  44. def live_demo_ui():
  45. with ui.column().classes('w-full items-stretch gap-8 no-wrap min-[1500px]:flex-row'):
  46. with python_window(classes='w-full max-w-[44rem]'):
  47. with ui.column().classes('w-full gap-4'):
  48. ui.markdown(f'''
  49. ```py
  50. from nicegui import ui
  51. element = {select_element.options[select_element.value]}('element')
  52. ```
  53. ''').classes('mb-[-0.25em]')
  54. with ui.row().classes('items-center gap-0 w-full px-2'):
  55. def handle_classes(e: events.ValueChangeEventArguments):
  56. try:
  57. element.classes(replace=e.value)
  58. except ValueError:
  59. pass
  60. ui.markdown("`element.classes('`")
  61. ui.input(on_change=handle_classes).classes('mt-[-0.5em] text-mono grow').props('dense')
  62. ui.markdown("`')`")
  63. with ui.row().classes('items-center gap-0 w-full px-2'):
  64. def handle_props(e: events.ValueChangeEventArguments):
  65. element._props = {'label': 'Button', 'color': 'primary'}
  66. try:
  67. element.props(e.value)
  68. except ValueError:
  69. pass
  70. element.update()
  71. ui.markdown("`element.props('`")
  72. ui.input(on_change=handle_props).classes('mt-[-0.5em] text-mono grow').props('dense')
  73. ui.markdown("`')`")
  74. with ui.row().classes('items-center gap-0 w-full px-2'):
  75. def handle_style(e: events.ValueChangeEventArguments):
  76. try:
  77. element.style(replace=e.value)
  78. except ValueError:
  79. pass
  80. ui.markdown("`element.style('`")
  81. ui.input(on_change=handle_style).classes('mt-[-0.5em] text-mono grow').props('dense')
  82. ui.markdown("`')`")
  83. ui.markdown('''
  84. ```py
  85. ui.run()
  86. ```
  87. ''')
  88. with browser_window(classes='w-full max-w-[44rem] min-[1500px]:max-w-[20rem] min-h-[10rem] browser-window'):
  89. element: ui.element = select_element.value('element')
  90. live_demo_ui()
  91. @doc.demo('Tailwind CSS', '''
  92. [Tailwind CSS](https://tailwindcss.com/) is a CSS framework for rapidly building custom user interfaces.
  93. NiceGUI provides a fluent, auto-complete friendly interface for adding Tailwind classes to UI elements.
  94. You can discover available classes by navigating the methods of the `tailwind` property.
  95. The builder pattern allows you to chain multiple classes together (as shown with "Label A").
  96. You can also call the `tailwind` property with a list of classes (as shown with "Label B").
  97. Although this is very similar to using the `classes` method, it is more convenient for Tailwind classes due to auto-completion.
  98. Last but not least, you can also predefine a style and apply it to multiple elements (labels C and D).
  99. Note that sometimes Tailwind is overruled by Quasar styles, e.g. when using `ui.button('Button').tailwind('bg-red-500')`.
  100. This is a known limitation and not fully in our control.
  101. But we try to provide solutions like the `color` parameter: `ui.button('Button', color='red-500')`.
  102. ''')
  103. def tailwind_demo():
  104. from nicegui import Tailwind
  105. ui.label('Label A').tailwind.font_weight('extrabold').text_color('blue-600').background_color('orange-200')
  106. ui.label('Label B').tailwind('drop-shadow', 'font-bold', 'text-green-600')
  107. red_style = Tailwind().text_color('red-600').font_weight('bold')
  108. label_c = ui.label('Label C')
  109. red_style.apply(label_c)
  110. ui.label('Label D').tailwind(red_style)
  111. @doc.demo('Tailwind CSS Layers', '''
  112. Tailwind CSS' `@layer` directive allows you to define custom classes that can be used in your HTML.
  113. NiceGUI supports this feature by allowing you to add custom classes to the `components` layer.
  114. This way, you can define your own classes and use them in your UI elements.
  115. In the example below, we define a custom class `blue-box` and apply it to two labels.
  116. Note that the style tag is of type `text/tailwindcss` and not `text/css`.
  117. ''')
  118. def tailwind_layers():
  119. ui.add_head_html('''
  120. <style type="text/tailwindcss">
  121. @layer components {
  122. .blue-box {
  123. @apply bg-blue-500 p-12 text-center shadow-lg rounded-lg text-white;
  124. }
  125. }
  126. </style>
  127. ''')
  128. with ui.row():
  129. ui.label('Hello').classes('blue-box')
  130. ui.label('world').classes('blue-box')
  131. doc.intro(element_filter_documentation)
  132. doc.intro(query_documentation)
  133. doc.intro(colors_documentation)
  134. @doc.demo('CSS Variables', '''
  135. You can customize the appearance of NiceGUI by setting CSS variables.
  136. Currently, the following variables with their default values are available:
  137. - `--nicegui-default-padding: 1rem`
  138. - `--nicegui-default-gap: 1rem`
  139. ''')
  140. def css_variables_demo():
  141. # ui.add_css('''
  142. # :root {
  143. # --nicegui-default-padding: 0.5rem;
  144. # --nicegui-default-gap: 3rem;
  145. # }
  146. # ''')
  147. # with ui.card():
  148. # ui.label('small padding')
  149. # ui.label('large gap')
  150. # END OF DEMO
  151. with ui.card().classes('p-[0.5rem] gap-[3rem]'):
  152. ui.label('small padding')
  153. ui.label('large gap')
  154. @doc.demo("Overwrite Tailwind's Default Style", '''
  155. Tailwind resets the default style of HTML elements, like the font size of `h2` elements in this example.
  156. You can overwrite these defaults by adding a style tag with type `text/tailwindcss`.
  157. Without this type, the style will be evaluated too early and will be overwritten by Tailwind.
  158. ''')
  159. def overwrite_tailwind_style_demo():
  160. ui.add_head_html('''
  161. <style type="text/tailwindcss">
  162. h2 {
  163. font-size: 150%;
  164. }
  165. </style>
  166. ''')
  167. ui.html('<h2>Hello world!</h2>')
  168. doc.intro(dark_mode_documentation)
  169. doc.intro(add_style_documentation)