Taffy

repository·main·Indexed 25 days ago

https://github.com/dioxuslabs/taffy

A flexible UI layout engine (version 0.12.2) that implements a variety of CSS style properties for Flexbox and CSS Grid layout modes. It provides structures for axis-aligned rectangles (Rect), dimensions (Size), and 2D coordinates (Point), and includes tools for synchronizing test fixtures from the Yoga layout engine.

Tokens
8K
Snippets
7
Records
47
Agent score
86%

What's inside taffy

  1. Sync test fixtures from Yoga

    main

    Use this script to sync test fixtures from the Yoga repository into Taffy. This is useful for ensuring Taffy's test infrastructure remains compatible with Yoga's tests.

    Follow these steps to import and run the new tests:

    1. Clone the Yoga repository locally.
    2. Set the YOGA_FIXTURE_DIR environment variable to the absolute path of the gentest/fixtures directory within your local Yoga clone.
    3. Run the import command:
      • From the scripts/import-yoga-tests directory: cargo run
      • From the Taffy repository root: cargo import-yoga-tests
    4. Manually inspect the imported files to ensure they are relevant to Taffy's implementation.
    5. Generate the actual tests using cargo gentest from the Taffy root.
    6. Run cargo test to verify the new tests pass.
    # Example setup and execution
    export YOGA_FIXTURE_DIR="/path/to/yoga/gentest/fixtures"
    cargo import-yoga-tests
    cargo gentest
    cargo test
  2. Understand Taffy Grid Coordinate Systems

    main

    Taffy utilizes two distinct coordinate systems for referring to grid lines (the gaps or gutters between rows and columns):

    1. CSS Grid Line Coordinates (GridLine):

      • Follows the CSS Grid specification.
      • The first line (left/top edge) is 1.
      • The last line (right/bottom edge) is -1.
      • 0 is not a valid index.
    2. OriginZero Coordinates (OriginZeroLine):

      • A normalized coordinate system used internally.
      • The first line (left/top edge) is 0.
      • Subsequent lines to the right/down are 1, 2, ....
      • Lines to the left/up are -1, -2, ....
  3. Use the Taffy High-level API

    main

    The high-level API is recommended for users using Taffy standalone. It uses the TaffyTree struct to manage node storage, caching, and algorithm dispatching automatically.

    To use this API:

    1. Construct a tree of UI nodes using TaffyTree (including Style, children, and optional context).
    2. Call compute_layout_with_measure to calculate the layout. This method requires a 'measure function' closure to compute the size of leaf nodes (e.g., for text or images).
    3. Access the resulting positions and sizes using the layout method.
  4. Use the Taffy Low-level API

    main

    The low-level API is designed for users embedding Taffy into a wider layout system or a UI framework that already has its own node/widget tree.

    When using this API, you are responsible for:

    • Implementing your own tree structure.
    • Handling node storage and caching.
    • Dispatching to the correct layout algorithm.

    Key components:

    • Implement the LayoutPartialTree trait to define your tree interface.
    • Use specific computation functions like compute_flexbox_layout or compute_grid_layout to compute layout for a single node at a time.
  5. Handle failing Yoga test fixtures

    main

    If newly imported Yoga tests fail in Taffy, you can disable them by prefixing the fixture filename with an x.

    For example, renaming align_content_stretch.html to xalign_content_stretch.html will cause cargo gentest to automatically remove the corresponding generated test during the next run.

  6. Configure safe and unsafe overflow alignment

    main

    Alignment structs like AlignContent, AlignItems, AlignSelf, JustifyItems, and JustifySelf support an AlignmentSafety field to handle overflow behavior.

    • AlignmentSafety::Safe: If the alignment would cause the subject to overflow its container, it falls back to the logical Start so the start edge remains visible.
    • AlignmentSafety::Unsafe (Default): Keeps the requested alignment even if it causes overflow at the start edge.

    Note: The safe/unsafe modifier is only defined for position keywords: start, end, flex-start, flex-end, and center. Combinations like safe stretch are treated as Unsafe.

    For ergonomics, Taffy provides associated constants for common CSS spellings (e.g., AlignContent::SafeStart, AlignItems::SafeFlexEnd).

    Use .is_safe() to check the safety modifier and .keyword() to retrieve the bare position keyword.

    pub struct AlignContent {
        pub keyword: AlignContentKeyword,   // Start, End, FlexStart, FlexEnd, Center, 
                                            // Stretch, SpaceBetween, SpaceEvenly, SpaceAround
        pub safety: AlignmentSafety,        // Safe | Unsafe
    }
  7. Morphorm Style Properties Reference

    main

    Morphorm provides a set of style properties categorized by their application to Layout Modes, Item Sizing, Borders, Containers, and Items.

    ### Layout Mode
    | Property | Type | Description |
    | --- | --- | --- |
    | `layout_mode` | `LayoutType` | Row vs. Column vs. Grid |
    | `position_type` | `Position` | SelfDirected (absolute) vs. ParentDirected (in-flow) position |
    
    ### Item size
    | Property | Type | Description |
    | --- | --- | --- |
    | `size` | `Size<Units>` | The preferred height and width of item |
    | `min_size` | `Size<Units>` | The minimum height and width of the item |
    | `max_size` | `Size<Units>` | The maximum height and width of the item |
    
    ### Border
    | Property | Type | Description |
    | --- | --- | --- |
    | `border` | `Rect<Units>` | How large should the border be on each side? |
    
    ### Morphorm Container
    | Property | Type | Description |
    | --- | --- | --- |
    | `child_spacing` | `Rect<Units>` | Sets the default "spacing" (~margin) on each side of child nodes |
    | `row_between` | `Units` | Sets the default vertical "spacing" (~margin) between child nodes |
    | `col_between` | `Units` | Sets the default horizontal "spacing" (~margin) between child nodes |
    | `grid_rows` | `Vec<Units>` | (Grid Container) Row definitions with a size for each row |
    | `grid_cols` | `Vec<Units>` | (Grid Container) Column definitions with a size for each column |
    
    ### Morphorm Item
    | Property | Type | Description |
    | --- | --- | --- |
    | `spacing` | `Rect<Units>` | The preferred spacing on each side of the item |
    | `min_spacing` | `Rect<Units>` | The minimum spacing on each side of the item |
    | `max_spacing` | `Rect<Units>` | The maximum spacing on each side of the item |
    | `row_index` | `usize` | (Grid Item) Zero-based index for the start row of the item |
    | `col_index` | `usize` | (Grid Item) Zero-based index for the start column of the item |
    | `row_span` | `usize` | (Grid Item) The number of rows the item spans |
    | `col_span` | `usize` | (Grid Item) The number of columns the item spans |
  8. Reference supported Taffy style properties

    main

    Taffy implements a variety of CSS style properties for both Flexbox and CSS Grid layout modes. The implementation status is indicated by:

    • Y: Supported in spec and implemented in Taffy
    • ~Y: Implemented in Taffy, but not thoroughly tested
    • N: Supported in spec but not implemented in Taffy
    • 1-5: Priorities for a phased implementation of CSS Grid
    • -: Not applicable to layout mode

    Layout & Position

    PropertyFlexGridTypeDescription
    displayYYDisplayLayout strategy
    positionYYPositionAbsolute vs. in-flow
    insetYYRect<LengthPercentageAuto>Position tweak relative to layout

    Item Size & Spacing

    PropertyFlexGridTypeDescription
    sizeYYSize<Dimension>Nominal height and width
    min_sizeYYSize<Dimension>Minimum height and width
    max_sizeYYSize<Dimension>Maximum height and width
    aspect_ratioY3Option<f32>Preferred aspect ratio
    paddingY~YRect<LengthPercentage>Padding on each side
    borderY~YRect<LengthPercentage>Border on each side
    marginY~YRect<LengthPercentageAuto>Margin on each side
    gapYYSize<LengthPercentage>Gap between items/rows

    Alignment

    PropertyFlexGridTypeDescription
    align_contentYYAlignContentContent alignment (cross axis)
    justify_contentYYAlignContentContent alignment (main axis)
    align_itemsYYAlignItemsItem alignment (cross axis)
    align_selfYYOption<AlignItems>Individual item cross axis alignment
    justify_items-YAlignItemsItem alignment (main axis)
    justify_self-YOption<AlignItems>Individual item main axis alignment

    Flexbox Specific

    PropertyFlexGridTypeDescription
    flex_directionY-FlexDirectionMain axis direction
    flex_wrapY-FlexWrapWrapping behavior
    flex_basisY-DimensionInitial main axis size
    flex_growY-f32Growth rate
    flex_shrinkY-f32Shrink rate

    CSS Grid Specific

    Container Properties

    PropertyFlexGridTypeDescription
    grid_template_columns-YVec<TrackSizingFunction>Explicit column sizing
    grid_template_rows-YVec<TrackSizingFunction>Explicit row sizing
    grid_template_areas-5-Named grid areas
    grid_auto_rows-YVec<NonRepeatedTrackSizingFunction>Implicit row sizing
    grid_auto_columns-YVec<NonRepeatedTrackSizingFunction>Implicit column sizing
    grid_auto_flow-YGridAutoFlowAuto-placement behavior

    Child Properties

    PropertyFlexGridTypeDescription
    grid_row-YLine<GridPlacement>Vertical placement
    grid_column-YLine<GridPlacement>Horizontal placement
    grid_area-5-Shorthand for row/column or named area
  9. Morphorm Unique Types

    main

    Morphorm uses simplified types that map to Taffy concepts. Note that some types, like Units::Stretch, have no direct equivalent in Taffy.

    // LayoutType corresponds to Taffy's Display
    enum LayoutType {
        Row,
        Column,
        Grid,
    }
    
    // PositionType corresponds to Taffy's Position
    pub enum PositionType {
        SelfDirected,   // = Position::Absolute
        ParentDirected, // = Position::Relative
    }
    
    // Units corresponds to Taffy's Dimension
    pub enum Units {
        Pixels(f32),    // = Dimension::Length
        Percentage(f32), // = Dimension::Percent
        Auto,           // = Dimension::Auto
        Stretch(f32),   // No equivalent in Taffy!
    }
  10. Use the Rect struct for axis-aligned rectangles

    main

    The Rect<T> struct represents an axis-aligned UI rectangle. It is defined by four properties: left, right, top, and bottom. These can represent either coordinates or padding amounts depending on the context (e.g., LTR vs RTL text).

    Key operations:

    • Mapping: Use .map(|val| ...) to transform all four sides into a new type.
    • Component Extraction: Use .horizontal_components() or .vertical_components() to get a Line<T> representing the respective axis.
    • Summing Axes: Use .horizontal_axis_sum() or .vertical_axis_sum() to get the sum of the start and end edges (often used for total padding). Note that this is not the width/height.
    • Creation: Use Rect::new(start, end, top, bottom) or Rect::ZERO for a zeroed rectangle.
  11. Create a new GridItem

    main

    Use new_with_placement_style_and_order to instantiate a GridItem. This method requires the node ID, the resolved column and row spans (as Line<OriginZeroLine>), the item's style, the parent's alignment settings, and the original source order.

    Note that row_indexes and column_indexes are initialized to zero and must be properly set during the layout process.

  12. Manage collapsible margins with CollapsibleMarginSet

    main

    For CSS Block layout, use CollapsibleMarginSet to handle margin collapsing. This struct tracks the largest positive margin and the smallest negative margin.

    Methods:

    • CollapsibleMarginSet::from_margin(margin: f32): Creates a set from a single value.
    • collapse_with_margin(margin: f32): Collapses a single margin into the current set.
    • collapse_with_set(other: CollapsibleMarginSet): Collapses another set into the current set.
    • resolve() -> f32: Returns the final resolved margin (positive + negative).