#razor
51 items (51 fixes)
@ref on a private field compiles with only a CS0649 warning: the ref stays null at runtime. Bind to a property instead.
A #if DEBUG guard inside a .razor component is always false in every configuration, so it strips nothing, and the razor source plus any sibling .scss ship into the uploaded package as readable text regardless. Build anything that must be absent from a release as a plain .cs class.
A pure C# Panel subclass has no settable Style.Rotate shortcut reachable from code the way razor markup can write transform:rotate(Xdeg). Rotate it by building a PanelTransform, calling AddRotation, and assigning it to Style.Transform each frame the angle changes.
A flex: 1 spacer takes all remaining height in a column, so every sibling after it starts at the container's bottom edge. Under overflow: hidden those trailing controls are laid out but never drawn: hover and onclick stay intact while zero pixels reach the screen. Put a spacer between two blocks that both fit, or bottom-anchor a group with margin-top: auto.
Compiling an s&box game assembly outside the editor needs the exact csproj shape the editor generates, and even a perfectly green offline build cannot surface whitelist violations. The SB1000 analyzer runs only in the editor compile pass, so code can build with 0 errors and 0 warnings offline and still be rejected in-editor. Build the editor-generated Code/<project>.csproj directly and confirm against the editor compile_status, never the offline build alone.
In a .razor file, `word@Expr.Member` (e.g. `P@Score.Value`) is parsed as a literal string, not an expression. Razor's email-address heuristic sees the `foo@bar.baz` shape and treats the whole thing as text. The element renders the raw source, with no compile error and no warning. Put the literal inside the expression instead: `@($"P{Score.Value}")`.
A razor background-image referencing a loose PNG/JPG renders in-editor (loose Assets are readable off the mounted filesystem) but goes blank in the published package, because loose non-compiled images are not auto-shipped. Add the disk glob to the sbproj Resources list; the wildcard matches the loose disk path, not the normalized asset path.
In s&box razor UI the declared width/height of a panel is the OUTER number: padding and borders sit inside it, not added on top. The default already behaves like box-sizing: border-box, with no such declaration anywhere. Author every width/height as the outer number the mockup shows; adding padding/border by hand under-sizes every box by exactly its own padding.
An absolutely positioned child with a percent size resolves against the nearest ancestor that is a positioning context, not against the track you can see. A track div does not become a positioning context by carrying flex, padding, a background, or a fixed size. It needs an explicit position declaration. Without one, height: 100% resolves against the panel root, so a stat-bar fill sized width N percent by height 100 percent floods the whole panel and buries the cards under it. Set position: relative on the track, then sweep every sibling with the same pattern, because small absolute children hide the same defect by landing in the wrong corner instead of flooding.
A ScreenPanel lays out against a logical canvas that is fixed in height at 1080 and takes its width from the window aspect ratio. At a 1920x1080 window the canvas measures 2060.7 x 1080, not 1920 x 1080. Vertical and left-anchored values from a 1920-wide mockup transfer 1:1, but anything hard-centred with arithmetic against an assumed 1920 width sits off-centre. Centre with flex, never with math.
A Panel with overflow: scroll and real overflow content answers WantsDrag = true, and FindDragTarget walks up from the pointer to the first ancestor that claims the drag. That ancestor steals every press-and-drag from any slider, scrub bar, or knob inside it. Set CanDragScroll = false on the scroll container in OnTreeBuilt.
A text element's line box measures max(declared line-height, the font's own natural box), so a column of rows built to a browser mockup's arithmetic runs long and overflows its fixed parent. Padding, borders, margins and gaps all measure exactly as declared: only the line box inflates. Size rows off the font size, not off an assumed 1.5×, and verify on a scale-1 capture.
SUPERSEDED: the font-size-declaration theory below was owner-settled (26.07.22) to be a CAPTURE-PATH artifact, not a live-render bug, and the mechanism was later traced to the root panel's fractional scale. Never strip font-size or letter-spacing from a shipping stylesheet to 'fix' captures. See camera-screenshot-cannot-verify-fonts.
Trailing children of a tall absolutely-positioned flex column silently vanish (no overflow, no compression) because Yoga's auto-height under-measures the content. Fix: give the column an explicit height.
An absolutely positioned child clips to the nearest ancestor that is a positioning context, not to its visual parent. A frame with flex, a fixed size, and a border radius but no position declaration is not a positioning context, so the absolute child skips past it and renders full-bleed against the screen root. A sibling screen using the same pattern renders correctly only because its own box already was the root, which makes the pattern look safe to copy. For one rectangle, drop the absolute child and paint the texture on the frame's own background.
Glyph-block corruption in an MCP camera_screenshot is a capture-path artifact, not a live-render bug. The same UI renders text perfectly on the real screen. You cannot screenshot your way out of it: the requested width/height does not change the UI render scale, and sub-native requests crop the top-left. Verify geometry from a capture, never text fidelity; font-face and legibility are owner-eyeball checks.
Referencing an scss variable a sheet never defines passes both dotnet build and the in-editor compile_status clean, but at runtime the style parser logs a 'malformed rule' warning and the panel using that sheet can stop rendering entirely. Variables don't cross sheets, so copying a rule between sheets silently drops its variables.
global using Sandbox + your razor namespace in Assembly.cs: without it, panels and game types don't resolve across the assembly.
border-style: solid is a parse error in s&box scss. The invalid property aborts the whole stylesheet, collapsing the panel to zero size -- invisible, not just unbordered.
The inset keyword on box-shadow is effectively ignored in s&box Razor panels: an inner vignette renders as an outer halo, and a full-screen inset vignette renders nothing at all. Build inner glows and vignettes from linear-gradient bands instead.
protected override int BuildHash() is a PanelComponent member; a logic-only Component has no such method, so the override fails headless with CS0115. Easy to hit when you split a UI feature into a logic Component beside its PanelComponent view and copy the 'keep the tree stable' BuildHash idiom onto the logic component too.
No native drag helper exists for PanelComponent sliders. Use the engine's SliderControl pattern: MousePanelEvent.LocalPosition over track width, with pointer-events routing.
One ScreenPanel host, static UIState for modals, self-closing panels, toast stack: BuildHash every flag the markup reads.
A child-combinator rule targeting the universal selector (`.parent > *`) is silently dead in s&box razor SCSS: no error, no warning, the rule simply never applies.
CSS @keyframes plus the animation: shorthand are supported in s&box razor SCSS, so a spinner or looping effect is pure CSS -- do not drive it from a per-frame BuildHash re-render.
Showing a loading overlay and running a synchronous main-thread job in the same handler never paints the overlay -- the blocking work runs before the render pass. Show the overlay, count down a couple of frames, then run the blocker in OnUpdate.
Razor HUD emoji and dashes die under Get-Content/Set-Content: edit with byte-safe UTF-8 APIs or a real editor.
SUPERSEDED: the text-run-count theory below was owner-settled (26.07.22) to be a CAPTURE-PATH artifact, not a live-render bug, and the mechanism was later traced to the root panel's fractional scale. Do not trim text runs to 'fix' glyph blocks in a capture.
dotnet build reports 0 errors on .razor files the in-editor compiler rejects: the headless build doesn't surface the Razor errors the live editor's Roslyn compiler flags.
A dropdown paints cleanly over the block below it, and that block still eats every press. Paint order and hit order come from two different sums: render depth accumulates z-index down the tree, but hit-testing ranks siblings by SiblingIndex + ZIndex within each parent. An absolute menu that overhangs a later sibling looks perfect and is unclickable. Fix the ancestors, not the popup.
BuildHash() is the only re-render trigger: hash everything the markup reads, including collection contents and flags.
A newly created .razor.scss file is not picked up by a running editor session: the panel component works but is unstyled until the next restart.
OnAfterTreeRender(bool) is a Panel hook: on a PanelComponent it fails with CS0115; use parameterless OnTreeBuilt() or OnTreeFirstBuilt().
A loading screen mounted right before a synchronous multi-second call never paints: one consumed tick isn't enough; gate the block on a frame counter (~6 frames) so the Razor pipeline finishes mount → style → layout → paint.
Thin flex rows with a gap inside a Razor RenderFragment expression under-measure their height and pile on top of each other. The same markup renders fine in the component's main root.
Razor component tag resolution does not consult global using directives: a library component renders as an inert HTML element while its class resolves fine in code-behind.
s&box loads Steam avatars through an avatar:<steamid64> texture-URL scheme usable from both SCSS background-image and C# Texture.Load. It returns a transparent placeholder immediately and swaps in the real avatar with no panel re-render.
SCSS background-image only resolves asset paths. Runtime Texture objects must be assigned via Panel.Style.BackgroundImage in OnTreeBuilt.
Nesting @{ } inside an already-open Razor code block (like @if or @for) causes RZ1010: you're already in C#, so drop the @.
ScenePanel's Camera property is GET-ONLY. Assigning a new SceneCamera fails with CS0200. Configure the existing camera in place and build the preview world manually.
ScreenPanel.ZIndex defaults to 100 (not 0), so any ScreenPanel that never sets a tier collides with the tier most projects author their modals at, and two roots with equal ZIndex have no defined paint order at all. Cross-root compositing is a stable OrderBy over an unordered HashSet, so tied roots keep an enumeration order that matches creation on a fresh boot but re-rolls on any enable/disable interleave or editor hotload. A full-screen surface can paint a perfectly healthy tree and still be invisible under a tied root.
ScreenPanel.ZIndex orders paint only: pointer input is NOT routed by cross-root stacking, so a lower-ZIndex root keeps swallowing clicks even when a higher-ZIndex modal draws over it.
A structural .razor change can throw a hotload exception that deregisters the project's entire toolset while compile_status still reports Success. Restart the editor to recover.
Use TextEntry with onsubmit and OnTextEdited: standard Blazor input bindings compile but are not how the engine UI works.
An untyped or expression-bodied lambda on TextEntry.OnTextEdited fails with CS8917 or CS0029. Use an explicit param type plus a block body.
Razor classes get a RootNamespace/folder-derived namespace: declare @namespace and global using or C# can't find your panels.
s&box Razor panels have three distinct 'text is there but not on screen' failure modes (long-line clipping, narrow-segment overflow, and inline expression resolution), each with a different structural fix.
transition-delay, :intro and :outro all parse in the engine's razor-scss pipeline, tested isolated on engine build 26.07.22. An earlier caution that treated these selectors as unsupported can relax. A novel selector is worth one isolated test before you write it off, because an unparsed selector aborts the whole stylesheet to a 0x0 render.
An undefined SCSS variable in a .razor.scss fails at runtime with only a console warning (no compile error, no toast) and the affected panels can render fully invisible. A trailing // comment on a value line fails the same way.
Literal spaces adjacent to a tag or @-expression boundary vanish in Razor markup: use a single interpolated string or CSS margin instead.
A button that never responds, with a clean console and a correct onclick handler, can be a BuildHash rebuild eating the click. If you write a focus-cursor field from onmouseover and that field participates in the panel's BuildHash, the mouse arriving over a row rebuilds the panel tree on the spot. The rebuild destroys and recreates the element under the cursor, and a press and release that straddles the rebuild is swallowed by the engine, so no onclick fires. Focus is a keyboard and gamepad concept, so never write it from a hover handler. Give the mouse its own affordance from CSS :hover, which needs no rebuild, and keep the keyboard focus index as a separate field if the panel needs both.