React Clean UI
Layout

FlexItem

Grow, shrink, or fill space inside a parent's flex layout.

FlexItem is a Container that additionally renders a Roblox UIFlexItem, letting it grow, shrink, or fill leftover space when placed inside a parent governed by a UIListLayout — for example HStack, VStack, Row/Column, or a raw frame with its own uilistlayout. By default it also lays out its own children in a horizontal row, so it doubles as a small flex container in its own right.

Import

import { FlexItem } from "@rbxts/react-clean-ui";

Basic usage

import React from "@rbxts/react";
import { Button, Container, FlexItem, HStack, Icon, Text } from "@rbxts/react-clean-ui";

export function FlexItemExample() {
    return (
        <Container width="300">
            <HStack valign="Center">
                <Icon icon="shopping-basket" LayoutOrder={1} />
                <Text text="Basket" variant="title" LayoutOrder={2} />
                <FlexItem align="Right" LayoutOrder={3}>
                    <Button icon="refresh" scale="sm" />
                </FlexItem>
            </HStack>
        </Container>
    );
}

Since mode defaults to "Grow", the FlexItem expands to consume the header's remaining width inside the HStack. Setting align="Right" then pushes its own content — the refresh button — to the right edge of that expanded space, giving a classic "title on the left, action on the right" header.

Requires a flex-layout parent

The underlying UIFlexItem only affects layout while FlexItem sits as a direct child of a frame governed by a UIListLayout — such as HStack, VStack, Row, or a raw frame with its own uilistlayout. Used outside of one, mode, GrowRatio, and ShrinkRatio have no visible effect; FlexItem still renders its own children horizontally, but doesn't grow or shrink relative to siblings.

Flex modes

Use mode to choose how the item behaves within its parent's flex layout:

  • "Grow" (the default) — expands beyond its automatic size to consume any leftover space, proportioned against other growing siblings by GrowRatio.
  • "Shrink" — allows the item to shrink below its automatic size when there isn't enough room, proportioned against other shrinking siblings by ShrinkRatio.
  • "Fill" — combines growing and shrinking so the item stretches or compresses to exactly fill the space available to it.
  • "Custom" — hands sizing entirely to GrowRatio/ShrinkRatio, without the automatic-size-based constraints the other modes apply.
  • "None" — the item is unaffected by the parent's flex layout.

See Roblox's UIFlexMode reference for the full behavior of each mode.

Fixed and flexible columns

mode="Custom" combined with explicit GrowRatio/ShrinkRatio values is useful for pinning one item to its content size while letting a sibling absorb the remaining space — the same pattern Fieldset.Label and Fieldset.Control use internally.

import React from "@rbxts/react";
import { FlexItem, HStack, Input, Text } from "@rbxts/react-clean-ui";

export function FixedLabelExample() {
    return (
        <HStack valign="Center" HorizontalFlex={Enum.UIFlexAlignment.Fill}>
            <FlexItem mode="Custom" GrowRatio={0} ShrinkRatio={0}>
                <Text text="Email address" />
            </FlexItem>
            <FlexItem mode="Custom" GrowRatio={1} ShrinkRatio={1}>
                <Input placeholder="you@example.com" />
            </FlexItem>
        </HStack>
    );
}

The label's FlexItem neither grows nor shrinks, so it always stays at its natural content width, while the input's FlexItem grows and shrinks to fill whatever space remains.

Line alignment

In a wrapping list layout, such as the default HStack, items sit at the top of their line. Set ItemLineAlignment to move one FlexItem within its line without changing its siblings. For example, ItemLineAlignment={Enum.ItemLineAlignment.Center} centres it vertically beside a taller sibling.

Aligning a FlexItem's own children

By default FlexItem arranges its own children using an internal horizontal UIListLayout. Use align to control how those children line up along that row — independent of how the FlexItem itself is positioned by its parent's layout.

<FlexItem align="Right">
    <Button icon="refresh" />
</FlexItem>

Use HorizontalFlex to distribute space between multiple children placed inside a single FlexItem, the same way the HorizontalFlex prop works on HStack.

Vertical direction

Set direction="vertical" to stack the FlexItem's own children top to bottom instead. align and HorizontalFlex still apply to the same internal layout.

<FlexItem direction="vertical" align="Center">
    <Text text="Level 12" />
    <Text text="2,450 XP" />
</FlexItem>

This only changes the internal layout's FillDirection. It isn't a VStack: there is no gap between children, and HorizontalFlex isn't set to Fill by default.

Bringing your own layout

Set layout={false} to drop the internal UIListLayout entirely, so a child VStack or HStack can own the layout with its own gap and flex settings. A frame with two UIListLayouts lays out unpredictably, so use this whenever a FlexItem holds a stack.

import React from "@rbxts/react";
import { Button, FlexItem, HStack, Text, VStack } from "@rbxts/react-clean-ui";

export function FillingColumnExample() {
    return (
        <HStack>
            <FlexItem layout={false} LayoutOrder={1}>
                <VStack>
                    <Text text="Inventory" variant="title" LayoutOrder={1} />
                    <Text text="12 / 40 slots used" LayoutOrder={2} />
                </VStack>
            </FlexItem>
            <Button text="Sort" LayoutOrder={2} />
        </HStack>
    );
}

The FlexItem grows to fill the row beside the button, and the VStack inside it stacks the text with the theme's gap. With layout={false}, align, HorizontalFlex, and direction have no effect. Use direction="vertical" instead when you don't need a gap.

Props

FlexItem-specific props

PropTypeDefaultDescription
modeEnum.UIFlexMode | "Grow" | "None" | "Shrink" | "Fill" | "Custom" | Binding<Enum.UIFlexMode>"Grow"Sets UIFlexItem.FlexMode, controlling how the item grows or shrinks within its parent's UIListLayout.
GrowRationumberRoblox default (1)Sets UIFlexItem.GrowRatio — the item's share of extra space relative to other growing siblings, used when mode is "Grow", "Fill", or "Custom".
ShrinkRationumberRoblox default (1)Sets UIFlexItem.ShrinkRatio — the item's share of shrinkage relative to other shrinking siblings, used when mode is "Shrink", "Fill", or "Custom".
ItemLineAlignmentEnum.ItemLineAlignmentRoblox default (Automatic)Sets UIFlexItem.ItemLineAlignment — where the item sits within its line when the parent layout wraps (such as the default HStack). Unset, it follows the parent layout, which puts items at the top.
alignEnum.HorizontalAlignment | "Right" | "Left" | "Center" | Binding<Enum.HorizontalAlignment>Roblox default (Left)Horizontal alignment applied to FlexItem's own children, via its internal UIListLayout.
HorizontalFlexEnum.UIFlexAlignment | "None" | "SpaceAround" | "Fill" | Binding<Enum.UIFlexAlignment>Roblox default (None)Space distribution applied between FlexItem's own children, via its internal UIListLayout.
direction"horizontal" | "vertical""horizontal"Sets the internal UIListLayout's FillDirection. "vertical" stacks children top to bottom with no gap.
layoutbooleantrueWhen false, no internal UIListLayout is rendered, so a child VStack/HStack can own the layout. align, HorizontalFlex, and direction then have no effect.
childrenReact.ReactNodeundefinedContent laid out inside the FlexItem (horizontally by default).

Shared props

FlexItem extends ContainerProps and forwards every prop it receives straight to an underlying Container, including the interfaces below.

InterfacePurpose
SizeElementPropsConfigures width, height, and automatic sizing (inherited via Container).
PositionElementPropsConfigures position, anchoring, and centering (inherited via Container).
ZIndexElementPropsConfigures render order via ZIndex (inherited via Container).
React.InstanceProps<ImageLabel>Native ImageLabel properties, including Event and Change (inherited via Container).

Container-only props such as group, backgroundImage, and backgroundGradient are also inherited and forwarded unchanged — see Container for details.

Behaviour

  • FlexItem always renders a UIFlexItem and, unless layout={false}, a UIListLayout as siblings of children, inside the Container it wraps. With the default direction, multiple children passed to a single FlexItem are laid out in a row; with direction="vertical" they are stacked with no gap.
  • With layout={false} there is no internal UIListLayout, so children are positioned only by their own layout (for example a child VStack). Don't put a VStack/HStack inside a FlexItem without layout={false}: the two UIListLayouts on one frame lay out unpredictably.
  • The UIFlexItem only has a visible effect while FlexItem is a direct child of a frame governed by a UIListLayout. Placed elsewhere, mode/GrowRatio/ShrinkRatio are inert.
  • Enabling group (inherited from Container) moves FlexItem's children — including its own UIFlexItem and internal UIListLayout — onto the inner measurement frame that Container creates for grouped sizing, rather than leaving them on the outer frame that actually participates in the parent's layout. In this combination mode/GrowRatio/ShrinkRatio most likely stop applying to the object the parent layout actually sees, so avoid combining group with flex sizing on the same FlexItem. This applies to the internal UIListLayout too, unless layout={false}.
GitHub Repository

On this page