Browse Source
## 🚀 Major New Features ### Complete Component Ecosystem - **Card Components**: `bg.card()`, `bg.card_section()`, `bg.card_actions()` with NiceGUI-style API - **Tab Navigation**: `bg.tabs()`, `bg.tab()`, `bg.tab_panels()`, `bg.tab_panel()` for interactive content - **Layout Components**: `bg.header()`, `bg.footer()` with context manager support - **Media Components**: `bg.image()`, `bg.icon()` with Material Design icon integration ### Enhanced Responsive Design - **Flex Utilities**: Added Quasar flex classes (`wrap`, `col-12 col-md-4`) to prevent overflow - **Context Manager Excellence**: Fixed AttributeError issues with proper component access patterns - **Material Design**: Full icon library support with color, size, and styling options ### Developer Experience Revolution - **Comprehensive Examples**: 7+ new example files demonstrating all components and patterns - **Context Manager Guide**: Detailed documentation for proper usage patterns - **Overflow Prevention**: Responsive layout patterns that prevent UI overflow issues ## 🔧 Technical Improvements ### Core Framework - Enhanced `Component` class with proper Vue.js component mapping - Added Quasar component mapping (`q-card`, `q-tabs`, `q-img`, `q-icon`, etc.) - Fixed context manager attribute access for all container components ### API Consistency - All components support NiceGUI-style method chaining - Consistent `.classes()`, `.props()`, `.style()` method support - Proper context manager patterns: `with bg.component() as name:` → `name.classes()` ## 📁 Files Added/Modified ### New Example Files - `simple_card_test.py` - Card component demonstrations - `simple_image_icon_test.py` - Image and icon usage examples - `tabs_examples.py` - Tab navigation and content management - `simple_header_footer_test.py` - Layout component examples - `flex_layout_test.py` - Responsive layout and overflow prevention - `enhanced_navigation_example.py` - Complete website showcase - `context_manager_guide.py` - Comprehensive usage guide ### Documentation Updates - Updated `README.md` with new component showcase and responsive examples - Enhanced `docs/source/components.rst` with all new components - Expanded `docs/source/examples.rst` with comprehensive usage patterns - Added `CHANGELOG.md` with detailed release notes ### Core Framework - `badgui/core.py` - Added all new components with proper Quasar mapping - `badgui/__init__.py` - Added convenience functions for all new components - `badgui/generator.py` - Removed blue header bar from default layout - Version bump to 0.2.0 ## 🎯 Key Usage Patterns Established ### Context Manager Excellence ```python # ✅ Correct pattern (now documented and examples provided) with bg.card() as my_card: my_card.classes("q-ma-md") with bg.card_section(): bg.label("Content") ``` ### Responsive Design ```python # Overflow prevention with proper flex utilities with bg.row() as grid: grid.classes("q-gutter-md wrap") # Prevents overflow with bg.card() as card: card.classes("col-12 col-sm-6 col-md-4") # Responsive breakpoints ``` ### Material Design Integration ```python # Full Material Design icon support bg.icon("home", size="2rem", color="primary") bg.image("https://example.com/image.jpg").classes("rounded-lg full-width") ``` ## 🚀 Impact & Value ### For Developers - **Zero Breaking Changes**: All existing code continues to work - **Enhanced Productivity**: Complete UI component suite reduces development time - **Better Documentation**: Comprehensive examples and usage guides - **Responsive by Default**: Built-in overflow prevention and mobile-first design ### For Applications - **Professional UI**: Material Design components with Quasar integration - **Mobile Responsive**: Proper breakpoints and flex utilities - **Modern Architecture**: Vue.js 3 + Quasar Framework output - **Instant Development**: `bg.dev()` workflow unchanged and enhanced ## 🎨 Component Coverage **Now Complete:** - ✅ Basic: `label`, `button`, `input`, `link` - ✅ Cards: `card`, `card_section`, `card_actions` - ✅ Tabs: `tabs`, `tab`, `tab_panels`, `tab_panel` - ✅ Layout: `header`, `footer`, `row`, `column` - ✅ Media: `image`, `icon` - ✅ Navigation: Router links with Vue Router **Foundation for Future:** - 🚧 Forms, Dialogs, Tables, Menus - 🚧 Advanced interactions and data binding - 🚧 Theming and customization system This release establishes BadGUI as a complete UI framework for building modern, responsive web applications with Python syntax. The comprehensive example suite and documentation ensure developers can immediately leverage all new capabilities. --- **Migration**: No changes required - all new features are additive **Compatibility**: Full backward compatibility maintained **Testing**: All examples tested with `bg.dev()` instant developmentmaster
39 changed files with 5639 additions and 147 deletions
@ -1,4 +1,5 @@ |
|||||||
example-output/ |
example-output/ |
||||||
venv/ |
venv/ |
||||||
__pycache__/ |
__pycache__/ |
||||||
*.pyc |
*.pyc |
||||||
|
docs/build/ |
||||||
@ -0,0 +1,170 @@ |
|||||||
|
# BadGUI Changelog |
||||||
|
|
||||||
|
## Version 0.2.0 - September 28, 2025 |
||||||
|
|
||||||
|
### 🎉 Major New Features |
||||||
|
|
||||||
|
#### **Complete UI Component Suite** |
||||||
|
- **Card Components**: Added `bg.card()`, `bg.card_section()`, and `bg.card_actions()` with full NiceGUI-style API |
||||||
|
- **Tab Navigation**: Implemented `bg.tabs()`, `bg.tab()`, `bg.tab_panels()`, and `bg.tab_panel()` for interactive content organization |
||||||
|
- **Layout Components**: Added `bg.header()` and `bg.footer()` with context manager support for complete page layouts |
||||||
|
- **Media Components**: Introduced `bg.image()` and `bg.icon()` with Material Design icon integration |
||||||
|
|
||||||
|
#### **Enhanced Styling & Responsive Design** |
||||||
|
- **Responsive Flex Utilities**: Added proper Quasar flex classes (`wrap`, `col-12 col-md-4`, etc.) to prevent card overflow |
||||||
|
- **Context Manager Improvements**: Fixed all context manager patterns for proper component nesting |
||||||
|
- **Material Design Integration**: Full Material Design icon library support with color and sizing options |
||||||
|
|
||||||
|
#### **Developer Experience Improvements** |
||||||
|
- **Comprehensive Examples**: Added 6+ new example files demonstrating all components and patterns |
||||||
|
- **Context Manager Guide**: Created detailed documentation for proper context manager usage |
||||||
|
- **Overflow Prevention**: Implemented responsive layout patterns that prevent UI overflow issues |
||||||
|
|
||||||
|
### 🔧 Technical Improvements |
||||||
|
|
||||||
|
#### **Component System** |
||||||
|
- Enhanced `Component` class with proper Vue.js component mapping |
||||||
|
- Added Quasar component mapping for all new components (`q-card`, `q-tabs`, `q-img`, `q-icon`, etc.) |
||||||
|
- Improved context manager yields for proper component access |
||||||
|
|
||||||
|
#### **Layout System** |
||||||
|
- Fixed context manager attribute access issues (`AttributeError` with `.classes()`) |
||||||
|
- Added proper responsive breakpoint support |
||||||
|
- Implemented flex wrapping utilities for overflow prevention |
||||||
|
|
||||||
|
#### **API Consistency** |
||||||
|
- All components now support NiceGUI-style method chaining |
||||||
|
- Consistent `.classes()`, `.props()`, and `.style()` method support |
||||||
|
- Proper context manager patterns across all container components |
||||||
|
|
||||||
|
### 📁 New Files Added |
||||||
|
|
||||||
|
#### **Example Files** |
||||||
|
- `simple_card_test.py` - Card component demonstrations |
||||||
|
- `simple_image_icon_test.py` - Image and icon usage examples |
||||||
|
- `tabs_examples.py` - Tab navigation and content management |
||||||
|
- `simple_header_footer_test.py` - Layout component examples |
||||||
|
- `flex_layout_test.py` - Responsive layout and overflow prevention |
||||||
|
- `enhanced_navigation_example.py` - Complete website with all components |
||||||
|
- `context_manager_guide.py` - Comprehensive usage guide |
||||||
|
|
||||||
|
#### **Documentation Updates** |
||||||
|
- Updated `README.md` with new component showcase |
||||||
|
- Enhanced `docs/source/components.rst` with all new components |
||||||
|
- Expanded `docs/source/examples.rst` with comprehensive examples |
||||||
|
|
||||||
|
### 🎯 Key Usage Patterns Established |
||||||
|
|
||||||
|
#### **Context Manager Pattern** |
||||||
|
```python |
||||||
|
# ✅ Correct usage |
||||||
|
with bg.card() as my_card: |
||||||
|
my_card.classes("q-ma-md") |
||||||
|
with bg.card_section(): |
||||||
|
bg.label("Content") |
||||||
|
|
||||||
|
# ❌ Wrong usage (fixed) |
||||||
|
# with bg.card().classes("q-ma-md"): # AttributeError resolved |
||||||
|
``` |
||||||
|
|
||||||
|
#### **Responsive Layout Pattern** |
||||||
|
```python |
||||||
|
# Proper flex wrapping to prevent overflow |
||||||
|
with bg.row() as responsive_row: |
||||||
|
responsive_row.classes("q-gutter-md wrap") |
||||||
|
|
||||||
|
with bg.card() as responsive_card: |
||||||
|
responsive_card.classes("col-12 col-sm-6 col-md-4") # Responsive breakpoints |
||||||
|
``` |
||||||
|
|
||||||
|
#### **Material Design Integration** |
||||||
|
```python |
||||||
|
# Material Design icons with full customization |
||||||
|
bg.icon("home", size="2rem", color="primary") |
||||||
|
bg.icon("star", color="yellow").classes("q-mr-sm") |
||||||
|
``` |
||||||
|
|
||||||
|
### 🔄 Breaking Changes |
||||||
|
- None - All changes are backward compatible |
||||||
|
- Existing code continues to work unchanged |
||||||
|
- New components are purely additive |
||||||
|
|
||||||
|
### 🚀 Instant Development |
||||||
|
- All new components work seamlessly with `bg.dev()` instant development mode |
||||||
|
- Examples automatically build and run with single command execution |
||||||
|
- Hot reload support for all new components |
||||||
|
|
||||||
|
### 📊 Component Coverage |
||||||
|
|
||||||
|
**Now Available:** |
||||||
|
- ✅ Basic Components: `label`, `button`, `input`, `link` |
||||||
|
- ✅ Card Components: `card`, `card_section`, `card_actions` |
||||||
|
- ✅ Tab Components: `tabs`, `tab`, `tab_panels`, `tab_panel` |
||||||
|
- ✅ Layout Components: `header`, `footer`, `row`, `column` |
||||||
|
- ✅ Media Components: `image`, `icon` |
||||||
|
- ✅ Navigation: Router links with Vue Router integration |
||||||
|
|
||||||
|
**Coming Next:** |
||||||
|
- 🚧 Form Components: `form`, `select`, `checkbox`, `radio` |
||||||
|
- 🚧 Dialog Components: `dialog`, `popup`, `tooltip` |
||||||
|
- 🚧 Data Components: `table`, `list`, `tree` |
||||||
|
- 🚧 Advanced Components: `menu`, `toolbar`, `drawer` |
||||||
|
|
||||||
|
### 🎨 Design Philosophy |
||||||
|
|
||||||
|
BadGUI now provides a complete foundation for building modern web applications: |
||||||
|
|
||||||
|
1. **NiceGUI Compatibility**: Familiar syntax and patterns for easy migration |
||||||
|
2. **Material Design**: Professional, consistent UI components |
||||||
|
3. **Responsive by Default**: Mobile-first design with proper breakpoints |
||||||
|
4. **Context Manager Excellence**: Proper Python patterns for UI nesting |
||||||
|
5. **Vue.js Power**: Modern web framework output with Quasar components |
||||||
|
|
||||||
|
--- |
||||||
|
|
||||||
|
## Version 0.1.0 - Previous Release |
||||||
|
|
||||||
|
### Initial Features |
||||||
|
- Basic component system (`label`, `button`, `input`, `link`) |
||||||
|
- Layout containers (`row`, `column`) with context managers |
||||||
|
- Vue.js/Quasar project generation |
||||||
|
- Instant development mode with `bg.dev()` |
||||||
|
- Multi-page routing with Vue Router |
||||||
|
- Styling system (`.classes()`, `.props()`, `.style()`) |
||||||
|
|
||||||
|
--- |
||||||
|
|
||||||
|
## Upgrade Guide |
||||||
|
|
||||||
|
### From 0.1.0 to 0.2.0 |
||||||
|
|
||||||
|
No breaking changes required. Simply update your BadGUI installation and start using the new components: |
||||||
|
|
||||||
|
```bash |
||||||
|
pip install --upgrade badgui |
||||||
|
``` |
||||||
|
|
||||||
|
### New Components Available |
||||||
|
```python |
||||||
|
import badgui as bg |
||||||
|
|
||||||
|
# Cards |
||||||
|
with bg.card() as my_card: |
||||||
|
with bg.card_section(): |
||||||
|
bg.label("Card content") |
||||||
|
|
||||||
|
# Tabs |
||||||
|
with bg.tabs(): |
||||||
|
with bg.tab("tab1", "Tab 1"): |
||||||
|
pass |
||||||
|
|
||||||
|
# Layout |
||||||
|
with bg.header(): |
||||||
|
bg.label("Header content") |
||||||
|
|
||||||
|
# Media |
||||||
|
bg.image("image.jpg") |
||||||
|
bg.icon("home", color="primary") |
||||||
|
``` |
||||||
|
|
||||||
|
All examples in the repository demonstrate the new components and proper usage patterns. |
||||||
@ -0,0 +1,20 @@ |
|||||||
|
# Minimal makefile for Sphinx documentation
|
||||||
|
#
|
||||||
|
|
||||||
|
# You can set these variables from the command line, and also
|
||||||
|
# from the environment for the first two.
|
||||||
|
SPHINXOPTS ?=
|
||||||
|
SPHINXBUILD ?= sphinx-build
|
||||||
|
SOURCEDIR = source
|
||||||
|
BUILDDIR = build
|
||||||
|
|
||||||
|
# Put it first so that "make" without argument is like "make help".
|
||||||
|
help: |
||||||
|
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||||
|
|
||||||
|
.PHONY: help Makefile |
||||||
|
|
||||||
|
# Catch-all target: route all unknown targets to Sphinx using the new
|
||||||
|
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
||||||
|
%: Makefile |
||||||
|
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||||
@ -0,0 +1,35 @@ |
|||||||
|
@ECHO OFF |
||||||
|
|
||||||
|
pushd %~dp0 |
||||||
|
|
||||||
|
REM Command file for Sphinx documentation |
||||||
|
|
||||||
|
if "%SPHINXBUILD%" == "" ( |
||||||
|
set SPHINXBUILD=sphinx-build |
||||||
|
) |
||||||
|
set SOURCEDIR=source |
||||||
|
set BUILDDIR=build |
||||||
|
|
||||||
|
%SPHINXBUILD% >NUL 2>NUL |
||||||
|
if errorlevel 9009 ( |
||||||
|
echo. |
||||||
|
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx |
||||||
|
echo.installed, then set the SPHINXBUILD environment variable to point |
||||||
|
echo.to the full path of the 'sphinx-build' executable. Alternatively you |
||||||
|
echo.may add the Sphinx directory to PATH. |
||||||
|
echo. |
||||||
|
echo.If you don't have Sphinx installed, grab it from |
||||||
|
echo.https://www.sphinx-doc.org/ |
||||||
|
exit /b 1 |
||||||
|
) |
||||||
|
|
||||||
|
if "%1" == "" goto help |
||||||
|
|
||||||
|
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% |
||||||
|
goto end |
||||||
|
|
||||||
|
:help |
||||||
|
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% |
||||||
|
|
||||||
|
:end |
||||||
|
popd |
||||||
@ -0,0 +1,7 @@ |
|||||||
|
badgui.components module |
||||||
|
======================== |
||||||
|
|
||||||
|
.. automodule:: badgui.components |
||||||
|
:members: |
||||||
|
:show-inheritance: |
||||||
|
:undoc-members: |
||||||
@ -0,0 +1,7 @@ |
|||||||
|
badgui.core module |
||||||
|
================== |
||||||
|
|
||||||
|
.. automodule:: badgui.core |
||||||
|
:members: |
||||||
|
:show-inheritance: |
||||||
|
:undoc-members: |
||||||
@ -0,0 +1,7 @@ |
|||||||
|
badgui.generator module |
||||||
|
======================= |
||||||
|
|
||||||
|
.. automodule:: badgui.generator |
||||||
|
:members: |
||||||
|
:show-inheritance: |
||||||
|
:undoc-members: |
||||||
@ -0,0 +1,7 @@ |
|||||||
|
badgui.layouts module |
||||||
|
===================== |
||||||
|
|
||||||
|
.. automodule:: badgui.layouts |
||||||
|
:members: |
||||||
|
:show-inheritance: |
||||||
|
:undoc-members: |
||||||
@ -0,0 +1,21 @@ |
|||||||
|
badgui package |
||||||
|
============== |
||||||
|
|
||||||
|
Submodules |
||||||
|
---------- |
||||||
|
|
||||||
|
.. toctree:: |
||||||
|
:maxdepth: 4 |
||||||
|
|
||||||
|
badgui.components |
||||||
|
badgui.core |
||||||
|
badgui.generator |
||||||
|
badgui.layouts |
||||||
|
|
||||||
|
Module contents |
||||||
|
--------------- |
||||||
|
|
||||||
|
.. automodule:: badgui |
||||||
|
:members: |
||||||
|
:show-inheritance: |
||||||
|
:undoc-members: |
||||||
@ -0,0 +1,7 @@ |
|||||||
|
badgui |
||||||
|
====== |
||||||
|
|
||||||
|
.. toctree:: |
||||||
|
:maxdepth: 4 |
||||||
|
|
||||||
|
badgui |
||||||
@ -0,0 +1,400 @@ |
|||||||
|
Components |
||||||
|
========== |
||||||
|
|
||||||
|
BadGUI provides a comprehensive set of components that map to Quasar Framework components, giving you access to a rich, Material Design-based UI library. All components support NiceGUI-style method chaining and proper context manager patterns. |
||||||
|
|
||||||
|
Base Component |
||||||
|
-------------- |
||||||
|
|
||||||
|
All BadGUI components inherit from the ``Component`` class, which provides common styling methods. |
||||||
|
|
||||||
|
.. autoclass:: badgui.core.Component |
||||||
|
:members: |
||||||
|
:undoc-members: |
||||||
|
|
||||||
|
Text Components |
||||||
|
--------------- |
||||||
|
|
||||||
|
Label |
||||||
|
~~~~~ |
||||||
|
|
||||||
|
The ``label`` component creates text elements and headings. |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
import badgui as bg |
||||||
|
|
||||||
|
# Basic label |
||||||
|
bg.label("Hello World") |
||||||
|
|
||||||
|
# With styling |
||||||
|
bg.label("Title").classes("text-h3 text-primary") |
||||||
|
bg.label("Subtitle").classes("text-h6 text-grey-7") |
||||||
|
|
||||||
|
# With inline styles |
||||||
|
bg.label("Custom").style("color: red; font-weight: bold") |
||||||
|
|
||||||
|
**Generated Output:** ``<q-item-label>`` |
||||||
|
|
||||||
|
Input Components |
||||||
|
---------------- |
||||||
|
|
||||||
|
Input |
||||||
|
~~~~~ |
||||||
|
|
||||||
|
The ``input`` component creates text input fields. |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
# Basic input |
||||||
|
bg.input(placeholder="Enter text") |
||||||
|
|
||||||
|
# Styled input |
||||||
|
bg.input(placeholder="Name").props("filled dense") |
||||||
|
bg.input(placeholder="Email").props('outlined label="Email Address"') |
||||||
|
|
||||||
|
# With validation styling |
||||||
|
bg.input().classes("q-mb-md").props("filled error-message=Required") |
||||||
|
|
||||||
|
**Generated Output:** ``<q-input>`` |
||||||
|
|
||||||
|
Interactive Components |
||||||
|
---------------------- |
||||||
|
|
||||||
|
Button |
||||||
|
~~~~~~ |
||||||
|
|
||||||
|
The ``button`` component creates clickable buttons. |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
# Basic button |
||||||
|
bg.button("Click Me") |
||||||
|
|
||||||
|
# Styled buttons |
||||||
|
bg.button("Primary").props("color=primary") |
||||||
|
bg.button("Secondary").props("color=secondary outline") |
||||||
|
bg.button("Icon").props("icon=star push") |
||||||
|
|
||||||
|
# With custom styling |
||||||
|
bg.button("Custom").classes("my-custom-button").style("border-radius: 20px") |
||||||
|
|
||||||
|
**Generated Output:** ``<q-btn>`` |
||||||
|
|
||||||
|
Card Components |
||||||
|
--------------- |
||||||
|
|
||||||
|
Card |
||||||
|
~~~~ |
||||||
|
|
||||||
|
The ``card`` component creates Material Design cards for grouping content. |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
# Basic card |
||||||
|
with bg.card() as my_card: |
||||||
|
my_card.classes("q-ma-md") |
||||||
|
with bg.card_section(): |
||||||
|
bg.label("Card Title").classes("text-h5") |
||||||
|
bg.label("Card content goes here") |
||||||
|
|
||||||
|
**Generated Output:** ``<q-card>`` |
||||||
|
|
||||||
|
Card Section |
||||||
|
~~~~~~~~~~~~ |
||||||
|
|
||||||
|
The ``card_section`` component creates sections within cards. |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
with bg.card(): |
||||||
|
with bg.card_section(): |
||||||
|
bg.label("Main content") |
||||||
|
with bg.card_section(): |
||||||
|
bg.label("Additional content") |
||||||
|
|
||||||
|
**Generated Output:** ``<q-card-section>`` |
||||||
|
|
||||||
|
Card Actions |
||||||
|
~~~~~~~~~~~~ |
||||||
|
|
||||||
|
The ``card_actions`` component creates action areas in cards. |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
with bg.card(): |
||||||
|
with bg.card_section(): |
||||||
|
bg.label("Card content") |
||||||
|
with bg.card_actions(): |
||||||
|
bg.button("Action 1") |
||||||
|
bg.button("Action 2") |
||||||
|
|
||||||
|
**Generated Output:** ``<q-card-actions>`` |
||||||
|
|
||||||
|
Tab Components |
||||||
|
-------------- |
||||||
|
|
||||||
|
Tabs |
||||||
|
~~~~ |
||||||
|
|
||||||
|
The ``tabs`` component creates tab navigation. |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
with bg.tabs() as main_tabs: |
||||||
|
main_tabs.classes("text-primary") |
||||||
|
with bg.tab("tab1", "Tab 1"): |
||||||
|
pass |
||||||
|
with bg.tab("tab2", "Tab 2"): |
||||||
|
pass |
||||||
|
|
||||||
|
**Generated Output:** ``<q-tabs>`` |
||||||
|
|
||||||
|
Tab |
||||||
|
~~~ |
||||||
|
|
||||||
|
The ``tab`` component creates individual tab items. |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
with bg.tabs(): |
||||||
|
with bg.tab("home", "Home"): |
||||||
|
pass # Tab content defined in tab_panel |
||||||
|
|
||||||
|
**Generated Output:** ``<q-tab>`` |
||||||
|
|
||||||
|
Tab Panels |
||||||
|
~~~~~~~~~~ |
||||||
|
|
||||||
|
The ``tab_panels`` component creates content containers for tabs. |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
with bg.tab_panels() as panels: |
||||||
|
panels.classes("q-pa-md") |
||||||
|
with bg.tab_panel("tab1"): |
||||||
|
bg.label("Content for Tab 1") |
||||||
|
with bg.tab_panel("tab2"): |
||||||
|
bg.label("Content for Tab 2") |
||||||
|
|
||||||
|
**Generated Output:** ``<q-tab-panels>`` |
||||||
|
|
||||||
|
Layout Components |
||||||
|
----------------- |
||||||
|
|
||||||
|
Header |
||||||
|
~~~~~~ |
||||||
|
|
||||||
|
The ``header`` component creates page headers with navigation. |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
with bg.header() as page_header: |
||||||
|
page_header.classes("bg-primary text-white q-pa-md") |
||||||
|
with bg.row() as nav_row: |
||||||
|
nav_row.classes("items-center justify-between") |
||||||
|
bg.label("Site Title").classes("text-h4") |
||||||
|
# Navigation items... |
||||||
|
|
||||||
|
**Generated Output:** ``<q-header>`` |
||||||
|
|
||||||
|
Footer |
||||||
|
~~~~~~ |
||||||
|
|
||||||
|
The ``footer`` component creates page footers. |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
with bg.footer() as page_footer: |
||||||
|
page_footer.classes("bg-dark text-white q-pa-md") |
||||||
|
bg.label("© 2024 My Website. Built with BadGUI.") |
||||||
|
|
||||||
|
**Generated Output:** ``<q-footer>`` |
||||||
|
|
||||||
|
Media Components |
||||||
|
---------------- |
||||||
|
|
||||||
|
Image |
||||||
|
~~~~~ |
||||||
|
|
||||||
|
The ``image`` component displays images with Quasar's optimized image loading. |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
# Basic image |
||||||
|
bg.image("https://example.com/image.jpg") |
||||||
|
|
||||||
|
# With styling |
||||||
|
bg.image("https://picsum.photos/300/200").classes("rounded-lg shadow-md") |
||||||
|
|
||||||
|
# Responsive image |
||||||
|
bg.image("/local/image.png").classes("full-width") |
||||||
|
|
||||||
|
**Generated Output:** ``<q-img>`` |
||||||
|
|
||||||
|
Icon |
||||||
|
~~~~ |
||||||
|
|
||||||
|
The ``icon`` component displays Material Design icons. |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
# Basic icon |
||||||
|
bg.icon("home") |
||||||
|
|
||||||
|
# With color and size |
||||||
|
bg.icon("star", color="yellow", size="2rem") |
||||||
|
|
||||||
|
# With styling |
||||||
|
bg.icon("favorite", color="red").classes("q-mr-sm") |
||||||
|
|
||||||
|
**Generated Output:** ``<q-icon>`` |
||||||
|
|
||||||
|
Navigation Components |
||||||
|
|
||||||
|
Link |
||||||
|
~~~~ |
||||||
|
|
||||||
|
The ``link`` component creates router navigation links. |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
# Basic link |
||||||
|
bg.link("Home", "/") |
||||||
|
|
||||||
|
# Styled as button |
||||||
|
bg.link("About", "/about").classes("q-btn q-btn-primary") |
||||||
|
|
||||||
|
# With props |
||||||
|
bg.link("Contact", "/contact").props("exact") |
||||||
|
|
||||||
|
**Generated Output:** ``<router-link>`` |
||||||
|
|
||||||
|
Layout Components |
||||||
|
----------------- |
||||||
|
|
||||||
|
Row |
||||||
|
~~~ |
||||||
|
|
||||||
|
The ``row`` component creates horizontal layout containers. |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
# Basic row |
||||||
|
with bg.row(): |
||||||
|
bg.label("Item 1") |
||||||
|
bg.label("Item 2") |
||||||
|
|
||||||
|
# Styled row |
||||||
|
with bg.row().classes("q-gutter-md justify-center") as row: |
||||||
|
row.style("background: #f5f5f5; padding: 16px") |
||||||
|
bg.button("Button 1") |
||||||
|
bg.button("Button 2") |
||||||
|
|
||||||
|
**Generated Output:** ``<div class="row">`` |
||||||
|
|
||||||
|
Column |
||||||
|
~~~~~~ |
||||||
|
|
||||||
|
The ``column`` component creates vertical layout containers. |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
# Basic column |
||||||
|
with bg.column(): |
||||||
|
bg.label("Item 1") |
||||||
|
bg.label("Item 2") |
||||||
|
|
||||||
|
# Styled column |
||||||
|
with bg.column().classes("q-gutter-sm items-center") as col: |
||||||
|
col.style("min-height: 200px") |
||||||
|
bg.label("Centered Item 1") |
||||||
|
bg.label("Centered Item 2") |
||||||
|
|
||||||
|
**Generated Output:** ``<div class="column">`` |
||||||
|
|
||||||
|
Component Properties |
||||||
|
-------------------- |
||||||
|
|
||||||
|
All components support these common properties: |
||||||
|
|
||||||
|
Classes |
||||||
|
~~~~~~~ |
||||||
|
|
||||||
|
Set CSS classes using the ``.classes()`` method: |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
component.classes("class1 class2 class3") |
||||||
|
component.classes(add="new-class", remove="old-class") |
||||||
|
component.classes(replace="completely-new-classes") |
||||||
|
|
||||||
|
Props |
||||||
|
~~~~~ |
||||||
|
|
||||||
|
Set component properties using the ``.props()`` method: |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
component.props("prop1 prop2=value") |
||||||
|
component.props('prop3="quoted value"') |
||||||
|
component.props(prop4=True, prop5="value") |
||||||
|
|
||||||
|
Styles |
||||||
|
~~~~~~ |
||||||
|
|
||||||
|
Set inline CSS styles using the ``.style()`` method: |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
component.style("color: blue; background: white") |
||||||
|
component.style(color="blue", backgroundColor="white") |
||||||
|
|
||||||
|
Method Chaining |
||||||
|
~~~~~~~~~~~~~~~ |
||||||
|
|
||||||
|
All styling methods return the component, allowing for method chaining: |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
bg.button("Styled Button")\ |
||||||
|
.classes("q-btn-primary q-ma-md")\ |
||||||
|
.props("push icon=star")\ |
||||||
|
.style("border-radius: 10px") |
||||||
|
|
||||||
|
Component Lifecycle |
||||||
|
------------------- |
||||||
|
|
||||||
|
Components are created when you call their factory functions (``bg.label()``, ``bg.button()``, etc.) and are automatically added to the current page context. The component tree is built during Python execution and then converted to Vue.js templates during the build process. |
||||||
|
|
||||||
|
Custom Components |
||||||
|
----------------- |
||||||
|
|
||||||
|
While BadGUI focuses on providing a curated set of components, you can extend the framework by creating custom components: |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
from badgui.core import Component |
||||||
|
import badgui as bg |
||||||
|
|
||||||
|
def custom_card(title, content): |
||||||
|
\"\"\"Create a custom card component.\"\"\" |
||||||
|
component = Component('q-card') |
||||||
|
component.classes("q-ma-md") |
||||||
|
|
||||||
|
# Add title |
||||||
|
title_comp = Component('q-card-section', text=title) |
||||||
|
title_comp.classes("text-h6") |
||||||
|
component.add_child(title_comp) |
||||||
|
|
||||||
|
# Add content |
||||||
|
content_comp = Component('q-card-section', text=content) |
||||||
|
component.add_child(content_comp) |
||||||
|
|
||||||
|
return bg.app._get_current_page()._add_component(component) |
||||||
|
|
||||||
|
# Usage |
||||||
|
with bg.page("/", "CustomDemo"): |
||||||
|
custom_card("My Card", "This is custom card content") |
||||||
|
|
||||||
|
This approach allows you to create reusable custom components while maintaining compatibility with BadGUI's styling system. |
||||||
@ -0,0 +1,67 @@ |
|||||||
|
# Configuration file for the Sphinx documentation builder. |
||||||
|
# |
||||||
|
# For the full list of built-in configuration values, see the documentation: |
||||||
|
# https://www.sphinx-doc.org/en/master/usage/configuration.html |
||||||
|
|
||||||
|
# -- Project information ----------------------------------------------------- |
||||||
|
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information |
||||||
|
|
||||||
|
project = 'BadGUI' |
||||||
|
copyright = '2025, BadGUI Team' |
||||||
|
author = 'BadGUI Team' |
||||||
|
release = '1.0.0' |
||||||
|
|
||||||
|
# -- General configuration --------------------------------------------------- |
||||||
|
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration |
||||||
|
|
||||||
|
import os |
||||||
|
import sys |
||||||
|
sys.path.insert(0, os.path.abspath('../../')) # Add badgui to path |
||||||
|
|
||||||
|
extensions = [ |
||||||
|
'sphinx.ext.autodoc', |
||||||
|
'sphinx.ext.viewcode', |
||||||
|
'sphinx.ext.napoleon', |
||||||
|
'sphinx.ext.intersphinx', |
||||||
|
'sphinx_autodoc_typehints', |
||||||
|
'myst_parser', |
||||||
|
] |
||||||
|
|
||||||
|
templates_path = ['_templates'] |
||||||
|
exclude_patterns = [] |
||||||
|
|
||||||
|
language = 'en' |
||||||
|
|
||||||
|
# -- Options for HTML output ------------------------------------------------- |
||||||
|
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output |
||||||
|
|
||||||
|
html_theme = 'sphinx_rtd_theme' |
||||||
|
html_static_path = ['_static'] |
||||||
|
|
||||||
|
# -- Extension configuration ------------------------------------------------- |
||||||
|
|
||||||
|
# Napoleon settings |
||||||
|
napoleon_google_docstring = True |
||||||
|
napoleon_numpy_docstring = True |
||||||
|
napoleon_include_init_with_doc = False |
||||||
|
napoleon_include_private_with_doc = False |
||||||
|
|
||||||
|
# Intersphinx mapping |
||||||
|
intersphinx_mapping = { |
||||||
|
'python': ('https://docs.python.org/3', None), |
||||||
|
} |
||||||
|
|
||||||
|
# MyST parser settings |
||||||
|
myst_heading_anchors = 3 |
||||||
|
myst_enable_extensions = [ |
||||||
|
"colon_fence", |
||||||
|
"deflist", |
||||||
|
"html_admonition", |
||||||
|
"html_image", |
||||||
|
"linkify", |
||||||
|
"replacements", |
||||||
|
"smartquotes", |
||||||
|
"strikethrough", |
||||||
|
"substitution", |
||||||
|
"tasklist", |
||||||
|
] |
||||||
@ -0,0 +1,248 @@ |
|||||||
|
Development Mode |
||||||
|
================ |
||||||
|
|
||||||
|
BadGUI provides two development workflows: **Instant Development** with ``bg.dev()`` and **Static Project Generation** with ``bg.build()``. |
||||||
|
|
||||||
|
Instant Development with bg.dev() |
||||||
|
---------------------------------- |
||||||
|
|
||||||
|
The ``bg.dev()`` method provides the fastest development experience by automatically: |
||||||
|
|
||||||
|
1. Creating a temporary project build |
||||||
|
2. Installing npm dependencies |
||||||
|
3. Starting the development server |
||||||
|
4. Opening your app in the browser |
||||||
|
5. Cleaning up temporary files on exit |
||||||
|
|
||||||
|
Basic Usage |
||||||
|
~~~~~~~~~~~ |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
import badgui as bg |
||||||
|
|
||||||
|
with bg.page("/", "HomePage", "My App"): |
||||||
|
bg.label("Hello World!").classes("text-h3 text-primary") |
||||||
|
bg.button("Click Me").classes("q-btn-primary") |
||||||
|
|
||||||
|
# 🚀 One command does it all! |
||||||
|
bg.dev() |
||||||
|
|
||||||
|
Run your script:: |
||||||
|
|
||||||
|
python my_app.py |
||||||
|
|
||||||
|
The server starts automatically at ``http://localhost:9000``. |
||||||
|
|
||||||
|
Configuration Options |
||||||
|
~~~~~~~~~~~~~~~~~~~~~ |
||||||
|
|
||||||
|
Customize the development server: |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
bg.dev( |
||||||
|
port=3000, # Custom port (default: 9000) |
||||||
|
host="localhost", # Bind to specific host (default: localhost) |
||||||
|
auto_reload=False, # Auto-rebuild on file changes (default: False) |
||||||
|
project_name="my-app" # Temporary project name (default: badgui-dev) |
||||||
|
) |
||||||
|
|
||||||
|
Advanced Example |
||||||
|
~~~~~~~~~~~~~~~~ |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
import badgui as bg |
||||||
|
|
||||||
|
def create_app(): |
||||||
|
with bg.page("/", "HomePage", "Development Demo"): |
||||||
|
bg.label("🚀 Live Development Mode").classes("text-h2 text-center q-mb-lg") |
||||||
|
|
||||||
|
with bg.row().classes("justify-center q-gutter-md") as row: |
||||||
|
bg.button("Primary").classes("q-btn-primary") |
||||||
|
bg.button("Secondary").classes("q-btn-secondary") |
||||||
|
bg.button("Accent").classes("q-btn-accent") |
||||||
|
|
||||||
|
with bg.column().classes("q-mt-lg max-width-sm mx-auto") as form: |
||||||
|
bg.input(placeholder="Name").classes("q-mb-md").props("filled") |
||||||
|
bg.input(placeholder="Email").classes("q-mb-md").props("filled type=email") |
||||||
|
bg.button("Submit").classes("q-btn-primary full-width") |
||||||
|
|
||||||
|
if __name__ == "__main__": |
||||||
|
create_app() |
||||||
|
|
||||||
|
# Development mode with custom settings |
||||||
|
bg.dev( |
||||||
|
port=3000, |
||||||
|
host="0.0.0.0", # Accept connections from any IP |
||||||
|
project_name="live-demo" |
||||||
|
) |
||||||
|
|
||||||
|
Benefits of bg.dev() |
||||||
|
~~~~~~~~~~~~~~~~~~~~ |
||||||
|
|
||||||
|
- **Zero Setup**: No manual ``npm install`` or server commands |
||||||
|
- **Fast Iteration**: Make changes and refresh browser |
||||||
|
- **Temporary Files**: No clutter in your project directory |
||||||
|
- **Automatic Cleanup**: Temp files removed on exit |
||||||
|
- **Cross-Platform**: Works on Windows, macOS, and Linux |
||||||
|
|
||||||
|
Multi-Page Development |
||||||
|
~~~~~~~~~~~~~~~~~~~~~~ |
||||||
|
|
||||||
|
``bg.dev()`` works seamlessly with multi-page applications: |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
import badgui as bg |
||||||
|
|
||||||
|
# Home page |
||||||
|
with bg.page("/", "HomePage", "Home"): |
||||||
|
bg.label("Welcome Home").classes("text-h3") |
||||||
|
bg.link("Go to About", "/about").classes("q-btn q-btn-primary") |
||||||
|
|
||||||
|
# About page |
||||||
|
with bg.page("/about", "AboutPage", "About"): |
||||||
|
bg.label("About Us").classes("text-h3") |
||||||
|
bg.link("Back Home", "/").classes("q-btn q-btn-secondary") |
||||||
|
|
||||||
|
# Contact page |
||||||
|
with bg.page("/contact", "ContactPage", "Contact"): |
||||||
|
bg.label("Contact Us").classes("text-h3") |
||||||
|
bg.input(placeholder="Message").props("filled type=textarea") |
||||||
|
bg.button("Send").classes("q-btn-primary") |
||||||
|
|
||||||
|
# Start development server |
||||||
|
bg.dev(port=8080) |
||||||
|
|
||||||
|
Static Project Generation |
||||||
|
------------------------- |
||||||
|
|
||||||
|
For production deployment or when you need full control over the build process, use ``bg.build()``. |
||||||
|
|
||||||
|
Basic Build |
||||||
|
~~~~~~~~~~~ |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
import badgui as bg |
||||||
|
|
||||||
|
with bg.page("/", "HomePage", "Production App"): |
||||||
|
bg.label("Production Ready").classes("text-h3") |
||||||
|
|
||||||
|
# Generate static project |
||||||
|
bg.build( |
||||||
|
output_dir="./dist", # Output directory |
||||||
|
project_name="my-prod-app", # Project name |
||||||
|
) |
||||||
|
|
||||||
|
Manual Development |
||||||
|
~~~~~~~~~~~~~~~~~~ |
||||||
|
|
||||||
|
After building, you can develop manually:: |
||||||
|
|
||||||
|
cd dist |
||||||
|
npm install |
||||||
|
npm run dev # Development server |
||||||
|
npm run build # Production build |
||||||
|
|
||||||
|
Deployment |
||||||
|
~~~~~~~~~~ |
||||||
|
|
||||||
|
Build for production deployment:: |
||||||
|
|
||||||
|
cd dist |
||||||
|
npm install |
||||||
|
npm run build |
||||||
|
|
||||||
|
# Deploy the dist/ folder contents to your web server |
||||||
|
|
||||||
|
When to Use Each Mode |
||||||
|
--------------------- |
||||||
|
|
||||||
|
**Use bg.dev() when:** |
||||||
|
|
||||||
|
- 🚀 Rapid prototyping and development |
||||||
|
- ⚡ Quick testing of UI changes |
||||||
|
- 🔧 Learning BadGUI features |
||||||
|
- 💻 Local development and experimentation |
||||||
|
|
||||||
|
**Use bg.build() when:** |
||||||
|
|
||||||
|
- 🌐 Preparing for production deployment |
||||||
|
- 📦 Need to customize the build process |
||||||
|
- 🔧 Integrating with CI/CD pipelines |
||||||
|
- 📝 Sharing projects with frontend developers |
||||||
|
|
||||||
|
Best Practices |
||||||
|
-------------- |
||||||
|
|
||||||
|
Development Workflow |
||||||
|
~~~~~~~~~~~~~~~~~~~ |
||||||
|
|
||||||
|
1. **Start with bg.dev()** for rapid development |
||||||
|
2. **Use version control** to track your Python code |
||||||
|
3. **Test different devices** using ``host="0.0.0.0"`` |
||||||
|
4. **Switch to bg.build()** when ready for deployment |
||||||
|
|
||||||
|
Project Organization |
||||||
|
~~~~~~~~~~~~~~~~~~~~ |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
# main.py |
||||||
|
import badgui as bg |
||||||
|
from pages import home, about, contact |
||||||
|
|
||||||
|
def main(): |
||||||
|
home.create_page() |
||||||
|
about.create_page() |
||||||
|
contact.create_page() |
||||||
|
|
||||||
|
if __name__ == "__main__": |
||||||
|
bg.dev(port=3000) |
||||||
|
|
||||||
|
# pages/home.py |
||||||
|
import badgui as bg |
||||||
|
|
||||||
|
def create_page(): |
||||||
|
with bg.page("/", "HomePage", "Home"): |
||||||
|
bg.label("Home Page Content") |
||||||
|
|
||||||
|
Troubleshooting |
||||||
|
--------------- |
||||||
|
|
||||||
|
**Port Already in Use** |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
# Try a different port |
||||||
|
bg.dev(port=3001) |
||||||
|
|
||||||
|
**npm Not Found** |
||||||
|
|
||||||
|
Install Node.js from https://nodejs.org/ |
||||||
|
|
||||||
|
**Permission Errors** |
||||||
|
|
||||||
|
.. code-block:: bash |
||||||
|
|
||||||
|
# Linux/macOS - fix npm permissions |
||||||
|
sudo chown -R $(whoami) ~/.npm |
||||||
|
|
||||||
|
**Slow Dependencies Install** |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
# The first run installs dependencies (can take 1-2 minutes) |
||||||
|
# Subsequent runs are much faster |
||||||
|
|
||||||
|
**Browser Not Opening** |
||||||
|
|
||||||
|
Manually navigate to the URL shown in the terminal output. |
||||||
|
|
||||||
|
Examples |
||||||
|
-------- |
||||||
|
|
||||||
|
Complete examples using ``bg.dev()`` are available in the :doc:`examples` section. |
||||||
@ -0,0 +1,88 @@ |
|||||||
|
.. BadGUI documentation master file, created by |
||||||
|
sphinx-quickstart on Sat Sep 27 21:52:16 2025. |
||||||
|
You can adapt this file completely to your liking, but it should at least |
||||||
|
contain the root `toctree` directive. |
||||||
|
|
||||||
|
BadGUI Documentation |
||||||
|
==================== |
||||||
|
|
||||||
|
.. image:: https://img.shields.io/badge/Python-3.8+-blue.svg |
||||||
|
:target: https://python.org |
||||||
|
:alt: Python Version |
||||||
|
|
||||||
|
.. image:: https://img.shields.io/badge/Framework-Vue.js%203-green.svg |
||||||
|
:target: https://vuejs.org |
||||||
|
:alt: Vue.js 3 |
||||||
|
|
||||||
|
.. image:: https://img.shields.io/badge/UI-Quasar-blue.svg |
||||||
|
:target: https://quasar.dev |
||||||
|
:alt: Quasar Framework |
||||||
|
|
||||||
|
**BadGUI** is a Python framework that generates Vue.js/Quasar projects using syntax similar to NiceGUI. Instead of running a live server, BadGUI creates a complete, editable Vue.js project that you can further customize and deploy. |
||||||
|
|
||||||
|
Key Features |
||||||
|
------------ |
||||||
|
|
||||||
|
- **NiceGUI-like syntax**: Write familiar Python code to define your UI |
||||||
|
- **Vue.js/Quasar output**: Generates modern, responsive web applications |
||||||
|
- **Static project generation**: Creates editable Vue projects, not live servers |
||||||
|
- **🚀 Instant Development**: ``bg.dev()`` creates temp build, installs deps, and starts server automatically |
||||||
|
- **Component-based**: Modular component system for reusable UI elements |
||||||
|
- **Layout system**: Built-in row/column layouts with context managers |
||||||
|
- **Multi-page routing**: Create multiple pages with Vue Router integration |
||||||
|
- **Styling methods**: NiceGUI-style ``.classes()``, ``.props()``, and ``.style()`` methods |
||||||
|
- **Method chaining**: Fluent API for building components |
||||||
|
- **Dual workflow**: Instant dev mode OR static project generation |
||||||
|
|
||||||
|
Quick Start |
||||||
|
----------- |
||||||
|
|
||||||
|
Installation:: |
||||||
|
|
||||||
|
pip install badgui |
||||||
|
|
||||||
|
Basic Usage: |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
import badgui as bg |
||||||
|
|
||||||
|
# Create a page using context manager |
||||||
|
with bg.page("/", "HomePage", "Welcome"): |
||||||
|
# Basic components with styling |
||||||
|
bg.label("Hello BadGUI!").classes("text-h3 text-primary") |
||||||
|
|
||||||
|
# Styled button with method chaining |
||||||
|
bg.button("Click me!").classes("q-btn-primary").props("outline") |
||||||
|
|
||||||
|
# Layout containers |
||||||
|
with bg.row().classes("q-gutter-md") as row: |
||||||
|
bg.label("Item 1").classes("bg-blue-100 p-4") |
||||||
|
bg.label("Item 2").classes("bg-green-100 p-4") |
||||||
|
|
||||||
|
# 🚀 INSTANT DEVELOPMENT - One command does it all! |
||||||
|
bg.dev(port=3000) # Creates temp build, installs deps, starts server! |
||||||
|
|
||||||
|
# OR build static project for deployment |
||||||
|
# bg.build(output_dir="./my-vue-app") |
||||||
|
|
||||||
|
.. toctree:: |
||||||
|
:maxdepth: 2 |
||||||
|
:caption: Contents: |
||||||
|
|
||||||
|
installation |
||||||
|
quickstart |
||||||
|
development |
||||||
|
components |
||||||
|
styling |
||||||
|
routing |
||||||
|
examples |
||||||
|
api/modules |
||||||
|
|
||||||
|
Indices and Tables |
||||||
|
================== |
||||||
|
|
||||||
|
* :ref:`genindex` |
||||||
|
* :ref:`modindex` |
||||||
|
* :ref:`search` |
||||||
|
|
||||||
@ -0,0 +1,71 @@ |
|||||||
|
Installation |
||||||
|
============ |
||||||
|
|
||||||
|
Requirements |
||||||
|
------------ |
||||||
|
|
||||||
|
BadGUI requires: |
||||||
|
|
||||||
|
- Python 3.8 or higher |
||||||
|
- Node.js 16+ (for running generated Vue.js projects) |
||||||
|
- npm or yarn (for package management) |
||||||
|
|
||||||
|
Install BadGUI |
||||||
|
-------------- |
||||||
|
|
||||||
|
Install from PyPI using pip:: |
||||||
|
|
||||||
|
pip install badgui |
||||||
|
|
||||||
|
Development Installation |
||||||
|
------------------------ |
||||||
|
|
||||||
|
To install BadGUI for development:: |
||||||
|
|
||||||
|
git clone https://github.com/your-username/badgui.git |
||||||
|
cd badgui |
||||||
|
pip install -e . |
||||||
|
|
||||||
|
Verify Installation |
||||||
|
------------------- |
||||||
|
|
||||||
|
To verify that BadGUI is installed correctly: |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
import badgui as bg |
||||||
|
print(bg.__version__) |
||||||
|
|
||||||
|
System Dependencies |
||||||
|
------------------- |
||||||
|
|
||||||
|
For generated Vue.js projects, you'll need: |
||||||
|
|
||||||
|
**Node.js and npm**:: |
||||||
|
|
||||||
|
# Ubuntu/Debian |
||||||
|
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - |
||||||
|
sudo apt-get install -y nodejs |
||||||
|
|
||||||
|
# macOS |
||||||
|
brew install node |
||||||
|
|
||||||
|
# Windows |
||||||
|
# Download from https://nodejs.org/ |
||||||
|
|
||||||
|
**Verify Node.js installation**:: |
||||||
|
|
||||||
|
node --version |
||||||
|
npm --version |
||||||
|
|
||||||
|
Troubleshooting |
||||||
|
--------------- |
||||||
|
|
||||||
|
**ImportError: No module named 'badgui'** |
||||||
|
Make sure BadGUI is installed in the correct Python environment. |
||||||
|
|
||||||
|
**Command 'npm' not found** |
||||||
|
Install Node.js which includes npm. |
||||||
|
|
||||||
|
**Permission denied errors** |
||||||
|
Use ``pip install --user badgui`` to install in user directory. |
||||||
@ -0,0 +1,147 @@ |
|||||||
|
Quick Start Guide |
||||||
|
================= |
||||||
|
|
||||||
|
This guide will get you up and running with BadGUI in minutes. |
||||||
|
|
||||||
|
Your First BadGUI App |
||||||
|
--------------------- |
||||||
|
|
||||||
|
Create a new Python file called ``hello_world.py``: |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
import badgui as bg |
||||||
|
|
||||||
|
# Create a page using context manager |
||||||
|
with bg.page("/", "HomePage", "Hello World"): |
||||||
|
bg.label("Hello, World!").classes("text-h2 text-primary") |
||||||
|
bg.label("Welcome to BadGUI").classes("text-body1 text-grey-7") |
||||||
|
|
||||||
|
with bg.row().classes("q-gutter-md q-mt-md") as row: |
||||||
|
bg.button("Primary Button").classes("q-btn-primary") |
||||||
|
bg.button("Secondary Button").classes("q-btn-secondary") |
||||||
|
|
||||||
|
# 🚀 INSTANT DEVELOPMENT MODE - One command does it all! |
||||||
|
bg.dev(port=3000) # Creates temp build, installs deps, starts server! |
||||||
|
|
||||||
|
Run the script:: |
||||||
|
|
||||||
|
python hello_world.py |
||||||
|
|
||||||
|
**That's it!** The server automatically starts at ``http://localhost:3000`` - no manual setup needed! |
||||||
|
|
||||||
|
Development Modes |
||||||
|
----------------- |
||||||
|
|
||||||
|
**🚀 Instant Development (Recommended)** |
||||||
|
|
||||||
|
BadGUI's ``bg.dev()`` method provides the fastest development experience: |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
# At the end of your script, use: |
||||||
|
bg.dev(port=3000) # Automatic build + install + server start |
||||||
|
|
||||||
|
**📦 Static Project Generation** |
||||||
|
|
||||||
|
For deployment or manual development, use ``bg.build()``: |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
# Generate static project |
||||||
|
bg.build("hello-world-app") |
||||||
|
|
||||||
|
Then manually run:: |
||||||
|
|
||||||
|
cd hello-world-app |
||||||
|
npm install |
||||||
|
npm run dev |
||||||
|
|
||||||
|
Adding Components |
||||||
|
----------------- |
||||||
|
|
||||||
|
BadGUI provides several built-in components: |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
import badgui as bg |
||||||
|
|
||||||
|
with bg.page("/", "ComponentsDemo", "Components Demo"): |
||||||
|
# Text components |
||||||
|
bg.label("Main Title").classes("text-h3") |
||||||
|
bg.label("Subtitle").classes("text-h6 text-grey-7") |
||||||
|
|
||||||
|
# Input components |
||||||
|
bg.input(placeholder="Enter your name").classes("q-mb-md") |
||||||
|
|
||||||
|
# Buttons |
||||||
|
bg.button("Click Me").props("push color=primary") |
||||||
|
|
||||||
|
# Navigation |
||||||
|
bg.link("Go to About", "/about").classes("q-btn q-btn-outline") |
||||||
|
|
||||||
|
bg.build("components-demo") |
||||||
|
|
||||||
|
Using Layouts |
||||||
|
------------- |
||||||
|
|
||||||
|
Create structured layouts with row and column containers: |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
import badgui as bg |
||||||
|
|
||||||
|
with bg.page("/", "LayoutDemo", "Layout Demo"): |
||||||
|
bg.label("Layout Example").classes("text-h4 q-mb-lg") |
||||||
|
|
||||||
|
# Horizontal layout |
||||||
|
with bg.row().classes("q-gutter-md q-mb-lg"): |
||||||
|
bg.label("Left Column").classes("bg-blue-1 p-4 rounded") |
||||||
|
bg.label("Middle Column").classes("bg-green-1 p-4 rounded") |
||||||
|
bg.label("Right Column").classes("bg-red-1 p-4 rounded") |
||||||
|
|
||||||
|
# Vertical layout |
||||||
|
with bg.column().classes("q-gutter-sm"): |
||||||
|
bg.label("Row 1").classes("bg-grey-2 p-2") |
||||||
|
bg.label("Row 2").classes("bg-grey-2 p-2") |
||||||
|
bg.label("Row 3").classes("bg-grey-2 p-2") |
||||||
|
|
||||||
|
bg.build("layout-demo") |
||||||
|
|
||||||
|
Multi-Page Applications |
||||||
|
----------------------- |
||||||
|
|
||||||
|
Create multiple pages with routing: |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
import badgui as bg |
||||||
|
|
||||||
|
# Home page |
||||||
|
with bg.page("/", "HomePage", "Home"): |
||||||
|
bg.label("Welcome to Home").classes("text-h3") |
||||||
|
bg.label("This is the home page content.") |
||||||
|
bg.link("Go to About", "/about").classes("q-btn q-btn-primary q-mt-md") |
||||||
|
|
||||||
|
# About page |
||||||
|
with bg.page("/about", "AboutPage", "About"): |
||||||
|
bg.label("About Us").classes("text-h3") |
||||||
|
bg.label("Learn more about our application.") |
||||||
|
bg.link("Back to Home", "/").classes("q-btn q-btn-secondary q-mt-md") |
||||||
|
|
||||||
|
# Contact page |
||||||
|
with bg.page("/contact", "ContactPage", "Contact"): |
||||||
|
bg.label("Contact Us").classes("text-h3") |
||||||
|
bg.input(placeholder="Your Name").classes("q-mb-md") |
||||||
|
bg.input(placeholder="Your Email").classes("q-mb-md") |
||||||
|
bg.button("Send Message").classes("q-btn q-btn-primary") |
||||||
|
|
||||||
|
bg.build("multi-page-app") |
||||||
|
|
||||||
|
Next Steps |
||||||
|
---------- |
||||||
|
|
||||||
|
- Learn about :doc:`components` for detailed component documentation |
||||||
|
- Explore :doc:`styling` for advanced styling techniques |
||||||
|
- Check out :doc:`examples` for complete application examples |
||||||
|
- Review the :doc:`api/modules` for full API reference |
||||||
@ -0,0 +1,389 @@ |
|||||||
|
Routing and Multi-Page Apps |
||||||
|
=========================== |
||||||
|
|
||||||
|
BadGUI supports creating multi-page applications with Vue Router integration, allowing you to build complex single-page applications with client-side routing. |
||||||
|
|
||||||
|
Page Management |
||||||
|
--------------- |
||||||
|
|
||||||
|
Pages in BadGUI are created using the ``page()`` function, which acts as both a page definer and a context manager. |
||||||
|
|
||||||
|
Creating Pages |
||||||
|
~~~~~~~~~~~~~~ |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
import badgui as bg |
||||||
|
|
||||||
|
# Create a page with context manager |
||||||
|
with bg.page("/", "HomePage", "Home"): |
||||||
|
bg.label("Welcome to the Home Page") |
||||||
|
bg.label("This is the main landing page") |
||||||
|
|
||||||
|
**Parameters:** |
||||||
|
|
||||||
|
- ``path``: URL path (e.g., ``"/"``, ``"/about"``, ``"/contact"``) |
||||||
|
- ``name``: Component name (e.g., ``"HomePage"``, ``"AboutPage"``) |
||||||
|
- ``title``: Page title displayed in browser tab (optional) |
||||||
|
|
||||||
|
Page Context |
||||||
|
~~~~~~~~~~~~ |
||||||
|
|
||||||
|
All components created within a page context are automatically added to that page: |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
with bg.page("/about", "AboutPage", "About Us"): |
||||||
|
# These components belong to the About page |
||||||
|
bg.label("About Our Company") |
||||||
|
bg.label("Founded in 2025") |
||||||
|
|
||||||
|
with bg.row(): |
||||||
|
bg.label("Mission") |
||||||
|
bg.label("Vision") |
||||||
|
|
||||||
|
Navigation |
||||||
|
---------- |
||||||
|
|
||||||
|
Link Component |
||||||
|
~~~~~~~~~~~~~~ |
||||||
|
|
||||||
|
Create navigation between pages using the ``link()`` component: |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
# Basic link |
||||||
|
bg.link("Go to About", "/about") |
||||||
|
|
||||||
|
# Styled as button |
||||||
|
bg.link("Contact Us", "/contact").classes("q-btn q-btn-primary") |
||||||
|
|
||||||
|
# With additional props |
||||||
|
bg.link("Home", "/").props("exact").classes("nav-link") |
||||||
|
|
||||||
|
**Generated Output:** ``<router-link to="/about">Go to About</router-link>`` |
||||||
|
|
||||||
|
Navigation Menu |
||||||
|
~~~~~~~~~~~~~~~ |
||||||
|
|
||||||
|
Create a navigation menu across multiple pages: |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
def create_nav(): |
||||||
|
\"\"\"Create consistent navigation menu.\"\"\" |
||||||
|
with bg.row().classes("q-gutter-md q-mb-lg justify-center") as nav: |
||||||
|
nav.classes("bg-primary text-white q-pa-md rounded") |
||||||
|
bg.link("Home", "/").classes("text-white no-underline q-btn q-btn-flat") |
||||||
|
bg.link("About", "/about").classes("text-white no-underline q-btn q-btn-flat") |
||||||
|
bg.link("Services", "/services").classes("text-white no-underline q-btn q-btn-flat") |
||||||
|
bg.link("Contact", "/contact").classes("text-white no-underline q-btn q-btn-flat") |
||||||
|
|
||||||
|
# Use in each page |
||||||
|
with bg.page("/", "HomePage", "Home"): |
||||||
|
create_nav() |
||||||
|
bg.label("Home Page Content") |
||||||
|
|
||||||
|
with bg.page("/about", "AboutPage", "About"): |
||||||
|
create_nav() |
||||||
|
bg.label("About Page Content") |
||||||
|
|
||||||
|
Route Parameters |
||||||
|
---------------- |
||||||
|
|
||||||
|
Dynamic Routes |
||||||
|
~~~~~~~~~~~~~~ |
||||||
|
|
||||||
|
Create routes with parameters: |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
# Route with parameter |
||||||
|
with bg.page("/user/:id", "UserPage", "User Profile"): |
||||||
|
bg.label("User Profile Page") |
||||||
|
bg.label("User ID will be available in Vue component") |
||||||
|
|
||||||
|
# Navigation to dynamic route |
||||||
|
bg.link("View User 123", "/user/123") |
||||||
|
|
||||||
|
Nested Routes |
||||||
|
~~~~~~~~~~~~~ |
||||||
|
|
||||||
|
Create nested route structures: |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
# Parent route |
||||||
|
with bg.page("/dashboard", "DashboardPage", "Dashboard"): |
||||||
|
bg.label("Dashboard").classes("text-h3") |
||||||
|
|
||||||
|
# Navigation to child routes |
||||||
|
with bg.row().classes("q-gutter-md"): |
||||||
|
bg.link("Analytics", "/dashboard/analytics") |
||||||
|
bg.link("Settings", "/dashboard/settings") |
||||||
|
bg.link("Profile", "/dashboard/profile") |
||||||
|
|
||||||
|
# Child routes |
||||||
|
with bg.page("/dashboard/analytics", "AnalyticsPage", "Analytics"): |
||||||
|
bg.label("Analytics Dashboard") |
||||||
|
bg.label("View your analytics data here") |
||||||
|
|
||||||
|
with bg.page("/dashboard/settings", "SettingsPage", "Settings"): |
||||||
|
bg.label("Dashboard Settings") |
||||||
|
bg.input(placeholder="Setting 1") |
||||||
|
bg.input(placeholder="Setting 2") |
||||||
|
|
||||||
|
Multi-Page Application Example |
||||||
|
------------------------------ |
||||||
|
|
||||||
|
Complete Blog Application |
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||||
|
|
||||||
|
Here's a complete multi-page blog application: |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
import badgui as bg |
||||||
|
|
||||||
|
def create_header(): |
||||||
|
\"\"\"Create site header with navigation.\"\"\" |
||||||
|
with bg.row().classes("bg-primary text-white q-pa-md justify-between items-center") as header: |
||||||
|
bg.label("My Blog").classes("text-h5 text-weight-bold") |
||||||
|
|
||||||
|
with bg.row().classes("q-gutter-md"): |
||||||
|
bg.link("Home", "/").classes("text-white q-btn q-btn-flat") |
||||||
|
bg.link("Posts", "/posts").classes("text-white q-btn q-btn-flat") |
||||||
|
bg.link("About", "/about").classes("text-white q-btn q-btn-flat") |
||||||
|
bg.link("Contact", "/contact").classes("text-white q-btn q-btn-flat") |
||||||
|
|
||||||
|
def create_footer(): |
||||||
|
\"\"\"Create site footer.\"\"\" |
||||||
|
with bg.row().classes("bg-grey-8 text-white q-pa-lg justify-center q-mt-xl"): |
||||||
|
bg.label("© 2025 My Blog. All rights reserved.").classes("text-body2") |
||||||
|
|
||||||
|
# Home Page |
||||||
|
with bg.page("/", "HomePage", "My Blog - Home"): |
||||||
|
create_header() |
||||||
|
|
||||||
|
# Hero section |
||||||
|
with bg.column().classes("text-center q-pa-xl bg-gradient-to-r from-blue-500 to-purple-600 text-white"): |
||||||
|
bg.label("Welcome to My Blog").classes("text-h2 q-mb-md") |
||||||
|
bg.label("Sharing thoughts and ideas").classes("text-h6 q-mb-lg") |
||||||
|
bg.link("Read Latest Posts", "/posts").classes("q-btn q-btn-lg q-btn-white text-primary") |
||||||
|
|
||||||
|
# Featured posts |
||||||
|
with bg.column().classes("q-pa-xl"): |
||||||
|
bg.label("Featured Posts").classes("text-h4 q-mb-lg text-center") |
||||||
|
|
||||||
|
with bg.row().classes("q-col-gutter-lg"): |
||||||
|
for i in range(3): |
||||||
|
with bg.column().classes("col-12 col-md-4"): |
||||||
|
with bg.column().classes("bg-white rounded-lg shadow-2 q-pa-lg"): |
||||||
|
bg.label(f"Post Title {i+1}").classes("text-h6 q-mb-md") |
||||||
|
bg.label("Post excerpt goes here...").classes("text-body2 q-mb-md") |
||||||
|
bg.link("Read More", f"/post/{i+1}").classes("q-btn q-btn-primary") |
||||||
|
|
||||||
|
create_footer() |
||||||
|
|
||||||
|
# Posts Page |
||||||
|
with bg.page("/posts", "PostsPage", "All Posts"): |
||||||
|
create_header() |
||||||
|
|
||||||
|
with bg.column().classes("q-pa-xl"): |
||||||
|
bg.label("All Posts").classes("text-h3 q-mb-lg") |
||||||
|
|
||||||
|
# Post list |
||||||
|
for i in range(10): |
||||||
|
with bg.row().classes("bg-white rounded q-pa-lg q-mb-md shadow-1"): |
||||||
|
with bg.column().classes("col-12"): |
||||||
|
bg.label(f"Blog Post {i+1}").classes("text-h6 q-mb-sm") |
||||||
|
bg.label("Published on January 1, 2025").classes("text-caption text-grey-6 q-mb-md") |
||||||
|
bg.label("This is a preview of the blog post content...").classes("text-body2 q-mb-md") |
||||||
|
bg.link("Read Full Post", f"/post/{i+1}").classes("q-btn q-btn-outline") |
||||||
|
|
||||||
|
create_footer() |
||||||
|
|
||||||
|
# Individual Post Page |
||||||
|
with bg.page("/post/:id", "PostPage", "Blog Post"): |
||||||
|
create_header() |
||||||
|
|
||||||
|
with bg.column().classes("q-pa-xl max-width-md mx-auto"): |
||||||
|
bg.label("Blog Post Title").classes("text-h3 q-mb-md") |
||||||
|
bg.label("Published on January 1, 2025 by Author").classes("text-caption text-grey-6 q-mb-lg") |
||||||
|
|
||||||
|
bg.label("Blog post content goes here...").classes("text-body1 q-mb-lg") |
||||||
|
bg.label("More content and paragraphs...").classes("text-body1 q-mb-lg") |
||||||
|
|
||||||
|
with bg.row().classes("q-mt-xl"): |
||||||
|
bg.link("← Back to Posts", "/posts").classes("q-btn q-btn-outline") |
||||||
|
|
||||||
|
create_footer() |
||||||
|
|
||||||
|
# About Page |
||||||
|
with bg.page("/about", "AboutPage", "About"): |
||||||
|
create_header() |
||||||
|
|
||||||
|
with bg.column().classes("q-pa-xl max-width-md mx-auto text-center"): |
||||||
|
bg.label("About Me").classes("text-h3 q-mb-lg") |
||||||
|
bg.label("Welcome to my personal blog...").classes("text-body1 q-mb-lg") |
||||||
|
bg.label("I write about technology, life, and everything in between.").classes("text-body1 q-mb-lg") |
||||||
|
|
||||||
|
create_footer() |
||||||
|
|
||||||
|
# Contact Page |
||||||
|
with bg.page("/contact", "ContactPage", "Contact"): |
||||||
|
create_header() |
||||||
|
|
||||||
|
with bg.column().classes("q-pa-xl max-width-sm mx-auto"): |
||||||
|
bg.label("Contact Me").classes("text-h3 q-mb-lg text-center") |
||||||
|
|
||||||
|
# Contact form |
||||||
|
bg.input(placeholder="Your Name").classes("q-mb-md").props("filled required") |
||||||
|
bg.input(placeholder="Your Email").classes("q-mb-md").props("filled required type=email") |
||||||
|
bg.input(placeholder="Subject").classes("q-mb-md").props("filled required") |
||||||
|
bg.input(placeholder="Your Message").classes("q-mb-lg").props("filled required type=textarea rows=4") |
||||||
|
|
||||||
|
bg.button("Send Message").classes("q-btn q-btn-primary full-width") |
||||||
|
|
||||||
|
create_footer() |
||||||
|
|
||||||
|
# Build the application |
||||||
|
bg.build("blog-app") |
||||||
|
|
||||||
|
Route Configuration |
||||||
|
------------------- |
||||||
|
|
||||||
|
Generated Router Files |
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~ |
||||||
|
|
||||||
|
BadGUI automatically generates Vue Router configuration files: |
||||||
|
|
||||||
|
**``src/router/routes.js``:** |
||||||
|
|
||||||
|
.. code-block:: javascript |
||||||
|
|
||||||
|
const routes = [ |
||||||
|
{ |
||||||
|
path: '/', |
||||||
|
component: () => import('layouts/MainLayout.vue'), |
||||||
|
children: [ |
||||||
|
{ path: '', component: () => import('pages/HomePage.vue') }, |
||||||
|
{ path: '/about', component: () => import('pages/AboutPage.vue') }, |
||||||
|
{ path: '/posts', component: () => import('pages/PostsPage.vue') }, |
||||||
|
{ path: '/post/:id', component: () => import('pages/PostPage.vue') }, |
||||||
|
{ path: '/contact', component: () => import('pages/ContactPage.vue') } |
||||||
|
] |
||||||
|
} |
||||||
|
] |
||||||
|
|
||||||
|
**``src/router/index.js``:** |
||||||
|
|
||||||
|
.. code-block:: javascript |
||||||
|
|
||||||
|
import { createRouter, createWebHistory } from 'vue-router' |
||||||
|
import routes from './routes' |
||||||
|
|
||||||
|
const router = createRouter({ |
||||||
|
history: createWebHistory(), |
||||||
|
routes |
||||||
|
}) |
||||||
|
|
||||||
|
export default router |
||||||
|
|
||||||
|
Page Components |
||||||
|
~~~~~~~~~~~~~~~ |
||||||
|
|
||||||
|
Each page generates a corresponding Vue component: |
||||||
|
|
||||||
|
**``src/pages/HomePage.vue``:** |
||||||
|
|
||||||
|
.. code-block:: vue |
||||||
|
|
||||||
|
<template> |
||||||
|
<q-page class="row items-center justify-evenly"> |
||||||
|
<!-- Generated components --> |
||||||
|
</q-page> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script setup> |
||||||
|
import { ref } from 'vue' |
||||||
|
// Component logic |
||||||
|
</script> |
||||||
|
|
||||||
|
Best Practices |
||||||
|
-------------- |
||||||
|
|
||||||
|
URL Structure |
||||||
|
~~~~~~~~~~~~~ |
||||||
|
|
||||||
|
1. **Use clear, descriptive URLs**: ``/about``, ``/contact``, ``/blog/post-title`` |
||||||
|
2. **Keep URLs short and readable**: Avoid deep nesting |
||||||
|
3. **Use hyphens for multi-word URLs**: ``/user-profile`` not ``/userprofile`` |
||||||
|
4. **Be consistent**: Choose a pattern and stick to it |
||||||
|
|
||||||
|
Page Organization |
||||||
|
~~~~~~~~~~~~~~~~~ |
||||||
|
|
||||||
|
1. **Group related pages**: Keep similar functionality together |
||||||
|
2. **Use consistent layouts**: Share common elements like headers/footers |
||||||
|
3. **Plan your navigation flow**: Make it easy for users to move between pages |
||||||
|
4. **Consider SEO**: Use descriptive page titles |
||||||
|
|
||||||
|
Performance Considerations |
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||||
|
|
||||||
|
1. **Code splitting**: Vue Router automatically splits pages into separate chunks |
||||||
|
2. **Lazy loading**: Pages are loaded only when needed |
||||||
|
3. **Minimize page complexity**: Keep individual pages focused and lightweight |
||||||
|
|
||||||
|
Error Handling |
||||||
|
-------------- |
||||||
|
|
||||||
|
404 Error Page |
||||||
|
~~~~~~~~~~~~~~ |
||||||
|
|
||||||
|
BadGUI automatically generates a 404 error page: |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
# This is generated automatically |
||||||
|
with bg.page("/:catchAll(.*)*", "ErrorNotFound", "Page Not Found"): |
||||||
|
bg.label("Oops. Nothing here...").classes("text-h2") |
||||||
|
bg.link("Go Home", "/").classes("q-btn q-btn-primary") |
||||||
|
|
||||||
|
The generated project includes proper error handling for routes that don't exist. |
||||||
|
|
||||||
|
Advanced Routing |
||||||
|
---------------- |
||||||
|
|
||||||
|
Route Guards |
||||||
|
~~~~~~~~~~~~ |
||||||
|
|
||||||
|
While BadGUI generates static routes, you can add route guards in the generated Vue project: |
||||||
|
|
||||||
|
.. code-block:: javascript |
||||||
|
|
||||||
|
// In the generated router/index.js, you can add: |
||||||
|
router.beforeEach((to, from, next) => { |
||||||
|
// Add authentication, analytics, etc. |
||||||
|
next() |
||||||
|
}) |
||||||
|
|
||||||
|
Programmatic Navigation |
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~ |
||||||
|
|
||||||
|
In the generated Vue components, you can add programmatic navigation: |
||||||
|
|
||||||
|
.. code-block:: vue |
||||||
|
|
||||||
|
<script setup> |
||||||
|
import { useRouter } from 'vue-router' |
||||||
|
|
||||||
|
const router = useRouter() |
||||||
|
|
||||||
|
const navigateToAbout = () => { |
||||||
|
router.push('/about') |
||||||
|
} |
||||||
|
</script> |
||||||
|
|
||||||
|
This allows for dynamic navigation based on user actions or application state. |
||||||
@ -0,0 +1,351 @@ |
|||||||
|
Styling |
||||||
|
======= |
||||||
|
|
||||||
|
BadGUI provides powerful styling capabilities inspired by NiceGUI, allowing you to style components using CSS classes, component properties, and inline styles. |
||||||
|
|
||||||
|
Styling Methods |
||||||
|
--------------- |
||||||
|
|
||||||
|
BadGUI components support three main styling methods: |
||||||
|
|
||||||
|
Classes Method |
||||||
|
~~~~~~~~~~~~~~ |
||||||
|
|
||||||
|
The ``.classes()`` method manages CSS classes, supporting Tailwind CSS, Quasar classes, and custom CSS classes. |
||||||
|
|
||||||
|
**Basic Usage:** |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
# Add classes |
||||||
|
label = bg.label("Styled Text") |
||||||
|
label.classes("text-h4 text-primary q-mb-md") |
||||||
|
|
||||||
|
**Method Chaining:** |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
bg.label("Chained Styling")\ |
||||||
|
.classes("text-center")\ |
||||||
|
.classes("text-bold")\ |
||||||
|
.classes("bg-blue-100 p-4") |
||||||
|
|
||||||
|
**Advanced Class Management:** |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
label = bg.label("Dynamic Classes") |
||||||
|
|
||||||
|
# Add specific classes |
||||||
|
label.classes(add="border rounded") |
||||||
|
|
||||||
|
# Remove classes |
||||||
|
label.classes(remove="bg-blue-100") |
||||||
|
|
||||||
|
# Replace all classes |
||||||
|
label.classes(replace="text-h3 text-success") |
||||||
|
|
||||||
|
Props Method |
||||||
|
~~~~~~~~~~~~ |
||||||
|
|
||||||
|
The ``.props()`` method sets component properties, supporting both string and keyword syntax. |
||||||
|
|
||||||
|
**String Syntax:** |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
# Boolean properties |
||||||
|
button = bg.button("Button") |
||||||
|
button.props("outline rounded push") |
||||||
|
|
||||||
|
# Key-value properties |
||||||
|
input_field = bg.input() |
||||||
|
input_field.props("color=primary dense filled") |
||||||
|
|
||||||
|
# Quoted values |
||||||
|
input_field.props('label="Enter your name" placeholder="Full name"') |
||||||
|
|
||||||
|
**Keyword Syntax:** |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
button.props( |
||||||
|
color="primary", |
||||||
|
outline=True, |
||||||
|
disabled=False, |
||||||
|
icon="star" |
||||||
|
) |
||||||
|
|
||||||
|
**Mixed Syntax:** |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
component.props("dense filled", color="teal", label="Advanced Input") |
||||||
|
|
||||||
|
Style Method |
||||||
|
~~~~~~~~~~~~ |
||||||
|
|
||||||
|
The ``.style()`` method applies inline CSS styles. |
||||||
|
|
||||||
|
**CSS String Syntax:** |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
label = bg.label("Custom Styled") |
||||||
|
label.style("color: #ff6b6b; font-size: 18px; padding: 10px") |
||||||
|
|
||||||
|
**Keyword Syntax:** |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
# camelCase is automatically converted to kebab-case |
||||||
|
label.style( |
||||||
|
color="#4ecdc4", |
||||||
|
backgroundColor="#f7f7f7", |
||||||
|
fontSize="16px", |
||||||
|
borderLeft="4px solid #4ecdc4" |
||||||
|
) |
||||||
|
|
||||||
|
**Style Chaining:** |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
bg.label("Multi-Style")\ |
||||||
|
.style("color: red; background: yellow")\ |
||||||
|
.style("padding: 10px; border-radius: 5px") |
||||||
|
|
||||||
|
CSS Frameworks |
||||||
|
-------------- |
||||||
|
|
||||||
|
BadGUI works seamlessly with popular CSS frameworks: |
||||||
|
|
||||||
|
Quasar Classes |
||||||
|
~~~~~~~~~~~~~~ |
||||||
|
|
||||||
|
BadGUI generates Quasar Framework projects, giving you access to all Quasar CSS classes: |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
# Typography |
||||||
|
bg.label("Heading").classes("text-h3 text-weight-bold text-primary") |
||||||
|
bg.label("Body").classes("text-body1 text-grey-7") |
||||||
|
|
||||||
|
# Spacing |
||||||
|
bg.button("Spaced").classes("q-ma-lg q-pa-md") |
||||||
|
|
||||||
|
# Colors |
||||||
|
bg.label("Colored").classes("bg-positive text-white") |
||||||
|
|
||||||
|
# Flexbox utilities |
||||||
|
with bg.row().classes("justify-center items-center q-gutter-md"): |
||||||
|
bg.button("Centered 1") |
||||||
|
bg.button("Centered 2") |
||||||
|
|
||||||
|
Tailwind CSS |
||||||
|
~~~~~~~~~~~~ |
||||||
|
|
||||||
|
BadGUI supports Tailwind CSS classes out of the box: |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
# Layout |
||||||
|
with bg.row().classes("flex flex-wrap gap-4"): |
||||||
|
bg.label("Item 1").classes("flex-1 bg-blue-100 p-4 rounded") |
||||||
|
bg.label("Item 2").classes("flex-1 bg-green-100 p-4 rounded") |
||||||
|
|
||||||
|
# Typography |
||||||
|
bg.label("Title").classes("text-2xl font-bold text-gray-800") |
||||||
|
bg.label("Subtitle").classes("text-lg text-gray-600 italic") |
||||||
|
|
||||||
|
# Responsive design |
||||||
|
bg.button("Responsive").classes("w-full md:w-auto px-6 py-2") |
||||||
|
|
||||||
|
Custom CSS |
||||||
|
~~~~~~~~~~ |
||||||
|
|
||||||
|
Add your own custom CSS classes: |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
# Assuming you have custom CSS defined |
||||||
|
bg.label("Custom").classes("my-custom-gradient-text shadow-custom") |
||||||
|
|
||||||
|
# Mix with framework classes |
||||||
|
bg.button("Mixed").classes("q-btn-primary my-custom-hover-effect") |
||||||
|
|
||||||
|
Layout Styling |
||||||
|
-------------- |
||||||
|
|
||||||
|
Style layout containers for complex designs: |
||||||
|
|
||||||
|
Responsive Layouts |
||||||
|
~~~~~~~~~~~~~~~~~~ |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
with bg.row().classes("row q-col-gutter-md") as responsive_row: |
||||||
|
responsive_row.style("min-height: 300px") |
||||||
|
|
||||||
|
# Responsive columns |
||||||
|
with bg.column().classes("col-12 col-md-6 col-lg-4"): |
||||||
|
bg.label("Column 1").classes("bg-blue-1 p-4 full-height") |
||||||
|
|
||||||
|
with bg.column().classes("col-12 col-md-6 col-lg-4"): |
||||||
|
bg.label("Column 2").classes("bg-green-1 p-4 full-height") |
||||||
|
|
||||||
|
with bg.column().classes("col-12 col-md-12 col-lg-4"): |
||||||
|
bg.label("Column 3").classes("bg-red-1 p-4 full-height") |
||||||
|
|
||||||
|
Grid Layouts |
||||||
|
~~~~~~~~~~~~ |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
# CSS Grid using Tailwind |
||||||
|
with bg.row().classes("grid grid-cols-1 md:grid-cols-3 gap-4") as grid: |
||||||
|
for i in range(6): |
||||||
|
bg.label(f"Grid Item {i+1}").classes("bg-gray-100 p-4 rounded text-center") |
||||||
|
|
||||||
|
Flexbox Layouts |
||||||
|
~~~~~~~~~~~~~~~ |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
# Flex container |
||||||
|
with bg.row().classes("flex justify-between items-center q-pa-md") as flex_row: |
||||||
|
flex_row.style("background: linear-gradient(45deg, #f0f0f0, #e0e0e0)") |
||||||
|
|
||||||
|
bg.label("Left").classes("text-h6") |
||||||
|
bg.button("Center").classes("q-btn-primary") |
||||||
|
bg.label("Right").classes("text-caption") |
||||||
|
|
||||||
|
Advanced Styling |
||||||
|
---------------- |
||||||
|
|
||||||
|
Dynamic Styling |
||||||
|
~~~~~~~~~~~~~~~ |
||||||
|
|
||||||
|
Create dynamic styles based on conditions: |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
def create_status_label(text, status): |
||||||
|
label = bg.label(text) |
||||||
|
|
||||||
|
if status == "success": |
||||||
|
label.classes("text-positive bg-light-green-1 q-pa-sm rounded") |
||||||
|
elif status == "warning": |
||||||
|
label.classes("text-warning bg-orange-1 q-pa-sm rounded") |
||||||
|
elif status == "error": |
||||||
|
label.classes("text-negative bg-red-1 q-pa-sm rounded") |
||||||
|
else: |
||||||
|
label.classes("text-grey-7 bg-grey-1 q-pa-sm rounded") |
||||||
|
|
||||||
|
return label |
||||||
|
|
||||||
|
# Usage |
||||||
|
with bg.page("/", "StatusDemo"): |
||||||
|
create_status_label("Success Message", "success") |
||||||
|
create_status_label("Warning Message", "warning") |
||||||
|
create_status_label("Error Message", "error") |
||||||
|
|
||||||
|
Theme Integration |
||||||
|
~~~~~~~~~~~~~~~~~ |
||||||
|
|
||||||
|
Work with Quasar's theming system: |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
# Using theme colors |
||||||
|
bg.button("Primary").props("color=primary") |
||||||
|
bg.button("Secondary").props("color=secondary") |
||||||
|
bg.button("Accent").props("color=accent") |
||||||
|
|
||||||
|
# Dark mode classes |
||||||
|
bg.label("Dark Mode Text").classes("text-white bg-dark q-pa-md") |
||||||
|
|
||||||
|
Animations and Transitions |
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||||
|
|
||||||
|
Add CSS animations and transitions: |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
# Hover effects |
||||||
|
bg.button("Hover Me").classes("transition-all duration-300 hover:scale-105") |
||||||
|
|
||||||
|
# Loading states |
||||||
|
bg.button("Loading").props("loading").classes("q-btn-primary") |
||||||
|
|
||||||
|
# Custom animations (requires custom CSS) |
||||||
|
bg.label("Animated").classes("fade-in-animation pulse-on-hover") |
||||||
|
|
||||||
|
Best Practices |
||||||
|
-------------- |
||||||
|
|
||||||
|
1. **Use Semantic Classes**: Prefer semantic class names over purely visual ones |
||||||
|
2. **Mobile First**: Design for mobile devices first, then add desktop styles |
||||||
|
3. **Consistent Spacing**: Use consistent spacing units (Quasar's spacing system) |
||||||
|
4. **Color Harmony**: Stick to a consistent color palette |
||||||
|
5. **Performance**: Avoid excessive inline styles; prefer CSS classes |
||||||
|
|
||||||
|
**Good Example:** |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
# Good: Semantic, consistent, mobile-first |
||||||
|
bg.label("Article Title").classes("text-h4 q-mb-md text-weight-medium") |
||||||
|
bg.label("Article Content").classes("text-body1 text-grey-8 line-height-md") |
||||||
|
|
||||||
|
**Avoid:** |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
# Avoid: Too specific, hard to maintain |
||||||
|
bg.label("Title").style("font-size: 24px; margin-bottom: 16px; font-weight: 500; color: #1976d2") |
||||||
|
|
||||||
|
Debugging Styles |
||||||
|
---------------- |
||||||
|
|
||||||
|
Tips for debugging styling issues: |
||||||
|
|
||||||
|
1. **Inspect Generated HTML**: Check the generated Vue components in the build output |
||||||
|
2. **Browser DevTools**: Use browser inspector to see applied styles |
||||||
|
3. **Class Conflicts**: Be aware of CSS specificity and class order |
||||||
|
4. **Framework Documentation**: Refer to Quasar and Tailwind documentation |
||||||
|
|
||||||
|
Example: Complete Styled Page |
||||||
|
----------------------------- |
||||||
|
|
||||||
|
Here's a complete example showcasing various styling techniques: |
||||||
|
|
||||||
|
.. code-block:: python |
||||||
|
|
||||||
|
import badgui as bg |
||||||
|
|
||||||
|
with bg.page("/", "StyledDemo", "Styling Demo"): |
||||||
|
# Header |
||||||
|
bg.label("Styling Showcase").classes("text-h2 text-center text-primary q-mb-xl") |
||||||
|
|
||||||
|
# Hero section |
||||||
|
with bg.row().classes("bg-gradient-to-r from-blue-400 to-purple-500 text-white q-pa-xl rounded-lg q-mb-lg") as hero: |
||||||
|
with bg.column().classes("items-center text-center"): |
||||||
|
bg.label("Welcome to BadGUI").classes("text-h3 q-mb-md") |
||||||
|
bg.label("Beautiful UIs with Python").classes("text-h6 opacity-80 q-mb-lg") |
||||||
|
bg.button("Get Started").classes("q-btn-lg").props("color=white text-color=primary") |
||||||
|
|
||||||
|
# Feature cards |
||||||
|
with bg.row().classes("q-col-gutter-lg q-mb-lg"): |
||||||
|
for i, feature in enumerate(["Fast", "Simple", "Powerful"]): |
||||||
|
with bg.column().classes("col-12 col-md-4"): |
||||||
|
with bg.column().classes("bg-white rounded-lg shadow-2 q-pa-lg items-center text-center") as card: |
||||||
|
card.style("border-top: 4px solid #1976d2") |
||||||
|
bg.label(feature).classes("text-h5 text-primary q-mb-md") |
||||||
|
bg.label(f"Feature {i+1} description").classes("text-body2 text-grey-7") |
||||||
|
|
||||||
|
# Call to action |
||||||
|
with bg.row().classes("justify-center q-mt-xl"): |
||||||
|
bg.button("Learn More").classes("q-btn-lg q-btn-primary q-mr-md") |
||||||
|
bg.button("Examples").classes("q-btn-lg q-btn-outline") |
||||||
|
|
||||||
|
bg.build("styled-demo") |
||||||
@ -1,34 +0,0 @@ |
|||||||
#!/usr/bin/env python3 |
|
||||||
""" |
|
||||||
Example BadGUI application demonstrating basic components and layouts. |
|
||||||
""" |
|
||||||
|
|
||||||
import badgui as bg |
|
||||||
|
|
||||||
def main(): |
|
||||||
# Main title |
|
||||||
bg.label("Welcome to BadGUI!", classes=["text-h3", "text-primary"]) |
|
||||||
|
|
||||||
# Buttons in a row |
|
||||||
with bg.row(): |
|
||||||
bg.button("Primary Button", classes=["q-mr-md"]) |
|
||||||
bg.button("Secondary Button", classes=["q-mr-md"]) |
|
||||||
bg.button("Success Button", classes=["bg-positive"]) |
|
||||||
|
|
||||||
# Input fields in a column |
|
||||||
with bg.column(): |
|
||||||
bg.input(placeholder="Enter your name", classes=["q-mb-md"]) |
|
||||||
bg.input(placeholder="Enter your email", classes=["q-mb-md"]) |
|
||||||
bg.input(placeholder="Enter your message", classes=["q-mb-md"]) |
|
||||||
|
|
||||||
# Another row with mixed content |
|
||||||
with bg.row(): |
|
||||||
bg.label("Status:") |
|
||||||
bg.label("Ready", classes=["text-positive", "text-weight-bold"]) |
|
||||||
|
|
||||||
# Build the Vue.js project |
|
||||||
print("🚀 Building BadGUI project...") |
|
||||||
bg.build(output_dir="./example-output", project_name="badgui-example") |
|
||||||
|
|
||||||
if __name__ == "__main__": |
|
||||||
main() |
|
||||||
@ -0,0 +1,218 @@ |
|||||||
|
""" |
||||||
|
BadGUI Context Manager Usage Guide |
||||||
|
================================== |
||||||
|
|
||||||
|
This guide explains the correct way to use BadGUI components, especially |
||||||
|
layout containers like row(), column(), card(), etc. |
||||||
|
|
||||||
|
PROBLEM: |
||||||
|
-------- |
||||||
|
BadGUI components that act as containers (row, column, card, etc.) are |
||||||
|
implemented as context managers. You cannot call .classes() directly on |
||||||
|
the context manager - you need to capture the yielded component first. |
||||||
|
|
||||||
|
WRONG WAY: |
||||||
|
---------- |
||||||
|
```python |
||||||
|
# This will cause AttributeError: '_GeneratorContextManager' object has no attribute 'classes' |
||||||
|
with bg.column().classes("q-pa-lg"): |
||||||
|
# content here |
||||||
|
``` |
||||||
|
|
||||||
|
CORRECT WAY: |
||||||
|
------------ |
||||||
|
```python |
||||||
|
# Capture the component with 'as' keyword, then call .classes() |
||||||
|
with bg.column() as main_col: |
||||||
|
main_col.classes("q-pa-lg") |
||||||
|
# content here |
||||||
|
``` |
||||||
|
|
||||||
|
COMPREHENSIVE EXAMPLES: |
||||||
|
---------------------- |
||||||
|
""" |
||||||
|
|
||||||
|
import badgui as bg |
||||||
|
from contextlib import contextmanager |
||||||
|
|
||||||
|
def demonstrate_correct_usage(): |
||||||
|
"""Show all the correct patterns for using BadGUI components.""" |
||||||
|
|
||||||
|
# 1. Basic layout containers |
||||||
|
with bg.column() as main_container: |
||||||
|
main_container.classes("q-pa-lg") |
||||||
|
|
||||||
|
with bg.row() as header_row: |
||||||
|
header_row.classes("items-center justify-between q-mb-lg") |
||||||
|
|
||||||
|
bg.label("Page Title").classes("text-h3") |
||||||
|
bg.button("Action").classes("q-ml-auto") |
||||||
|
|
||||||
|
# 2. Cards with styling |
||||||
|
with bg.card() as feature_card: |
||||||
|
feature_card.classes("q-ma-md shadow-5") |
||||||
|
|
||||||
|
with bg.card_section() as card_content: |
||||||
|
bg.label("Feature Title").classes("text-h5 q-mb-md") |
||||||
|
bg.label("Feature description goes here") |
||||||
|
|
||||||
|
# 3. Complex responsive layouts |
||||||
|
with bg.row() as responsive_row: |
||||||
|
responsive_row.classes("q-gutter-md wrap") |
||||||
|
|
||||||
|
# Left column |
||||||
|
with bg.column() as left_column: |
||||||
|
left_column.classes("col-12 col-md-8") |
||||||
|
|
||||||
|
with bg.card() as main_card: |
||||||
|
main_card.classes("q-pa-lg") |
||||||
|
bg.label("Main content area") |
||||||
|
|
||||||
|
# Right sidebar |
||||||
|
with bg.column() as right_sidebar: |
||||||
|
right_sidebar.classes("col-12 col-md-4") |
||||||
|
|
||||||
|
with bg.card() as sidebar_card: |
||||||
|
sidebar_card.classes("q-pa-md bg-grey-1") |
||||||
|
bg.label("Sidebar content") |
||||||
|
|
||||||
|
# 4. Headers and footers |
||||||
|
with bg.header() as page_header: |
||||||
|
page_header.classes("bg-primary text-white q-pa-md") |
||||||
|
|
||||||
|
with bg.row() as nav_row: |
||||||
|
nav_row.classes("items-center justify-between") |
||||||
|
bg.label("Site Logo").classes("text-h4") |
||||||
|
|
||||||
|
with bg.row() as nav_links: |
||||||
|
nav_links.classes("q-gutter-md") |
||||||
|
bg.link("Home", "/") |
||||||
|
bg.link("About", "/about") |
||||||
|
|
||||||
|
# 5. Tabs |
||||||
|
with bg.tabs() as main_tabs: |
||||||
|
main_tabs.classes("text-primary") |
||||||
|
|
||||||
|
with bg.tab("tab1", "Tab 1"): |
||||||
|
pass |
||||||
|
|
||||||
|
with bg.tab("tab2", "Tab 2"): |
||||||
|
pass |
||||||
|
|
||||||
|
with bg.tab_panels() as panels: |
||||||
|
panels.classes("q-pa-lg") |
||||||
|
|
||||||
|
with bg.tab_panel("tab1"): |
||||||
|
bg.label("Content for Tab 1") |
||||||
|
|
||||||
|
with bg.tab_panel("tab2"): |
||||||
|
bg.label("Content for Tab 2") |
||||||
|
|
||||||
|
def demonstrate_common_patterns(): |
||||||
|
"""Show common layout patterns that prevent overflow.""" |
||||||
|
|
||||||
|
# Pattern 1: Card grid with wrapping |
||||||
|
with bg.row() as card_grid: |
||||||
|
card_grid.classes("q-gutter-md wrap") |
||||||
|
|
||||||
|
# Create multiple cards that will wrap nicely |
||||||
|
for i in range(6): |
||||||
|
with bg.card() as grid_card: |
||||||
|
grid_card.classes("col-12 col-sm-6 col-md-4 col-lg-3") |
||||||
|
with bg.card_section(): |
||||||
|
bg.label(f"Card {i+1}").classes("text-h6") |
||||||
|
bg.label("Card content here") |
||||||
|
|
||||||
|
# Pattern 2: Vertical list with consistent spacing |
||||||
|
with bg.column() as item_list: |
||||||
|
item_list.classes("q-gutter-md q-pa-lg") |
||||||
|
|
||||||
|
for i in range(5): |
||||||
|
with bg.card() as list_item: |
||||||
|
list_item.classes("q-pa-md") |
||||||
|
with bg.card_section(): |
||||||
|
with bg.row() as item_row: |
||||||
|
item_row.classes("items-center q-gutter-sm") |
||||||
|
bg.icon("circle", color="primary") |
||||||
|
bg.label(f"List item {i+1}") |
||||||
|
|
||||||
|
# Pattern 3: Hero section with image |
||||||
|
with bg.card() as hero: |
||||||
|
hero.classes("bg-primary text-white q-pa-xl") |
||||||
|
|
||||||
|
with bg.row() as hero_content: |
||||||
|
hero_content.classes("items-center") |
||||||
|
|
||||||
|
with bg.column() as hero_text: |
||||||
|
hero_text.classes("col-12 col-md-6") |
||||||
|
bg.label("Hero Title").classes("text-h2 q-mb-md") |
||||||
|
bg.label("Hero description goes here") |
||||||
|
|
||||||
|
with bg.column() as hero_image: |
||||||
|
hero_image.classes("col-12 col-md-6 text-center") |
||||||
|
bg.image("https://picsum.photos/400/300").classes("rounded-lg") |
||||||
|
|
||||||
|
# UTILITY FUNCTIONS FOR EASIER USAGE: |
||||||
|
# =================================== |
||||||
|
|
||||||
|
def quick_row(*classes): |
||||||
|
"""Create a row with classes in one line (when you don't need complex styling).""" |
||||||
|
@contextmanager |
||||||
|
def _quick_row(): |
||||||
|
with bg.row() as r: |
||||||
|
if classes: |
||||||
|
r.classes(" ".join(classes)) |
||||||
|
yield r |
||||||
|
return _quick_row() |
||||||
|
|
||||||
|
def quick_column(*classes): |
||||||
|
"""Create a column with classes in one line.""" |
||||||
|
@contextmanager |
||||||
|
def _quick_column(): |
||||||
|
with bg.column() as c: |
||||||
|
if classes: |
||||||
|
c.classes(" ".join(classes)) |
||||||
|
yield c |
||||||
|
return _quick_column() |
||||||
|
|
||||||
|
def quick_card(*classes): |
||||||
|
"""Create a card with classes in one line.""" |
||||||
|
@contextmanager |
||||||
|
def _quick_card(): |
||||||
|
with bg.card() as card: |
||||||
|
if classes: |
||||||
|
card.classes(" ".join(classes)) |
||||||
|
yield card |
||||||
|
return _quick_card() |
||||||
|
|
||||||
|
# EXAMPLE USING UTILITY FUNCTIONS: |
||||||
|
# ================================= |
||||||
|
|
||||||
|
def example_with_utilities(): |
||||||
|
"""Example using the utility functions for cleaner code.""" |
||||||
|
|
||||||
|
with quick_column("q-pa-lg"): |
||||||
|
bg.label("Page with Utilities").classes("text-h3 q-mb-lg") |
||||||
|
|
||||||
|
with quick_row("q-gutter-md wrap"): |
||||||
|
with quick_card("col-12 col-md-4"): |
||||||
|
with bg.card_section(): |
||||||
|
bg.label("Quick Card 1") |
||||||
|
|
||||||
|
with quick_card("col-12 col-md-4"): |
||||||
|
with bg.card_section(): |
||||||
|
bg.label("Quick Card 2") |
||||||
|
|
||||||
|
with quick_card("col-12 col-md-4"): |
||||||
|
with bg.card_section(): |
||||||
|
bg.label("Quick Card 3") |
||||||
|
|
||||||
|
if __name__ == "__main__": |
||||||
|
print("🎯 BadGUI Context Manager Usage Guide") |
||||||
|
print("This demonstrates the correct way to use BadGUI components") |
||||||
|
print("All components are properly using context managers with 'as' syntax") |
||||||
|
print() |
||||||
|
|
||||||
|
# Run the main demonstration |
||||||
|
demonstrate_correct_usage() |
||||||
|
bg.dev(port=3008) |
||||||
@ -0,0 +1,308 @@ |
|||||||
|
""" |
||||||
|
Enhanced Navigation Example with Images and Icons |
||||||
|
Demonstrates header, footer, image, and icon components in a complete website. |
||||||
|
""" |
||||||
|
|
||||||
|
import badgui as bg |
||||||
|
|
||||||
|
# Home page with enhanced navigation |
||||||
|
with bg.page("/", "HomePage", "Home - My Website"): |
||||||
|
|
||||||
|
# Header with logo, navigation bar and icons |
||||||
|
with bg.header(elevated=True) as header: |
||||||
|
header.classes("bg-primary text-white q-pa-md") |
||||||
|
|
||||||
|
with bg.row() as nav_row: |
||||||
|
nav_row.classes("items-center justify-between w-full") |
||||||
|
|
||||||
|
# Logo with icon |
||||||
|
with bg.row() as logo_row: |
||||||
|
logo_row.classes("items-center q-gutter-sm") |
||||||
|
bg.icon("home", size="2rem", color="white") |
||||||
|
bg.label("My Website").classes("text-h4 font-bold") |
||||||
|
|
||||||
|
# Navigation menu with icons |
||||||
|
with bg.row() as nav_menu: |
||||||
|
nav_menu.classes("q-gutter-md items-center") |
||||||
|
|
||||||
|
with bg.row() as home_link: |
||||||
|
home_link.classes("items-center q-gutter-xs") |
||||||
|
bg.icon("home", color="white") |
||||||
|
bg.link("Home", "/").classes("text-white") |
||||||
|
|
||||||
|
with bg.row() as about_link: |
||||||
|
about_link.classes("items-center q-gutter-xs") |
||||||
|
bg.icon("info", color="white") |
||||||
|
bg.link("About", "/about").classes("text-white") |
||||||
|
|
||||||
|
with bg.row() as services_link: |
||||||
|
services_link.classes("items-center q-gutter-xs") |
||||||
|
bg.icon("business", color="white") |
||||||
|
bg.link("Services", "/services").classes("text-white") |
||||||
|
|
||||||
|
with bg.row() as contact_link: |
||||||
|
contact_link.classes("items-center q-gutter-xs") |
||||||
|
bg.icon("contact_mail", color="white") |
||||||
|
bg.link("Contact", "/contact").classes("text-white") |
||||||
|
|
||||||
|
# Main content area |
||||||
|
with bg.column() as main_content: |
||||||
|
main_content.classes("q-pa-lg") |
||||||
|
|
||||||
|
# Hero section with background image concept |
||||||
|
with bg.card() as hero_card: |
||||||
|
hero_card.classes("bg-gradient-to-r from-blue-500 to-purple-600 text-white q-mb-lg q-pa-xl") |
||||||
|
with bg.card_section(): |
||||||
|
with bg.row() as hero_row: |
||||||
|
hero_row.classes("items-center justify-between") |
||||||
|
|
||||||
|
with bg.column() as hero_text: |
||||||
|
hero_text.classes("col-12 col-md-6") |
||||||
|
bg.label("Welcome to My Website").classes("text-h3 q-mb-md") |
||||||
|
bg.label("Building beautiful web applications with BadGUI framework. Combining Python simplicity with modern web technologies.").classes("text-h6") |
||||||
|
|
||||||
|
with bg.row() as hero_buttons: |
||||||
|
hero_buttons.classes("q-gutter-md q-mt-lg") |
||||||
|
with bg.row() as get_started: |
||||||
|
get_started.classes("items-center q-gutter-xs") |
||||||
|
bg.icon("play_arrow", color="white") |
||||||
|
bg.button("Get Started").classes("bg-white text-primary") |
||||||
|
|
||||||
|
with bg.row() as learn_more: |
||||||
|
learn_more.classes("items-center q-gutter-xs") |
||||||
|
bg.icon("book", color="white") |
||||||
|
bg.button("Learn More").classes("text-white outline") |
||||||
|
|
||||||
|
# Placeholder for hero image |
||||||
|
with bg.column() as hero_image: |
||||||
|
hero_image.classes("col-12 col-md-6 text-center q-mt-md q-mt-md-none") |
||||||
|
bg.image("https://picsum.photos/400/300?random=1").classes("rounded-lg shadow-lg") |
||||||
|
|
||||||
|
# Features section with icons |
||||||
|
with bg.row() as features_row: |
||||||
|
features_row.classes("q-gutter-md q-mb-lg wrap") |
||||||
|
|
||||||
|
with bg.card() as feature1: |
||||||
|
feature1.classes("col-12 col-sm-12 col-md-4 text-center q-pa-lg flex-grow-1") |
||||||
|
with bg.card_section(): |
||||||
|
bg.icon("speed", size="3rem", color="primary").classes("q-mb-md") |
||||||
|
bg.label("Fast Development").classes("text-h5 q-mb-md text-primary") |
||||||
|
bg.label("Rapid prototyping with Python syntax") |
||||||
|
bg.label("Generate production-ready Vue.js applications") |
||||||
|
|
||||||
|
with bg.card() as feature2: |
||||||
|
feature2.classes("col-12 col-sm-12 col-md-4 text-center q-pa-lg flex-grow-1") |
||||||
|
with bg.card_section(): |
||||||
|
bg.icon("build", size="3rem", color="secondary").classes("q-mb-md") |
||||||
|
bg.label("Modern Stack").classes("text-h5 q-mb-md text-secondary") |
||||||
|
bg.label("Vue.js 3 with Quasar Framework") |
||||||
|
bg.label("Responsive design out of the box") |
||||||
|
|
||||||
|
with bg.card() as feature3: |
||||||
|
feature3.classes("col-12 col-sm-12 col-md-4 text-center q-pa-lg flex-grow-1") |
||||||
|
with bg.card_section(): |
||||||
|
bg.icon("code", size="3rem", color="accent").classes("q-mb-md") |
||||||
|
bg.label("NiceGUI Compatible").classes("text-h5 q-mb-md text-accent") |
||||||
|
bg.label("Familiar syntax and patterns") |
||||||
|
bg.label("Easy migration from NiceGUI") |
||||||
|
|
||||||
|
# Gallery section with images |
||||||
|
with bg.card() as gallery_card: |
||||||
|
gallery_card.classes("q-mb-lg") |
||||||
|
with bg.card_section(): |
||||||
|
with bg.row() as gallery_header: |
||||||
|
gallery_header.classes("items-center q-gutter-sm q-mb-lg") |
||||||
|
bg.icon("photo_library", size="2rem", color="primary") |
||||||
|
bg.label("Project Gallery").classes("text-h4") |
||||||
|
|
||||||
|
with bg.row() as gallery_row: |
||||||
|
gallery_row.classes("q-gutter-md wrap") |
||||||
|
|
||||||
|
with bg.column() as gallery_item1: |
||||||
|
gallery_item1.classes("col-12 col-sm-6 col-md-3 text-center q-mb-md") |
||||||
|
bg.image("https://picsum.photos/300/200?random=2").classes("rounded-lg shadow-md q-mb-sm full-width") |
||||||
|
bg.label("E-commerce Platform").classes("text-h6") |
||||||
|
bg.label("Modern shopping experience") |
||||||
|
|
||||||
|
with bg.column() as gallery_item2: |
||||||
|
gallery_item2.classes("col-12 col-sm-6 col-md-3 text-center q-mb-md") |
||||||
|
bg.image("https://picsum.photos/300/200?random=3").classes("rounded-lg shadow-md q-mb-sm full-width") |
||||||
|
bg.label("Dashboard App").classes("text-h6") |
||||||
|
bg.label("Data visualization tool") |
||||||
|
|
||||||
|
with bg.column() as gallery_item3: |
||||||
|
gallery_item3.classes("col-12 col-sm-6 col-md-3 text-center q-mb-md") |
||||||
|
bg.image("https://picsum.photos/300/200?random=4").classes("rounded-lg shadow-md q-mb-sm full-width") |
||||||
|
bg.label("Mobile App").classes("text-h6") |
||||||
|
bg.label("Cross-platform solution") |
||||||
|
|
||||||
|
with bg.column() as gallery_item4: |
||||||
|
gallery_item4.classes("col-12 col-sm-6 col-md-3 text-center q-mb-md") |
||||||
|
bg.image("https://picsum.photos/300/200?random=5").classes("rounded-lg shadow-md q-mb-sm full-width") |
||||||
|
bg.label("Portfolio Site").classes("text-h6") |
||||||
|
bg.label("Creative showcase") |
||||||
|
|
||||||
|
# Footer with social icons |
||||||
|
with bg.footer() as footer: |
||||||
|
footer.classes("bg-dark text-white q-pa-lg") |
||||||
|
bg.label("© 2024 My Website. All rights reserved. Built with BadGUI.").classes("opacity-75") |
||||||
|
|
||||||
|
# About page with team images |
||||||
|
with bg.page("/about", "AboutPage", "About - My Website"): |
||||||
|
|
||||||
|
# Header (same as home page) |
||||||
|
with bg.header(elevated=True) as header: |
||||||
|
header.classes("bg-primary text-white q-pa-md") |
||||||
|
|
||||||
|
with bg.row() as nav_row: |
||||||
|
nav_row.classes("items-center justify-between w-full") |
||||||
|
|
||||||
|
with bg.row() as logo_row: |
||||||
|
logo_row.classes("items-center q-gutter-sm") |
||||||
|
bg.icon("home", size="2rem", color="white") |
||||||
|
bg.label("My Website").classes("text-h4 font-bold") |
||||||
|
|
||||||
|
with bg.row() as nav_menu: |
||||||
|
nav_menu.classes("q-gutter-md items-center") |
||||||
|
|
||||||
|
with bg.row() as home_link: |
||||||
|
home_link.classes("items-center q-gutter-xs") |
||||||
|
bg.icon("home", color="white") |
||||||
|
bg.link("Home", "/").classes("text-white") |
||||||
|
|
||||||
|
with bg.row() as about_link: |
||||||
|
about_link.classes("items-center q-gutter-xs") |
||||||
|
bg.icon("info", color="white") |
||||||
|
bg.link("About", "/about").classes("text-white font-bold") |
||||||
|
|
||||||
|
with bg.row() as services_link: |
||||||
|
services_link.classes("items-center q-gutter-xs") |
||||||
|
bg.icon("business", color="white") |
||||||
|
bg.link("Services", "/services").classes("text-white") |
||||||
|
|
||||||
|
with bg.row() as contact_link: |
||||||
|
contact_link.classes("items-center q-gutter-xs") |
||||||
|
bg.icon("contact_mail", color="white") |
||||||
|
bg.link("Contact", "/contact").classes("text-white") |
||||||
|
|
||||||
|
# Main content |
||||||
|
with bg.column() as main_content: |
||||||
|
main_content.classes("q-pa-lg") |
||||||
|
|
||||||
|
# Page header with icon |
||||||
|
with bg.row() as page_header: |
||||||
|
page_header.classes("items-center q-gutter-md q-mb-lg") |
||||||
|
bg.icon("info", size="3rem", color="primary") |
||||||
|
bg.label("About Us").classes("text-h3") |
||||||
|
|
||||||
|
# About content with images |
||||||
|
with bg.row() as about_content: |
||||||
|
about_content.classes("q-gutter-lg") |
||||||
|
|
||||||
|
# Text content |
||||||
|
with bg.column() as text_content: |
||||||
|
text_content.classes("col-12 col-md-6") |
||||||
|
|
||||||
|
with bg.card() as story_card: |
||||||
|
story_card.classes("q-mb-lg") |
||||||
|
with bg.card_section(): |
||||||
|
with bg.row() as story_header: |
||||||
|
story_header.classes("items-center q-gutter-sm q-mb-md") |
||||||
|
bg.icon("auto_stories", color="primary") |
||||||
|
bg.label("Our Story").classes("text-h5 text-primary") |
||||||
|
|
||||||
|
bg.label("We are passionate developers who believe in making web development accessible and enjoyable. Our BadGUI framework combines the simplicity of Python with the power of modern web technologies.") |
||||||
|
|
||||||
|
with bg.card() as mission_card: |
||||||
|
with bg.card_section(): |
||||||
|
with bg.row() as mission_header: |
||||||
|
mission_header.classes("items-center q-gutter-sm q-mb-md") |
||||||
|
bg.icon("flag", color="secondary") |
||||||
|
bg.label("Our Mission").classes("text-h5 text-secondary") |
||||||
|
|
||||||
|
bg.label("To empower developers to create beautiful, functional web applications without the complexity of traditional web development. We bridge the gap between Python's simplicity and modern web frameworks.") |
||||||
|
|
||||||
|
# Company image |
||||||
|
with bg.column() as image_content: |
||||||
|
image_content.classes("col-12 col-md-6") |
||||||
|
bg.image("https://picsum.photos/500/400?random=6").classes("rounded-lg shadow-lg q-mb-md") |
||||||
|
bg.label("Our team at work").classes("text-center text-gray-600") |
||||||
|
|
||||||
|
# Team section |
||||||
|
with bg.card() as team_card: |
||||||
|
team_card.classes("q-mt-xl") |
||||||
|
with bg.card_section(): |
||||||
|
with bg.row() as team_header: |
||||||
|
team_header.classes("items-center justify-center q-gutter-sm q-mb-lg") |
||||||
|
bg.icon("group", size="2rem", color="primary") |
||||||
|
bg.label("Meet Our Team").classes("text-h4") |
||||||
|
|
||||||
|
with bg.row() as team_row: |
||||||
|
team_row.classes("q-gutter-md justify-center wrap") |
||||||
|
|
||||||
|
# Team member 1 |
||||||
|
with bg.column() as member1: |
||||||
|
member1.classes("col-12 col-sm-6 col-md-4 text-center q-mb-md") |
||||||
|
bg.image("https://picsum.photos/200/200?random=10").classes("rounded-full q-mb-md") |
||||||
|
bg.label("John Smith").classes("text-h6") |
||||||
|
bg.label("Lead Developer").classes("text-primary") |
||||||
|
with bg.row() as member1_social: |
||||||
|
member1_social.classes("justify-center q-gutter-sm q-mt-sm") |
||||||
|
bg.icon("linkedin", color="primary") |
||||||
|
bg.icon("github", color="dark") |
||||||
|
|
||||||
|
# Team member 2 |
||||||
|
with bg.column() as member2: |
||||||
|
member2.classes("col-12 col-sm-6 col-md-4 text-center q-mb-md") |
||||||
|
bg.image("https://picsum.photos/200/200?random=11").classes("rounded-full q-mb-md") |
||||||
|
bg.label("Sarah Johnson").classes("text-h6") |
||||||
|
bg.label("UI/UX Designer").classes("text-secondary") |
||||||
|
with bg.row() as member2_social: |
||||||
|
member2_social.classes("justify-center q-gutter-sm q-mt-sm") |
||||||
|
bg.icon("linkedin", color="primary") |
||||||
|
bg.icon("dribbble", color="pink") |
||||||
|
|
||||||
|
# Team member 3 |
||||||
|
with bg.column() as member3: |
||||||
|
member3.classes("col-12 col-sm-6 col-md-4 text-center q-mb-md") |
||||||
|
bg.image("https://picsum.photos/200/200?random=12").classes("rounded-full q-mb-md") |
||||||
|
bg.label("Mike Chen").classes("text-h6") |
||||||
|
bg.label("Backend Engineer").classes("text-accent") |
||||||
|
with bg.row() as member3_social: |
||||||
|
member3_social.classes("justify-center q-gutter-sm q-mt-sm") |
||||||
|
bg.icon("linkedin", color="primary") |
||||||
|
bg.icon("github", color="dark") |
||||||
|
|
||||||
|
# Footer (same as home page) |
||||||
|
with bg.footer() as footer: |
||||||
|
footer.classes("bg-dark text-white q-pa-lg") |
||||||
|
|
||||||
|
with bg.column(): |
||||||
|
with bg.row() as footer_content: |
||||||
|
footer_content.classes("justify-between items-start q-mb-lg") |
||||||
|
|
||||||
|
with bg.column() as company_info: |
||||||
|
company_info.classes("col-12 col-md-4") |
||||||
|
with bg.row() as footer_logo: |
||||||
|
footer_logo.classes("items-center q-gutter-sm q-mb-md") |
||||||
|
bg.icon("home", size="1.5rem", color="white") |
||||||
|
bg.label("My Website").classes("text-h6") |
||||||
|
bg.label("Building the future of web development with BadGUI framework.") |
||||||
|
|
||||||
|
with bg.row() as footer_bottom: |
||||||
|
footer_bottom.classes("justify-center q-pt-lg border-t border-gray-600") |
||||||
|
bg.label("© 2024 My Website. All rights reserved. Built with BadGUI.").classes("opacity-75") |
||||||
|
|
||||||
|
if __name__ == "__main__": |
||||||
|
print("🎨 Enhanced Navigation Example with Images & Icons") |
||||||
|
print("This example demonstrates:") |
||||||
|
print(" • Header and footer layout components") |
||||||
|
print(" • Image component with various sources") |
||||||
|
print(" • Icon component with Material Design icons") |
||||||
|
print(" • Complete navigation website structure") |
||||||
|
print(" • Social media icons and interactive elements") |
||||||
|
print(" • Responsive gallery and team sections") |
||||||
|
print() |
||||||
|
|
||||||
|
# Start the development server |
||||||
|
bg.dev(port=3005) |
||||||
@ -0,0 +1,46 @@ |
|||||||
|
#!/usr/bin/env python3 |
||||||
|
""" |
||||||
|
Example BadGUI application demonstrating basic components and layouts. |
||||||
|
""" |
||||||
|
|
||||||
|
import badgui as ui |
||||||
|
|
||||||
|
def main(): |
||||||
|
# Main title |
||||||
|
ui.label("Welcome to BadGUI!", classes=["text-h3", "text-primary"]) |
||||||
|
|
||||||
|
# Buttons in a row |
||||||
|
with ui.row(): |
||||||
|
ui.button("Primary Button", classes=["q-mr-md"]) |
||||||
|
ui.button("Secondary Button", classes=["q-mr-md"]) |
||||||
|
ui.button("Success Button", classes=["bg-positive"]) |
||||||
|
|
||||||
|
# Input fields in a column |
||||||
|
with ui.column(): |
||||||
|
ui.input(placeholder="Enter your name", classes=["q-mb-md"]) |
||||||
|
ui.input(placeholder="Enter your email", classes=["q-mb-md"]) |
||||||
|
ui.input(placeholder="Enter your message", classes=["q-mb-md"]) |
||||||
|
|
||||||
|
# Another row with mixed content |
||||||
|
with ui.row(): |
||||||
|
ui.label("Status:") |
||||||
|
ui.label("Ready", classes=["text-positive", "text-weight-bold"]) |
||||||
|
|
||||||
|
# a table with some data |
||||||
|
with ui.column(): |
||||||
|
ui.label("User Data", classes=["text-h5", "text-secondary", "q-mb-md"]) |
||||||
|
with ui.row(classes=["q-pa-md", "bg-grey-2"]): |
||||||
|
ui.label("Name", classes=["text-bold", "q-mr-lg"]) |
||||||
|
ui.label("Email", classes=["text-bold", "q-mr-lg"]) |
||||||
|
ui.label("Role", classes=["text-bold"]) |
||||||
|
with ui.row(classes=["q-pa-md"]): |
||||||
|
ui.label("Alice", classes=["q-mr-lg"]) |
||||||
|
ui.label("alice@example.com", classes=["q-mr-lg"]) |
||||||
|
ui.label("Admin", classes=["q-mr-lg"]) |
||||||
|
|
||||||
|
# Build the Vue.js project |
||||||
|
print("🚀 Building BadGUI project...") |
||||||
|
ui.build(output_dir="./example-output", project_name="badgui-example") |
||||||
|
|
||||||
|
if __name__ == "__main__": |
||||||
|
main() |
||||||
@ -0,0 +1,151 @@ |
|||||||
|
""" |
||||||
|
Flex Layout Test - Demonstrating Quasar Flex Utilities |
||||||
|
Tests different flex layouts to prevent card overflow issues. |
||||||
|
""" |
||||||
|
|
||||||
|
import badgui as bg |
||||||
|
|
||||||
|
# Test page demonstrating proper flex layouts |
||||||
|
with bg.column() as main: |
||||||
|
main.classes("q-pa-lg") |
||||||
|
|
||||||
|
bg.label("Flex Layout Tests").classes("text-h3 q-mb-lg text-center") |
||||||
|
|
||||||
|
# Test 1: Horizontal flex row with wrapping |
||||||
|
with bg.card() as test1_card: |
||||||
|
test1_card.classes("q-mb-lg") |
||||||
|
with bg.card_section(): |
||||||
|
bg.label("Test 1: Horizontal Row with Wrapping").classes("text-h5 q-mb-md text-primary") |
||||||
|
|
||||||
|
with bg.row() as test1_row: |
||||||
|
test1_row.classes("q-gutter-md wrap") |
||||||
|
with bg.card() as card1: |
||||||
|
card1.classes("col-12 col-sm-6 col-md-4 bg-blue-1") |
||||||
|
with bg.card_section(): |
||||||
|
bg.icon("speed", size="2rem", color="primary") |
||||||
|
bg.label("Card 1").classes("text-h6") |
||||||
|
bg.label("This card will wrap on small screens") |
||||||
|
|
||||||
|
with bg.card() as card2: |
||||||
|
card2.classes("col-12 col-sm-6 col-md-4 bg-green-1") |
||||||
|
with bg.card_section(): |
||||||
|
bg.icon("build", size="2rem", color="secondary") |
||||||
|
bg.label("Card 2").classes("text-h6") |
||||||
|
bg.label("Responsive wrapping prevents overflow") |
||||||
|
|
||||||
|
with bg.card() as card3: |
||||||
|
card3.classes("col-12 col-sm-6 col-md-4 bg-orange-1") |
||||||
|
with bg.card_section(): |
||||||
|
bg.icon("code", size="2rem", color="accent") |
||||||
|
bg.label("Card 3").classes("text-h6") |
||||||
|
bg.label("Uses Quasar's flex system") |
||||||
|
|
||||||
|
# Test 2: Vertical flex column |
||||||
|
with bg.card() as test2_card: |
||||||
|
test2_card.classes("q-mb-lg") |
||||||
|
with bg.card_section(): |
||||||
|
bg.label("Test 2: Vertical Column Layout").classes("text-h5 q-mb-md text-secondary") |
||||||
|
|
||||||
|
with bg.column() as test2_col: |
||||||
|
test2_col.classes("q-gutter-md") |
||||||
|
with bg.card() as purple_card: |
||||||
|
purple_card.classes("bg-purple-1") |
||||||
|
with bg.card_section(): |
||||||
|
with bg.row() as purple_row: |
||||||
|
purple_row.classes("items-center q-gutter-sm") |
||||||
|
bg.icon("layers", color="purple") |
||||||
|
bg.label("Stacked Card 1").classes("text-h6") |
||||||
|
|
||||||
|
with bg.card() as teal_card: |
||||||
|
teal_card.classes("bg-teal-1") |
||||||
|
with bg.card_section(): |
||||||
|
with bg.row() as teal_row: |
||||||
|
teal_row.classes("items-center q-gutter-sm") |
||||||
|
bg.icon("dashboard", color="teal") |
||||||
|
bg.label("Stacked Card 2").classes("text-h6") |
||||||
|
|
||||||
|
with bg.card() as pink_card: |
||||||
|
pink_card.classes("bg-pink-1") |
||||||
|
with bg.card_section(): |
||||||
|
with bg.row() as pink_row: |
||||||
|
pink_row.classes("items-center q-gutter-sm") |
||||||
|
bg.icon("widgets", color="pink") |
||||||
|
bg.label("Stacked Card 3").classes("text-h6") |
||||||
|
|
||||||
|
# Test 3: Mixed layout with proper responsive behavior |
||||||
|
with bg.card() as test3_card: |
||||||
|
test3_card.classes("q-mb-lg") |
||||||
|
with bg.card_section(): |
||||||
|
bg.label("Test 3: Mixed Responsive Layout").classes("text-h5 q-mb-md text-accent") |
||||||
|
|
||||||
|
with bg.row() as test3_row: |
||||||
|
test3_row.classes("q-gutter-md wrap") |
||||||
|
# Left column - takes full width on mobile, half on tablet+ |
||||||
|
with bg.column() as left_col: |
||||||
|
left_col.classes("col-12 col-md-6") |
||||||
|
with bg.card() as main_card: |
||||||
|
main_card.classes("bg-grey-2 full-height") |
||||||
|
with bg.card_section(): |
||||||
|
bg.label("Main Content").classes("text-h6 q-mb-md") |
||||||
|
bg.label("This column adapts to screen size") |
||||||
|
bg.label("Full width on mobile, half width on desktop") |
||||||
|
|
||||||
|
# Right column - also responsive |
||||||
|
with bg.column() as right_col: |
||||||
|
right_col.classes("col-12 col-md-6") |
||||||
|
with bg.column() as right_inner: |
||||||
|
right_inner.classes("q-gutter-md") |
||||||
|
with bg.card() as info_card: |
||||||
|
info_card.classes("bg-blue-2") |
||||||
|
with bg.card_section(): |
||||||
|
with bg.row() as info_row: |
||||||
|
info_row.classes("items-center q-gutter-sm") |
||||||
|
bg.icon("info", color="blue") |
||||||
|
bg.label("Info Card").classes("text-subtitle1") |
||||||
|
|
||||||
|
with bg.card() as success_card: |
||||||
|
success_card.classes("bg-green-2") |
||||||
|
with bg.card_section(): |
||||||
|
with bg.row() as success_row: |
||||||
|
success_row.classes("items-center q-gutter-sm") |
||||||
|
bg.icon("check_circle", color="green") |
||||||
|
bg.label("Success Card").classes("text-subtitle1") |
||||||
|
|
||||||
|
# Test 4: Gallery grid with proper wrapping |
||||||
|
with bg.card() as gallery_card: |
||||||
|
with bg.card_section(): |
||||||
|
bg.label("Test 4: Image Gallery Grid").classes("text-h5 q-mb-md text-deep-orange") |
||||||
|
|
||||||
|
with bg.row() as gallery_row: |
||||||
|
gallery_row.classes("q-gutter-sm wrap") |
||||||
|
# Create 6 image cards that will wrap nicely |
||||||
|
for i in range(1, 7): |
||||||
|
with bg.column() as img_col: |
||||||
|
img_col.classes("col-6 col-sm-4 col-md-2") |
||||||
|
bg.image(f"https://picsum.photos/150/150?random={i}").classes("rounded-lg full-width") |
||||||
|
bg.label(f"Image {i}").classes("text-center text-caption q-mt-xs") |
||||||
|
|
||||||
|
# Summary card |
||||||
|
with bg.card() as summary_card: |
||||||
|
summary_card.classes("q-mt-lg bg-indigo-1") |
||||||
|
with bg.card_section(): |
||||||
|
bg.label("Key Flex Classes Used:").classes("text-h6 q-mb-md text-indigo") |
||||||
|
with bg.column() as summary_col: |
||||||
|
summary_col.classes("q-gutter-sm") |
||||||
|
bg.label("• .wrap - Allows flex items to wrap to new lines") |
||||||
|
bg.label("• .col-12 .col-sm-6 .col-md-4 - Responsive column sizing") |
||||||
|
bg.label("• .q-gutter-md - Consistent spacing between items") |
||||||
|
bg.label("• .full-width - Ensures images don't overflow") |
||||||
|
bg.label("• .items-center .justify-center - Alignment utilities") |
||||||
|
|
||||||
|
if __name__ == "__main__": |
||||||
|
print("🎨 Flex Layout Test") |
||||||
|
print("This example demonstrates:") |
||||||
|
print(" • Proper flex wrapping to prevent overflow") |
||||||
|
print(" • Responsive column layouts") |
||||||
|
print(" • Vertical and horizontal flex containers") |
||||||
|
print(" • Mixed responsive layouts") |
||||||
|
print(" • Image gallery with proper grid wrapping") |
||||||
|
print() |
||||||
|
|
||||||
|
bg.dev(port=3007) |
||||||
@ -0,0 +1,327 @@ |
|||||||
|
""" |
||||||
|
BadGUI Header & Footer Example |
||||||
|
Demonstrates header and footer layout components with a complete navigation site. |
||||||
|
""" |
||||||
|
|
||||||
|
import badgui as bg |
||||||
|
|
||||||
|
# Create the main page with header and footer layout |
||||||
|
with bg.page("/", "HomePage", "Home - My Website"): |
||||||
|
|
||||||
|
# Header with navigation bar |
||||||
|
with bg.header(elevated=True) as header: |
||||||
|
header.classes("bg-primary text-white") |
||||||
|
with bg.row() as nav_row: |
||||||
|
nav_row.classes("items-center justify-between w-full") |
||||||
|
# Logo/Brand |
||||||
|
bg.label("My Website").classes("text-h4 font-bold") |
||||||
|
|
||||||
|
# Navigation menu |
||||||
|
with bg.row() as nav_menu: |
||||||
|
nav_menu.classes("q-gutter-md") |
||||||
|
bg.link("Home", "/").classes("text-white no-underline hover:text-yellow-300") |
||||||
|
bg.link("About", "/about").classes("text-white no-underline hover:text-yellow-300") |
||||||
|
bg.link("Services", "/services").classes("text-white no-underline hover:text-yellow-300") |
||||||
|
bg.link("Contact", "/contact").classes("text-white no-underline hover:text-yellow-300") |
||||||
|
|
||||||
|
# Main content area |
||||||
|
with bg.column() as main_content: |
||||||
|
main_content.classes("flex-grow q-pa-lg") |
||||||
|
# Hero section |
||||||
|
with bg.card().classes("bg-gradient-to-r from-blue-500 to-purple-600 text-white q-mb-lg"): |
||||||
|
with bg.card_section(): |
||||||
|
bg.label("Welcome to My Website").classes("text-h3 text-center q-mb-md") |
||||||
|
bg.label("Building beautiful web applications with BadGUI").classes("text-h6 text-center opacity-90") |
||||||
|
|
||||||
|
# Content sections |
||||||
|
with bg.row().classes("q-gutter-lg"): |
||||||
|
# Features section |
||||||
|
with bg.card().classes("col-4"): |
||||||
|
with bg.card_section(): |
||||||
|
bg.label("Features").classes("text-h5 q-mb-md text-primary") |
||||||
|
bg.label("• Fast development with Python") |
||||||
|
bg.label("• Generates Vue.js/Quasar projects") |
||||||
|
bg.label("• NiceGUI-like syntax") |
||||||
|
bg.label("• Responsive design") |
||||||
|
|
||||||
|
# Services section |
||||||
|
with bg.card().classes("col-4"): |
||||||
|
with bg.card_section(): |
||||||
|
bg.label("Services").classes("text-h5 q-mb-md text-primary") |
||||||
|
bg.label("• Web Application Development") |
||||||
|
bg.label("• UI/UX Design") |
||||||
|
bg.label("• Consulting Services") |
||||||
|
bg.label("• Training & Support") |
||||||
|
|
||||||
|
# Technologies section |
||||||
|
with bg.card().classes("col-4"): |
||||||
|
with bg.card_section(): |
||||||
|
bg.label("Technologies").classes("text-h5 q-mb-md text-primary") |
||||||
|
bg.label("• Python Backend") |
||||||
|
bg.label("• Vue.js 3 Frontend") |
||||||
|
bg.label("• Quasar Framework") |
||||||
|
bg.label("• Modern CSS/Tailwind") |
||||||
|
|
||||||
|
# Footer |
||||||
|
with bg.footer().classes("bg-dark text-white"): |
||||||
|
with bg.column().classes("q-pa-md"): |
||||||
|
# Footer content |
||||||
|
with bg.row().classes("justify-between items-start"): |
||||||
|
# Company info |
||||||
|
with bg.column().classes("col-4"): |
||||||
|
bg.label("My Website").classes("text-h6 q-mb-sm") |
||||||
|
bg.label("Building the future of web development with BadGUI framework.") |
||||||
|
|
||||||
|
# Quick links |
||||||
|
with bg.column().classes("col-4"): |
||||||
|
bg.label("Quick Links").classes("text-h6 q-mb-sm") |
||||||
|
with bg.column().classes("q-gutter-xs"): |
||||||
|
bg.link("Home", "/").classes("text-white no-underline") |
||||||
|
bg.link("About", "/about").classes("text-white no-underline") |
||||||
|
bg.link("Services", "/services").classes("text-white no-underline") |
||||||
|
bg.link("Contact", "/contact").classes("text-white no-underline") |
||||||
|
|
||||||
|
# Contact info |
||||||
|
with bg.column().classes("col-4"): |
||||||
|
bg.label("Contact").classes("text-h6 q-mb-sm") |
||||||
|
bg.label("📧 contact@mywebsite.com") |
||||||
|
bg.label("📞 +1 (555) 123-4567") |
||||||
|
bg.label("📍 123 Main St, City, State") |
||||||
|
|
||||||
|
# Copyright |
||||||
|
with bg.row().classes("justify-center q-mt-lg q-pt-md border-t border-gray-600"): |
||||||
|
bg.label("© 2024 My Website. All rights reserved. Built with BadGUI.").classes("text-center opacity-75") |
||||||
|
|
||||||
|
# About page |
||||||
|
with bg.page("/about", "AboutPage", "About - My Website"): |
||||||
|
|
||||||
|
# Header with navigation bar |
||||||
|
with bg.header(elevated=True).classes("bg-primary text-white"): |
||||||
|
with bg.row().classes("items-center justify-between w-full"): |
||||||
|
# Logo/Brand |
||||||
|
bg.label("My Website").classes("text-h4 font-bold") |
||||||
|
|
||||||
|
# Navigation menu |
||||||
|
with bg.row().classes("q-gutter-md"): |
||||||
|
bg.link("Home", "/").classes("text-white no-underline hover:text-yellow-300") |
||||||
|
bg.link("About", "/about").classes("text-white no-underline hover:text-yellow-300 font-bold") |
||||||
|
bg.link("Services", "/services").classes("text-white no-underline hover:text-yellow-300") |
||||||
|
bg.link("Contact", "/contact").classes("text-white no-underline hover:text-yellow-300") |
||||||
|
|
||||||
|
# Main content |
||||||
|
with bg.column().classes("flex-grow q-pa-lg"): |
||||||
|
bg.label("About Us").classes("text-h3 q-mb-lg text-center") |
||||||
|
|
||||||
|
with bg.card().classes("max-w-4xl mx-auto"): |
||||||
|
with bg.card_section(): |
||||||
|
bg.label("Our Story").classes("text-h5 q-mb-md text-primary") |
||||||
|
bg.label("We are passionate developers who believe in making web development accessible and enjoyable. Our BadGUI framework combines the simplicity of Python with the power of modern web technologies.") |
||||||
|
|
||||||
|
bg.label("Our Mission").classes("text-h5 q-mb-md q-mt-lg text-primary") |
||||||
|
bg.label("To empower developers to create beautiful, functional web applications without the complexity of traditional web development. We bridge the gap between Python's simplicity and modern web frameworks.") |
||||||
|
|
||||||
|
# Footer (same as home page) |
||||||
|
with bg.footer().classes("bg-dark text-white"): |
||||||
|
with bg.column().classes("q-pa-md"): |
||||||
|
with bg.row().classes("justify-between items-start"): |
||||||
|
with bg.column().classes("col-4"): |
||||||
|
bg.label("My Website").classes("text-h6 q-mb-sm") |
||||||
|
bg.label("Building the future of web development with BadGUI framework.") |
||||||
|
|
||||||
|
with bg.column().classes("col-4"): |
||||||
|
bg.label("Quick Links").classes("text-h6 q-mb-sm") |
||||||
|
with bg.column().classes("q-gutter-xs"): |
||||||
|
bg.link("Home", "/").classes("text-white no-underline") |
||||||
|
bg.link("About", "/about").classes("text-white no-underline") |
||||||
|
bg.link("Services", "/services").classes("text-white no-underline") |
||||||
|
bg.link("Contact", "/contact").classes("text-white no-underline") |
||||||
|
|
||||||
|
with bg.column().classes("col-4"): |
||||||
|
bg.label("Contact").classes("text-h6 q-mb-sm") |
||||||
|
bg.label("📧 contact@mywebsite.com") |
||||||
|
bg.label("📞 +1 (555) 123-4567") |
||||||
|
bg.label("📍 123 Main St, City, State") |
||||||
|
|
||||||
|
with bg.row().classes("justify-center q-mt-lg q-pt-md border-t border-gray-600"): |
||||||
|
bg.label("© 2024 My Website. All rights reserved. Built with BadGUI.").classes("text-center opacity-75") |
||||||
|
|
||||||
|
# Services page |
||||||
|
with bg.page("/services", "ServicesPage", "Services - My Website"): |
||||||
|
|
||||||
|
# Header with navigation bar |
||||||
|
with bg.header(elevated=True).classes("bg-primary text-white"): |
||||||
|
with bg.row().classes("items-center justify-between w-full"): |
||||||
|
bg.label("My Website").classes("text-h4 font-bold") |
||||||
|
|
||||||
|
with bg.row().classes("q-gutter-md"): |
||||||
|
bg.link("Home", "/").classes("text-white no-underline hover:text-yellow-300") |
||||||
|
bg.link("About", "/about").classes("text-white no-underline hover:text-yellow-300") |
||||||
|
bg.link("Services", "/services").classes("text-white no-underline hover:text-yellow-300 font-bold") |
||||||
|
bg.link("Contact", "/contact").classes("text-white no-underline hover:text-yellow-300") |
||||||
|
|
||||||
|
# Main content |
||||||
|
with bg.column().classes("flex-grow q-pa-lg"): |
||||||
|
bg.label("Our Services").classes("text-h3 q-mb-lg text-center") |
||||||
|
|
||||||
|
with bg.row().classes("q-gutter-lg justify-center"): |
||||||
|
# Web Development |
||||||
|
with bg.card().classes("col-5"): |
||||||
|
with bg.card_section(): |
||||||
|
bg.label("🌐 Web Development").classes("text-h5 q-mb-md text-primary") |
||||||
|
bg.label("Custom web applications built with modern technologies. We specialize in Python backends and Vue.js frontends.") |
||||||
|
|
||||||
|
with bg.card_actions(): |
||||||
|
bg.button("Learn More").classes("bg-primary text-white") |
||||||
|
|
||||||
|
# UI/UX Design |
||||||
|
with bg.card().classes("col-5"): |
||||||
|
with bg.card_section(): |
||||||
|
bg.label("🎨 UI/UX Design").classes("text-h5 q-mb-md text-primary") |
||||||
|
bg.label("Beautiful, intuitive user interfaces that provide excellent user experience across all devices.") |
||||||
|
|
||||||
|
with bg.card_actions(): |
||||||
|
bg.button("View Portfolio").classes("bg-primary text-white") |
||||||
|
|
||||||
|
with bg.row().classes("q-gutter-lg justify-center q-mt-lg"): |
||||||
|
# Consulting |
||||||
|
with bg.card().classes("col-5"): |
||||||
|
with bg.card_section(): |
||||||
|
bg.label("💡 Consulting").classes("text-h5 q-mb-md text-primary") |
||||||
|
bg.label("Expert advice on technology choices, architecture decisions, and development best practices.") |
||||||
|
|
||||||
|
with bg.card_actions(): |
||||||
|
bg.button("Get Consultation").classes("bg-primary text-white") |
||||||
|
|
||||||
|
# Training |
||||||
|
with bg.card().classes("col-5"): |
||||||
|
with bg.card_section(): |
||||||
|
bg.label("📚 Training").classes("text-h5 q-mb-md text-primary") |
||||||
|
bg.label("Comprehensive training programs for your team on BadGUI, Vue.js, Python, and modern web development.") |
||||||
|
|
||||||
|
with bg.card_actions(): |
||||||
|
bg.button("View Courses").classes("bg-primary text-white") |
||||||
|
|
||||||
|
# Footer |
||||||
|
with bg.footer().classes("bg-dark text-white"): |
||||||
|
with bg.column().classes("q-pa-md"): |
||||||
|
with bg.row().classes("justify-between items-start"): |
||||||
|
with bg.column().classes("col-4"): |
||||||
|
bg.label("My Website").classes("text-h6 q-mb-sm") |
||||||
|
bg.label("Building the future of web development with BadGUI framework.") |
||||||
|
|
||||||
|
with bg.column().classes("col-4"): |
||||||
|
bg.label("Quick Links").classes("text-h6 q-mb-sm") |
||||||
|
with bg.column().classes("q-gutter-xs"): |
||||||
|
bg.link("Home", "/").classes("text-white no-underline") |
||||||
|
bg.link("About", "/about").classes("text-white no-underline") |
||||||
|
bg.link("Services", "/services").classes("text-white no-underline") |
||||||
|
bg.link("Contact", "/contact").classes("text-white no-underline") |
||||||
|
|
||||||
|
with bg.column().classes("col-4"): |
||||||
|
bg.label("Contact").classes("text-h6 q-mb-sm") |
||||||
|
bg.label("📧 contact@mywebsite.com") |
||||||
|
bg.label("📞 +1 (555) 123-4567") |
||||||
|
bg.label("📍 123 Main St, City, State") |
||||||
|
|
||||||
|
with bg.row().classes("justify-center q-mt-lg q-pt-md border-t border-gray-600"): |
||||||
|
bg.label("© 2024 My Website. All rights reserved. Built with BadGUI.").classes("text-center opacity-75") |
||||||
|
|
||||||
|
# Contact page |
||||||
|
with bg.page("/contact", "ContactPage", "Contact - My Website"): |
||||||
|
|
||||||
|
# Header with navigation bar |
||||||
|
with bg.header(elevated=True).classes("bg-primary text-white"): |
||||||
|
with bg.row().classes("items-center justify-between w-full"): |
||||||
|
bg.label("My Website").classes("text-h4 font-bold") |
||||||
|
|
||||||
|
with bg.row().classes("q-gutter-md"): |
||||||
|
bg.link("Home", "/").classes("text-white no-underline hover:text-yellow-300") |
||||||
|
bg.link("About", "/about").classes("text-white no-underline hover:text-yellow-300") |
||||||
|
bg.link("Services", "/services").classes("text-white no-underline hover:text-yellow-300") |
||||||
|
bg.link("Contact", "/contact").classes("text-white no-underline hover:text-yellow-300 font-bold") |
||||||
|
|
||||||
|
# Main content |
||||||
|
with bg.column().classes("flex-grow q-pa-lg"): |
||||||
|
bg.label("Contact Us").classes("text-h3 q-mb-lg text-center") |
||||||
|
|
||||||
|
with bg.row().classes("q-gutter-lg justify-center"): |
||||||
|
# Contact form |
||||||
|
with bg.card().classes("col-6"): |
||||||
|
with bg.card_section(): |
||||||
|
bg.label("Send us a message").classes("text-h5 q-mb-md text-primary") |
||||||
|
|
||||||
|
with bg.column().classes("q-gutter-md"): |
||||||
|
bg.input(placeholder="Your Name", v_model="name").classes("full-width") |
||||||
|
bg.input(placeholder="Your Email", v_model="email").classes("full-width") |
||||||
|
bg.input(placeholder="Subject", v_model="subject").classes("full-width") |
||||||
|
# Note: textarea would need to be implemented as a separate component |
||||||
|
bg.input(placeholder="Your Message", v_model="message").classes("full-width") |
||||||
|
bg.button("Send Message").classes("bg-primary text-white full-width") |
||||||
|
|
||||||
|
# Contact info |
||||||
|
with bg.card().classes("col-4"): |
||||||
|
with bg.card_section(): |
||||||
|
bg.label("Get in touch").classes("text-h5 q-mb-md text-primary") |
||||||
|
|
||||||
|
with bg.column().classes("q-gutter-md"): |
||||||
|
with bg.row().classes("items-center"): |
||||||
|
bg.label("📧") |
||||||
|
with bg.column(): |
||||||
|
bg.label("Email") |
||||||
|
bg.label("contact@mywebsite.com").classes("text-primary") |
||||||
|
|
||||||
|
with bg.row().classes("items-center"): |
||||||
|
bg.label("📞") |
||||||
|
with bg.column(): |
||||||
|
bg.label("Phone") |
||||||
|
bg.label("+1 (555) 123-4567").classes("text-primary") |
||||||
|
|
||||||
|
with bg.row().classes("items-center"): |
||||||
|
bg.label("📍") |
||||||
|
with bg.column(): |
||||||
|
bg.label("Address") |
||||||
|
bg.label("123 Main St, City, State 12345").classes("text-primary") |
||||||
|
|
||||||
|
with bg.row().classes("items-center"): |
||||||
|
bg.label("🕒") |
||||||
|
with bg.column(): |
||||||
|
bg.label("Hours") |
||||||
|
bg.label("Mon-Fri: 9AM-6PM").classes("text-primary") |
||||||
|
|
||||||
|
# Footer |
||||||
|
with bg.footer().classes("bg-dark text-white"): |
||||||
|
with bg.column().classes("q-pa-md"): |
||||||
|
with bg.row().classes("justify-between items-start"): |
||||||
|
with bg.column().classes("col-4"): |
||||||
|
bg.label("My Website").classes("text-h6 q-mb-sm") |
||||||
|
bg.label("Building the future of web development with BadGUI framework.") |
||||||
|
|
||||||
|
with bg.column().classes("col-4"): |
||||||
|
bg.label("Quick Links").classes("text-h6 q-mb-sm") |
||||||
|
with bg.column().classes("q-gutter-xs"): |
||||||
|
bg.link("Home", "/").classes("text-white no-underline") |
||||||
|
bg.link("About", "/about").classes("text-white no-underline") |
||||||
|
bg.link("Services", "/services").classes("text-white no-underline") |
||||||
|
bg.link("Contact", "/contact").classes("text-white no-underline") |
||||||
|
|
||||||
|
with bg.column().classes("col-4"): |
||||||
|
bg.label("Contact").classes("text-h6 q-mb-sm") |
||||||
|
bg.label("📧 contact@mywebsite.com") |
||||||
|
bg.label("📞 +1 (555) 123-4567") |
||||||
|
bg.label("📍 123 Main St, City, State") |
||||||
|
|
||||||
|
with bg.row().classes("justify-center q-mt-lg q-pt-md border-t border-gray-600"): |
||||||
|
bg.label("© 2024 My Website. All rights reserved. Built with BadGUI.").classes("text-center opacity-75") |
||||||
|
|
||||||
|
if __name__ == "__main__": |
||||||
|
print("🌟 BadGUI Header & Footer Navigation Example") |
||||||
|
print("This example demonstrates:") |
||||||
|
print(" • Header component with navigation bar") |
||||||
|
print(" • Footer component with structured content") |
||||||
|
print(" • Multi-page website with consistent layout") |
||||||
|
print(" • Responsive design with Quasar components") |
||||||
|
print(" • Professional styling with Tailwind classes") |
||||||
|
print() |
||||||
|
|
||||||
|
# Start the development server |
||||||
|
bg.dev(port=3003) |
||||||
@ -0,0 +1,16 @@ |
|||||||
|
#!/usr/bin/env python3 |
||||||
|
""" |
||||||
|
Basic BadGUI Hello World Example |
||||||
|
""" |
||||||
|
|
||||||
|
import badgui as bg |
||||||
|
|
||||||
|
def main(): |
||||||
|
with bg.page("/", "HelloPage", "Hello World"): |
||||||
|
bg.label("Hello, World!").classes("text-h2 text-primary") |
||||||
|
bg.label("Welcome to BadGUI!").classes("text-body1 text-grey-7") |
||||||
|
|
||||||
|
bg.build("hello-world-output") |
||||||
|
|
||||||
|
if __name__ == "__main__": |
||||||
|
main() |
||||||
@ -0,0 +1,20 @@ |
|||||||
|
#!/usr/bin/env python3 |
||||||
|
"""Minimal props test.""" |
||||||
|
|
||||||
|
import badgui as bg |
||||||
|
|
||||||
|
def minimal_test(): |
||||||
|
# Clear pages |
||||||
|
bg.app.pages.clear() |
||||||
|
|
||||||
|
# Use page as context manager and build within it |
||||||
|
with bg.page("/test", "Test"): |
||||||
|
# Add input with props |
||||||
|
input1 = bg.input(placeholder="Styled Input") |
||||||
|
input1.props('filled dense color=teal label="Enter text"') |
||||||
|
|
||||||
|
# Build the project |
||||||
|
bg.build("minimal-test-output") |
||||||
|
|
||||||
|
if __name__ == "__main__": |
||||||
|
minimal_test() |
||||||
@ -0,0 +1,85 @@ |
|||||||
|
#!/usr/bin/env python3 |
||||||
|
""" |
||||||
|
Multi-page BadGUI Application Example |
||||||
|
Demonstrates routing and navigation between pages. |
||||||
|
""" |
||||||
|
|
||||||
|
import badgui as bg |
||||||
|
|
||||||
|
def create_navbar(): |
||||||
|
"""Create consistent navigation across all pages.""" |
||||||
|
with bg.row().classes("bg-primary text-white q-pa-md justify-between items-center"): |
||||||
|
bg.label("My Multi-Page App").classes("text-h6 text-weight-bold") |
||||||
|
|
||||||
|
with bg.row().classes("q-gutter-md"): |
||||||
|
bg.link("Home", "/").classes("text-white no-underline q-btn q-btn-flat") |
||||||
|
bg.link("About", "/about").classes("text-white no-underline q-btn q-btn-flat") |
||||||
|
bg.link("Services", "/services").classes("text-white no-underline q-btn q-btn-flat") |
||||||
|
bg.link("Contact", "/contact").classes("text-white no-underline q-btn q-btn-flat") |
||||||
|
|
||||||
|
def main(): |
||||||
|
# Home Page |
||||||
|
with bg.page("/", "HomePage", "Home - My App"): |
||||||
|
create_navbar() |
||||||
|
|
||||||
|
with bg.column().classes("text-center q-pa-xl"): |
||||||
|
bg.label("Welcome Home").classes("text-h2 text-primary q-mb-lg") |
||||||
|
bg.label("This is a multi-page BadGUI application.").classes("text-h6 text-grey-7 q-mb-lg") |
||||||
|
|
||||||
|
with bg.row().classes("justify-center q-gutter-md"): |
||||||
|
bg.link("Learn About Us", "/about").classes("q-btn q-btn-primary") |
||||||
|
bg.link("Our Services", "/services").classes("q-btn q-btn-secondary") |
||||||
|
|
||||||
|
# About Page |
||||||
|
with bg.page("/about", "AboutPage", "About - My App"): |
||||||
|
create_navbar() |
||||||
|
|
||||||
|
with bg.column().classes("q-pa-xl max-width-md mx-auto"): |
||||||
|
bg.label("About Us").classes("text-h3 text-center q-mb-lg") |
||||||
|
bg.label("We are a company dedicated to building amazing web applications.").classes("text-body1 q-mb-md") |
||||||
|
bg.label("Our team has years of experience in web development.").classes("text-body1 q-mb-lg") |
||||||
|
|
||||||
|
bg.link("← Back to Home", "/").classes("q-btn q-btn-outline") |
||||||
|
|
||||||
|
# Services Page |
||||||
|
with bg.page("/services", "ServicesPage", "Services - My App"): |
||||||
|
create_navbar() |
||||||
|
|
||||||
|
with bg.column().classes("q-pa-xl"): |
||||||
|
bg.label("Our Services").classes("text-h3 text-center q-mb-xl") |
||||||
|
|
||||||
|
services = [ |
||||||
|
("Web Development", "Custom web applications built with modern technologies"), |
||||||
|
("Mobile Apps", "Native and cross-platform mobile app development"), |
||||||
|
("Consulting", "Technical consulting and architecture design"), |
||||||
|
("Support", "Ongoing maintenance and support services") |
||||||
|
] |
||||||
|
|
||||||
|
with bg.row().classes("q-col-gutter-lg"): |
||||||
|
for title, description in services: |
||||||
|
with bg.column().classes("col-12 col-md-6 col-lg-3"): |
||||||
|
with bg.column().classes("bg-white rounded shadow-2 q-pa-lg text-center"): |
||||||
|
bg.label(title).classes("text-h6 text-primary q-mb-md") |
||||||
|
bg.label(description).classes("text-body2") |
||||||
|
|
||||||
|
# Contact Page |
||||||
|
with bg.page("/contact", "ContactPage", "Contact - My App"): |
||||||
|
create_navbar() |
||||||
|
|
||||||
|
with bg.column().classes("q-pa-xl max-width-sm mx-auto"): |
||||||
|
bg.label("Contact Us").classes("text-h3 text-center q-mb-lg") |
||||||
|
|
||||||
|
# Contact form |
||||||
|
bg.input(placeholder="Your Name").classes("q-mb-md").props("filled required") |
||||||
|
bg.input(placeholder="Your Email").classes("q-mb-md").props("filled required type=email") |
||||||
|
bg.input(placeholder="Subject").classes("q-mb-md").props("filled required") |
||||||
|
bg.input(placeholder="Your Message").classes("q-mb-lg").props("filled required type=textarea rows=4") |
||||||
|
|
||||||
|
bg.button("Send Message").classes("q-btn q-btn-primary full-width q-mb-md") |
||||||
|
|
||||||
|
bg.link("← Back to Home", "/").classes("q-btn q-btn-outline full-width") |
||||||
|
|
||||||
|
bg.build("multipage-app-output") |
||||||
|
|
||||||
|
if __name__ == "__main__": |
||||||
|
main() |
||||||
@ -0,0 +1,118 @@ |
|||||||
|
#!/usr/bin/env python3 |
||||||
|
""" |
||||||
|
Multi-page BadGUI application demonstrating routing between pages. |
||||||
|
""" |
||||||
|
|
||||||
|
import badgui as ui |
||||||
|
|
||||||
|
def main(): |
||||||
|
# ===== HOME PAGE ===== |
||||||
|
ui.page("/", "HomePage", "Home") |
||||||
|
|
||||||
|
# Welcome section |
||||||
|
ui.label("Welcome to BadGUI Multi-Page App!", classes=["text-h3", "text-primary", "q-mb-lg"]) |
||||||
|
|
||||||
|
# Navigation links |
||||||
|
with ui.row(classes=["q-gutter-md", "q-mb-xl"]): |
||||||
|
ui.link("Go to About", "/about", classes=["q-btn", "q-btn--outline"]) |
||||||
|
ui.link("Visit Contact", "/contact", classes=["q-btn", "q-btn--outline"]) |
||||||
|
ui.link("View Products", "/products", classes=["q-btn", "q-btn--outline"]) |
||||||
|
|
||||||
|
# Main content |
||||||
|
with ui.column(classes=["q-gutter-md"]): |
||||||
|
ui.label("This is the home page content", classes=["text-body1"]) |
||||||
|
|
||||||
|
with ui.row(classes=["q-pa-md", "bg-grey-1"]): |
||||||
|
ui.label("Feature 1", classes=["text-weight-bold"]) |
||||||
|
ui.label("Amazing functionality") |
||||||
|
|
||||||
|
with ui.row(classes=["q-pa-md", "bg-grey-1"]): |
||||||
|
ui.label("Feature 2", classes=["text-weight-bold"]) |
||||||
|
ui.label("Even better features") |
||||||
|
|
||||||
|
# ===== ABOUT PAGE ===== |
||||||
|
ui.page("/about", "AboutPage", "About Us") |
||||||
|
|
||||||
|
ui.label("About Our Company", classes=["text-h3", "text-secondary", "q-mb-lg"]) |
||||||
|
|
||||||
|
# Navigation back |
||||||
|
with ui.row(classes=["q-gutter-sm", "q-mb-lg"]): |
||||||
|
ui.link("← Back to Home", "/", classes=["q-btn", "q-btn--flat"]) |
||||||
|
ui.link("Contact Us", "/contact", classes=["q-btn", "q-btn--outline"]) |
||||||
|
|
||||||
|
# About content |
||||||
|
with ui.column(classes=["q-gutter-md"]): |
||||||
|
ui.label("We are a company dedicated to making Vue.js development easier with Python.", |
||||||
|
classes=["text-body1"]) |
||||||
|
|
||||||
|
ui.label("Our Mission", classes=["text-h5", "text-primary"]) |
||||||
|
ui.label("To bridge the gap between Python and modern web development.", |
||||||
|
classes=["text-body2"]) |
||||||
|
|
||||||
|
with ui.row(classes=["q-pa-lg", "bg-blue-1"]): |
||||||
|
ui.label("Founded: 2024", classes=["q-mr-lg"]) |
||||||
|
ui.label("Team Size: 5+", classes=["q-mr-lg"]) |
||||||
|
ui.label("Projects: 10+") |
||||||
|
|
||||||
|
# ===== CONTACT PAGE ===== |
||||||
|
ui.page("/contact", "ContactPage", "Contact") |
||||||
|
|
||||||
|
ui.label("Get in Touch", classes=["text-h3", "text-accent", "q-mb-lg"]) |
||||||
|
|
||||||
|
# Navigation |
||||||
|
with ui.row(classes=["q-gutter-sm", "q-mb-lg"]): |
||||||
|
ui.link("← Home", "/", classes=["q-btn", "q-btn--flat"]) |
||||||
|
ui.link("About Us", "/about", classes=["q-btn", "q-btn--flat"]) |
||||||
|
|
||||||
|
# Contact form |
||||||
|
with ui.column(classes=["q-gutter-md", "q-pa-md", "bg-grey-1"]): |
||||||
|
ui.label("Contact Form", classes=["text-h5"]) |
||||||
|
|
||||||
|
ui.input(placeholder="Your Name", classes=["q-mb-md"]) |
||||||
|
ui.input(placeholder="Your Email", classes=["q-mb-md"]) |
||||||
|
ui.input(placeholder="Your Message", classes=["q-mb-md"]) |
||||||
|
|
||||||
|
with ui.row(): |
||||||
|
ui.button("Send Message", classes=["q-btn", "bg-primary", "text-white"]) |
||||||
|
ui.button("Clear", classes=["q-btn", "q-btn--outline", "q-ml-md"]) |
||||||
|
|
||||||
|
# ===== PRODUCTS PAGE ===== |
||||||
|
ui.page("/products", "ProductsPage", "Our Products") |
||||||
|
|
||||||
|
ui.label("Our Products", classes=["text-h3", "text-primary", "q-mb-lg"]) |
||||||
|
|
||||||
|
# Navigation |
||||||
|
with ui.row(classes=["q-gutter-sm", "q-mb-lg"]): |
||||||
|
ui.link("← Home", "/", classes=["q-btn", "q-btn--flat"]) |
||||||
|
ui.link("About", "/about", classes=["q-btn", "q-btn--flat"]) |
||||||
|
ui.link("Contact", "/contact", classes=["q-btn", "q-btn--flat"]) |
||||||
|
|
||||||
|
# Products grid |
||||||
|
with ui.column(classes=["q-gutter-lg"]): |
||||||
|
# Product 1 |
||||||
|
with ui.row(classes=["q-pa-lg", "bg-blue-1"]): |
||||||
|
with ui.column(): |
||||||
|
ui.label("BadGUI Framework", classes=["text-h5", "text-primary"]) |
||||||
|
ui.label("Python to Vue.js code generator", classes=["text-body2"]) |
||||||
|
ui.button("Learn More", classes=["q-btn", "q-btn--outline", "q-mt-md"]) |
||||||
|
|
||||||
|
# Product 2 |
||||||
|
with ui.row(classes=["q-pa-lg", "bg-green-1"]): |
||||||
|
with ui.column(): |
||||||
|
ui.label("BadGUI CLI", classes=["text-h5", "text-positive"]) |
||||||
|
ui.label("Command line tools for rapid development", classes=["text-body2"]) |
||||||
|
ui.button("Download", classes=["q-btn", "q-btn--outline", "q-mt-md"]) |
||||||
|
|
||||||
|
# Product 3 |
||||||
|
with ui.row(classes=["q-pa-lg", "bg-orange-1"]): |
||||||
|
with ui.column(): |
||||||
|
ui.label("BadGUI Templates", classes=["text-h5", "text-warning"]) |
||||||
|
ui.label("Pre-built templates for common use cases", classes=["text-body2"]) |
||||||
|
ui.button("Browse", classes=["q-btn", "q-btn--outline", "q-mt-md"]) |
||||||
|
|
||||||
|
# Build the Vue.js project |
||||||
|
print("🚀 Building BadGUI Multi-Page project...") |
||||||
|
ui.build(output_dir="./multipage-output", project_name="badgui-multipage") |
||||||
|
|
||||||
|
if __name__ == "__main__": |
||||||
|
main() |
||||||
@ -0,0 +1,146 @@ |
|||||||
|
""" |
||||||
|
Simplified Navigation Example with Header & Footer |
||||||
|
Working example that demonstrates the header and footer functionality. |
||||||
|
""" |
||||||
|
|
||||||
|
import badgui as bg |
||||||
|
|
||||||
|
# Home page |
||||||
|
with bg.page("/", "HomePage", "Home - My Website"): |
||||||
|
|
||||||
|
# Header with navigation bar |
||||||
|
with bg.header(elevated=True) as header: |
||||||
|
header.classes("bg-primary text-white q-pa-md") |
||||||
|
|
||||||
|
with bg.row() as nav_row: |
||||||
|
nav_row.classes("items-center justify-between w-full") |
||||||
|
|
||||||
|
# Logo/Brand |
||||||
|
bg.label("My Website").classes("text-h4 font-bold") |
||||||
|
|
||||||
|
# Navigation menu |
||||||
|
with bg.row() as nav_menu: |
||||||
|
nav_menu.classes("q-gutter-md") |
||||||
|
bg.link("Home", "/").classes("text-white") |
||||||
|
bg.link("About", "/about").classes("text-white") |
||||||
|
bg.link("Services", "/services").classes("text-white") |
||||||
|
bg.link("Contact", "/contact").classes("text-white") |
||||||
|
|
||||||
|
# Main content area |
||||||
|
with bg.column() as main_content: |
||||||
|
main_content.classes("q-pa-lg") |
||||||
|
|
||||||
|
# Hero section |
||||||
|
with bg.card() as hero_card: |
||||||
|
hero_card.classes("bg-blue-500 text-white q-mb-lg") |
||||||
|
with bg.card_section(): |
||||||
|
bg.label("Welcome to My Website").classes("text-h3 text-center q-mb-md") |
||||||
|
bg.label("Building beautiful web applications with BadGUI").classes("text-h6 text-center") |
||||||
|
|
||||||
|
# Features section |
||||||
|
with bg.row() as features_row: |
||||||
|
features_row.classes("q-gutter-lg") |
||||||
|
|
||||||
|
with bg.card() as feature1: |
||||||
|
feature1.classes("col-4") |
||||||
|
with bg.card_section(): |
||||||
|
bg.label("Features").classes("text-h5 q-mb-md text-primary") |
||||||
|
bg.label("• Fast Python development") |
||||||
|
bg.label("• Vue.js/Quasar output") |
||||||
|
bg.label("• NiceGUI-like syntax") |
||||||
|
|
||||||
|
with bg.card() as feature2: |
||||||
|
feature2.classes("col-4") |
||||||
|
with bg.card_section(): |
||||||
|
bg.label("Services").classes("text-h5 q-mb-md text-primary") |
||||||
|
bg.label("• Web Development") |
||||||
|
bg.label("• UI/UX Design") |
||||||
|
bg.label("• Consulting") |
||||||
|
|
||||||
|
with bg.card() as feature3: |
||||||
|
feature3.classes("col-4") |
||||||
|
with bg.card_section(): |
||||||
|
bg.label("Technologies").classes("text-h5 q-mb-md text-primary") |
||||||
|
bg.label("• Python Backend") |
||||||
|
bg.label("• Vue.js Frontend") |
||||||
|
bg.label("• Quasar Framework") |
||||||
|
|
||||||
|
# # Footer |
||||||
|
# with bg.footer() as footer: |
||||||
|
# footer.classes("bg-dark text-white q-pa-md") |
||||||
|
|
||||||
|
# with bg.column(): |
||||||
|
# with bg.row() as footer_content: |
||||||
|
# footer_content.classes("justify-between items-start") |
||||||
|
|
||||||
|
# # Company info |
||||||
|
# with bg.column() as company_info: |
||||||
|
# company_info.classes("col-4") |
||||||
|
# bg.label("My Website").classes("text-h6 q-mb-sm") |
||||||
|
# bg.label("Building the future of web development.") |
||||||
|
|
||||||
|
# # Quick links |
||||||
|
# with bg.column() as quick_links: |
||||||
|
# quick_links.classes("col-4") |
||||||
|
# bg.label("Quick Links").classes("text-h6 q-mb-sm") |
||||||
|
# bg.link("Home", "/").classes("text-white") |
||||||
|
# bg.link("About", "/about").classes("text-white") |
||||||
|
# bg.link("Services", "/services").classes("text-white") |
||||||
|
# bg.link("Contact", "/contact").classes("text-white") |
||||||
|
|
||||||
|
# # Contact info |
||||||
|
# with bg.column() as contact_info: |
||||||
|
# contact_info.classes("col-4") |
||||||
|
# bg.label("Contact").classes("text-h6 q-mb-sm") |
||||||
|
# bg.label("📧 contact@mywebsite.com") |
||||||
|
# bg.label("📞 +1 (555) 123-4567") |
||||||
|
|
||||||
|
# # Copyright |
||||||
|
# with bg.row() as copyright_row: |
||||||
|
# copyright_row.classes("justify-center q-mt-lg") |
||||||
|
# bg.label("© 2024 My Website. Built with BadGUI.").classes("text-center") |
||||||
|
|
||||||
|
# About page |
||||||
|
with bg.page("/about", "AboutPage", "About - My Website"): |
||||||
|
|
||||||
|
# Header |
||||||
|
with bg.header(elevated=True) as header: |
||||||
|
header.classes("bg-primary text-white q-pa-md") |
||||||
|
with bg.row() as nav_row: |
||||||
|
nav_row.classes("items-center justify-between w-full") |
||||||
|
bg.label("My Website").classes("text-h4 font-bold") |
||||||
|
with bg.row() as nav_menu: |
||||||
|
nav_menu.classes("q-gutter-md") |
||||||
|
bg.link("Home", "/").classes("text-white") |
||||||
|
bg.link("About", "/about").classes("text-white font-bold") |
||||||
|
bg.link("Services", "/services").classes("text-white") |
||||||
|
bg.link("Contact", "/contact").classes("text-white") |
||||||
|
|
||||||
|
# Main content |
||||||
|
with bg.column() as main_content: |
||||||
|
main_content.classes("q-pa-lg") |
||||||
|
bg.label("About Us").classes("text-h3 q-mb-lg text-center") |
||||||
|
|
||||||
|
with bg.card(): |
||||||
|
with bg.card_section(): |
||||||
|
bg.label("Our Story").classes("text-h5 q-mb-md text-primary") |
||||||
|
bg.label("We create amazing web applications using BadGUI framework.") |
||||||
|
|
||||||
|
# Footer |
||||||
|
with bg.footer() as footer: |
||||||
|
footer.classes("bg-dark text-white q-pa-md") |
||||||
|
with bg.row() as footer_content: |
||||||
|
footer_content.classes("justify-center") |
||||||
|
bg.label("© 2024 My Website. Built with BadGUI.") |
||||||
|
|
||||||
|
if __name__ == "__main__": |
||||||
|
print("🌟 BadGUI Navigation Example with Header & Footer") |
||||||
|
print("Features:") |
||||||
|
print(" • Header component with navigation") |
||||||
|
print(" • Footer component with structured content") |
||||||
|
print(" • Multi-page website structure") |
||||||
|
print(" • Quasar layout components") |
||||||
|
print() |
||||||
|
|
||||||
|
# Start the development server |
||||||
|
bg.dev(port=3005) |
||||||
@ -0,0 +1,114 @@ |
|||||||
|
#!/usr/bin/env python3 |
||||||
|
""" |
||||||
|
BadGUI styling example demonstrating .classes(), .props(), and .style() methods. |
||||||
|
""" |
||||||
|
|
||||||
|
import badgui as bg |
||||||
|
|
||||||
|
def main(): |
||||||
|
# ===== STYLING EXAMPLES PAGE ===== |
||||||
|
with bg.page("/", "StylingPage", "Styling Examples"): |
||||||
|
bg.label("BadGUI Styling Examples", classes=["text-h3", "text-primary", "q-mb-lg"]) |
||||||
|
|
||||||
|
# ===== CLASSES EXAMPLES ===== |
||||||
|
bg.label("1. Classes Method Examples", classes=["text-h5", "text-secondary", "q-mb-md"]) |
||||||
|
|
||||||
|
# Basic classes |
||||||
|
label1 = bg.label("Basic classes").classes("text-bold text-blue-600 bg-blue-100 p-4 rounded") |
||||||
|
|
||||||
|
# Method chaining with classes |
||||||
|
label2 = bg.label("Chained classes").classes("text-center").classes("text-green-600").classes("bg-green-100 p-2") |
||||||
|
|
||||||
|
# Classes with add/remove/replace |
||||||
|
label3 = bg.label("Dynamic classes") |
||||||
|
label3.classes("text-red-600 bg-red-100 p-3") |
||||||
|
label3.classes(add="border border-red-300") |
||||||
|
label3.classes(remove="bg-red-100", add="bg-red-50") |
||||||
|
|
||||||
|
# Button with classes |
||||||
|
btn1 = bg.button("Styled Button") |
||||||
|
btn1.classes("bg-purple-500 text-white rounded-full px-6 py-2 shadow-lg hover:bg-purple-600") |
||||||
|
|
||||||
|
# ===== PROPS EXAMPLES ===== |
||||||
|
bg.label("2. Props Method Examples", classes=["text-h5", "text-secondary", "q-mb-md", "q-mt-lg"]) |
||||||
|
|
||||||
|
# Button with Quasar props |
||||||
|
btn2 = bg.button("Quasar Props Button") |
||||||
|
btn2.props("outline rounded color=primary") |
||||||
|
btn2.classes("q-mr-md") |
||||||
|
|
||||||
|
# Input with props |
||||||
|
input1 = bg.input(placeholder="Styled Input") |
||||||
|
input1.props('filled dense color=teal label="Enter text"') |
||||||
|
input1.classes("q-mb-md") |
||||||
|
|
||||||
|
# Button with multiple props |
||||||
|
btn3 = bg.button("Advanced Props") |
||||||
|
btn3.props("push glossy") |
||||||
|
btn3.props(add='icon=star color=orange') |
||||||
|
btn3.classes("q-mr-md") |
||||||
|
|
||||||
|
# ===== STYLE EXAMPLES ===== |
||||||
|
bg.label("3. Style Method Examples", classes=["text-h5", "text-secondary", "q-mb-md", "q-mt-lg"]) |
||||||
|
|
||||||
|
# Basic CSS styles |
||||||
|
label4 = bg.label("CSS Styled Label") |
||||||
|
label4.style("color: #ff6b6b; font-size: 18px; font-weight: bold; padding: 10px; background: linear-gradient(45deg, #ffd93d, #ff6b6b); border-radius: 8px") |
||||||
|
|
||||||
|
# Style with method chaining |
||||||
|
label5 = bg.label("Chained Styles") |
||||||
|
label5.style("color: #4ecdc4").style("background-color: #f7f7f7; padding: 8px").style("border-left: 4px solid #4ecdc4") |
||||||
|
|
||||||
|
# Dynamic styles |
||||||
|
label6 = bg.label("Dynamic Styles") |
||||||
|
label6.style("color: red; background: yellow; padding: 5px") |
||||||
|
label6.style(remove="background", add="background: lightblue; border: 2px solid navy") |
||||||
|
|
||||||
|
# ===== COMBINED STYLING ===== |
||||||
|
bg.label("4. Combined Styling Examples", classes=["text-h5", "text-secondary", "q-mb-md", "q-mt-lg"]) |
||||||
|
|
||||||
|
# Combine all three methods |
||||||
|
combined_label = bg.label("All Methods Combined") |
||||||
|
combined_label.classes("text-center rounded shadow-md").props("data-test=combined").style("background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 15px; font-size: 16px") |
||||||
|
|
||||||
|
# Complex button styling |
||||||
|
fancy_button = bg.button("Fancy Button") |
||||||
|
fancy_button.classes("shadow-2xl transform transition-all duration-200").props("push glossy color=deep-purple").style("border-radius: 25px; padding: 12px 24px; text-transform: uppercase; letter-spacing: 1px") |
||||||
|
|
||||||
|
# ===== LAYOUTS WITH STYLING ===== |
||||||
|
bg.label("5. Layout Styling", classes=["text-h5", "text-secondary", "q-mb-md", "q-mt-lg"]) |
||||||
|
|
||||||
|
# Styled row |
||||||
|
with bg.row() as row_container: |
||||||
|
row_container.classes("bg-grey-1 p-4 rounded-lg shadow").style("border-left: 5px solid #1976d2") |
||||||
|
bg.label("Styled Row Item 1").classes("text-primary") |
||||||
|
bg.label("Styled Row Item 2").classes("text-secondary") |
||||||
|
bg.label("Styled Row Item 3").classes("text-accent") |
||||||
|
|
||||||
|
# Styled column |
||||||
|
with bg.column() as col_container: |
||||||
|
col_container.classes("bg-gradient-to-r from-blue-50 to-indigo-100 p-6 rounded-xl").style("min-height: 100px") |
||||||
|
bg.label("Column Header").classes("text-lg font-bold text-indigo-800") |
||||||
|
bg.label("Column content with styling").classes("text-indigo-600") |
||||||
|
bg.button("Column Button").classes("bg-indigo-500 text-white mt-2").props("outline") |
||||||
|
|
||||||
|
# ===== RESPONSIVE AND UTILITY CLASSES ===== |
||||||
|
bg.label("6. Responsive & Utility Classes", classes=["text-h5", "text-secondary", "q-mb-md", "q-mt-lg"]) |
||||||
|
|
||||||
|
# Responsive grid-like layout |
||||||
|
with bg.row() as responsive_row: |
||||||
|
responsive_row.classes("flex-wrap q-gutter-md") |
||||||
|
for i in range(6): |
||||||
|
card_label = bg.label(f"Card {i+1}") |
||||||
|
card_label.classes("bg-white p-4 rounded shadow flex-grow").style(f"min-width: 150px; background: hsl({i*60}, 70%, 90%)") |
||||||
|
|
||||||
|
# Utility classes example |
||||||
|
utility_label = bg.label("Utility Classes") |
||||||
|
utility_label.classes("text-xl font-bold text-center uppercase tracking-wide text-gray-700 bg-gray-100 p-6 rounded-lg border-2 border-dashed border-gray-300") |
||||||
|
|
||||||
|
# Build the Vue.js project |
||||||
|
print("🚀 Building BadGUI Styling Examples project...") |
||||||
|
bg.build(output_dir="./styling-output", project_name="badgui-styling") |
||||||
|
|
||||||
|
if __name__ == "__main__": |
||||||
|
main() |
||||||
@ -0,0 +1,118 @@ |
|||||||
|
#!/usr/bin/env python3 |
||||||
|
""" |
||||||
|
BadGUI Styling Examples - showcasing .classes(), .props(), and .style() methods |
||||||
|
""" |
||||||
|
|
||||||
|
import badgui as bg |
||||||
|
|
||||||
|
def main(): |
||||||
|
# ===== STYLING EXAMPLES PAGE ===== |
||||||
|
with bg.page("/", "StylingPage", "Styling Examples"): |
||||||
|
bg.label("BadGUI Styling Examples", classes=["text-h3", "text-primary", "q-mb-lg"]) |
||||||
|
|
||||||
|
# ===== CLASSES EXAMPLES ===== |
||||||
|
bg.label("1. Classes Method Examples", classes=["text-h5", "text-secondary", "q-mb-md"]) |
||||||
|
|
||||||
|
# Basic classes |
||||||
|
label1 = bg.label("Basic classes").classes("text-bold text-blue-600 bg-blue-100 p-4 rounded") |
||||||
|
|
||||||
|
# Method chaining with classes |
||||||
|
label2 = bg.label("Chained classes").classes("text-center").classes("text-green-600").classes("bg-green-100 p-2") |
||||||
|
|
||||||
|
# Classes with add/remove/replace |
||||||
|
label3 = bg.label("Dynamic classes") |
||||||
|
label3.classes("text-red-600 bg-red-100 p-3") |
||||||
|
label3.classes(add="border border-red-300") |
||||||
|
label3.classes(remove="bg-red-100", add="bg-red-50") |
||||||
|
|
||||||
|
# Button with classes |
||||||
|
btn1 = bg.button("Styled Button") |
||||||
|
btn1.classes("bg-purple-500 text-white rounded-full px-6 py-2 shadow-lg hover:bg-purple-600") |
||||||
|
|
||||||
|
# ===== PROPS EXAMPLES ===== |
||||||
|
bg.label("2. Props Method Examples", classes=["text-h5", "text-secondary", "q-mb-md", "q-mt-lg"]) |
||||||
|
|
||||||
|
# Button with Quasar props |
||||||
|
btn2 = bg.button("Quasar Props Button") |
||||||
|
btn2.props("outline rounded color=primary") |
||||||
|
btn2.classes("q-mr-md") |
||||||
|
|
||||||
|
# Input with props |
||||||
|
input1 = bg.input(placeholder="Styled Input") |
||||||
|
input1.props('filled dense color=teal label="Enter text"') |
||||||
|
input1.classes("q-mb-md") |
||||||
|
|
||||||
|
# Button with multiple props |
||||||
|
btn3 = bg.button("Advanced Props") |
||||||
|
btn3.props("push glossy") |
||||||
|
btn3.props(add="icon=star color=orange") |
||||||
|
btn3.classes("q-mr-md") |
||||||
|
|
||||||
|
# ===== STYLE EXAMPLES ===== |
||||||
|
bg.label("3. Style Method Examples", classes=["text-h5", "text-secondary", "q-mb-md", "q-mt-lg"]) |
||||||
|
|
||||||
|
# CSS styles as string |
||||||
|
label4 = bg.label("CSS Styled Label") |
||||||
|
label4.style("color: #ff6b6b; font-size: 18px; font-weight: bold; padding: 10px; background: linear-gradient(45deg, #ffd93d, #ff6b6b); border-radius: 8px") |
||||||
|
|
||||||
|
# Chained styles |
||||||
|
label5 = bg.label("Chained Styles") |
||||||
|
label5.style("color: #4ecdc4; background-color: #f7f7f7; padding: 8px") |
||||||
|
label5.style("border-left: 4px solid #4ecdc4") |
||||||
|
|
||||||
|
# Style method chaining with add/remove |
||||||
|
label6 = bg.label("Dynamic Styles") |
||||||
|
label6.style("color: red; background: yellow; padding: 5px") |
||||||
|
label6.style(remove="background", add="background: lightblue; border: 2px solid navy") |
||||||
|
|
||||||
|
# ===== COMBINED STYLING ===== |
||||||
|
bg.label("4. Combined Styling Examples", classes=["text-h5", "text-secondary", "q-mb-md", "q-mt-lg"]) |
||||||
|
|
||||||
|
# All methods combined |
||||||
|
combined_label = bg.label("All Methods Combined") |
||||||
|
combined_label.classes("text-center rounded shadow-md") |
||||||
|
combined_label.style("background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 15px; font-size: 16px") |
||||||
|
combined_label.props(dataTest="combined") |
||||||
|
|
||||||
|
# Fancy button with all styling methods |
||||||
|
fancy_btn = bg.button("Fancy Button") |
||||||
|
fancy_btn.classes("shadow-2xl transform transition-all duration-200") |
||||||
|
fancy_btn.style("border-radius: 25px; padding: 12px 24px; text-transform: uppercase; letter-spacing: 1px") |
||||||
|
fancy_btn.props("push glossy color=deep-purple") |
||||||
|
|
||||||
|
# ===== LAYOUT STYLING ===== |
||||||
|
bg.label("5. Layout Styling", classes=["text-h5", "text-secondary", "q-mb-md", "q-mt-lg"]) |
||||||
|
|
||||||
|
# Styled row |
||||||
|
with bg.row() as row_container: |
||||||
|
row_container.classes("bg-grey-1 p-4 rounded-lg shadow").style("border-left: 5px solid #1976d2") |
||||||
|
bg.label("Styled Row Item 1").classes("text-primary") |
||||||
|
bg.label("Styled Row Item 2").classes("text-secondary") |
||||||
|
bg.label("Styled Row Item 3").classes("text-accent") |
||||||
|
|
||||||
|
# Styled column |
||||||
|
with bg.column() as col_container: |
||||||
|
col_container.classes("bg-gradient-to-r from-blue-50 to-indigo-100 p-6 rounded-xl").style("min-height: 100px") |
||||||
|
bg.label("Column Header").classes("text-lg font-bold text-indigo-800") |
||||||
|
bg.label("Column Content").classes("text-indigo-600") |
||||||
|
|
||||||
|
# ===== RESPONSIVE AND UTILITY CLASSES ===== |
||||||
|
bg.label("6. Responsive & Utility Classes", classes=["text-h5", "text-secondary", "q-mb-md", "q-mt-lg"]) |
||||||
|
|
||||||
|
# Responsive grid-like layout |
||||||
|
with bg.row() as responsive_row: |
||||||
|
responsive_row.classes("flex-wrap q-gutter-md") |
||||||
|
for i in range(6): |
||||||
|
card_label = bg.label(f"Card {i+1}") |
||||||
|
card_label.classes("bg-white p-4 rounded shadow flex-grow").style(f"min-width: 150px; background: hsl({i*60}, 70%, 90%)") |
||||||
|
|
||||||
|
# Utility classes example |
||||||
|
utility_label = bg.label("Utility Classes") |
||||||
|
utility_label.classes("text-xl font-bold text-center uppercase tracking-wide text-gray-700 bg-gray-100 p-6 rounded-lg border-2 border-dashed border-gray-300") |
||||||
|
|
||||||
|
# Build the Vue.js project |
||||||
|
print("🚀 Building BadGUI Styling Examples project...") |
||||||
|
bg.build("styling-output") |
||||||
|
|
||||||
|
if __name__ == "__main__": |
||||||
|
main() |
||||||
@ -0,0 +1,33 @@ |
|||||||
|
#!/usr/bin/env python3 |
||||||
|
""" |
||||||
|
Test the new bg.dev() method for instant development server |
||||||
|
""" |
||||||
|
|
||||||
|
import badgui as bg |
||||||
|
|
||||||
|
def main(): |
||||||
|
with bg.page("/", "DevTestPage", "Dev Mode Test"): |
||||||
|
bg.label("🚀 Live Development Mode Test").classes("text-h2 text-primary text-center q-mb-lg") |
||||||
|
|
||||||
|
bg.label("This page was created with bg.dev()!").classes("text-h6 text-center q-mb-md") |
||||||
|
bg.label("No manual build, install, or server start needed.").classes("text-body1 text-grey-7 text-center q-mb-lg") |
||||||
|
|
||||||
|
with bg.row() as button_row: |
||||||
|
button_row.classes("justify-center q-gutter-md q-mb-lg") |
||||||
|
bg.button("Primary Button").classes("q-btn-primary") |
||||||
|
bg.button("Secondary Button").classes("q-btn-secondary") |
||||||
|
bg.button("Accent Button").classes("q-btn-accent") |
||||||
|
|
||||||
|
with bg.column() as form_column: |
||||||
|
form_column.classes("bg-grey-1 p-4 rounded max-width-md mx-auto") |
||||||
|
bg.label("Quick Test Form").classes("text-h6 q-mb-md") |
||||||
|
bg.input(placeholder="Your name").classes("q-mb-md").props("filled") |
||||||
|
bg.input(placeholder="Your email").classes("q-mb-md").props("filled type=email") |
||||||
|
bg.button("Submit").classes("q-btn-primary full-width") |
||||||
|
|
||||||
|
# Instead of bg.build(), just run bg.dev()! |
||||||
|
print("Starting development server with bg.dev()...") |
||||||
|
bg.dev(port=3000, host="localhost") |
||||||
|
|
||||||
|
if __name__ == "__main__": |
||||||
|
main() |
||||||
Loading…
Reference in new issue