From c0b1c950a6c0cfbf7ca3abc4ca0e3fc14ae07e0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20Ko=C5=BEelj?= Date: Wed, 15 Mar 2023 10:24:02 +0100 Subject: [PATCH 01/11] Add global js event handlers for transition and animation ends --- src/Connected.Components/Events/EventHandlers.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 src/Connected.Components/Events/EventHandlers.cs diff --git a/src/Connected.Components/Events/EventHandlers.cs b/src/Connected.Components/Events/EventHandlers.cs new file mode 100644 index 0000000..146a4ee --- /dev/null +++ b/src/Connected.Components/Events/EventHandlers.cs @@ -0,0 +1,14 @@ +using Microsoft.AspNetCore.Components; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Connected.Components; + +[EventHandler("ontransitionend", typeof(EventArgs), enableStopPropagation: true, enablePreventDefault: false)] +[EventHandler("onanimationend", typeof(EventArgs), enableStopPropagation: true, enablePreventDefault: false)] +public static class EventHandlers +{ +} From 35d1da8579ca4d7b6cdc31f9caae3731d7e839c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20Ko=C5=BEelj?= Date: Wed, 15 Mar 2023 10:25:00 +0100 Subject: [PATCH 02/11] Add animation styles and transitions to drop down menu and backdrop --- .../Styles/components/_dropdown.scss | 84 ++++++++++++------- 1 file changed, 54 insertions(+), 30 deletions(-) diff --git a/src/Connected.Components/Styles/components/_dropdown.scss b/src/Connected.Components/Styles/components/_dropdown.scss index 71014c8..5ac4e40 100644 --- a/src/Connected.Components/Styles/components/_dropdown.scss +++ b/src/Connected.Components/Styles/components/_dropdown.scss @@ -1,30 +1,55 @@ @use "../globals/" as *; @use "../util/" as *; +.drop-down { + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + min-width: 80%; + height: auto; + max-height: max-content; + width: 80%; + opacity: 0; + display: flex; + flex-direction: column; + z-index: $dropdown-zindex; + list-style: none; + background-color: #fff; + box-shadow: $base-box-shadow; + border-radius: $border-radius-lg; + transition: all 0.3s ease-in-out; +} +.drop-down.fade-in { + animation: fade-in 0.3s ease-in-out forwards; +} +.drop-down.fade-out { + animation: fade-out 0.3s ease-in-out forwards; +} -.drop-down { - position: fixed; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - min-width: 80%; - width: 80%; - height: 0; - max-height: 0; - display: flex; - flex-direction: column; - opacity: 0; - pointer-events: none; - z-index: $dropdown-zindex; - list-style: none; - background-color: #fff; - box-shadow: $base-box-shadow; - border-radius: $border-radius-lg; - transition: all 0.3s ease-in-out; +@keyframes fade-in { + 0% { + opacity: 0; + } + + 100% { + opacity: 1; + } +} + +@keyframes fade-out { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + } } + @include breakpoint(sm) { .drop-down { position: absolute; @@ -39,17 +64,16 @@ } .backdrop { - display: none; - opacity: 0; - z-index: $backdrop-zindex; - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - overflow: hidden; - background-color: rgba(0, 0, 0, 0.5); - transition: all 0.3s ease-in-out; + z-index: $backdrop-zindex; + position: fixed; + display: block; + top: 0; + right: 0; + bottom: 0; + left: 0; + overflow: hidden; + background-color: rgba(0, 0, 0, 0.5); + transition: all 0.3s ease-in-out; } .dropdown-header { From 30a1e7924c73c1ac4cb5202052f0121df9d8e476 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20Ko=C5=BEelj?= Date: Wed, 15 Mar 2023 10:29:47 +0100 Subject: [PATCH 03/11] Remove unused app.css from default index.html --- src/Connected.Components.Showcase.Runner/wwwroot/index.html | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Connected.Components.Showcase.Runner/wwwroot/index.html b/src/Connected.Components.Showcase.Runner/wwwroot/index.html index 3a6c8ca..c905d6e 100644 --- a/src/Connected.Components.Showcase.Runner/wwwroot/index.html +++ b/src/Connected.Components.Showcase.Runner/wwwroot/index.html @@ -6,7 +6,6 @@ Connected.Components.Showcase.Runner - From 651b866f05fbc96fb2db8cec0521153e6a4f678c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20Ko=C5=BEelj?= Date: Wed, 15 Mar 2023 10:30:18 +0100 Subject: [PATCH 04/11] Set versions of Microsoft.AspNetCore.Components to auto-update --- src/Connected.Components/Connected.Components.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Connected.Components/Connected.Components.csproj b/src/Connected.Components/Connected.Components.csproj index 68de09a..163f7f4 100644 --- a/src/Connected.Components/Connected.Components.csproj +++ b/src/Connected.Components/Connected.Components.csproj @@ -28,7 +28,7 @@ - + From 3a734a71ef1e6855cef5f76f6bedbe3c65e8ee17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20Ko=C5=BEelj?= Date: Wed, 15 Mar 2023 10:31:08 +0100 Subject: [PATCH 05/11] Remove css defined transitions for select, as this is now code controlled --- .../Styles/components/_inputs.scss | 25 ------------------- 1 file changed, 25 deletions(-) diff --git a/src/Connected.Components/Styles/components/_inputs.scss b/src/Connected.Components/Styles/components/_inputs.scss index 0057e5a..935b75a 100644 --- a/src/Connected.Components/Styles/components/_inputs.scss +++ b/src/Connected.Components/Styles/components/_inputs.scss @@ -1,10 +1,6 @@ @use "../util" as *; @use "../globals" as *; - - - - $trans-time: 300ms; $width: 100%; @@ -199,29 +195,8 @@ form{ display:none } -/*SELECT*/ - - -select { - appearance: none; - - &:focus-within ~ .drop-down { - height: auto; - max-height: max-content; - opacity: 1; - pointer-events: initial; - - } - &:focus-within ~ .backdrop { - opacity: 1; - display: block; - } -} - - /*form group-alt*/ - .form-group-alt { --height: 2.5rem; From 81fece5cd49394e2d7d8087b18ff7b618f6264f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20Ko=C5=BEelj?= Date: Wed, 15 Mar 2023 10:32:41 +0100 Subject: [PATCH 06/11] Add Tom PIT git to nuget resource in order to restore css compilation tool --- nuget.config | 1 + 1 file changed, 1 insertion(+) diff --git a/nuget.config b/nuget.config index 05dc31f..2611e88 100644 --- a/nuget.config +++ b/nuget.config @@ -10,6 +10,7 @@ + \ No newline at end of file From 86e32a197b24067b818c9c35b25f81395592d262 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20Ko=C5=BEelj?= Date: Wed, 15 Mar 2023 10:33:58 +0100 Subject: [PATCH 07/11] Update references to include prerelease version Remove unneeded watch ignore entries --- .../Connected.Components.Showcase.Runner.csproj | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/Connected.Components.Showcase.Runner/Connected.Components.Showcase.Runner.csproj b/src/Connected.Components.Showcase.Runner/Connected.Components.Showcase.Runner.csproj index f6e0064..7de2092 100644 --- a/src/Connected.Components.Showcase.Runner/Connected.Components.Showcase.Runner.csproj +++ b/src/Connected.Components.Showcase.Runner/Connected.Components.Showcase.Runner.csproj @@ -7,8 +7,8 @@ - - + + @@ -22,9 +22,4 @@ - - - - - From 455119f46734b0523946f3b6a7e2d2c7da95a7e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20Ko=C5=BEelj?= Date: Wed, 15 Mar 2023 10:34:34 +0100 Subject: [PATCH 08/11] Add TransitionAnimator component to help with transition implementations --- .../Components/TransitionAnimator.razor | 107 ++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 src/Connected.Components/Components/TransitionAnimator.razor diff --git a/src/Connected.Components/Components/TransitionAnimator.razor b/src/Connected.Components/Components/TransitionAnimator.razor new file mode 100644 index 0000000..399cfd1 --- /dev/null +++ b/src/Connected.Components/Components/TransitionAnimator.razor @@ -0,0 +1,107 @@ +@using Connected.Utilities; + +
+ @if (ContentVisible) + { + @ChildContent + } +
+ + + +@code { + private bool _visible = false; + + /// + /// The class to append to the container while content is visible and transitioning in + /// + [Parameter, EditorRequired] + public string? TransitionInClass { get; set; } + + /// + /// The class to append to the container while content is transitioning out and hidden + /// + [Parameter, EditorRequired] + public string? TransitionOutClass { get; set; } + + /// + /// The class to append to the container to control transitions + /// + [Parameter] + public string? TransitionContainerClass { get; set; } = "transition-container-component"; + + /// + /// Controls the visibility of the child content + /// + [Parameter, EditorRequired] + public bool Visible { get => _visible; set => StartTransition(value); } + + /// + /// The content to show/hide + /// + [Parameter, EditorRequired] + public RenderFragment? ChildContent { get; set; } + + /// + /// Indicates a transition has ended. Useful for visual cleanup. + /// + [Parameter] + public EventCallback TransitionEnded { get; set; } + + /// + /// The duration of transitions in milliseconds. + /// + [Parameter] + public int TransitionDuration { get; set; } = 2000; + + private bool TransitioningIn { get; set; } + + private bool TransitioningOut { get; set; } + + private bool ContentVisible { get; set; } + + private CssBuilder ClassList + { + get + { + return new CssBuilder(TransitionContainerClass) + .AddClass(TransitionInClass, TransitioningIn) + .AddClass(TransitionOutClass, TransitioningOut); + } + } + + private void StartTransition(bool visible) + { + if (visible == Visible) + return; + + _visible = visible; + + TransitioningIn = visible; + + TransitioningOut = !visible; + + if (visible) + ContentVisible = true; + + StateHasChanged(); + } + + private void TransitionEnd() + { + ContentVisible = Visible; + StateHasChanged(); + + TransitionEnded.InvokeAsync(); + } + + protected override void OnInitialized() + { + base.OnInitialized(); + ContentVisible = Visible; + } +} From b250353ad8cd5a4417b2574ef26567838698193d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20Ko=C5=BEelj?= Date: Wed, 15 Mar 2023 10:35:13 +0100 Subject: [PATCH 09/11] Add dropdown component --- .../Components/Dropdown.razor | 48 ++++++++ .../Components/Dropdown.razor.cs | 112 ++++++++++++++++++ 2 files changed, 160 insertions(+) create mode 100644 src/Connected.Components/Components/Dropdown.razor create mode 100644 src/Connected.Components/Components/Dropdown.razor.cs diff --git a/src/Connected.Components/Components/Dropdown.razor b/src/Connected.Components/Components/Dropdown.razor new file mode 100644 index 0000000..99a445e --- /dev/null +++ b/src/Connected.Components/Components/Dropdown.razor @@ -0,0 +1,48 @@ +@typeparam T; +@inherits Connected.Models.InputBase; + +
+ + + + + + +
@HelperText
+
@ErrorText
+ + + + + + + + + + + + + +
+
+ +
+
\ No newline at end of file diff --git a/src/Connected.Components/Components/Dropdown.razor.cs b/src/Connected.Components/Components/Dropdown.razor.cs new file mode 100644 index 0000000..2c2780c --- /dev/null +++ b/src/Connected.Components/Components/Dropdown.razor.cs @@ -0,0 +1,112 @@ +using Microsoft.AspNetCore.Components; +using System.Collections.ObjectModel; +using Connected.Models; +using System.Collections.Immutable; + +namespace Connected.Components; + +public partial class Dropdown : InputBase, IAsyncDisposable +{ + [Parameter, EditorRequired] + public ObservableCollection Items { get; set; } = new ObservableCollection(); + + [Parameter] + public RenderFragment? OptionTemplate { get; set; } + + [Parameter] + public RenderFragment? SelectedValueTemplate { get; set; } + + [Parameter, EditorRequired] + public Func ItemToKey { get; set; } = default!; + + [Parameter] + public ObservableCollection SelectedItems { get; set; } = new(); + + [Parameter] + public EventCallback> SelectedItemsChanged { get; set; } + + [Parameter] + public bool AllowMultiple { get; set; } + + private bool DropdownOpen { get; set; } + + private bool IsItemSelected(T item) + { + return SelectedItems.Contains(item); + } + + public void Open() + { + DropdownOpen = true; + } + + public void Close() + { + DropdownOpen = false; + } + + public void Toggle() + { + DropdownOpen = !DropdownOpen; + } + + protected override void OnInitialized() + { + base.OnInitialized(); + + OptionTemplate ??= (T item) => (builder) => + { + builder.OpenElement(0, "div"); + builder.SetKey(item); + builder.AddContent(1, item?.ToString()); + builder.CloseElement(); + }; + + SelectedValueTemplate ??= (T item) => (builder) => + { + builder.OpenElement(0, "span"); + builder.SetKey(item); + builder.AddContent(1, item?.ToString()); + builder.CloseElement(); + }; + } + protected override void OnParametersSet() + { + base.OnParametersSet(); + + Items.CollectionChanged += CollectionChanged; + SelectedItems.CollectionChanged += CollectionChanged; + } + + private void CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) + { + if (sender == SelectedItems) + SelectedItemsChanged.InvokeAsync(SelectedItems); + + StateHasChanged(); + } + + private async Task OptionSelected(T item) + { + if (AllowMultiple) + { + if (SelectedItems.Contains(item)) + { + SelectedItems.Remove(item); + return; + } + } + else + { + SelectedItems.Clear(); + } + + SelectedItems.Add(item); + } + + public async ValueTask DisposeAsync() + { + Items.CollectionChanged -= CollectionChanged; + SelectedItems.CollectionChanged -= CollectionChanged; + } +} \ No newline at end of file From 0830532e7ecd8a73599d0560ffeffce441ce995a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20Ko=C5=BEelj?= Date: Wed, 15 Mar 2023 10:35:41 +0100 Subject: [PATCH 10/11] Add dropdown demo page for implementation testing --- .../Pages/DropdownDemo.razor | 18 ++++++++++++ .../Pages/DropdownDemo.razor.cs | 29 +++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 src/Connected.Components.Showcase.Runner/Pages/DropdownDemo.razor create mode 100644 src/Connected.Components.Showcase.Runner/Pages/DropdownDemo.razor.cs diff --git a/src/Connected.Components.Showcase.Runner/Pages/DropdownDemo.razor b/src/Connected.Components.Showcase.Runner/Pages/DropdownDemo.razor new file mode 100644 index 0000000..c06ae02 --- /dev/null +++ b/src/Connected.Components.Showcase.Runner/Pages/DropdownDemo.razor @@ -0,0 +1,18 @@ +@page "/demo/components/dropdown" + +@namespace Connected.Components.Showcase.Runner + +@using Connected.Components; + + e.Value.ToString()) @bind-SelectedItems="@SelectedItems" AllowMultiple=true> + + @context.Name + + + @context.Name + + + +
+ @string.Join(", ", SelectedItems.Select(e=> e.Value)) +
diff --git a/src/Connected.Components.Showcase.Runner/Pages/DropdownDemo.razor.cs b/src/Connected.Components.Showcase.Runner/Pages/DropdownDemo.razor.cs new file mode 100644 index 0000000..75f36ad --- /dev/null +++ b/src/Connected.Components.Showcase.Runner/Pages/DropdownDemo.razor.cs @@ -0,0 +1,29 @@ +using System.Collections.ObjectModel; + +namespace Connected.Components.Showcase.Runner; + +public partial class DropdownDemo +{ + private ObservableCollection SelectedItems { get; set; } = new(); + + private ObservableCollection Items { get; set; } = new ObservableCollection + { + new TestObject + { + Name= "Simple", + Value = 1 + }, + new TestObject + { + Name = "Simpler", + Value = 2 + } + }; + + public class TestObject + { + public string Name { get; set; } + + public long Value { get; set; } + } +} \ No newline at end of file From 98ff5d5dd84b3d1e40a3366f5e93135a6aac968c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20Ko=C5=BEelj?= Date: Wed, 15 Mar 2023 11:08:59 +0100 Subject: [PATCH 11/11] Remove unused required parameter ItemToKey --- src/Connected.Components/Components/Dropdown.razor.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Connected.Components/Components/Dropdown.razor.cs b/src/Connected.Components/Components/Dropdown.razor.cs index 2c2780c..fa821b2 100644 --- a/src/Connected.Components/Components/Dropdown.razor.cs +++ b/src/Connected.Components/Components/Dropdown.razor.cs @@ -16,9 +16,6 @@ public partial class Dropdown : InputBase, IAsyncDisposable [Parameter] public RenderFragment? SelectedValueTemplate { get; set; } - [Parameter, EditorRequired] - public Func ItemToKey { get; set; } = default!; - [Parameter] public ObservableCollection SelectedItems { get; set; } = new();