Skip to content
Merged
361 changes: 358 additions & 3 deletions docs/COMPONENTS.md

Large diffs are not rendered by default.

20 changes: 16 additions & 4 deletions docs/COMPONENTS_ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ Icons: `python scripts/generate-icons.py` regenerates `Icon.cs` from the ShellIc
| Component | Priority | Dependencies | ShellUI Ref | Notes |
|-----------|----------|--------------|-------------|-------|
| **avatar** ✅ | P5.1 | shell, icon | Avatar | Done 2026-09-27 |
| **table** | P5.2 | table-header, table-body, table-row, table-cell, table-head | Table | Data table |
| **table** ✅ | P5.2 | shell | Table | Done 2026-10-05 — one template (Table, TableHeader, TableRow, TableHead, TableCell); hover, selection, caption, sideways scroll |
| **empty-state** ✅ | P5.3 | shell, icon | EmptyState | Done 2026-10-04 — icon tile, title, description, action row, optional dashed border |
| **callout** ✅ | P5.4 | shell, icon | Callout | Done 2026-10-04 — Info / Warning / Danger / Tip / Default, tinted background |
| **pagination** ✅ | P5.5 | shell, icon | Pagination | Done 2026-10-04 — previous/next, sibling window, ellipses |
Expand All @@ -190,9 +190,9 @@ Icons: `python scripts/generate-icons.py` regenerates `Icon.cs` from the ShellIc
### P6 — Lower (Advanced)
| Component | Priority | Dependencies | ShellUI Ref | Notes |
|-----------|----------|--------------|-------------|-------|
| **context-menu** | P6.1 | context-menu-trigger, context-menu-content, context-menu-option | ContextMenu | Right-click / long-press menu |
| **carousel** | P6.2 | carousel-content, carousel-item, carousel-previous, carousel-next, carousel-dots | Carousel | Image/content carousel |
| **stepper** | P6.3 | stepper-list, stepper-step, stepper-content | Stepper | Step wizard |
| **context-menu** ✅ | P6.1 | shell, icon, element-extensions | ContextMenu | Done 2026-10-05 — one template; opens at the pointer on right-click, under the trigger on long-press |
| **carousel** ✅ | P6.2 | shell, icon | Carousel | Done 2026-10-05 — one template; swipe, arrows, dots, loop, auto-play |
| **stepper** ✅ | P6.3 | shell, icon, button | Stepper | Done 2026-10-05 — one template (Stepper + StepperStep) with built-in navigation |
| **resizable** | P6.4 | — | Resizable | Resizable panels |
| **navbar** | P6.5 | nav-trigger, nav-content, nav-list, nav-item | Navbar | Collapsible nav bar |
| **sidebar** | P6.6 | — | Sidebar | App sidebar layout |
Expand All @@ -207,6 +207,18 @@ Icons: `python scripts/generate-icons.py` regenerates `Icon.cs` from the ShellIc
| file-upload | P7 | File picker |
| input-otp ✅ | P7 | Done 2026-10-04 — slots over one hidden field (paste / autofill / numeric keyboard) |
| date-range-picker | P7 | Date range selection |
| toggle-group ✅ | — | Done 2026-10-05 — single or multiple selection, Default / Outline |
| number-input ✅ | — | Done 2026-10-05 — − / + buttons, min / max clamp, decimal value |
| tag-input ✅ | — | Done 2026-10-05 — chips with remove, Enter / comma / semicolon to commit |
| kbd ✅ | — | Done 2026-10-05 |
| stat-card ✅ | — | Done 2026-10-05 — title, value, trend pill, description, icon |
| timeline ✅ | — | Done 2026-10-05 — dot or icon markers joined by a line |
| multi-select ✅ | — | Done 2026-10-05 — searchable, chips in the trigger, panel stays open while picking |
| tree-view ✅ | — | Done 2026-10-05 — nested items, expand / collapse, selection |
| copy-button ✅ | P7 | Done 2026-10-05 — clipboard copy with a check confirmation |
| link-card ✅ | — | Done 2026-10-05 — tappable card that can open a URL |
| aspect-ratio ✅ | — | Done 2026-10-05 |
| wrap-layout ✅ | — | Done 2026-10-05 — wrapping layout used by tag-input and the demo's button rows |
| theme-toggle | P7 | Already in demo; consider as component |
| copy-button | P7 | Copy to clipboard |
| toggle | P7 | Toggle button (vs Switch) |
Expand Down
53 changes: 45 additions & 8 deletions docs/DEVELOPMENT_PLAN.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,8 @@ Short-lived sub-branches (`feat/<phase>/<slice>`) cut off the phase branch and m
into it, not directly into `main`.

```
main ← Phase 1a merged (2026-07-05), Phase 1b merged (2026-08-29 via PR #2)
└─ feat/p3-navigation-layout ← Phase 1c (active) — MAUI P3 tier (tabs, accordion, …)
└─ feat/p4-overlay-portal ← Phase 1d (queued after 1c) — portal rewrite + shadcn-style controls
main ← Phase 1a (2026-07-05), 1b (2026-08-29, PR #2), 1c + 1d (2026-10-05, PR #3) merged
└─ feat/p5-p6-components ← Phase 1e (active) — MAUI P5/P6 tier (table, context menu, carousel, stepper, …)
└─ feat/avalonia-implementation ← Phase 2 (planned) — Avalonia templates + reference impl
└─ feat/winui ← Phase 3 (conditional)
```
Expand All @@ -36,8 +35,8 @@ main ← Phase 1a merged (2026-07-05), Phase 1b merged (2026-08-29 via PR #2)

| Branch | Base | Status | Purpose |
|--------|------|--------|---------|
| `main` | — | Phase 1a + 1b merged | 44 platform-keyed components, `SupportsPlatform` registry, xUnit 199/199, sizing + token contracts locked |
| `feat/p3-navigation-layout` | `main` | **Next** | Phase 1c — MAUI P3 (tabs, accordion, collapsible, breadcrumb, scroll-area, skeleton) |
| `main` | — | Phase 1a–1d merged | 76 platform-keyed components, theme tokens, overlay portal, xUnit 408/408 |
| `feat/p5-p6-components` | `main` | **Active** | Phase 1e — MAUI P5/P6 (table, context-menu, carousel, stepper; 80 components, xUnit 428/428) |

---

Expand Down Expand Up @@ -240,7 +239,7 @@ public static class ButtonTemplate

---

## Phase 1c — `feat/p3-navigation-layout` (**in review**)
## Phase 1c — `feat/p3-navigation-layout` (**merged 2026-10-05 via [PR #3](https://github.com/shellui-dev/shellui-native/pull/3)**)

Finish MAUI's component vocabulary through P3 before opening the cross-platform front.
Rationale: Phase 2 (Avalonia) turns every new MAUI component into two components to
Expand Down Expand Up @@ -317,7 +316,7 @@ nullable `Date`/`Time` + non-generic `ItemsSource` adaptations. Proper fixes →

---

## Phase 1d — `feat/p4-overlay-portal` (queued after Phase 1c)
## Phase 1d — overlay portal (**merged 2026-10-05 with Phase 1c in PR #3**; the separate `feat/p4-overlay-portal` branch was never cut)

Surface polish pass driven by live testing on Windows 2026-08-30. Two distinct problems
that both need architectural fixes rather than sizing tweaks.
Expand Down Expand Up @@ -380,7 +379,45 @@ Date/Time pickers inside a themed border with the native frame stripped.

---

## Phase 2 — `feat/avalonia-implementation` (queued after Phase 1d)
## Phase 1e — `feat/p5-p6-components` (active)

The remaining MAUI data-display and advanced tiers, built demo-first like Phase 1d.

### Deliverables

- [x] `table` — header, rows with hover / selection / tap, caption, sideways scroll below a minimum width
- [x] `context-menu` — opens at the pointer on right-click; long-press on touch
- [x] `carousel` — swipe, arrows, dots, loop, auto-play
- [x] `stepper` — numbered steps with completed / active states and built-in navigation
- [x] Android pass for the four above plus combobox, time picker, callout and back-to-close
(2026-10-05, Pixel 7 / API 34, light and dark): fixed popup top padding, context-menu long-press
and toast offset
- [x] `toggle-group`, `number-input`, `tag-input`, `kbd`, `stat-card`, `timeline`, `wrap-layout`
(Windows only so far)
- [x] Icon generator converts arcs to Bezier curves — MAUI on Windows failed to draw the small
arcs in `activity`, which crashed the app
- [x] Demo shows one category at a time (a single page of every component exceeded WinUI's
layout-pass limit; see COMPONENTS.md, "Long pages on Windows")
- [x] Android pass for the second batch (2026-10-05): fixed the overlay layer for a Grid page root
and the tag-input keyboard / height
- [x] `multi-select`, `tree-view`, `copy-button`, `link-card`, `aspect-ratio` — run on Windows and
Android
- [ ] iOS / Mac Catalyst pass for everything
- [ ] Escape closes the overlay on top on Mac Catalyst
- [ ] `resizable`, `navbar`, `sidebar` (P6.4–P6.6)

Each family ships as one template (e.g. `table` holds Table, TableHeader, TableRow, TableHead
and TableCell) rather than one template per part.

### Exit criteria

1. Every new component clicked through in `MAUI.Demo` on Windows and on an Android device
2. `dotnet build` clean for the Windows and Android targets, `dotnet test` green
3. Docs and roadmap updated

---

## Phase 2 — `feat/avalonia-implementation` (queued after Phase 1e)

Cross-desktop (Windows + macOS + Linux) from one XAML codebase.

Expand Down
33 changes: 33 additions & 0 deletions examples/MAUI.Demo/Components/UI/AspectRatio.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
namespace MAUI.Demo.Components.UI;

// Keeps its content at a fixed width / height ratio: the height follows the width.
// <ui:AspectRatio Ratio="1.7778">
// <Image Source="cover.jpg" Aspect="AspectFill" />
// </ui:AspectRatio>
public partial class AspectRatio : ContentView
{
// Width divided by height. 16:9 is 1.7778, 4:3 is 1.3333, a square is 1.
public static readonly BindableProperty RatioProperty =
BindableProperty.Create(nameof(Ratio), typeof(double), typeof(AspectRatio), 16d / 9d,
propertyChanged: (b, o, n) => ((AspectRatio)b).Fit());

public double Ratio
{
get => (double)GetValue(RatioProperty);
set => SetValue(RatioProperty, value);
}

public AspectRatio()
{
IsClippedToBounds = true;
SizeChanged += (_, _) => Fit();
}

private void Fit()
{
if (Width <= 0 || Ratio <= 0) return;
var height = Width / Ratio;
// Only when it actually changes: setting it again would ask for another layout pass.
if (Math.Abs(HeightRequest - height) > 0.5) HeightRequest = height;
}
}
Loading
Loading