- Getting Started
- Architecture
- The Basics
- Digging Deeper
-
EDGE Components
- Introduction
- Activity Indicator
- Badge
- Bottom Navigation
- Bottom Sheet
- Button
- Button Group
- Canvas
- Carousel
- Checkbox
- Chip
- Column
- Divider
- Gesture Area
- Icon
- Image
- Lazy Grid
- Layout & Styling
- List
- Menus
- Modal
- Pressable
- Progress Bar
- Radio Group
- Refreshable
- Row
- Scroll View
- Select
- Shapes
- Side Navigation
- Slider
- Spacer
- Stack
- Tab Row
- Text
- Text Input
- Toggle
- Top Bar
- Virtual List
- Web View
- Plugins
- Testing
- Publishing Your App
List
Get the Jump app
You'll need the free Jump app to preview this page on your device. Install it, then scan the code again.
Overview#
A virtualized list container. On iOS, renders as a SwiftUI List with native pull-to-refresh and trailing
swipe-to-delete. On Android, renders as a LazyColumn / LazyRow.
Pair with <native:list-item> for Material3 list rows, or use any EDGE element as a child.
<native:list separator on-refresh="refresh" on-end-reached="loadMore"> @foreach($contacts as $contact) <native:list-item headline="{{ $contact->name }}" supporting="{{ $contact->email }}" leadingMonogram="{{ $contact->initials }}" trailingIcon="forward" @press="openContact({{ $contact->id }})" /> @endforeach</native:list>
Props#
horizontal- Lay out children horizontally instead of vertically (optional, boolean, default:false)shows-indicators- Show scroll indicators (optional, boolean, default:false) [iOS]separator- Render dividers between rows (optional, boolean, default:false)plain- Force a flat, ungrouped list. By default a list containing<native:list-section>children adopts the inset-grouped style (rounded cards — iOS.insetGrouped, grouped cards on Android);plainkeeps flat rows with plain section headers instead (optional, boolean, default:false)on-refresh- Component method called on pull-to-refresh (optional, string) [iOS]on-end-reached- Component method called when the user nears the end of the list (optional, string)
Children#
Accepts any EDGE elements as children. <native:list-item> is the canonical child for Material3-style rows.
List Item#
A pre-styled Material3 row with a headline, optional supporting + overline text, and configurable leading + trailing content slots.
<native:list-item headline="Inbox" supporting="42 unread" leadingIcon="email" trailingIcon="forward" @press="openInbox"/>
Text props#
headline- Primary text (required, string)supporting- Secondary text rendered below the headline (optional, string)overline- Small caption rendered above the headline (optional, string)
Leading slot (mutually exclusive)#
leadingIcon- Icon name rendered as a leading icon. Pair withleadingIconIos/leadingIconAndroidto override the icon per platformleadingAvatar- URL of a circular avatar imageleadingMonogram- 1-2 character monogram (combine withleadingMonogramColor)leadingMonogramColor- Hex color for monogram backgroundleadingImage- URL of a square image with a small radiusleadingCheckbox- Boolean value for a leading checkbox. Interactive whenon-leading-changeis set — tapping the box fires your handler with the new value (the row's own@pressstill handles taps elsewhere on the row); without a handler it renders as a static state glyphleadingRadio- Boolean value for a leading radio button. Interactive whenon-leading-changeis set; static glyph otherwise
Trailing slot (mutually exclusive)#
trailingIcon- Icon name rendered as a trailing icon. Pair withtrailingIconIos/trailingIconAndroidto override the icon per platformtrailingText- Trailing text labeltrailingCheckbox- Boolean value for a trailing checkbox. Interactive whenon-trailing-changeis set; static glyph otherwisetrailingSwitch- Boolean value for a trailing switch [Android]trailingIconButton- Icon name for a tappable trailing buttontrailing-a11y-label- Accessibility label for the trailing icon button (recommended whenevertrailingIconButtonis set). See Accessibilitytrailing-menu- Attach a tap-to-open dropdown to the row's trailing edge. When set without an explicit trailing slot, anellipsisicon button is auto-created as the anchor. See Menus
Independent of the mutually-exclusive slot above, a row can also show a stack of small status icons:
trailing-badges- An array of small status badges drawn right-aligned, so several can show at once (e.g. a flag and a pin). Each badge is['icon' => ..., 'ios' => ..., 'android' => ..., 'color' => 'red-500'], whereiconis a shared icon name,ios/androidoverride it per platform, andcolortakes any color value.
Color overrides#
All color props accept the full color grammar — hex (including
#RRGGBBAA alpha), Tailwind palette names, and /N opacity modifiers (red-300/20).
headlineColor,supportingColor,overlineColor- Colors for the text stylescontainerColor- Row background colorleadingIconColor,trailingIconColor,trailingTextColor- Colors for the slot contentleadingIconBgColor- Background color of the leading icon's circle
State#
disabled- Disable the row (optional, boolean, default:false)tonalElevation- Tonal elevation in dp [Android]shadowElevation- Shadow elevation in dp [Android]
Events#
-
@press/@longPress- Standard press handlers on the row -
on-swipe-delete- Shortcut for a single destructive trailing swipe. For anything richer, usetrailing-actionsbelow. -
on-leading-change/on-trailing-change- Component method called when the leading/trailing checkbox or radio is toggled, receiving the new value. Without a handler the control renders as a static state glyph.
onTrailingPress() fires on both platforms when the trailing icon button is tapped. The trailing switch is
interactive on [Android] only.
Swipe actions#
Configure swipe actions on either edge with leading-actions and trailing-actions — each an array of action
definitions the user reveals by swiping the row. Each action is an array:
method- Component method to call when the action is tapped (required)label- The action's textios/android- The action icon, resolved per platform (oriconfor a shared name)tint- Background color as a hex stringrole- Set todestructiveto render in the platform's delete style (trailing only)
Swipe actions only work on rows that are direct children of <native:list> (or a <native:list-section>) —
they are attached by the list renderer, so a standalone <native:list-item> silently ignores them.
<native:list> @foreach ($emails as $email) <native:list-item :headline="$email->subject" :leading-actions="[ ['method' => 'toggleRead('.$email->id.')', 'label' => 'Read', 'ios' => 'envelope.open', 'android' => 'mark_email_read', 'tint' => '#3B82F6'], ]" :trailing-actions="[ ['method' => 'flag('.$email->id.')', 'label' => 'Flag', 'ios' => 'flag', 'android' => 'flag', 'tint' => '#F97316'], ['method' => 'delete('.$email->id.')', 'label' => 'Delete', 'ios' => 'trash', 'android' => 'delete', 'role' => 'destructive'], ]" /> @endforeach</native:list>
List Section#
Group rows under a header (and optional footer) with <native:list-section> — a SwiftUI Section on iOS, a
sticky-header group on Android. Place <native:list-item> children inside; a section on its own renders nothing.
A list that contains sections automatically adopts the inset-grouped style (rounded cards); pass plain to the
list to keep flat rows with plain section headers instead.
<native:list> <native:list-section header="Fruits" footer="2 items"> <native:list-item headline="Apple" /> <native:list-item headline="Banana" /> </native:list-section> <native:list-section header="Vegetables"> <native:list-item headline="Carrot" /> </native:list-section></native:list>
header- Section header textfooter- Optional footer text below the section
use Nativephp\NativeUi\Elements\ListSection; ListSection::make('Fruits', ListItem::make('Apple'))->footer('1 item');
ListSection methods#
make(string $header = '', Element ...$children)- Create a section with a header and rowsheader(string $text)- Set the section header textfooter(string $text)- Set the optional footer text
Examples#
Settings menu#
<native:list separator> <native:list-item headline="Profile" leadingIcon="person" trailingIcon="forward" @press="openProfile" /> <native:list-item headline="Notifications" leadingIcon="notifications" trailingIcon="forward" @press="openNotifications" /> <native:list-item headline="Privacy" leadingIcon="lock" trailingIcon="forward" @press="openPrivacy" /> <native:list-item headline="Help" leadingIcon="help" trailingIcon="forward" @press="openHelp" /></native:list>
Swipe-to-delete with pull-to-refresh#
The checkbox, swipe, and row press are three independent targets on one row: tapping the box fires
on-leading-change, swiping left fires on-swipe-delete, tapping anywhere else fires @press.
<native:list separator on-refresh="refreshTasks"> @foreach($tasks as $task) <native:list-item headline="{{ $task->title }}" supporting="{{ $task->due }}" leadingCheckbox="{{ $task->done }}" on-leading-change="toggleTask({{ $task->id }})" trailingIcon="forward" on-swipe-delete="deleteTask({{ $task->id }})" @press="openTask({{ $task->id }})" /> @endforeach</native:list>
Note
Pull-to-refresh needs to own the pull gesture, so it only fires when the list is the screen's scrolling container — inside another scroll view (like this docs page) the outer container wins the pull. Swipe and checkbox work inline; run the refresh on a dedicated screen.
Infinite scroll#
loadMore() is a method on your component that fetches the next page and appends it to the collection the loop
renders — in a real app the loop is @foreach($posts as $post) over your paginated results. The fixed range()
here just gives the demo enough rows to scroll before the end-reached trigger fires.
<native:list on-end-reached="loadMore"> @foreach (range(1, 15) as $i) <native:list-item headline="Post {{ $i }}" supporting="Keep scrolling — loadMore() fires near the end" /> @endforeach</native:list>
Element#
use Nativephp\NativeUi\Elements\NativeList;use Nativephp\NativeUi\Elements\ListItem; NativeList::make( ListItem::make('Profile')->leadingIcon('person')->trailingIcon('forward'), ListItem::make('Settings')->leadingIcon('settings')->trailingIcon('forward'),) ->separator() ->onRefresh('refresh') ->onEndReached('loadMore');
NativeList methods#
make(Element ...$children)- Create a list with childrenhorizontal(bool $value = true)- Horizontal layoutshowsIndicators(bool $value = true)- Show scroll indicatorsseparator(bool $value = true)- Render dividers between rowsonRefresh(string $method)- Pull-to-refresh handleronEndReached(string $method)- End-reached handler
ListItem methods#
Text:
make(string $headline = ''),supporting(string $text),overline(string $text)
Leading slot:
leadingIcon(?string $name = null, IosSymbol|string|null $ios = null, AndroidSymbol|string|null $android = null)leadingAvatar(string $url)leadingMonogram(string $initials, ?string $color = null)leadingImage(string $url)leadingCheckbox(bool $checked = false)leadingRadio(bool $selected = false)
Trailing slot:
trailingIcon(?string $name = null, IosSymbol|string|null $ios = null, AndroidSymbol|string|null $android = null)trailingText(string $text)trailingCheckbox(bool $checked = false)trailingSwitch(bool $checked = false)trailingIconButton(?string $name = null, IosSymbol|string|null $ios = null, AndroidSymbol|string|null $android = null)trailingA11yLabel(string $label)- Accessibility label for the trailing icon button
Swipe actions & badges:
leadingActions(array $actions),trailingActions(array $actions)- Arrays of swipe-action definitions (method,label,ios/android,tint, androlefor trailing)trailingBadges(array $badges)- Stacked right-aligned status icons; each badge is['icon' => ..., 'ios' => ..., 'android' => ..., 'color' => '#hex']
Styling:
headlineColor,supportingColor,overlineColor,containerColor,leadingIconColor,leadingIconBackgroundColor,trailingIconColor,trailingTextColor(all(string $color))tonalElevation(float $dp),shadowElevation(float $dp)
Callbacks:
onLeadingChange(string $method),onTrailingChange(string $method),onTrailingPress(string $method),onSwipeDelete(string $method)disabled(bool $disabled = true)
in no time