You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
-[ ] Run IvyFeatureTester with a positional record type and verify `DataTableBuilder.Remove()` renders remaining columns correctly
4
+
-[ ] Test with EF Core / database-backed `IQueryable` to confirm the expression tree translates to valid SQL (the default values for removed params should be excluded from the SELECT)
All Ivy documentation pages are listed on: <https://docs.ivy.app/sitemap.xml>.
2
-
Add ".md" to the end of any URL to go directly to the Markdown version of the doc.
3
-
4
1
# Introduction to the Ivy Framework for LLMs
5
2
6
3
- Ivy is a declarative full-stack UI framework that allows developers to build user interfaces using a component-based approach very similar to React.
7
-
- In Ivy you only write one application in pure C# and we don't have a BE and FE distinction.
4
+
- In Ivy, you only write one application in pure C# and we don't have a BE and FE distinction.
8
5
- UI rendering is handled by Ivy.
9
6
- When programming in Ivy you focus on building the logical structure of your application using a large set of pre-built widgets and views - you rarely need to specify any styling - Ivy just makes it look good by default.
10
7
@@ -17,6 +14,8 @@ Terminology:
17
14
18
15
A view is defined as a class that inherits from `ViewBase` and implements a `Build` method. The `Build` method returns either another view or a widget.
19
16
17
+
> WARNING: There is NO `AppBase` class. ALL views and apps inherit from `ViewBase`.
18
+
20
19
Widgets can have multiple children, but views can only return a single object (widget or view). To return multiple widgets from a view, you can use a `Fragment` use the Layout helpers. See below.
21
20
22
21
public class MyView : ViewBase
@@ -30,13 +29,43 @@ public class MyView : ViewBase
30
29
}
31
30
}
32
31
33
-
The topmost view in an Ivy application is called an [App](https://docs.ivy.app/onboarding/concepts/apps.md) and is decorated with the `[App]` attribute.
32
+
The topmost view in an Ivy application is called an [App](https://docs.ivy.app/onboarding/concepts/apps.md) and is decorated with the `[App]` attribute. The attribute uses **named parameters**:
33
+
34
+
[App(title: "Customers", icon: Icons.Rocket)]
35
+
public class CustomersApp : ViewBase
36
+
37
+
-`title` is optional — if omitted, it is derived from the class name (e.g. `CustomersApp` → "Customers").
38
+
-`icon` uses the `Icons` enum — these are Lucide icons in PascalCase (e.g. `Icons.Link`, `Icons.Settings`, `Icons.Rocket`).
39
+
40
+
An app is built into a tree of widgets. This is what's rendered to the screen.
41
+
42
+
## Application Structure
43
+
44
+
A typical Ivy project has this folder structure:
45
+
46
+
MyProject/
47
+
├── Program.cs # Entry point — configures and starts the Ivy server
48
+
├── MyProject.csproj # Project file
49
+
├── Apps/ # All app classes go here (convention)
50
+
│ ├── DashboardApp.cs
51
+
│ └── Settings/ # Subfolder namespaces become URL path segments
- Add Children: Pipe child elements using the | operator to arrange them top-to-bottom (vertical) or left-to-right (horizontal).
65
94
- Layouts can be customized with methods like .Gap(int number) to set spacing between children. Use .Left(), .Center(), or .Right() methods to control alignment.
66
95
- The number in Gap(int number) works the same as in Tailwind CSS spacing scale (e.g., 1 = 0.25rem, 2 = 0.5rem, etc.).
67
-
Layouts have a default gap of 4 (1rem). In general, you very rarely need to set the gap explicitly.
96
+
- Layouts have a default gap of 4 (1rem). Do NOT add `.Gap(4)` — it is the default and adds unnecessary noise. Only use `.Gap()` when you need a value other than 4.
97
+
-`.Padding()` is rarely needed. Layouts and pages already have appropriate padding by default. Only add `.Padding()` when you need extra inner spacing for a specific design reason.
68
98
69
99
// Basic Vertical Layout
70
100
Layout.Vertical()
@@ -84,8 +114,6 @@ Grids:
84
114
Layout.Grid()
85
115
.Columns(2)
86
116
.Rows(2)
87
-
.Gap(4)
88
-
.Padding(8)
89
117
| Text.Block("Cell 1")
90
118
| Text.Block("Cell 2")
91
119
...
@@ -103,6 +131,7 @@ The Text helper utility is used to create various semantic text elements.
103
131
- Text.P: For standard paragraphs.
104
132
- Text.Block: For block-level content (e.g., list items).
105
133
- Text.InlineCode: For displaying inline code snippets.
Size is NOT the same as Density. Size controls dimensions; Density controls visual density.
177
+
120
178
## Event Handling
121
179
122
180
new Button("Click Me")
123
181
.Primary()
124
-
.HandleClick(() => {
182
+
.OnClick(() => {
125
183
count.Set(count.Value + 1);
126
184
})
127
185
@@ -138,15 +196,19 @@ new TextInput().Default()
138
196
### UseState
139
197
140
198
var nameState = UseState("World");
141
-
var iconsState = this.UseState<Icons[]>();
199
+
var iconsState = UseState<Icons[]>();
142
200
143
201
If you don't specify a value, default(T) is used.
144
202
145
203
UseState hook returns a state object IState<T> that provides:
146
204
205
+
> WARNING: UseState returns `IState<T>`, NOT `State<T>`. There is no `State<T>` type in Ivy.
206
+
147
207
- .Value property to read the current state.
148
208
- .Set(newValue) method to update the state in UseEffect or in an event handler.
149
209
210
+
Always use immutable types (e.g. records) with `UseState` — mutable classes that are modified in-place and passed back via `.Set()` will not trigger a re-render because the reference hasn't changed. Instead, create a new instance (e.g. using `with` expressions on records) before calling `.Set()`.
- Base class is `ViewBase` (NOT `AppBase` there is no `AppBase` class)
321
+
-`Text` is a static helper - use `Text.P()`, `Text.H2()`, ...
322
+
-`UseState<T>()` returns `IState<T>`, NOT `State<T>`
323
+
- All types are in the `Ivy` namespace
324
+
-`Colors` is a flat enum (e.g. `Colors.Red`, `Colors.Blue`) we have no shade levels
325
+
-`DbContext` must never be injected directly! Always resolve `IDbContextFactory<T>` via `UseService` and create scoped instances with `CreateDbContextAsync()` inside query/mutation lambdas
0 commit comments