1
0

main.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. #!/usr/bin/env python3
  2. from pathlib import Path
  3. from pygments.formatters import HtmlFormatter
  4. from nicegui import Client, ui
  5. from website import demo_card, reference, svg
  6. from website.example import bash_window, browser_window, python_window
  7. from website.style import example_link, features, header_link, heading, link_target, section_heading, subtitle, title
  8. ui.add_static_files('/favicon', Path(__file__).parent / 'website' / 'favicon')
  9. def add_head_html() -> None:
  10. ui.add_head_html((Path(__file__).parent / 'website' / 'static' / 'header.html').read_text())
  11. ui.add_head_html(f'<style>{HtmlFormatter(nobackground=True).get_style_defs(".codehilite")}</style>')
  12. ui.add_head_html(f"<style>{(Path(__file__).parent / 'website' / 'static' / 'style.css').read_text()}</style>")
  13. def add_header() -> None:
  14. menu_items = {
  15. 'Features': '/#features',
  16. 'Installation': '/#installation',
  17. 'Examples': '/#examples',
  18. 'API Reference': '/reference',
  19. 'Demos': '/#demos',
  20. 'Why?': '/#why',
  21. }
  22. with ui.header() \
  23. .classes('items-center duration-200 p-0 px-4 no-wrap') \
  24. .style('box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1)'):
  25. with ui.link(target=index_page).classes('row gap-4 items-center no-wrap mr-auto'):
  26. svg.face().classes('w-8 stroke-white stroke-2')
  27. svg.word().classes('w-24')
  28. with ui.row().classes('lg:hidden'):
  29. with ui.menu().classes('bg-primary text-white text-lg') as menu:
  30. for title, target in menu_items.items():
  31. ui.menu_item(title, on_click=lambda _, target=target: ui.open(target))
  32. ui.button(on_click=menu.open).props('flat color=white icon=menu')
  33. with ui.row().classes('max-lg:hidden'):
  34. for title, target in menu_items.items():
  35. header_link(title, target)
  36. with ui.link(target='https://github.com/zauberzeug/nicegui/'):
  37. svg.github().classes('fill-white scale-125 m-1')
  38. @ui.page('/')
  39. async def index_page(client: Client):
  40. client.content.classes(remove='q-pa-md gap-4')
  41. add_head_html()
  42. add_header()
  43. with ui.row().classes('w-full h-screen items-center gap-16 no-wrap').style(f'transform: translateX(-250px)'):
  44. svg.face().classes('stroke-black w-[500px]')
  45. with ui.column().classes('gap-8'):
  46. title('Meet the *NiceGUI*.')
  47. subtitle('And let any browser be the frontend\n\nof your Python code.')
  48. with ui.link(target='#about') \
  49. .classes('column mt-6 items-center ml-[-12px] hover:translate-y-1 duration-100 ease-out'):
  50. ui.icon('keyboard_arrow_down').classes('text-4xl text-grey-5 mb-[-0.95em]')
  51. ui.icon('keyboard_arrow_down').classes('text-6xl text-black')
  52. ui.icon('keyboard_arrow_down').classes('text-4xl text-grey-5 mt-[-0.85em]')
  53. with ui.row().classes('dark-box h-screen items-center gap-28 p-32 no-wrap'):
  54. link_target('about')
  55. with ui.column().classes('gap-6 text-white'):
  56. heading('Interact with Python through buttons, dialogs, 3D scenes, plots and much more.')
  57. with ui.column().classes('gap-2 text-xl bold-links arrow-links'):
  58. ui.markdown(
  59. 'NiceGUI handles all the web development details for you. '
  60. 'So you can focus on writing Python code. '
  61. 'Anything from short scripts and dashboards to full robotics projects, IoT solutions, '
  62. 'smart home automations and machine learning projects can benefit from having all code in one place.'
  63. )
  64. ui.markdown(
  65. 'Available as '
  66. '[PyPI package](https://pypi.org/project/nicegui/), '
  67. '[Docker image](https://hub.docker.com/r/zauberzeug/nicegui) and on '
  68. '[GitHub](https://github.com/zauberzeug/nicegui).')
  69. demo_card.create()
  70. with ui.column().classes('w-full q-pa-xl q-mb-xl bold-links'):
  71. link_target('features', '-50px')
  72. section_heading('Features', 'Code *nicely*')
  73. with ui.row().classes('w-full no-wrap text-lg leading-tight justify-between q-mb-xl'):
  74. features('swap_horiz', 'Interaction', [
  75. 'buttons, switches, sliders, inputs, ...',
  76. 'notifications, dialogs and menus',
  77. 'keyboard input',
  78. 'on-screen joystick',
  79. ])
  80. features('space_dashboard', 'Layout', [
  81. 'navigation bars, tabs, panels, ...',
  82. 'grouping with rows, columns and cards',
  83. 'HTML and markdown elements',
  84. 'flex layout by default',
  85. ])
  86. features('insights', 'Visualization', [
  87. 'charts, diagrams and tables',
  88. '3D scenes',
  89. 'progress bars',
  90. 'built-in timer for data refresh',
  91. ])
  92. with ui.row().classes('w-full no-wrap text-lg leading-tight justify-between'):
  93. features('brush', 'Styling', [
  94. 'customizable color themes',
  95. 'custom CSS and classes',
  96. 'modern look with material design',
  97. 'built-in [Tailwind](https://tailwindcss.com/) support',
  98. ])
  99. features('source', 'Coding', [
  100. 'live-cycle events',
  101. 'implicit reload on code change',
  102. 'straight-forward data binding',
  103. 'execute javascript from Python',
  104. ])
  105. features('anchor', 'Foundation', [
  106. 'generic [Vue](https://vuejs.org/) to Python bridge',
  107. 'dynamic GUI through [Quasar](https://quasar.dev/)',
  108. 'content is served with [FastAPI](http://fastapi.tiangolo.com/)',
  109. 'Python 3.7+',
  110. ])
  111. with ui.column().classes('w-full q-pa-xl q-mb-xl'):
  112. link_target('installation', '-50px')
  113. section_heading('Installation', 'Get *started*')
  114. with ui.row().classes('w-full no-wrap text-lg leading-tight'):
  115. with ui.column().classes('w-1/3 gap-2'):
  116. ui.html('<em>1.</em>').classes('text-3xl text-bold')
  117. ui.markdown('Create __main.py__').classes('text-lg')
  118. with python_window(classes='w-full h-52'):
  119. ui.markdown('''```python\n
  120. from nicegui import ui
  121. ui.label('Hello NiceGUI!')
  122. ui.run()
  123. ```''')
  124. with ui.column().classes('w-1/3 gap-2'):
  125. ui.html('<em>2.</em>').classes('text-3xl text-bold')
  126. ui.markdown('Install and launch').classes('text-lg')
  127. with bash_window(classes='w-full h-52'):
  128. ui.markdown('```bash\npip3 install nicegui\npython3 main.py\n```')
  129. with ui.column().classes('w-1/3 gap-2'):
  130. ui.html('<em>3.</em>').classes('text-3xl text-bold')
  131. ui.markdown('Enjoy').classes('text-lg')
  132. with browser_window(classes='w-full h-52'):
  133. ui.label('Hello NiceGUI!')
  134. with ui.column().classes('w-full q-pa-xl q-mb-xl'):
  135. link_target('examples', '-50px')
  136. section_heading('Examples', 'Try *this*')
  137. with ui.row().classes('justify-center w-full'), ui.column().classes('w-[65rem]'):
  138. reference.create_intro()
  139. with ui.row().classes('dark-box items-center gap-28 px-32 py-16'):
  140. with ui.column().classes('gap-2'):
  141. ui.markdown('Browse through plenty of live examples.').classes('text-3xl text-white font-medium')
  142. ui.html('Fun-Fact: This whole website is also coded with NiceGUI.').classes('text-xl text-white')
  143. ui.link('API reference', '/reference').classes('rounded-full mx-auto px-12 py-2 text-xl text-bold bg-white')
  144. with ui.column().classes('w-full q-pa-xl q-mb-xl'):
  145. link_target('demos', '-50px')
  146. section_heading('In-depth demonstrations', 'Pick your *solution*')
  147. with ui.row().classes('w-full no-wrap text-lg leading-tight'):
  148. with ui.column().classes('w-1/3'):
  149. example_link('Slideshow', 'implements a keyboard-controlled image slideshow')
  150. example_link('Authentication', 'shows how to use sessions to build a login screen')
  151. example_link(
  152. 'Modularization',
  153. 'provides an example of how to modularize your application into multiple files and reuse code')
  154. example_link(
  155. 'FastAPI',
  156. 'illustrates the integration of NiceGUI with an existing FastAPI application')
  157. with ui.column().classes('w-1/3'):
  158. example_link(
  159. 'Map',
  160. 'demonstrates wrapping the JavaScript library [leaflet](https://leafletjs.com/) to display a map at specific locations')
  161. example_link(
  162. 'AI Interface',
  163. 'utilizes the [replicate](https://replicate.com) library to perform voice-to-text transcription and generate images from prompts with Stable Diffusion')
  164. example_link('3D Scene', 'creates a webGL view and loads an STL mesh illuminated with a spotlight')
  165. with ui.column().classes('w-1/3'):
  166. example_link('Custom Vue Component', 'shows how to write and integrate a custom Vue component')
  167. example_link('Image Mask Overlay', 'shows how to overlay an image with a mask')
  168. example_link('Infinite Scroll', 'presents an infinitely scrolling image gallery')
  169. with ui.row().classes('dark-box h-screen items-center gap-28 p-32 no-wrap'):
  170. link_target('why')
  171. with ui.column().classes('gap-8'):
  172. heading('Why?')
  173. with ui.column().classes('gap-2 text-xl text-white bold-links arrow-links'):
  174. ui.markdown(
  175. 'We like '
  176. '[Streamlit](https://streamlit.io/) '
  177. 'but find it does '
  178. '[too much magic](https://github.com/zauberzeug/nicegui/issues/1#issuecomment-847413651) '
  179. 'when it comes to state handling. '
  180. 'In search for an alternative nice library to write simple graphical user interfaces in Python we discovered '
  181. '[JustPy](https://justpy.io/). '
  182. 'Although we liked the approach, it is too "low-level HTML" for our daily usage. '
  183. 'But it inspired us to use '
  184. '[Vue](https://vuejs.org/) '
  185. 'and '
  186. '[Quasar](https://quasar.dev/) '
  187. 'for the frontend.')
  188. ui.markdown(
  189. 'We have built on top of '
  190. '[FastAPI](https://fastapi.tiangolo.com/), '
  191. 'which itself is based on the ASGI framework '
  192. '[Starlette](https://www.starlette.io/) '
  193. 'and the ASGI webserver '
  194. '[Uvicorn](https://www.uvicorn.org/) '
  195. 'because of their great performance and ease of use.'
  196. )
  197. svg.face().classes('stroke-white w-[1500px]')
  198. @ui.page('/reference')
  199. def reference_page():
  200. add_head_html()
  201. add_header()
  202. reference.create_full()
  203. ui.run(uvicorn_reload_includes='*.py, *.css, *.html')