-
Notifications
You must be signed in to change notification settings - Fork 12
Expand file tree
/
Copy pathApp.cs
More file actions
133 lines (120 loc) · 3.61 KB
/
App.cs
File metadata and controls
133 lines (120 loc) · 3.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
using Microsoft.UI.Reactor;
using Microsoft.UI.Reactor.Core;
using static Microsoft.UI.Reactor.Factories;
using Microsoft.UI.Xaml;
ReactorApp.Run<ComponentsApp>("Components Demo", width: 650, height: 550
#if DEBUG
, preview: true
#endif
);
// <snippet:basic-component>
class Greeting : Component
{
public override Element Render()
{
var (name, setName) = UseState("World");
return VStack(12,
TextBlock($"Hello, {name}!").FontSize(20).Bold(),
TextBox(name, setName, placeholder: "Your name")
.Width(200)
).Padding(16);
}
}
// </snippet:basic-component>
// <snippet:props-record>
record AlertProps(string Title, string Message, string Severity = "info");
// </snippet:props-record>
// <snippet:props-component>
class Alert : Component<AlertProps>
{
public override Element Render()
{
var bg = Props.Severity switch
{
"error" => "#FDE7E9",
"warning" => "#FFF4CE",
_ => "#DFF6DD"
};
return Border(
VStack(4,
TextBlock(Props.Title).Bold(),
TextBlock(Props.Message)
).Padding(12)
).Background(bg).CornerRadius(4);
}
}
// </snippet:props-component>
// <snippet:should-update>
record ExpensiveProps(string Label, int Value);
class ExpensiveDisplay : Component<ExpensiveProps>
{
protected override bool ShouldUpdate(
ExpensiveProps? oldProps, ExpensiveProps? newProps)
{
// Only re-render when the Value changes, ignore Label
return oldProps?.Value != newProps?.Value;
}
public override Element Render()
{
return TextBlock($"Value: {Props.Value}").FontSize(18).Bold();
}
}
// </snippet:should-update>
// <snippet:function-component>
class FunctionComponentDemo : Component
{
public override Element Render()
{
return VStack(12,
SubHeading("Function components"),
// Memo: render once + own state changes (the common case).
Memo(ctx =>
{
var (on, setOn) = ctx.UseState(false);
return HStack(8,
ToggleSwitch(on, setOn),
TextBlock(on ? "Active" : "Inactive")
);
}),
// Memo with a dep: skip re-render when deps haven't changed.
Memo(ctx =>
{
return TextBlock("I only re-render when deps change")
.Opacity(0.6);
}, "stable-dep")
).Padding(16);
}
}
// </snippet:function-component>
// <snippet:factory-helpers>
static class Components
{
public static ComponentElement Alert(string title, string message,
string severity = "info") =>
Component<global::Alert, AlertProps>(new(title, message, severity));
}
// </snippet:factory-helpers>
// <snippet:composition>
class ComponentsApp : Component
{
public override Element Render()
{
var (count, setCount) = UseState(0);
return ScrollView(
VStack(16,
Heading("Component Patterns"),
Component<Greeting>(),
Component<Alert, AlertProps>(new("Success", "It works!")),
Component<Alert, AlertProps>(new("Oops", "Something broke",
"error")),
HStack(8,
Button("+1", () => setCount(count + 1)),
Component<ExpensiveDisplay, ExpensiveProps>(
new("Counter", count))
),
Component<FunctionComponentDemo>()
).Padding(24)
);
}
}
// </snippet:composition>