refactoring dropdown
This commit is contained in:
@@ -2,13 +2,15 @@
|
|||||||
@using GameIdeas.BlazorApp.Layouts
|
@using GameIdeas.BlazorApp.Layouts
|
||||||
@using GameIdeas.BlazorApp.Pages.Games.Header
|
@using GameIdeas.BlazorApp.Pages.Games.Header
|
||||||
@using GameIdeas.BlazorApp.Shared.Components
|
@using GameIdeas.BlazorApp.Shared.Components
|
||||||
@using GameIdeas.BlazorApp.Shared.Headers
|
@using GameIdeas.BlazorApp.Shared.Layouts.Header
|
||||||
@using GameIdeas.Resources
|
@using GameIdeas.Resources
|
||||||
|
|
||||||
@layout MainLayout
|
@layout MainLayout
|
||||||
|
|
||||||
<PageTitle>@ResourcesKey.GamesIdeas</PageTitle>
|
<PageTitle>@ResourcesKey.GamesIdeas</PageTitle>
|
||||||
|
|
||||||
<HeaderBase>
|
<HeaderLayout>
|
||||||
|
<Body>
|
||||||
<HeaderGame />
|
<HeaderGame />
|
||||||
</HeaderBase>
|
</Body>
|
||||||
|
</HeaderLayout>
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
@using GameIdeas.BlazorApp.Shared.Headers
|
|
||||||
@inherits HeaderBaseComponent
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
using GameIdeas.BlazorApp.Shared.Headers;
|
|
||||||
|
|
||||||
namespace GameIdeas.BlazorApp.Pages.Games.Header;
|
namespace GameIdeas.BlazorApp.Pages.Games.Header;
|
||||||
|
|
||||||
public partial class HeaderGame : HeaderBaseComponent
|
public partial class HeaderGame
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
@using GameIdeas.Resources
|
@using GameIdeas.Resources
|
||||||
@using Blazored.FluentValidation;
|
@using Blazored.FluentValidation;
|
||||||
|
|
||||||
<div class="account-setting-container" tabindex="1001">
|
<div class="account-setting-container" tabindex="1000">
|
||||||
<div class="account-setting-content @(ContentVisile ? string.Empty : "invisible")">
|
<div class="account-setting-content @(ContentVisile ? string.Empty : "invisible")">
|
||||||
@if (!AuthentificationService.IsLogin)
|
@if (!AuthentificationService.IsLogin)
|
||||||
{
|
{
|
||||||
@@ -2,7 +2,7 @@ using GameIdeas.BlazorApp.Services;
|
|||||||
using GameIdeas.Shared.Dto;
|
using GameIdeas.Shared.Dto;
|
||||||
using Microsoft.AspNetCore.Components.Forms;
|
using Microsoft.AspNetCore.Components.Forms;
|
||||||
|
|
||||||
namespace GameIdeas.BlazorApp.Shared.Headers;
|
namespace GameIdeas.BlazorApp.Shared.Components.Account;
|
||||||
|
|
||||||
public partial class AccountSettings (
|
public partial class AccountSettings (
|
||||||
AuthentificationService AuthentificationService)
|
AuthentificationService AuthentificationService)
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
@typeparam TItem
|
|
||||||
|
|
||||||
<div @ref=Content class="dropdown-container" tabindex="1000"
|
|
||||||
@onfocusout=HandleDropdownAddFocusOut>
|
|
||||||
<div class="dropdown-content @(ContentVisile ? string.Empty : "invisible") @(Enum.GetName(Theme)?.ToLower())">
|
|
||||||
@foreach (var item in Items)
|
|
||||||
{
|
|
||||||
<div class="drowdown-element @(Enum.GetName(Theme)?.ToLower())" @onclick=HandleItemClicked>
|
|
||||||
@(LabelSelector != null ? LabelSelector.Invoke(item) : item?.ToString())
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Components;
|
|
||||||
|
|
||||||
namespace GameIdeas.BlazorApp.Shared.Components.Dropdown;
|
|
||||||
|
|
||||||
public partial class DropdownContent<TItem>
|
|
||||||
{
|
|
||||||
[Parameter] public TItem? Value { get; set; }
|
|
||||||
[Parameter] public EventCallback<TItem?> ValueChanged { get; set; }
|
|
||||||
[Parameter] public IEnumerable<TItem> Items { get; set; } = [];
|
|
||||||
[Parameter] public Func<TItem, string>? LabelSelector { get; set; }
|
|
||||||
[Parameter] public DropdownTheme Theme { get; set; }
|
|
||||||
|
|
||||||
private bool ContentVisile = false;
|
|
||||||
private DateTime ContentLastFocusOut = DateTime.Now;
|
|
||||||
private ElementReference Content;
|
|
||||||
|
|
||||||
public async Task OpenAsync()
|
|
||||||
{
|
|
||||||
if (DateTime.Now - ContentLastFocusOut >= TimeSpan.FromSeconds(0.2))
|
|
||||||
{
|
|
||||||
await Content.FocusAsync();
|
|
||||||
ContentVisile = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Close() => ContentVisile = false;
|
|
||||||
|
|
||||||
private void HandleDropdownAddFocusOut()
|
|
||||||
{
|
|
||||||
ContentLastFocusOut = DateTime.Now;
|
|
||||||
ContentVisile = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task HandleItemClicked() => await ValueChanged.InvokeAsync(Value);
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
namespace GameIdeas.BlazorApp.Shared.Components.Dropdown;
|
|
||||||
|
|
||||||
public enum DropdownTheme
|
|
||||||
{
|
|
||||||
Navigation,
|
|
||||||
Account
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
@typeparam TItem
|
||||||
|
|
||||||
|
<div class="select-element @(Enum.GetName(Theme)?.ToLower())" @onclick=HandleItemClicked>
|
||||||
|
<div class="selected">
|
||||||
|
@if (Value != null && Value.IsSelected)
|
||||||
|
{
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||||
|
<path d="M9,20.42L2.79,14.21L5.62,11.38L9,14.77L18.88,4.88L21.71,7.71L9,20.42Z" />
|
||||||
|
</svg>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<div class="select-label">
|
||||||
|
@Value?.Label
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
|
||||||
|
namespace GameIdeas.BlazorApp.Shared.Components.Select.Components;
|
||||||
|
|
||||||
|
public partial class SelectListElement<TItem>
|
||||||
|
{
|
||||||
|
[Parameter] public EventCallback<SelectElement<TItem>?> ValueChanged { get; set; }
|
||||||
|
[Parameter] public SelectElement<TItem>? Value { get; set; }
|
||||||
|
[Parameter] public SelectListTheme Theme { get; set; }
|
||||||
|
private async Task HandleItemClicked()
|
||||||
|
{
|
||||||
|
if (Value != null)
|
||||||
|
{
|
||||||
|
Value.IsSelected = true;
|
||||||
|
await ValueChanged.InvokeAsync(Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
.select-element {
|
||||||
|
width: fit-content;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-element:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selected svg {
|
||||||
|
fill: var(--white)
|
||||||
|
}
|
||||||
|
|
||||||
|
/***** Navigation Theme *****/
|
||||||
|
.navigation .selected {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navigation .select-label:hover {
|
||||||
|
color: var(--light-grey);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***** Sort Theme *****/
|
||||||
|
.sort .select-label:hover {
|
||||||
|
color: var(--light-grey);
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
namespace GameIdeas.BlazorApp.Shared.Components.Select;
|
||||||
|
|
||||||
|
public class SelectElement<TItem>
|
||||||
|
{
|
||||||
|
public TItem? Item { get; set; }
|
||||||
|
public string? Label { get; set; }
|
||||||
|
public bool IsSelected { get; set; } = false;
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
@using GameIdeas.BlazorApp.Shared.Components.Select.Components
|
||||||
|
@typeparam TItem
|
||||||
|
|
||||||
|
<div class="select-list" @onclick=HandleButtonClicked>
|
||||||
|
<div class="select-button">
|
||||||
|
@Button
|
||||||
|
</div>
|
||||||
|
<div @ref=Container class="select-container" tabindex="1000"
|
||||||
|
@onfocusout=HandleFocusOut>
|
||||||
|
<div class="select-content @(ContentVisile ? string.Empty : "invisible") @(Enum.GetName(Theme)?.ToLower())">
|
||||||
|
@foreach (var item in Headers)
|
||||||
|
{
|
||||||
|
<SelectListElement TItem="TItem"
|
||||||
|
Value="item"
|
||||||
|
ValueChanged="HandleHeaderClicked"
|
||||||
|
Theme="Theme"/>
|
||||||
|
}
|
||||||
|
@if (Headers.Any())
|
||||||
|
{
|
||||||
|
<span class="line"></span>
|
||||||
|
}
|
||||||
|
@foreach (var item in Items)
|
||||||
|
{
|
||||||
|
<SelectListElement TItem="TItem"
|
||||||
|
Value="item"
|
||||||
|
ValueChanged="HandleItemClicked"
|
||||||
|
Theme="Theme" />
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
|
||||||
|
namespace GameIdeas.BlazorApp.Shared.Components.Select;
|
||||||
|
|
||||||
|
public partial class SelectList<TItem>
|
||||||
|
{
|
||||||
|
[Parameter] public RenderFragment? Button { get; set; }
|
||||||
|
[Parameter] public TItem? Value { get; set; }
|
||||||
|
[Parameter] public EventCallback<TItem?> ValueChanged { get; set; }
|
||||||
|
[Parameter] public TItem? Header { get; set; }
|
||||||
|
[Parameter] public EventCallback<TItem?> HeaderChanged { get; set; }
|
||||||
|
[Parameter] public IEnumerable<SelectElement<TItem>> Items { get; set; } = [];
|
||||||
|
[Parameter] public IEnumerable<SelectElement<TItem>> Headers { get; set; } = [];
|
||||||
|
[Parameter] public SelectListTheme Theme { get; set; }
|
||||||
|
[Parameter] public bool AlignRight { get; set; }
|
||||||
|
|
||||||
|
private bool ContentVisile = false;
|
||||||
|
private DateTime ContentLastFocusOut = DateTime.Now;
|
||||||
|
private ElementReference Container;
|
||||||
|
|
||||||
|
public async Task OpenAsync()
|
||||||
|
{
|
||||||
|
if (DateTime.Now - ContentLastFocusOut >= TimeSpan.FromSeconds(0.2))
|
||||||
|
{
|
||||||
|
await Container.FocusAsync();
|
||||||
|
ContentVisile = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close() => ContentVisile = false;
|
||||||
|
|
||||||
|
private async Task HandleButtonClicked() => await OpenAsync();
|
||||||
|
|
||||||
|
private void HandleFocusOut()
|
||||||
|
{
|
||||||
|
ContentLastFocusOut = DateTime.Now;
|
||||||
|
ContentVisile = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task HandleItemClicked(SelectElement<TItem> selectedValue)
|
||||||
|
{
|
||||||
|
foreach (var item in Items)
|
||||||
|
{
|
||||||
|
item.IsSelected = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
selectedValue.IsSelected = true;
|
||||||
|
Value = selectedValue.Item;
|
||||||
|
await ValueChanged.InvokeAsync(Value);
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task HandleHeaderClicked(SelectElement<TItem> selectedValue)
|
||||||
|
{
|
||||||
|
foreach (var header in Headers)
|
||||||
|
{
|
||||||
|
header.IsSelected = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
selectedValue.IsSelected = true;
|
||||||
|
Header = selectedValue.Item;
|
||||||
|
await HeaderChanged.InvokeAsync(Header);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
.dropdown-content {
|
.select-content {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@@ -9,25 +9,28 @@
|
|||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.drowdown-element {
|
|
||||||
width: fit-content;
|
|
||||||
}
|
|
||||||
|
|
||||||
.drowdown-element:hover {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.invisible {
|
.invisible {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dropdown-content.navigation {
|
.line {
|
||||||
|
margin: 0 6px;
|
||||||
|
border-bottom: 2px solid var(--light-grey);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***** Navigation Theme *****/
|
||||||
|
.select-content.navigation {
|
||||||
gap: 4px;
|
gap: 4px;
|
||||||
background: var(--violet);
|
background: var(--violet);
|
||||||
box-shadow: var(--drop-shadow);
|
box-shadow: var(--drop-shadow);
|
||||||
padding: 4px 6px;
|
padding: 4px 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.drowdown-element.navigation:hover {
|
/***** Sort Theme *****/
|
||||||
color: var(--light-grey);
|
.select-content.sort {
|
||||||
|
gap: 4px;
|
||||||
|
background: var(--black);
|
||||||
|
box-shadow: var(--drop-shadow);
|
||||||
|
padding: 4px 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
namespace GameIdeas.BlazorApp.Shared.Components.Select;
|
||||||
|
|
||||||
|
public enum SelectListTheme
|
||||||
|
{
|
||||||
|
Navigation,
|
||||||
|
Sort,
|
||||||
|
Filter
|
||||||
|
}
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Components;
|
|
||||||
|
|
||||||
namespace GameIdeas.BlazorApp.Shared.Headers;
|
|
||||||
|
|
||||||
public class HeaderBaseComponent : ComponentBase;
|
|
||||||
@@ -1,14 +1,18 @@
|
|||||||
@using GameIdeas.BlazorApp.Pages.Games
|
@using GameIdeas.BlazorApp.Pages.Games
|
||||||
@using GameIdeas.BlazorApp.Pages.Games.Models
|
@using GameIdeas.BlazorApp.Pages.Games.Models
|
||||||
|
@using GameIdeas.BlazorApp.Shared.Components.Account
|
||||||
@using GameIdeas.BlazorApp.Shared.Components.Dropdown
|
@using GameIdeas.BlazorApp.Shared.Components.Dropdown
|
||||||
|
@using GameIdeas.BlazorApp.Shared.Components.Select
|
||||||
@using GameIdeas.Resources
|
@using GameIdeas.Resources
|
||||||
|
|
||||||
|
@inherits LayoutComponentBase
|
||||||
|
|
||||||
<div class="header-tab">
|
<div class="header-tab">
|
||||||
<div class="icon-container" @onclick="HandleIconClicked">
|
<div class="icon-container" @onclick="HandleIconClicked">
|
||||||
<img src="icon.png" alt="Game Ideas">
|
<img src="icon.png" alt="Game Ideas">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@Header
|
@Body
|
||||||
|
|
||||||
<div class="account-add-container">
|
<div class="account-add-container">
|
||||||
<div class="add-container">
|
<div class="add-container">
|
||||||
@@ -18,21 +22,21 @@
|
|||||||
<path d="M19,13H13V19H11V13H5V11H11V5H13V11H19V13Z" />
|
<path d="M19,13H13V19H11V13H5V11H11V5H13V11H19V13Z" />
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<div class="second-button button" @onclick=HandleMoreButton>
|
<SelectList TItem="AddType"
|
||||||
|
Items="SelectElements"
|
||||||
|
ValueChanged=HandleAddTypeClickedAsync
|
||||||
|
Theme="SelectListTheme.Navigation">
|
||||||
|
<Button>
|
||||||
|
<div class="second-button button">
|
||||||
<svg class="button-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
<svg class="button-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||||
<path d="M1 3H23L12 22" />
|
<path d="M1 3H23L12 22" />
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Button>
|
||||||
<DropdownContent @ref="DropdownAdd"
|
</SelectList>
|
||||||
TItem="AddTypeParams"
|
|
||||||
ValueChanged=HandleAddTypeClickedAsync
|
|
||||||
Items="AddTypes"
|
|
||||||
LabelSelector="(addtype => addtype.Label)"
|
|
||||||
Theme="DropdownTheme.Navigation" />
|
|
||||||
</div>
|
</div>
|
||||||
<div class="account-container">
|
<div class="account-container">
|
||||||
<div class="icon-container">
|
<div class="icon-container" @onclick=HandleAccountClicked>
|
||||||
<svg class="account-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
<svg class="account-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||||
<path d="M12,19.2C9.5,19.2 7.29,17.92 6,16C6.03,14 10,12.9 12,12.9C14,12.9 17.97,14 18,16C16.71,17.92 14.5,19.2 12,19.2M12,5A3,3 0 0,1 15,8A3,3 0 0,1 12,11A3,3 0 0,1 9,8A3,3 0 0,1 12,5M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12C22,6.47 17.5,2 12,2Z" />
|
<path d="M12,19.2C9.5,19.2 7.29,17.92 6,16C6.03,14 10,12.9 12,12.9C14,12.9 17.97,14 18,16C16.71,17.92 14.5,19.2 12,19.2M12,5A3,3 0 0,1 15,8A3,3 0 0,1 12,11A3,3 0 0,1 9,8A3,3 0 0,1 12,5M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12C22,6.47 17.5,2 12,2Z" />
|
||||||
</svg>
|
</svg>
|
||||||
@@ -1,15 +1,21 @@
|
|||||||
using GameIdeas.BlazorApp.Pages.Games.Models;
|
using GameIdeas.BlazorApp.Pages.Games.Models;
|
||||||
|
using GameIdeas.BlazorApp.Shared.Components.Account;
|
||||||
using GameIdeas.BlazorApp.Shared.Components.Dropdown;
|
using GameIdeas.BlazorApp.Shared.Components.Dropdown;
|
||||||
|
using GameIdeas.BlazorApp.Shared.Components.Select;
|
||||||
using GameIdeas.Resources;
|
using GameIdeas.Resources;
|
||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
|
|
||||||
namespace GameIdeas.BlazorApp.Shared.Headers;
|
namespace GameIdeas.BlazorApp.Shared.Layouts.Header;
|
||||||
|
|
||||||
public partial class HeaderBase
|
public partial class HeaderLayout : LayoutComponentBase
|
||||||
{
|
{
|
||||||
[Parameter] public HeaderBaseComponent? Header { get; set; }
|
|
||||||
[Parameter] public EventCallback<AddType> AddTypeChanged { get; set; }
|
[Parameter] public EventCallback<AddType> AddTypeChanged { get; set; }
|
||||||
|
|
||||||
|
private readonly IEnumerable<SelectElement<AddType>> SelectElements = [
|
||||||
|
new SelectElement<AddType> { Item = AddType.Manual, Label = ResourcesKey.ManualAdd },
|
||||||
|
new SelectElement<AddType> { Item = AddType.Auto, Label = ResourcesKey.AutoAdd }
|
||||||
|
];
|
||||||
|
|
||||||
private DropdownContent<AddTypeParams>? DropdownAdd;
|
private DropdownContent<AddTypeParams>? DropdownAdd;
|
||||||
private readonly IEnumerable<AddTypeParams> AddTypes =
|
private readonly IEnumerable<AddTypeParams> AddTypes =
|
||||||
[
|
[
|
||||||
@@ -34,9 +40,9 @@ public partial class HeaderBase
|
|||||||
AccountSettings?.Close();
|
AccountSettings?.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task HandleAddTypeClickedAsync(AddTypeParams value)
|
private async Task HandleAddTypeClickedAsync(AddType value)
|
||||||
{
|
{
|
||||||
await AddTypeChanged.InvokeAsync(value.AddType);
|
await AddTypeChanged.InvokeAsync(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleAccountClicked()
|
private void HandleAccountClicked()
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
using FluentValidation;
|
using FluentValidation;
|
||||||
using GameIdeas.Shared.Dto;
|
using GameIdeas.Shared.Dto;
|
||||||
|
|
||||||
namespace GameIdeas.BlazorApp.Shared.Headers;
|
namespace GameIdeas.BlazorApp.Shared.Layouts.Header;
|
||||||
|
|
||||||
public class LoginValidator : AbstractValidator<LoginDto>
|
public class LoginValidator : AbstractValidator<LoginDto>
|
||||||
{
|
{
|
||||||
Reference in New Issue
Block a user