| allowed-tools | Glob Grep Read Write |
| compatibility | Designed for Blazing Story projects (a Blazor-based Storybook clone for .NET). Requires a .Stories project referencing BlazingStory NuGet packages. |
| description | Implement a Blazing Story story file (.stories.razor) for a Blazor UI component. Use when the user says "create a story for component X", "add stories for X", or similar requests in a Blazing Story (.NET / Blazor / Storybook) project. |
| license | Unlicense |
| metadata | {"author":"jsakamoto","github-path":"skills/blazing-story-story","github-ref":"refs/tags/v1.0.2","github-repo":"https://github.com/BlazingStory/agent-skills","github-tree-sha":"36d13a0943547a646a3d91de27c9d8870b951cbd"} |
| name | blazing-story-story |
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
RenderFragment parameters (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.razor to 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 at Stories/Components/Button.stories.razor → [Stories("Components/Button")]).
<Stories TComponent="...">
TComponent is the Blazor component type.
Layout is 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
Layout entirely if you are unsure or if the project has no custom layouts.
<ArgType>
- Controls how a parameter appears in the Controls panel.
- Available
ControlType values:
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 for string or Color parameters 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>
<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
@using directives
- Check whether the component namespace is already imported globally (e.g., via
_Imports.razor). Add @using only 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
ArgType customizations applied
- Any assumptions made (e.g., chosen
Layout, omitted optional parameters)