diff --git a/Dock.slnx b/Dock.slnx
index 3466da765..de52a95c2 100644
--- a/Dock.slnx
+++ b/Dock.slnx
@@ -49,6 +49,7 @@
+
diff --git a/samples/DockFigmaSample/App.axaml b/samples/DockFigmaSample/App.axaml
new file mode 100644
index 000000000..6362c15f2
--- /dev/null
+++ b/samples/DockFigmaSample/App.axaml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/DockFigmaSample/App.axaml.cs b/samples/DockFigmaSample/App.axaml.cs
new file mode 100644
index 000000000..91c46c21e
--- /dev/null
+++ b/samples/DockFigmaSample/App.axaml.cs
@@ -0,0 +1,61 @@
+using Avalonia;
+using Avalonia.Controls.ApplicationLifetimes;
+using Avalonia.Markup.Xaml;
+using DockFigmaSample.ViewModels;
+using DockFigmaSample.ViewModels.Documents;
+using DockFigmaSample.ViewModels.Tools;
+using DockFigmaSample.Views;
+using DockFigmaSample.Views.Documents;
+using DockFigmaSample.Views.Tools;
+using ReactiveUI;
+using Splat;
+
+namespace DockFigmaSample;
+
+public class App : Application
+{
+ public override void Initialize()
+ {
+ AvaloniaXamlLoader.Load(this);
+ RegisterViews();
+ }
+
+ private static void RegisterViews()
+ {
+ Locator.CurrentMutable.Register>(() => new MainWindow());
+ Locator.CurrentMutable.Register>(() => new HomeView());
+ Locator.CurrentMutable.Register>(() => new WorkspaceView());
+
+ Locator.CurrentMutable.Register>(() => new CanvasDocumentView());
+ Locator.CurrentMutable.Register>(() => new DesignCanvasView());
+ Locator.CurrentMutable.Register>(() => new PrototypeCanvasView());
+ Locator.CurrentMutable.Register>(() => new InspectCanvasView());
+
+ Locator.CurrentMutable.Register>(() => new ToolbarToolView());
+ Locator.CurrentMutable.Register>(() => new LayersToolView());
+ Locator.CurrentMutable.Register>(() => new AssetsToolView());
+ Locator.CurrentMutable.Register>(() => new InspectorToolView());
+ Locator.CurrentMutable.Register>(() => new InspectorDesignView());
+ Locator.CurrentMutable.Register>(() => new InspectorPrototypeView());
+ Locator.CurrentMutable.Register>(() => new InspectorInspectView());
+ Locator.CurrentMutable.Register>(() => new CommentsToolView());
+ }
+
+ public override void OnFrameworkInitializationCompleted()
+ {
+ var vm = new MainWindowViewModel();
+
+ if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
+ {
+ desktop.MainWindow = new MainWindow
+ {
+ DataContext = vm
+ };
+ }
+
+ base.OnFrameworkInitializationCompleted();
+#if DEBUG
+ this.AttachDevTools();
+#endif
+ }
+}
diff --git a/samples/DockFigmaSample/Converters/EnumEqualsConverter.cs b/samples/DockFigmaSample/Converters/EnumEqualsConverter.cs
new file mode 100644
index 000000000..8c8589889
--- /dev/null
+++ b/samples/DockFigmaSample/Converters/EnumEqualsConverter.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Globalization;
+using Avalonia;
+using Avalonia.Data.Converters;
+
+namespace DockFigmaSample.Converters;
+
+public class EnumEqualsConverter : IValueConverter
+{
+ public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
+ {
+ if (value is null || parameter is null)
+ {
+ return false;
+ }
+
+ return value.Equals(parameter);
+ }
+
+ public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
+ {
+ if (value is true && parameter is not null)
+ {
+ return parameter;
+ }
+
+ return AvaloniaProperty.UnsetValue;
+ }
+}
diff --git a/samples/DockFigmaSample/DockFigmaSample.csproj b/samples/DockFigmaSample/DockFigmaSample.csproj
new file mode 100644
index 000000000..624a26718
--- /dev/null
+++ b/samples/DockFigmaSample/DockFigmaSample.csproj
@@ -0,0 +1,25 @@
+
+
+ net10.0
+ WinExe
+ false
+ false
+ enable
+ OnlyProperties
+ true
+ $(BaseIntermediateOutputPath)\GeneratedFiles
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/DockFigmaSample/Models/AssetSwatch.cs b/samples/DockFigmaSample/Models/AssetSwatch.cs
new file mode 100644
index 000000000..8686c713a
--- /dev/null
+++ b/samples/DockFigmaSample/Models/AssetSwatch.cs
@@ -0,0 +1,17 @@
+using Avalonia.Media;
+
+namespace DockFigmaSample.Models;
+
+public class AssetSwatch
+{
+ public AssetSwatch(string name, Color color)
+ {
+ Name = name;
+ Brush = new SolidColorBrush(color);
+ Hex = $"#{color.R:X2}{color.G:X2}{color.B:X2}";
+ }
+
+ public string Name { get; }
+ public IBrush Brush { get; }
+ public string Hex { get; }
+}
diff --git a/samples/DockFigmaSample/Models/CommentItem.cs b/samples/DockFigmaSample/Models/CommentItem.cs
new file mode 100644
index 000000000..5b3d5f8bb
--- /dev/null
+++ b/samples/DockFigmaSample/Models/CommentItem.cs
@@ -0,0 +1,42 @@
+using System;
+
+namespace DockFigmaSample.Models;
+
+public class CommentItem
+{
+ public CommentItem(string author, string body, string time)
+ {
+ Author = author;
+ Body = body;
+ Time = time;
+ Initials = GetInitials(author);
+ }
+
+ public string Author { get; }
+ public string Body { get; }
+ public string Time { get; }
+ public string Initials { get; }
+
+ private static string GetInitials(string author)
+ {
+ if (string.IsNullOrWhiteSpace(author))
+ {
+ return "?";
+ }
+
+ var parts = author.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
+ if (parts.Length == 0)
+ {
+ return "?";
+ }
+
+ if (parts.Length == 1)
+ {
+ return parts[0].Substring(0, 1).ToUpperInvariant();
+ }
+
+ var first = parts[0].Substring(0, 1).ToUpperInvariant();
+ var last = parts[^1].Substring(0, 1).ToUpperInvariant();
+ return first + last;
+ }
+}
diff --git a/samples/DockFigmaSample/Models/ComponentItem.cs b/samples/DockFigmaSample/Models/ComponentItem.cs
new file mode 100644
index 000000000..eea11bf96
--- /dev/null
+++ b/samples/DockFigmaSample/Models/ComponentItem.cs
@@ -0,0 +1,13 @@
+namespace DockFigmaSample.Models;
+
+public class ComponentItem
+{
+ public ComponentItem(string name, string description)
+ {
+ Name = name;
+ Description = description;
+ }
+
+ public string Name { get; }
+ public string Description { get; }
+}
diff --git a/samples/DockFigmaSample/Models/InspectSpecItem.cs b/samples/DockFigmaSample/Models/InspectSpecItem.cs
new file mode 100644
index 000000000..8bcef148b
--- /dev/null
+++ b/samples/DockFigmaSample/Models/InspectSpecItem.cs
@@ -0,0 +1,13 @@
+namespace DockFigmaSample.Models;
+
+public class InspectSpecItem
+{
+ public InspectSpecItem(string label, string value)
+ {
+ Label = label;
+ Value = value;
+ }
+
+ public string Label { get; }
+ public string Value { get; }
+}
diff --git a/samples/DockFigmaSample/Models/LayerItem.cs b/samples/DockFigmaSample/Models/LayerItem.cs
new file mode 100644
index 000000000..126f4adf9
--- /dev/null
+++ b/samples/DockFigmaSample/Models/LayerItem.cs
@@ -0,0 +1,21 @@
+using Avalonia;
+
+namespace DockFigmaSample.Models;
+
+public class LayerItem
+{
+ public LayerItem(string name, string type, int depth, bool isVisible = true, bool isLocked = false)
+ {
+ Name = name;
+ Type = type;
+ IsVisible = isVisible;
+ IsLocked = isLocked;
+ Indent = new Thickness(8 + depth * 16, 2, 8, 2);
+ }
+
+ public string Name { get; }
+ public string Type { get; }
+ public bool IsVisible { get; }
+ public bool IsLocked { get; }
+ public Thickness Indent { get; }
+}
diff --git a/samples/DockFigmaSample/Models/PrototypeFlowItem.cs b/samples/DockFigmaSample/Models/PrototypeFlowItem.cs
new file mode 100644
index 000000000..b67556b38
--- /dev/null
+++ b/samples/DockFigmaSample/Models/PrototypeFlowItem.cs
@@ -0,0 +1,15 @@
+namespace DockFigmaSample.Models;
+
+public class PrototypeFlowItem
+{
+ public PrototypeFlowItem(string trigger, string action, string destination)
+ {
+ Trigger = trigger;
+ Action = action;
+ Destination = destination;
+ }
+
+ public string Trigger { get; }
+ public string Action { get; }
+ public string Destination { get; }
+}
diff --git a/samples/DockFigmaSample/Models/RecentFileItem.cs b/samples/DockFigmaSample/Models/RecentFileItem.cs
new file mode 100644
index 000000000..7b14881d1
--- /dev/null
+++ b/samples/DockFigmaSample/Models/RecentFileItem.cs
@@ -0,0 +1,19 @@
+using Avalonia.Media;
+
+namespace DockFigmaSample.Models;
+
+public class RecentFileItem
+{
+ public RecentFileItem(string name, string team, string updated, Color accent)
+ {
+ Name = name;
+ Team = team;
+ Updated = updated;
+ AccentBrush = new SolidColorBrush(accent);
+ }
+
+ public string Name { get; }
+ public string Team { get; }
+ public string Updated { get; }
+ public IBrush AccentBrush { get; }
+}
diff --git a/samples/DockFigmaSample/Models/SampleData.cs b/samples/DockFigmaSample/Models/SampleData.cs
new file mode 100644
index 000000000..5d7ec1511
--- /dev/null
+++ b/samples/DockFigmaSample/Models/SampleData.cs
@@ -0,0 +1,85 @@
+using System.Collections.ObjectModel;
+using Avalonia.Media;
+
+namespace DockFigmaSample.Models;
+
+public static class SampleData
+{
+ public static ObservableCollection CreateLayers() => new()
+ {
+ new LayerItem("Landing Page", "Frame", 0),
+ new LayerItem("Hero", "Group", 1),
+ new LayerItem("Headline", "Text", 2),
+ new LayerItem("Subhead", "Text", 2),
+ new LayerItem("CTA", "Group", 2),
+ new LayerItem("Button Primary", "Rectangle", 3),
+ new LayerItem("Button Label", "Text", 3),
+ new LayerItem("Product Cards", "Group", 1),
+ new LayerItem("Card 01", "Frame", 2),
+ new LayerItem("Card 02", "Frame", 2),
+ new LayerItem("Card 03", "Frame", 2),
+ new LayerItem("Footer", "Group", 1, isLocked: true)
+ };
+
+ public static ObservableCollection CreateComponents() => new()
+ {
+ new ComponentItem("Button / Primary", "CTA with gradient fill"),
+ new ComponentItem("Badge / Status", "Rounded pill badge"),
+ new ComponentItem("Card / Pricing", "Card with shadow"),
+ new ComponentItem("Input / Search", "Leading icon input"),
+ new ComponentItem("Nav / Top", "Logo + actions")
+ };
+
+ public static ObservableCollection CreateSwatches() => new()
+ {
+ new AssetSwatch("Primary", Color.Parse("#3D7EFF")),
+ new AssetSwatch("Warm", Color.Parse("#FF8A4C")),
+ new AssetSwatch("Mint", Color.Parse("#22C55E")),
+ new AssetSwatch("Ink", Color.Parse("#1E2228")),
+ new AssetSwatch("Canvas", Color.Parse("#ECEFF3")),
+ new AssetSwatch("Lavender", Color.Parse("#9A8CFF"))
+ };
+
+ public static ObservableCollection CreateComments() => new()
+ {
+ new CommentItem("Ava Fox", "Can we nudge the hero title up 12px?", "2m"),
+ new CommentItem("Noah Reed", "The pricing cards feel tight on mobile.", "9m"),
+ new CommentItem("Iris Park", "Try a softer background behind the CTA.", "1h")
+ };
+
+ public static ObservableCollection CreateRecentFiles() => new()
+ {
+ new RecentFileItem("Marketing Site", "Nimbus", "Updated 12m ago", Color.Parse("#3D7EFF")),
+ new RecentFileItem("Onboarding Flow", "Nimbus", "Updated 2h ago", Color.Parse("#FF8A4C")),
+ new RecentFileItem("Design System", "Atlas", "Updated yesterday", Color.Parse("#22C55E")),
+ new RecentFileItem("Mobile Kit", "Atlas", "Updated 4d ago", Color.Parse("#F97316"))
+ };
+
+ public static ObservableCollection CreatePrototypeFlows() => new()
+ {
+ new PrototypeFlowItem("On Click", "Navigate", "Pricing Modal"),
+ new PrototypeFlowItem("On Hover", "Swap", "Button / Hover"),
+ new PrototypeFlowItem("After Delay", "Auto Animate", "Hero Alt")
+ };
+
+ public static ObservableCollection CreateInspectSpecs() => new()
+ {
+ new InspectSpecItem("Spacing", "24 px"),
+ new InspectSpecItem("Padding", "32 px"),
+ new InspectSpecItem("Radius", "24 px"),
+ new InspectSpecItem("Shadow", "0 24 48 0"),
+ new InspectSpecItem("Font", "Space Grotesk / 28")
+ };
+
+ public static ObservableCollection CreateToolbarTools() => new()
+ {
+ new ToolItem("Move", "V", true),
+ new ToolItem("Frame", "F"),
+ new ToolItem("Section", "S"),
+ new ToolItem("Rectangle", "R"),
+ new ToolItem("Ellipse", "O"),
+ new ToolItem("Pen", "P"),
+ new ToolItem("Text", "T"),
+ new ToolItem("Comment", "C")
+ };
+}
diff --git a/samples/DockFigmaSample/Models/ToolItem.cs b/samples/DockFigmaSample/Models/ToolItem.cs
new file mode 100644
index 000000000..973610fca
--- /dev/null
+++ b/samples/DockFigmaSample/Models/ToolItem.cs
@@ -0,0 +1,15 @@
+namespace DockFigmaSample.Models;
+
+public class ToolItem
+{
+ public ToolItem(string name, string glyph, bool isActive = false)
+ {
+ Name = name;
+ Glyph = glyph;
+ IsActive = isActive;
+ }
+
+ public string Name { get; }
+ public string Glyph { get; }
+ public bool IsActive { get; }
+}
diff --git a/samples/DockFigmaSample/Program.cs b/samples/DockFigmaSample/Program.cs
new file mode 100644
index 000000000..131566974
--- /dev/null
+++ b/samples/DockFigmaSample/Program.cs
@@ -0,0 +1,20 @@
+using System;
+using Avalonia;
+using ReactiveUI.Avalonia;
+
+namespace DockFigmaSample;
+
+internal class Program
+{
+ [STAThread]
+ private static void Main(string[] args)
+ {
+ BuildAvaloniaApp().StartWithClassicDesktopLifetime(args);
+ }
+
+ public static AppBuilder BuildAvaloniaApp() =>
+ AppBuilder.Configure()
+ .UsePlatformDetect()
+ .UseReactiveUI()
+ .LogToTrace();
+}
diff --git a/samples/DockFigmaSample/Styles/FigmaTheme.axaml b/samples/DockFigmaSample/Styles/FigmaTheme.axaml
new file mode 100644
index 000000000..cbe3d9242
--- /dev/null
+++ b/samples/DockFigmaSample/Styles/FigmaTheme.axaml
@@ -0,0 +1,283 @@
+
+
+ Space Grotesk, Segoe UI
+ JetBrains Mono, Consolas
+
+ #101317
+ #5C6673
+ #ECEFF3
+ #FFFFFF
+ #E1E6ED
+ #F4F6FA
+ #101317
+ #1E2330
+ #FAFBFC
+ #3D7EFF
+ #FF8A4C
+ #22C55E
+ #FFFFFFCC
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/DockFigmaSample/ViewLocator.cs b/samples/DockFigmaSample/ViewLocator.cs
new file mode 100644
index 000000000..299baea05
--- /dev/null
+++ b/samples/DockFigmaSample/ViewLocator.cs
@@ -0,0 +1,43 @@
+using System;
+using Avalonia.Controls;
+using Avalonia.Controls.Templates;
+using Dock.Model.Core;
+using ReactiveUI;
+using Splat;
+
+namespace DockFigmaSample;
+
+public partial class ViewLocator : IDataTemplate
+{
+ public Control? Build(object? data)
+ {
+ if (data is null)
+ {
+ return null;
+ }
+
+ var viewLocator = Locator.Current.GetService();
+ if (viewLocator?.ResolveView(data) is Control control)
+ {
+ return control;
+ }
+
+ throw new Exception($"Unable to create view for type: {data.GetType()}");
+ }
+
+ public bool Match(object? data)
+ {
+ if (data is null)
+ {
+ return false;
+ }
+
+ if (data is IDockable)
+ {
+ return true;
+ }
+
+ var viewLocator = Locator.Current.GetService();
+ return viewLocator?.ResolveView(data) is not null;
+ }
+}
diff --git a/samples/DockFigmaSample/ViewModels/Documents/CanvasDocumentViewModel.cs b/samples/DockFigmaSample/ViewModels/Documents/CanvasDocumentViewModel.cs
new file mode 100644
index 000000000..01f236e9c
--- /dev/null
+++ b/samples/DockFigmaSample/ViewModels/Documents/CanvasDocumentViewModel.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Reactive.Linq;
+using Dock.Model.ReactiveUI.Navigation.Controls;
+using DockFigmaSample.ViewModels;
+using ReactiveUI;
+
+namespace DockFigmaSample.ViewModels.Documents;
+
+public class CanvasDocumentViewModel : RoutableDocument
+{
+ private readonly DesignCanvasViewModel _designView;
+ private readonly PrototypeCanvasViewModel _prototypeView;
+ private readonly InspectCanvasViewModel _inspectView;
+
+ public CanvasDocumentViewModel(IScreen host) : base(host, "canvas")
+ {
+ _designView = new DesignCanvasViewModel(this);
+ _prototypeView = new PrototypeCanvasViewModel(this);
+ _inspectView = new InspectCanvasViewModel(this);
+
+ Router.Navigate.Execute(_designView).Subscribe(_ => { });
+ }
+
+ public void SetMode(WorkspaceMode mode)
+ {
+ switch (mode)
+ {
+ case WorkspaceMode.Design:
+ Router.Navigate.Execute(_designView).Subscribe(_ => { });
+ break;
+ case WorkspaceMode.Prototype:
+ Router.Navigate.Execute(_prototypeView).Subscribe(_ => { });
+ break;
+ case WorkspaceMode.Inspect:
+ Router.Navigate.Execute(_inspectView).Subscribe(_ => { });
+ break;
+ }
+ }
+}
diff --git a/samples/DockFigmaSample/ViewModels/Documents/DesignCanvasViewModel.cs b/samples/DockFigmaSample/ViewModels/Documents/DesignCanvasViewModel.cs
new file mode 100644
index 000000000..db2c36ad1
--- /dev/null
+++ b/samples/DockFigmaSample/ViewModels/Documents/DesignCanvasViewModel.cs
@@ -0,0 +1,17 @@
+using ReactiveUI;
+
+namespace DockFigmaSample.ViewModels.Documents;
+
+public class DesignCanvasViewModel : ReactiveObject, IRoutableViewModel
+{
+ public DesignCanvasViewModel(IScreen host)
+ {
+ HostScreen = host;
+ }
+
+ public string UrlPathSegment { get; } = "design-canvas";
+ public IScreen HostScreen { get; }
+
+ public string FrameName { get; } = "Landing Page";
+ public string FrameSize { get; } = "1440 x 900";
+}
diff --git a/samples/DockFigmaSample/ViewModels/Documents/InspectCanvasViewModel.cs b/samples/DockFigmaSample/ViewModels/Documents/InspectCanvasViewModel.cs
new file mode 100644
index 000000000..3c376d0d3
--- /dev/null
+++ b/samples/DockFigmaSample/ViewModels/Documents/InspectCanvasViewModel.cs
@@ -0,0 +1,17 @@
+using ReactiveUI;
+
+namespace DockFigmaSample.ViewModels.Documents;
+
+public class InspectCanvasViewModel : ReactiveObject, IRoutableViewModel
+{
+ public InspectCanvasViewModel(IScreen host)
+ {
+ HostScreen = host;
+ }
+
+ public string UrlPathSegment { get; } = "inspect-canvas";
+ public IScreen HostScreen { get; }
+
+ public string SelectedLayer { get; } = "Hero / CTA";
+ public string Measurements { get; } = "320 x 56";
+}
diff --git a/samples/DockFigmaSample/ViewModels/Documents/PrototypeCanvasViewModel.cs b/samples/DockFigmaSample/ViewModels/Documents/PrototypeCanvasViewModel.cs
new file mode 100644
index 000000000..03c29e84b
--- /dev/null
+++ b/samples/DockFigmaSample/ViewModels/Documents/PrototypeCanvasViewModel.cs
@@ -0,0 +1,22 @@
+using System.Collections.ObjectModel;
+using ReactiveUI;
+
+namespace DockFigmaSample.ViewModels.Documents;
+
+public class PrototypeCanvasViewModel : ReactiveObject, IRoutableViewModel
+{
+ public PrototypeCanvasViewModel(IScreen host)
+ {
+ HostScreen = host;
+ }
+
+ public string UrlPathSegment { get; } = "prototype-canvas";
+ public IScreen HostScreen { get; }
+
+ public ObservableCollection Frames { get; } = new()
+ {
+ "Landing Page",
+ "Pricing Modal",
+ "Checkout"
+ };
+}
diff --git a/samples/DockFigmaSample/ViewModels/HomeViewModel.cs b/samples/DockFigmaSample/ViewModels/HomeViewModel.cs
new file mode 100644
index 000000000..a84e08649
--- /dev/null
+++ b/samples/DockFigmaSample/ViewModels/HomeViewModel.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections.ObjectModel;
+using System.Reactive;
+using System.Reactive.Linq;
+using DockFigmaSample.Models;
+using ReactiveUI;
+
+namespace DockFigmaSample.ViewModels;
+
+public class HomeViewModel : ReactiveObject, IRoutableViewModel
+{
+ public HomeViewModel(IScreen host)
+ {
+ HostScreen = host;
+ OpenWorkspace = ReactiveCommand.Create(() =>
+ HostScreen.Router.Navigate.Execute(new WorkspaceViewModel(host)).Subscribe(_ => { }));
+ }
+
+ public string UrlPathSegment { get; } = "home";
+ public IScreen HostScreen { get; }
+
+ public ObservableCollection RecentFiles { get; } = SampleData.CreateRecentFiles();
+
+ public ReactiveCommand OpenWorkspace { get; }
+}
diff --git a/samples/DockFigmaSample/ViewModels/MainWindowViewModel.cs b/samples/DockFigmaSample/ViewModels/MainWindowViewModel.cs
new file mode 100644
index 000000000..279246314
--- /dev/null
+++ b/samples/DockFigmaSample/ViewModels/MainWindowViewModel.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Reactive.Linq;
+using ReactiveUI;
+
+namespace DockFigmaSample.ViewModels;
+
+public class MainWindowViewModel : ReactiveObject, IScreen
+{
+ public RoutingState Router { get; } = new RoutingState();
+
+ public MainWindowViewModel()
+ {
+ var home = new HomeViewModel(this);
+ Router.Navigate.Execute(home).Subscribe(_ => { });
+ }
+}
diff --git a/samples/DockFigmaSample/ViewModels/Tools/AssetsToolViewModel.cs b/samples/DockFigmaSample/ViewModels/Tools/AssetsToolViewModel.cs
new file mode 100644
index 000000000..a7945ea73
--- /dev/null
+++ b/samples/DockFigmaSample/ViewModels/Tools/AssetsToolViewModel.cs
@@ -0,0 +1,11 @@
+using System.Collections.ObjectModel;
+using Dock.Model.ReactiveUI.Controls;
+using DockFigmaSample.Models;
+
+namespace DockFigmaSample.ViewModels.Tools;
+
+public class AssetsToolViewModel : Tool
+{
+ public ObservableCollection Swatches { get; } = SampleData.CreateSwatches();
+ public ObservableCollection Components { get; } = SampleData.CreateComponents();
+}
diff --git a/samples/DockFigmaSample/ViewModels/Tools/CommentsToolViewModel.cs b/samples/DockFigmaSample/ViewModels/Tools/CommentsToolViewModel.cs
new file mode 100644
index 000000000..4a59ad5ff
--- /dev/null
+++ b/samples/DockFigmaSample/ViewModels/Tools/CommentsToolViewModel.cs
@@ -0,0 +1,10 @@
+using System.Collections.ObjectModel;
+using Dock.Model.ReactiveUI.Controls;
+using DockFigmaSample.Models;
+
+namespace DockFigmaSample.ViewModels.Tools;
+
+public class CommentsToolViewModel : Tool
+{
+ public ObservableCollection Comments { get; } = SampleData.CreateComments();
+}
diff --git a/samples/DockFigmaSample/ViewModels/Tools/InspectorDesignViewModel.cs b/samples/DockFigmaSample/ViewModels/Tools/InspectorDesignViewModel.cs
new file mode 100644
index 000000000..a8703bac9
--- /dev/null
+++ b/samples/DockFigmaSample/ViewModels/Tools/InspectorDesignViewModel.cs
@@ -0,0 +1,22 @@
+using ReactiveUI;
+
+namespace DockFigmaSample.ViewModels.Tools;
+
+public class InspectorDesignViewModel : ReactiveObject, IRoutableViewModel
+{
+ public InspectorDesignViewModel(IScreen host)
+ {
+ HostScreen = host;
+ }
+
+ public string UrlPathSegment { get; } = "inspector-design";
+ public IScreen HostScreen { get; }
+
+ public string Width { get; } = "1280";
+ public string Height { get; } = "720";
+ public string Radius { get; } = "24";
+ public string Fill { get; } = "#FFFFFF";
+ public string Opacity { get; } = "100";
+ public string Layout { get; } = "Auto";
+ public string Spacing { get; } = "24";
+}
diff --git a/samples/DockFigmaSample/ViewModels/Tools/InspectorInspectViewModel.cs b/samples/DockFigmaSample/ViewModels/Tools/InspectorInspectViewModel.cs
new file mode 100644
index 000000000..7d0b4fbe3
--- /dev/null
+++ b/samples/DockFigmaSample/ViewModels/Tools/InspectorInspectViewModel.cs
@@ -0,0 +1,18 @@
+using System.Collections.ObjectModel;
+using DockFigmaSample.Models;
+using ReactiveUI;
+
+namespace DockFigmaSample.ViewModels.Tools;
+
+public class InspectorInspectViewModel : ReactiveObject, IRoutableViewModel
+{
+ public InspectorInspectViewModel(IScreen host)
+ {
+ HostScreen = host;
+ }
+
+ public string UrlPathSegment { get; } = "inspector-inspect";
+ public IScreen HostScreen { get; }
+
+ public ObservableCollection Specs { get; } = SampleData.CreateInspectSpecs();
+}
diff --git a/samples/DockFigmaSample/ViewModels/Tools/InspectorPrototypeViewModel.cs b/samples/DockFigmaSample/ViewModels/Tools/InspectorPrototypeViewModel.cs
new file mode 100644
index 000000000..c789d8299
--- /dev/null
+++ b/samples/DockFigmaSample/ViewModels/Tools/InspectorPrototypeViewModel.cs
@@ -0,0 +1,18 @@
+using System.Collections.ObjectModel;
+using DockFigmaSample.Models;
+using ReactiveUI;
+
+namespace DockFigmaSample.ViewModels.Tools;
+
+public class InspectorPrototypeViewModel : ReactiveObject, IRoutableViewModel
+{
+ public InspectorPrototypeViewModel(IScreen host)
+ {
+ HostScreen = host;
+ }
+
+ public string UrlPathSegment { get; } = "inspector-prototype";
+ public IScreen HostScreen { get; }
+
+ public ObservableCollection Flows { get; } = SampleData.CreatePrototypeFlows();
+}
diff --git a/samples/DockFigmaSample/ViewModels/Tools/InspectorToolViewModel.cs b/samples/DockFigmaSample/ViewModels/Tools/InspectorToolViewModel.cs
new file mode 100644
index 000000000..82fd2fd7a
--- /dev/null
+++ b/samples/DockFigmaSample/ViewModels/Tools/InspectorToolViewModel.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Reactive.Linq;
+using Dock.Model.ReactiveUI.Navigation.Controls;
+using DockFigmaSample.ViewModels;
+using ReactiveUI;
+
+namespace DockFigmaSample.ViewModels.Tools;
+
+public class InspectorToolViewModel : RoutableTool
+{
+ private readonly InspectorDesignViewModel _designView;
+ private readonly InspectorPrototypeViewModel _prototypeView;
+ private readonly InspectorInspectViewModel _inspectView;
+
+ public InspectorToolViewModel(IScreen host) : base(host, "inspector")
+ {
+ _designView = new InspectorDesignViewModel(this);
+ _prototypeView = new InspectorPrototypeViewModel(this);
+ _inspectView = new InspectorInspectViewModel(this);
+
+ Router.Navigate.Execute(_designView).Subscribe(_ => { });
+ }
+
+ public void SetMode(WorkspaceMode mode)
+ {
+ switch (mode)
+ {
+ case WorkspaceMode.Design:
+ Router.Navigate.Execute(_designView).Subscribe(_ => { });
+ break;
+ case WorkspaceMode.Prototype:
+ Router.Navigate.Execute(_prototypeView).Subscribe(_ => { });
+ break;
+ case WorkspaceMode.Inspect:
+ Router.Navigate.Execute(_inspectView).Subscribe(_ => { });
+ break;
+ }
+ }
+}
diff --git a/samples/DockFigmaSample/ViewModels/Tools/LayersToolViewModel.cs b/samples/DockFigmaSample/ViewModels/Tools/LayersToolViewModel.cs
new file mode 100644
index 000000000..2a75a1941
--- /dev/null
+++ b/samples/DockFigmaSample/ViewModels/Tools/LayersToolViewModel.cs
@@ -0,0 +1,10 @@
+using System.Collections.ObjectModel;
+using Dock.Model.ReactiveUI.Controls;
+using DockFigmaSample.Models;
+
+namespace DockFigmaSample.ViewModels.Tools;
+
+public class LayersToolViewModel : Tool
+{
+ public ObservableCollection Layers { get; } = SampleData.CreateLayers();
+}
diff --git a/samples/DockFigmaSample/ViewModels/Tools/ToolbarToolViewModel.cs b/samples/DockFigmaSample/ViewModels/Tools/ToolbarToolViewModel.cs
new file mode 100644
index 000000000..8ff70e720
--- /dev/null
+++ b/samples/DockFigmaSample/ViewModels/Tools/ToolbarToolViewModel.cs
@@ -0,0 +1,10 @@
+using System.Collections.ObjectModel;
+using Dock.Model.ReactiveUI.Controls;
+using DockFigmaSample.Models;
+
+namespace DockFigmaSample.ViewModels.Tools;
+
+public class ToolbarToolViewModel : Tool
+{
+ public ObservableCollection Tools { get; } = SampleData.CreateToolbarTools();
+}
diff --git a/samples/DockFigmaSample/ViewModels/WorkspaceDockFactory.cs b/samples/DockFigmaSample/ViewModels/WorkspaceDockFactory.cs
new file mode 100644
index 000000000..a814ab7d0
--- /dev/null
+++ b/samples/DockFigmaSample/ViewModels/WorkspaceDockFactory.cs
@@ -0,0 +1,156 @@
+using System;
+using System.Collections.Generic;
+using Dock.Avalonia.Controls;
+using Dock.Model.Controls;
+using Dock.Model.Core;
+using Dock.Model.ReactiveUI;
+using Dock.Model.ReactiveUI.Controls;
+using Dock.Model.ReactiveUI.Navigation.Controls;
+using Dock.Settings;
+using DockFigmaSample.ViewModels.Documents;
+using DockFigmaSample.ViewModels.Tools;
+using ReactiveUI;
+
+namespace DockFigmaSample.ViewModels;
+
+public class WorkspaceDockFactory : Factory
+{
+ private readonly IScreen _host;
+
+ public WorkspaceDockFactory(IScreen host)
+ {
+ _host = host;
+ }
+
+ public CanvasDocumentViewModel CanvasDocument { get; private set; } = null!;
+ public InspectorToolViewModel InspectorTool { get; private set; } = null!;
+
+ public override IRootDock CreateLayout()
+ {
+ CanvasDocument = new CanvasDocumentViewModel(_host)
+ {
+ Id = "Canvas",
+ Title = "Canvas"
+ };
+
+ var toolbarTool = new ToolbarToolViewModel
+ {
+ Id = "Toolbar",
+ Title = "Tools"
+ };
+
+ var layersTool = new LayersToolViewModel
+ {
+ Id = "Layers",
+ Title = "Layers"
+ };
+
+ var assetsTool = new AssetsToolViewModel
+ {
+ Id = "Assets",
+ Title = "Assets"
+ };
+
+ InspectorTool = new InspectorToolViewModel(_host)
+ {
+ Id = "Inspector",
+ Title = "Properties"
+ };
+
+ var commentsTool = new CommentsToolViewModel
+ {
+ Id = "Comments",
+ Title = "Comments"
+ };
+
+ var documentDock = new DocumentDock
+ {
+ Id = "Documents",
+ VisibleDockables = CreateList(CanvasDocument),
+ ActiveDockable = CanvasDocument,
+ CanCreateDocument = false
+ };
+
+ var toolbarDock = new ToolDock
+ {
+ Id = "ToolbarDock",
+ Alignment = Alignment.Left,
+ Proportion = 0.08,
+ VisibleDockables = CreateList(toolbarTool),
+ ActiveDockable = toolbarTool
+ };
+
+ var leftPanelDock = new ToolDock
+ {
+ Id = "LeftPanel",
+ Alignment = Alignment.Left,
+ Proportion = 0.22,
+ VisibleDockables = CreateList(layersTool, assetsTool),
+ ActiveDockable = layersTool
+ };
+
+ var leftGroup = new ProportionalDock
+ {
+ Orientation = Orientation.Horizontal,
+ VisibleDockables = CreateList(toolbarDock, new ProportionalDockSplitter(), leftPanelDock),
+ ActiveDockable = leftPanelDock
+ };
+
+ var bottomDock = new ToolDock
+ {
+ Id = "BottomPanel",
+ Alignment = Alignment.Bottom,
+ Proportion = 0.25,
+ VisibleDockables = CreateList(commentsTool),
+ ActiveDockable = commentsTool
+ };
+
+ var centerGroup = new ProportionalDock
+ {
+ Orientation = Orientation.Vertical,
+ VisibleDockables = CreateList(documentDock, new ProportionalDockSplitter(), bottomDock),
+ ActiveDockable = documentDock
+ };
+
+ var rightDock = new ToolDock
+ {
+ Id = "RightPanel",
+ Alignment = Alignment.Right,
+ Proportion = 0.26,
+ VisibleDockables = CreateList(InspectorTool),
+ ActiveDockable = InspectorTool
+ };
+
+ var mainLayout = new ProportionalDock
+ {
+ Orientation = Orientation.Horizontal,
+ VisibleDockables = CreateList(leftGroup, new ProportionalDockSplitter(), centerGroup, new ProportionalDockSplitter(), rightDock),
+ ActiveDockable = centerGroup
+ };
+
+ var root = new RoutableRootDock(_host)
+ {
+ VisibleDockables = CreateList(mainLayout),
+ DefaultDockable = mainLayout,
+ ActiveDockable = mainLayout
+ };
+
+ root.LeftPinnedDockables = CreateList();
+ root.RightPinnedDockables = CreateList();
+ root.TopPinnedDockables = CreateList();
+ root.BottomPinnedDockables = CreateList();
+ root.PinnedDock = null;
+
+ return root;
+ }
+
+ public override void InitLayout(IDockable layout)
+ {
+ HostWindowLocator = new Dictionary>
+ {
+ [nameof(IDockWindow)] = () => DockSettings.UseManagedWindows ? new ManagedHostWindow() : new HostWindow()
+ };
+
+ base.InitLayout(layout);
+ }
+}
diff --git a/samples/DockFigmaSample/ViewModels/WorkspaceMode.cs b/samples/DockFigmaSample/ViewModels/WorkspaceMode.cs
new file mode 100644
index 000000000..5dd077254
--- /dev/null
+++ b/samples/DockFigmaSample/ViewModels/WorkspaceMode.cs
@@ -0,0 +1,8 @@
+namespace DockFigmaSample.ViewModels;
+
+public enum WorkspaceMode
+{
+ Design,
+ Prototype,
+ Inspect
+}
diff --git a/samples/DockFigmaSample/ViewModels/WorkspaceViewModel.cs b/samples/DockFigmaSample/ViewModels/WorkspaceViewModel.cs
new file mode 100644
index 000000000..85d414f07
--- /dev/null
+++ b/samples/DockFigmaSample/ViewModels/WorkspaceViewModel.cs
@@ -0,0 +1,61 @@
+using System.Reactive;
+using Dock.Model.Controls;
+using DockFigmaSample.ViewModels.Documents;
+using DockFigmaSample.ViewModels.Tools;
+using ReactiveUI;
+
+namespace DockFigmaSample.ViewModels;
+
+public class WorkspaceViewModel : ReactiveObject, IRoutableViewModel
+{
+ private IRootDock? _layout;
+ private WorkspaceMode _editorMode;
+ private readonly CanvasDocumentViewModel _canvasDocument;
+ private readonly InspectorToolViewModel _inspectorTool;
+
+ public WorkspaceViewModel(IScreen host)
+ {
+ HostScreen = host;
+
+ var factory = new WorkspaceDockFactory(host);
+ Layout = factory.CreateLayout();
+ if (Layout is not null)
+ {
+ factory.InitLayout(Layout);
+ }
+
+ _canvasDocument = factory.CanvasDocument;
+ _inspectorTool = factory.InspectorTool;
+
+ SwitchMode = ReactiveCommand.Create(SetMode);
+ SetMode(WorkspaceMode.Design);
+ }
+
+ public string UrlPathSegment { get; } = "workspace";
+ public IScreen HostScreen { get; }
+
+ public IRootDock? Layout
+ {
+ get => _layout;
+ set => this.RaiseAndSetIfChanged(ref _layout, value);
+ }
+
+ public WorkspaceMode EditorMode
+ {
+ get => _editorMode;
+ private set => this.RaiseAndSetIfChanged(ref _editorMode, value);
+ }
+
+ public string FileName { get; } = "LandingPage.fig";
+ public string ProjectName { get; } = "Nimbus";
+ public string StatusMessage { get; } = "All changes saved";
+
+ public ReactiveCommand SwitchMode { get; }
+
+ private void SetMode(WorkspaceMode mode)
+ {
+ EditorMode = mode;
+ _canvasDocument.SetMode(mode);
+ _inspectorTool.SetMode(mode);
+ }
+}
diff --git a/samples/DockFigmaSample/Views/Documents/CanvasDocumentView.axaml b/samples/DockFigmaSample/Views/Documents/CanvasDocumentView.axaml
new file mode 100644
index 000000000..9d690ef37
--- /dev/null
+++ b/samples/DockFigmaSample/Views/Documents/CanvasDocumentView.axaml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/DockFigmaSample/Views/Documents/CanvasDocumentView.axaml.cs b/samples/DockFigmaSample/Views/Documents/CanvasDocumentView.axaml.cs
new file mode 100644
index 000000000..3b9b4409b
--- /dev/null
+++ b/samples/DockFigmaSample/Views/Documents/CanvasDocumentView.axaml.cs
@@ -0,0 +1,13 @@
+using Avalonia.Markup.Xaml;
+using DockFigmaSample.ViewModels.Documents;
+using ReactiveUI.Avalonia;
+
+namespace DockFigmaSample.Views.Documents;
+
+public partial class CanvasDocumentView : ReactiveUserControl
+{
+ public CanvasDocumentView()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+}
diff --git a/samples/DockFigmaSample/Views/Documents/DesignCanvasView.axaml b/samples/DockFigmaSample/Views/Documents/DesignCanvasView.axaml
new file mode 100644
index 000000000..2402f72a6
--- /dev/null
+++ b/samples/DockFigmaSample/Views/Documents/DesignCanvasView.axaml
@@ -0,0 +1,91 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/DockFigmaSample/Views/Documents/DesignCanvasView.axaml.cs b/samples/DockFigmaSample/Views/Documents/DesignCanvasView.axaml.cs
new file mode 100644
index 000000000..026c9067e
--- /dev/null
+++ b/samples/DockFigmaSample/Views/Documents/DesignCanvasView.axaml.cs
@@ -0,0 +1,13 @@
+using Avalonia.Markup.Xaml;
+using DockFigmaSample.ViewModels.Documents;
+using ReactiveUI.Avalonia;
+
+namespace DockFigmaSample.Views.Documents;
+
+public partial class DesignCanvasView : ReactiveUserControl
+{
+ public DesignCanvasView()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+}
diff --git a/samples/DockFigmaSample/Views/Documents/InspectCanvasView.axaml b/samples/DockFigmaSample/Views/Documents/InspectCanvasView.axaml
new file mode 100644
index 000000000..cb506dd9d
--- /dev/null
+++ b/samples/DockFigmaSample/Views/Documents/InspectCanvasView.axaml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/DockFigmaSample/Views/Documents/InspectCanvasView.axaml.cs b/samples/DockFigmaSample/Views/Documents/InspectCanvasView.axaml.cs
new file mode 100644
index 000000000..a61d76257
--- /dev/null
+++ b/samples/DockFigmaSample/Views/Documents/InspectCanvasView.axaml.cs
@@ -0,0 +1,13 @@
+using Avalonia.Markup.Xaml;
+using DockFigmaSample.ViewModels.Documents;
+using ReactiveUI.Avalonia;
+
+namespace DockFigmaSample.Views.Documents;
+
+public partial class InspectCanvasView : ReactiveUserControl
+{
+ public InspectCanvasView()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+}
diff --git a/samples/DockFigmaSample/Views/Documents/PrototypeCanvasView.axaml b/samples/DockFigmaSample/Views/Documents/PrototypeCanvasView.axaml
new file mode 100644
index 000000000..5ac23229c
--- /dev/null
+++ b/samples/DockFigmaSample/Views/Documents/PrototypeCanvasView.axaml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/DockFigmaSample/Views/Documents/PrototypeCanvasView.axaml.cs b/samples/DockFigmaSample/Views/Documents/PrototypeCanvasView.axaml.cs
new file mode 100644
index 000000000..4c53a5155
--- /dev/null
+++ b/samples/DockFigmaSample/Views/Documents/PrototypeCanvasView.axaml.cs
@@ -0,0 +1,13 @@
+using Avalonia.Markup.Xaml;
+using DockFigmaSample.ViewModels.Documents;
+using ReactiveUI.Avalonia;
+
+namespace DockFigmaSample.Views.Documents;
+
+public partial class PrototypeCanvasView : ReactiveUserControl
+{
+ public PrototypeCanvasView()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+}
diff --git a/samples/DockFigmaSample/Views/HomeView.axaml b/samples/DockFigmaSample/Views/HomeView.axaml
new file mode 100644
index 000000000..f104e16bf
--- /dev/null
+++ b/samples/DockFigmaSample/Views/HomeView.axaml
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/DockFigmaSample/Views/HomeView.axaml.cs b/samples/DockFigmaSample/Views/HomeView.axaml.cs
new file mode 100644
index 000000000..171dc8176
--- /dev/null
+++ b/samples/DockFigmaSample/Views/HomeView.axaml.cs
@@ -0,0 +1,13 @@
+using Avalonia.Markup.Xaml;
+using DockFigmaSample.ViewModels;
+using ReactiveUI.Avalonia;
+
+namespace DockFigmaSample.Views;
+
+public partial class HomeView : ReactiveUserControl
+{
+ public HomeView()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+}
diff --git a/samples/DockFigmaSample/Views/MainWindow.axaml b/samples/DockFigmaSample/Views/MainWindow.axaml
new file mode 100644
index 000000000..ea7c04147
--- /dev/null
+++ b/samples/DockFigmaSample/Views/MainWindow.axaml
@@ -0,0 +1,12 @@
+
+
+
diff --git a/samples/DockFigmaSample/Views/MainWindow.axaml.cs b/samples/DockFigmaSample/Views/MainWindow.axaml.cs
new file mode 100644
index 000000000..97830c466
--- /dev/null
+++ b/samples/DockFigmaSample/Views/MainWindow.axaml.cs
@@ -0,0 +1,13 @@
+using Avalonia.Markup.Xaml;
+using DockFigmaSample.ViewModels;
+using ReactiveUI.Avalonia;
+
+namespace DockFigmaSample.Views;
+
+public partial class MainWindow : ReactiveWindow
+{
+ public MainWindow()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+}
diff --git a/samples/DockFigmaSample/Views/Tools/AssetsToolView.axaml b/samples/DockFigmaSample/Views/Tools/AssetsToolView.axaml
new file mode 100644
index 000000000..9f2ac4419
--- /dev/null
+++ b/samples/DockFigmaSample/Views/Tools/AssetsToolView.axaml
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/DockFigmaSample/Views/Tools/AssetsToolView.axaml.cs b/samples/DockFigmaSample/Views/Tools/AssetsToolView.axaml.cs
new file mode 100644
index 000000000..8ef7507be
--- /dev/null
+++ b/samples/DockFigmaSample/Views/Tools/AssetsToolView.axaml.cs
@@ -0,0 +1,13 @@
+using Avalonia.Markup.Xaml;
+using DockFigmaSample.ViewModels.Tools;
+using ReactiveUI.Avalonia;
+
+namespace DockFigmaSample.Views.Tools;
+
+public partial class AssetsToolView : ReactiveUserControl
+{
+ public AssetsToolView()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+}
diff --git a/samples/DockFigmaSample/Views/Tools/CommentsToolView.axaml b/samples/DockFigmaSample/Views/Tools/CommentsToolView.axaml
new file mode 100644
index 000000000..548225dba
--- /dev/null
+++ b/samples/DockFigmaSample/Views/Tools/CommentsToolView.axaml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/DockFigmaSample/Views/Tools/CommentsToolView.axaml.cs b/samples/DockFigmaSample/Views/Tools/CommentsToolView.axaml.cs
new file mode 100644
index 000000000..93a2d360b
--- /dev/null
+++ b/samples/DockFigmaSample/Views/Tools/CommentsToolView.axaml.cs
@@ -0,0 +1,13 @@
+using Avalonia.Markup.Xaml;
+using DockFigmaSample.ViewModels.Tools;
+using ReactiveUI.Avalonia;
+
+namespace DockFigmaSample.Views.Tools;
+
+public partial class CommentsToolView : ReactiveUserControl
+{
+ public CommentsToolView()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+}
diff --git a/samples/DockFigmaSample/Views/Tools/InspectorDesignView.axaml b/samples/DockFigmaSample/Views/Tools/InspectorDesignView.axaml
new file mode 100644
index 000000000..5b6a44300
--- /dev/null
+++ b/samples/DockFigmaSample/Views/Tools/InspectorDesignView.axaml
@@ -0,0 +1,61 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/DockFigmaSample/Views/Tools/InspectorDesignView.axaml.cs b/samples/DockFigmaSample/Views/Tools/InspectorDesignView.axaml.cs
new file mode 100644
index 000000000..b4ddb0833
--- /dev/null
+++ b/samples/DockFigmaSample/Views/Tools/InspectorDesignView.axaml.cs
@@ -0,0 +1,13 @@
+using Avalonia.Markup.Xaml;
+using DockFigmaSample.ViewModels.Tools;
+using ReactiveUI.Avalonia;
+
+namespace DockFigmaSample.Views.Tools;
+
+public partial class InspectorDesignView : ReactiveUserControl
+{
+ public InspectorDesignView()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+}
diff --git a/samples/DockFigmaSample/Views/Tools/InspectorInspectView.axaml b/samples/DockFigmaSample/Views/Tools/InspectorInspectView.axaml
new file mode 100644
index 000000000..ddfdc725c
--- /dev/null
+++ b/samples/DockFigmaSample/Views/Tools/InspectorInspectView.axaml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/DockFigmaSample/Views/Tools/InspectorInspectView.axaml.cs b/samples/DockFigmaSample/Views/Tools/InspectorInspectView.axaml.cs
new file mode 100644
index 000000000..10f0bd7b0
--- /dev/null
+++ b/samples/DockFigmaSample/Views/Tools/InspectorInspectView.axaml.cs
@@ -0,0 +1,13 @@
+using Avalonia.Markup.Xaml;
+using DockFigmaSample.ViewModels.Tools;
+using ReactiveUI.Avalonia;
+
+namespace DockFigmaSample.Views.Tools;
+
+public partial class InspectorInspectView : ReactiveUserControl
+{
+ public InspectorInspectView()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+}
diff --git a/samples/DockFigmaSample/Views/Tools/InspectorPrototypeView.axaml b/samples/DockFigmaSample/Views/Tools/InspectorPrototypeView.axaml
new file mode 100644
index 000000000..d78259da5
--- /dev/null
+++ b/samples/DockFigmaSample/Views/Tools/InspectorPrototypeView.axaml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/DockFigmaSample/Views/Tools/InspectorPrototypeView.axaml.cs b/samples/DockFigmaSample/Views/Tools/InspectorPrototypeView.axaml.cs
new file mode 100644
index 000000000..45c805ac5
--- /dev/null
+++ b/samples/DockFigmaSample/Views/Tools/InspectorPrototypeView.axaml.cs
@@ -0,0 +1,13 @@
+using Avalonia.Markup.Xaml;
+using DockFigmaSample.ViewModels.Tools;
+using ReactiveUI.Avalonia;
+
+namespace DockFigmaSample.Views.Tools;
+
+public partial class InspectorPrototypeView : ReactiveUserControl
+{
+ public InspectorPrototypeView()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+}
diff --git a/samples/DockFigmaSample/Views/Tools/InspectorToolView.axaml b/samples/DockFigmaSample/Views/Tools/InspectorToolView.axaml
new file mode 100644
index 000000000..e20ed387c
--- /dev/null
+++ b/samples/DockFigmaSample/Views/Tools/InspectorToolView.axaml
@@ -0,0 +1,10 @@
+
+
+
+
+
diff --git a/samples/DockFigmaSample/Views/Tools/InspectorToolView.axaml.cs b/samples/DockFigmaSample/Views/Tools/InspectorToolView.axaml.cs
new file mode 100644
index 000000000..a9f663cef
--- /dev/null
+++ b/samples/DockFigmaSample/Views/Tools/InspectorToolView.axaml.cs
@@ -0,0 +1,13 @@
+using Avalonia.Markup.Xaml;
+using DockFigmaSample.ViewModels.Tools;
+using ReactiveUI.Avalonia;
+
+namespace DockFigmaSample.Views.Tools;
+
+public partial class InspectorToolView : ReactiveUserControl
+{
+ public InspectorToolView()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+}
diff --git a/samples/DockFigmaSample/Views/Tools/LayersToolView.axaml b/samples/DockFigmaSample/Views/Tools/LayersToolView.axaml
new file mode 100644
index 000000000..f07e05294
--- /dev/null
+++ b/samples/DockFigmaSample/Views/Tools/LayersToolView.axaml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/DockFigmaSample/Views/Tools/LayersToolView.axaml.cs b/samples/DockFigmaSample/Views/Tools/LayersToolView.axaml.cs
new file mode 100644
index 000000000..fddc4d454
--- /dev/null
+++ b/samples/DockFigmaSample/Views/Tools/LayersToolView.axaml.cs
@@ -0,0 +1,13 @@
+using Avalonia.Markup.Xaml;
+using DockFigmaSample.ViewModels.Tools;
+using ReactiveUI.Avalonia;
+
+namespace DockFigmaSample.Views.Tools;
+
+public partial class LayersToolView : ReactiveUserControl
+{
+ public LayersToolView()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+}
diff --git a/samples/DockFigmaSample/Views/Tools/ToolbarToolView.axaml b/samples/DockFigmaSample/Views/Tools/ToolbarToolView.axaml
new file mode 100644
index 000000000..0ac595afc
--- /dev/null
+++ b/samples/DockFigmaSample/Views/Tools/ToolbarToolView.axaml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/DockFigmaSample/Views/Tools/ToolbarToolView.axaml.cs b/samples/DockFigmaSample/Views/Tools/ToolbarToolView.axaml.cs
new file mode 100644
index 000000000..e5a82dd21
--- /dev/null
+++ b/samples/DockFigmaSample/Views/Tools/ToolbarToolView.axaml.cs
@@ -0,0 +1,13 @@
+using Avalonia.Markup.Xaml;
+using DockFigmaSample.ViewModels.Tools;
+using ReactiveUI.Avalonia;
+
+namespace DockFigmaSample.Views.Tools;
+
+public partial class ToolbarToolView : ReactiveUserControl
+{
+ public ToolbarToolView()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+}
diff --git a/samples/DockFigmaSample/Views/WorkspaceView.axaml b/samples/DockFigmaSample/Views/WorkspaceView.axaml
new file mode 100644
index 000000000..ea82d0770
--- /dev/null
+++ b/samples/DockFigmaSample/Views/WorkspaceView.axaml
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/DockFigmaSample/Views/WorkspaceView.axaml.cs b/samples/DockFigmaSample/Views/WorkspaceView.axaml.cs
new file mode 100644
index 000000000..deedaa416
--- /dev/null
+++ b/samples/DockFigmaSample/Views/WorkspaceView.axaml.cs
@@ -0,0 +1,13 @@
+using Avalonia.Markup.Xaml;
+using DockFigmaSample.ViewModels;
+using ReactiveUI.Avalonia;
+
+namespace DockFigmaSample.Views;
+
+public partial class WorkspaceView : ReactiveUserControl
+{
+ public WorkspaceView()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+}