Skip to content

Commit 9e4af0a

Browse files
committed
feat: dark mode support for angular
1 parent 55f2bf9 commit 9e4af0a

File tree

15 files changed

+126
-129
lines changed

15 files changed

+126
-129
lines changed

apps/demo-angular/src/app/demos/chat-demo.ts

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -64,18 +64,17 @@ export class ChatComponent {
6464
6565
This creates a smooth streaming experience! ✨`,
6666

67-
table: `Here's a comparison **table** of mobile frameworks:
67+
table: `Here's a comparison **table**:
6868
69-
| Framework | Language | Performance | Learning Curve |
69+
| Staying In | Going Out | Outdoors | Habits |
7070
|-----------|----------|-------------|----------------|
71-
| NativeScript | TypeScript | ⚡ Native | Medium |
72-
| React Native | JavaScript | 🔥 Good | Medium |
73-
| Flutter | Dart | ⚡ Native | Higher |
74-
| Ionic | TypeScript | 📱 WebView | Lower |
71+
| Energy level | Low | Medium | Medium |
72+
| Main feature | Comfort | Variety | Medium |
73+
| Snacks | Popcorn | Spontaneous | Higher |
7574
7675
### Key Takeaways:
7776
- **NativeScript** provides true native UI
78-
- Direct access to iOS/Android APIs
77+
- Direct access to native platform APIs
7978
- Use Angular, Vue, Solid, React, or Svelte!`,
8079

8180
math: `Let me show you some **mathematical expressions**:
@@ -97,11 +96,11 @@ Pretty cool, right? 🧮`,
9796

9897
hello: `# Hello! 👋
9998
100-
Nice to meet you! I'm running **natively on iOS** through NativeScript.
99+
Nice to meet you! I'm running **natively** through NativeScript.
101100
102101
## What makes this special?
103102
104-
> Unlike web-based solutions, every element you see is a *real* native iOS view.
103+
> Every element you see is a *real* native platform view.
105104
106105
### Benefits:
107106
- ⚡ Native performance
@@ -115,9 +114,9 @@ Use the **⋯** menu to explore more demos!`,
115114
@Component({
116115
selector: 'ChatDemo',
117116
template: `
118-
<GridLayout rows="auto, *, auto" class="bg-slate-100">
117+
<GridLayout rows="auto, *, auto" class="bg-slate-100 dark:bg-slate-900">
119118
<!-- Native ActionBar -->
120-
<ActionBar flat="true" class="bg-slate-50" title="AI Chat">
119+
<ActionBar flat="true" class="bg-slate-50 dark:bg-slate-900" title="AI Chat">
121120
<NavigationButton text="" android.systemIcon="ic_menu_back" (tap)="goBack()"></NavigationButton>
122121
<ActionItem ios.position="right" (tap)="clearChat()">
123122
<Image src="sys://trash" class="w-5 h-5 text-red-500"></Image>
@@ -131,7 +130,7 @@ Use the **⋯** menu to explore more demos!`,
131130
<!-- User message -->
132131
@if (message.role === 'user') {
133132
<GridLayout columns="*, auto" class="mb-3">
134-
<StackLayout col="1" class="bg-blue-600 rounded-2xl rounded-br-sm py-2 px-3 max-w-[280]">
133+
<StackLayout col="1" class="bg-blue-600 dark:bg-blue-700 rounded-2xl rounded-br-sm py-2 px-3 max-w-[280]">
135134
<Label [text]="message.content" class="text-white text-sm leading-[3]" textWrap="true"></Label>
136135
</StackLayout>
137136
</GridLayout>
@@ -141,12 +140,12 @@ Use the **⋯** menu to explore more demos!`,
141140
@if (message.role === 'assistant') {
142141
<GridLayout columns="32, *" class="mb-3">
143142
<!-- Avatar - using GridLayout for vertical centering -->
144-
<GridLayout col="0" rows="32" columns="32" class="bg-purple-600 rounded-full mr-2 h-[32] w-[32]">
143+
<GridLayout col="0" rows="32" columns="32" class="bg-purple-600 dark:bg-purple-700 rounded-full mr-2 h-[32] w-[32]">
145144
<Label text="AI" class="text-white text-xs font-bold text-center"></Label>
146145
</GridLayout>
147146
148147
<!-- Message bubble -->
149-
<StackLayout col="1" class="bg-white rounded-2xl rounded-tl-sm py-2 px-3 shadow-sm">
148+
<StackLayout col="1" class="bg-white dark:bg-slate-800 rounded-2xl rounded-tl-sm py-2 px-3 shadow-sm">
150149
<Streamdown [content]="message.content" [config]="getMessageConfig(message)"></Streamdown>
151150
</StackLayout>
152151
</GridLayout>
@@ -156,22 +155,22 @@ Use the **⋯** menu to explore more demos!`,
156155
<!-- Typing indicator -->
157156
@if (isTyping()) {
158157
<GridLayout columns="32, auto" class="mb-3">
159-
<GridLayout col="0" rows="32" columns="32" class="bg-purple-600 rounded-full mr-2 h-[32] w-[32]">
158+
<GridLayout col="0" rows="32" columns="32" class="bg-purple-600 dark:bg-purple-700 rounded-full mr-2 h-[32] w-[32]">
160159
<Label text="AI" class="text-white text-xs font-bold text-center"></Label>
161160
</GridLayout>
162-
<StackLayout col="1" class="bg-white rounded-2xl py-2 px-3 shadow-sm">
163-
<Label text="•••" class="text-slate-400 text-base"></Label>
161+
<StackLayout col="1" class="bg-white dark:bg-slate-800 rounded-2xl py-2 px-3 shadow-sm">
162+
<Label text="•••" class="text-slate-400 dark:text-slate-500 text-base"></Label>
164163
</StackLayout>
165164
</GridLayout>
166165
}
167166
</StackLayout>
168167
</ScrollView>
169168
170169
<!-- Bottom menu bar -->
171-
<GridLayout row="2" columns="*, auto" class="bg-white px-4 py-3 border-t border-slate-200">
172-
<Label col="0" text="Tap menu to explore demos" class="text-xs text-slate-400"></Label>
173-
<StackLayout col="1" #menuAnchor class="bg-slate-100 rounded-lg px-3 py-2" (tap)="showOptionsMenu($event)">
174-
<Label text="⋯ Options" class="text-sm text-slate-600 font-medium"></Label>
170+
<GridLayout row="2" columns="*, auto" class="bg-white dark:bg-slate-800 px-4 py-3 border-t border-slate-200 dark:border-slate-700">
171+
<Label col="0" text="Tap menu to explore demos" class="text-xs text-slate-400 dark:text-slate-500"></Label>
172+
<StackLayout col="1" #menuAnchor class="bg-slate-100 dark:bg-slate-700 rounded-lg px-3 py-2" (tap)="showOptionsMenu($event)">
173+
<Label text="⋯ Options" class="text-sm text-slate-600 dark:text-slate-300 font-medium"></Label>
175174
</StackLayout>
176175
</GridLayout>
177176
</GridLayout>

apps/demo-angular/src/app/demos/home-demo.ts

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,63 +11,64 @@ interface DemoItem {
1111
icon: string;
1212
route: string;
1313
color: string;
14+
darkColor: string;
1415
}
1516

1617
@Component({
1718
selector: 'HomeDemo',
1819
template: `
19-
<GridLayout rows="auto, *" class="bg-slate-50">
20+
<GridLayout rows="auto, *" class="bg-slate-50 dark:bg-slate-900">
2021
<!-- Native ActionBar -->
21-
<ActionBar flat="true" class="bg-slate-50">
22-
<Label text="Streamdown ~ NativeScript" class="text-lg font-bold text-slate-800"></Label>
22+
<ActionBar flat="true" class="bg-slate-50 dark:bg-slate-900">
23+
<Label text="Streamdown ~ NativeScript" class="text-lg font-bold text-slate-800 dark:text-slate-100"></Label>
2324
</ActionBar>
2425
2526
<!-- Content -->
2627
<ScrollView row="1">
2728
<StackLayout class="p-4 pt-6">
2829
<!-- Hero section -->
29-
<StackLayout class="bg-gradient-to-br from-blue-600 to-purple-700 rounded-2xl p-6 mb-6">
30-
<Label text="Native iOS Markdown Streaming" class="text-xl text-slate-500 font-bold text-center leading-[3]"></Label>
31-
<Label text="Real-time AI streaming with beautiful markdown rendering, powered by NativeScript." class="text-sm text-blue-300 text-center leading-[3] mt-2" textWrap="true"></Label>
30+
<StackLayout class="bg-gradient-to-br from-blue-600 to-purple-700 dark:from-blue-700 dark:to-purple-800 rounded-2xl p-6 mb-6">
31+
<Label text="Native iOS Markdown Streaming" class="text-xl text-white font-bold text-center leading-[3]"></Label>
32+
<Label text="Real-time AI streaming with beautiful markdown rendering, powered by NativeScript." class="text-sm text-blue-100 dark:text-blue-200 text-center leading-[3] mt-2" textWrap="true"></Label>
3233
</StackLayout>
3334
3435
<!-- Demo cards -->
35-
<Label text="Demos" class="text-xs font-semibold text-slate-400 uppercase tracking-wide mb-3"></Label>
36+
<Label text="Demos" class="text-xs font-semibold text-slate-400 dark:text-slate-500 uppercase tracking-wide mb-3"></Label>
3637
3738
@for (demo of demos; track demo.route) {
3839
<StackLayout class="mb-3">
39-
<GridLayout columns="48, *, auto" rows="48" class="bg-white rounded-xl p-3 shadow-sm" [nsRouterLink]="[demo.route]">
40+
<GridLayout columns="48, *, auto" rows="48" class="bg-white dark:bg-slate-800 rounded-xl p-3 shadow-sm" [nsRouterLink]="[demo.route]">
4041
<!-- Icon container - vertically centered via GridLayout -->
41-
<GridLayout col="0" rows="*" columns="*" [class]="'w-12 h-12 rounded-xl ' + demo.color">
42+
<GridLayout col="0" rows="*" columns="*" [class]="'w-12 h-12 rounded-xl ' + demo.color + ' ' + demo.darkColor">
4243
<Label [text]="demo.icon" class="text-xl text-center"></Label>
4344
</GridLayout>
4445
4546
<!-- Text - use nested GridLayout for vertical centering -->
4647
<GridLayout col="1" rows="auto, auto" class="ml-3">
47-
<Label row="0" [text]="demo.title" class="text-base font-semibold text-slate-800 leading-[3]"></Label>
48-
<Label row="1" [text]="demo.description" class="text-xs text-slate-500 leading-[3]" textWrap="true"></Label>
48+
<Label row="0" [text]="demo.title" class="text-base font-semibold text-slate-800 dark:text-slate-100 leading-[3]"></Label>
49+
<Label row="1" [text]="demo.description" class="text-xs text-slate-500 dark:text-slate-400 leading-[3]" textWrap="true"></Label>
4950
</GridLayout>
5051
5152
<!-- Arrow -->
52-
<Label col="2" text="›" class="text-2xl text-slate-300 font-light"></Label>
53+
<Label col="2" text="›" class="text-2xl text-slate-300 dark:text-slate-600 font-light"></Label>
5354
</GridLayout>
5455
</StackLayout>
5556
}
5657
5758
<!-- Features list -->
58-
<Label text="Features" class="text-xs font-semibold text-slate-400 uppercase tracking-wide mt-6 mb-3"></Label>
59+
<Label text="Features" class="text-xs font-semibold text-slate-400 dark:text-slate-500 uppercase tracking-wide mt-6 mb-3"></Label>
5960
60-
<GridLayout columns="*, *" rows="auto, auto, auto, auto, auto" class="bg-white rounded-xl p-4 shadow-sm">
61+
<GridLayout columns="*, *" rows="auto, auto, auto, auto, auto" class="bg-white dark:bg-slate-800 rounded-xl p-4 shadow-sm">
6162
@for (feature of features; track $index; let i = $index) {
6263
<GridLayout [row]="getFeatureRow(i)" [col]="getFeatureCol(i)" columns="auto, *" class="p-2">
63-
<Label col="0" text="✓" class="text-green-500 text-sm mr-2"></Label>
64-
<Label col="1" [text]="feature" class="text-sm text-slate-600 leading-[3]" textWrap="true"></Label>
64+
<Label col="0" text="✓" class="text-green-500 dark:text-green-400 text-sm mr-2"></Label>
65+
<Label col="1" [text]="feature" class="text-sm text-slate-600 dark:text-slate-300 leading-[3]" textWrap="true"></Label>
6566
</GridLayout>
6667
}
6768
</GridLayout>
6869
6970
<!-- Footer -->
70-
<Label text="Inspired by streamdown.ai • Built for NativeScript" class="text-xs text-slate-400 text-center mt-8 mb-4"></Label>
71+
<Label text="Inspired by streamdown.ai • Built for NativeScript" class="text-xs text-slate-400 dark:text-slate-500 text-center mt-8 mb-4"></Label>
7172
</StackLayout>
7273
</ScrollView>
7374
</GridLayout>
@@ -84,13 +85,15 @@ export class HomeDemo {
8485
icon: '⚡',
8586
route: '/demo',
8687
color: 'bg-green-100',
88+
darkColor: 'dark:bg-green-900',
8789
},
8890
{
8991
title: 'Chat Interface',
9092
description: 'Interactive AI chat with streaming',
9193
icon: '💬',
9294
route: '/chat',
9395
color: 'bg-purple-100',
96+
darkColor: 'dark:bg-purple-900',
9497
},
9598
];
9699

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,30 @@
1-
<GridLayout rows="auto, *, auto" class="bg-slate-50">
1+
<GridLayout rows="auto, *" class="bg-slate-50 dark:bg-slate-900">
22
<!-- Native ActionBar with navigation -->
3-
<ActionBar flat="true" class="bg-slate-50" title="Streaming Demo">
3+
<ActionBar flat="true" class="bg-slate-50 dark:bg-slate-900" title="Streaming Demo">
44
<NavigationButton text="" android.systemIcon="ic_menu_back" (tap)="goBack()"></NavigationButton>
55
<ActionItem ios.position="right" (tap)="toggleStreaming()">
66
@if (isIOS) { @if (isStreaming()) {
77
<image src="sys://stop.fill" class="w-5 h-5"></image>
88
} @else {
99
<image src="sys://play.fill" class="w-5 h-5"></image>
1010
} } @else {
11-
<label [text]="isStreaming() ? 'Stop' : 'Start'" class="text-blue-600 font-medium px-2"></label>
11+
<label [text]="isStreaming() ? 'Stop' : 'Start'" class="text-blue-600 dark:text-blue-400 font-medium px-2"></label>
1212
}
1313
</ActionItem>
1414
</ActionBar>
1515

1616
<!-- Main content area with scroll -->
1717
<GridLayout row="1" rows="auto, *, auto">
1818
<!-- Mode selector -->
19-
<GridLayout row="0" columns="*, *" class="mx-4 mt-3 bg-slate-200 rounded-lg p-1">
19+
<GridLayout row="0" columns="*, *" class="mx-4 mt-3 bg-slate-200 dark:bg-slate-800 rounded-lg p-1">
2020
<label
2121
col="0"
2222
text="Streaming"
2323
[class]="
2424
'text-center py-2 rounded-md text-sm font-medium ' +
2525
(streamingMode() === 'streaming'
26-
? 'bg-white text-slate-800 shadow-sm'
27-
: 'text-slate-500')
26+
? 'bg-white dark:bg-slate-700 text-slate-800 dark:text-slate-100 shadow-sm'
27+
: 'text-slate-500 dark:text-slate-400')
2828
"
2929
(tap)="setMode('streaming')"
3030
></label>
@@ -34,37 +34,34 @@
3434
[class]="
3535
'text-center py-2 rounded-md text-sm font-medium ' +
3636
(streamingMode() === 'static'
37-
? 'bg-white text-slate-800 shadow-sm'
38-
: 'text-slate-500')
37+
? 'bg-white dark:bg-slate-700 text-slate-800 dark:text-slate-100 shadow-sm'
38+
: 'text-slate-500 dark:text-slate-400')
3939
"
4040
(tap)="setMode('static')"
4141
></label>
4242
</GridLayout>
4343

4444
<!-- Streamdown content -->
45-
<ScrollView row="1" rowSpan="2" #scrollView class="mt-3">
46-
<StackLayout class="mx-4 mb-20 bg-white rounded-xl p-4 shadow-sm">
45+
<ScrollView row="1" #scrollView class="my-3">
46+
<StackLayout class="mx-4 bg-white dark:bg-slate-800 rounded-xl p-4 shadow-sm">
4747
<Streamdown [content]="currentContent()" [config]="config()"></Streamdown>
4848
</StackLayout>
4949
</ScrollView>
5050

5151
<!-- Stats bar - fixed at bottom of content area -->
52-
<GridLayout row="2" columns="*, *, *" class="mx-4 mb-2 bg-slate-100 rounded-lg px-3 py-2 opacity-90">
52+
<GridLayout row="2" columns="*, *, *" class="mx-4 mb-2 bg-slate-100 dark:bg-slate-800 rounded-lg px-3 py-2">
5353
<GridLayout col="0" rows="auto, auto" class="text-center">
54-
<label row="0" [text]="charCount()" class="text-sm font-semibold text-slate-700"></label>
55-
<label row="1" text="chars" class="text-[10] text-slate-400"></label>
54+
<label row="0" [text]="charCount()" class="text-sm font-semibold text-slate-700 dark:text-slate-200"></label>
55+
<label row="1" text="chars" class="text-[10] text-slate-400 dark:text-slate-500"></label>
5656
</GridLayout>
5757
<GridLayout col="1" rows="auto, auto" class="text-center">
58-
<label row="0" [text]="tokenCount()" class="text-sm font-semibold text-slate-700"></label>
59-
<label row="1" text="tokens" class="text-[10] text-slate-400"></label>
58+
<label row="0" [text]="tokenCount()" class="text-sm font-semibold text-slate-700 dark:text-slate-200"></label>
59+
<label row="1" text="tokens" class="text-[10] text-slate-400 dark:text-slate-500"></label>
6060
</GridLayout>
6161
<GridLayout col="2" rows="auto, auto" class="text-center">
62-
<label row="0" [text]="streamSpeed()" class="text-sm font-semibold text-slate-700"></label>
63-
<label row="1" text="chars/s" class="text-[10] text-slate-400"></label>
62+
<label row="0" [text]="streamSpeed()" class="text-sm font-semibold text-slate-700 dark:text-slate-200"></label>
63+
<label row="1" text="chars/s" class="text-[10] text-slate-400 dark:text-slate-500"></label>
6464
</GridLayout>
6565
</GridLayout>
6666
</GridLayout>
67-
68-
<!-- Footer -->
69-
<label row="2" text="iOS Native Rendering" class="text-slate-400 text-xs text-center my-1 border-t border-slate-100"></label>
7067
</GridLayout>

apps/demo-vue/src/components/ChatDemo.vue

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -61,18 +61,17 @@ export class ChatComponent {
6161
6262
This creates a smooth streaming experience! ✨`,
6363
64-
table: `Here's a comparison **table** of mobile frameworks:
64+
table: `Here's a comparison **table**:
6565
66-
| Framework | Language | Performance | Learning Curve |
66+
| Staying In | Going Out | Outdoors | Habits |
6767
|-----------|----------|-------------|----------------|
68-
| NativeScript | TypeScript | ⚡ Native | Medium |
69-
| React Native | JavaScript | 🔥 Good | Medium |
70-
| Flutter | Dart | ⚡ Native | Higher |
71-
| Ionic | TypeScript | 📱 WebView | Lower |
68+
| Energy level | Low | Medium | Medium |
69+
| Main feature | Comfort | Variety | Medium |
70+
| Snacks | Popcorn | Spontaneous | Higher |
7271
7372
### Key Takeaways:
7473
- **NativeScript** provides true native UI
75-
- Direct access to iOS/Android APIs
74+
- Direct access to native platform APIs
7675
- Use Angular, Vue, Solid, React, or Svelte!`,
7776
7877
math: `Let me show you some **mathematical expressions**:
@@ -94,11 +93,11 @@ Pretty cool, right? 🧮`,
9493
9594
hello: `# Hello! 👋
9695
97-
Nice to meet you! I'm running **natively on iOS** through NativeScript.
96+
Nice to meet you! I'm running **natively** through NativeScript.
9897
9998
## What makes this special?
10099
101-
> Unlike web-based solutions, every element you see is a *real* native iOS view.
100+
> Every element you see is a *real* native platform view.
102101
103102
### Benefits:
104103
- ⚡ Native performance

packages/nstreamdown/angular/components/md-blockquote.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,26 @@ import { openUrl } from '@nstudio/nstreamdown';
1212
template: `
1313
<GridLayout columns="4, *" class="my-3 pl-2">
1414
<!-- Left border -->
15-
<StackLayout col="0" class="bg-slate-300 rounded-full w-1"></StackLayout>
15+
<StackLayout col="0" class="bg-slate-300 dark:bg-slate-600 rounded-full w-1"></StackLayout>
1616
1717
<!-- Content with inline formatting -->
1818
<FlexboxLayout col="1" class="pl-3" flexWrap="wrap" alignItems="center">
1919
@for (token of displayTokens(); track $index) {
2020
@switch (token.type) {
2121
@case ('text') {
22-
<Label [text]="token.content" class="text-sm text-slate-500 italic leading-[3]" textWrap="true"></Label>
22+
<Label [text]="token.content" class="text-sm text-slate-500 dark:text-slate-400 italic leading-[3]" textWrap="true"></Label>
2323
}
2424
@case ('bold') {
25-
<Label [text]="token.content" class="text-sm text-slate-600 font-bold italic leading-[3]" textWrap="true"></Label>
25+
<Label [text]="token.content" class="text-sm text-slate-600 dark:text-slate-300 font-bold italic leading-[3]" textWrap="true"></Label>
2626
}
2727
@case ('italic') {
28-
<Label [text]="token.content" class="text-sm text-slate-500 italic leading-[3]" textWrap="true"></Label>
28+
<Label [text]="token.content" class="text-sm text-slate-500 dark:text-slate-400 italic leading-[3]" textWrap="true"></Label>
2929
}
3030
@case ('code-inline') {
31-
<Label [text]="token.content" class="text-xs font-mono bg-slate-100 text-pink-600 rounded px-1" textWrap="true"></Label>
31+
<Label [text]="token.content" class="text-xs font-mono bg-slate-100 dark:bg-slate-700 text-pink-600 dark:text-pink-400 rounded px-1" textWrap="true"></Label>
3232
}
3333
@case ('link') {
34-
<Label [text]="token.content" class="text-sm text-blue-600 italic leading-[3]" textDecoration="underline" (tap)="onLinkTap(token)" textWrap="true"></Label>
34+
<Label [text]="token.content" class="text-sm text-blue-600 dark:text-blue-400 italic leading-[3]" textDecoration="underline" (tap)="onLinkTap(token)" textWrap="true"></Label>
3535
}
3636
}
3737
}

0 commit comments

Comments
 (0)