---
description: For tasks requiring working with user facing UI components.
globs:
alwaysApply: false
---
# Telegram Desktop UI Styling

## Style Definition Files

UI element styles (colors, fonts, paddings, margins, icons, etc.) are defined in `.style` files using a custom syntax. These files are located alongside the C++ source files they correspond to within specific UI component directories (e.g., `Telegram/SourceFiles/ui/chat/chat.style`).

Definitions from other `.style` files can be included using the `using` directive at the top of the file:
```style
using "ui/basic.style";
using "ui/widgets/widgets.style";
```

The central definition of named colors happens in `Telegram/SourceFiles/ui/colors.palette`. This file allows for theme generation and loading colors from various sources.

### Syntax Overview

1.  **Built-in Types:** The syntax recognizes several base types inferred from the value assigned:
    *   `int`: Integer numbers (e.g., `lineHeight: 20;`)
    *   `bool`: Boolean values (e.g., `useShadow: true;`)
    *   `pixels`: Pixel values, ending with `px` (e.g., `borderWidth: 1px;`). Generated as `int` in C++.
    *   `color`: Named colors defined in `colors.palette` (e.g., `background: windowBg;`)
    *   `icon`: Defined inline using a specific syntax (see below). Generates `style::icon`.
    *   `margins`: Four pixel values for margins or padding. Requires `margins(top, right, bottom, left)` syntax (e.g., `margin: margins(10px, 5px, 10px, 5px);` or `padding: margins(8px, 8px, 8px, 8px);`). Generates `style::margins` (an alias for `QMargins`).
    *   `size`: Two pixel values for width and height (e.g., `iconSize: size(16px, 16px);`). Generates `style::size`.
    *   `point`: Two pixel values for x and y coordinates (e.g., `textPos: point(5px, 2px);`). Generates `style::point`.
    *   `align`: Alignment keywords (e.g., `textAlign: align(center);` or `iconAlign: align(left);`). Generates `style::align`.
    *   `font`: Font definitions (e.g., `font: font(14px semibold);`). Generates `style::font`.
    *   `double`: Floating point numbers (e.g., `disabledOpacity: 0.5;`)

    *Note on Borders:* Borders are typically defined using multiple fields like `border: pixels;` (for width) and `borderFg: color;` (for color), rather than a single CSS-like property.

2.  **Structure Definition:** You can define complex data structures directly within the `.style` file:
    ```style
    MyButtonStyle { // Defines a structure named 'MyButtonStyle'
      textPadding: margins; // Field 'textPadding' expects margins type
      icon: icon;         // Field 'icon' of type icon
      height: pixels;     // Field 'height' of type pixels
    }
    ```
    This generates a `struct MyButtonStyle { ... };` inside the `namespace style`. Fields will have corresponding C++ types (`style::margins`, `style::icon`, `int`).

3.  **Variable Definition & Inheritance:** Variables are defined using `name: value;` or `groupName { ... }`. They can be of built-in types or custom structures. Structures can be initialized inline or inherit from existing variables.

    **Icon Definition Syntax:** Icons are defined inline using the `icon{...}` syntax. The generator probes for `.svg` files or `.png` files (including `@2x`, `@3x` variants) based on the provided path stem.
    ```style
    // Single-part icon definition:
    myIconSearch: icon{{ "gui/icons/search", iconColor }};
    // Multi-part icon definition (layers drawn bottom-up):
    myComplexIcon: icon{
      { "gui/icons/background", iconBgColor },
      { "gui/icons/foreground", iconFgColor }
    };
    // Icon with path modifiers (PNG only for flips, SVG only for size):
    myFlippedIcon: icon{{ "gui/icons/arrow-flip_horizontal", arrowColor }};
    myResizedIcon: icon{{ "gui/icons/logo-128x128", logoColor }}; // Forces 128x128 for SVG
    ```

    **Other Variable Examples:**
    ```style
    // Simple variables
    buttonHeight: 30px;
    activeButtonColor: buttonBgActive; // Named color from colors.palette

    // Variable of a custom structure type, initialized inline
    defaultButton: MyButtonStyle {
      textPadding: margins(10px, 15px, 10px, 15px); // Use margins(...) syntax
      icon: myIconSearch; // Assign the previously defined icon variable
      height: buttonHeight; // Reference another variable
    }

    // Another variable inheriting from 'defaultButton' and overriding/adding fields
    primaryButton: MyButtonStyle(defaultButton) {
      icon: myComplexIcon; // Override icon with the multi-part one
      backgroundColor: activeButtonColor; // Add a field not in MyButtonStyle definition
    }

    // Style group (often used for specific UI elements)
    chatInput { // Example using separate border properties and explicit padding
      border: 1px;                          // Border width
      borderFg: defaultInputFieldBorder;    // Border color (named color)
      padding: margins(5px, 10px, 5px, 10px); // Use margins(...) syntax for padding field
      backgroundColor: defaultChatBg;       // Background color
    }
    ```

## Code Generation

A code generation tool processes these `.style` files and `colors.palette` to create C++ objects.
- The `using` directives resolve dependencies between `.style` files.
- Custom structure definitions (like `MyButtonStyle`) generate corresponding `struct MyButtonStyle { ... };` within the `namespace style`.
- Style variables/groups (like `defaultButton`, `primaryButton`, `chatInput`) are generated as objects/structs within the `st` namespace (e.g., `st::defaultButton`, `st::primaryButton`, `st::chatInput`). These generated structs contain members corresponding to the fields defined in the `.style` file.
- Color objects are generated into the `st` namespace as well, based on their names in `colors.palette` (e.g., `st::windowBg`, `st::buttonBgActive`).
- The generated header files for styles are placed in the `Telegram/SourceFiles/styles/` directory with a `style_` prefix (e.g., `styles/style_widgets.h` for `ui/widgets/widgets.style`). You include them like `#include "styles/style_widgets.h"`.

Generated C++ types correspond to the `.style` types: `style::color`, `style::font`, `style::margins` (used for both `margin:` and `padding:` fields), `style::icon`, `style::size`, `style::point`, `style::align`, and `int` or `bool` for simple types.

## Style Usage in Code

Styles are applied in C++ code by referencing the generated `st::...` objects and their members.

```cpp
// Example: Including the generated style header
#include "styles/style_widgets.h" // For styles defined in ui/widgets/widgets.style

// ... inside some UI class code ...

// Accessing members of a generated style struct
int height = st::primaryButton.height; // Accessing the 'height' field (pixels -> int)
const style::icon &icon = st::primaryButton.icon; // Accessing the 'icon' field (st::myComplexIcon)
style::margins padding = st::primaryButton.textPadding; // Accessing 'textPadding'
style::color bgColor = st::primaryButton.backgroundColor; // Accessing the color (st::activeButtonColor)

// Applying styles (conceptual examples)
myButton->setIcon(st::primaryButton.icon);
myButton->setHeight(st::primaryButton.height);
myButton->setPadding(st::primaryButton.textPadding);
myButton->setBackgroundColor(st::primaryButton.backgroundColor);

// Using styles directly in painting
void MyWidget::paintEvent(QPaintEvent *e) {
    Painter p(this);
    p.fillRect(rect(), st::chatInput.backgroundColor); // Use color from chatInput style

    // Border painting requires width and color
    int borderWidth = st::chatInput.border; // Access border width (pixels -> int)
    style::color borderColor = st::chatInput.borderFg; // Access border color
    if (borderWidth > 0) {
        p.setPen(QPen(borderColor, borderWidth));
        // Adjust rect for pen width if needed before drawing
        p.drawRect(rect().adjusted(borderWidth / 2, borderWidth / 2, -borderWidth / 2, -borderWidth / 2));
    }

    // Access padding (style::margins)
    style::margins inputPadding = st::chatInput.padding;
    // ... use inputPadding.top(), inputPadding.left() etc. for content layout ...
}
```

**Key Points:**

*   Styles are defined in `.style` files next to their corresponding C++ source files.
*   `using "path/to/other.style";` includes definitions from other style files.
*   Named colors are defined centrally in `ui/colors.palette`.
*   `.style` syntax supports built-in types (like `pixels`, `color`, `margins`, `point`, `size`, `align`, `font`, `double`), custom structure definitions (`Name { field: type; ... }`), variable definitions (`name: value;`), and inheritance (`child: Name(parent) { ... }`).
*   Values must match the expected type (e.g., fields declared as `margins` type, like `margin:` or `padding:`, require `margins(...)` syntax). Borders are typically set via separate `border: pixels;` and `borderFg: color;` fields.
*   Icons are defined inline using `name: icon{{ "path_stem", color }};` or `name: icon{ { "path1", c1 }, ... };` syntax, with optional path modifiers.
*   Code generation creates `struct` definitions in the `style` namespace for custom types and objects/structs in the `st` namespace for defined variables/groups.
*   Generated headers are in `styles/` with a `style_` prefix and must be included.
*   Access style properties via the generated `st::` objects (e.g., `st::primaryButton.height`, `st::chatInput.backgroundColor`).
