KeepNeeds Refinement
Tabs Component link

The Tabs container composes a row of Tab Item instances. 12 variants across Orientation (Vertical/Horizontal) × Size (Medium/Large) × Tabs Count (2/3/4).

Rebuilt — container is clean
Renamed to Tabs (plural), disambiguating it from the Tab Item atom, and rebuilt to 12 variants across Orientation × Size × Tabs Count. Every cell is a real Tab Item instance, so atom changes propagate. The fixed Tabs Count axis and the absence of a scrollable variant are both intentional — GCash tabs are capped at 2–4. Only Code Connect registration remains.
In Context

Contexts are illustrative. Final screens will reference actual GCash patterns. Tabs sit below a Title Bar to switch between screen sections.

Title Overview Details History
Live Preview
LabelLabelLabelLabel
Properties
tabsCount
active
DS Health
Reusable
Pass
Used anywhere a screen switches between sections — Transactions, Vouchers, Profile, category filters. Two orientations and two sizes cover both compact rows and vertical rails.
Self-contained
Pass
Carries its own layout and spacing across all 12 variants, and delegates every cell to the Tab Item atom rather than redrawing tabs locally.
Consistent
Pass
Named Tabs (plural), correctly distinguishing the container from the Tab Item atom. Three orthogonal props — Orientation × Size × Tabs Count = a complete 2 × 2 × 3 matrix with no invalid cells.
Composable
Pass
Every cell is a real Tab Item INSTANCE, so atom changes propagate automatically. Orientation and Size forward down to the nested items.
Behavior
State iOS Android Figma Property Notes
Horizontal Yes Yes Orientation=Horizontal Tabs laid out in a row with the label beside the optional icon. Medium 48px tall, Large 50px.
Vertical Yes Yes Orientation=Vertical Tabs stacked with the icon above the label, 92px tall. Used for rail-style navigation.
Tab count Yes Yes Tabs Count=2 | 3 | 4 Container width adapts to the number of tabs. Capped at 4 by design — GCash tab bars do not exceed four destinations.
5+ tabs / scrollable N/A N/A Not modelled by design. The 2–4 cap is deliberate, so horizontal overflow and scrolling do not arise.
Issues
  • Code Connect mappings not registered. The rename and container structure are settled, so registration is unblocked — but the SwiftUI / Compose mappings are not yet wired and the native component does not exist. Snippets remain a Planned API. C7 · Code Connect Linkability
  • v2.0: Component renamed TabTabs (plural) — the container is no longer confusable with the Tab Item atom. (C2)
  • v2.0: Rebuilt to 12 variants across Orientation (Vertical / Horizontal) × Size (Medium / Large) × Tabs Count (2 / 3 / 4) — a complete 2 × 2 × 3 matrix, up from the earlier count-only split. (C2)
  • v2.0: Tabs Count as a fixed variant axis confirmed intentional — GCash tab bars are capped at 2–4 destinations, so a Slot-based container is not needed here. (C2)
  • v2.0: Absence of a scrollable / overflow variant confirmed intentional — follows directly from the 2–4 cap; horizontal overflow never occurs. (C5)
  • v2.0: Composition verified — every cell is a real Tab Item INSTANCE rather than a redrawn tab, so atom changes propagate to all 12 variants. (C4)
Recommendations
  • Register Code Connect mapping to EBTabs. Wire Orientation, Size, and Tabs Count to the SwiftUI / Compose API, forwarding orientation and size down to the nested EBTabItem children. Docs
  • Rename "Tab" → "Tabs". v2.0: Applied — the container is now plural, disambiguating it from the Tab Item atom. Rename
  • Drop the tabsCount variant. v2.0: Reviewed and closed as not needed — the 2–4 cap is deliberate, so a flexible slot-based container would add complexity without covering a real case. Property
  • Add a scrollable variant. v2.0: Reviewed and closed as not needed — follows from the 2–4 cap; overflow never occurs. State
Variants
4 tabs — default
DES DEV

4 Tab Items in an equal-width flex row. 248px total width.

LabelLabelLabelLabel
Properties
Active tab
Properties
Tab count 4
Active tab Tab 1
Colors
Label #005CE5
Border #005CE5
Layout
Tab height 44px
Padding H 16px
Gap 24px
Indicator height 3px
Total width 248px
Typography
Text Style Primary/Label/Base
Font Proxima Soft Bold
Size 16px
Tracking 0.25px
Line-height 16px
Layout
Role Token
Total width (2 tabs) 124px
Total width (3 tabs) 186px
Total width (4 tabs) 248px
Per-tab width 62px (flex 1 0 0)
Gap between tabs 0 (shared border-bottom)
Shadow Depth/D4 — 0 0 8px #73819A1A
3 tabs
DES DEV

3 Tab Items in an equal-width flex row. 186px total width.

LabelLabelLabel
Properties
Active tab
Properties
Tab count 3
Active tab Tab 1
Colors
Label #005CE5
Border #005CE5
Layout
Tab height 44px
Padding H 16px
Gap 24px
Indicator height 3px
Total width 186px
Typography
Text Style Primary/Label/Base
Font Proxima Soft Bold
Size 16px
Tracking 0.25px
Line-height 16px
2 tabs
DES DEV

2 Tab Items in an equal-width flex row. 124px total width.

LabelLabel
Properties
Active tab
Properties
Tab count 2
Active tab Tab 1
Colors
Label #005CE5
Border #005CE5
Layout
Tab height 44px
Padding H 16px
Gap 24px
Indicator height 3px
Total width 124px
Typography
Text Style Primary/Label/Base
Font Proxima Soft Bold
Size 16px
Tracking 0.25px
Line-height 16px
Installation Planned API

iOS — Swift Package Manager

// In Xcode: File → Add Package Dependencies
"https://github.com/AY-Org/eb-ds-ios"

Android — Gradle (Kotlin DSL)

dependencies {
    implementation("com.eastblue.ds:tabs:1.0.0")
}
Property Mapping
Figma PropertySwiftUICompose
items items: [EBTabItem] items: List<EBTabItem>
selectedIndex @Binding selection: Int selectedIndex: Int
onSelect onSelect: (Int) -> Void onSelect: (Int) -> Unit
scrollable .scrollable(true) scrollable: Boolean
SwiftUI
ios/Components/Tabs/EBTabs.swift
Jetpack Compose
android/components/tabs/EBTabs.kt
Usage Snippets Planned API
Usage
EBTabs(
    items: [
        EBTabItem(label: "Overview", icon: .image(Image("overview"))),
        EBTabItem(label: "Details"),
        EBTabItem(label: "History")
    ],
    selection: $selectedIndex
)
EBTabs(
    items = listOf(
        EBTabItem(label = "Overview", icon = painterResource(R.drawable.overview)),
        EBTabItem(label = "Details"),
        EBTabItem(label = "History")
    ),
    selectedIndex = state,
    onSelect = { state = it }
)
Accessibility
RequirementiOSAndroid
Tab list role Automatic via TabView Automatic via TabRow (Material semantics)
Selected state announced .accessibilityAddTraits(.isSelected) on active tab selected = true in semantics
Keyboard / focus navigation iOS handles via focus traits Compose handles via focus semantics
Usage Guidelines

Do

Use 2–4 tabs for primary navigation within a screen. Tabs should represent peer sections of equal importance.

Don't

Use tabs for sequential flows (Step 1 / Step 2 / Step 3) — use a Stepper component instead.

Do

Keep tab labels short (one or two words). If labels exceed 12 characters, use icons only or switch to vertical orientation.

Don't

Nest Tabs inside Tabs — creates navigation ambiguity and accessibility issues.

Criteria Scorecard
ID Criterion Status Notes
C1 Layer Structure & Naming Ready Tab 1, Tab 2, ... container, icon-label. Semantic.
C2 Variant & Property Naming Requires Rework Component named singular "Tab"; tabsCount uses string values and shouldn't be a variant at all.
C3 Token Coverage Ready Shadow and spacing bound to tokens. Colors live on the Tab Item atom.
C4 Native Mappability Ready Maps cleanly to TabView / TabRow.
C5 Interaction State Coverage Needs Refinement Active/inactive covered via Tab Item. No scrollable pattern for 5+ tabs.
C6 Asset & Icon Quality Ready Children are Tab Item instances.
C7 Code Connect Linkability Needs Refinement Not mapped.
Variants Inventory (3 total)

After the recommended restructure these 3 variants collapse to 1 flexible container accepting a list.

tabsCountWidthNode ID
2124px18482:33259
3186px18482:33255
4248px18482:33250
1.0.0 — April 2026Major
Initial Assessment · node 18482:33249
Component assessed — 3 variants (tabsCount 2/3/4). Container composing Tab Item children. Recommended rename "Tab" → "Tabs" and dropping the count variant. Documented
Initial
Component named singular — "Tab" should be "Tabs" (plural) to disambiguate from the Tab Item atom. Open
C2 Open
tabsCount is a variant property — Should be removed; the container should accept a list of Tab Items instead of exposing a fixed count enum. Open
C2 Open
No scrollable variant — 5+ tabs have no documented overflow pattern. Open
C5 Open
Code Connect mappings — Not registered. Open
C7 Open