Add form value persistence across cache revalidation re-renders 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
5.3 KiB
Executable File
name, description
| name | description |
|---|---|
| scss | SCSS styling architecture in RSX including component scoping, BEM naming, responsive breakpoints, and variables. Use when writing SCSS files, styling components, working with responsive design, or troubleshooting CSS conflicts. |
RSX SCSS Architecture
Component-First Philosophy
Every styled element is a component with scoped SCSS. No CSS spaghetti - no generic classes like .page-header scattered across files.
Pattern vs Unique Decision:
- If you're copy-pasting markup, extract a component
- Reusable structures → shared component with slots
- One-off structures → page-specific component
Directory Rules
| Location | Purpose | Scoping |
|---|---|---|
rsx/app/ |
Feature components | Must wrap in component class |
rsx/theme/components/ |
Shared components | Must wrap in component class |
rsx/theme/ (outside components/) |
Primitives, variables, Bootstrap overrides | Global |
rsx/lib/ |
Non-visual utilities | No styles |
Component Scoping (Required)
SCSS in rsx/app/ and rsx/theme/components/ must wrap in a single component class:
// dashboard_index_action.scss
.Dashboard_Index_Action {
padding: 2rem;
.card {
margin-bottom: 1rem;
}
.stats-grid {
display: grid;
gap: 1rem;
}
}
- Wrapper class matches JS class or Blade
@rsx_id - Filename must match associated
.jsor.blade.phpfile - Components auto-render with
class="Component_Name"on root
BEM Child Classes
Child classes use exact PascalCase component name as prefix:
.DataGrid_Kanban {
&__loading { /* .DataGrid_Kanban__loading */ }
&__board { /* .DataGrid_Kanban__board */ }
&__column { /* .DataGrid_Kanban__column */ }
}
<!-- Correct -->
<div class="DataGrid_Kanban__loading">
<!-- WRONG - kebab-case doesn't match compiled CSS -->
<div class="datagrid-kanban__loading"> <!-- No styles! -->
No kebab-case in component BEM classes.
Variables
Define in rsx/theme/variables.scss. Check this file before writing new SCSS.
In bundles, variables.scss must be included before directory includes:
'include' => [
'rsx/theme/variables.scss', // First
'rsx/theme', // Then directories
'rsx/app/frontend',
],
Variables can be declared outside the wrapper for sharing:
// frontend_spa_layout.scss
$sidebar-width: 215px;
$header-height: 57px;
.Frontend_Spa_Layout {
.sidebar { width: $sidebar-width; }
}
Variables-Only Files
Files with only $var: value; declarations (no selectors) are valid without wrapper:
// _variables.scss
$primary-color: #0d6efd;
$border-radius: 0.375rem;
Supplemental SCSS Files
Split large SCSS by breakpoint or feature:
frontend_spa_layout.scss # Primary (required)
frontend_spa_layout_mobile.scss # Supplemental
frontend_spa_layout_print.scss # Supplemental
Supplemental files use the same wrapper class as primary:
// frontend_spa_layout_mobile.scss
.Frontend_Spa_Layout {
@media (max-width: 768px) {
.sidebar { width: 100%; }
}
}
Responsive Breakpoints
RSX replaces Bootstrap breakpoints. Bootstrap's .col-md-6, .d-lg-none do NOT work.
Tier 1 (Simple)
| Name | Range |
|---|---|
mobile |
0-1023px |
desktop |
1024px+ |
Tier 2 (Granular)
| Name | Range |
|---|---|
phone |
0-799px |
tablet |
800-1023px |
desktop-sm |
1024-1199px |
desktop-md |
1200-1639px |
desktop-lg |
1640-2199px |
desktop-xl |
2200px+ |
SCSS Mixins
.Component {
padding: 2rem;
@include mobile {
padding: 1rem;
}
@include phone {
padding: 0.5rem;
}
@include desktop-xl {
max-width: 1800px;
}
}
Utility Classes
<div class="col-mobile-12 col-desktop-6">...</div>
<div class="d-mobile-none">Hidden on mobile</div>
<div class="mobile-only">Only visible on mobile</div>
<div class="hide-tablet">Hidden on tablet only</div>
JavaScript Detection
if (Responsive.is_mobile()) {
// Mobile behavior
}
if (Responsive.is_desktop_xl()) {
// Extra large desktop
}
Slot-Based Composition
Use slots to separate structure from content:
<Define:Datagrid_Card>
<div class="card">
<div class="card-header"><%= content('toolbar') %></div>
<div class="card-body"><%= content('body') %></div>
</div>
</Define:Datagrid_Card>
<!-- Usage -->
<Datagrid_Card>
<Slot:toolbar><button>Add</button></Slot:toolbar>
<Slot:body><My_Datagrid /></Slot:body>
</Datagrid_Card>
Component owns layout/styling; pages provide content via slots.
What Remains Shared (Unscoped)
Only primitives should be unscoped:
- Buttons (
.btn-primary,.btn-secondary) - Spacing utilities (
.mb-3,.p-2) - Typography (
.text-muted,.fw-bold) - Bootstrap overrides
Everything else → component-scoped SCSS.
No Exemptions
There are no exemptions to scoping rules for files in rsx/app/ or rsx/theme/components/. If a file can't be associated with a component, it likely belongs in:
rsx/theme/base/for global utilities- A dedicated partial imported via
@use
More Information
Details: php artisan rsx:man scss, php artisan rsx:man responsive