Skip to main content
Neural Nativev0.1.0-beta.1Documentation

Import

component.ts
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
basic.component.ts
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
persistent-information.component.ts
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
projected-regions.component.ts
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);
}
Interactive playground

Change the settings and try the result.

Device captures shown in English.

Panel · android · native capture
AndroidNative screenshot
Panel · ios · native capture
iOSNative screenshot

Personalization

Import these directives together with the component and add them to Component.imports. The examples above include the complete setup.

personalization-imports.ts
import { NeuPanelHeaderDirective, NeuPanelFooterDirective } from '@neural-ui/native/panel';
Template or regionContextPurpose
[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

NameTypeDefaultBindingDescription
titlestringRequiredInputHeading for the surface, section or presentation.
collapsiblebooleantrueInputAllows the user to collapse and expand this surface.

Models

NameTypeDefaultBindingDescription
collapsedbooleanfalseModel · two-wayWhether the panel is currently collapsed. Bind a writable signal with [(collapsed)].

Outputs

NamePayloadWhen it emits
collapsedChangebooleanEmits 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.

model-fields.ts
import { signal } from '@angular/core';

// Fields inside your component class
readonly collapsed = signal<boolean>(false);