LilyDesignSystem.Blazor.SharePicker 0.2.1

dotnet add package LilyDesignSystem.Blazor.SharePicker --version 0.2.1
                    
NuGet\Install-Package LilyDesignSystem.Blazor.SharePicker -Version 0.2.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="LilyDesignSystem.Blazor.SharePicker" Version="0.2.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="LilyDesignSystem.Blazor.SharePicker" Version="0.2.1" />
                    
Directory.Packages.props
<PackageReference Include="LilyDesignSystem.Blazor.SharePicker" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add LilyDesignSystem.Blazor.SharePicker --version 0.2.1
                    
#r "nuget: LilyDesignSystem.Blazor.SharePicker, 0.2.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package LilyDesignSystem.Blazor.SharePicker@0.2.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=LilyDesignSystem.Blazor.SharePicker&version=0.2.1
                    
Install as a Cake Addin
#tool nuget:?package=LilyDesignSystem.Blazor.SharePicker&version=0.2.1
                    
Install as a Cake Tool

SharePicker (Blazor helper)

A headless Blazor 10 share control: an icon button (a bundled outline-arrow SVG, not a Unicode character) that opens the native share sheet where the browser has one, and otherwise shows a list of destinations you supply, plus copy the page URL.

Ships no CSS, no JS file, and no third-party endpoints.

The single source of truth is spec/index.md. This file is the human-readable guide.

Install

Add a project reference to LilyDesignSystem.Blazor.SharePicker.csproj, or the published LilyDesignSystem.Blazor.SharePicker NuGet package.

<ProjectReference Include="path/to/LilyDesignSystem.Blazor.SharePicker.csproj" />

Quick start

@using LilyDesignSystem.Blazor.Helpers

<SharePicker Label="Share this page"
             Title="An article worth reading"
             Targets="@Targets"
             CopyLabel="Copy link"
             CopiedLabel="Link copied"
             CopyFailedLabel="Could not copy — copy it from the address bar" />

@code {
    private static readonly ShareTarget[] Targets =
    {
        new()
        {
            Id = "mastodon",
            Label = "Mastodon",
            Href = (url, title, _) =>
                $"https://mastodon.social/share?text={Uri.EscapeDataString(title)}%20{Uri.EscapeDataString(url)}",
        },
        new()
        {
            Id = "email",
            Label = "Email",
            Href = (url, title, _) =>
                $"mailto:?subject={Uri.EscapeDataString(title)}&body={Uri.EscapeDataString(url)}",
            NewTab = false,
        },
    };
}

Url defaults to the current page (read from NavigationManager), so the common case needs no wiring.

The control needs an interactive render mode — InteractiveServer, InteractiveWebAssembly, or InteractiveAuto. Under static SSR it renders correctly but cannot act: OnAfterRenderAsync never fires, so nothing can open the sheet, write the clipboard, or move focus.

You supply the destinations

This package ships no social-network URLs. That is deliberate: which networks belong in your product is an editorial and privacy decision, the share endpoints change, and networks die. You pass Targets, so the labels localise with the rest of your copy and no third-party endpoint is baked into a design system.

Href is a Func<string, string, string, string> — (url, title, text) — so you own the whole URL and its encoding:

new ShareTarget
{
    Id = "linkedin",
    Label = "LinkedIn",
    Href = (url, _, _) =>
        $"https://www.linkedin.com/sharing/share-offsite/?url={Uri.EscapeDataString(url)}",
}

Set NewTab = false on a destination that should open in the same tab — mailto: links being the usual case. It drops target="_blank" for that destination only.

Native share sheet

With Strategy.Auto (the default), pressing the button on a device with navigator.share opens the OS sheet — the user gets their real installed apps, and nothing is disclosed to a third party by the act of opening it. Where there is no sheet, the list opens instead.

This means behaviour differs by platform, which is worth knowing when you write help text or test scripts. Force one path with Strategy.List or Strategy.Native.

A dismissed sheet ends the interaction — the list does not then pop open, which would resurrect UI the user just dismissed.

Copy to clipboard

Supply CopyLabel and a copy item appears. There is no default label, because a default would be a hardcoded English string. CopiedLabel and CopyFailedLabel are announced in a polite live region — copying is otherwise silent, so without them the user gets no confirmation.

Failure is handled, not assumed away: a denied permission, an insecure context, or a browser with no async clipboard all announce CopyFailedLabel rather than throwing.

Destinations render as real <a> elements, not role="menuitem". A menuitem role strips middle-click, open-in-new-tab, and copy-link-address — affordances users genuinely reach for on a share list. The WAI-ARIA APG suggests a disclosure when the items are links. Copy is a real action, so it is a <button>.

Driving it from your own UI

ActivateAsync(), CopyAsync() and ShareNativelyAsync() are public, so a @ref lets you trigger the control from elsewhere:

<SharePicker @ref="share" Label="Share" Targets="@Targets" />
<button type="button" @onclick="() => share!.ActivateAsync()">Share</button>

@code {
    private SharePicker? share;
}

Custom icon

ChildContent replaces the icon inside the button and receives a SharePickerContext of { Open, Url }:

<SharePicker Label="Share" Targets="@Targets">
    <span class="my-icon" aria-hidden="true">@(context.Open ? "▲" : "▶")</span>
</SharePicker>

It replaces the icon only — it does not render list items.

Parameters

Full table in spec/index.md §4.1. Required: Label. Everything else is optional.

Static helpers

Member Purpose
SharePicker.NextSharePickerId() Mint a stable, prerender-safe id prefix.
SharePicker.CanShareNativelyAsync(js) Does this browser have a share sheet?
SharePicker.CanCopyAsync(js) Does this browser have an async clipboard?

Both probes are async — the browser is only reachable over JS interop — and both return false during prerender rather than throwing.

Accessibility

  • The icon is aria-hidden; the name comes from aria-label, and the list repeats it (aria-label = Label) so a screen reader entering the list hears what it is for.
  • Escape closes and returns focus to the button; arrows move between items and clamp; Home / End jump; Tab parks focus on the button before closing, so the next Tab proceeds from the picker's position.
  • The status region is polite and empty on load.
  • Tradeoff: an icon-only control's name rests entirely on Label — there is no visible text fallback. See docs/accessibility.md.

Styling

Class hooks: .share-picker (root), .share-picker-button, .share-picker-icon, .share-picker-list, .share-picker-list-item, .share-picker-target, .share-picker-copy, .share-picker-status.

The package ships no CSS. The root themes/ stylesheets style the button and popup, including the optical icon sizing that keeps every picker's icon visually consistent.

Position the root and the list yourself (position: relative / position: absolute), or an open list shoves the page around.

Tests

From ../tests/LilyDesignSystem.Blazor.Helpers.Tests:

dotnet test

34 cases for this package, one or more per §7 clause; 122 across the catalog.


Lily™ and Lily Design System™ are trademarks.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on LilyDesignSystem.Blazor.SharePicker:

Package Downloads
LilyDesignSystem.Blazor.PickerBar

Lily Design System Blazor picker bar: composes theme-picker, locale-picker, text-size-picker, and share-picker into one page-header row. Headless, SSR-safe, no CSS.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.2.1 33 10/1/2026
0.2.0 112 9/16/2026
0.1.0 111 9/2/2026