Document SCSS component-first architecture philosophy
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -42,6 +42,66 @@ DESCRIPTION
|
||||
Key principle: The SCSS filename must match the filename of its
|
||||
associated .js (action/component) or .blade.php file.
|
||||
|
||||
COMPONENT-FIRST PHILOSOPHY
|
||||
Every styled element should be a component. If an element needs custom
|
||||
styles, it deserves a name, a jqhtml definition, and scoped SCSS. This
|
||||
eliminates CSS spaghetti - generic classes like .page-header, .filter-bar,
|
||||
.action-buttons scattered across files, overriding each other unpredictably.
|
||||
|
||||
Pattern Recognition:
|
||||
When building a page, ask: "Is this structure unique, or a pattern?"
|
||||
|
||||
Pattern (shared structure):
|
||||
A datagrid page with toolbar, tabs, filters, and search appears
|
||||
on 8 different pages. Create Datagrid_Card once with slots, use
|
||||
it everywhere. Changes propagate automatically.
|
||||
|
||||
Unique (one-off structure):
|
||||
A project dashboard with custom widgets specific to that page.
|
||||
Create Project_Dashboard for that page alone.
|
||||
|
||||
Decision heuristic: If you're about to copy-paste structural markup,
|
||||
stop and extract a component.
|
||||
|
||||
Slot-Based Composition:
|
||||
Use slots to separate structure from content. The component owns
|
||||
layout and styling; pages provide the variable parts via slots.
|
||||
|
||||
// Datagrid_Card owns the structure
|
||||
<Define:Datagrid_Card>
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<%= content('toolbar') %>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<%= content('body') %>
|
||||
</div>
|
||||
</div>
|
||||
</Define:Datagrid_Card>
|
||||
|
||||
// Page provides content via slots
|
||||
<Datagrid_Card>
|
||||
<Slot:toolbar>
|
||||
<button>Add New</button>
|
||||
<Search_Input />
|
||||
</Slot:toolbar>
|
||||
<Slot:body>
|
||||
<Contacts_Datagrid />
|
||||
</Slot:body>
|
||||
</Datagrid_Card>
|
||||
|
||||
This keeps pages declarative and components reusable.
|
||||
|
||||
What Remains Shared:
|
||||
Only primitives should be shared/unscoped styles:
|
||||
- Buttons (.btn-primary, .btn-secondary)
|
||||
- Spacing utilities (.mb-3, .p-2)
|
||||
- Typography (.text-muted, .fw-bold)
|
||||
- Bootstrap overrides
|
||||
|
||||
Everything else - page layouts, card variations, custom UI patterns -
|
||||
should be component-scoped SCSS.
|
||||
|
||||
SCOPING RULES
|
||||
|
||||
Files in rsx/app/**/*.scss and rsx/theme/components/**/*.scss:
|
||||
|
||||
@@ -423,6 +423,41 @@ SUBLAYOUTS
|
||||
|
||||
To access intermediate layouts, use DOM traversal or layout hooks.
|
||||
|
||||
STYLING
|
||||
SPA actions and layouts are jqhtml components, so they automatically
|
||||
receive their class name on the root DOM element. This enables scoped
|
||||
SCSS styling.
|
||||
|
||||
Automatic Class Assignment:
|
||||
<Define:Contacts_Index_Action> renders as:
|
||||
<div class="Contacts_Index_Action Component Spa_Action ...">
|
||||
|
||||
<Define:Frontend_Layout> renders as:
|
||||
<div class="Frontend_Layout Component Spa_Layout ...">
|
||||
|
||||
SCSS File Pairing:
|
||||
Each action/layout can have a companion SCSS file with all styles
|
||||
scoped to the component class:
|
||||
|
||||
// rsx/app/frontend/contacts/contacts_index_action.scss
|
||||
.Contacts_Index_Action {
|
||||
.filters { margin-bottom: 1rem; }
|
||||
.contact-list { ... }
|
||||
}
|
||||
|
||||
// rsx/app/frontend/frontend_layout.scss
|
||||
.Frontend_Layout {
|
||||
.app-sidebar { width: 250px; }
|
||||
.app-content { margin-left: 250px; }
|
||||
}
|
||||
|
||||
Enforcement:
|
||||
SCSS files in rsx/app/ must wrap all rules in a single class
|
||||
matching the action/layout name. This is enforced by the manifest
|
||||
scanner and prevents CSS conflicts between pages.
|
||||
|
||||
See scss man page for complete scoping rules and philosophy.
|
||||
|
||||
URL GENERATION
|
||||
CRITICAL: All URLs must use Rsx::Route() or Rsx.Route(). Raw URLs like
|
||||
"/contacts" will produce errors.
|
||||
@@ -833,3 +868,4 @@ SEE ALSO
|
||||
routing(3) - URL generation and route patterns
|
||||
modals(3) - Modal dialogs in SPA context
|
||||
ajax_error_handling(3) - Error handling patterns
|
||||
scss(3) - SCSS scoping conventions and component-first philosophy
|
||||
|
||||
@@ -430,19 +430,21 @@ The process involves creating Action classes with @route decorators and converti
|
||||
**NO inline styles, scripts, or event handlers** - Use companion `.scss` and `.js` files.
|
||||
**jqhtml components** work fully in Blade (no slots).
|
||||
|
||||
### SCSS Pairing
|
||||
### SCSS Component-First Architecture
|
||||
|
||||
For page/component-specific styles, wrap all rules in a class matching the component name:
|
||||
**Philosophy**: Every styled element is a component. If it needs custom styles, give it a name, a jqhtml definition, and scoped SCSS. This eliminates CSS spaghetti - generic classes overriding each other unpredictably across files.
|
||||
|
||||
```scss
|
||||
/* my_component.scss - Scoped to component */
|
||||
.My_Component { /* Matches component class or @rsx_id */
|
||||
.content { padding: 20px; }
|
||||
/* All component-specific rules here */
|
||||
}
|
||||
```
|
||||
**Recognition**: When building a page, ask: "Is this structure unique, or a pattern?" A datagrid page with toolbar, tabs, filters, and search is a *pattern* - create `Datagrid_Card` once with slots, use it everywhere. A one-off project dashboard is *unique* - create `Project_Dashboard` for that page. If you're about to copy-paste structural markup, stop and extract a component.
|
||||
|
||||
**Convention**: Each Blade view, jqhtml action, or component automatically gets its name as a class on its root element, enabling scoped styling.
|
||||
**Composition**: Use slots to separate structure from content. The component owns layout and styling; pages provide the variable parts via slots. This keeps pages declarative and components reusable.
|
||||
|
||||
**Enforcement**: SCSS in `rsx/app/` and `rsx/theme/components/` must wrap in a single component class matching the jqhtml/blade file. This works because all jqhtml components, SPA actions/layouts, and Blade views with `@rsx_id` automatically render with `class="Component_Name"` on their root element. `rsx/lib/` is for non-visual plumbing (validators, utilities). `rsx/theme/` (outside components/) holds primitives, variables, Bootstrap overrides.
|
||||
|
||||
**Variables**: Define shared values (colors, spacing, border-radius) in `rsx/theme/variables.scss` or similar. These must be explicitly included before directory includes in bundle definitions. Component-local variables can be defined within the scoped rule.
|
||||
|
||||
**Supplemental files**: Multiple SCSS files can target the same component (e.g., breakpoint-specific styles) if a primary file with matching filename exists.
|
||||
|
||||
Details: `php artisan rsx:man scss`
|
||||
|
||||
### JavaScript for Blade Pages
|
||||
|
||||
|
||||
Reference in New Issue
Block a user