desktop-design

Desktop Design Principles for PySide6 Applications

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "desktop-design" with this command: npx skills add caliphsdev/water-balance-application/caliphsdev-water-balance-application-desktop-design

Desktop Design Principles for PySide6 Applications

This skill guides creation of distinctive, professional desktop interfaces using PySide6/Qt. Apply these design thinking principles when styling dashboards, creating custom widgets, or refining UI aesthetics.

Design Thinking Process

Before coding UI, understand the context and commit to a clear aesthetic direction:

  1. Purpose & Audience
  • Who uses this? Mine engineers, operations managers, data analysts

  • What problem does it solve? Water balance monitoring, KPI tracking, flow visualization

  • Context of use: Office desktop, control room displays, presentations

  1. Tone & Aesthetic Direction

Choose a clear direction and execute with precision:

Aesthetic Description Best For

Professional/Corporate Clean, neutral, data-focused Dashboards, reports

Industrial/Utilitarian Rugged, high-contrast, control-panel Monitoring systems

Minimalist/Modern Generous whitespace, subtle accents Analytics views

Dark Mode/Technical Low-light optimized, vivid accents 24/7 operations

Data-Dense/Editorial Information-rich, typography-driven Complex data tables

  1. Differentiation

Ask: What makes this interface memorable and effective?

  • Clear visual hierarchy

  • Distinctive but readable typography

  • Purposeful color usage (not decoration)

  • Smooth, meaningful animations

Typography for Qt Applications

Font Selection Principles

AVOID: Generic, overused fonts

❌ Arial, Helvetica, Times New Roman, Comic Sans

❌ System default fonts without customization

USE: Distinctive, professional fonts

✅ Segoe UI Variable (Windows 11 modern)

✅ SF Pro (macOS native)

✅ IBM Plex Sans/Mono (technical, open source)

✅ JetBrains Mono (code/data display)

✅ Roboto Flex (variable weight, Google)

✅ Source Sans Pro (Adobe, professional)

Typography Hierarchy

from PySide6.QtGui import QFont

Define clear hierarchy with purpose

FONTS = { # Page titles - bold, commanding 'title': QFont('Segoe UI Variable', 24, QFont.Weight.DemiBold),

# Section headers - clear separation
'header': QFont('Segoe UI Variable', 16, QFont.Weight.Medium),

# Body text - optimized for reading
'body': QFont('Segoe UI', 11, QFont.Weight.Normal),

# Data/numbers - monospace for alignment
'data': QFont('JetBrains Mono', 11, QFont.Weight.Normal),

# Captions/labels - subtle, supporting
'caption': QFont('Segoe UI', 9, QFont.Weight.Normal),

# KPI values - large, impactful
'kpi_value': QFont('Segoe UI Variable', 32, QFont.Weight.Bold),

}

QSS Typography Styling

/* Typography hierarchy in QSS / QLabel#pageTitle { font-size: 24px; font-weight: 600; color: #FFFFFF; letter-spacing: -0.5px; / Tighten for large text */ }

QLabel#sectionHeader { font-size: 16px; font-weight: 500; color: #E6EDF3; padding-bottom: 8px; border-bottom: 1px solid #30363D; }

QLabel#bodyText { font-size: 11px; font-weight: 400; color: #8B949E; line-height: 1.5; }

QLabel#kpiValue { font-size: 32px; font-weight: 700; color: #58A6FF; }

Color & Theme Design

Color Palette Principles

  • Dominant + Accent: One primary color, sharp accents for actions

  • Semantic Colors: Consistent meaning (green=success, red=error, blue=info)

  • Contrast: WCAG AA minimum (4.5:1 for text)

  • Hierarchy: Lighter/darker shades create depth

Professional Dark Theme Palette

Dark theme - professional, low eye strain

COLORS_DARK = { # Backgrounds (layered depth) 'bg_primary': '#0D1117', # Deepest - main canvas 'bg_secondary': '#161B22', # Cards, panels 'bg_tertiary': '#21262D', # Hover states, elevated 'bg_overlay': '#30363D', # Modals, tooltips

# Text hierarchy
'text_primary': '#E6EDF3',    # Main content
'text_secondary': '#8B949E',  # Supporting text
'text_muted': '#484F58',      # Disabled, hints

# Semantic colors
'accent_blue': '#58A6FF',     # Primary actions, links
'accent_green': '#238636',    # Success, positive values
'accent_red': '#F85149',      # Errors, negative values
'accent_yellow': '#D29922',   # Warnings, caution
'accent_purple': '#A371F7',   # Special, highlighted

# Borders & dividers
'border_default': '#30363D',
'border_muted': '#21262D',

# Status indicators
'status_online': '#238636',
'status_offline': '#6E7681',
'status_warning': '#D29922',
'status_error': '#F85149',

}

Professional Light Theme Palette

Light theme - clean, high readability

COLORS_LIGHT = { # Backgrounds 'bg_primary': '#FFFFFF', 'bg_secondary': '#F6F8FA', 'bg_tertiary': '#EAEEF2', 'bg_overlay': '#FFFFFF',

# Text hierarchy
'text_primary': '#1F2328',
'text_secondary': '#656D76',
'text_muted': '#8C959F',

# Semantic colors (adjusted for light bg)
'accent_blue': '#0969DA',
'accent_green': '#1A7F37',
'accent_red': '#CF222E',
'accent_yellow': '#9A6700',
'accent_purple': '#8250DF',

# Borders
'border_default': '#D0D7DE',
'border_muted': '#EAEEF2',

}

QSS Theme Application

/* CSS Variables pattern in QSS */ QWidget { background-color: #0D1117; color: #E6EDF3; }

/* Card/panel styling with depth */ QFrame#card { background-color: #161B22; border: 1px solid #30363D; border-radius: 8px; padding: 16px; }

/* Accent buttons */ QPushButton#primaryAction { background-color: #238636; color: #FFFFFF; border: none; border-radius: 6px; padding: 8px 16px; font-weight: 600; }

QPushButton#primaryAction:hover { background-color: #2EA043; }

QPushButton#primaryAction:pressed { background-color: #238636; border: 2px solid #58A6FF; }

/* Semantic status colors */ QLabel#statusSuccess { color: #238636; } QLabel#statusError { color: #F85149; } QLabel#statusWarning { color: #D29922; } QLabel#statusInfo { color: #58A6FF; }

Spatial Composition & Layout

Layout Principles

  • Visual Hierarchy: Important elements larger, higher, or more prominent

  • Grouping: Related items close together (Gestalt proximity)

  • Whitespace: Generous padding prevents visual clutter

  • Alignment: Consistent grid system creates order

  • Rhythm: Repeating patterns create visual harmony

Spacing System (8px Grid)

Consistent spacing based on 8px grid

SPACING = { 'xs': 4, # Tight: icon to text 'sm': 8, # Compact: related items 'md': 16, # Standard: between groups 'lg': 24, # Generous: section separation 'xl': 32, # Spacious: major sections 'xxl': 48, # Hero: page margins }

Apply in layouts

layout = QVBoxLayout() layout.setContentsMargins(SPACING['xl'], SPACING['lg'], SPACING['xl'], SPACING['lg']) layout.setSpacing(SPACING['md'])

Dashboard Layout Patterns

KPI Cards Row (3-4 cards, equal width)

kpi_layout = QHBoxLayout() kpi_layout.setSpacing(16) for kpi_data in kpis: card = KPICard(kpi_data) kpi_layout.addWidget(card, stretch=1) # Equal stretch

Two-column content (sidebar + main)

content_layout = QHBoxLayout() sidebar = QWidget() sidebar.setFixedWidth(280) # Fixed sidebar main_content = QWidget() content_layout.addWidget(sidebar) content_layout.addWidget(main_content, stretch=1) # Main stretches

Grid of cards (responsive feel)

grid = QGridLayout() grid.setSpacing(16) for i, item in enumerate(items): row, col = divmod(i, 3) # 3 columns grid.addWidget(ItemCard(item), row, col)

Visual Grouping with Cards

class CardFrame(QFrame): """Reusable card container with consistent styling."""

def __init__(self, title: str = None, parent=None):
    super().__init__(parent)
    self.setObjectName("card")
    
    layout = QVBoxLayout(self)
    layout.setContentsMargins(16, 16, 16, 16)
    layout.setSpacing(12)
    
    if title:
        title_label = QLabel(title)
        title_label.setObjectName("cardTitle")
        layout.addWidget(title_label)

Visual Details & Polish

Shadows & Depth (QPainter)

from PySide6.QtWidgets import QGraphicsDropShadowEffect from PySide6.QtGui import QColor

def add_card_shadow(widget: QWidget): """Add subtle shadow for depth (VISUAL POLISH).""" shadow = QGraphicsDropShadowEffect() shadow.setBlurRadius(20) shadow.setXOffset(0) shadow.setYOffset(4) shadow.setColor(QColor(0, 0, 0, 40)) # 15% opacity black widget.setGraphicsEffect(shadow)

Border Radius & Rounded Corners

/* Consistent border radius scale / QFrame#card { border-radius: 8px; } QPushButton { border-radius: 6px; } QLineEdit { border-radius: 4px; } QLabel#badge { border-radius: 12px; } / Pill shape for small badges */

Subtle Gradients & Backgrounds

/* Subtle gradient for depth */ QWidget#sidebar { background: qlineargradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #161B22, stop: 1 #0D1117 ); }

/* Accent gradient for buttons */ QPushButton#heroButton { background: qlineargradient( x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 #238636, stop: 1 #2EA043 ); }

Icons & Visual Indicators

Use icons purposefully, not decoratively

from PySide6.QtGui import QIcon

Status indicators with color + icon

def create_status_indicator(status: str) -> QLabel: """Create status badge with icon and color (VISUAL INDICATOR).""" label = QLabel()

status_config = {
    'online': ('●', '#238636'),
    'offline': ('○', '#6E7681'),
    'warning': ('⚠', '#D29922'),
    'error': ('✕', '#F85149'),
}

icon, color = status_config.get(status, ('?', '#8B949E'))
label.setText(f"{icon} {status.title()}")
label.setStyleSheet(f"color: {color}; font-weight: 500;")
return label

Motion & Animation

Animation Principles

  • Purpose: Animation should communicate, not decorate

  • Duration: 150-300ms for UI feedback, 300-500ms for transitions

  • Easing: Use natural curves (ease-out for entries, ease-in for exits)

  • Consistency: Same animation for same action type

Qt Animation Implementation

from PySide6.QtCore import QPropertyAnimation, QEasingCurve, QSequentialAnimationGroup

def fade_in_widget(widget: QWidget, duration: int = 200): """Fade in widget on show (MICRO-INTERACTION).""" widget.setWindowOpacity(0)

animation = QPropertyAnimation(widget, b"windowOpacity")
animation.setDuration(duration)
animation.setStartValue(0.0)
animation.setEndValue(1.0)
animation.setEasingCurve(QEasingCurve.Type.OutCubic)
animation.start()

def slide_in_panel(widget: QWidget, direction: str = 'left', duration: int = 300): """Slide panel into view (PAGE TRANSITION).""" start_pos = widget.pos()

if direction == 'left':
    widget.move(start_pos.x() - 50, start_pos.y())
elif direction == 'right':
    widget.move(start_pos.x() + 50, start_pos.y())

animation = QPropertyAnimation(widget, b"pos")
animation.setDuration(duration)
animation.setEndValue(start_pos)
animation.setEasingCurve(QEasingCurve.Type.OutCubic)
animation.start()

def pulse_attention(widget: QWidget): """Pulse widget to draw attention (NOTIFICATION).""" animation = QPropertyAnimation(widget, b"windowOpacity") animation.setDuration(150) animation.setKeyValueAt(0, 1.0) animation.setKeyValueAt(0.5, 0.6) animation.setKeyValueAt(1, 1.0) animation.start()

Hover State Animations

class AnimatedButton(QPushButton): """Button with smooth hover animation (MICRO-INTERACTION)."""

def __init__(self, text: str, parent=None):
    super().__init__(text, parent)
    self._animation = QPropertyAnimation(self, b"geometry")
    self._animation.setDuration(100)
    self._animation.setEasingCurve(QEasingCurve.Type.OutCubic)

def enterEvent(self, event):
    # Subtle scale up on hover
    current = self.geometry()
    self._animation.setStartValue(current)
    expanded = current.adjusted(-2, -1, 2, 1)
    self._animation.setEndValue(expanded)
    self._animation.start()
    super().enterEvent(event)

def leaveEvent(self, event):
    # Return to original size
    self._animation.setDirection(QPropertyAnimation.Direction.Backward)
    self._animation.start()
    super().leaveEvent(event)

Design Checklist

Before shipping any UI:

Typography

  • Clear hierarchy (title > header > body > caption)

  • Consistent font family throughout

  • Appropriate sizes (not too small, not too large)

  • Sufficient line height for readability

Color

  • Semantic colors used consistently

  • Sufficient contrast for accessibility

  • Dark/light theme support (if applicable)

  • Accent colors draw attention purposefully

Layout

  • Consistent spacing (8px grid)

  • Visual grouping of related items

  • Alignment on invisible grid

  • Adequate whitespace

Polish

  • Smooth animations where appropriate

  • Hover/active states for interactive elements

  • Loading states for async operations

  • Error states are clear and helpful

Accessibility

  • Keyboard navigation works

  • Focus states are visible

  • Color is not the only indicator

  • Text is resizable

Resources

Qt/PySide6 Specific

Design Inspiration

Color Tools

Typography

Last Updated: February 2, 2026

Purpose: Design thinking principles for PySide6 desktop applications

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

pyside6-development

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

frontend-design

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

openclaw-version-monitor

监控 OpenClaw GitHub 版本更新,获取最新版本发布说明,翻译成中文, 并推送到 Telegram 和 Feishu。用于:(1) 定时检查版本更新 (2) 推送版本更新通知 (3) 生成中文版发布说明

Archived SourceRecently Updated