Rask
Rask
v0.23.1-alpha.0.440

Components

Callout

A message set apart from the page: an icon, a heading, text, and what to do about it. It announces nothing by itself; one that appears because something happened says so with Role.

Drawn and behaving as Flux UI's callout does, measured against its live docs.

Callout

CalloutExample.cs
namespace Rask.Site.Features.UiDocs.Examples;

public sealed partial class CalloutExample : Component
{
    protected override Component? Render() =>
        Ui.Callout.Icon(Ui.IconName.Clock)[
            Ui.CalloutHeading["Upcoming maintenance"],
            Ui.CalloutText[
                "Our servers will be undergoing scheduled maintenance this Sunday from 2 AM - 5 AM UTC. "
                + "Some services may be temporarily unavailable. ",
                Ui.CalloutLink.Href("#")["Learn more"]
            ]
        ];
}
Live result
Upcoming maintenance
Our servers will be undergoing scheduled maintenance this Sunday from 2 AM - 5 AM UTC. Some services may be temporarily unavailable. Learn more

Icon inside heading

CalloutHeadingIconExample.cs
namespace Rask.Site.Features.UiDocs.Examples;

public sealed partial class CalloutHeadingIconExample : Component
{
    protected override Component? Render() =>
        Ui.Callout[
            Ui.CalloutHeading.Icon(Ui.IconName.Newspaper)["Policy update"],
            Ui.CalloutText["We've updated our Terms of Service and Privacy Policy. Please review them to stay informed."]
        ];
}
Live result
Policy update
We've updated our Terms of Service and Privacy Policy. Please review them to stay informed.

Custom icon

Any SVG of your own in place of a Heroicon.

CalloutCustomIconExample.cs
namespace Rask.Site.Features.UiDocs.Examples;

public sealed partial class CalloutCustomIconExample : Component
{
    private const string AlarmClock =
        "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" "
        + "stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">"
        + "<circle cx=\"12\" cy=\"13\" r=\"8\"/><path d=\"M12 9v4l2 2\"/><path d=\"M5 3 2 6\"/><path d=\"m22 6-3-3\"/>"
        + "<path d=\"M6.38 18.7 4 21\"/><path d=\"M17.64 18.67 20 21\"/></svg>";

    protected override Component? Render() =>
        Ui.Callout.CustomIcon(Raw.Value(AlarmClock))[
            Ui.CalloutHeading["Notification system updated"],
            Ui.CalloutText["We've improved our notification system to deliver alerts faster and more reliably."]
        ];
}
Live result
Notification system updated
We've improved our notification system to deliver alerts faster and more reliably.

With actions

CalloutActionsExample.cs
namespace Rask.Site.Features.UiDocs.Examples;

public sealed partial class CalloutActionsExample : Component
{
    protected override Component? Render() =>
        Ui.Callout.Icon(Ui.IconName.Clock).Actions([Ui.Button["Renew now"], Ui.Button.Ghost["View plans"]])[
            Ui.CalloutHeading["Subscription expiring soon"],
            Ui.CalloutText["Your current plan will expire in 3 days. Renew now to avoid service interruption and continue accessing premium features."]
        ];
}
Live result
Subscription expiring soon
Your current plan will expire in 3 days. Renew now to avoid service interruption and continue accessing premium features.

Inline actions

Inline puts the actions beside the text, where there is room.

CalloutInlineActionsExample.cs
namespace Rask.Site.Features.UiDocs.Examples;

public sealed partial class CalloutInlineActionsExample : Component
{
    protected override Component? Render() =>
        Div.Class("space-y-3")[
            Ui.Callout.Icon(Ui.IconName.Cube).Secondary.Inline().Actions([Ui.Button["Track order ->"], Ui.Button.Ghost["Reschedule"]])[
                Ui.CalloutHeading["Your package is delayed"]
            ],
            Ui.Callout.Icon(Ui.IconName.ExclamationTriangle).Secondary.Inline().Actions(Ui.Button["Update billing"])[
                Ui.CalloutHeading["Payment issue detected"],
                Ui.CalloutText["Your last payment attempt failed. Update your billing details to prevent service interruption."]
            ]
        ];
}
Live result
Your package is delayed
Payment issue detected
Your last payment attempt failed. Update your billing details to prevent service interruption.

Dismissible

The callout places the control; what pressing it does is the page's — here, two fields.

CalloutDismissibleExample.cs
namespace Rask.Site.Features.UiDocs.Examples;

public sealed partial class CalloutDismissibleExample : Component
{
    private bool _meeting = true;
    private bool _login = true;

    protected override Component? Render() =>
        Div.Class("space-y-3")[
            _meeting
                ? Ui.Callout.Key("meeting").Icon(Ui.IconName.Bell).Secondary.Inline().Controls(Dismiss(() => _meeting = false))[
                    Ui.CalloutHeading["Upcoming meeting"],
                    Ui.CalloutText["10:00 AM"]
                ]
                : null,
            _login
                ? Ui.Callout.Key("login").Icon(Ui.IconName.FingerPrint).Secondary
                    .Actions([Ui.Button["Change password"], Ui.Button.Ghost["Review activity"]])
                    .Controls(Dismiss(() => _login = false))[
                    Ui.CalloutHeading["Unusual login attempt"],
                    Ui.CalloutText["We detected a login from a new device in New York, USA. If this was you, no action is needed. If not, secure your account immediately."]
                ]
                : null,
            _meeting && _login ? null : Ui.Button.Key("restore").Sm.OnClick(() => { _meeting = _login = true; })["Show them again"]
        ];

    private static UiButton Dismiss(Action dismiss) =>
        Ui.Button.Ghost.Icon(Ui.IconName.XMark).AriaLabel("Dismiss").OnClick(dismiss);
}
Live result
Upcoming meeting
10:00 AM
Unusual login attempt
We detected a login from a new device in New York, USA. If this was you, no action is needed. If not, secure your account immediately.

Variants

CalloutVariantsExample.cs
namespace Rask.Site.Features.UiDocs.Examples;

public sealed partial class CalloutVariantsExample : Component
{
    protected override Component? Render() =>
        Div.Class("space-y-3")[
            Ui.Callout.Secondary.Icon(Ui.IconName.InformationCircle).Heading("Your account has been successfully created."),
            Ui.Callout.Success.Icon(Ui.IconName.CheckCircle).Heading("Your account is verified and ready to use."),
            Ui.Callout.Warning.Icon(Ui.IconName.ExclamationCircle).Heading("Please verify your account to unlock all features."),
            Ui.Callout.Danger.Icon(Ui.IconName.XCircle).Heading("Something went wrong. Try again or contact support.")
        ];
}
Live result
Your account has been successfully created.
Your account is verified and ready to use.
Please verify your account to unlock all features.
Something went wrong. Try again or contact support.

Colors

CalloutColorsExample.cs
namespace Rask.Site.Features.UiDocs.Examples;

public sealed partial class CalloutColorsExample : Component
{
    private static readonly Ui.Color[] Colors =
    [
        Ui.Color.Zinc, Ui.Color.Red, Ui.Color.Orange, Ui.Color.Amber, Ui.Color.Yellow, Ui.Color.Lime,
        Ui.Color.Green, Ui.Color.Emerald, Ui.Color.Teal, Ui.Color.Cyan, Ui.Color.Sky, Ui.Color.Blue,
        Ui.Color.Indigo, Ui.Color.Violet, Ui.Color.Purple, Ui.Color.Fuchsia, Ui.Color.Pink, Ui.Color.Rose,
    ];

    protected override Component? Render() =>
        Div.Class("space-y-3")[
            Colors.Select(color => Ui.Callout.Key(color).Color(color).Icon(Ui.IconName.ExclamationCircle).Inline()
                .Heading("You've received a new message.")
                .Actions(Ui.Button["View message"]))
        ];
}
Live result
You've received a new message.
You've received a new message.
You've received a new message.
You've received a new message.
You've received a new message.
You've received a new message.
You've received a new message.
You've received a new message.
You've received a new message.
You've received a new message.
You've received a new message.
You've received a new message.
You've received a new message.
You've received a new message.
You've received a new message.
You've received a new message.
You've received a new message.
You've received a new message.

Examples

CalloutSpotlightsExample.cs
namespace Rask.Site.Features.UiDocs.Examples;

public sealed partial class CalloutSpotlightsExample : Component
{
    protected override Component? Render() =>
        Div.Class("space-y-3")[
            Ui.Callout.Icon(Ui.IconName.Sparkles).Color(Ui.Color.Purple)[
                Ui.CalloutHeading["Have a question?"],
                Ui.CalloutText[
                    "Try our new AI assistant, Jeffrey. Let him handle tasks and answer questions for you. ",
                    Ui.CalloutLink.Href("#")["Learn more"]
                ]
            ],
            Ui.Callout.Icon(Ui.IconName.ShieldCheck).Color(Ui.Color.Blue).Inline().Actions(Ui.Button["Upgrade to Pro ->"])[
                Ui.CalloutHeading["API access is restricted"],
                Ui.CalloutText["Get access to all of our premium features and benefits."]
            ],
            Ui.Callout.Icon(Ui.IconName.Banknotes).Color(Ui.Color.Lime).Inline().Actions(Ui.Button["Switch now ->"])[
                Ui.CalloutHeading["You could save $4,900/yr on annual billing."]
            ],
            Ui.Callout.Secondary.Icon(Ui.IconName.UserGroup).Actions([Ui.Button["Invite member"], Ui.Button.Ghost["Manage team"]])[
                Div.Class("flex items-start gap-2 @max-md:flex-col")[
                    Ui.CalloutHeading["Team collaboration"],
                    Ui.Badge.Sm["Available with Pro"]
                ],
                Ui.CalloutText["Share projects, manage permissions, and collaborate in real time with your team. Upgrade now to access these features."]
            ]
        ];
}
Live result
Have a question?
Try our new AI assistant, Jeffrey. Let him handle tasks and answer questions for you. Learn more
API access is restricted
Get access to all of our premium features and benefits.
You could save $4,900/yr on annual billing.
Team collaboration
Available with Pro
Share projects, manage permissions, and collaborate in real time with your team. Upgrade now to access these features.

Reference

Ui.Callout

flux:callout

A message set apart from the page: an icon, a heading, text and actions.

Step
Takes
What it does
.Variant(…)
Ui.CalloutVariant
Secondary
Success
Warning
Danger

Each is a step of its own too, unless an HTML tag has its name.

What it is saying. Secondary on a white surface when unset.
.Color(…)Ui.Color: one of Tailwind's hues, each a step too (.Blue)A hue of its own, which wins over Variant.
.Icon(…)Ui.IconName — one of 317 namesThe icon beside the content. None when unset.
.IconVariant(…)
Ui.IconVariant
Outline
Solid
Mini
Micro

Each is a step of its own too, unless an HTML tag has its name.

Which drawing of the icon. Mini when unset.
.CustomIcon(…)ComponentAn icon of your own in place of Icon.
.Heading(…)stringShorthand for a Ui.CalloutHeading as the first child.
.Text(…)stringShorthand for a Ui.CalloutText after the heading.
.Actions(…)ComponentWhat the reader can do about it: buttons or links.
.Inline()boolPuts the actions beside the text where there is room.
.Controls(…)ComponentWhat sits at the top right: a dismiss button. Dismissing is the page's.
.Role(…)stringThe callout's role. None when unset: a callout that appears because something happened says status or alert.

Ui.CalloutHeading

flux:callout.heading

The callout's title line.

Step
Takes
What it does
.Icon(…)Ui.IconName — one of 317 namesAn icon in the heading's line, instead of beside the whole callout.
.IconVariant(…)
Ui.IconVariant
Outline
Solid
Mini
Micro

Each is a step of its own too, unless an HTML tag has its name.

Which drawing of the icon. Mini when unset.
.CustomIcon(…)ComponentAn icon of your own in place of Icon.

Ui.CalloutText

flux:callout.text

The callout's body copy.

No steps of its own: what goes inside it is its content.

It is one HTML element, so Id, Class, Style, Data, Aria and the events are its steps too.

Ui.CalloutLink

flux:callout.link

A link inside the text, drawn in the callout's ink.

Step
Takes
What it does
.Href(…)a route, or a URL stringWhere it goes: a generated route to stay in the app, or a URL string to leave it.
.External()boolOpens it in a new tab, safely. Ignored for a route of the app.

It is one HTML element, so Id, Class, Style, Data, Aria and the events are its steps too.