🎉 BadGUI v0.2.0 - Complete UI Component Suite & Enhanced Developer Experience

## 🚀 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 development
This commit is contained in:
Matteo Benedetto
2025-09-28 00:07:57 +02:00
parent 0e0412eb3c
commit 577df5c95e
39 changed files with 5639 additions and 147 deletions
+7
View File
@@ -0,0 +1,7 @@
badgui.components module
========================
.. automodule:: badgui.components
:members:
:show-inheritance:
:undoc-members:
+7
View File
@@ -0,0 +1,7 @@
badgui.core module
==================
.. automodule:: badgui.core
:members:
:show-inheritance:
:undoc-members:
+7
View File
@@ -0,0 +1,7 @@
badgui.generator module
=======================
.. automodule:: badgui.generator
:members:
:show-inheritance:
:undoc-members:
+7
View File
@@ -0,0 +1,7 @@
badgui.layouts module
=====================
.. automodule:: badgui.layouts
:members:
:show-inheritance:
:undoc-members:
+21
View File
@@ -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:
+7
View File
@@ -0,0 +1,7 @@
badgui
======
.. toctree::
:maxdepth: 4
badgui
+400
View File
@@ -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.
+67
View File
@@ -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",
]
+248
View File
@@ -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.
+747
View File
@@ -0,0 +1,747 @@
Examples
========
This section contains practical examples demonstrating BadGUI features, including new components like cards, tabs, headers, footers, images, and icons, with emphasis on the **🚀 Instant Development** workflow using ``bg.dev()``.
🚀 Quick Start with bg.dev()
-----------------------------
The fastest way to get started - one command does it all:
.. code-block:: python
import badgui as bg
with bg.page("/", "HomePage", "Quick Start"):
bg.label("Hello BadGUI!").classes("text-h2 text-primary text-center")
bg.button("Click Me").classes("q-btn-primary q-btn-lg")
# 🚀 INSTANT DEVELOPMENT - Creates temp build, installs deps, starts server!
bg.dev()
Save as ``quick_start.py`` and run::
python quick_start.py
Your app opens automatically at ``http://localhost:9000`` ✨
Modern Website with New Components
----------------------------------
A complete website demonstrating all the new components:
.. code-block:: python
import badgui as bg
# Home page with full component showcase
with bg.page("/", "HomePage", "Modern Website"):
# Header with navigation
with bg.header() as nav_header:
nav_header.classes("bg-primary text-white q-pa-md")
with bg.row() as nav_row:
nav_row.classes("items-center justify-between")
# Logo with icon
with bg.row() as logo:
logo.classes("items-center q-gutter-sm")
bg.icon("home", size="2rem", color="white")
bg.label("My Website").classes("text-h4")
# Navigation links
with bg.row() as nav_links:
nav_links.classes("q-gutter-md")
bg.link("Home", "/").classes("text-white")
bg.link("About", "/about").classes("text-white")
# Main content
with bg.column() as main_content:
main_content.classes("q-pa-lg")
# Hero card
with bg.card() as hero:
hero.classes("bg-blue-1 q-pa-xl q-mb-lg")
with bg.card_section():
bg.label("Welcome to BadGUI").classes("text-h3 text-primary q-mb-md")
bg.label("Build modern web applications with Python syntax")
with bg.card_actions():
bg.button("Get Started").classes("q-btn-primary")
bg.button("Learn More").classes("q-btn-secondary")
# Feature cards with responsive layout
with bg.row() as features:
features.classes("q-gutter-md wrap")
# Feature 1
with bg.card() as feature1:
feature1.classes("col-12 col-md-4")
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")
bg.label("Rapid prototyping with Python syntax")
# Feature 2
with bg.card() as feature2:
feature2.classes("col-12 col-md-4")
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")
bg.label("Vue.js 3 + Quasar Framework")
# Feature 3
with bg.card() as feature3:
feature3.classes("col-12 col-md-4")
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")
bg.label("Familiar syntax and patterns")
# Image gallery
with bg.card() as gallery:
gallery.classes("q-mt-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")
# Gallery items
projects = [
("E-commerce Platform", "Modern shopping experience"),
("Dashboard App", "Data visualization tool"),
("Mobile App", "Cross-platform solution")
]
for i, (title, desc) in enumerate(projects, 1):
with bg.column() as gallery_item:
gallery_item.classes("col-12 col-sm-6 col-md-4 text-center")
bg.image(f"https://picsum.photos/300/200?random={i}").classes("rounded-lg shadow-md q-mb-sm full-width")
bg.label(title).classes("text-h6")
bg.label(desc)
# Tabs example
with bg.tabs() as main_tabs:
main_tabs.classes("text-primary q-mt-lg")
with bg.tab("features", "Features"):
pass
with bg.tab("pricing", "Pricing"):
pass
with bg.tab("support", "Support"):
pass
with bg.tab_panels() as panels:
panels.classes("q-pa-md")
with bg.tab_panel("features"):
with bg.column() as features_content:
features_content.classes("q-gutter-md")
bg.label("Comprehensive Feature Set").classes("text-h5 q-mb-md")
features_list = [
("Context Managers", "Proper component nesting with 'with' statements"),
("Responsive Design", "Built-in flex utilities and breakpoints"),
("Material Icons", "Full Material Design icon library"),
("NiceGUI API", "Familiar method chaining and styling")
]
for title, desc in features_list:
with bg.card() as feature_card:
feature_card.classes("q-pa-md")
with bg.card_section():
with bg.row() as feature_row:
feature_row.classes("items-center q-gutter-md")
bg.icon("check_circle", color="positive")
with bg.column():
bg.label(title).classes("text-h6")
bg.label(desc)
with bg.tab_panel("pricing"):
bg.label("Pricing information goes here").classes("text-h5")
bg.label("BadGUI is open source and free to use!")
with bg.tab_panel("support"):
bg.label("Support & Documentation").classes("text-h5 q-mb-md")
bg.label("Visit our GitHub repository for documentation and support")
# Footer
with bg.footer() as page_footer:
page_footer.classes("bg-dark text-white q-pa-lg")
with bg.column():
with bg.row() as footer_content:
footer_content.classes("justify-between items-center")
# Company info
with bg.column():
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")
# Social icons
with bg.row() as social_icons:
social_icons.classes("q-gutter-md")
bg.icon("facebook", size="1.5rem", color="blue")
bg.icon("twitter", size="1.5rem", color="light-blue")
bg.icon("github", size="1.5rem", color="white")
# Copyright
with bg.row() as copyright:
copyright.classes("justify-center q-pt-lg border-t border-gray-600")
bg.label("© 2024 My Website. Built with BadGUI.").classes("opacity-75")
# 🚀 Start instant development
bg.dev(port=3000)
Context Manager Usage Guide
---------------------------
Proper usage of BadGUI's context managers:
.. code-block:: python
import badgui as bg
# ✅ CORRECT: Use 'as' to capture the component
with bg.column() as main_col:
main_col.classes("q-pa-lg")
with bg.row() as header_row:
header_row.classes("items-center justify-between")
bg.label("Title")
# ❌ WRONG: Cannot call .classes() on context manager directly
# with bg.column().classes("q-pa-lg"): # This will cause AttributeError
# ✅ CORRECT: Cards with proper nesting
with bg.card() as my_card:
my_card.classes("q-ma-md shadow-5")
with bg.card_section():
bg.label("Card Title").classes("text-h5")
bg.label("Card content")
with bg.card_actions():
bg.button("Action 1")
bg.button("Action 2")
Responsive Layout Examples
--------------------------
Preventing card overflow with proper flex utilities:
.. code-block:: python
import badgui as bg
with bg.page("/responsive", "ResponsivePage", "Responsive Layouts"):
with bg.column() as main:
main.classes("q-pa-lg")
# Card grid that wraps properly
with bg.row() as card_grid:
card_grid.classes("q-gutter-md wrap") # 'wrap' prevents overflow
# Cards with responsive column classes
for i in range(6):
with bg.card() as grid_card:
grid_card.classes("col-12 col-sm-6 col-md-4 col-lg-2") # Responsive breakpoints
with bg.card_section():
bg.label(f"Card {i+1}").classes("text-h6")
bg.label("Responsive card content")
# Mixed responsive layout
with bg.row() as mixed_layout:
mixed_layout.classes("q-gutter-md wrap")
# Main content area
with bg.column() as main_content:
main_content.classes("col-12 col-md-8") # Full width on mobile, 2/3 on desktop
with bg.card() as main_card:
main_card.classes("q-pa-lg")
bg.label("Main Content").classes("text-h4 q-mb-md")
bg.label("This content area is responsive and adapts to screen size")
# Sidebar
with bg.column() as sidebar:
sidebar.classes("col-12 col-md-4") # Full width on mobile, 1/3 on desktop
with bg.card() as sidebar_card:
sidebar_card.classes("q-pa-md bg-grey-1")
bg.label("Sidebar").classes("text-h5 q-mb-md")
bg.label("Sidebar content stacks below main content on mobile")
bg.dev(port=3001)
Dashboard Application
---------------------
A complete dashboard with multiple sections:
.. code-block:: python
import badgui as bg
def create_sidebar():
\"\"\"Create sidebar navigation.\"\"\"
with bg.column().classes("bg-grey-2 q-pa-md") as sidebar:
sidebar.style("min-height: 100vh; width: 250px")
bg.label("Dashboard").classes("text-h5 q-mb-lg text-center")
# Navigation items
nav_items = [
("Overview", "/"),
("Analytics", "/analytics"),
("Users", "/users"),
("Settings", "/settings")
]
for label, path in nav_items:
bg.link(label, path).classes("q-btn q-btn-flat full-width justify-start q-mb-sm")
def create_header(title):
\"\"\"Create page header.\"\"\"
with bg.row().classes("bg-primary text-white q-pa-md items-center justify-between"):
bg.label(title).classes("text-h4")
bg.label("Welcome, User").classes("text-body1")
def create_stat_card(title, value, icon, color):
\"\"\"Create a statistics card.\"\"\"
with bg.column().classes(f"bg-{color}-1 q-pa-lg rounded text-center") as card:
bg.label(icon).classes(f"text-{color} text-h3 q-mb-md")
bg.label(value).classes("text-h4 text-weight-bold q-mb-sm")
bg.label(title).classes("text-body2 text-grey-7")
# Overview Page
with bg.page("/", "OverviewPage", "Dashboard - Overview"):
with bg.row().classes("no-wrap") as main_layout:
create_sidebar()
with bg.column().classes("col"):
create_header("Overview")
with bg.column().classes("q-pa-lg"):
# Statistics row
with bg.row().classes("q-col-gutter-lg q-mb-lg"):
with bg.column().classes("col-12 col-md-3"):
create_stat_card("Total Users", "1,234", "👥", "blue")
with bg.column().classes("col-12 col-md-3"):
create_stat_card("Revenue", "$12,345", "💰", "green")
with bg.column().classes("col-12 col-md-3"):
create_stat_card("Orders", "567", "📦", "orange")
with bg.column().classes("col-12 col-md-3"):
create_stat_card("Growth", "+23%", "📈", "purple")
# Recent activity
bg.label("Recent Activity").classes("text-h5 q-mb-md")
with bg.column().classes("bg-white rounded q-pa-lg shadow-1"):
activities = [
"New user registered",
"Order #1234 completed",
"Payment received",
"Product updated"
]
for activity in activities:
bg.label(f"• {activity}").classes("q-mb-sm")
# Analytics Page
with bg.page("/analytics", "AnalyticsPage", "Dashboard - Analytics"):
with bg.row().classes("no-wrap"):
create_sidebar()
with bg.column().classes("col"):
create_header("Analytics")
with bg.column().classes("q-pa-lg"):
bg.label("Analytics Dashboard").classes("text-h4 q-mb-lg")
# Placeholder for charts
with bg.row().classes("q-col-gutter-lg"):
with bg.column().classes("col-12 col-md-6"):
with bg.column().classes("bg-white q-pa-lg rounded shadow-1"):
bg.label("Revenue Chart").classes("text-h6 q-mb-md")
bg.label("Chart placeholder - integrate with Chart.js").classes("text-center q-pa-xl bg-grey-1")
with bg.column().classes("col-12 col-md-6"):
with bg.column().classes("bg-white q-pa-lg rounded shadow-1"):
bg.label("User Growth").classes("text-h6 q-mb-md")
bg.label("Chart placeholder - integrate with Chart.js").classes("text-center q-pa-xl bg-grey-1")
# Users Page
with bg.page("/users", "UsersPage", "Dashboard - Users"):
with bg.row().classes("no-wrap"):
create_sidebar()
with bg.column().classes("col"):
create_header("Users")
with bg.column().classes("q-pa-lg"):
bg.label("User Management").classes("text-h4 q-mb-lg")
# User table header
with bg.row().classes("bg-grey-3 q-pa-md rounded-top"):
bg.label("Name").classes("col-3 text-weight-bold")
bg.label("Email").classes("col-4 text-weight-bold")
bg.label("Role").classes("col-2 text-weight-bold")
bg.label("Actions").classes("col-3 text-weight-bold")
# User rows
users = [
("John Doe", "john@example.com", "Admin"),
("Jane Smith", "jane@example.com", "User"),
("Bob Johnson", "bob@example.com", "Editor")
]
for name, email, role in users:
with bg.row().classes("bg-white q-pa-md border-bottom"):
bg.label(name).classes("col-3")
bg.label(email).classes("col-4")
bg.label(role).classes("col-2")
with bg.row().classes("col-3 q-gutter-sm"):
bg.button("Edit").classes("q-btn-sm q-btn-primary")
bg.button("Delete").classes("q-btn-sm q-btn-negative")
bg.build("dashboard-app")
E-commerce Store
----------------
A complete e-commerce store example:
.. code-block:: python
import badgui as bg
def create_navbar():
\"\"\"Create store navigation bar.\"\"\"
with bg.row().classes("bg-white shadow-1 q-pa-md items-center justify-between"):
bg.label("🛍️ MyStore").classes("text-h5 text-primary text-weight-bold")
with bg.row().classes("q-gutter-md items-center"):
bg.input(placeholder="Search products...").classes("").props("outlined dense")
bg.link("Products", "/products").classes("text-grey-8 no-underline")
bg.link("Cart (0)", "/cart").classes("text-grey-8 no-underline")
bg.button("Login").classes("q-btn-primary q-btn-sm")
def create_product_card(name, price, image_placeholder):
\"\"\"Create a product card.\"\"\"
with bg.column().classes("bg-white rounded shadow-2 q-pa-md"):
# Product image placeholder
with bg.column().classes("bg-grey-3 rounded q-mb-md text-center q-pa-xl"):
bg.label("📷").classes("text-h3")
bg.label(image_placeholder).classes("text-caption")
bg.label(name).classes("text-h6 q-mb-sm")
bg.label(f"${price}").classes("text-h5 text-green-6 text-weight-bold q-mb-md")
with bg.row().classes("q-gutter-sm"):
bg.button("Add to Cart").classes("q-btn-primary col")
bg.button("♡").classes("q-btn-outline col-auto")
# Home Page
with bg.page("/", "HomePage", "MyStore - Home"):
create_navbar()
# Hero section
with bg.column().classes("bg-gradient-to-r from-purple-400 to-pink-400 text-white text-center q-pa-xl"):
bg.label("Welcome to MyStore").classes("text-h2 q-mb-md")
bg.label("Discover amazing products at great prices").classes("text-h6 q-mb-lg")
bg.link("Shop Now", "/products").classes("q-btn q-btn-lg q-btn-white text-primary")
# Featured products
with bg.column().classes("q-pa-xl"):
bg.label("Featured Products").classes("text-h4 text-center q-mb-lg")
with bg.row().classes("q-col-gutter-lg"):
products = [
("Wireless Headphones", "99.99", "Headphones Image"),
("Smart Watch", "199.99", "Watch Image"),
("Laptop Stand", "49.99", "Stand Image"),
("USB-C Cable", "19.99", "Cable Image")
]
for name, price, image in products:
with bg.column().classes("col-12 col-sm-6 col-md-3"):
create_product_card(name, price, image)
# Products Page
with bg.page("/products", "ProductsPage", "Products"):
create_navbar()
with bg.row().classes("q-pa-lg"):
# Sidebar filters
with bg.column().classes("col-12 col-md-3 q-pr-lg"):
bg.label("Filters").classes("text-h6 q-mb-md")
with bg.column().classes("bg-white rounded q-pa-md shadow-1"):
bg.label("Category").classes("text-weight-bold q-mb-sm")
categories = ["Electronics", "Clothing", "Home", "Sports"]
for category in categories:
with bg.row().classes("items-center q-mb-sm"):
bg.label(f"☐ {category}").classes("text-body2")
bg.label("Price Range").classes("text-weight-bold q-mb-sm q-mt-md")
bg.input(placeholder="Min").classes("q-mb-sm").props("outlined dense type=number")
bg.input(placeholder="Max").classes("q-mb-md").props("outlined dense type=number")
bg.button("Apply Filters").classes("q-btn-primary full-width")
# Products grid
with bg.column().classes("col-12 col-md-9"):
bg.label("All Products").classes("text-h5 q-mb-lg")
with bg.row().classes("q-col-gutter-lg"):
# Generate more products
all_products = [
("Gaming Mouse", "79.99", "Mouse Image"),
("Mechanical Keyboard", "129.99", "Keyboard Image"),
("4K Monitor", "299.99", "Monitor Image"),
("Webcam", "89.99", "Camera Image"),
("Phone Case", "24.99", "Case Image"),
("Power Bank", "39.99", "Battery Image")
]
for name, price, image in all_products:
with bg.column().classes("col-12 col-sm-6 col-lg-4"):
create_product_card(name, price, image)
# Cart Page
with bg.page("/cart", "CartPage", "Shopping Cart"):
create_navbar()
with bg.column().classes("q-pa-xl max-width-md mx-auto"):
bg.label("Shopping Cart").classes("text-h4 q-mb-lg")
# Cart items
cart_items = [
("Wireless Headphones", "99.99", "1"),
("Smart Watch", "199.99", "1")
]
for name, price, qty in cart_items:
with bg.row().classes("bg-white rounded q-pa-md q-mb-md shadow-1 items-center"):
with bg.column().classes("col"):
bg.label(name).classes("text-h6")
bg.label(f"${price}").classes("text-green-6")
with bg.column().classes("col-auto"):
bg.input(value=qty).classes("text-center").props("outlined dense type=number style=width:60px")
with bg.column().classes("col-auto"):
bg.button("Remove").classes("q-btn-sm q-btn-negative")
# Cart total
with bg.row().classes("bg-grey-1 q-pa-md rounded justify-between items-center q-mt-lg"):
bg.label("Total: $299.98").classes("text-h5 text-weight-bold")
bg.button("Checkout").classes("q-btn-lg q-btn-primary")
bg.build("ecommerce-store")
Portfolio Website
-----------------
A personal portfolio website:
.. code-block:: python
import badgui as bg
def create_nav():
\"\"\"Create navigation menu.\"\"\"
with bg.row().classes("bg-white shadow-1 q-pa-md justify-between items-center sticky-top"):
bg.label("John Developer").classes("text-h6 text-primary text-weight-bold")
with bg.row().classes("q-gutter-lg"):
bg.link("Home", "/").classes("text-grey-8 no-underline hover-primary")
bg.link("About", "/about").classes("text-grey-8 no-underline hover-primary")
bg.link("Projects", "/projects").classes("text-grey-8 no-underline hover-primary")
bg.link("Contact", "/contact").classes("text-grey-8 no-underline hover-primary")
# Home Page
with bg.page("/", "HomePage", "John Developer - Portfolio"):
create_nav()
# Hero section
with bg.column().classes("text-center q-pa-xl bg-gradient-to-br from-blue-50 to-indigo-100"):
bg.label("Hi, I'm John").classes("text-h2 q-mb-md")
bg.label("Full Stack Developer").classes("text-h4 text-grey-7 q-mb-lg")
bg.label("I create beautiful, functional web applications").classes("text-h6 text-grey-6 q-mb-xl")
with bg.row().classes("justify-center q-gutter-md"):
bg.link("View My Work", "/projects").classes("q-btn q-btn-lg q-btn-primary")
bg.link("Get In Touch", "/contact").classes("q-btn q-btn-lg q-btn-outline")
# Skills section
with bg.column().classes("q-pa-xl"):
bg.label("Technologies I Work With").classes("text-h4 text-center q-mb-lg")
with bg.row().classes("justify-center q-col-gutter-lg"):
skills = [
("Python", "🐍"),
("JavaScript", "⚡"),
("Vue.js", "💚"),
("React", "⚛️"),
("Node.js", "🟢"),
("Database", "🗄️")
]
for skill, icon in skills:
with bg.column().classes("col-6 col-sm-4 col-md-2 text-center"):
with bg.column().classes("bg-white rounded shadow-2 q-pa-lg"):
bg.label(icon).classes("text-h2 q-mb-md")
bg.label(skill).classes("text-weight-bold")
# Projects Page
with bg.page("/projects", "ProjectsPage", "Projects"):
create_nav()
with bg.column().classes("q-pa-xl"):
bg.label("My Projects").classes("text-h3 text-center q-mb-xl")
projects = [
("E-commerce Platform", "Full-stack online store with payment integration", "🛒"),
("Task Management App", "Collaborative project management tool", "✅"),
("Weather Dashboard", "Real-time weather data visualization", "🌤️"),
("Blog Platform", "Content management system with admin panel", "📝")
]
with bg.row().classes("q-col-gutter-xl"):
for title, desc, icon in projects:
with bg.column().classes("col-12 col-md-6"):
with bg.column().classes("bg-white rounded shadow-4 q-pa-lg"):
bg.label(icon).classes("text-h1 text-center q-mb-md")
bg.label(title).classes("text-h5 text-center q-mb-md")
bg.label(desc).classes("text-body1 text-grey-7 text-center q-mb-lg")
with bg.row().classes("justify-center q-gutter-sm"):
bg.button("Live Demo").classes("q-btn-primary")
bg.button("Source Code").classes("q-btn-outline")
bg.build("portfolio-website")
Blog Platform
-------------
A complete blog with admin features:
.. code-block:: python
import badgui as bg
def create_header():
\"\"\"Create blog header.\"\"\"
with bg.row().classes("bg-white shadow-1 q-pa-md justify-between items-center"):
bg.link("Tech Blog", "/").classes("text-h5 text-primary text-weight-bold no-underline")
with bg.row().classes("q-gutter-md"):
bg.link("Home", "/").classes("text-grey-8 no-underline")
bg.link("Categories", "/categories").classes("text-grey-8 no-underline")
bg.link("About", "/about").classes("text-grey-8 no-underline")
bg.input(placeholder="Search...").classes("").props("outlined dense")
def create_post_card(title, excerpt, date, category):
\"\"\"Create blog post card.\"\"\"
with bg.column().classes("bg-white rounded shadow-2 q-pa-lg"):
bg.label(category).classes("text-caption text-primary text-weight-bold q-mb-sm")
bg.label(title).classes("text-h6 q-mb-md")
bg.label(excerpt).classes("text-body2 text-grey-7 q-mb-md")
with bg.row().classes("justify-between items-center"):
bg.label(date).classes("text-caption text-grey-6")
bg.button("Read More").classes("q-btn-sm q-btn-primary")
# Home Page
with bg.page("/", "HomePage", "Tech Blog"):
create_header()
# Featured post
with bg.column().classes("bg-gradient-to-r from-purple-600 to-blue-600 text-white q-pa-xl text-center"):
bg.label("Featured Article").classes("text-caption q-mb-md opacity-80")
bg.label("The Future of Web Development").classes("text-h3 q-mb-md")
bg.label("Exploring emerging technologies and trends shaping the web").classes("text-h6 q-mb-lg opacity-90")
bg.button("Read Article").classes("q-btn q-btn-lg q-btn-white text-primary")
# Recent posts
with bg.column().classes("q-pa-xl"):
bg.label("Recent Posts").classes("text-h4 q-mb-lg")
with bg.row().classes("q-col-gutter-lg"):
posts = [
("Getting Started with Vue.js 3", "Learn the basics of Vue.js 3 and its composition API...", "March 15, 2025", "Vue.js"),
("Python Best Practices", "Write cleaner, more maintainable Python code...", "March 12, 2025", "Python"),
("CSS Grid vs Flexbox", "When to use Grid and when to use Flexbox...", "March 10, 2025", "CSS"),
("API Design Principles", "Building RESTful APIs that developers love...", "March 8, 2025", "Backend")
]
for title, excerpt, date, category in posts:
with bg.column().classes("col-12 col-md-6 col-lg-3"):
create_post_card(title, excerpt, date, category)
# Single Post Page
with bg.page("/post/:slug", "PostPage", "Blog Post"):
create_header()
with bg.column().classes("q-pa-xl max-width-md mx-auto"):
# Post header
bg.label("Vue.js").classes("text-caption text-primary text-weight-bold q-mb-sm")
bg.label("Getting Started with Vue.js 3").classes("text-h3 q-mb-md")
with bg.row().classes("text-grey-6 q-mb-xl"):
bg.label("Published on March 15, 2025")
bg.label(" • ")
bg.label("5 min read")
# Post content
bg.label("Introduction").classes("text-h5 q-mb-md q-mt-lg")
bg.label("Vue.js 3 brings many exciting features...").classes("text-body1 q-mb-lg")
bg.label("Key Features").classes("text-h5 q-mb-md q-mt-lg")
bg.label("The Composition API is one of the biggest additions...").classes("text-body1 q-mb-lg")
# Related posts
bg.label("Related Posts").classes("text-h5 q-mb-md q-mt-xl")
with bg.row().classes("q-col-gutter-md"):
for i in range(2):
with bg.column().classes("col-12 col-md-6"):
create_post_card("Related Post", "Short excerpt...", "March 10, 2025", "Vue.js")
bg.build("blog-platform")
Running the Examples
--------------------
To generate and run any of these examples:
1. **Save the code** to a Python file (e.g., ``dashboard.py``)
2. **Generate the project**::
python dashboard.py
3. **Run the project**::
cd dashboard-app # or whatever you named it
npm install
npm run dev
4. **Open in browser**: Navigate to ``http://localhost:9000``
Customization Tips
------------------
All examples can be customized by:
1. **Modifying styles**: Update CSS classes and inline styles
2. **Adding components**: Insert additional BadGUI components
3. **Changing layouts**: Reorganize with different row/column structures
4. **Updating content**: Replace placeholder text with real content
5. **Adding pages**: Create additional routes for more functionality
The generated Vue.js projects are fully editable, so you can continue development with standard Vue.js tools and practices.
+88
View File
@@ -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`
+71
View File
@@ -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.
+147
View File
@@ -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
+389
View File
@@ -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.
+351
View File
@@ -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")