Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
555 changes: 555 additions & 0 deletions src/BlazorUI/Bit.BlazorUI/Components/Utilities/Sticky/BitSticky.cs

Large diffs are not rendered by default.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
@import "../../../Styles/functions.scss";

.bit-stk {
z-index: 1;
// Enough to pass over the plain flowing content the element sticks above without covering the
// popups and overlays of the rest of the page, which sit far higher up the scale. Declared as a
// custom property so a stylesheet can raise it for a whole region at once, the way the ZIndex
// parameter raises it for one component.
--bit-stk-zin: 1;
z-index: var(--bit-stk-zin);
position: sticky;

// A disabled sticky steps back into the normal flow: a static position ignores every inset, so
// the element scrolls away with its content like any other box - which is what makes IsEnabled
// the switch that turns the stickiness itself off.
&.bit-dis {
position: static;
}
}

.bit-stk-top {
Expand All @@ -29,4 +41,4 @@
.bit-stk-sae {
inset-inline-end: 0;
inset-inline-start: 0;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
namespace Bit.BlazorUI;

/// <summary>
/// The edges of the scrolling container a BitSticky is currently pinned to.
/// </summary>
/// <remarks>
/// These are the physical edges of the scrollport, the way the browser resolves them: a
/// <see cref="BitStickyPosition.Start"/> sticky reports <see cref="Left"/> in a left-to-right
/// container and <see cref="Right"/> in a right-to-left one.
/// <br />
/// More than one of them can be set at once, since an element pinned into a corner is held by the
/// two edges that meet there.
/// </remarks>
[Flags]
public enum BitStickyEdges
{
/// <summary>
/// The element is not pinned: it is travelling with the content of its scrolling container.
/// </summary>
None = 0,

/// <summary>
/// The element is pinned to the top edge of its scrolling container.
/// </summary>
Top = 1,

/// <summary>
/// The element is pinned to the bottom edge of its scrolling container.
/// </summary>
Bottom = 2,

/// <summary>
/// The element is pinned to the left edge of its scrolling container.
/// </summary>
Left = 4,

/// <summary>
/// The element is pinned to the right edge of its scrolling container.
/// </summary>
Right = 8,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
namespace Bit.BlazorUI;

/// <summary>
/// The parameters for <see cref="BitSticky"/> component.
/// </summary>
/// <remarks>
/// What belongs here is what every sticky of a page or of an app agrees on - which edge they pin to,
/// how far from it, how they look while pinned, what they pass over. The content and the callbacks
/// are deliberately not here: they are what makes one sticky the one it is, and cascading them would
/// give every sticky on the page the same content and the same observer.
/// </remarks>
public class BitStickyParams : BitComponentBaseParams, IBitComponentParams
{
/// <summary>
/// Represents the parameter name used to identify the <see cref="BitSticky"/> cascading parameters within <see cref="BitParams"/>.
/// </summary>
/// <remarks>
/// This constant is typically used when referencing or accessing the BitSticky value in
/// parameterized APIs or configuration settings. Using this constant helps ensure consistency and reduces the risk
/// of typographical errors.
/// </remarks>
public const string ParamName = $"{nameof(BitParams)}.{nameof(BitSticky)}";



public string Name => ParamName;



/// <summary>
/// Gets or sets the vertical offset the element pins at from the bottom edge.
/// </summary>
public string? Bottom { get; set; }

/// <summary>
/// Gets or sets the custom html element used for the root node.
/// </summary>
public string? Element { get; set; }

/// <summary>
/// Gets or sets the horizontal offset the element pins at from the left edge.
/// </summary>
public string? Left { get; set; }

/// <summary>
/// Gets or sets the edge of the scrolling container the element pins to.
/// </summary>
public BitStickyPosition? Position { get; set; }

/// <summary>
/// Gets or sets the horizontal offset the element pins at from the right edge.
/// </summary>
public string? Right { get; set; }

/// <summary>
/// Gets or sets the CSS class applied to the root element only while the component is stuck.
/// </summary>
public string? StuckClass { get; set; }

/// <summary>
/// Gets or sets the CSS style applied to the root element only while the component is stuck.
/// </summary>
public string? StuckStyle { get; set; }

/// <summary>
/// Gets or sets the vertical offset the element pins at from the top edge.
/// </summary>
public string? Top { get; set; }

/// <summary>
/// Gets or sets the z-index of the root element.
/// </summary>
public int? ZIndex { get; set; }



/// <summary>
/// Updates the properties of the specified <see cref="BitSticky"/> instance with any values that have been set on
/// this object, if those properties have not already been set on the <see cref="BitSticky"/> itself.
/// </summary>
/// <param name="bitSticky">
/// The <see cref="BitSticky"/> instance whose properties will be updated. Cannot be null.
/// </param>
public void UpdateParameters(BitSticky bitSticky)
{
if (bitSticky is null) return;

UpdateBaseParameters(bitSticky);

if (Bottom.HasValue() && bitSticky.HasNotBeenSet(nameof(Bottom)))
{
bitSticky.Bottom = Bottom;

bitSticky.ClassBuilder.Reset();
bitSticky.StyleBuilder.Reset();
}

if (Element.HasValue() && bitSticky.HasNotBeenSet(nameof(Element)))
{
bitSticky.Element = Element;
}

if (Left.HasValue() && bitSticky.HasNotBeenSet(nameof(Left)))
{
bitSticky.Left = Left;

bitSticky.ClassBuilder.Reset();
bitSticky.StyleBuilder.Reset();
}

if (Position.HasValue && bitSticky.HasNotBeenSet(nameof(Position)))
{
bitSticky.Position = Position.Value;

bitSticky.ClassBuilder.Reset();
}

if (Right.HasValue() && bitSticky.HasNotBeenSet(nameof(Right)))
{
bitSticky.Right = Right;

bitSticky.ClassBuilder.Reset();
bitSticky.StyleBuilder.Reset();
}

if (StuckClass.HasValue() && bitSticky.HasNotBeenSet(nameof(StuckClass)))
{
bitSticky.StuckClass = StuckClass;

bitSticky.ClassBuilder.Reset();
}

if (StuckStyle.HasValue() && bitSticky.HasNotBeenSet(nameof(StuckStyle)))
{
bitSticky.StuckStyle = StuckStyle;
}

if (Top.HasValue() && bitSticky.HasNotBeenSet(nameof(Top)))
{
bitSticky.Top = Top;

bitSticky.ClassBuilder.Reset();
bitSticky.StyleBuilder.Reset();
}

if (ZIndex.HasValue && bitSticky.HasNotBeenSet(nameof(ZIndex)))
{
bitSticky.ZIndex = ZIndex.Value;

bitSticky.StyleBuilder.Reset();
}
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,41 @@
namespace Bit.BlazorUI;

/// <summary>
/// The edges of the scrolling container a BitSticky pins itself to.
/// </summary>
public enum BitStickyPosition
{
/// <summary>
/// Sticks to the top edge while the container scrolls vertically.
/// </summary>
Top,

/// <summary>
/// Sticks to the bottom edge while the container scrolls vertically.
/// </summary>
Bottom,

/// <summary>
/// Sticks to whichever vertical edge the scroll carries it to: the top while scrolling down past
/// it, the bottom while it is still below the fold.
/// </summary>
TopAndBottom,

/// <summary>
/// Sticks to the start edge while the container scrolls horizontally - the left edge in LTR, the
/// right edge in RTL.
/// </summary>
Start,

/// <summary>
/// Sticks to the end edge while the container scrolls horizontally - the right edge in LTR, the
/// left edge in RTL.
/// </summary>
End,

/// <summary>
/// Sticks to whichever horizontal edge the scroll carries it to, following the reading direction
/// the way Start and End do.
/// </summary>
StartAndEnd,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
namespace Bit.BlazorUI;

internal static class StickiesJsRuntimeExtensions
{
internal static ValueTask BitStickiesSetup(this IJSRuntime jsRuntime, string id, DotNetObjectReference<BitSticky> obj)
{
return jsRuntime.InvokeVoid("BitBlazorUI.Stickies.setup", id, obj);
}

internal static ValueTask BitStickiesRefresh(this IJSRuntime jsRuntime, string id)
{
return jsRuntime.InvokeVoid("BitBlazorUI.Stickies.refresh", id);
}

internal static ValueTask BitStickiesDispose(this IJSRuntime jsRuntime, string id)
{
return jsRuntime.InvokeVoid("BitBlazorUI.Stickies.dispose", id);
}
}
Loading
Loading