UI/Components/Menu/PromptCard.razor

A UI component (Razor) for a prompt card in the game's menu. It displays a verb, label, optional glyph, optional cost in points, a progress fill bar, and adjusts appearance when disabled or when hold-progress is provided.

File Access
@namespace Sunless.Libraries.UI
@using Sandbox
@using Sandbox.UI
@inherits Panel
@attribute [StyleSheet]

<root class="@(IsDisabled ? "disabled" : "")">
	<div class="prompt-frame">
		<div class="prompt-vignette"></div>

		<div class="prompt-content">
			<div class="prompt-glyph">
				@if ( !string.IsNullOrEmpty( Glyph ) )
				{
					<div class="kbd">@Glyph</div>
				}
			</div>

			<div class="prompt-text">
				<div class="prompt-verb">@EffectiveVerb</div>
				<div class="prompt-label">@Prompt</div>
			</div>

			@if ( Cost > 0 )
			{
				<div class="prompt-cost">
					<div class="prompt-cost-value">@Cost</div>
					<div class="prompt-cost-unit">PTS</div>
				</div>
			}
		</div>

		<div class="prompt-rule">
			<div class="prompt-rule-fill" @ref="ruleFill"></div>
		</div>
	</div>
</root>

@code
{
	public string Verb { get; set; } = "Press";
	public string Prompt { get; set; } = "";
	public string Glyph { get; set; } = "E";
	public int Cost { get; set; }
	public bool IsDisabled { get; set; }
	public Func<float> HoldProgressFn { get; set; }

	Panel ruleFill { get; set; }

	string EffectiveVerb => IsDisabled && Cost > 0 ? "Not enough points" : Verb;

	public override void Tick()
	{
		if ( ruleFill is null ) return;

		var p = HoldProgressFn?.Invoke() ?? 0f;
		if ( p < 0f ) p = 0f;
		else if ( p > 1f ) p = 1f;

		ruleFill.Style.Opacity = p > 0f ? 1f : 0f;
		ruleFill.Style.Width = Length.Percent( p * 100f );
	}

	protected override int BuildHash() => HashCode.Combine( Verb, Prompt, Glyph, Cost, IsDisabled );
}