general-ui-ux
NewUI/UX design principles: color theory, typography, accessibility, layout, WCAG compliance
Overview
Table of Contents
- Overview
- Features
- Installation
- Quick Start Guide
- Helper Scripts
- Skills Guide
- Integration with Textual Ecosystem
- Best Practices
- Troubleshooting
- FAQ
- Resources
Overview
The Textual Plugin is a comprehensive collection of 12+ skills, helper scripts, templates, and examples designed to help AI agents and developers build professional Text-based User Interface (TUI) applications using the Textual framework.
This plugin provides everything you need to:
- •Learn Textual from scratch or deepen your expertise
- •Generate complete applications programmatically
- •Access pre-built templates for common patterns
- •Find relevant examples for your specific use case
- •Test and validate your TUI applications
- •Apply UI/UX best practices
What is Textual?
Textual is a Python framework for building rich text user interfaces (TUIs) - terminal applications with modern UI features like:
- •Interactive widgets (buttons, inputs, tables, lists)
- •CSS styling (colors, layouts, animations)
- •Reactive programming (auto-updating UI)
- •Multi-screen navigation (modals, dialogs, wizards)
- •Event-driven architecture (keyboard, mouse, focus events)
Features
✅ Complete Skills Catalog
Core Foundation (2 skills)
- •Getting Started with Textual - Basic app structure and async patterns
- •App Lifecycle & Structure - Initialization, configuration, CLI args
Widget Development (2 skills)
- •Built-in Widgets - All standard widgets with examples
- •Custom Widgets - Create reusable components
Layout & Design (2 skills)
- •Layout Systems - Vertical, Horizontal, Grid, Dock layouts
- •CSS Styling (TCSS) - Selectors, colors, themes, responsive design
Interactivity (1 skill)
- •Events and Messages - Event handlers, @on decorator, custom messages
Reactivity (1 skill)
- •Reactive Attributes - Auto-updating state, watch/compute methods
Navigation (1 skill)
- •Screens and Navigation - Multi-screen apps, modals, async handling
Testing (1 skill)
- •Snapshot Testing - Visual regression testing with pytest
UI/UX Design (2 skills)
- •CLI UX Principles - Human-first design, progressive discovery
- •General UI/UX - Color theory, typography, accessibility
✅ Helper Scripts
- •textual_generator.py - Generate complete apps programmatically
- •template_manager.py - Access 20+ pre-built code templates
- •skill_finder.py - Find relevant skills for your task
- •quick_reference.py - Fast syntax lookup and patterns
- •marimo_generator.py - Generate Marimo reactive notebooks (bonus!)
✅ Ready-to-Run Examples
- •Complete example applications demonstrating best practices
- •Each skill file is runnable and educational
- •Quick start demo showcasing key features
✅ Learning Resources
- •4 structured learning paths (Beginner to Expert)
- •Task-based skill recommendations
- •Quick reference guides
- •Best practices documentation
Installation
Prerequisites
# Ensure you have Python 3.8+ installed
python --version
# Install Textual and dependencies
pip install textual textual-devInstall Plugin Dependencies
# Install test dependencies (optional but recommended)
pip install pytest pytest-asyncio pytest-textual-snapshotVerify Installation
# Run the quick start example
cd examples
python quick_start.pyYou should see a fully functional TUI application launching in your terminal.
For AI Agents
If using in Claude Code or similar AI environment:
from helpers.skill_finder import SkillFinder
# Verify plugin is loaded
finder = SkillFinder()
skills = finder.find_skills("getting started")
print(f"Found {len(skills)} skills")Quick Start Guide
Method 1: Run Examples (Fastest)
# Launch the comprehensive demo
cd examples
python quick_start.pyThis runs a complete application demonstrating:
- •Widgets (buttons, inputs, tables)
- •Layout (grid, horizontal, vertical)
- •Reactivity (auto-updating values)
- •Navigation (modal dialogs)
- •CSS styling
Method 2: Learn by Doing
# Start with the basics
cd skills/textual/core
python 01_getting_started.py
# Explore widgets
cd ../widgets
python 01_builtin_widgets.pyEach skill file is runnable and contains:
- Working examples
- Explanatory comments
- Progressive complexity
- Best practices
Method 3: Generate Code
from helpers.textual_generator import TextualGenerator, WidgetSpec
# Create a specification
widgets = [
WidgetSpec("Button", id="submit", properties={"label": "Submit"}),
WidgetSpec("Input", id="name", properties={"placeholder": "Name"}),
]
# Generate complete app
generator = TextualGenerator()
app_code = generator.generate_app(
"MyFormApp",
widgets=widgets,
css="Button { margin: 1; }",
bindings=[("q", "quit", "Quit")]
)
print(app_code)Method 4: Use Templates
from helpers.template_manager import TemplateManager, TemplateType
manager = TemplateManager()
# Get an app template
app_code = manager.get_template(
TemplateType.APP,
"basic",
app_name="MyApp"
)
# Get a reactive widget template
widget_code = manager.get_template(
TemplateType.WIDGET,
"reactive",
widget_name="Counter",
reactive_attr="count",
default_value=0
)Helper Scripts
1. textual_generator.py
Purpose: Generate complete Textual applications programmatically
Features:
- •Generate full apps from specifications
- •Create custom widgets with reactivity
- •Generate screens and modals
- •Create test files
- •Auto-import collection
Usage Examples:
from helpers.textual_generator import TextualGenerator, WidgetSpec
# Generate a complete app
generator = TextualGenerator()
widgets = [
WidgetSpec("Header"),
WidgetSpec("Static", id="title", properties={"content": "My App"}),
WidgetSpec("Button", id="click", properties={"label": "Click Me"}),
WidgetSpec("Footer"),
]
code = generator.generate_app(
"HelloWorldApp",
widgets=widgets,
css="""
Screen {
align: center middle;
}
Button {
margin: 1;
}
""",
bindings=[
("q", "quit", "Quit"),
("r", "reload", "Reload"),
]
)Output:
"""
Generated Textual Application: HelloWorldApp
"""
from textual.app import App, ComposeResult
from textual.widgets import Header, Footer, Static, Button
class HelloWorldApp(App):
"""A Textual application."""
CSS = '''
Screen {
align: center middle;
}
Button {
margin: 1;
}
'''
BINDINGS = [
("q", "quit", "Quit"),
("r", "reload", "Reload"),
]
def compose(self) -> ComposeResult:
"""Create child widgets."""
yield Header()
yield Static("My App", id="title")
yield Button("Click Me", id="click")
yield Footer()
def on_button_pressed(self, event: Button.Pressed) -> None:
"""Handle button press."""
if __name__ == "__main__":
app = HelloWorldApp()
app.run()2. template_manager.py
Purpose: Access pre-built templates for common patterns
Template Types:
| Type | Variants | Use Case |
|---|---|---|
| APP | basic, with_css, multi_screen, with_config | Starting points for applications |
| WIDGET | basic, reactive, with_message, container | Custom widget development |
| SCREEN | basic, with_return | Multi-screen navigation |
| MODAL | confirm, input | Dialog boxes |
| TEST | snapshot, unit | Testing patterns |
| CSS | basic, card, grid_layout | Styling examples |
| EVENT_HANDLER | button, key, custom | Event patterns |
| REACTIVE | basic, computed, validated | State management |
Usage Examples:
from helpers.template_manager import TemplateManager, TemplateType
manager = TemplateManager()
# List all templates
templates = manager.list_templates()
print(templates)
# Get a specific template
app_template = manager.get_template(
TemplateType.APP,
"multi_screen",
app_name="MyMultiScreenApp"
)
# Get a modal template
modal_template = manager.get_template(
TemplateType.MODAL,
"confirm",
title="Confirm Action",
message="Are you sure?"
)Customizing Templates:
# Template with variables
widget_code = manager.get_template(
TemplateType.WIDGET,
"reactive",
widget_name="CustomWidget",
reactive_attr="value",
default_value="default",
widget_type="Static" # The underlying widget
)3. skill_finder.py
Purpose: Find relevant skills based on your task
Features:
- •Search skills by keyword
- •Get recommendations for specific tasks
- •List learning paths
- •Find examples by functionality
Usage Examples:
from helpers.skill_finder import SkillFinder
finder = SkillFinder()
# Search by keyword
skills = finder.find_skills("button events")
for skill in skills:
print(f"{skill.name}: {skill.description}")
# Get task-based recommendations
task = "Create a data entry form with validation"
recommendations = finder.find_by_task(task)
print(f"Recommended skills: {[r.name for r in recommendations]}")
# Get learning path
path = finder.get_learning_path("beginner")
print(f"Learning path: {path}")
# Find by category
core_skills = finder.find_by_category("core")
widget_skills = finder.find_by_category("widgets")Task Examples:
| Task | Recommended Skills |
|---|---|
| "Create a counter" | Reactive Attributes, Built-in Widgets |
| "Build a modal dialog" | Screens and Navigation |
| "Style my app" | CSS Styling, Layout Systems |
| "Test my application" | Snapshot Testing |
| "Create custom widget" | Custom Widgets, Reactive Attributes |
4. quick_reference.py
Purpose: Fast lookup for syntax and patterns
Content:
- •Widget signatures
- •Event handler patterns
- •CSS snippets
- •Common patterns
- •Best practices
Usage:
from helpers.quick_reference import QUICK_REFERENCE, get_pattern
# Display full reference
print(QUICK_REFERENCE)
# Get specific pattern
counter_pattern = get_pattern("counter")
form_pattern = get_pattern("form")
modal_pattern = get_pattern("modal")
reactive_pattern = get_pattern("reactive")Available Patterns:
- •
counter- Reactive counter widget - •
form- Input form with validation - •
modal- Confirmation dialog - •
reactive- Reactive attributes - •
grid- Grid layout - •
event_handler- Event patterns - •
custom_widget- Custom widget structure - •
data_table- Table with data - •
tabs- Tabbed interface - •
navigation- Screen navigation
5. marimo_generator.py
Purpose: Generate Marimo reactive notebooks (bonus feature)
Features:
- •Create notebooks programmatically
- •Add cells with proper reactivity
- •Generate interactive dashboards
- •Support for widgets and layouts
Usage:
from helpers.marimo.marimo_generator import MarimoNotebookGenerator
gen = MarimoNotebookGenerator()
# Create basic notebook
gen.add_imports_cell(["import marimo as mo", "import pandas as pd"])
gen.add_markdown_cell("# My Analysis")
gen.add_widget_cell("slider", "threshold", start=0, stop=100)
gen.add_code_cell("filtered_data = df[df['value'] > threshold]")
gen.save("analysis.py")Skills Guide
Navigation Structure
skills/
├── textual/
│ ├── core/
│ │ ├── 01_getting_started.py # ⭐ Start here
│ │ └── 02_app_lifecycle.py
│ ├── widgets/
│ │ ├── 01_builtin_widgets.py # Essential widgets
│ │ └── 02_custom_widgets.py
│ ├── layout/
│ │ ├── 01_layouts.py # Layout systems
│ │ └── 02_css_styling.py # CSS styling
│ ├── interactivity/
│ │ └── 01_events_messages.py # Event handling
│ ├── reactivity/
│ │ └── 01_reactive_attributes.py # State management
│ ├── navigation/
│ │ └── 01_screens.py # Multi-screen apps
│ └── testing/
│ └── 01_snapshot_testing.py # Testing patterns
├── marimo/
│ ├── 01_getting_started.py # Reactive notebooks
│ ├── 02_widgets_ui.py
│ ├── 03_layouts.py
│ └── 04_working_with_marimo.py
└── design/
├── 01_cli_ux_principles.py # CLI UX best practices
└── 02_general_ui_ux.py # General UX principlesLearning Paths
1. ⭐ skills/textual/core/01_getting_started.py
2. ⭐ skills/textual/widgets/01_builtin_widgets.py
3. ⭐ skills/textual/layout/01_layouts.py
4. ⭐ skills/textual/interactivity/01_events_messages.py
5. ⭐ skills/textual/layout/02_css_styling.pyGoal: Create simple, functional TUI applications
1. skills/textual/widgets/02_custom_widgets.py
2. skills/textual/reactivity/01_reactive_attributes.py
3. skills/textual/navigation/01_screens.py
4. skills/textual/testing/01_snapshot_testing.pyGoal: Build multi-screen, reactive applications
1. skills/textual/core/02_app_lifecycle.py
2. Advanced testing strategies
3. Performance optimization
4. Complex state management
5. AccessibilityGoal: Production-ready applications
1. ⭐ skills/design/01_cli_ux_principles.py
2. ⭐ skills/design/02_general_ui_ux.py
3. Apply to Textual apps
4. Apply to Marimo notebooksGoal: Master UI/UX design principles
Skill Categories
File: skills/textual/core/01_getting_started.py
What you'll learn:
- •Basic app structure
- •Compose method
- •Widget basics
- •Running apps
- •Hot reload development
Key Example:
from textual.app import App, ComposeResult
from textual.widgets import Static
class BasicApp(App):
def compose(self) -> ComposeResult:
yield Static("Hello, Textual!")
if __name__ == "__main__":
app = BasicApp()
app.run()File: skills/textual/widgets/01_builtin_widgets.py
What you'll learn:
- •Button (all variants)
- •Input (text, password, validation)
- •DataTable, Tree, ListView
- •Checkbox, RadioButton, Switch
- •ProgressBar, Tabs
- •Markdown, RichLog
Key Examples:
# Button
Button("Click Me", variant="success")
# Input
Input(placeholder="Enter name", id="name")
# DataTable
table = DataTable()
table.add_columns("Name", "Age", "City")
table.add_rows([["Alice", 30, "NYC"], ["Bob", 25, "LA"]])File: skills/textual/layout/01_layouts.py
Layout types:
- •Vertical (default) - Stacks widgets top to bottom
- •Horizontal - Arranges widgets left to right
- •Grid - Places widgets in a grid
- •Dock - Sticks widgets to edges
- •Scrollable - Makes content scrollable
Key Example:
from textual.containers import Vertical, Horizontal, Container
# Vertical layout (default)
with Vertical():
yield Button("Top")
yield Button("Bottom")
# Horizontal layout
with Horizontal():
yield Button("Left")
yield Button("Right")
# Grid layout
with Container():
# CSS will define grid
passFile: skills/textual/layout/02_css_styling.py
CSS features:
- •Selectors (type, ID, class)
- •Colors and palettes
- •Borders and spacing
- •Text styling
- •Responsive design
- •External stylesheets
Key Example:
CSS = '''
Screen {
background: $primary;
}
Button {
margin: 1;
padding: 0 2;
}
#special-button {
background: $success;
}
'''File: skills/textual/interactivity/01_events_messages.py
Event patterns:
- •Button clicks
- •Keyboard events
- •Mouse events
- •Focus events
- •Custom messages
Key Example:
from textual.widgets import Button
def on_button_pressed(self, event: Button.Pressed) -> None:
"""Handle button clicks."""
if event.button.id == "submit":
self.process_form()
# Or using @on decorator
from textual.on import on
@on(Button.Pressed, "#submit")
def handle_submit(self) -> None:
self.process_form()File: skills/textual/reactivity/01_reactive_attributes.py
Reactivity features:
- •Auto-updating state
- •Watch methods
- •Compute methods
- •Validation
- •Init parameters
Key Example:
from textual.reactive import reactive
class CounterApp(App):
count = reactive(0)
def watch_count(self, new_count: int) -> None:
"""Called when count changes."""
self.query_one("#display", Static).update(str(new_count))
def on_button_pressed(self) -> None:
self.count += 1File: skills/textual/navigation/01_screens.py
Navigation patterns:
- •Define screens
- •Push/pop/switch
- •Modal screens
- •Return values
- •Async handling
Key Example:
from textual.screen import Screen
class SettingsScreen(Screen):
"""Settings screen."""
def compose(self) -> ComposeResult:
yield Button("Back", id="back")
class MainApp(App):
async def on_button_pressed(self) -> None:
"""Show settings screen."""
await self.push_screen_wait(SettingsScreen())File: skills/textual/testing/01_snapshot_testing.py
Testing patterns:
- •Snapshot testing
- •User interaction simulation
- •Keyboard/mouse testing
- •Form testing
Key Example:
from textual.testing import press
def test_counter():
"""Test counter app."""
app = CounterApp()
async with app.run_test() as pilot:
# Click increment button
await pilot.click("#inc")
# Check result
assert app.query_one("#display").renderable == "1"Common Use Cases
Skills Needed:
layout/01_layouts.py- Grid layout for dashboardwidgets/01_builtin_widgets.py- DataTable, ProgressBarreactivity/01_reactive_attributes.py- Auto-updateslayout/02_css_styling.py- Professional styling
Approach:
# Use grid layout with CSS
CSS = '''
.grid-container {
grid-size: 3 2;
grid-gutter: 1;
}
'''
# Add widgets to grid
with Container(classes="grid-container"):
yield DataTable(id="table")
yield ProgressBar(id="progress")
yield Static(id="stats")Skills Needed:
widgets/01_builtin_widgets.py- Input, Button, validationinteractivity/01_events_messages.py- Form submissionreactivity/01_reactive_attributes.py- Validation feedbacknavigation/01_screens.py- Confirmation modals
Approach:
# Create form widgets
yield Input(placeholder="Name", id="name")
yield Input(placeholder="Email", id="email")
yield Button("Submit", id="submit")
# Handle submission
def on_button_pressed(self, event: Button.Pressed) -> None:
if event.button.id == "submit":
self.submit_form()
def submit_form(self):
name = self.query_one("#name", Input).value
email = self.query_one("#email", Input).value
# Validate and processSkills Needed:
widgets/01_builtin_widgets.py- Tree, ListViewnavigation/01_screens.py- Multi-screen navigationinteractivity/01_events_messages.py- Keyboard navigationlayout/01_layouts.py- Dock layout for sidebar
Integration with Textual Ecosystem
Official Textual Resources
- •Documentation: https://textual.textualize.io
- •Tutorial: https://textual.textualize.io/tutorial/
- •Widget Gallery: https://textual.textualize.io/widget_gallery/
- •GitHub: https://github.com/Textualize/textual
- •Discord: https://discord.gg/Enf6Z3qhVr
Plugin vs Official Docs
| Topic | This Plugin | Official Docs |
|---|---|---|
| Learning Path | Structured skill progression | Topic-based |
| Examples | Runnable skills with explanations | 分散在docs中 |
| Code Generation | Built-in generators | Manual coding |
| Templates | 20+ pre-built templates | Code snippets |
| Testing | Complete testing patterns | Basic examples |
| Best Practices | Curated patterns | 分散在docs中 |
Compatibility
This plugin is compatible with:
- •Textual 0.40+ (latest recommended)
- •Python 3.8+
- •All platforms (Linux, macOS, Windows)
Extending the Plugin
To add your own skills:
- Create a skill file in the appropriate category
- Follow the existing skill format
- Include runnable examples
- Add docstrings and comments
- Update SKILLS_INDEX.md
Best Practices
1. App Structure
✅ DO:
from textual.app import App, ComposeResult
from textual.widgets import Static
class MyApp(App):
"""A well-structured app."""
CSS = '''
/* Keep CSS concise */
'''
def compose(self) -> ComposeResult:
"""Create child widgets."""
yield Static("Content")
def on_mount(self) -> None:
"""Initialize after mounting."""
self.log("App mounted")
def on_unmount(self) -> None:
"""Clean up before unmounting."""
self.log("App unmounting")❌ DON'T:
# Don't put logic in compose()
def compose(self) -> ComposeResult:
# This should only yield widgets!
data = fetch_data() # ❌
yield create_widget_from_data(data) # ❌2. Widget IDs and Classes
✅ DO:
# Use IDs for unique widgets
yield Button("Click", id="submit-button")
# Use classes for groups
yield Button("Cancel", classes="secondary-button")
yield Button("Save", classes="primary-button")❌ DON'T:
# Don't query by content
self.query("Button:disabled") # ❌ Fragile3. CSS Organization
✅ DO:
# Use external CSS files for large projects
class MyApp(App):
CSS_PATH = "styles.tcss"
# Or use a separate CSS constant
CSS = '''
/* Group related styles */
.header {
background: $primary;
}
.content {
padding: 1;
}
'''❌ DON'T:
# Don't inline styles in compose()
with Container(style="background: red;"): # ❌
pass4. Event Handling
✅ DO:
from textual.on import on
@on(Button.Pressed, "#submit")
def handle_submit(self, event: Button.Pressed) -> None:
"""Handle submit button."""
self.process_form()
# Or use named methods
def on_button_pressed(self, event: Button.Pressed) -> None:
"""Handle any button press."""
if event.button.id == "submit":
self.process_form()❌ DON'T:
# Don't use complex conditionals
def on_key(self, event) -> None:
if event.key == "a" and self.state == "editing": # ❌
pass5. Reactive Attributes
✅ DO:
from textual.reactive import reactive
class CounterApp(App):
count = reactive(0)
def watch_count(self, new_count: int) -> None:
"""Auto-update when count changes."""
self.query_one("#display", Static).update(str(new_count))❌ DON'T:
# Don't manually update without reactivity
def increment(self):
self.count += 1
self.update_display() # ❌ Manual update6. Testing
✅ DO:
from textual.testing import press, click
async def test_form_submission():
app = FormApp()
async with app.run_test() as pilot:
# Simulate user interaction
await pilot.click("#submit")
# Verify state
assert app.submitted❌ DON'T:
# Don't test without running the app
def test_form():
app = FormApp()
assert app.is_valid() # ❌ No event loop7. Error Handling
✅ DO:
from textual.widgets import Static
def on_button_pressed(self) -> None:
try:
self.process_data()
except ValueError as e:
self.notify(f"Error: {e}", severity="error")
self.query_one("#error", Static).update(str(e))❌ DON'T:
# Don't silently ignore errors
def on_button_pressed(self) -> None:
self.process_data() # ❌ No error handling8. Performance
✅ DO:
from textual.workers import worker
@worker
async def fetch_data(self):
"""Use workers for long operations."""
data = await self.api.get_data()
self.data = data
def on_mount(self):
self.run_worker(self.fetch_data)❌ DON'T:
# Don't block the UI
def on_mount(self):
# This will freeze the app!
data = self.blocking_api.get_data() # ❌
self.data = dataTroubleshooting
Issue: Import Errors
Symptom:
ModuleNotFoundError: No module named 'textual'Solution:
# Install Textual
pip install textual textual-dev
# Verify installation
python -c "import textual; print(textual.__version__)"Issue: Widget Not Updating
Symptom: UI doesn't reflect state changes
Solution:
- Check if you're using reactive attributes
# ✅ Use reactive attributes
count = reactive(0)
def watch_count(self, new_count):
self.query_one("#display").update(str(new_count))- Verify event handlers are firing
def on_button_pressed(self, event):
self.log(f"Button pressed: {event.button.id}") # DebugIssue: Layout Broken
Symptom: Widgets not positioned correctly
Solution:
- Check CSS grid settings
CSS = '''
Container {
grid-size: 2 2; /* 2 columns, 2 rows */
}
'''- Verify container hierarchy
# ✅ Correct nesting
with Container():
with Vertical():
yield Button("Top")
# ❌ Incorrect
yield Container(Vertical(Button("Top")))Issue: Events Not Firing
Symptom: Event handlers not called
Solution:
- Check widget IDs
# Ensure IDs match
yield Button("Click", id="my-button")
def on_button_pressed(self, event: Button.Pressed):
if event.button.id == "my-button": # ✅ Match
pass- Use @on decorator for clarity
from textual.on import on
@on(Button.Pressed, "#my-button")
def handle_click(self) -> None:
"""Explicit event handler."""
passIssue: Can't Run Examples
Symptom:
Permission denied: examples/quick_start.pySolution:
# Make executable (optional)
chmod +x examples/*.py
# Run with Python
python examples/quick_start.pyIssue: App Crashes on Exit
Symptom: App doesn't shut down gracefully
Solution:
- Add cleanup handlers
def on_unmount(self) -> None:
"""Clean up resources."""
self.log("App closing")
# Or use exit hooks
def on_exit(self) -> None:
"""Handle exit."""
passIssue: Slow Performance
Symptom: UI is sluggish or unresponsive
Solution:
- Use workers for long operations
from textual.workers import worker
@worker
async def long_task(self):
result = await self.do_work()
return result- Batch DOM updates
def update_multiple_widgets(self):
with self.batch_update():
self.query_one("#w1").update("New 1")
self.query_one("#w2").update("New 2")
self.query_one("#w3").update("New 3")Issue: CSS Not Loading
Symptom: Styles don't apply
Solution:
- Check CSS_PATH
class MyApp(App):
CSS_PATH = "styles.tcss" # File must exist- Verify CSS syntax
CSS = '''
Button { /* ✅ Correct */
margin: 1;
}
'''Issue: Type Errors
Symptom: Type checker reports errors
Solution:
- Add type hints
from textual.widgets import Button
from textual.app import ComposeResult
def compose(self) -> ComposeResult:
"""Return type hint."""
yield Button("Click")
def on_button_pressed(self, event: Button.Pressed) -> None:
"""Event type hint."""
passFAQ
Q: How is this plugin different from official Textual documentation?
A: This plugin provides:
- •Structured learning paths instead of topic-based browsing
- •Runnable examples embedded in each skill
- •Code generators for rapid prototyping
- •Pre-built templates for common patterns
- •Testing frameworks with ready-to-use examples
- •UI/UX best practices specific to TUIs
Q: Do I need to know Python async/await?
A: Basic understanding helps, but isn't required for simple apps. The plugin includes:
- •Sync examples for beginners
- •Async patterns in intermediate skills
- •Detailed explanations of async concepts
Q: Can I build web apps with this plugin?
A: No, this plugin is specifically for Textual TUI applications (terminal-based). For web apps, consider:
- •Textual Web - Run Textual in browsers
- •Traditional web frameworks (Flask, Django, FastAPI)
Q: Is this plugin suitable for production use?
A: Yes! Textual itself is production-ready and used by:
- •AWS CLI tools
- •Docker CLI
- •Poetry
- •And many more
This plugin includes production best practices for:
- •Error handling
- •Performance optimization
- •Testing strategies
- •Accessibility
Q: How do I contribute skills to this plugin?
A:
- Follow the existing skill format
- Create runnable examples
- Add comprehensive docstrings
- Include test cases (optional)
- Update SKILLS_INDEX.md
- Submit a pull request
Q: Can I use this with other terminal frameworks?
A: The skills are Textual-specific, but many concepts transfer:
- •Rich (text formatting)
- •Prompt Toolkit (CLI apps)
- •Urwid (TUI framework)
However, the code generators only produce Textual code.
Q: What's the learning curve?
A: Based on user feedback:
- •Beginner path: 2-4 hours (basic TUIs)
- •Intermediate path: 4-6 hours (multi-screen apps)
- •Advanced path: 6-10 hours (production apps)
Start with the examples to get immediate results!
Q: Does this work on Windows/macOS/Linux?
A: Yes! Textual works on all platforms:
- •Linux: Full support
- •macOS: Full support
- •Windows: Full support (requires Windows Terminal for best experience)
Q: How do I style my TUI?
A: Textual uses TCSS (Textual CSS):
CSS = '''
Button {
background: $primary;
color: $text;
margin: 1;
}
'''The plugin includes comprehensive CSS guides in skills/textual/layout/02_css_styling.py.
Q: Can I create animations?
A: Yes! Textual supports:
- •CSS transitions
- •Keyframe animations
- •Timer-based animations
See the CSS styling guide for examples.
Q: How do I handle multiple screens?
A: Use the Screen API:
from textual.screen import Screen
class SettingsScreen(Screen):
pass
class MainApp(App):
async def show_settings(self):
await self.push_screen_wait(SettingsScreen())Full examples in skills/textual/navigation/01_screens.py.
Q: What's the difference between Textual and curses?
A:
| Feature | Textual | Python Curses |
|---|---|---|
| API | Modern, Pythonic | Low-level |
| Styling | Rich CSS support | Limited |
| Widgets | Built-in components | Manual coding |
| Reactivity | Built-in reactive attributes | Manual updates |
| Testing | Snapshot testing | Manual testing |
| Debugging | DevTools, console | Print statements |
Q: Can I integrate with databases?
A: Yes! Standard Python libraries work:
import sqlite3
import asyncpg
import sqlalchemy
# Use workers for DB operations
@worker
async def fetch_data(self):
async with sqlite3.connect('data.db') as conn:
cursor = conn.cursor()
cursor.execute("SELECT * FROM users")
return cursor.fetchall()Q: How do I create custom widgets?
A:
from textual.widgets import Static
from textual.reactive import reactive
class CustomWidget(Static):
"""A custom widget."""
DEFAULT_CSS = '''
CustomWidget {
background: $primary;
color: $text;
}
'''
value = reactive(0)
def compose(self) -> ComposeResult:
yield Static("Custom content")
def watch_value(self, new_value):
"""Auto-update when value changes."""
self.update(str(new_value))Full guide in skills/textual/widgets/02_custom_widgets.py.
Resources
Official Textual
- •Documentation: https://textual.textualize.io
- •Tutorial: https://textual.textualize.io/tutorial/
- •Widget Gallery: https://textual.textualize.io/widget_gallery/
- •GitHub: https://github.com/Textualize/textual
- •Discord: https://discord.gg/Enf6Z3qhVr
Community
- •GitHub Discussions: https://github.com/Textualize/textual/discussions
- •Stack Overflow: Use "textual" tag
- •Reddit: r/Python (Textual posts)
Tools & Extensions
- •Textual Web: Run TUIs in browsers
- •Textual DevTools: Debug and inspect
- •Rich: Text formatting library (used by Textual)
- •Typing: Type annotations for Python
Example Projects
- •Textual Docs: https://github.com/Textualize/textual/tree/main/examples
- •Textual Apps: https://github.com/Textualize/textual-apps
Learning Resources
- •Real Python Textual Tutorial: https://realpython.com/python-textual-tutorial/
- •Textual Blog: https://www.textualize.io/blog/
- •YouTube: Search "Textual Python TUI"
Next Steps
- Run the examples
``bash cd examples python quick_start.py ``
- Choose your learning path
- Beginner: Start with skills/textual/core/01_getting_started.py - Intermediate: Try skills/textual/widgets/02_custom_widgets.py - Expert: Explore skills/textual/testing/01_snapshot_testing.py
- Use helper scripts
- Generate code: helpers/textual_generator.py - Get templates: helpers/template_manager.py - Find skills: helpers/skill_finder.py
- Join the community
- Discord: https://discord.gg/Enf6Z3qhVr - GitHub: https://github.com/Textualize/textual
- Build something amazing!
- Create your first TUI app - Share it with the community - Contribute back to Textual
Happy Building! 🎉
Create beautiful, interactive terminal applications with Textual and this comprehensive plugin!
Install & Usage
mkdir -p .claude/skillsmkdir -p .claude/skills && curl -o .claude/skills/general-ui-ux.md https://raw.githubusercontent.com/Jrakru/marketplace_UI/main/SKILL.md/general-ui-uxFrequently Asked Questions
What is general-ui-ux?
UI/UX design principles: color theory, typography, accessibility, layout, WCAG compliance
How to install general-ui-ux?
To install general-ui-ux, create the .claude/skills directory in your project, then run the curl command to download the skill file. Once installed, invoke it in Claude Code with /general-ui-ux.
What is general-ui-ux best for?
general-ui-ux is a community categorized under Documentation. It is designed for: design, ui, ux, accessibility, wcag, typography. Created by Jrakru.