Files
rspade_system/docs/skills/scss/SKILL.md
root 1b46c5270c Add skills documentation and misc updates
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>
2025-12-29 04:38:06 +00:00

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 .js or .blade.php file
  • 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