-
+
-
-
+
- @if (IsMenuOpen)
- {
-
-
- @Username
-
-
-
+
+
+ @Username
- }
+
+
+ -
+
+
+
+
+
diff --git a/src/AliasVault.Client/Main/Pages/MainBase.cs b/src/AliasVault.Client/Main/Pages/MainBase.cs
index ae1597ac0..a94b6fd2b 100644
--- a/src/AliasVault.Client/Main/Pages/MainBase.cs
+++ b/src/AliasVault.Client/Main/Pages/MainBase.cs
@@ -60,6 +60,12 @@ public class MainBase : OwningComponentBase
[Inject]
public DbService DbService { get; set; } = null!;
+ ///
+ /// Gets or sets the KeyboardShortcutService.
+ ///
+ [Inject]
+ public KeyboardShortcutService KeyboardShortcutService { get; set; } = null!;
+
///
/// Gets or sets the AuthService.
///
diff --git a/src/AliasVault.Client/Program.cs b/src/AliasVault.Client/Program.cs
index 576c3be60..d3757306d 100644
--- a/src/AliasVault.Client/Program.cs
+++ b/src/AliasVault.Client/Program.cs
@@ -67,6 +67,7 @@ builder.Services.AddScoped
();
builder.Services.AddScoped();
builder.Services.AddScoped();
builder.Services.AddScoped();
+builder.Services.AddScoped();
builder.Services.AddScoped();
builder.Services.AddSingleton();
diff --git a/src/AliasVault.Client/Services/CredentialService.cs b/src/AliasVault.Client/Services/CredentialService.cs
index 048891cf3..142129512 100644
--- a/src/AliasVault.Client/Services/CredentialService.cs
+++ b/src/AliasVault.Client/Services/CredentialService.cs
@@ -21,8 +21,34 @@ using Identity = AliasGenerators.Identity.Models.Identity;
///
/// Service class for alias operations.
///
-public class CredentialService(HttpClient httpClient, DbService dbService)
+public class CredentialService(HttpClient httpClient, DbService dbService, Config config)
{
+ ///
+ /// Gets the default email domain based on settings and available domains.
+ ///
+ /// Default email domain.
+ public string GetDefaultEmailDomain()
+ {
+ var defaultDomain = dbService.Settings.DefaultEmailDomain;
+
+ // Function to check if a domain is valid
+ bool IsValidDomain(string domain) =>
+ !string.IsNullOrEmpty(domain) &&
+ domain != "DISABLED.TLD" &&
+ (config.PublicEmailDomains.Contains(domain) || config.PrivateEmailDomains.Contains(domain));
+
+ // Get the first valid domain from private or public domains
+ string GetFirstValidDomain() =>
+ config.PrivateEmailDomains.Find(IsValidDomain) ??
+ config.PublicEmailDomains.FirstOrDefault() ??
+ "example.com";
+
+ // Use the default domain if it's valid, otherwise get the first valid domain
+ string domainToUse = IsValidDomain(defaultDomain) ? defaultDomain : GetFirstValidDomain();
+
+ return domainToUse;
+ }
+
///
/// Generate random identity by calling the IdentityGenerator API.
///
diff --git a/src/AliasVault.Client/Services/KeyboardShortcutService.cs b/src/AliasVault.Client/Services/KeyboardShortcutService.cs
new file mode 100644
index 000000000..7d2f5d6ce
--- /dev/null
+++ b/src/AliasVault.Client/Services/KeyboardShortcutService.cs
@@ -0,0 +1,108 @@
+//-----------------------------------------------------------------------
+//
+// Copyright (c) lanedirt. All rights reserved.
+// Licensed under the MIT license. See LICENSE.md file in the project root for full license information.
+//
+//-----------------------------------------------------------------------
+
+namespace AliasVault.Client.Services;
+
+using System;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Components;
+using Microsoft.JSInterop;
+
+///
+/// Service class for alias operations.
+///
+public class KeyboardShortcutService : IAsyncDisposable
+{
+ private readonly IJSRuntime _jsRuntime;
+ private readonly DotNetObjectReference _dotNetHelper;
+ private readonly NavigationManager _navigationManager;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// IJSRuntime instance.
+ /// NavigationManager instance.
+ public KeyboardShortcutService(IJSRuntime jsRuntime, NavigationManager navigationManager)
+ {
+ _jsRuntime = jsRuntime;
+ _dotNetHelper = DotNetObjectReference.Create(new CallbackWrapper());
+ _navigationManager = navigationManager;
+
+ _ = RegisterStaticShortcuts();
+ }
+
+ ///
+ /// Registers a keyboard shortcut with the given keys and callback.
+ ///
+ /// The keyboard keys.
+ /// Callback when shortcut is pressed.
+ /// Task.
+ public async Task RegisterShortcutAsync(string keys, Func callback)
+ {
+ _dotNetHelper.Value.RegisterCallback(keys, callback);
+ await _jsRuntime.InvokeVoidAsync("keyboardShortcuts.registerShortcut", keys, _dotNetHelper);
+ }
+
+ ///
+ /// Unregisters a keyboard shortcut with the given keys.
+ ///
+ /// The keyboard keys.
+ /// Task.
+ public async Task UnregisterShortcutAsync(string keys)
+ {
+ _dotNetHelper.Value.UnregisterCallback(keys);
+ await _jsRuntime.InvokeVoidAsync("keyboardShortcuts.unregisterShortcut", keys);
+ }
+
+ ///
+ /// Disposes the service.
+ ///
+ /// ValueTask.
+ public async ValueTask DisposeAsync()
+ {
+ await _jsRuntime.InvokeVoidAsync("keyboardShortcuts.unregisterAllShortcuts");
+ _dotNetHelper.Dispose();
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Registers static shortcuts that are always available.
+ ///
+ private async Task RegisterStaticShortcuts()
+ {
+ // Global shortcut: Go home
+ await RegisterShortcutAsync("gh", () =>
+ {
+ _navigationManager.NavigateTo("/");
+ return Task.CompletedTask;
+ });
+ }
+
+ private class CallbackWrapper
+ {
+ private readonly Dictionary> _callbacks = new Dictionary>();
+
+ public void RegisterCallback(string keys, Func callback)
+ {
+ _callbacks[keys] = callback;
+ }
+
+ public void UnregisterCallback(string keys)
+ {
+ _callbacks.Remove(keys);
+ }
+
+ [JSInvokable]
+ public async Task Invoke(string keys)
+ {
+ if (_callbacks.TryGetValue(keys, out var callback))
+ {
+ await callback();
+ }
+ }
+ }
+}
diff --git a/src/AliasVault.Client/_Imports.razor b/src/AliasVault.Client/_Imports.razor
index 5456c412c..0c921c70c 100644
--- a/src/AliasVault.Client/_Imports.razor
+++ b/src/AliasVault.Client/_Imports.razor
@@ -19,6 +19,7 @@
@using AliasVault.Client.Main.Components.Forms
@using AliasVault.Client.Main.Components.Layout
@using AliasVault.Client.Main.Components.Loading
+@using AliasVault.Client.Main.Components.Widgets
@using AliasVault.Client.Main.Models
@using AliasVault.Client.Services
@using AliasVault.Client.Services.Auth
diff --git a/src/AliasVault.Client/wwwroot/css/tailwind.css b/src/AliasVault.Client/wwwroot/css/tailwind.css
index 7ebfd9c4c..1f7be715e 100644
--- a/src/AliasVault.Client/wwwroot/css/tailwind.css
+++ b/src/AliasVault.Client/wwwroot/css/tailwind.css
@@ -566,14 +566,6 @@ video {
border-width: 0;
}
-.visible {
- visibility: visible;
-}
-
-.invisible {
- visibility: hidden;
-}
-
.fixed {
position: fixed;
}
@@ -612,6 +604,10 @@ video {
right: 0px;
}
+.right-1 {
+ right: 0.25rem;
+}
+
.right-10 {
right: 2.5rem;
}
@@ -620,26 +616,10 @@ video {
top: 2.5rem;
}
-.right-4 {
- right: 1rem;
-}
-
-.right-1 {
- right: 0.25rem;
-}
-
-.right-5 {
- right: 1.25rem;
-}
-
.top-20 {
top: 5rem;
}
-.z-10 {
- z-index: 10;
-}
-
.z-30 {
z-index: 30;
}
@@ -648,10 +628,6 @@ video {
z-index: 50;
}
-.z-20 {
- z-index: 20;
-}
-
.col-span-2 {
grid-column: span 2 / span 2;
}
@@ -716,6 +692,10 @@ video {
margin-left: 0.25rem;
}
+.ml-2 {
+ margin-left: 0.5rem;
+}
+
.ml-3 {
margin-left: 0.75rem;
}
@@ -752,6 +732,10 @@ video {
margin-top: 0.5rem;
}
+.mt-3 {
+ margin-top: 0.75rem;
+}
+
.mt-4 {
margin-top: 1rem;
}
@@ -764,18 +748,6 @@ video {
margin-top: 2rem;
}
-.mt-3 {
- margin-top: 0.75rem;
-}
-
-.mr-1 {
- margin-right: 0.25rem;
-}
-
-.ml-2 {
- margin-left: 0.5rem;
-}
-
.block {
display: block;
}
@@ -816,6 +788,10 @@ video {
height: 3rem;
}
+.h-3 {
+ height: 0.75rem;
+}
+
.h-4 {
height: 1rem;
}
@@ -840,18 +816,10 @@ video {
height: 2.25rem;
}
-.h-\[700px\] {
- height: 700px;
-}
-
.h-full {
height: 100%;
}
-.h-3 {
- height: 0.75rem;
-}
-
.w-1\/2 {
width: 50%;
}
@@ -868,6 +836,14 @@ video {
width: 7rem;
}
+.w-3 {
+ width: 0.75rem;
+}
+
+.w-3\/4 {
+ width: 75%;
+}
+
.w-4 {
width: 1rem;
}
@@ -896,20 +872,12 @@ video {
width: 2rem;
}
-.w-full {
- width: 100%;
-}
-
.w-96 {
width: 24rem;
}
-.w-3 {
- width: 0.75rem;
-}
-
-.w-3\/4 {
- width: 75%;
+.w-full {
+ width: 100%;
}
.min-w-full {
@@ -936,16 +904,6 @@ video {
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
-@keyframes spin {
- to {
- transform: rotate(360deg);
- }
-}
-
-.animate-spin {
- animation: spin 1s linear infinite;
-}
-
@keyframes pulse {
50% {
opacity: .5;
@@ -956,31 +914,14 @@ video {
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
-@keyframes ping {
- 75%, 100% {
- transform: scale(2);
- opacity: 0;
+@keyframes spin {
+ to {
+ transform: rotate(360deg);
}
}
-.animate-ping {
- animation: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite;
-}
-
-@keyframes bounce {
- 0%, 100% {
- transform: translateY(-25%);
- animation-timing-function: cubic-bezier(0.8,0,1,1);
- }
-
- 50% {
- transform: none;
- animation-timing-function: cubic-bezier(0,0,0.2,1);
- }
-}
-
-.animate-bounce {
- animation: bounce 1s infinite;
+.animate-spin {
+ animation: spin 1s linear infinite;
}
.cursor-pointer {
@@ -1069,6 +1010,12 @@ video {
margin-left: calc(0.25rem * calc(1 - var(--tw-space-x-reverse)));
}
+.space-x-2 > :not([hidden]) ~ :not([hidden]) {
+ --tw-space-x-reverse: 0;
+ margin-right: calc(0.5rem * var(--tw-space-x-reverse));
+ margin-left: calc(0.5rem * calc(1 - var(--tw-space-x-reverse)));
+}
+
.space-x-4 > :not([hidden]) ~ :not([hidden]) {
--tw-space-x-reverse: 0;
margin-right: calc(1rem * var(--tw-space-x-reverse));
@@ -1099,12 +1046,6 @@ video {
margin-bottom: calc(1.5rem * var(--tw-space-y-reverse));
}
-.space-x-2 > :not([hidden]) ~ :not([hidden]) {
- --tw-space-x-reverse: 0;
- margin-right: calc(0.5rem * var(--tw-space-x-reverse));
- margin-left: calc(0.5rem * calc(1 - var(--tw-space-x-reverse)));
-}
-
.divide-y > :not([hidden]) ~ :not([hidden]) {
--tw-divide-y-reverse: 0;
border-top-width: calc(1px * calc(1 - var(--tw-divide-y-reverse)));
@@ -1221,16 +1162,6 @@ video {
border-color: rgb(34 197 94 / var(--tw-border-opacity));
}
-.border-red-300 {
- --tw-border-opacity: 1;
- border-color: rgb(252 165 165 / var(--tw-border-opacity));
-}
-
-.border-primary-300 {
- --tw-border-opacity: 1;
- border-color: rgb(248 185 99 / var(--tw-border-opacity));
-}
-
.border-primary-100 {
--tw-border-opacity: 1;
border-color: rgb(253 222 133 / var(--tw-border-opacity));
@@ -1266,6 +1197,11 @@ video {
background-color: rgb(107 114 128 / var(--tw-bg-opacity));
}
+.bg-gray-600 {
+ --tw-bg-opacity: 1;
+ background-color: rgb(75 85 99 / var(--tw-bg-opacity));
+}
+
.bg-gray-700 {
--tw-bg-opacity: 1;
background-color: rgb(55 65 81 / var(--tw-bg-opacity));
@@ -1276,21 +1212,26 @@ video {
background-color: rgb(31 41 55 / var(--tw-bg-opacity));
}
-.bg-gray-900 {
- --tw-bg-opacity: 1;
- background-color: rgb(17 24 39 / var(--tw-bg-opacity));
-}
-
.bg-green-50 {
--tw-bg-opacity: 1;
background-color: rgb(240 253 244 / var(--tw-bg-opacity));
}
+.bg-green-500 {
+ --tw-bg-opacity: 1;
+ background-color: rgb(34 197 94 / var(--tw-bg-opacity));
+}
+
.bg-green-600 {
--tw-bg-opacity: 1;
background-color: rgb(22 163 74 / var(--tw-bg-opacity));
}
+.bg-primary-300 {
+ --tw-bg-opacity: 1;
+ background-color: rgb(248 185 99 / var(--tw-bg-opacity));
+}
+
.bg-primary-600 {
--tw-bg-opacity: 1;
background-color: rgb(214 131 56 / var(--tw-bg-opacity));
@@ -1316,21 +1257,6 @@ video {
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
}
-.bg-gray-300 {
- --tw-bg-opacity: 1;
- background-color: rgb(209 213 219 / var(--tw-bg-opacity));
-}
-
-.bg-gray-600 {
- --tw-bg-opacity: 1;
- background-color: rgb(75 85 99 / var(--tw-bg-opacity));
-}
-
-.bg-primary-300 {
- --tw-bg-opacity: 1;
- background-color: rgb(248 185 99 / var(--tw-bg-opacity));
-}
-
.bg-opacity-50 {
--tw-bg-opacity: 0.5;
}
@@ -1339,6 +1265,20 @@ video {
--tw-bg-opacity: 0.75;
}
+.bg-gradient-to-r {
+ background-image: linear-gradient(to right, var(--tw-gradient-stops));
+}
+
+.from-primary-500 {
+ --tw-gradient-from: #f49541 var(--tw-gradient-from-position);
+ --tw-gradient-to: rgb(244 149 65 / 0) var(--tw-gradient-to-position);
+ --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);
+}
+
+.to-primary-600 {
+ --tw-gradient-to: #d68338 var(--tw-gradient-to-position);
+}
+
.fill-primary-600 {
fill: #d68338;
}
@@ -1355,6 +1295,10 @@ video {
padding: 1rem;
}
+.p-5 {
+ padding: 1.25rem;
+}
+
.p-6 {
padding: 1.5rem;
}
@@ -1363,10 +1307,6 @@ video {
padding: 2rem;
}
-.p-5 {
- padding: 1.25rem;
-}
-
.px-2 {
padding-left: 0.5rem;
padding-right: 0.5rem;
@@ -1392,6 +1332,11 @@ video {
padding-right: 1.5rem;
}
+.px-7 {
+ padding-left: 1.75rem;
+ padding-right: 1.75rem;
+}
+
.py-1 {
padding-top: 0.25rem;
padding-bottom: 0.25rem;
@@ -1422,9 +1367,8 @@ video {
padding-bottom: 1.5rem;
}
-.px-7 {
- padding-left: 1.75rem;
- padding-right: 1.75rem;
+.pb-2 {
+ padding-bottom: 0.5rem;
}
.pr-10 {
@@ -1443,6 +1387,14 @@ video {
padding-top: 4rem;
}
+.pt-2 {
+ padding-top: 0.5rem;
+}
+
+.pt-4 {
+ padding-top: 1rem;
+}
+
.pt-6 {
padding-top: 1.5rem;
}
@@ -1451,10 +1403,6 @@ video {
padding-top: 2rem;
}
-.pt-4 {
- padding-top: 1rem;
-}
-
.text-left {
text-align: left;
}
@@ -1463,6 +1411,10 @@ video {
text-align: center;
}
+.text-start {
+ text-align: start;
+}
+
.align-middle {
vertical-align: middle;
}
@@ -1618,15 +1570,6 @@ video {
color: rgb(255 255 255 / var(--tw-text-opacity));
}
-.text-red-600 {
- --tw-text-opacity: 1;
- color: rgb(220 38 38 / var(--tw-text-opacity));
-}
-
-.opacity-0 {
- opacity: 0;
-}
-
.opacity-25 {
opacity: 0.25;
}
@@ -1663,15 +1606,21 @@ video {
outline-width: 0px;
}
+.transition {
+ transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter;
+ transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
+ transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter;
+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
+ transition-duration: 150ms;
+}
+
.transition-colors {
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}
-.transition-opacity {
- transition-property: opacity;
- transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
+.duration-150 {
transition-duration: 150ms;
}
@@ -1679,8 +1628,14 @@ video {
transition-duration: 200ms;
}
-.duration-300 {
- transition-duration: 300ms;
+.ease-in-out {
+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
+}
+
+.hover\:scale-105:hover {
+ --tw-scale-x: 1.05;
+ --tw-scale-y: 1.05;
+ transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.hover\:bg-blue-600:hover {
@@ -1703,6 +1658,11 @@ video {
background-color: rgb(229 231 235 / var(--tw-bg-opacity));
}
+.hover\:bg-gray-300:hover {
+ --tw-bg-opacity: 1;
+ background-color: rgb(209 213 219 / var(--tw-bg-opacity));
+}
+
.hover\:bg-gray-50:hover {
--tw-bg-opacity: 1;
background-color: rgb(249 250 251 / var(--tw-bg-opacity));
@@ -1718,6 +1678,11 @@ video {
background-color: rgb(21 128 61 / var(--tw-bg-opacity));
}
+.hover\:bg-primary-400:hover {
+ --tw-bg-opacity: 1;
+ background-color: rgb(246 167 82 / var(--tw-bg-opacity));
+}
+
.hover\:bg-primary-700:hover {
--tw-bg-opacity: 1;
background-color: rgb(184 112 47 / var(--tw-bg-opacity));
@@ -1738,14 +1703,24 @@ video {
background-color: rgb(153 27 27 / var(--tw-bg-opacity));
}
-.hover\:bg-gray-300:hover {
- --tw-bg-opacity: 1;
- background-color: rgb(209 213 219 / var(--tw-bg-opacity));
+.hover\:from-primary-600:hover {
+ --tw-gradient-from: #d68338 var(--tw-gradient-from-position);
+ --tw-gradient-to: rgb(214 131 56 / 0) var(--tw-gradient-to-position);
+ --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);
}
-.hover\:bg-primary-400:hover {
- --tw-bg-opacity: 1;
- background-color: rgb(246 167 82 / var(--tw-bg-opacity));
+.hover\:to-primary-700:hover {
+ --tw-gradient-to: #b8702f var(--tw-gradient-to-position);
+}
+
+.hover\:text-blue-700:hover {
+ --tw-text-opacity: 1;
+ color: rgb(29 78 216 / var(--tw-text-opacity));
+}
+
+.hover\:text-blue-800:hover {
+ --tw-text-opacity: 1;
+ color: rgb(30 64 175 / var(--tw-text-opacity));
}
.hover\:text-gray-500:hover {
@@ -1778,50 +1753,45 @@ video {
color: rgb(255 255 255 / var(--tw-text-opacity));
}
-.hover\:text-blue-800:hover {
- --tw-text-opacity: 1;
- color: rgb(30 64 175 / var(--tw-text-opacity));
-}
-
.hover\:underline:hover {
text-decoration-line: underline;
}
-.focus\:border-primary-500:focus {
- --tw-border-opacity: 1;
- border-color: rgb(244 149 65 / var(--tw-border-opacity));
-}
-
.focus\:border-blue-500:focus {
--tw-border-opacity: 1;
border-color: rgb(59 130 246 / var(--tw-border-opacity));
}
+.focus\:border-primary-500:focus {
+ --tw-border-opacity: 1;
+ border-color: rgb(244 149 65 / var(--tw-border-opacity));
+}
+
.focus\:outline-none:focus {
outline: 2px solid transparent;
outline-offset: 2px;
}
-.focus\:ring-4:focus {
- --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
- --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color);
- box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
-}
-
.focus\:ring-2:focus {
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
}
+.focus\:ring-4:focus {
+ --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
+ --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color);
+ box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
+}
+
.focus\:ring-blue-300:focus {
--tw-ring-opacity: 1;
--tw-ring-color: rgb(147 197 253 / var(--tw-ring-opacity));
}
-.focus\:ring-gray-200:focus {
+.focus\:ring-blue-500:focus {
--tw-ring-opacity: 1;
- --tw-ring-color: rgb(229 231 235 / var(--tw-ring-opacity));
+ --tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity));
}
.focus\:ring-gray-300:focus {
@@ -1829,6 +1799,11 @@ video {
--tw-ring-color: rgb(209 213 219 / var(--tw-ring-opacity));
}
+.focus\:ring-gray-400:focus {
+ --tw-ring-opacity: 1;
+ --tw-ring-color: rgb(156 163 175 / var(--tw-ring-opacity));
+}
+
.focus\:ring-green-300:focus {
--tw-ring-opacity: 1;
--tw-ring-color: rgb(134 239 172 / var(--tw-ring-opacity));
@@ -1849,25 +1824,16 @@ video {
--tw-ring-color: rgb(252 165 165 / var(--tw-ring-opacity));
}
-.focus\:ring-indigo-500:focus {
- --tw-ring-opacity: 1;
- --tw-ring-color: rgb(99 102 241 / var(--tw-ring-opacity));
-}
-
-.focus\:ring-gray-400:focus {
- --tw-ring-opacity: 1;
- --tw-ring-color: rgb(156 163 175 / var(--tw-ring-opacity));
-}
-
-.focus\:ring-blue-500:focus {
- --tw-ring-opacity: 1;
- --tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity));
-}
-
.focus\:ring-offset-2:focus {
--tw-ring-offset-width: 2px;
}
+.active\:scale-95:active {
+ --tw-scale-x: .95;
+ --tw-scale-y: .95;
+ transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
+}
+
.dark\:divide-gray-600:is(.dark *) > :not([hidden]) ~ :not([hidden]) {
--tw-divide-opacity: 1;
border-color: rgb(75 85 99 / var(--tw-divide-opacity));
@@ -1937,6 +1903,16 @@ video {
--tw-bg-opacity: 0.8;
}
+.dark\:from-primary-400:is(.dark *) {
+ --tw-gradient-from: #f6a752 var(--tw-gradient-from-position);
+ --tw-gradient-to: rgb(246 167 82 / 0) var(--tw-gradient-to-position);
+ --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);
+}
+
+.dark\:to-primary-500:is(.dark *) {
+ --tw-gradient-to: #f49541 var(--tw-gradient-to-position);
+}
+
.dark\:text-blue-400:is(.dark *) {
--tw-text-opacity: 1;
color: rgb(96 165 250 / var(--tw-text-opacity));
@@ -2011,6 +1987,11 @@ video {
background-color: rgb(37 99 235 / var(--tw-bg-opacity));
}
+.dark\:hover\:bg-gray-500:hover:is(.dark *) {
+ --tw-bg-opacity: 1;
+ background-color: rgb(107 114 128 / var(--tw-bg-opacity));
+}
+
.dark\:hover\:bg-gray-600:hover:is(.dark *) {
--tw-bg-opacity: 1;
background-color: rgb(75 85 99 / var(--tw-bg-opacity));
@@ -2041,9 +2022,19 @@ video {
background-color: rgb(220 38 38 / var(--tw-bg-opacity));
}
-.dark\:hover\:bg-gray-500:hover:is(.dark *) {
- --tw-bg-opacity: 1;
- background-color: rgb(107 114 128 / var(--tw-bg-opacity));
+.dark\:hover\:from-primary-500:hover:is(.dark *) {
+ --tw-gradient-from: #f49541 var(--tw-gradient-from-position);
+ --tw-gradient-to: rgb(244 149 65 / 0) var(--tw-gradient-to-position);
+ --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);
+}
+
+.dark\:hover\:to-primary-600:hover:is(.dark *) {
+ --tw-gradient-to: #d68338 var(--tw-gradient-to-position);
+}
+
+.dark\:hover\:text-blue-200:hover:is(.dark *) {
+ --tw-text-opacity: 1;
+ color: rgb(191 219 254 / var(--tw-text-opacity));
}
.dark\:hover\:text-primary-500:hover:is(.dark *) {
@@ -2056,9 +2047,9 @@ video {
color: rgb(255 255 255 / var(--tw-text-opacity));
}
-.dark\:hover\:text-blue-200:hover:is(.dark *) {
- --tw-text-opacity: 1;
- color: rgb(191 219 254 / var(--tw-text-opacity));
+.dark\:focus\:border-blue-500:focus:is(.dark *) {
+ --tw-border-opacity: 1;
+ border-color: rgb(59 130 246 / var(--tw-border-opacity));
}
.dark\:focus\:border-primary-500:focus:is(.dark *) {
@@ -2066,9 +2057,14 @@ video {
border-color: rgb(244 149 65 / var(--tw-border-opacity));
}
-.dark\:focus\:border-blue-500:focus:is(.dark *) {
- --tw-border-opacity: 1;
- border-color: rgb(59 130 246 / var(--tw-border-opacity));
+.dark\:focus\:ring-blue-500:focus:is(.dark *) {
+ --tw-ring-opacity: 1;
+ --tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity));
+}
+
+.dark\:focus\:ring-blue-600:focus:is(.dark *) {
+ --tw-ring-opacity: 1;
+ --tw-ring-color: rgb(37 99 235 / var(--tw-ring-opacity));
}
.dark\:focus\:ring-blue-800:focus:is(.dark *) {
@@ -2121,16 +2117,6 @@ video {
--tw-ring-color: rgb(127 29 29 / var(--tw-ring-opacity));
}
-.dark\:focus\:ring-blue-500:focus:is(.dark *) {
- --tw-ring-opacity: 1;
- --tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity));
-}
-
-.dark\:focus\:ring-blue-600:focus:is(.dark *) {
- --tw-ring-opacity: 1;
- --tw-ring-color: rgb(37 99 235 / var(--tw-ring-opacity));
-}
-
@media (min-width: 640px) {
.sm\:col-span-3 {
grid-column: span 3 / span 3;
@@ -2148,10 +2134,6 @@ video {
width: auto;
}
- .sm\:flex-row {
- flex-direction: row;
- }
-
.sm\:space-x-4 > :not([hidden]) ~ :not([hidden]) {
--tw-space-x-reverse: 0;
margin-right: calc(1rem * var(--tw-space-x-reverse));
diff --git a/src/AliasVault.Client/wwwroot/index.template.html b/src/AliasVault.Client/wwwroot/index.template.html
index e13ca2199..64d395c8f 100644
--- a/src/AliasVault.Client/wwwroot/index.template.html
+++ b/src/AliasVault.Client/wwwroot/index.template.html
@@ -50,6 +50,7 @@
+