OutSystems UI is the official Trusted Forge component providing 70+ pre-built, accessible UI patterns for Reactive Web and Mobile apps. Patterns are Blocks with Input Parameters and Events. Drag them from the Toolbox, configure Input Parameters in the Properties panel, and wire Events to Client Actions. No CSS required for standard usage — customize with ExtendedClass for CSS overrides.
70+ Pre-Built Components, Zero Extra Cost
The OutSystems UI library is a Trusted Forge component that ships pre-installed in every Reactive Web app template. It provides Accordion, Tabs, Cards, Gallery, Wizard, Pagination, BottomSheet, Carousel, Notifications, and dozens more. Each pattern is a Block — a reusable UI component with Input Parameters (data in) and Events (interactions out). Understanding how to configure Blocks is the universal skill for using the entire library. This tutorial covers the most commonly used patterns with hands-on configuration examples.
Prerequisites
- A Reactive Web application open in Service Studio
- OutSystems UI dependency referenced in your module (Ctrl+Q → check for 'OutSystemsUI' module)
- A screen to work with (Interface tab → UI Flows → MainFlow → double-click an existing screen)
Step-by-step guide
Verify OutSystems UI Is Referenced and Find Patterns in the Toolbox
Verify OutSystems UI Is Referenced and Find Patterns in the Toolbox
OutSystems UI is pre-installed in the OutSystems environment, but your module must reference it to use its patterns in the Toolbox. **Verify the reference:** 1. Press Ctrl+Q to open Manage Dependencies 2. Search for 'OutSystemsUI' in the producer modules list 3. If it appears with elements checked, you are set. If not checked, check the Blocks you need and click Apply. **Finding patterns in the Toolbox:** Open a screen in the Screen Editor (double-click a screen in Interface tab). The Toolbox on the left shows widgets and blocks grouped by category. With OutSystems UI referenced, new categories appear: - **Content:** Accordion, Alert, Badge, BlankSlate, Card, CardSectioned, Section, Tag, Tooltip - **Data:** Gallery, DataGrid, ProgressBar, Rating, Timeline, Counter - **Interaction:** Carousel, DatePicker, Dropdown ServerSide, RangeSlider, Tabs, Search, ToggleButton, Video - **Navigation:** Breadcrumbs, Pagination, Sidebar, Steps, Wizard - **Utilities:** Animate, MasterDetail, Spinner Search the Toolbox by typing the pattern name (e.g., 'Accordion') in the Toolbox search field.
Expected result: The Toolbox shows OutSystems UI pattern categories (Content, Data, Interaction, etc.) with blocks like Accordion, Tabs, and Card visible and draggable.
Build an Accordion with Dynamic Content
Build an Accordion with Dynamic Content
The Accordion pattern creates expandable/collapsible sections — ideal for FAQs, settings panels, and grouped data. **Adding the Accordion:** 1. In the Toolbox, find and drag **AccordionItem** (not the full Accordion wrapper — each item is added individually) onto the screen canvas 2. Drag multiple AccordionItems and stack them vertically, or use the Accordion block wrapper that manages a group of items **AccordionItem Input Parameters:** - **Title** — the header text displayed at all times (Text expression) - **StartsOpen** — `True` to expand by default, `False` to start collapsed (Boolean) - **IsOpen** — bind to a local Boolean variable if you need programmatic control - **ExtendedClass** — additional CSS classes for customization **AccordionItem Event:** - **OnToggle** — fires when user expands or collapses. Wire to a Client Action to run logic when toggle happens. **Dynamic AccordionItem titles from data:** Place AccordionItem blocks inside a List widget bound to an Aggregate, then set Title to `List.Current.FAQ.Question` and the Content placeholder content to match. **Widget tree for an FAQ section:**
1/* Widget tree:2 List (Source: GetFAQs.List)3 └─ AccordionItem4 Title: GetFAQs.List.Current.FAQ.Question5 StartsOpen: False6 ExtendedClass: "faq-item"7 └─ [Content placeholder]8 └─ Text: GetFAQs.List.Current.FAQ.Answer9*/1011/* AccordionItem OnToggle Client Action (optional):12 Input: IsOpen (Boolean)1314 Use to track which section is open:15 Start → Assign: LastOpenedQuestion = Title → End16*/Expected result: The screen shows a list of expandable FAQ items. Each item header is clickable; clicking expands the answer. The AccordionItem fires OnToggle when opened or closed.
Build a Tabs Pattern for Content Organization
Build a Tabs Pattern for Content Organization
Tabs organize related content into switchable panels without page navigation. **Adding Tabs:** 1. Drag the **Tabs** block from the Toolbox onto the screen 2. By default it contains TabsHeaderItem and TabsContentItem placeholders **Tabs Input Parameters:** - **ActiveTab** — bind to a local Integer variable (`ActiveTabIndex`, Default: 1). Tab 1 is active when value = 1. - **JustifyHeaders** — `True` to make tabs equal width and fill container - **Position** — `Position.Top`, `Position.Bottom`, `Position.Left`, `Position.Right` - **ExtendedClass** — additional CSS classes **Tabs Event:** - **OnTabChange** — fires with the new tab index. Wire to a Client Action. **Setting up tab content:** 1. Inside the Tabs block, the TabsHeaderItem contains the tab label 2. The TabsContentItem contains the tab's content 3. Duplicate these placeholder groups for each tab you need 4. Set each TabsHeaderItem's Label to the tab name **Wiring OnTabChange:** Create `OnTabChange` Client Action with Input `TabIndex` (Integer): Start → Assign: ActiveTabIndex = TabIndex → [optional: refresh Aggregate for new tab] → End
1/* Local variable:2 ActiveTabIndex: Integer = 134 Tabs block properties:5 ActiveTab: ActiveTabIndex6 Position: Position.Top7 JustifyHeaders: True8 OnTabChange → OnTabChange(TabIndex: NewTabIndex)910 Widget tree:11 Tabs (ActiveTab: ActiveTabIndex)12 ├─ TabsHeaderItem (Label: "Overview")13 ├─ TabsContentItem14 │ └─ [Overview content]15 ├─ TabsHeaderItem (Label: "Details")16 ├─ TabsContentItem17 │ └─ [Details content]18 └─ TabsHeaderItem (Label: "History")19 [third content item]2021 OnTabChange Client Action:22 Start → Assign: ActiveTabIndex = TabIndex → End23*/Expected result: The screen shows three tabs. Clicking a tab header switches the active content panel. The active tab index is tracked in the local variable, and OnTabChange fires with the new index when the user switches tabs.
Use the Card and Gallery Patterns for Data Display
Use the Card and Gallery Patterns for Data Display
The **Card** pattern provides a styled container for displaying individual records. The **Gallery** pattern creates a responsive grid of cards. **Basic Card setup:** 1. Drag a **Card** block onto the screen 2. The Card has placeholder sections: Image, Header, Content, Footer 3. Drag widgets into each placeholder (Image widget in Image, Text in Header, etc.) **Card Input Parameters:** - **Clickable** — `True` makes the entire card a clickable surface (adds hover effect) - **ExtendedClass** — CSS classes for custom styling **Gallery for a card grid:** 1. Drag **Gallery** block onto the screen 2. Gallery Input Parameters: - **ColumnsInDesktop** — number of columns on desktop (e.g., 3) - **ColumnsInTablet** — columns on tablet (e.g., 2) - **ColumnsInPhone** — columns on phone (e.g., 1) - **GutterSize** — space between cards: `GutterSize.Base`, `GutterSize.Small`, `GutterSize.Large` 3. Inside the Gallery, place a **List** widget (Source: your Aggregate) 4. Inside the List, place a **Card** block 5. Inside the Card, fill each placeholder with data from the current List item **Handling card click navigation:** Set Card's Clickable to True → Card's OnClick → Client Action → Navigate to detail screen with the record Id as input parameter.
1/* Gallery + Card widget tree:2 Gallery3 ColumnsInDesktop: 34 ColumnsInTablet: 25 ColumnsInPhone: 16 GutterSize: GutterSize.Base7 └─ List (Source: GetProducts.List)8 └─ Card9 Clickable: True10 OnClick → OpenProductDetail(ProductId: GetProducts.List.Current.Product.Id)11 ├─ [Image placeholder]12 │ └─ Image (URL: GetProducts.List.Current.Product.ImageUrl)13 ├─ [Header placeholder]14 │ └─ Text: GetProducts.List.Current.Product.Name15 ├─ [Content placeholder]16 │ └─ Text: GetProducts.List.Current.Product.Description17 └─ [Footer placeholder]18 └─ Text: "$" + DecimalToText(GetProducts.List.Current.Product.Price)19*/Expected result: The screen shows a 3-column product grid on desktop (2 on tablet, 1 on phone). Each card displays product image, name, description, and price. Clicking any card navigates to the product detail screen.
Customize Patterns with ExtendedClass and CSS Overrides
Customize Patterns with ExtendedClass and CSS Overrides
Every OutSystems UI pattern block has an **ExtendedClass** input parameter. This is a Text field that accepts additional CSS class names to apply to the pattern's root element. **Common uses of ExtendedClass:** - Add custom class from your theme: `"product-card shadow-lg"` - Apply utility classes: `"margin-bottom-m background-primary"` - Multiple classes: `"card-custom margin-top-s border-none"` **The ExtendedClass pattern:** When you set ExtendedClass to `"my-custom-class"`, the pattern renders with both its own OutSystems UI class and your custom class: `<div class="osui-card my-custom-class">` **CSS overrides for patterns:** In your Theme's Style Sheet Editor, target the combined class: **Dynamic ExtendedClass expression:** ExtendedClass accepts expressions, enabling dynamic class application: `If(Product.IsNew, "card-featured", "card-standard")` **Full override of a pattern's internal styles:** Target the internal class names (inspect in browser DevTools): `.osui-tabs__tab` — individual tab item `.osui-tabs__content` — tab content panel `.osui-accordion__item.is-open` — open accordion item
1/* ExtendedClass value examples:23 Static:4 "product-card"56 Multiple classes:7 "product-card shadow-elevation-2"89 Dynamic (expression editor):10 If(Product.IsFeatured, "card-featured card-highlighted", "card-standard")1112 In your Application Theme CSS:13 .product-card {14 border: 2px solid var(--color-brand-primary);15 transition: transform 0.2s ease;16 }1718 .product-card:hover {19 transform: translateY(-4px);20 box-shadow: 0 8px 24px rgba(0,0,0,0.12);21 }2223 .card-featured {24 border-color: var(--color-brand-accent);25 background: linear-gradient(135deg, #FFF 0%, #FEF3C7 100%);26 }2728 /* Override OutSystems UI tab active indicator color */29 .osui-tabs__tab.is-active {30 border-bottom-color: var(--color-brand-primary) !important;31 color: var(--color-brand-primary) !important;32 }33*/Expected result: Cards have custom hover effects from the CSS class set via ExtendedClass. Featured products show a distinct background. Tab active indicator matches your brand color. All customizations survive OutSystems UI version updates as long as .osui- class names remain stable.
Complete working example
1/* OutSystems UI Patterns — Implementation Reference23=== ACCORDION (FAQ Section) ===4 Local variable: (none needed for basic accordion)56 Widget tree:7 List (Source: GetFAQItems.List)8 └─ AccordionItem9 Title: GetFAQItems.List.Current.FAQItem.Question10 StartsOpen: GetFAQItems.List.CurrentIndex = 0 // first item open11 └─ [Content placeholder]12 └─ Text: GetFAQItems.List.Current.FAQItem.Answer1314=== TABS (Detail View) ===15 Local variable: ActiveTab: Integer = 11617 Tabs block:18 ActiveTab: ActiveTab19 OnTabChange → OnTabChange(NewTabIndex: TabIndex)2021 OnTabChange:22 Start → Assign: ActiveTab = NewTabIndex → End2324=== GALLERY + CARDS (Product Grid) ===25 Gallery:26 ColumnsInDesktop: 427 ColumnsInTablet: 228 ColumnsInPhone: 12930 Inside Gallery → List → CardSectioned:31 ExtendedClass: "product-card"32 Clickable: True33 OnClick → NavigateToProduct(ProductId: List.Current.Product.Id)3435=== WIZARD (Multi-Step Form) ===36 Local variable: CurrentStep: Integer = 13738 Wizard block:39 Step: CurrentStep40 Labels: ["Account", "Details", "Confirm"]4142 NextStep Client Action:43 Start → Assign: CurrentStep = CurrentStep + 1 → End4445 PrevStep Client Action:46 Start → If(CurrentStep > 1)47 [True] → Assign: CurrentStep = CurrentStep - 1 → End48 [False] → End4950=== SPINNER (Loading State) ===51 Local variable: IsLoading: Boolean = False5253 Conditional display:54 If widget: Condition = IsLoading55 [True] → Spinner block56 [False] → actual content5758 Usage — wrap any data-loading action:59 Start → Assign: IsLoading = True60 → [call Server Action]61 → Refresh Data: GetItems62 → Assign: IsLoading = False63 → End6465=== TAG (Status Display) ===66 Tag block:67 Label: Task.StatusName68 Color: If(Task.StatusId = Entities.Status.Active,69 "green", "grey")70 ExtendedClass: "status-tag"71*/Common mistakes
Why it's a problem: Dragging the Accordion block onto the screen and expecting it to show items automatically
How to avoid: Accordion is a container block — you must place AccordionItem blocks inside it. Each AccordionItem is a separate block with its own Title and Content placeholder. Add multiple AccordionItem blocks inside the Accordion wrapper to create multiple sections.
Why it's a problem: Setting Tabs ActiveTab to a hardcoded integer (e.g., 1) and wondering why tab switching does not work
How to avoid: ActiveTab must be bound to a local variable, not a hardcoded value. Create a local Integer variable (ActiveTabIndex, default 1), bind ActiveTab to it, and in the OnTabChange event update the variable. Without this binding, the tabs cannot track the selected state.
Why it's a problem: Using the Card block's image placeholder but the image not appearing — setting image URL in ExtendedClass instead of the Image widget
How to avoid: The Card pattern has a placeholder named 'Image'. Drag an Image widget INTO this placeholder and set the Image widget's URL source property. Do not use CSS background-image via ExtendedClass for the main card image — use the dedicated Image widget for accessibility and correct sizing behavior.
Why it's a problem: Trying to find OutSystems UI patterns in the Toolbox and they do not appear after adding the dependency
How to avoid: After adding the OutSystems UI dependency via Ctrl+Q, close and reopen the screen in the Screen Editor. The Toolbox is refreshed when a screen is opened. If patterns still do not appear, verify in Manage Dependencies that you checked the specific Block elements (not just the module).
Best practices
- Always check that ExtendedClass is a quoted string expression (not an unquoted variable name) — TrueChange will flag unquoted values as errors
- For tab content that requires data fetching, use Fetch = 'Only on demand' Aggregates and trigger fetch in OnTabChange — avoids loading all tab data upfront
- Use Gallery ColumnsInPhone: 1 as the default — card grids almost always need to collapse to single column on mobile
- Handle the AccordionItem OnToggle event when you need to track which section is open — do not rely on internal state if your logic depends on the open/closed status
- Use the Wizard pattern (not manual If widgets) for multi-step forms — Wizard handles step validation hooks and progress indicators out of the box
- Test all pattern interactions with keyboard navigation (Tab, Enter, Space, Escape) — OutSystems UI patterns are built to be accessible and keyboard operable
- When a pattern update breaks your CSS overrides, check the OutSystems UI changelog — .osui- class names occasionally change between major versions
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
I am building an OutSystems Reactive Web app product catalog page. I need: (1) a Gallery showing product cards in a 3-column desktop / 2-column tablet / 1-column phone grid, where clicking a card navigates to the product detail screen; (2) on the detail screen, a Tabs pattern with Overview, Specifications, and Reviews tabs where the Reviews tab loads review data only when first selected; and (3) an Accordion on the detail screen for a FAQ section populated from a database entity. Show me the widget tree structure, local variables, and key input parameter values for each pattern.
In my OutSystems app, I want to add an Accordion FAQ section. I have a FAQItem entity with Question (Text) and Answer (Text) fields. I want to populate the AccordionItems from a GetFAQItems Aggregate in a List widget. Show me: (1) the widget tree with the List containing AccordionItem blocks, (2) the Title and Content expressions, (3) how to make the first item start open, and (4) the ExtendedClass CSS for a custom FAQ style.
Frequently asked questions
How many OutSystems UI patterns are available and where is the full documentation?
The OutSystems UI library provides 70+ patterns as of 2026, organized into Content, Data, Interaction, Navigation, and Utilities categories. The full documentation is available at outsystems.com/outsystems-ui/ with interactive examples, property descriptions, and accessibility notes for every pattern. The Forge listing at forge.outsystems.com/reactive/home/project/584/outsystems-ui also has version history and usage guides.
Can I use OutSystems UI patterns in Traditional Web apps?
No. The OutSystems UI library is designed exclusively for Reactive Web and Mobile apps. Traditional Web apps use the older Silk UI library, which is in maintenance mode and not receiving new components. This is one of the strong reasons to choose Reactive Web for new projects — you get the full 70+ pattern library.
How do I update to a newer version of OutSystems UI?
Go to forge.outsystems.com, find the OutSystems UI component, and click Install to install the newer version. This updates the module in your environment. After updating, open your application module in Service Studio — TrueChange will highlight any breaking changes (renamed properties, removed events). Review the OutSystems UI changelog on Forge before updating to anticipate breaking changes.
What is the difference between a Block and a Widget in OutSystems?
Widgets are atomic UI elements built into OutSystems (Button, Input, Text, Image, Table, List). Blocks are reusable compound components created in OutSystems — either by your team or by Forge providers like OutSystems UI. OutSystems UI patterns are all Blocks. The difference matters in the Toolbox: widgets appear in the base widget section; blocks appear under the categories added by their dependency. Both are dragged onto screens the same way.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation