Refactor: Update style and dropdown #10
@@ -1,12 +1,13 @@
|
|||||||
.page {
|
.page {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow: hidden;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.orb {
|
.orb {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
border-radius: 100%;
|
border-radius: 100%;
|
||||||
z-index: -999;
|
z-index: var(--index-orb);
|
||||||
}
|
}
|
||||||
|
|
||||||
.green {
|
.green {
|
||||||
@@ -42,5 +43,5 @@
|
|||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
z-index: -1000;
|
z-index: var(--index-background);
|
||||||
}
|
}
|
||||||
@@ -27,7 +27,7 @@ public partial class AdvancedGameFilter
|
|||||||
new() { Item = "Electronic Arts", Label = "Electronic Arts" },
|
new() { Item = "Electronic Arts", Label = "Electronic Arts" },
|
||||||
new() { Item = "Ubisoft", Label = "Ubisoft" },
|
new() { Item = "Ubisoft", Label = "Ubisoft" },
|
||||||
new() { Item = "Activision Blizzard", Label = "Activision Blizzard" },
|
new() { Item = "Activision Blizzard", Label = "Activision Blizzard" },
|
||||||
new() { Item = "Bethesda", Label = "Bethesda" },
|
new() { Item = "Bethesda", Label = "Bethesda" }
|
||||||
];
|
];
|
||||||
|
|
||||||
private readonly IEnumerable<SelectElement<string>> Developers = [
|
private readonly IEnumerable<SelectElement<string>> Developers = [
|
||||||
|
|||||||
@@ -5,7 +5,10 @@
|
|||||||
padding-right: 20px;
|
padding-right: 20px;
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
border-left: 2px solid var(--light-grey);
|
box-sizing: border-box;
|
||||||
|
width: 240px;
|
||||||
|
border-left: 2px solid var(--line);
|
||||||
|
z-index: var(--index-component);
|
||||||
}
|
}
|
||||||
|
|
||||||
.duplicate {
|
.duplicate {
|
||||||
|
|||||||
@@ -2,11 +2,9 @@
|
|||||||
@using GameIdeas.BlazorApp.Shared.Components.Select
|
@using GameIdeas.BlazorApp.Shared.Components.Select
|
||||||
@using GameIdeas.BlazorApp.Shared.Components.Select.Models
|
@using GameIdeas.BlazorApp.Shared.Components.Select.Models
|
||||||
@using GameIdeas.BlazorApp.Shared.Components.SliderRange
|
@using GameIdeas.BlazorApp.Shared.Components.SliderRange
|
||||||
|
@using GameIdeas.BlazorApp.Shared.Models
|
||||||
@using GameIdeas.Shared.Dto
|
@using GameIdeas.Shared.Dto
|
||||||
@using GameIdeas.BlazorApp.Pages.Games.Models
|
|
||||||
|
|
||||||
|
|
||||||
<EditForm EditContext="EditContext">
|
|
||||||
<div class="form-filter">
|
<div class="form-filter">
|
||||||
<SelectList TItem="Func<GameDto, object>"
|
<SelectList TItem="Func<GameDto, object>"
|
||||||
Headers="SortTypes"
|
Headers="SortTypes"
|
||||||
@@ -14,13 +12,11 @@
|
|||||||
@bind-Value=GameFilterParams!.SortProperty
|
@bind-Value=GameFilterParams!.SortProperty
|
||||||
HeaderChanged=HandleSortTypeChanged
|
HeaderChanged=HandleSortTypeChanged
|
||||||
Theme="SelectListTheme.Sort">
|
Theme="SelectListTheme.Sort">
|
||||||
<Button>
|
|
||||||
<div class="square-button">
|
<div class="square-button">
|
||||||
<svg class="sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
<svg class="sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||||
<path d="M10,13H22V11H10M10,19H22V17H10M10,7H22V5H10M6,7H8.5L5,3.5L1.5,7H4V17H1.5L5,20.5L8.5,17H6V7Z" />
|
<path d="M10,13H22V11H10M10,19H22V17H10M10,7H22V5H10M6,7H8.5L5,3.5L1.5,7H4V17H1.5L5,20.5L8.5,17H6V7Z" />
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</Button>
|
|
||||||
</SelectList>
|
</SelectList>
|
||||||
|
|
||||||
<div class="square-button" @onclick="@(() => HandleDisplayClicked(DisplayType.List))">
|
<div class="square-button" @onclick="@(() => HandleDisplayClicked(DisplayType.List))">
|
||||||
@@ -62,7 +58,5 @@
|
|||||||
@bind-Min=GameFilterParams.MinRating />
|
@bind-Min=GameFilterParams.MinRating />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</EditForm>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
using GameIdeas.BlazorApp.Pages.Games.Models;
|
|
||||||
using GameIdeas.BlazorApp.Shared.Components.Select.Models;
|
using GameIdeas.BlazorApp.Shared.Components.Select.Models;
|
||||||
using GameIdeas.BlazorApp.Shared.Components.SliderRange;
|
using GameIdeas.BlazorApp.Shared.Components.SliderRange;
|
||||||
|
using GameIdeas.BlazorApp.Shared.Models;
|
||||||
using GameIdeas.Shared.Dto;
|
using GameIdeas.Shared.Dto;
|
||||||
using GameIdeas.Shared.Enum;
|
using GameIdeas.Shared.Enum;
|
||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
@@ -10,7 +10,7 @@ namespace GameIdeas.BlazorApp.Pages.Games.Filter;
|
|||||||
|
|
||||||
public partial class GameFilter
|
public partial class GameFilter
|
||||||
{
|
{
|
||||||
[Parameter] public GameFilterParams? GameFilterParams { get; set; }
|
[Parameter] public GameFilterParams GameFilterParams { get; set; } = new();
|
||||||
[Parameter] public EventCallback<GameFilterParams> GameFilterParamsChanged { get; set; }
|
[Parameter] public EventCallback<GameFilterParams> GameFilterParamsChanged { get; set; }
|
||||||
[Parameter] public DisplayType DisplayType { get; set; }
|
[Parameter] public DisplayType DisplayType { get; set; }
|
||||||
[Parameter] public EventCallback<DisplayType> DisplayTypeChanged { get; set; }
|
[Parameter] public EventCallback<DisplayType> DisplayTypeChanged { get; set; }
|
||||||
@@ -45,7 +45,7 @@ public partial class GameFilter
|
|||||||
|
|
||||||
protected override void OnInitialized()
|
protected override void OnInitialized()
|
||||||
{
|
{
|
||||||
EditContext = new EditContext(GameFilterParams!);
|
EditContext = new EditContext(GameFilterParams);
|
||||||
EditContext.OnFieldChanged += async (s, e) =>
|
EditContext.OnFieldChanged += async (s, e) =>
|
||||||
{
|
{
|
||||||
await GameFilterParamsChanged.InvokeAsync(GameFilterParams);
|
await GameFilterParamsChanged.InvokeAsync(GameFilterParams);
|
||||||
@@ -54,7 +54,7 @@ public partial class GameFilter
|
|||||||
|
|
||||||
private void HandleSortTypeChanged(Func<GameDto?, object?> getHeader)
|
private void HandleSortTypeChanged(Func<GameDto?, object?> getHeader)
|
||||||
{
|
{
|
||||||
GameFilterParams!.SortType = (SortType?)getHeader(null) ?? SortType.Ascending;
|
GameFilterParams.SortType = (SortType?)getHeader(null) ?? SortType.Ascending;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task HandleDisplayClicked(DisplayType displayType)
|
private async Task HandleDisplayClicked(DisplayType displayType)
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
z-index: var(--index-component);
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-container {
|
.search-container {
|
||||||
@@ -26,7 +27,7 @@
|
|||||||
width: 28px;
|
width: 28px;
|
||||||
min-width: 28px;
|
min-width: 28px;
|
||||||
border-radius: var(--small-radius);
|
border-radius: var(--small-radius);
|
||||||
background: var(--black);
|
background: var(--input-primary);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,7 +41,7 @@
|
|||||||
|
|
||||||
.square-button svg:hover {
|
.square-button svg:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background: var(--low-white);
|
background: var(--input-selected);
|
||||||
}
|
}
|
||||||
|
|
||||||
.selected-icon {
|
.selected-icon {
|
||||||
|
|||||||
@@ -1,20 +1,18 @@
|
|||||||
@page "/Games"
|
@page "/Games"
|
||||||
@using GameIdeas.BlazorApp.Layouts
|
@using GameIdeas.BlazorApp.Layouts
|
||||||
@using GameIdeas.BlazorApp.Pages.Games.Filter
|
@using GameIdeas.BlazorApp.Pages.Games.Filter
|
||||||
|
@using GameIdeas.BlazorApp.Pages.Games.Header
|
||||||
@using GameIdeas.BlazorApp.Shared.Components
|
@using GameIdeas.BlazorApp.Shared.Components
|
||||||
@using GameIdeas.BlazorApp.Shared.Layouts.Header
|
|
||||||
@using GameIdeas.Resources
|
@using GameIdeas.Resources
|
||||||
|
|
||||||
@layout MainLayout
|
@layout MainLayout
|
||||||
|
|
||||||
<PageTitle>@ResourcesKey.GamesIdeas</PageTitle>
|
<PageTitle>@ResourcesKey.GamesIdeas</PageTitle>
|
||||||
|
|
||||||
<HeaderLayout>
|
<GamesHeader>
|
||||||
<Body>
|
|
||||||
<GameFilter @bind-DisplayType=DisplayType
|
<GameFilter @bind-DisplayType=DisplayType
|
||||||
@bind-GameFilterParams=GameFilterParams />
|
@bind-GameFilterParams=GameFilterParams />
|
||||||
</Body>
|
</GamesHeader>
|
||||||
</HeaderLayout>
|
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="content">
|
<div class="content">
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
using GameIdeas.BlazorApp.Pages.Games.Filter;
|
using GameIdeas.BlazorApp.Pages.Games.Filter;
|
||||||
using GameIdeas.BlazorApp.Pages.Games.Models;
|
using GameIdeas.BlazorApp.Shared.Models;
|
||||||
|
|
||||||
namespace GameIdeas.BlazorApp.Pages.Games;
|
namespace GameIdeas.BlazorApp.Pages.Games;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
.container {
|
.container {
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
|
margin-bottom: 10px;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
@@ -7,5 +8,5 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
|
z-index: var(--index-content);
|
||||||
}
|
}
|
||||||
@@ -1,18 +1,18 @@
|
|||||||
@using GameIdeas.BlazorApp.Pages.Games
|
@using GameIdeas.BlazorApp.Pages.Games
|
||||||
@using GameIdeas.BlazorApp.Pages.Games.Models
|
|
||||||
@using GameIdeas.BlazorApp.Shared.Components.Account
|
@using GameIdeas.BlazorApp.Shared.Components.Account
|
||||||
@using GameIdeas.BlazorApp.Shared.Components.Select
|
@using GameIdeas.BlazorApp.Shared.Components.Select
|
||||||
@using GameIdeas.BlazorApp.Shared.Components.Select.Models
|
@using GameIdeas.BlazorApp.Shared.Components.Select.Models
|
||||||
|
@using GameIdeas.BlazorApp.Shared.Models
|
||||||
@using GameIdeas.Resources
|
@using GameIdeas.Resources
|
||||||
|
|
||||||
@inherits LayoutComponentBase
|
@inherits ComponentBase
|
||||||
|
|
||||||
<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>
|
||||||
|
|
||||||
@Body
|
@ChildContent
|
||||||
|
|
||||||
<div class="account-add-container">
|
<div class="account-add-container">
|
||||||
<div class="add-container">
|
<div class="add-container">
|
||||||
@@ -27,13 +27,11 @@
|
|||||||
ValueChanged=HandleAddTypeClickedAsync
|
ValueChanged=HandleAddTypeClickedAsync
|
||||||
Theme="SelectListTheme.Navigation"
|
Theme="SelectListTheme.Navigation"
|
||||||
AlignRight=true>
|
AlignRight=true>
|
||||||
<Button>
|
|
||||||
<div class="second-button 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>
|
||||||
</Button>
|
|
||||||
</SelectList>
|
</SelectList>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -1,14 +1,16 @@
|
|||||||
using GameIdeas.BlazorApp.Pages.Games.Models;
|
|
||||||
using GameIdeas.BlazorApp.Shared.Components.Account;
|
using GameIdeas.BlazorApp.Shared.Components.Account;
|
||||||
using GameIdeas.BlazorApp.Shared.Components.Select.Models;
|
using GameIdeas.BlazorApp.Shared.Components.Select.Models;
|
||||||
|
using GameIdeas.BlazorApp.Shared.Models;
|
||||||
using GameIdeas.Resources;
|
using GameIdeas.Resources;
|
||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
|
|
||||||
namespace GameIdeas.BlazorApp.Shared.Layouts.Header;
|
namespace GameIdeas.BlazorApp.Pages.Games.Header;
|
||||||
|
|
||||||
public partial class HeaderLayout : LayoutComponentBase
|
public partial class GamesHeader : ComponentBase
|
||||||
{
|
{
|
||||||
[Parameter] public EventCallback<AddType> AddTypeChanged { get; set; }
|
[Parameter] public EventCallback<AddType> AddTypeChanged { get; set; }
|
||||||
|
[Parameter] public RenderFragment? ChildContent { get; set; }
|
||||||
|
|
||||||
|
|
||||||
private readonly IEnumerable<SelectElement<AddType>> SelectElements = [
|
private readonly IEnumerable<SelectElement<AddType>> SelectElements = [
|
||||||
new SelectElement<AddType> { Item = AddType.Manual, Label = ResourcesKey.ManualAdd },
|
new SelectElement<AddType> { Item = AddType.Manual, Label = ResourcesKey.ManualAdd },
|
||||||
@@ -33,7 +33,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.add-container {
|
.add-container {
|
||||||
overflow: visible;
|
|
||||||
margin-right: 40px;
|
margin-right: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,7 +41,6 @@
|
|||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
background: var(--violet);
|
background: var(--violet);
|
||||||
border-radius: var(--small-radius);
|
border-radius: var(--small-radius);
|
||||||
overflow: visible;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.button {
|
.button {
|
||||||
@@ -54,11 +52,15 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.first-button {
|
.first-button {
|
||||||
border-right: 2px solid var(--line-black);
|
border-right: 2px solid var(--violet-selected);
|
||||||
|
border-radius: var(--small-radius) 0 0 var(--small-radius);
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.second-button .button-icon {
|
.second-button .button-icon {
|
||||||
padding: 6px;
|
padding: 6px;
|
||||||
|
border-radius: 0 var(--small-radius) var(--small-radius) 0;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-icon {
|
.button-icon {
|
||||||
@@ -66,10 +68,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.button-icon:hover {
|
.button-icon:hover {
|
||||||
background: var(--line-black);
|
background: var(--violet-selected);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.account-icon {
|
.account-icon {
|
||||||
fill: var(--light-grey);
|
fill: var(--line);
|
||||||
}
|
}
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
namespace GameIdeas.BlazorApp.Pages.Games.Models;
|
|
||||||
|
|
||||||
public enum AddType
|
|
||||||
{
|
|
||||||
Manual,
|
|
||||||
Auto
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
namespace GameIdeas.BlazorApp.Pages.Games.Models;
|
|
||||||
|
|
||||||
public enum DisplayType
|
|
||||||
{
|
|
||||||
Card,
|
|
||||||
List
|
|
||||||
}
|
|
||||||
@@ -4,10 +4,11 @@
|
|||||||
position: fixed;
|
position: fixed;
|
||||||
animation-name: fade-in;
|
animation-name: fade-in;
|
||||||
animation-duration: 0.4s;
|
animation-duration: 0.4s;
|
||||||
border: 2px solid var(--low-white);
|
border: 2px solid var(--input-selected);
|
||||||
background: var(--semi-black);
|
background: var(--dropdown-content);
|
||||||
right: 10px;
|
right: 10px;
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
|
z-index: var(--index-floating);
|
||||||
}
|
}
|
||||||
|
|
||||||
.invisible {
|
.invisible {
|
||||||
@@ -30,8 +31,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
::deep .input-text {
|
::deep .input-text {
|
||||||
background: var(--low-white);
|
background: var(--input-selected);
|
||||||
border: 2px solid var(--low-white);
|
border: 2px solid var(--input-selected);
|
||||||
border-radius: var(--small-radius);
|
border-radius: var(--small-radius);
|
||||||
padding: 6px;
|
padding: 6px;
|
||||||
color: var(--white);
|
color: var(--white);
|
||||||
@@ -64,7 +65,7 @@
|
|||||||
width: 18px;
|
width: 18px;
|
||||||
height: 18px;
|
height: 18px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
border: 3px solid var(--line-black);
|
border: 3px solid rgba(0, 0, 0, 0.2);
|
||||||
border-top-color: var(--white);
|
border-top-color: var(--white);
|
||||||
animation: loading 1s linear infinite;
|
animation: loading 1s linear infinite;
|
||||||
justify-self: center;
|
justify-self: center;
|
||||||
@@ -77,7 +78,7 @@
|
|||||||
|
|
||||||
.line {
|
.line {
|
||||||
margin: 0 6px;
|
margin: 0 6px;
|
||||||
border-bottom: 2px solid var(--light-grey);
|
border-bottom: 2px solid var(--line);
|
||||||
}
|
}
|
||||||
|
|
||||||
.settings-element {
|
.settings-element {
|
||||||
@@ -88,7 +89,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.settings-element:hover {
|
.settings-element:hover {
|
||||||
background: var(--light-grey)
|
background: var(--line)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
@if (IsVisible)
|
||||||
|
{
|
||||||
|
<div class="backdrop-filter @Color.ToString().ToLower()" @onclick="HandleBackdropClicked"></div>
|
||||||
|
}
|
||||||
|
|
||||||
|
@code {
|
||||||
|
[Inject] private IJSRuntime Js { get; set; } = default!;
|
||||||
|
[Parameter] public EventCallback OnClick { get; set; }
|
||||||
|
[Parameter] public bool AllowBodyScroll { get; set; }
|
||||||
|
[Parameter] public BackdropFilterColor Color { get; set; } = BackdropFilterColor.Overlay;
|
||||||
|
[Parameter] public bool CloseOnClick { get; set; } = true;
|
||||||
|
[Parameter] public bool IsVisible { get; set; }
|
||||||
|
|
||||||
|
public async Task Show()
|
||||||
|
{
|
||||||
|
IsVisible = true;
|
||||||
|
await HandleBodyOverflow();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Hide()
|
||||||
|
{
|
||||||
|
IsVisible = false;
|
||||||
|
await HandleBodyOverflow();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task HandleBodyOverflow()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (AllowBodyScroll) return;
|
||||||
|
|
||||||
|
if (IsVisible)
|
||||||
|
{
|
||||||
|
await Js.InvokeVoidAsync("setBodyOverflow", "hidden");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await Js.InvokeVoidAsync("setBodyOverflow", "auto");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
// ignored because js not loaded
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task HandleBackdropClicked()
|
||||||
|
{
|
||||||
|
if (!CloseOnClick) return;
|
||||||
|
|
||||||
|
await Hide();
|
||||||
|
await OnClick.InvokeAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
.backdrop-filter {
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
z-index: var(--index-backdrop);
|
||||||
|
}
|
||||||
|
|
||||||
|
.backdrop-filter.overlay {
|
||||||
|
background-color: var(--grey-filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
.backdrop-filter.transparent {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
window.setBodyOverflow = (overflow) => {
|
||||||
|
document.getElementsByTagName('html')[0].style.overflow = overflow;
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace GameIdeas.BlazorApp.Shared.Components.BackdropFilter;
|
||||||
|
|
||||||
|
public enum BackdropFilterColor
|
||||||
|
{
|
||||||
|
Overlay,
|
||||||
|
Transparent
|
||||||
|
}
|
||||||
@@ -1,31 +1,25 @@
|
|||||||
<div class="search-container">
|
@using GameIdeas.Shared.Constants
|
||||||
<input type="text"
|
<div class="search-container">
|
||||||
|
<input @ref=InputText
|
||||||
|
type="text"
|
||||||
class="search-field"
|
class="search-field"
|
||||||
placeholder="@Placeholder"
|
placeholder="@Placeholder"
|
||||||
@bind=@Text
|
@bind=@Text
|
||||||
@bind:event="oninput"
|
@bind:event="oninput"
|
||||||
@bind:after=HandleTextChanged />
|
@bind:after=HandleTextChanged
|
||||||
|
@onfocusin=HandleFocusIn/>
|
||||||
|
|
||||||
|
<div class="buttons">
|
||||||
@if (!string.IsNullOrEmpty(Text))
|
@if (!string.IsNullOrEmpty(Text))
|
||||||
{
|
{
|
||||||
<div class="clear-icon" @onclick=HandleClearClicked>
|
<div class="clear-icon" @onclick=HandleClearClicked>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
@ClearIcon
|
||||||
<path d="M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z" />
|
|
||||||
</svg>
|
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
<div class="search-icon @(Enum.GetName(Icon)?.ToLower())" @onclick=HandleSearchClicked>
|
<div class="search-icon @(Enum.GetName(Icon)?.ToLower())" @onclick=HandleSearchClicked>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
@GetSearchIcon()
|
||||||
@if (Icon == SearchInputIcon.Search)
|
</div>
|
||||||
{
|
|
||||||
<path d="M9.5,3A6.5,6.5 0 0,1 16,9.5C16,11.11 15.41,12.59 14.44,13.73L14.71,14H15.5L20.5,19L19,20.5L14,15.5V14.71L13.73,14.44C12.59,15.41 11.11,16 9.5,16A6.5,6.5 0 0,1 3,9.5A6.5,6.5 0 0,1 9.5,3M9.5,5C7,5 5,7 5,9.5C5,12 7,14 9.5,14C12,14 14,12 14,9.5C14,7 12,5 9.5,5Z" />
|
|
||||||
}
|
|
||||||
else if (Icon == SearchInputIcon.Dropdown)
|
|
||||||
{
|
|
||||||
<path d="M1 3H23L12 22" />
|
|
||||||
}
|
|
||||||
</svg>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using GameIdeas.Shared.Constants;
|
||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
|
|
||||||
namespace GameIdeas.BlazorApp.Shared.Components.Search;
|
namespace GameIdeas.BlazorApp.Shared.Components.Search;
|
||||||
@@ -9,8 +10,12 @@ public partial class SearchInput
|
|||||||
[Parameter] public EventCallback<string> TextChanged { get; set; }
|
[Parameter] public EventCallback<string> TextChanged { get; set; }
|
||||||
[Parameter] public EventCallback ClearClicked { get; set; }
|
[Parameter] public EventCallback ClearClicked { get; set; }
|
||||||
[Parameter] public EventCallback SearchClicked { get; set; }
|
[Parameter] public EventCallback SearchClicked { get; set; }
|
||||||
|
[Parameter] public EventCallback FocusIn { get; set; }
|
||||||
[Parameter] public SearchInputIcon Icon { get; set; }
|
[Parameter] public SearchInputIcon Icon { get; set; }
|
||||||
|
|
||||||
|
private ElementReference InputText;
|
||||||
|
private readonly MarkupString ClearIcon = new(Icons.Search.Clear);
|
||||||
|
|
||||||
protected override void OnInitialized()
|
protected override void OnInitialized()
|
||||||
{
|
{
|
||||||
Text = string.Empty;
|
Text = string.Empty;
|
||||||
@@ -36,5 +41,20 @@ public partial class SearchInput
|
|||||||
{
|
{
|
||||||
await TextChanged.InvokeAsync(Text);
|
await TextChanged.InvokeAsync(Text);
|
||||||
await SearchClicked.InvokeAsync();
|
await SearchClicked.InvokeAsync();
|
||||||
|
await InputText.FocusAsync();
|
||||||
|
}
|
||||||
|
private async Task HandleFocusIn()
|
||||||
|
{
|
||||||
|
await FocusIn.InvokeAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
private MarkupString GetSearchIcon()
|
||||||
|
{
|
||||||
|
return Icon switch
|
||||||
|
{
|
||||||
|
SearchInputIcon.Dropdown => new MarkupString(Icons.Search.Triangle),
|
||||||
|
SearchInputIcon.Search => new MarkupString(Icons.Search.Glass),
|
||||||
|
_ => new MarkupString()
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6,10 +6,16 @@
|
|||||||
padding-left: 8px;
|
padding-left: 8px;
|
||||||
padding-right: 2px;
|
padding-right: 2px;
|
||||||
border-radius: var(--small-radius);
|
border-radius: var(--small-radius);
|
||||||
background: var(--black);
|
background: var(--input-primary);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
width: 140px;
|
z-index: var(--index-component);
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttons {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
::deep .search-field {
|
::deep .search-field {
|
||||||
@@ -33,7 +39,7 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.clear-icon svg {
|
::deep .clear-icon svg {
|
||||||
fill: var(--white);
|
fill: var(--white);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,11 +54,11 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-icon svg {
|
::deep .search-icon svg {
|
||||||
fill: var(--white);
|
fill: var(--white);
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-icon.dropdown svg {
|
::deep .search-icon.dropdown svg {
|
||||||
fill: var(--violet);
|
fill: var(--violet);
|
||||||
transform: scale(.8, .5);
|
transform: scale(.8, .5);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,13 +10,6 @@ public partial class SelectListElement<TItem>
|
|||||||
[Parameter] public SelectListTheme Theme { get; set; }
|
[Parameter] public SelectListTheme Theme { get; set; }
|
||||||
private async Task HandleItemClicked()
|
private async Task HandleItemClicked()
|
||||||
{
|
{
|
||||||
if (Value == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Value.IsSelected = true;
|
|
||||||
StateHasChanged();
|
|
||||||
await ValueChanged.InvokeAsync(Value);
|
await ValueChanged.InvokeAsync(Value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,12 +1,10 @@
|
|||||||
.select-element {
|
.select-element {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
width: fit-content;
|
width: auto;
|
||||||
width: 100%;
|
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
z-index: 501;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.select-element:hover {
|
.select-element:hover {
|
||||||
@@ -18,6 +16,7 @@
|
|||||||
min-width: 12px;
|
min-width: 12px;
|
||||||
height: 12px;
|
height: 12px;
|
||||||
min-height: 12px;
|
min-height: 12px;
|
||||||
|
border: 1px solid var(--line);
|
||||||
}
|
}
|
||||||
|
|
||||||
.selected svg {
|
.selected svg {
|
||||||
@@ -43,7 +42,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.sort:hover {
|
.sort:hover {
|
||||||
background: var(--low-white);
|
background: var(--input-selected);
|
||||||
}
|
}
|
||||||
|
|
||||||
.sort .select-label {
|
.sort .select-label {
|
||||||
@@ -57,7 +56,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.filter:hover {
|
.filter:hover {
|
||||||
background: var(--low-white);
|
background: var(--input-selected);
|
||||||
}
|
}
|
||||||
|
|
||||||
.filter .select-label {
|
.filter .select-label {
|
||||||
@@ -65,27 +64,13 @@
|
|||||||
margin-right: 6px;
|
margin-right: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***** Filter Theme *****/
|
/***** Advanced Filter Theme *****/
|
||||||
.filter {
|
|
||||||
padding: 2px 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.filter:hover {
|
|
||||||
background: var(--low-white);
|
|
||||||
}
|
|
||||||
|
|
||||||
.filter .select-label {
|
|
||||||
text-wrap: nowrap;
|
|
||||||
margin-right: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***** Filter Theme *****/
|
|
||||||
.advancedfilter {
|
.advancedfilter {
|
||||||
padding: 2px 6px;
|
padding: 2px 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.advancedfilter:hover {
|
.advancedfilter:hover {
|
||||||
background: var(--low-white);
|
background: var(--input-selected);
|
||||||
}
|
}
|
||||||
|
|
||||||
.advancedfilter .select-label {
|
.advancedfilter .select-label {
|
||||||
|
|||||||
@@ -1,21 +1,19 @@
|
|||||||
@using GameIdeas.BlazorApp.Shared.Components.Search
|
@using GameIdeas.BlazorApp.Shared.Components.BackdropFilter
|
||||||
|
@using GameIdeas.BlazorApp.Shared.Components.Search
|
||||||
@using GameIdeas.BlazorApp.Shared.Components.Select.Components
|
@using GameIdeas.BlazorApp.Shared.Components.Select.Components
|
||||||
@typeparam TItem
|
@typeparam TItem
|
||||||
|
|
||||||
<div class="select-list" tabindex="1001" @ref="BaseElement">
|
<div class="select-list">
|
||||||
<div class="select-button @(Enum.GetName(Theme)?.ToLower())" @onfocusin=HandleFocusIn @onfocusout=HandleFocusOut>
|
<div class="select-button @(Enum.GetName(Theme)?.ToLower())">
|
||||||
<SearchInput @ref=SearchInput
|
<SearchInput @ref=SearchInput
|
||||||
Icon="SearchInputIcon.Dropdown"
|
Icon="SearchInputIcon.Dropdown"
|
||||||
Placeholder="@Placeholder"
|
Placeholder="@Placeholder"
|
||||||
TextChanged="HandleTextChanged"
|
TextChanged="HandleTextChanged"
|
||||||
ClearClicked="HandleTextChanged"
|
ClearClicked="HandleTextChanged"
|
||||||
SearchClicked="HandleSearchClicked" />
|
SearchClicked="HandleSearchClicked"
|
||||||
|
FocusIn="HandleTextFocusIn"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="select-container @(AlignRight ? "align-right" : "")"
|
<div class="select-container">
|
||||||
tabindex="1000"
|
|
||||||
@ref=ContentElement
|
|
||||||
@onfocusin=HandleContentFocusIn
|
|
||||||
@onfocusout=HandleContentFocusOut>
|
|
||||||
|
|
||||||
@if (IsContentOpen)
|
@if (IsContentOpen)
|
||||||
{
|
{
|
||||||
@@ -32,3 +30,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<BackdropFilter AllowBodyScroll=true CloseOnClick=true Color="BackdropFilterColor.Transparent"
|
||||||
|
IsVisible=IsContentOpen OnClick="HandleContentClosed" />
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
using GameIdeas.BlazorApp.Shared.Components.Search;
|
using GameIdeas.BlazorApp.Shared.Components.Search;
|
||||||
using GameIdeas.BlazorApp.Shared.Components.Select.Models;
|
using GameIdeas.BlazorApp.Shared.Components.Select.Models;
|
||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
|
using Microsoft.JSInterop;
|
||||||
|
|
||||||
namespace GameIdeas.BlazorApp.Shared.Components.Select;
|
namespace GameIdeas.BlazorApp.Shared.Components.Select;
|
||||||
|
|
||||||
public partial class MultipleSelectList<TItem>
|
public partial class MultipleSelectList<TItem>
|
||||||
{
|
{
|
||||||
|
[Inject] IJSRuntime JS { get; set; } = default!;
|
||||||
[Parameter] public IEnumerable<TItem>? Values { get; set; }
|
[Parameter] public IEnumerable<TItem>? Values { get; set; }
|
||||||
[Parameter] public EventCallback<IEnumerable<TItem>?> ValuesChanged { get; set; }
|
[Parameter] public EventCallback<IEnumerable<TItem>?> ValuesChanged { get; set; }
|
||||||
[Parameter] public IEnumerable<SelectElement<TItem>> Items { get; set; } = [];
|
[Parameter] public IEnumerable<SelectElement<TItem>> Items { get; set; } = [];
|
||||||
@@ -13,60 +15,51 @@ public partial class MultipleSelectList<TItem>
|
|||||||
[Parameter] public bool AlignRight { get; set; }
|
[Parameter] public bool AlignRight { get; set; }
|
||||||
[Parameter] public string? Placeholder { get; set; }
|
[Parameter] public string? Placeholder { get; set; }
|
||||||
|
|
||||||
private bool IsContentOpen
|
private bool IsContentOpen = false;
|
||||||
{
|
|
||||||
get => InputFocus || ContentFocus;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool InputFocus = false;
|
|
||||||
private bool ContentFocus = false;
|
|
||||||
private SearchInput? SearchInput;
|
private SearchInput? SearchInput;
|
||||||
private ElementReference ContentElement;
|
|
||||||
private ElementReference BaseElement;
|
|
||||||
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
|
{
|
||||||
|
await JS.InvokeVoidAsync("addResizeListener");
|
||||||
|
|
||||||
|
await base.OnAfterRenderAsync(firstRender);
|
||||||
|
}
|
||||||
|
|
||||||
private async Task HandleItemClicked(SelectElement<TItem> selectedValue)
|
private async Task HandleItemClicked(SelectElement<TItem> selectedValue)
|
||||||
{
|
{
|
||||||
|
selectedValue.IsSelected = !selectedValue.IsSelected;
|
||||||
|
|
||||||
Values = Items.Where(x => x.IsSelected && x.Item != null).Select(x => x.Item!);
|
Values = Items.Where(x => x.IsSelected && x.Item != null).Select(x => x.Item!);
|
||||||
SearchInput?.SetText(string.Join(", ", Values));
|
SearchInput?.SetText(string.Join(", ", Values));
|
||||||
|
|
||||||
await ValuesChanged.InvokeAsync(Values);
|
await ValuesChanged.InvokeAsync(Values);
|
||||||
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task HandleTextChanged()
|
private async Task HandleTextChanged()
|
||||||
{
|
{
|
||||||
await BaseElement.FocusAsync();
|
IsContentOpen = false;
|
||||||
|
|
||||||
|
foreach (var item in Items)
|
||||||
|
{
|
||||||
|
item.IsSelected = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleFocusIn()
|
Values = Items.Where(x => x.IsSelected && x.Item != null).Select(x => x.Item!);
|
||||||
{
|
await ValuesChanged.InvokeAsync(Values);
|
||||||
InputFocus = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleContentFocusIn()
|
private void HandleSearchClicked()
|
||||||
{
|
{
|
||||||
ContentFocus = true;
|
IsContentOpen = !IsContentOpen;
|
||||||
}
|
}
|
||||||
|
private void HandleContentClosed()
|
||||||
private async Task HandleContentFocusOut()
|
|
||||||
{
|
{
|
||||||
await Task.Delay(TimeSpan.FromSeconds(0.3));
|
IsContentOpen = false;
|
||||||
ContentFocus = false;
|
|
||||||
}
|
}
|
||||||
|
private void HandleTextFocusIn()
|
||||||
private async Task HandleFocusOut()
|
|
||||||
{
|
{
|
||||||
await Task.Delay(TimeSpan.FromSeconds(0.3));
|
IsContentOpen = true;
|
||||||
InputFocus = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task HandleSearchClicked()
|
|
||||||
{
|
|
||||||
if (!IsContentOpen)
|
|
||||||
{
|
|
||||||
await ContentElement.FocusAsync();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
await BaseElement.FocusAsync();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,63 +3,62 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.select-container {
|
.select-container {
|
||||||
|
overflow: auto;
|
||||||
|
right: 0;
|
||||||
|
min-width: 100%;
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 500;
|
z-index: var(--index-dropdown);
|
||||||
}
|
border-radius: var(--small-radius);
|
||||||
|
|
||||||
.align-right {
|
|
||||||
right: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.select-content {
|
.select-content {
|
||||||
overflow: hidden;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
border-radius: var(--small-radius);
|
|
||||||
animation-name: fade-in;
|
animation-name: fade-in;
|
||||||
animation-duration: 0.4s;
|
animation-duration: 0.4s;
|
||||||
z-index: 500;
|
background: var(--dropdown-content);
|
||||||
|
box-shadow: var(--drop-shadow);
|
||||||
|
padding: 4px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-button {
|
||||||
|
z-index: var(--index-component)
|
||||||
}
|
}
|
||||||
|
|
||||||
.line {
|
.line {
|
||||||
margin: 2px 6px;
|
margin: 2px 6px;
|
||||||
border-bottom: 2px solid var(--low-white);
|
border-bottom: 2px solid var(--input-selected);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***** Navigation Theme *****/
|
|
||||||
.select-content.navigation {
|
|
||||||
background: var(--violet);
|
|
||||||
box-shadow: var(--drop-shadow);
|
|
||||||
}
|
|
||||||
|
|
||||||
/***** Sort Theme *****/
|
|
||||||
.select-content.sort {
|
|
||||||
background: var(--semi-black);
|
|
||||||
box-shadow: var(--drop-shadow);
|
|
||||||
padding: 4px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***** Filter Theme *****/
|
|
||||||
.select-content.filter {
|
|
||||||
background: var(--semi-black);
|
|
||||||
box-shadow: var(--drop-shadow);
|
|
||||||
padding: 4px 0;
|
|
||||||
min-width: 150px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***** AdvanceFilter Theme *****/
|
|
||||||
.select-content.advancedfilter {
|
|
||||||
background: var(--light-grey);
|
|
||||||
box-shadow: var(--drop-shadow);
|
|
||||||
padding: 4px 0;
|
|
||||||
min-width: 150px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
::deep .select-button.advancedfilter .search-container {
|
::deep .select-button.advancedfilter .search-container {
|
||||||
height: 24px;
|
height: 24px;
|
||||||
width: 210px;
|
background: var(--input-secondary);
|
||||||
border: 2px solid var(--low-white);
|
}
|
||||||
|
|
||||||
|
::deep .select-button.advancedfilter .search-container input::placeholder {
|
||||||
|
color: #bbb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* width */
|
||||||
|
.select-container::-webkit-scrollbar {
|
||||||
|
width: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Track */
|
||||||
|
.select-container::-webkit-scrollbar-track {
|
||||||
|
background: var(--input-secondary);
|
||||||
|
border-radius: 0 var(--small-radius) var(--small-radius) 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle */
|
||||||
|
.select-container::-webkit-scrollbar-thumb {
|
||||||
|
background: #555;
|
||||||
|
border-radius: var(--small-radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle on hover */
|
||||||
|
.select-container::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: #777;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
function offset(el) {
|
||||||
|
var rect = el.getBoundingClientRect(),
|
||||||
|
scrollLeft = window.scrollY || document.documentElement.scrollLeft,
|
||||||
|
scrollTop = window.scrollX || document.documentElement.scrollTop;
|
||||||
|
return { top: rect.top + scrollTop, left: rect.left + scrollLeft }
|
||||||
|
}
|
||||||
|
|
||||||
|
function resizeSelectContent() {
|
||||||
|
const height = window.innerHeight;
|
||||||
|
const selects = document.getElementsByClassName('select-container');
|
||||||
|
for (var i = 0; i < selects.length; i++) {
|
||||||
|
selects[i].style.maxHeight = height - offset(selects[i]).top - 10 + "px";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addResizeListener = () => {
|
||||||
|
resizeSelectContent();
|
||||||
|
window.addEventListener('resize', resizeSelectContent);
|
||||||
|
};
|
||||||
@@ -1,15 +1,14 @@
|
|||||||
@using GameIdeas.BlazorApp.Shared.Components.Select.Components
|
@using GameIdeas.BlazorApp.Shared.Components.BackdropFilter
|
||||||
|
@using GameIdeas.BlazorApp.Shared.Components.Select.Components
|
||||||
@typeparam TItem
|
@typeparam TItem
|
||||||
|
|
||||||
<div class="select-list" @onclick=HandleButtonClicked>
|
<div class="select-list">
|
||||||
<div class="select-button">
|
<div class="select-button" @onclick=HandleButtonClicked>
|
||||||
@Button
|
@ChildContent
|
||||||
</div>
|
</div>
|
||||||
<div @ref=Container @onfocusout=HandleFocusOut
|
|
||||||
class="select-container @(AlignRight ? "align-right" : "")"
|
|
||||||
tabindex="1000">
|
|
||||||
|
|
||||||
@if (ContentVisile)
|
<div class="select-container @(AlignRight ? "align-right" : "")">
|
||||||
|
@if (IsContentOpen)
|
||||||
{
|
{
|
||||||
<div class="select-content @(Enum.GetName(Theme)?.ToLower())">
|
<div class="select-content @(Enum.GetName(Theme)?.ToLower())">
|
||||||
@foreach (var item in Headers)
|
@foreach (var item in Headers)
|
||||||
@@ -35,3 +34,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<BackdropFilter AllowBodyScroll=true CloseOnClick=true Color="BackdropFilterColor.Transparent"
|
||||||
|
IsVisible=IsContentOpen OnClick="HandleContentClosed" />
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ namespace GameIdeas.BlazorApp.Shared.Components.Select;
|
|||||||
|
|
||||||
public partial class SelectList<TItem>
|
public partial class SelectList<TItem>
|
||||||
{
|
{
|
||||||
[Parameter] public RenderFragment? Button { get; set; }
|
[Parameter] public RenderFragment? ChildContent { get; set; }
|
||||||
[Parameter] public TItem? Value { get; set; }
|
[Parameter] public TItem? Value { get; set; }
|
||||||
[Parameter] public EventCallback<TItem?> ValueChanged { get; set; }
|
[Parameter] public EventCallback<TItem?> ValueChanged { get; set; }
|
||||||
[Parameter] public TItem? Header { get; set; }
|
[Parameter] public TItem? Header { get; set; }
|
||||||
@@ -15,27 +15,16 @@ public partial class SelectList<TItem>
|
|||||||
[Parameter] public SelectListTheme Theme { get; set; }
|
[Parameter] public SelectListTheme Theme { get; set; }
|
||||||
[Parameter] public bool AlignRight { get; set; }
|
[Parameter] public bool AlignRight { get; set; }
|
||||||
|
|
||||||
private bool ContentVisile = false;
|
private bool IsContentOpen = false;
|
||||||
private DateTime ContentLastFocusOut = DateTime.Now;
|
|
||||||
private ElementReference Container;
|
|
||||||
|
|
||||||
public async Task OpenAsync()
|
private void HandleButtonClicked()
|
||||||
{
|
{
|
||||||
if (DateTime.Now - ContentLastFocusOut >= TimeSpan.FromSeconds(0.2))
|
IsContentOpen = !IsContentOpen;
|
||||||
{
|
|
||||||
await Container.FocusAsync();
|
|
||||||
ContentVisile = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Close() => ContentVisile = false;
|
private void HandleContentClosed()
|
||||||
|
|
||||||
private async Task HandleButtonClicked() => await OpenAsync();
|
|
||||||
|
|
||||||
private void HandleFocusOut()
|
|
||||||
{
|
{
|
||||||
ContentLastFocusOut = DateTime.Now;
|
IsContentOpen = false;
|
||||||
ContentVisile = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task HandleItemClicked(SelectElement<TItem> selectedValue)
|
private async Task HandleItemClicked(SelectElement<TItem> selectedValue)
|
||||||
@@ -46,6 +35,7 @@ public partial class SelectList<TItem>
|
|||||||
}
|
}
|
||||||
|
|
||||||
selectedValue.IsSelected = true;
|
selectedValue.IsSelected = true;
|
||||||
|
|
||||||
Value = selectedValue.Item;
|
Value = selectedValue.Item;
|
||||||
await ValueChanged.InvokeAsync(Value);
|
await ValueChanged.InvokeAsync(Value);
|
||||||
}
|
}
|
||||||
@@ -58,6 +48,7 @@ public partial class SelectList<TItem>
|
|||||||
}
|
}
|
||||||
|
|
||||||
selectedValue.IsSelected = true;
|
selectedValue.IsSelected = true;
|
||||||
|
|
||||||
Header = selectedValue.Item;
|
Header = selectedValue.Item;
|
||||||
await HeaderChanged.InvokeAsync(Header);
|
await HeaderChanged.InvokeAsync(Header);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
.select-container {
|
.select-container {
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
z-index: var(--index-dropdown)
|
||||||
}
|
}
|
||||||
|
|
||||||
.align-right {
|
.align-right {
|
||||||
@@ -20,9 +21,13 @@
|
|||||||
animation-duration: 0.4s;
|
animation-duration: 0.4s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.select-button {
|
||||||
|
z-index: var(--index-component)
|
||||||
|
}
|
||||||
|
|
||||||
.line {
|
.line {
|
||||||
margin: 2px 6px;
|
margin: 2px 6px;
|
||||||
border-bottom: 2px solid var(--low-white);
|
border-bottom: 2px solid var(--input-selected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -34,7 +39,7 @@
|
|||||||
|
|
||||||
/***** Sort Theme *****/
|
/***** Sort Theme *****/
|
||||||
.select-content.sort {
|
.select-content.sort {
|
||||||
background: var(--semi-black);
|
background: var(--dropdown-content);
|
||||||
box-shadow: var(--drop-shadow);
|
box-shadow: var(--drop-shadow);
|
||||||
padding: 4px 0;
|
padding: 4px 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ public partial class SliderRange
|
|||||||
{
|
{
|
||||||
var percent1 = (double)(Params.ValueMin - Params.Min) / (Params.Max - Params.Min) * 100;
|
var percent1 = (double)(Params.ValueMin - Params.Min) / (Params.Max - Params.Min) * 100;
|
||||||
var percent2 = (double)(Params.ValueMax - Params.Min) / (Params.Max - Params.Min) * 100;
|
var percent2 = (double)(Params.ValueMax - Params.Min) / (Params.Max - Params.Min) * 100;
|
||||||
return $"background: linear-gradient(to right, var(--light-grey) {percent1}% , var(--violet) {percent1}% , var(--violet) {percent2}%, var(--light-grey) {percent2}%)";
|
return $"background: linear-gradient(to right, var(--line) {percent1}% , var(--violet) {percent1}% , var(--violet) {percent2}%, var(--line) {percent2}%)";
|
||||||
}
|
}
|
||||||
|
|
||||||
private string StatusColor(int value)
|
private string StatusColor(int value)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
.container {
|
.container {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
z-index: var(--index-component)
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="range"] {
|
input[type="range"] {
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace GameIdeas.BlazorApp.Shared.Models;
|
||||||
|
|
||||||
|
public enum AddType
|
||||||
|
{
|
||||||
|
Manual,
|
||||||
|
Auto
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace GameIdeas.BlazorApp.Shared.Models;
|
||||||
|
|
||||||
|
public enum DisplayType
|
||||||
|
{
|
||||||
|
Card,
|
||||||
|
List
|
||||||
|
}
|
||||||
@@ -7,29 +7,39 @@
|
|||||||
--red: #FF5E51;
|
--red: #FF5E51;
|
||||||
--yellow: #FFC107;
|
--yellow: #FFC107;
|
||||||
--green: #43F8C0;
|
--green: #43F8C0;
|
||||||
--light-grey: #5C5C5E;
|
|
||||||
--black: rgba(0, 0, 0, 0.8);
|
|
||||||
--white: #fff;
|
--white: #fff;
|
||||||
--low-white: rgb(255, 255, 255, 0.1);
|
--line: #5C5C5E;
|
||||||
--semi-black: rgba(0, 0, 0, 0.5);
|
--input-primary: rgba(0, 0, 0, 0.8);
|
||||||
--line-black: rgba(0, 0, 0, 0.2);
|
--input-secondary: rgb(45, 45, 48);
|
||||||
|
--input-selected: rgb(255, 255, 255, 0.1);
|
||||||
|
--dropdown-content: rgb(45, 45, 48);
|
||||||
|
|
||||||
--small-radius: 4px;
|
--small-radius: 4px;
|
||||||
--big-radius: 10px;
|
--big-radius: 10px;
|
||||||
--radius: 6px;
|
|
||||||
--drop-shadow: 0px 0px 20px rgba(0, 0, 0, 0.25);
|
--drop-shadow: 0px 0px 20px rgba(0, 0, 0, 0.25);
|
||||||
|
|
||||||
|
--index-background: -100;
|
||||||
|
--index-orb: -1;
|
||||||
|
--index-content: 0;
|
||||||
|
--index-component: 300;
|
||||||
|
--index-floating: 500;
|
||||||
|
--index-backdrop: 700;
|
||||||
|
--index-dropdown: 900;
|
||||||
|
--index-popup: 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
html {
|
html {
|
||||||
font-family: 'Noto Sans', sans-serif;
|
font-family: 'Noto Sans', sans-serif;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: var(--white)
|
color: var(--white);
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
html, body, #app {
|
html, body, #app {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow: hidden;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.valid.modified:not([type=checkbox]) {
|
.valid.modified:not([type=checkbox]) {
|
||||||
|
|||||||
@@ -26,6 +26,8 @@
|
|||||||
<span class="dismiss">🗙</span>
|
<span class="dismiss">🗙</span>
|
||||||
</div>
|
</div>
|
||||||
<script src="_framework/blazor.webassembly.js"></script>
|
<script src="_framework/blazor.webassembly.js"></script>
|
||||||
|
<script src="Shared/Components/BackdropFilter/BackdropFilter.razor.js"></script>
|
||||||
|
<script src="Shared/Components/Select/MultipleSelectList.razor.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
23
src/GameIdeas/GameIdeas.Shared/Constants/Icons.cs
Normal file
23
src/GameIdeas/GameIdeas.Shared/Constants/Icons.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
namespace GameIdeas.Shared.Constants;
|
||||||
|
|
||||||
|
public static class Icons
|
||||||
|
{
|
||||||
|
private const string OpenBraket = "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\">";
|
||||||
|
private const string CloseBraket = "</svg>";
|
||||||
|
|
||||||
|
|
||||||
|
public static class Search
|
||||||
|
{
|
||||||
|
public const string Clear = OpenBraket +
|
||||||
|
"<path d=\"M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z\" />" +
|
||||||
|
CloseBraket;
|
||||||
|
|
||||||
|
public const string Glass = OpenBraket +
|
||||||
|
"<path d=\"M9.5,3A6.5,6.5 0 0,1 16,9.5C16,11.11 15.41,12.59 14.44,13.73L14.71,14H15.5L20.5,19L19,20.5L14,15.5V14.71L13.73,14.44C12.59,15.41 11.11,16 9.5,16A6.5,6.5 0 0,1 3,9.5A6.5,6.5 0 0,1 9.5,3M9.5,5C7,5 5,7 5,9.5C5,12 7,14 9.5,14C12,14 14,12 14,9.5C14,7 12,5 9.5,5Z\" />" +
|
||||||
|
CloseBraket;
|
||||||
|
|
||||||
|
public const string Triangle = OpenBraket +
|
||||||
|
"<path d=\"M1 3H23L12 22\" />" +
|
||||||
|
CloseBraket;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user