Blazing Story — Story Implementation
Create a .stories.razor file for a Blazor component in the currently open Blazing Story project.
Investigation policy
The main goal of this policy is to free the developer from the hassle of approving "may I run this command?" prompts one by one. Many of those prompts come from operations that poke around outside the project — and most of the knowledge needed to write a story file is already available without them.
Implement the story relying primarily on:
- The guidance in this skill file
- Your own knowledge of C#, .NET, Blazor, and general web/UI development
- Other relevant skills available in this environment
- Already-configured MCP servers and tools
- Read-only exploration of the current project (
ls,Glob,Grep,Read)
Avoid operations that inspect the NuGet package cache folder, decompile Blazing Story DLLs, or otherwise probe the installed package contents. These are slow, require the developer's per-command approval, and disrupt the flow of work.
If implementation details that are not covered above become necessary, consult the published source code on GitHub at https://github.com/jsakamoto/BlazingStory instead of digging into the local NuGet cache or decompiling DLLs.
This policy may be relaxed only when strictly unavoidable.
Step 1: Identify the target component
From $ARGUMENTS or the user's message, determine the component name (e.g., Button, Rating).
Step 2: Locate the component file
Search the workspace for a .razor file matching the component name (e.g., Button.razor). Read it to understand:
- All
[Parameter]properties and their types - Any
RenderFragmentparameters (e.g.,ChildContent) - Enum types used by parameters
Step 3: Locate the stories project
Find the stories project directory — it is typically a separate project named *.Stories or containing a Stories/ subfolder. Look for existing .stories.razor files to confirm the correct location and the @using conventions used.
Step 4: Determine the story file path
Place the new file inside the Stories/ folder of the stories project, mirroring the category structure if one already exists. Name the file ComponentName.stories.razor.
Example: MyApp.Stories/Stories/Components/Button.stories.razor
Step 5: Write the story file
Use the following structure:
@attribute [Stories("Category/ComponentName")]
<Stories TComponent="ComponentName" Layout="typeof(Centered)">
<ArgType For="_ => _.EnumParam" Control="ControlType.Radio" />
<ArgType For="_ => _.ColorParam" Control="ControlType.Color" />
<Story Name="Default">
<Arguments>
<Arg For="_ => _.SomeParam" Value="someValue" />
</Arguments>
<Template>
<ComponentName @attributes="context.Args" />
</Template>
</Story>
</Stories>
@code {
private RenderFragment _content = @<text>Label</text>;
}
Rules
File naming
- Must end in
.stories.razorto enable the "Show code" feature in Blazing Story.
[Stories("...")] path
- Use
/as separator. The path becomes the sidebar navigation tree. - Mirror the folder path under
Stories/(e.g., file atStories/Components/Button.stories.razor→[Stories("Components/Button")]).
<Stories TComponent="...">
TComponentis the Blazor component type.Layoutis optional. Common choices:Centered— centers the component horizontally and vertically (good default for most UI components).FullScreen— fills the entire canvas (good for page-level components).MarginedFrame— adds a margin around the component.- Omit
Layoutentirely if you are unsure or if the project has no custom layouts.
<ArgType>
- Controls how a parameter appears in the Controls panel.
- Available
ControlTypevalues:ControlType.Default— auto-detected from the parameter type (no need to specify explicitly).ControlType.Radio— radio buttons; good for enums with 2–4 values.ControlType.Select— dropdown; good for enums with 5+ values.ControlType.Color— color picker; use forstringorColorparameters representing a color.
<Story Name="...">
- Each
<Story>represents one variant shown in the sidebar. - Always include a
"Default"story as the baseline. - Add further stories for meaningful parameter combinations (e.g.,
"Large","Disabled","With Icon").
<Arguments> and <Arg>
- Use
<Arg For="_ => _.ParamName" Value="..." />to set initial parameter values for a story. - For
RenderFragmentparameters, define the value in the@codeblock and reference it via<Arg>:<Arg For="_ => _.ChildContent" Value="_content" /> @code { private RenderFragment _content = @<text>Click me</text>; } - Do not hardcode
RenderFragmentcontent directly in the<Template>markup — this prevents runtime modification via the Controls panel.
<Template>
- Always add
@attributes="context.Args"to the component tag to wire up the Controls panel. - Pass only parameters that cannot be handled via
@attributes(e.g., event callbacks, non-parameter child content) directly in the markup.
Null-forgiving operator
- When the component type is nullable, use
_=>_!.PropertyNameinForlambdas:<ArgType For="_=>_!.Color" Control="ControlType.Color" />
@using directives
- Check whether the component namespace is already imported globally (e.g., via
_Imports.razor). Add@usingonly if needed.
Step 6: Verify
After writing the file, briefly summarize:
- The file path created
- The stories added and which parameter variants they cover
- Any
ArgTypecustomizations applied - Any assumptions made (e.g., chosen
Layout, omitted optional parameters)