Refactor page headers in client to shared component (#220)

This commit is contained in:
Leendert de Borst
2024-10-07 14:34:53 +02:00
parent 4c5e312f11
commit 35f35b8bbe
36 changed files with 297 additions and 295 deletions

View File

@@ -1,52 +0,0 @@
@inherits ComponentBase
<nav class="flex mb-5">
<ol class="inline-flex items-center space-x-1 text-sm font-medium md:space-x-2">
<li class="inline-flex items-center">
<a href="/" class="inline-flex items-center text-gray-700 hover:text-primary-600 dark:text-gray-300 dark:hover:text-primary-500">
<svg class="w-5 h-5 mr-2.5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M10.707 2.293a1 1 0 00-1.414 0l-7 7a1 1 0 001.414 1.414L4 10.414V17a1 1 0 001 1h2a1 1 0 001-1v-2a1 1 0 011-1h2a1 1 0 011 1v2a1 1 0 001 1h2a1 1 0 001-1v-6.586l.293.293a1 1 0 001.414-1.414l-7-7z"></path></svg>
Home
</a>
</li>
@foreach (var item in BreadcrumbItems)
{
@if (item.Url is not null)
{
<li>
<div class="flex items-center">
<svg class="w-6 h-6 text-gray-400" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"></path></svg>
<a href="@item.Url" class="ml-1 text-gray-700 hover:text-primary-600 md:ml-2 dark:text-gray-300 dark:hover:text-primary-500">@item.DisplayName</a>
</div>
</li>
}
else
{
<li>
<div class="flex items-center">
<svg class="w-6 h-6 text-gray-400" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"></path></svg>
@item.DisplayName
</div>
</li>
}
}
</ol>
</nav>
@code {
/// <summary>
/// Gets or sets the list of breadcrumb items.
/// </summary>
[Parameter]
public List<BreadcrumbItem> BreadcrumbItems { get; set; } = new();
/// <inheritdoc />
protected override void OnInitialized()
{
base.OnInitialized();
// Remove first item if it is the home page
if (BreadcrumbItems.Any() && BreadcrumbItems[0].DisplayName == "Home")
{
BreadcrumbItems.RemoveAt(0);
}
}
}

View File

@@ -1,24 +0,0 @@
//-----------------------------------------------------------------------
// <copyright file="BreadcrumbItem.cs" company="lanedirt">
// Copyright (c) lanedirt. All rights reserved.
// Licensed under the MIT license. See LICENSE.md file in the project root for full license information.
// </copyright>
//-----------------------------------------------------------------------
namespace AliasVault.Admin.Main.Models;
/// <summary>
/// Breadcrumb item model.
/// </summary>
public class BreadcrumbItem
{
/// <summary>
/// Gets or sets the display name.
/// </summary>
public string? DisplayName { get; set; }
/// <summary>
/// Gets or sets the URL.
/// </summary>
public string? Url { get; set; }
}

View File

@@ -5,7 +5,7 @@
<div class="grid grid-cols-1 px-4 pt-6 xl:grid-cols-3 xl:gap-4 dark:bg-gray-900">
<div class="mb-4 col-span-full xl:mb-2">
<div class="flex items-center justify-between">
<h1 class="text-xl font-semibold text-gray-900 sm:text-2xl dark:text-white">Manage account</h1>
<H1>Manage account</H1>
</div>
<p>Manage your profile here.</p>
</div>

View File

@@ -7,7 +7,7 @@
<div class="mb-4 col-span-full xl:mb-2">
<Breadcrumb BreadcrumbItems="BreadcrumbItems" />
<div class="flex items-center justify-between">
<h1 class="text-xl font-semibold text-gray-900 sm:text-2xl dark:text-white">Emails</h1>
<H1>Emails</H1>
<RefreshButton OnClick="RefreshData" ButtonText="Refresh" />
</div>
<p>This page gives an overview of recently received mails by this AliasVault server.</p>

View File

@@ -7,7 +7,7 @@
<div class="mb-4 col-span-full xl:mb-2">
<Breadcrumb BreadcrumbItems="BreadcrumbItems" />
<div class="flex items-center justify-between">
<h1 class="text-xl font-semibold text-gray-900 sm:text-2xl dark:text-white">AliasVault Admin</h1>
<H1>AliasVault Admin</H1>
</div>
<p>Welcome to the AliasVault admin portal.</p>
</div>

View File

@@ -8,7 +8,7 @@
<div class="mb-4 col-span-full xl:mb-2">
<Breadcrumb BreadcrumbItems="BreadcrumbItems" />
<div class="flex items-center justify-between">
<h1 class="text-xl font-semibold text-gray-900 sm:text-2xl dark:text-white">Auth logs</h1>
<H1>Auth logs</H1>
<div class="flex items-end space-x-2">
<DeleteButton OnClick="DeleteLogsWithConfirmation" ButtonText="Delete all logs" />
<RefreshButton OnClick="RefreshData" ButtonText="Refresh" />

View File

@@ -7,7 +7,7 @@
<div class="mb-4 col-span-full xl:mb-2">
<Breadcrumb BreadcrumbItems="BreadcrumbItems" />
<div class="flex items-center justify-between">
<h1 class="text-xl font-semibold text-gray-900 sm:text-2xl dark:text-white">General logs</h1>
<H1>General logs</H1>
<div class="flex items-end space-x-2">
<DeleteButton OnClick="DeleteLogsWithConfirmation" ButtonText="Delete all logs" />
<RefreshButton OnClick="RefreshData" ButtonText="Refresh" />

View File

@@ -7,7 +7,7 @@
<div class="mb-4 col-span-full xl:mb-2">
<Breadcrumb BreadcrumbItems="BreadcrumbItems" />
<div class="flex items-center justify-between">
<h1 class="text-xl font-semibold text-gray-900 sm:text-2xl dark:text-white">Delete user</h1>
<H1>Delete user</H1>
</div>
<p>You can delete the user below.</p>
</div>

View File

@@ -7,7 +7,7 @@
<div class="mb-4 col-span-full xl:mb-2">
<Breadcrumb BreadcrumbItems="BreadcrumbItems" />
<div class="flex items-center justify-between">
<h1 class="text-xl font-semibold text-gray-900 sm:text-2xl dark:text-white">Users</h1>
<H1>Users</H1>
<RefreshButton OnClick="RefreshData" ButtonText="Refresh" />
</div>
<p>This page gives an overview of all registered users and the associated vaults.</p>

View File

@@ -14,7 +14,7 @@ else
<Breadcrumb BreadcrumbItems="BreadcrumbItems"/>
<div class="flex items-center justify-between">
<h1 class="text-xl font-semibold text-gray-900 sm:text-2xl dark:text-white">View user</h1>
<H1>View user</H1>
<div class="flex">
<a href="/users/@Id/delete" class="mr-2 px-4 py-2 text-white bg-red-600 rounded-lg hover:bg-red-700 focus:ring-4 focus:ring-red-300 dark:bg-red-500 dark:hover:bg-red-600 dark:focus:ring-red-800">
Delete user
@@ -121,7 +121,7 @@ else
</div>
</div>
</div>
<div class="p-4 mb-4 bg-white border border-gray-200 rounded-lg shadow-sm dark:border-gray-700 sm:p-6 dark:bg-gray-800">
<div class="items-center">
<div>

View File

@@ -20,6 +20,7 @@
@using AliasVault.RazorComponents
@using AliasVault.RazorComponents.Alerts
@using AliasVault.RazorComponents.Buttons
@using AliasVault.RazorComponents.Headings
@using AliasVault.Admin.Main.Models
@using AliasVault.Admin.Main.Pages
@using AliasVault.Admin.Services

View File

@@ -11,39 +11,15 @@
@inject IJSRuntime JSRuntime
@implements IAsyncDisposable
@if (EditMode)
{
<LayoutPageTitle>Edit credentials</LayoutPageTitle>
}
else {
<LayoutPageTitle>Add credentials</LayoutPageTitle>
}
<div class="grid grid-cols-1 px-4 pt-6 xl:grid-cols-3 xl:gap-4 dark:bg-gray-900">
<div class="mb-4 col-span-full xl:mb-2">
<Breadcrumb BreadcrumbItems="BreadcrumbItems" />
<div class="flex items-center justify-between">
@if (EditMode)
{
<h1 class="text-xl font-semibold text-gray-900 sm:text-2xl dark:text-white">Edit credentials</h1>
}
else {
<h1 class="text-xl font-semibold text-gray-900 sm:text-2xl dark:text-white">Add credentials</h1>
}
<div>
<button type="button" @onclick="TriggerFormSubmit" class="px-4 py-2 text-white bg-green-600 rounded-lg hover:bg-green-700 focus:ring-4 focus:ring-green-300 dark:bg-green-500 dark:hover:bg-green-600 dark:focus:ring-green-800">Save Credentials</button>
<button type="button" @onclick="Cancel" class="px-4 py-2 text-white bg-red-600 rounded-lg hover:bg-red-700 focus:ring-4 focus:ring-red-300 dark:bg-red-500 dark:hover:bg-red-600 dark:focus:ring-red-800">Cancel</button>
</div>
</div>
@if (EditMode)
{
<p>Edit the existing credentials entry below.</p>
}
else {
<p>Create a new credentials entry below.</p>
}
</div>
</div>
<PageHeader
BreadcrumbItems="@BreadcrumbItems"
Title="@(EditMode ? "Edit credentials" : "Add credentials")"
Description="@(EditMode ? "Edit the existing credentials entry below." : "Create a new credentials entry below.")">
<CustomActions>
<ConfirmButton OnClick="TriggerFormSubmit">Save Credentials</ConfirmButton>
<CancelButton OnClick="Cancel">Cancel</CancelButton>
</CustomActions>
</PageHeader>
@if (Loading)
{

View File

@@ -4,15 +4,11 @@
<LayoutPageTitle>Delete credentials entry</LayoutPageTitle>
<div class="grid grid-cols-1 px-4 pt-6 xl:grid-cols-3 xl:gap-4 dark:bg-gray-900">
<div class="mb-4 col-span-full xl:mb-2">
<Breadcrumb BreadcrumbItems="BreadcrumbItems" />
<div class="flex items-center justify-between">
<h1 class="text-xl font-semibold text-gray-900 sm:text-2xl dark:text-white">Delete credentials</h1>
</div>
<p>You can delete a credentials entry below.</p>
</div>
</div>
<PageHeader
BreadcrumbItems="@BreadcrumbItems"
Title="Delete credentials"
Description="You can delete a credentials entry below.">
</PageHeader>
@if (IsLoading)
{
@@ -55,8 +51,8 @@ else
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
BreadcrumbItems.Add(new BreadcrumbItem { Url = "credentials/" + Id, DisplayName = "View Credentials Entry" });
BreadcrumbItems.Add(new BreadcrumbItem { DisplayName = "Delete credentials" });
BreadcrumbItems.Add(new BreadcrumbItem { Url = "credentials/" + Id, DisplayName = "View credentials entry" });
BreadcrumbItems.Add(new BreadcrumbItem { DisplayName = "Delete credential" });
}
/// <inheritdoc />

View File

@@ -4,16 +4,14 @@
<LayoutPageTitle>Home</LayoutPageTitle>
<div class="grid grid-cols-1 px-4 pt-6 xl:grid-cols-3 xl:gap-4 dark:bg-gray-900">
<div class="mb-4 col-span-full xl:mb-2">
<Breadcrumb BreadcrumbItems="BreadcrumbItems" />
<div class="flex items-center justify-between">
<h1 class="text-xl font-semibold text-gray-900 sm:text-2xl dark:text-white">Credentials</h1>
<RefreshButton OnClick="LoadCredentialsAsync" ButtonText="Refresh" />
</div>
<p>Find all of your credentials below.</p>
</div>
</div>
<PageHeader
BreadcrumbItems="@BreadcrumbItems"
Title="Credentials"
Description="Find all of your credentials below.">
<CustomActions>
<RefreshButton OnClick="LoadCredentialsAsync" ButtonText="Refresh" />
</CustomActions>
</PageHeader>
@if (IsLoading)
{

View File

@@ -10,24 +10,24 @@
}
else
{
<PageHeader
BreadcrumbItems="@BreadcrumbItems"
Title="View credentials entry">
<CustomActions>
<LinkButton
Text="Edit"
AdditionalText="credentials entry"
Href="@($"/credentials/{Id}/edit")"
Color="primary" />
<LinkButton
Text="Delete"
AdditionalText="credentials entry"
Href="@($"/credentials/{Id}/delete")"
Color="danger" />
</CustomActions>
</PageHeader>
<div class="grid grid-cols-2 px-4 pt-6 md:grid-cols-3 lg:gap-4 dark:bg-gray-900">
<div class="mb-4 col-span-full xl:mb-2">
<Breadcrumb BreadcrumbItems="BreadcrumbItems"/>
<div class="flex items-center justify-between">
<h1 class="text-xl font-semibold text-gray-900 sm:text-2xl dark:text-white">View credentials entry</h1>
<div class="flex">
<a href="/credentials/@Id/edit" class="mr-3 px-4 py-2 text-white bg-primary-600 rounded-lg hover:bg-primary-700 focus:ring-4 focus:ring-primary-300 dark:bg-primary-500 dark:hover:bg-primary-600 dark:focus:ring-primary-800">
Edit <span class="hidden md:inline">credentials entry</span>
</a>
<a href="/credentials/@Id/delete" class="px-4 py-2 text-white bg-red-600 rounded-lg hover:bg-red-700 focus:ring-4 focus:ring-red-300 dark:bg-red-500 dark:hover:bg-red-600 dark:focus:ring-red-800">
Delete <span class="hidden md:inline">credentials entry</span>
</a>
</div>
</div>
</div>
<!-- Right Content -->
<div class="col-span-full lg:col-auto">
<div class="p-4 mb-4 bg-white border border-gray-200 rounded-lg shadow-sm 2xl:col-span-2 dark:border-gray-700 sm:p-6 dark:bg-gray-800">
<div class="items-center sm:flex xl:block 2xl:flex sm:space-x-4 xl:space-x-0 2xl:space-x-4">
@@ -48,7 +48,7 @@ else
<FormattedNote Notes="@Alias.Notes" />
}
@if (Alias.Attachments != null && Alias.Attachments.Count > 0)
@if (Alias.Attachments.Count > 0)
{
<AttachmentViewer Attachments="@Alias.Attachments" />
}

View File

@@ -17,16 +17,14 @@
<EmailModal Email="EmailModalEmail" IsSpamOk="false" OnClose="CloseEmailModal" OnEmailDeleted="RefreshData" />
}
<div class="grid grid-cols-1 px-4 pt-6 xl:grid-cols-3 xl:gap-4 dark:bg-gray-900">
<div class="mb-4 col-span-full xl:mb-2">
<Breadcrumb BreadcrumbItems="BreadcrumbItems"/>
<div class="flex items-center justify-between">
<h1 class="text-xl font-semibold text-gray-900 sm:text-2xl dark:text-white">Emails</h1>
<RefreshButton OnClick="RefreshData" ButtonText="Refresh" />
</div>
<p>Below you can find all recent emails sent to one of the email addresses used in your credentials.</p>
</div>
</div>
<PageHeader
BreadcrumbItems="@BreadcrumbItems"
Title="Emails"
Description="You can view all emails received by your private email addresses below.">
<CustomActions>
<RefreshButton OnClick="RefreshData" ButtonText="Refresh" />
</CustomActions>
</PageHeader>
@if (IsLoading)
{

View File

@@ -3,13 +3,11 @@
<LayoutPageTitle>General settings</LayoutPageTitle>
<div class="grid grid-cols-1 px-4 pt-6 xl:grid-cols-3 xl:gap-4 dark:bg-gray-900">
<div class="mb-4 col-span-full xl:mb-2">
<Breadcrumb BreadcrumbItems="BreadcrumbItems" />
<h1 class="text-xl font-semibold text-gray-900 sm:text-2xl dark:text-white">General settings</h1>
<p class="mt-2 text-sm text-gray-600 dark:text-gray-400">Configure general AliasVault settings.</p>
</div>
</div>
<PageHeader
BreadcrumbItems="@BreadcrumbItems"
Title="General settings"
Description="Configure general AliasVault settings.">
</PageHeader>
<div class="p-4 mb-4 mx-4 bg-white border border-gray-200 rounded-lg shadow-sm dark:border-gray-700 sm:p-6 dark:bg-gray-800">
<h3 class="mb-4 text-lg font-medium text-gray-900 dark:text-white">Email Settings</h3>

View File

@@ -11,7 +11,7 @@
<div class="grid grid-cols-1 px-4 pt-6 xl:grid-cols-3 xl:gap-4 dark:bg-gray-900">
<div class="mb-4 col-span-full xl:mb-2">
<Breadcrumb BreadcrumbItems="BreadcrumbItems"/>
<h1 class="text-xl font-semibold text-gray-900 sm:text-2xl dark:text-white">Change password</h1>
<H1>Change password</H1>
<p class="mt-2 text-sm text-gray-600 dark:text-gray-400">Changing your master password also changes the vault encryption keys. It is advised to periodically change your master password to keep your vaults secure.</p>
</div>
</div>

View File

@@ -13,7 +13,7 @@ else
<div class="grid grid-cols-1 px-4 pt-6 xl:grid-cols-3 xl:gap-4 dark:bg-gray-900">
<div class="mb-4 col-span-full xl:mb-2">
<Breadcrumb BreadcrumbItems="BreadcrumbItems"/>
<h1 class="text-xl font-semibold text-gray-900 sm:text-2xl dark:text-white">Disable two-factor authentication</h1>
<H1>Disable two-factor authentication</H1>
<p class="mt-2 text-sm text-gray-600 dark:text-gray-400">Disabling two-factor authentication means you will be able to login with only your password.</p>
</div>
</div>

View File

@@ -8,7 +8,7 @@
<div class="grid grid-cols-1 px-4 pt-6 xl:grid-cols-3 xl:gap-4 dark:bg-gray-900">
<div class="mb-4 col-span-full xl:mb-2">
<Breadcrumb BreadcrumbItems="BreadcrumbItems"/>
<h1 class="text-xl font-semibold text-gray-900 sm:text-2xl dark:text-white">Enable two-factor authentication</h1>
<H1>Enable two-factor authentication</H1>
<p class="mt-2 text-sm text-gray-600 dark:text-gray-400">Enable two-factor authentication to increase the security of your vaults.</p>
</div>
</div>

View File

@@ -4,16 +4,14 @@
<LayoutPageTitle>Security settings</LayoutPageTitle>
<div class="grid grid-cols-1 px-4 pt-6 xl:grid-cols-3 xl:gap-4 dark:bg-gray-900">
<div class="mb-4 col-span-full xl:mb-2">
<Breadcrumb BreadcrumbItems="BreadcrumbItems"/>
<div class="flex items-center justify-between">
<h1 class="text-xl font-semibold text-gray-900 sm:text-2xl dark:text-white">Security settings</h1>
<RefreshButton OnClick="LoadData" ButtonText="Refresh" />
</div>
<p class="mt-2 text-sm text-gray-600 dark:text-gray-400">Configure security settings.</p>
</div>
</div>
<PageHeader
BreadcrumbItems="@BreadcrumbItems"
Title="Security settings"
Description="Configure security settings.">
<CustomActions>
<RefreshButton OnClick="LoadData" ButtonText="Refresh" />
</CustomActions>
</PageHeader>
<PasswordChangeSection OnStatusChanged="LoadData" />
<TwoFactorAuthenticationSection @ref="TwoFactorSection" OnStatusChanged="LoadData" />

View File

@@ -5,15 +5,11 @@
<LayoutPageTitle>Vault settings</LayoutPageTitle>
<div class="grid grid-cols-1 px-4 pt-6 xl:grid-cols-3 xl:gap-4 dark:bg-gray-900">
<div class="mb-4 col-span-full xl:mb-2">
<Breadcrumb BreadcrumbItems="BreadcrumbItems" />
<div class="flex items-center justify-between">
<h1 class="text-xl font-semibold text-gray-900 sm:text-2xl dark:text-white">Vault settings</h1>
</div>
<p>On this page you can configure your vault settings.</p>
</div>
</div>
<PageHeader
BreadcrumbItems="@BreadcrumbItems"
Title="Vault settings"
Description="On this page you can configure your vault settings.">
</PageHeader>
<div class="p-4 mx-4 mb-4 bg-white border border-gray-200 rounded-lg shadow-sm 2xl:col-span-2 dark:border-gray-700 sm:p-6 dark:bg-gray-800">
<h3 class="mb-4 text-xl font-semibold dark:text-white">Export vault</h3>

View File

@@ -4,15 +4,11 @@
<LayoutPageTitle>Test webapi call 1</LayoutPageTitle>
<div class="grid grid-cols-1 px-4 pt-6 xl:grid-cols-3 xl:gap-4 dark:bg-gray-900">
<div class="mb-4 col-span-full xl:mb-2">
<Breadcrumb BreadcrumbItems="BreadcrumbItems" />
<div class="flex items-center justify-between">
<h1 class="text-xl font-semibold text-gray-900 sm:text-2xl dark:text-white">Test webapi call 1</h1>
</div>
<p>Test webapi call 1.</p>
</div>
</div>
<PageHeader
BreadcrumbItems="@BreadcrumbItems"
Title="Test webapi call 1"
Description="Test webapi call 1">
</PageHeader>
@if (IsLoading)
{

View File

@@ -4,15 +4,11 @@
<LayoutPageTitle>Test webapi call 2</LayoutPageTitle>
<div class="grid grid-cols-1 px-4 pt-6 xl:grid-cols-3 xl:gap-4 dark:bg-gray-900">
<div class="mb-4 col-span-full xl:mb-2">
<Breadcrumb BreadcrumbItems="BreadcrumbItems" />
<div class="flex items-center justify-between">
<h1 class="text-xl font-semibold text-gray-900 sm:text-2xl dark:text-white">Test webapi call 2</h1>
</div>
<p>Test webapi call 2.</p>
</div>
</div>
<PageHeader
BreadcrumbItems="@BreadcrumbItems"
Title="Test webapi call 2"
Description="Test webapi call 2">
</PageHeader>
@if (IsLoading)
{

View File

@@ -27,6 +27,7 @@
@using AliasVault.RazorComponents
@using AliasVault.RazorComponents.Alerts
@using AliasVault.RazorComponents.Buttons
@using AliasVault.RazorComponents.Headings
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@using Blazored.LocalStorage

View File

@@ -3,6 +3,7 @@ module.exports = {
content: [
'./**/*.html',
'./**/*.razor',
'../Shared/AliasVault.RazorComponents/**/*.cs',
'../Shared/AliasVault.RazorComponents/**/*.razor',
],
safelist: [

View File

@@ -554,40 +554,6 @@ video {
--tw-contain-style: ;
}
.container {
width: 100%;
}
@media (min-width: 640px) {
.container {
max-width: 640px;
}
}
@media (min-width: 768px) {
.container {
max-width: 768px;
}
}
@media (min-width: 1024px) {
.container {
max-width: 1024px;
}
}
@media (min-width: 1280px) {
.container {
max-width: 1280px;
}
}
@media (min-width: 1536px) {
.container {
max-width: 1536px;
}
}
.sr-only {
position: absolute;
width: 1px;
@@ -600,6 +566,10 @@ video {
border-width: 0;
}
.visible {
visibility: visible;
}
.static {
position: static;
}
@@ -1072,6 +1042,12 @@ video {
margin-left: calc(0.5rem * calc(1 - var(--tw-space-x-reverse)));
}
.space-x-3 > :not([hidden]) ~ :not([hidden]) {
--tw-space-x-reverse: 0;
margin-right: calc(0.75rem * var(--tw-space-x-reverse));
margin-left: calc(0.75rem * 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));
@@ -1517,10 +1493,6 @@ video {
padding-right: 0.75rem;
}
.pt-10 {
padding-top: 2.5rem;
}
.pt-16 {
padding-top: 4rem;
}
@@ -1913,11 +1885,6 @@ video {
background-color: rgb(220 38 38 / var(--tw-bg-opacity));
}
.hover\:bg-red-700:hover {
--tw-bg-opacity: 1;
background-color: rgb(185 28 28 / var(--tw-bg-opacity));
}
.hover\:bg-red-800:hover {
--tw-bg-opacity: 1;
background-color: rgb(153 27 27 / var(--tw-bg-opacity));
@@ -2119,11 +2086,6 @@ video {
background-color: rgb(17 24 39 / var(--tw-bg-opacity));
}
.dark\:bg-green-500:is(.dark *) {
--tw-bg-opacity: 1;
background-color: rgb(34 197 94 / var(--tw-bg-opacity));
}
.dark\:bg-green-600:is(.dark *) {
--tw-bg-opacity: 1;
background-color: rgb(22 163 74 / var(--tw-bg-opacity));
@@ -2139,11 +2101,6 @@ video {
background-color: rgb(214 131 56 / var(--tw-bg-opacity));
}
.dark\:bg-red-500:is(.dark *) {
--tw-bg-opacity: 1;
background-color: rgb(239 68 68 / var(--tw-bg-opacity));
}
.dark\:bg-red-600:is(.dark *) {
--tw-bg-opacity: 1;
background-color: rgb(220 38 38 / var(--tw-bg-opacity));
@@ -2267,11 +2224,6 @@ video {
background-color: rgb(55 65 81 / var(--tw-bg-opacity));
}
.dark\:hover\:bg-green-600:hover:is(.dark *) {
--tw-bg-opacity: 1;
background-color: rgb(22 163 74 / var(--tw-bg-opacity));
}
.dark\:hover\:bg-green-700:hover:is(.dark *) {
--tw-bg-opacity: 1;
background-color: rgb(21 128 61 / var(--tw-bg-opacity));
@@ -2287,11 +2239,6 @@ video {
background-color: rgb(184 112 47 / var(--tw-bg-opacity));
}
.dark\:hover\:bg-red-600:hover:is(.dark *) {
--tw-bg-opacity: 1;
background-color: rgb(220 38 38 / var(--tw-bg-opacity));
}
.dark\:hover\:bg-red-700:hover:is(.dark *) {
--tw-bg-opacity: 1;
background-color: rgb(185 28 28 / var(--tw-bg-opacity));
@@ -2569,11 +2516,6 @@ video {
.lg\:gap-4 {
gap: 1rem;
}
.lg\:px-0 {
padding-left: 0px;
padding-right: 0px;
}
}
@media (min-width: 1280px) {

View File

@@ -52,17 +52,9 @@
/// <returns>A string containing the CSS classes for the button.</returns>
private string GetButtonClasses()
{
var baseClasses = "flex center items-center px-3 py-2 text-sm font-medium text-white rounded-lg focus:outline-none focus:ring-4";
var colorClasses = Color switch
{
"primary" => "bg-primary-700 hover:bg-primary-800 focus:ring-primary-300 dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800",
"danger" => "bg-red-700 hover:bg-red-800 focus:ring-red-300 dark:bg-red-600 dark:hover:bg-red-700 dark:focus:ring-red-800",
"success" => "bg-green-700 hover:bg-green-800 focus:ring-green-300 dark:bg-green-600 dark:hover:bg-green-700 dark:focus:ring-green-800",
"secondary" => "bg-secondary-700 hover:bg-secondary-800 focus:ring-secondary-300 dark:bg-secondary-600 dark:hover:bg-secondary-700 dark:focus:ring-secondary-800",
_ => "bg-gray-700 hover:bg-gray-800 focus:ring-gray-300 dark:bg-gray-600 dark:hover:bg-gray-700 dark:focus:ring-gray-800"
};
var disabledClasses = IsDisabled ? "bg-gray-400 cursor-not-allowed" : "";
var colorClasses = ButtonStyles.GetColorClasses(Color);
var disabledClasses = IsDisabled ? ButtonStyles.DisabledClasses : "";
return $"{baseClasses} {colorClasses} {disabledClasses} {AdditionalClasses}".Trim();
return $"{ButtonStyles.BaseClasses} {colorClasses} {disabledClasses} {AdditionalClasses}".Trim();
}
}

View File

@@ -0,0 +1,38 @@
//-----------------------------------------------------------------------
// <copyright file="ButtonStyles.cs" company="lanedirt">
// Copyright (c) lanedirt. All rights reserved.
// Licensed under the MIT license. See LICENSE.md file in the project root for full license information.
// </copyright>
//-----------------------------------------------------------------------
namespace AliasVault.RazorComponents.Buttons;
/// <summary>
/// A static class that provides CSS classes for buttons.
/// </summary>
public static class ButtonStyles
{
/// <summary>
/// Gets the base CSS classes for buttons.
/// </summary>
public static string BaseClasses => "flex center items-center px-3 py-2 text-sm font-medium text-white rounded-lg focus:outline-none focus:ring-4";
/// <summary>
/// Gets the CSS classes for a disabled button.
/// </summary>
public static string DisabledClasses => "bg-gray-400 cursor-not-allowed";
/// <summary>
/// Gets the color-specific CSS classes for a button based on the provided color.
/// </summary>
/// <param name="color">The color name for the button (e.g., "primary", "danger", "success", "secondary").</param>
/// <returns>A string containing the appropriate CSS classes for the specified color.</returns>
public static string GetColorClasses(string color) => color switch
{
"primary" => "bg-primary-700 hover:bg-primary-800 focus:ring-primary-300 dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800",
"danger" => "bg-red-700 hover:bg-red-800 focus:ring-red-300 dark:bg-red-600 dark:hover:bg-red-700 dark:focus:ring-red-800",
"success" => "bg-green-700 hover:bg-green-800 focus:ring-green-300 dark:bg-green-600 dark:hover:bg-green-700 dark:focus:ring-green-800",
"secondary" => "bg-secondary-700 hover:bg-secondary-800 focus:ring-secondary-300 dark:bg-secondary-600 dark:hover:bg-secondary-700 dark:focus:ring-secondary-800",
_ => "bg-gray-700 hover:bg-gray-800 focus:ring-gray-300 dark:bg-gray-600 dark:hover:bg-gray-700 dark:focus:ring-gray-800",
};
}

View File

@@ -0,0 +1,26 @@
<Button OnClick="HandleClick"
Color="danger">
@ChildContent
</Button>
@code {
/// <summary>
/// The event to call in the parent when the cancel button is clicked.
/// </summary>
[Parameter]
public EventCallback OnClick { get; set; }
/// <summary>
/// The content to be displayed inside the button.
/// </summary>
[Parameter]
public RenderFragment? ChildContent { get; set; }
/// <summary>
/// Handles the button click event.
/// </summary>
private async Task HandleClick()
{
await OnClick.InvokeAsync();
}
}

View File

@@ -0,0 +1,26 @@
<Button OnClick="HandleClick"
Color="success">
@ChildContent
</Button>
@code {
/// <summary>
/// The event to call in the parent when the confirm button is clicked.
/// </summary>
[Parameter]
public EventCallback OnClick { get; set; }
/// <summary>
/// The content to be displayed inside the button.
/// </summary>
[Parameter]
public RenderFragment? ChildContent { get; set; }
/// <summary>
/// Handles the button click event.
/// </summary>
private async Task HandleClick()
{
await OnClick.InvokeAsync();
}
}

View File

@@ -0,0 +1,46 @@
<a href="@Href" class="@GetButtonClasses()">
@Text <span class="hidden md:inline ms-1">@AdditionalText</span>
</a>
@code {
/// <summary>
/// Gets or sets the URL that the hyperlink points to.
/// </summary>
[Parameter]
public string Href { get; set; } = string.Empty;
/// <summary>
/// Gets or sets the main text of the button.
/// </summary>
[Parameter]
public string Text { get; set; } = string.Empty;
/// <summary>
/// Gets or sets the additional text that appears on larger screens.
/// </summary>
[Parameter]
public string AdditionalText { get; set; } = string.Empty;
/// <summary>
/// Gets or sets the color theme of the button.
/// </summary>
[Parameter]
public string Color { get; set; } = "primary";
/// <summary>
/// Gets or sets additional CSS classes to apply to the button.
/// </summary>
[Parameter]
public string AdditionalClasses { get; set; } = string.Empty;
/// <summary>
/// Gets the CSS classes for the link button based on the color and additional classes.
/// </summary>
/// <returns>A string containing the CSS classes for the link button.</returns>
private string GetButtonClasses()
{
var colorClasses = ButtonStyles.GetColorClasses(Color);
return $"{ButtonStyles.BaseClasses} {colorClasses} {AdditionalClasses}".Trim();
}
}

View File

@@ -1,6 +1,7 @@
@inherits ComponentBase
@using AliasVault.Client.Main.Models
@inherits ComponentBase
<nav class="flex mb-5">
<nav class="flex mb-4">
<ol class="inline-flex items-center space-x-1 text-sm font-medium md:space-x-2">
<li class="inline-flex items-center">
<a href="/" class="inline-flex items-center text-gray-700 hover:text-primary-600 dark:text-gray-300 dark:hover:text-primary-500">

View File

@@ -0,0 +1,9 @@
<h1 class="text-xl font-semibold text-gray-900 sm:text-2xl dark:text-white">@ChildContent</h1>
@code {
/// <summary>
/// The content to be displayed inside the heading.
/// </summary>
[Parameter]
public RenderFragment? ChildContent { get; set; }
}

View File

@@ -0,0 +1,43 @@
@using AliasVault.Client.Main.Models
<div class="grid grid-cols-1 px-4 pt-6 xl:grid-cols-3 xl:gap-4 dark:bg-gray-900">
<div class="mb-4 col-span-full xl:mb-2">
<Breadcrumb BreadcrumbItems="BreadcrumbItems" />
<div class="flex items-center justify-between">
<H1>@Title</H1>
@if (CustomActions != null)
{
<div class="flex items-center space-x-3">
@CustomActions
</div>
}
</div>
<p class="text-sm text-gray-600 dark:text-gray-400">@Description</p>
</div>
</div>
@code {
/// <summary>
/// Gets or sets the breadcrumb items for the header.
/// </summary>
[Parameter]
public List<BreadcrumbItem> BreadcrumbItems { get; set; } = new List<BreadcrumbItem>();
/// <summary>
/// Gets or sets the title of the header.
/// </summary>
[Parameter]
public string Title { get; set; } = string.Empty;
/// <summary>
/// Gets or sets the description text below the title.
/// </summary>
[Parameter]
public string Description { get; set; } = string.Empty;
/// <summary>
/// The caller can provide a custom action button section to be displayed on the right side of the header.
/// </summary>
[Parameter]
public RenderFragment? CustomActions { get; set; }
}