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
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"]
]
];
}Icon inside heading
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."]
];
}Custom icon
Any SVG of your own in place of a Heroicon.
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."]
];
}With actions
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."]
];
}Inline actions
Inline puts the actions beside the text, where there is room.
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."]
]
];
}Dismissible
The callout places the control; what pressing it does is the page's — here, two fields.
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);
}Variants
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.")
];
}Colors
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"]))
];
}Examples
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."]
]
];
}Reference
Ui.Callout
A message set apart from the page: an icon, a heading, text and actions.
Step | Takes | What it does |
|---|---|---|
.Variant(…) | Ui.CalloutVariantSecondary 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 names | The icon beside the content. None when unset. |
.IconVariant(…) | Ui.IconVariantOutline 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(…) | Component | An icon of your own in place of Icon. |
.Heading(…) | string | Shorthand for a Ui.CalloutHeading as the first child. |
.Text(…) | string | Shorthand for a Ui.CalloutText after the heading. |
.Actions(…) | Component | What the reader can do about it: buttons or links. |
.Inline() | bool | Puts the actions beside the text where there is room. |
.Controls(…) | Component | What sits at the top right: a dismiss button. Dismissing is the page's. |
.Role(…) | string | The callout's role. None when unset: a callout that appears because something happened says status or alert. |
Ui.CalloutHeading
The callout's title line.
Step | Takes | What it does |
|---|---|---|
.Icon(…) | Ui.IconName — one of 317 names | An icon in the heading's line, instead of beside the whole callout. |
.IconVariant(…) | Ui.IconVariantOutline 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(…) | Component | An icon of your own in place of Icon. |
Ui.CalloutText
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
A link inside the text, drawn in the callout's ink.
Step | Takes | What it does |
|---|---|---|
.Href(…) | a route, or a URL string | Where it goes: a generated route to stay in the app, or a URL string to leave it. |
.External() | bool | Opens 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.