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

Import

component.ts
import { NeuBottomSheetComponent } from '@neural-ui/native/bottom-sheet';

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.

Plan a calmer day

Open a compact preferences sheet with a draft. Save commits it locally; Cancel or dismissal leaves the summary unchanged, and reopening starts from the saved value.

View and copy the complete example
basic.component.ts
import { Component, signal } from '@angular/core';
import { NeuButtonComponent } from '@neural-ui/native/button';
import { NeuSwitchComponent } from '@neural-ui/native/switch';
import { NeuCardComponent } from '@neural-ui/native/card';
import { NeuBottomSheetComponent } from '@neural-ui/native/bottom-sheet';
import { View, Text, ScrollView } from '@ng-native/components';

@Component({
  selector: 'app-example',
  imports: [NeuButtonComponent, NeuSwitchComponent, NeuCardComponent, NeuBottomSheetComponent, 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">Plan a calmer day</text><text class="product-caption">Preferences you can change without leaving</text></view>
    <neu-card title="Your daily digest" [description]="saved() ? 'Email delivery enabled' : 'Email delivery paused'" variant="outlined"><view class="product-section"><text>The useful parts of your workspace, together in one message.</text><view class="product-actions"><neu-button label="Notification preferences" size="sm" variant="outline" (pressed)="edit()" /></view></view></neu-card>
    <neu-bottom-sheet title="Preferences" height="auto" [(open)]="open"><view class="product-section"><text class="product-caption">Choose what reaches your inbox.</text><neu-switch label="Email updates" [(checked)]="draft" /><view class="product-actions"><neu-button label="Save changes" size="sm" (pressed)="save()" /><neu-button label="Cancel" size="sm" variant="text" (pressed)="open.set(false)" /></view></view></neu-bottom-sheet></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); }

  `,
})
export class ExampleComponent {
  readonly open = signal(false);
  readonly saved = signal(true);
  readonly draft = signal(true);
  edit() { this.draft.set(this.saved()); this.open.set(true); }
  save() { this.saved.set(this.draft()); this.open.set(false); }
}

Presentation height

Open the same sheet at auto, small, medium, large or full height.

View and copy the complete example
presentation-height.component.ts
import { Component, signal } from '@angular/core';
import { NeuButtonComponent } from '@neural-ui/native/button';
import { NeuBottomSheetComponent } from '@neural-ui/native/bottom-sheet';
import { View, Text, ScrollView } from '@ng-native/components';
import type { NeuBottomSheetHeight } from '@neural-ui/native/bottom-sheet';

@Component({
  selector: 'app-example',
  imports: [NeuButtonComponent, NeuBottomSheetComponent, View, Text, ScrollView],
  template: `
    <scroll-view class="usage-scroll" keyboardShouldPersistTaps="handled"><view class="usage-stack">
    <view class="usage-actions">@for (choice of sheetHeights; track choice) {
    <neu-button [label]="choice" size="sm" [variant]="sheetHeight() === choice ? 'solid' : 'outline'" (pressed)="sheetHeight.set(choice); heightPreview.set(true)" />
    }</view>
    <neu-bottom-sheet title="Presentation preview" [height]="sheetHeight()" [(open)]="heightPreview"><text>Use Done or the close action to return.</text><neu-button label="Done" size="sm" (pressed)="heightPreview.set(false)" /></neu-bottom-sheet>
    </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 {
  readonly sheetHeights = ['auto', 'sm', 'md', 'lg', 'full'] as const;
  readonly sheetHeight = signal<NeuBottomSheetHeight>('auto');
  readonly heightPreview = signal(false);
}
Interactive playground

Change the settings and try the result.

Device captures shown in English.

Bottom Sheet · android · native capture
AndroidNative screenshot
Bottom Sheet · ios · native capture
iOSNative screenshot

Personalization

Projected content

Inside the sheet’s scrollable body, beneath its title. Project forms, text and actions; your application owns their state.

Use native elements from @ng-native/components and public Neural Native controls. Angular styles belong to the component that declares this content.

API reference

Inputs

NameTypeDefaultBindingDescription
titlestringRequiredInputHeading for the surface, section or presentation.
dismissiblebooleantrueInputAllows user dismissal of the presentation. The application can still close it through open.
closeLabelstring'Close'InputText or accessible name used for close. It does not perform the action by itself.
heightNeuBottomSheetHeight'auto'InputSheet height: auto keeps the existing content-based height, capped at 85% of the available container. The sm, md, lg and full options occupy 35%, 50%, 75% and 100%. Fixed heights keep the header visible and scroll the body. These are selectable heights, not draggable snap points.

Models

NameTypeDefaultBindingDescription
openbooleanfalseModel · two-wayWhether the presentation or message is requested to be open. Bind a writable signal with [(open)].

Outputs

NamePayloadWhen it emits
openChangebooleanEmits the updated open value. [(open)] binds this output together with its model input.
closedvoidReports a close request; inspect the declared payload before sharing handlers across overlays.
openedvoidReports that the native presentation has opened.
dismissedvoidReports completion of native dismissal.

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 open = signal<boolean>(false);

Types and data interfaces

Use the imports in your application. The definitions below are provided for reference.

NeuBottomSheetHeight

NeuBottomSheetHeight.ts
import type { NeuBottomSheetHeight } from '@neural-ui/native/bottom-sheet';

// Public definition for reference only. Import this type; do not redeclare it.
export type NeuBottomSheetHeight = 'auto' | 'sm' | 'md' | 'lg' | 'full';