Surfaces
Panel
Show a titled content area that can be expanded or collapsed.
Import
import { NeuPanelComponent } from '@neural-ui/native/panel';Examples
Import ExampleComponent into its parent and place <app-example /> inside your application’s root neu-theme. The preview supplies the device frame and safe areas; use the root setup from Installation in your app.
A delivery with every detail
Collapse delivery details while keeping an illustrated Neural Editions order and its arrival window visible. The panel contains the recipient and delivery note; the order is illustrative and does not track a real shipment.
View and copy the complete example
import { Component, signal } from '@angular/core';
import { NeuBadgeComponent } from '@neural-ui/native/badge';
import { NeuDividerComponent } from '@neural-ui/native/divider';
import { NeuPanelComponent } from '@neural-ui/native/panel';
import { View, Text, ScrollView } from '@ng-native/components';
@Component({
selector: 'app-example',
imports: [NeuBadgeComponent, NeuDividerComponent, NeuPanelComponent, View, Text, ScrollView],
template: `
<scroll-view class="product-scroll" keyboardShouldPersistTaps="handled" [showsVerticalScrollIndicator]="true"><view class="product-stack"><view class="product-section"><text class="product-title" accessibilityRole="header">A delivery with every detail</text><text class="product-caption">Keep the summary visible and the rest close</text></view>
<view class="delivery-summary"><view class="product-row"><view class="product-copy"><text class="delivery-kicker">NEURAL EDITIONS</text></view><neu-badge label="On the way" tone="info" /></view>
<view class="product-row"><view class="edition-cover"><text class="edition-small">FIELD GUIDE</text><text class="edition-number">03</text><view class="edition-rule"></view><text class="edition-small">Ideas into practice</text></view><view class="product-copy"><text class="delivery-title">Space to create</text><text class="delivery-caption">Studio notebook · Blue edition</text><text class="delivery-order">Order NN-2048</text></view></view>
<view class="delivery-arrival"><text class="delivery-arrival-label">EXPECTED FRIDAY</text><text class="delivery-arrival-time">09:00 — 12:00</text></view></view>
<neu-panel title="Delivery details" [collapsible]="true" [(collapsed)]="collapsed"><view class="delivery-details"><view class="product-section"><text class="delivery-detail-label">RECIPIENT</text><text class="product-heading">Alex Morgan</text><text>24 Market Street</text></view><neu-divider /><view class="product-section"><text class="delivery-detail-label">DELIVERY NOTE</text><text class="product-caption">Leave with reception if nobody is available.</text></view></view></neu-panel></view></scroll-view>
`,
styles: `
.actions { gap: 12px; align-items: flex-start; } text { color: var(--neu-text, #172033); font-size: 16px; }
:host { flex: 1; flex-shrink: 1; min-height: 0; }
.product-scroll { flex: 1; flex-shrink: 1; height: 0px; min-height: 0; }
.product-stack { gap: 24px; padding-bottom: 20px; }
.product-section { gap: 12px; }
.product-row { flex-direction: row; align-items: center; gap: 12px; }
.product-copy { flex: 1; min-width: 0; gap: 4px; }
.product-title { color: var(--neu-text, #172033); font-size: 24px; line-height: 30px; font-weight: 600; }
.product-heading { color: var(--neu-text, #172033); font-size: 17px; line-height: 23px; font-weight: 600; }
.product-caption { color: var(--neu-muted, #596477); font-size: 14px; line-height: 20px; }
.product-actions { flex-direction: row; flex-wrap: wrap; align-items: center; gap: 8px; }
.product-surface { gap: 16px; padding: 16px; border-radius: 16px; background-color: var(--neu-surface, #ffffff); border-width: 1px; border-color: var(--neu-border, #a5afbf); }
.delivery-summary { gap: 20px; padding: 20px; border-radius: 20px; background-color: #f4eee4; --neu-text: #28374b; --neu-muted: #536277; }
.delivery-kicker { color: #526075; font-size: 11px; line-height: 16px; letter-spacing: 1px; font-weight: 600; }
.edition-cover { width: 100px; min-height: 142px; padding: 12px; gap: 8px; border-radius: 4px; background-color: #1748a8; }
.edition-small { color: #dce9ff; font-size: 9px; line-height: 13px; font-weight: 600; }
.edition-number { color: #ffffff; font-size: 44px; line-height: 48px; font-weight: 600; }
.edition-rule { height: 2px; background-color: #9dc8fc; }
.delivery-title { color: #28374b; font-size: 22px; line-height: 28px; font-weight: 600; }
.delivery-caption { color: #536277; font-size: 13px; line-height: 19px; }
.delivery-order { color: #536277; font-size: 11px; line-height: 16px; padding-top: 8px; }
.delivery-arrival { gap: 4px; padding-top: 16px; border-top-width: 1px; border-color: #d4cec4; }
.delivery-arrival-label { color: #536277; font-size: 10px; line-height: 16px; letter-spacing: 1px; font-weight: 600; }
.delivery-arrival-time { color: #28374b; font-size: 20px; line-height: 26px; font-weight: 600; }
.delivery-details { gap: 20px; padding: 4px; }
.delivery-detail-label { color: var(--neu-muted, #596477); font-size: 10px; line-height: 16px; letter-spacing: 1px; font-weight: 600; }
`,
})
export class ExampleComponent {
readonly collapsed = signal(false);
}Persistent information
Keep important delivery-support content visible.
View and copy the complete example
import { Component } from '@angular/core';
import { NeuPanelComponent } from '@neural-ui/native/panel';
import { View, Text, ScrollView } from '@ng-native/components';
@Component({
selector: 'app-example',
imports: [NeuPanelComponent, View, Text, ScrollView],
template: `
<scroll-view class="usage-scroll" keyboardShouldPersistTaps="handled"><view class="usage-stack">
<neu-panel title="Delivery support" [collapsible]="false"><text>Need a change? Contact your delivery team before 18:00.</text></neu-panel>
</view></scroll-view>
`,
styles: `
.actions { gap: 12px; align-items: flex-start; } text { color: var(--neu-text, #172033); font-size: 16px; }
.usage-scroll { flex: 1; }
.usage-stack { gap: 20px; padding-bottom: 20px; }
.usage-section { gap: 12px; }
.usage-heading { color: var(--neu-text, #172033); font-size: 16px; font-weight: 600; }
.usage-caption { color: var(--neu-muted, #64748b); font-size: 14px; }
.usage-row { flex-direction: row; flex-wrap: wrap; gap: 12px; align-items: center; }
.usage-actions { flex-direction: row; flex-wrap: wrap; gap: 8px; align-items: center; }
`,
})
export class ExampleComponent {
}Custom heading and footer
The custom heading keeps the panel toggle. The body and footer collapse together.
View and copy the complete example
import { Component, signal } from '@angular/core';
import { NeuButtonComponent } from '@neural-ui/native/button';
import { NeuBadgeComponent } from '@neural-ui/native/badge';
import { NeuPanelComponent } from '@neural-ui/native/panel';
import { View, Text, ScrollView } from '@ng-native/components';
import { NeuPanelHeaderDirective, NeuPanelFooterDirective } from '@neural-ui/native/panel';
@Component({
selector: 'app-example',
imports: [NeuButtonComponent, NeuBadgeComponent, NeuPanelComponent, NeuPanelHeaderDirective, NeuPanelFooterDirective, View, Text, ScrollView],
template: `
<scroll-view class="usage-scroll" keyboardShouldPersistTaps="handled"><view class="usage-stack">
<neu-panel title="Delivery details" [(collapsed)]="collapsed">
<view neuPanelHeader class="delivery-heading"><text class="usage-heading">Delivery details</text><neu-badge label="Tomorrow" tone="info" /></view>
<text>24 Market Street · 9:00–12:00</text>
<view neuPanelFooter class="delivery-actions"><neu-button label="Change delivery" size="sm" variant="text" (pressed)="changed.set(true)" /></view>
</neu-panel>
<text class="usage-caption" accessibilityLiveRegion="polite">{{ changed() ? 'Delivery change requested' : 'Review your delivery' }}</text>
</view></scroll-view>
`,
styles: `
.actions { gap: 12px; align-items: flex-start; } text { color: var(--neu-text, #172033); font-size: 16px; }
.usage-scroll { flex: 1; }
.usage-stack { gap: 20px; padding-bottom: 20px; }
.usage-section { gap: 12px; }
.usage-heading { color: var(--neu-text, #172033); font-size: 16px; font-weight: 600; }
.usage-caption { color: var(--neu-muted, #64748b); font-size: 14px; }
.usage-row { flex-direction: row; flex-wrap: wrap; gap: 12px; align-items: center; }
.usage-actions { flex-direction: row; flex-wrap: wrap; gap: 8px; align-items: center; }
.delivery-heading { gap: 6px; align-items: flex-start; } .delivery-actions { flex-direction: row; justify-content: flex-end; }
`,
})
export class ExampleComponent {
readonly collapsed = signal(false);
readonly changed = signal(false);
}Change the settings and try the result.
Device captures shown in English.


Personalization
Import these directives together with the component and add them to Component.imports. The examples above include the complete setup.
import { NeuPanelHeaderDirective, NeuPanelFooterDirective } from '@neural-ui/native/panel';| Template or region | Context | Purpose |
|---|---|---|
[neuPanelHeader] | — | Replaces the heading content. The parent keeps its toggle and uses title as its accessible name; do not nest another button here. |
ng-content | — | Unmarked content is the collapsible body. |
[neuPanelFooter] | — | Renders after the body and collapses with it. |
API reference
Inputs
| Name | Type | Default | Binding | Description |
|---|---|---|---|---|
| title | string | Required | Input | Heading for the surface, section or presentation. |
| collapsible | boolean | true | Input | Allows the user to collapse and expand this surface. |
Models
| Name | Type | Default | Binding | Description |
|---|---|---|---|---|
| collapsed | boolean | false | Model · two-way | Whether the panel is currently collapsed. Bind a writable signal with [(collapsed)]. |
Outputs
| Name | Payload | When it emits |
|---|---|---|
| collapsedChange | boolean | Emits the updated collapsed value. [(collapsed)] binds this output together with its model input. |
Model state
Bind the signal with [(modelName)] without calling it. Use modelName() to read its value.
import { signal } from '@angular/core';
// Fields inside your component class
readonly collapsed = signal<boolean>(false);