diff --git a/ImportUI/Components/App.razor b/ImportUI/Components/App.razor
index 433bb70..7aa9339 100644
--- a/ImportUI/Components/App.razor
+++ b/ImportUI/Components/App.razor
@@ -15,7 +15,7 @@
-
+
diff --git a/ImportUI/Components/Layout/ApplicationLayout.razor b/ImportUI/Components/Layout/ApplicationLayout.razor
new file mode 100644
index 0000000..30aacb3
--- /dev/null
+++ b/ImportUI/Components/Layout/ApplicationLayout.razor
@@ -0,0 +1,20 @@
+@inherits LayoutComponentBase
+@layout BaseLayout
+
+
+
+
+ @AppText
+
+
+
+
+ @if (BaseLayout != null)
+ {
+
+
+
+ }
+
+ @Body
+
\ No newline at end of file
diff --git a/ImportUI/Components/Layout/ApplicationLayout.razor.cs b/ImportUI/Components/Layout/ApplicationLayout.razor.cs
new file mode 100644
index 0000000..bb8b0d6
--- /dev/null
+++ b/ImportUI/Components/Layout/ApplicationLayout.razor.cs
@@ -0,0 +1,16 @@
+using Microsoft.AspNetCore.Components;
+
+namespace ImportUI.Components.Layout;
+
+public partial class ApplicationLayout
+{
+ [CascadingParameter]
+ public BaseLayout? BaseLayout { get; set; }
+ public bool DrawerOpen { get; set; } = true;
+ public string AppText { get; set; } = "YouTube Import";
+
+ private void ToggleDrawerOpen()
+ {
+ DrawerOpen = !DrawerOpen;
+ }
+}
\ No newline at end of file
diff --git a/ImportUI/Components/Layout/BaseLayout.razor b/ImportUI/Components/Layout/BaseLayout.razor
new file mode 100644
index 0000000..dfacab8
--- /dev/null
+++ b/ImportUI/Components/Layout/BaseLayout.razor
@@ -0,0 +1,20 @@
+@inherits LayoutComponentBase
+
+
+
+
+
+
+
+
+
+ @Body
+
+
+
+
+
+ An unhandled error has occurred.
+
Reload
+
🗙
+
\ No newline at end of file
diff --git a/ImportUI/Components/Layout/BaseLayout.razor.cs b/ImportUI/Components/Layout/BaseLayout.razor.cs
new file mode 100644
index 0000000..be8d52c
--- /dev/null
+++ b/ImportUI/Components/Layout/BaseLayout.razor.cs
@@ -0,0 +1,37 @@
+using Microsoft.AspNetCore.Components;
+using MudBlazor;
+
+namespace ImportUI.Components.Layout;
+
+public partial class BaseLayout
+{
+ private readonly MudTheme _mudTheme = new MudTheme();
+ private MudThemeProvider? _themeProvider;
+ private bool _isDarkTheme = true;
+
+ public event EventHandler? OnDarkThemeChanged;
+
+ public bool DarkTheme
+ {
+ get => _isDarkTheme;
+ set
+ {
+ _isDarkTheme = value;
+ ThemeChanged();
+ }
+ }
+
+ private void ThemeChanged()
+ {
+ StateHasChanged();
+ }
+
+ protected override async Task OnAfterRenderAsync(bool firstRender)
+ {
+ if (firstRender && _themeProvider != null)
+ {
+ DarkTheme = await _themeProvider.GetSystemDarkModeAsync();
+ _themeProvider.IsDarkModeChanged = EventCallback.Factory.Create(this, x => OnDarkThemeChanged?.Invoke(this, x));
+ }
+ }
+}
\ No newline at end of file
diff --git a/ImportUI/Components/Layout/BaseLayout.razor.css b/ImportUI/Components/Layout/BaseLayout.razor.css
new file mode 100644
index 0000000..0d26cfc
--- /dev/null
+++ b/ImportUI/Components/Layout/BaseLayout.razor.css
@@ -0,0 +1,18 @@
+#blazor-error-ui {
+ background: lightyellow;
+ bottom: 0;
+ box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
+ display: none;
+ left: 0;
+ padding: 0.6rem 1.25rem 0.7rem 1.25rem;
+ position: fixed;
+ width: 100%;
+ z-index: 1000;
+}
+
+#blazor-error-ui .dismiss {
+ cursor: pointer;
+ position: absolute;
+ right: 0.75rem;
+ top: 0.5rem;
+}
diff --git a/ImportUI/Components/Layout/MainLayout.razor b/ImportUI/Components/Layout/MainLayout.razor
index 967b5e4..d2c2779 100644
--- a/ImportUI/Components/Layout/MainLayout.razor
+++ b/ImportUI/Components/Layout/MainLayout.razor
@@ -1,33 +1,16 @@
@inherits LayoutComponentBase
+@layout ApplicationLayout
-
-@* Required MudBlazor *@
-
-
-@* Needed for dialogs *@
-
-@* Needed for snackbars *@
-
-
-
-
-
+
+
+}
+else
+{
+
Error getting cascading parameter 'ApplicationLayout'!
+}
-
-
-
-
- @Body
-
-
-
-
-
- An unhandled error has occurred.
-
Reload
-
🗙
-
\ No newline at end of file
+@Body
\ No newline at end of file
diff --git a/ImportUI/Components/Layout/MainLayout.razor.cs b/ImportUI/Components/Layout/MainLayout.razor.cs
new file mode 100644
index 0000000..fbdf9ac
--- /dev/null
+++ b/ImportUI/Components/Layout/MainLayout.razor.cs
@@ -0,0 +1,9 @@
+using Microsoft.AspNetCore.Components;
+
+namespace ImportUI.Components.Layout;
+
+public partial class MainLayout
+{
+ [CascadingParameter]
+ public ApplicationLayout? ApplicationLayout { get; set; }
+}
\ No newline at end of file
diff --git a/ImportUI/Components/Layout/MainLayout.razor.css b/ImportUI/Components/Layout/MainLayout.razor.css
index 038baf1..97d3580 100644
--- a/ImportUI/Components/Layout/MainLayout.razor.css
+++ b/ImportUI/Components/Layout/MainLayout.razor.css
@@ -8,89 +8,3 @@ main {
flex: 1;
}
-.sidebar {
- background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%);
-}
-
-.top-row {
- background-color: #f7f7f7;
- border-bottom: 1px solid #d6d5d5;
- justify-content: flex-end;
- height: 3.5rem;
- display: flex;
- align-items: center;
-}
-
- .top-row ::deep a, .top-row ::deep .btn-link {
- white-space: nowrap;
- margin-left: 1.5rem;
- text-decoration: none;
- }
-
- .top-row ::deep a:hover, .top-row ::deep .btn-link:hover {
- text-decoration: underline;
- }
-
- .top-row ::deep a:first-child {
- overflow: hidden;
- text-overflow: ellipsis;
- }
-
-@media (max-width: 640.98px) {
- .top-row {
- justify-content: space-between;
- }
-
- .top-row ::deep a, .top-row ::deep .btn-link {
- margin-left: 0;
- }
-}
-
-@media (min-width: 641px) {
- .page {
- flex-direction: row;
- }
-
- .sidebar {
- width: 250px;
- height: 100vh;
- position: sticky;
- top: 0;
- }
-
- .top-row {
- position: sticky;
- top: 0;
- z-index: 1;
- }
-
- .top-row.auth ::deep a:first-child {
- flex: 1;
- text-align: right;
- width: 0;
- }
-
- .top-row, article {
- padding-left: 2rem !important;
- padding-right: 1.5rem !important;
- }
-}
-
-#blazor-error-ui {
- background: lightyellow;
- bottom: 0;
- box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
- display: none;
- left: 0;
- padding: 0.6rem 1.25rem 0.7rem 1.25rem;
- position: fixed;
- width: 100%;
- z-index: 1000;
-}
-
- #blazor-error-ui .dismiss {
- cursor: pointer;
- position: absolute;
- right: 0.75rem;
- top: 0.5rem;
- }
diff --git a/ImportUI/Components/Layout/NavMenu.razor b/ImportUI/Components/Layout/NavMenu.razor
index 8b6f316..0fbe68c 100644
--- a/ImportUI/Components/Layout/NavMenu.razor
+++ b/ImportUI/Components/Layout/NavMenu.razor
@@ -1,17 +1,9 @@
-
-
-
-
-
\ No newline at end of file
+
+
+ YouTube Import
+
+ Home
+ Accounts
+ Library
+ Playlists
+
\ No newline at end of file
diff --git a/ImportUI/Components/Layout/NavMenu.razor.css b/ImportUI/Components/Layout/NavMenu.razor.css
index 4e15395..e69de29 100644
--- a/ImportUI/Components/Layout/NavMenu.razor.css
+++ b/ImportUI/Components/Layout/NavMenu.razor.css
@@ -1,105 +0,0 @@
-.navbar-toggler {
- appearance: none;
- cursor: pointer;
- width: 3.5rem;
- height: 2.5rem;
- color: white;
- position: absolute;
- top: 0.5rem;
- right: 1rem;
- border: 1px solid rgba(255, 255, 255, 0.1);
- background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e") no-repeat center/1.75rem rgba(255, 255, 255, 0.1);
-}
-
-.navbar-toggler:checked {
- background-color: rgba(255, 255, 255, 0.5);
-}
-
-.top-row {
- height: 3.5rem;
- background-color: rgba(0,0,0,0.4);
-}
-
-.navbar-brand {
- font-size: 1.1rem;
-}
-
-.bi {
- display: inline-block;
- position: relative;
- width: 1.25rem;
- height: 1.25rem;
- margin-right: 0.75rem;
- top: -1px;
- background-size: cover;
-}
-
-.bi-house-door-fill-nav-menu {
- background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-house-door-fill' viewBox='0 0 16 16'%3E%3Cpath d='M6.5 14.5v-3.505c0-.245.25-.495.5-.495h2c.25 0 .5.25.5.5v3.5a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5v-7a.5.5 0 0 0-.146-.354L13 5.793V2.5a.5.5 0 0 0-.5-.5h-1a.5.5 0 0 0-.5.5v1.293L8.354 1.146a.5.5 0 0 0-.708 0l-6 6A.5.5 0 0 0 1.5 7.5v7a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5Z'/%3E%3C/svg%3E");
-}
-
-.bi-plus-square-fill-nav-menu {
- background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-plus-square-fill' viewBox='0 0 16 16'%3E%3Cpath d='M2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2zm6.5 4.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3a.5.5 0 0 1 1 0z'/%3E%3C/svg%3E");
-}
-
-.bi-list-nested-nav-menu {
- background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-list-nested' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' d='M4.5 11.5A.5.5 0 0 1 5 11h10a.5.5 0 0 1 0 1H5a.5.5 0 0 1-.5-.5zm-2-4A.5.5 0 0 1 3 7h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm-2-4A.5.5 0 0 1 1 3h10a.5.5 0 0 1 0 1H1a.5.5 0 0 1-.5-.5z'/%3E%3C/svg%3E");
-}
-
-.nav-item {
- font-size: 0.9rem;
- padding-bottom: 0.5rem;
-}
-
- .nav-item:first-of-type {
- padding-top: 1rem;
- }
-
- .nav-item:last-of-type {
- padding-bottom: 1rem;
- }
-
- .nav-item ::deep .nav-link {
- color: #d7d7d7;
- background: none;
- border: none;
- border-radius: 4px;
- height: 3rem;
- display: flex;
- align-items: center;
- line-height: 3rem;
- width: 100%;
- }
-
-.nav-item ::deep a.active {
- background-color: rgba(255,255,255,0.37);
- color: white;
-}
-
-.nav-item ::deep .nav-link:hover {
- background-color: rgba(255,255,255,0.1);
- color: white;
-}
-
-.nav-scrollable {
- display: none;
-}
-
-.navbar-toggler:checked ~ .nav-scrollable {
- display: block;
-}
-
-@media (min-width: 641px) {
- .navbar-toggler {
- display: none;
- }
-
- .nav-scrollable {
- /* Never collapse the sidebar for wide screens */
- display: block;
-
- /* Allow sidebar to scroll for tall menus */
- height: calc(100vh - 3.5rem);
- overflow-y: auto;
- }
-}