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

Import

component.ts
import { NeuSkeletonComponent } from '@neural-ui/native/skeleton';

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.

Content preview

Switch between loading placeholders and the loaded card.

View and copy the complete example
content-preview.component.ts
import { Component, signal } from '@angular/core';
import { NeuButtonComponent } from '@neural-ui/native/button';
import { NeuCardComponent } from '@neural-ui/native/card';
import { NeuSkeletonComponent } from '@neural-ui/native/skeleton';
import { View, Text, ScrollView } from '@ng-native/components';

@Component({
  selector: 'app-example',
  imports: [NeuButtonComponent, NeuCardComponent, NeuSkeletonComponent, View, Text, ScrollView],
  template: `
    <scroll-view class="usage-scroll" keyboardShouldPersistTaps="handled"><view class="usage-stack">
    <view class="usage-section">
    <neu-button [label]="loading() ? 'Show loaded content' : 'Show loading placeholders'" variant="outline" size="sm" (pressed)="loading.set(!loading())" />
    @if (loading()) {
    <view class="loading-card">
      <view class="loading-header">
        <neu-skeleton label="Loading profile photo" variant="circle" [width]="40" [height]="40" />
        <view class="loading-name">
          <neu-skeleton label="Loading author" [lines]="2" [height]="12" [gap]="8" lastLineWidth="55%" />
        </view>
      </view>
      <neu-skeleton label="Loading project image" variant="rect" [height]="112" [borderRadius]="10" />
      <neu-skeleton label="Loading project description" [lines]="3" [height]="12" [gap]="8" lastLineWidth="70%" />
    </view>
    } @else {
    <neu-card title="Design review" description="Alex Morgan · Product team" variant="outlined"><text>The onboarding flow is ready for your feedback.</text></neu-card>
    }
    </view>
    </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; }

:host { width: 100%; } .loading-card { gap: 16px; } .loading-header { flex-direction: row; align-items: center; gap: 12px; } .loading-name { flex: 1; min-width: 0; }
  `,
})
export class ExampleComponent {
  readonly loading = signal(true);
}

Without animation

Use static placeholders when motion is not needed.

View and copy the complete example
without-animation.component.ts
import { Component, signal } from '@angular/core';
import { NeuSkeletonComponent } from '@neural-ui/native/skeleton';
import { View, ScrollView } from '@ng-native/components';

@Component({
  selector: 'app-example',
  imports: [NeuSkeletonComponent, View, ScrollView],
  template: `
    <scroll-view class="usage-scroll" keyboardShouldPersistTaps="handled"><view class="usage-stack">
    <view class="usage-section">
    <neu-skeleton label="Static loading description" animation="none" [lines]="2" [height]="12" lastLineWidth="55%" />
    </view>
    </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; }

:host { width: 100%; } .loading-card { gap: 16px; } .loading-header { flex-direction: row; align-items: center; gap: 12px; } .loading-name { flex: 1; min-width: 0; }
  `,
})
export class ExampleComponent {
  readonly loading = signal(true);
}
Interactive playground

Change the settings and try the result.

Device captures shown in English.

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

API reference

Inputs

NameTypeDefaultBindingDescription
labelstring'Loading'InputHuman-readable name for the control, action or group.
linesnumber3InputNumber of text lines, clamped to 1–20. The rect and circle variants always render one shape. Nonfinite counts use three lines.
variantNeuSkeletonVariant'text'InputThe text variant renders repeated lines; rect and circle render one shape. Match the placeholder to the content that will replace it.
widthstring | number | undefinedundefinedInputWidth in layout points (number or numeric string), px, or a percentage of the parent. Unset uses 100% for text/rect and the resolved height for circle. Use equal width and height for a circle; its radius remains fully rounded. Invalid values fall back to the automatic width and the wrapper never exceeds its parent.
heightnumber | undefinedundefinedInputHeight of each line or shape in layout points. Unset uses 16 for text/rect and 40 for circle. Negative values become zero.
borderRadiusnumber8InputCorner radius in layout points for text and rect. Zero creates square corners. The circle variant always stays fully rounded.
gapnumber12InputVertical separation between text lines in layout points. Zero joins the lines; it has no visible effect on a single shape.
lastLineWidthstring | number'65%'InputWidth of the last text line, in layout points, px or a percentage of the skeleton width. Use 100% for equally long lines. Does not affect rect or circle.
animationNeuSkeletonAnimation'pulse'InputThe pulse animation gently changes opacity; none keeps the placeholder static. System reduced motion and a zero-duration theme disable movement even when pulse is selected.

Models

This component declares no two-way models.

Outputs

This component declares no public outputs.

Types and data interfaces

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

NeuSkeletonVariant

NeuSkeletonVariant.ts
import type { NeuSkeletonVariant } from '@neural-ui/native/skeleton';

// Public definition for reference only. Import this type; do not redeclare it.
export type NeuSkeletonVariant = 'text' | 'rect' | 'circle';

NeuSkeletonAnimation

NeuSkeletonAnimation.ts
import type { NeuSkeletonAnimation } from '@neural-ui/native/skeleton';

// Public definition for reference only. Import this type; do not redeclare it.
export type NeuSkeletonAnimation = 'pulse' | 'none';