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/ |
||||
venv/ |
||||
__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