diff --git a/app/RSpade/Commands/Rsx/Man_Command.php b/app/RSpade/Commands/Rsx/Man_Command.php index fddd27b35..c126f9a6e 100755 --- a/app/RSpade/Commands/Rsx/Man_Command.php +++ b/app/RSpade/Commands/Rsx/Man_Command.php @@ -30,14 +30,19 @@ class Man_Command extends Command /** * Create a new command instance. * + * Directories are listed in priority order - first match wins for same-named files. + * Project-specific docs in rsx/resource/man override framework docs in app/RSpade/man. + * * @return void */ public function __construct() { parent::__construct(); + // Priority order: project-specific > user docs > framework docs $this->docs_dirs = [ - base_path('docs/man'), - base_path('app/RSpade/man'), + base_path('../rsx/resource/man'), // Project-specific (highest priority) + base_path('docs/man'), // User docs + base_path('app/RSpade/man'), // Framework docs (lowest priority) ]; } @@ -100,15 +105,7 @@ class Man_Command extends Command */ protected function list_all_documentation() { - $files = []; - foreach ($this->docs_dirs as $dir) { - if (is_dir($dir)) { - $dir_files = glob($dir . '/*.txt'); - if ($dir_files) { - $files = array_merge($files, $dir_files); - } - } - } + $files = $this->get_all_files_deduplicated(); if (empty($files)) { $this->warn('No documentation files found in:'); @@ -175,6 +172,32 @@ class Man_Command extends Command return 0; } + /** + * Get all documentation files, deduplicated by filename. + * Files from earlier directories in docs_dirs take precedence. + * + * @return array + */ + protected function get_all_files_deduplicated(): array + { + $files_by_name = []; + foreach ($this->docs_dirs as $dir) { + if (is_dir($dir)) { + $dir_files = glob($dir . '/*.txt'); + if ($dir_files) { + foreach ($dir_files as $file) { + $name = basename($file, '.txt'); + // First occurrence wins (higher priority directory) + if (!isset($files_by_name[$name])) { + $files_by_name[$name] = $file; + } + } + } + } + } + return array_values($files_by_name); + } + /** * Find documentation files matching the given term. * @@ -183,15 +206,7 @@ class Man_Command extends Command */ protected function find_matching_files(string $term): array { - $files = []; - foreach ($this->docs_dirs as $dir) { - if (is_dir($dir)) { - $dir_files = glob($dir . '/*.txt'); - if ($dir_files) { - $files = array_merge($files, $dir_files); - } - } - } + $files = $this->get_all_files_deduplicated(); $term_lower = strtolower($term); $matches = []; @@ -373,25 +388,14 @@ class Man_Command extends Command */ protected function get_all_topic_names(): array { - $files = []; - foreach ($this->docs_dirs as $dir) { - if (is_dir($dir)) { - $dir_files = glob($dir . '/*.txt'); - if ($dir_files) { - $files = array_merge($files, $dir_files); - } - } - } + $files = $this->get_all_files_deduplicated(); $topics = []; foreach ($files as $file) { $topics[] = basename($file, '.txt'); } - // Remove duplicates and sort - $topics = array_unique($topics); sort($topics); - return $topics; } diff --git a/app/RSpade/Core/Js/Responsive.js b/app/RSpade/Core/Js/Responsive.js new file mode 100755 index 000000000..6846370f7 --- /dev/null +++ b/app/RSpade/Core/Js/Responsive.js @@ -0,0 +1,106 @@ +/** + * Responsive - JavaScript breakpoint detection for RSX two-tier responsive system + * + * Provides runtime detection of current viewport against CSS breakpoint values. + * Values are read from CSS custom properties defined in rsx/theme/responsive.scss. + * + * Two-tier system: + * Tier 1 (Semantic): is_mobile() / is_desktop() - broad categories + * Tier 2 (Granular): is_phone() / is_tablet() / is_desktop_sm() / is_desktop_md() / is_desktop_lg() + * + * Usage: + * if (Responsive.is_mobile()) { ... } + * if (Responsive.is_desktop_md()) { ... } + */ +class Responsive { + static _cache = {}; + + /** + * Get breakpoint value from CSS custom property as integer + * @param {string} name - Breakpoint name (e.g., 'desktop', 'tablet', 'desktop-md') + * @returns {number} Breakpoint value in pixels + * @private + */ + static _get_breakpoint(name) { + if (this._cache[name] !== undefined) { + return this._cache[name]; + } + + const styles = getComputedStyle(document.documentElement); + const value = styles.getPropertyValue(`--bp-${name}-min`).trim(); + const parsed = parseInt(value, 10); + + this._cache[name] = parsed; + return parsed; + } + + /** + * Get current viewport width + * @returns {number} + * @private + */ + static _viewport() { + return window.innerWidth; + } + + /** + * Tier 1: Check if viewport is mobile (0 - 1023px) + * Includes phone and tablet sizes + * @returns {boolean} + */ + static is_mobile() { + return !this.is_desktop(); + } + + /** + * Tier 1: Check if viewport is desktop (1024px+) + * Includes desktop-sm, desktop-md, and desktop-lg sizes + * @returns {boolean} + */ + static is_desktop() { + return this._viewport() >= this._get_breakpoint('desktop'); + } + + /** + * Tier 2: Check if viewport is phone (0 - 799px) + * @returns {boolean} + */ + static is_phone() { + return this._viewport() < this._get_breakpoint('tablet'); + } + + /** + * Tier 2: Check if viewport is tablet (800 - 1023px) + * @returns {boolean} + */ + static is_tablet() { + const vp = this._viewport(); + return vp >= this._get_breakpoint('tablet') && vp < this._get_breakpoint('desktop'); + } + + /** + * Tier 2: Check if viewport is desktop-sm (1024 - 1699px) + * @returns {boolean} + */ + static is_desktop_sm() { + const vp = this._viewport(); + return vp >= this._get_breakpoint('desktop-sm') && vp < this._get_breakpoint('desktop-md'); + } + + /** + * Tier 2: Check if viewport is desktop-md (1700 - 2199px) + * @returns {boolean} + */ + static is_desktop_md() { + const vp = this._viewport(); + return vp >= this._get_breakpoint('desktop-md') && vp < this._get_breakpoint('desktop-lg'); + } + + /** + * Tier 2: Check if viewport is desktop-lg (2200px+) + * @returns {boolean} + */ + static is_desktop_lg() { + return this._viewport() >= this._get_breakpoint('desktop-lg'); + } +} diff --git a/app/RSpade/man/man.txt b/app/RSpade/man/man.txt new file mode 100755 index 000000000..839270bff --- /dev/null +++ b/app/RSpade/man/man.txt @@ -0,0 +1,102 @@ +NAME + man - RSX manual page system + +SYNOPSIS + php artisan rsx:man # List all available topics + php artisan rsx:man # Display documentation for topic + php artisan rsx:man responsive # Example: show responsive docs + +DESCRIPTION + The man page system provides detailed technical documentation for RSX + framework features and project-specific implementations. These documents + serve as immediate reference when detailed understanding of any subsystem + is necessary. + + Man pages are plain text files following Unix man page conventions: + terse, complete, expert-level documentation with code examples. + +DIRECTORY STRUCTURE + Documentation is loaded from multiple directories in priority order: + + /rsx/resource/man/ Project-specific docs (highest priority) + /system/docs/man/ User docs + /system/app/RSpade/man/ Framework docs (lowest priority) + + When the same filename exists in multiple directories, the higher + priority version is used. This allows projects to override framework + documentation when customizations require different instructions. + +PROJECT-SPECIFIC DOCUMENTATION + The /rsx/resource/man/ directory contains documentation specific to the + current project. Create man pages here for: + + - Custom features built on top of the framework + - Project-specific configuration or patterns + - Implementation details unique to this application + - Overrides of framework behavior + + To override a framework man page, create a file with the same name in + /rsx/resource/man/. The project version will be displayed instead of + the framework version. + +FILE FORMAT + Man pages use plain text with these conventions: + + - Section headers in ALL CAPS on their own line + - Code examples indented with 4 spaces + - No markdown, no Unicode, no box-drawing characters + - ASCII only for maximum compatibility + + Standard sections: + + NAME Feature name and one-line description + SYNOPSIS Quick usage example + DESCRIPTION Overview and purpose + USAGE Detailed instructions + EXAMPLES Code samples + SEE ALSO Related documentation + +EXAMPLES + List all available documentation: + + php artisan rsx:man + + View documentation for a specific topic: + + php artisan rsx:man jqhtml + php artisan rsx:man bundle_api + php artisan rsx:man responsive + + Partial matching works: + + php artisan rsx:man bundle # Matches bundle_api + php artisan rsx:man spa # Matches spa + +CREATING MAN PAGES + Framework man pages go in /system/app/RSpade/man/*.txt + Project man pages go in /rsx/resource/man/*.txt + + See /rsx/resource/man/CLAUDE.md for detailed writing guidelines. + + Template: + + NAME + feature_name - brief description + + SYNOPSIS + Most common usage example + + DESCRIPTION + What the feature does, why it exists. + + USAGE + Step-by-step instructions. + + EXAMPLES + Real code examples. + + SEE ALSO + Related topics + +SEE ALSO + jqhtml, bundle_api, spa, coding_standards diff --git a/app/RSpade/upstream_changes/CLAUDE.md b/app/RSpade/upstream_changes/CLAUDE.md new file mode 100755 index 000000000..be333b908 --- /dev/null +++ b/app/RSpade/upstream_changes/CLAUDE.md @@ -0,0 +1,80 @@ +# Upstream Changes Log + +## Purpose + +This directory contains migration guides for significant framework changes that affect existing RSX applications. When framework updates introduce breaking changes or new patterns that downstream projects should adopt, a detailed migration document is created here. + +These documents serve as technical references for updating existing applications to match the current framework patterns. + +## When to Create a Document + +Create a migration guide when: +- Breaking changes affect existing application code +- New patterns replace old patterns (and old code should be updated) +- Configuration or directory structure changes +- New required dependencies or bundle includes + +Do NOT create documents for: +- Internal framework refactoring that doesn't affect applications +- New features that don't require changes to existing code +- Bug fixes + +## File Naming Convention + +``` +{feature}_{month}_{day}.txt +``` + +Examples: +- `responsive_12_18.txt` - Responsive system changes on December 18 +- `bundle_api_03_15.txt` - Bundle API changes on March 15 +- `auth_session_07_22.txt` - Authentication/session changes on July 22 + +Use lowercase with underscores. Date is MM_DD format (no year - files are naturally ordered by creation). + +## Document Structure + +Each migration guide should include: + +``` +FEATURE NAME - MIGRATION GUIDE +Date: YYYY-MM-DD + +SUMMARY + One paragraph describing what changed and why. + +AFFECTED FILES + List of file paths that need modification in downstream projects. + +CHANGES REQUIRED + + 1. First Change Category + - What to do + - Code examples (before/after) + + 2. Second Change Category + - What to do + - Code examples + +CONFIGURATION + Any new configuration values, bundle includes, or settings. + +VERIFICATION + How to verify the migration was successful. + +REFERENCE + Links to man pages or other documentation. +``` + +## Level of Detail + +Migration guides should be: +- **Complete**: Every change needed to migrate, no assumptions +- **Actionable**: Clear steps, not just descriptions +- **Example-driven**: Show before/after code for each change type +- **Self-contained**: Reader shouldn't need to reference other docs to complete migration + +Assume the reader: +- Has an existing RSX application +- Understands the framework basics +- Does NOT know what changed or why diff --git a/app/RSpade/upstream_changes/responsive_12_18.txt b/app/RSpade/upstream_changes/responsive_12_18.txt new file mode 100755 index 000000000..e746f80a4 --- /dev/null +++ b/app/RSpade/upstream_changes/responsive_12_18.txt @@ -0,0 +1,427 @@ +RESPONSIVE BREAKPOINT SYSTEM - MIGRATION GUIDE +Date: 2024-12-18 + +SUMMARY + RSX now uses a custom two-tier responsive breakpoint system that replaces + Bootstrap's default breakpoints (xs/sm/md/lg/xl/xxl) with semantic device + names. This provides clearer intent (mobile vs desktop) and finer control + (phone/tablet/desktop-sm/desktop-md/desktop-lg). All existing media queries + using hardcoded pixel values or Bootstrap breakpoint variables should be + migrated to use the new SCSS mixins. + + Bootstrap's default responsive utility classes (.col-md-*, .d-lg-*, etc.) + no longer work. Applications must use the new breakpoint names. + +BREAKPOINT DEFINITIONS + + Tier 1 - Semantic (Mobile vs Desktop): + mobile 0 - 1023px Phone + tablet combined + desktop 1024px+ All desktop sizes + + Tier 2 - Granular Device Classes: + phone 0 - 799px Phones, small handhelds + tablet 800 - 1023px Tablets portrait, large phones landscape + desktop-sm 1024 - 1699px Laptops, small monitors + desktop-md 1700 - 2199px Standard monitors (1080p-1440p) + desktop-lg 2200px+ Large/ultra-wide monitors, 4K + + The 1024px mobile/desktop boundary was chosen because tablets in landscape + (iPad Pro at 1366px) should receive desktop layouts. + +AFFECTED FILES + + Framework files (already updated): + rsx/theme/vendor/bootstrap5/scss/_variables.scss + rsx/theme/variables.scss + rsx/theme/responsive.scss (new file) + All bundle definition files (*_bundle.php) + + Application files requiring migration: + Any *.scss file with @media queries using pixel values + Any template using Bootstrap responsive classes (.col-md-*, .d-lg-*, etc.) + +CHANGES REQUIRED + + 1. Bootstrap Assertion Disabled + ------------------------------------------------------------------------- + In rsx/theme/vendor/bootstrap5/scss/_variables.scss, the ascending + assertion for $grid-breakpoints has been commented out to allow + semantic aliases (mobile/phone share 0, desktop/desktop-sm share 1024px): + + Line 494-495: + // RSX: Disabled to allow semantic breakpoint aliases + // @include _assert-ascending($grid-breakpoints, "$grid-breakpoints"); + + If you have a custom Bootstrap checkout, apply this change. + + 2. Create responsive.scss + ------------------------------------------------------------------------- + Create rsx/theme/responsive.scss with mixins and utility classes. + + Full file contents: + + // ========================================================================== + // RSX RESPONSIVE SYSTEM + // ========================================================================== + // + // Two-tier responsive breakpoint system for consistent mobile/desktop handling. + // + // TIER 1 - Semantic (Mobile vs Desktop): + // Mobile: 0 - 1023px (phone + tablet combined) + // Desktop: 1024px+ (all desktop sizes) + // + // TIER 2 - Granular Device Classes: + // phone: 0 - 799px + // tablet: 800 - 1023px + // desktop-sm: 1024 - 1699px + // desktop-md: 1700 - 2199px + // desktop-lg: 2200px+ + + // ========================================================================== + // TIER 1 MIXINS: Mobile vs Desktop + // ========================================================================== + + @mixin mobile { + @media (max-width: $bp-mobile-max) { + @content; + } + } + + @mixin desktop { + @media (min-width: $bp-desktop-min) { + @content; + } + } + + // ========================================================================== + // TIER 2 MIXINS: Device-specific + // ========================================================================== + + @mixin phone { + @media (max-width: $bp-phone-max) { + @content; + } + } + + @mixin tablet { + @media (min-width: $bp-tablet-min) and (max-width: $bp-tablet-max) { + @content; + } + } + + @mixin tablet-up { + @media (min-width: $bp-tablet-min) { + @content; + } + } + + @mixin tablet-down { + @media (max-width: $bp-tablet-max) { + @content; + } + } + + @mixin desktop-sm { + @media (min-width: $bp-desktop-sm-min) and (max-width: $bp-desktop-sm-max) { + @content; + } + } + + @mixin desktop-sm-up { + @media (min-width: $bp-desktop-sm-min) { + @content; + } + } + + @mixin desktop-md { + @media (min-width: $bp-desktop-md-min) and (max-width: $bp-desktop-md-max) { + @content; + } + } + + @mixin desktop-md-up { + @media (min-width: $bp-desktop-md-min) { + @content; + } + } + + @mixin desktop-lg { + @media (min-width: $bp-desktop-lg-min) { + @content; + } + } + + // ========================================================================== + // UTILITY CLASSES + // ========================================================================== + + .mobile-only { + @include desktop { + display: none !important; + } + } + + .desktop-only { + @include mobile { + display: none !important; + } + } + + .hide-mobile { + @include mobile { + display: none !important; + } + } + + .hide-desktop { + @include desktop { + display: none !important; + } + } + + .phone-only { + @include tablet-up { + display: none !important; + } + } + + .tablet-only { + @include phone { + display: none !important; + } + @include desktop { + display: none !important; + } + } + + .hide-phone { + @include phone { + display: none !important; + } + } + + .hide-tablet { + @include tablet { + display: none !important; + } + } + + // ========================================================================== + // CSS CUSTOM PROPERTIES (for JavaScript access) + // ========================================================================== + + :root { + --bp-mobile-max: #{$bp-mobile-max}; + --bp-desktop-min: #{$bp-desktop-min}; + --bp-phone-max: #{$bp-phone-max}; + --bp-tablet-min: #{$bp-tablet-min}; + --bp-tablet-max: #{$bp-tablet-max}; + --bp-desktop-sm-min: #{$bp-desktop-sm-min}; + --bp-desktop-sm-max: #{$bp-desktop-sm-max}; + --bp-desktop-md-min: #{$bp-desktop-md-min}; + --bp-desktop-md-max: #{$bp-desktop-md-max}; + --bp-desktop-lg-min: #{$bp-desktop-lg-min}; + } + + 3. Update variables.scss + ------------------------------------------------------------------------- + Add breakpoint variables and Bootstrap $grid-breakpoints override. + + Add to rsx/theme/variables.scss (replace any existing breakpoint vars): + + // ========================================================================== + // RESPONSIVE BREAKPOINTS + // ========================================================================== + // Two-tier system: Tier 1 (Mobile vs Desktop) and Tier 2 (Granular devices) + // See rsx/theme/responsive.scss for mixins and utilities + + // Tier 2: Granular device breakpoints + $bp-phone-max: 799px; + $bp-tablet-min: 800px; + $bp-tablet-max: 1023px; + $bp-desktop-sm-min: 1024px; + $bp-desktop-sm-max: 1699px; + $bp-desktop-md-min: 1700px; + $bp-desktop-md-max: 2199px; + $bp-desktop-lg-min: 2200px; + + // Tier 1: Semantic breakpoints (mobile = phone + tablet) + $bp-mobile-max: 1023px; + $bp-desktop-min: 1024px; + + // Bootstrap grid breakpoints override + // Allows: .col-mobile-6, .col-phone-12, .col-tablet-8, .col-desktop-4, etc. + // Note: mobile/phone share 0, desktop/desktop-sm share 1024px (assertion disabled) + $grid-breakpoints: ( + xs: 0, + mobile: 0, + phone: 0, + tablet: 800px, + desktop: 1024px, + desktop-sm: 1024px, + desktop-md: 1700px, + desktop-lg: 2200px + ); + + Remove any old breakpoint variables like: + $breakpoint-sm, $breakpoint-md, $breakpoint-lg, $breakpoint-xl, $breakpoint-2xl + + 4. Update Bundle Definitions + ------------------------------------------------------------------------- + Add responsive.scss to every bundle after variables.scss but before Bootstrap. + + Before: + 'include' => [ + 'rsx/theme/variables.scss', + 'Bootstrap5_Src_Bundle', + ... + ] + + After: + 'include' => [ + 'rsx/theme/variables.scss', + 'rsx/theme/responsive.scss', // ADD THIS LINE + 'Bootstrap5_Src_Bundle', + ... + ] + + Apply to all bundle files: + - rsx/app/frontend/frontend_bundle.php + - rsx/app/login/login_bundle.php + - rsx/app/root/root_bundle.php + - rsx/app/dev/dev_bundle.php + - rsx/app/backend/backend_bundle.php + - Any other *_bundle.php files + + 5. Migrate SCSS Media Queries + ------------------------------------------------------------------------- + Replace hardcoded media queries with mixins. + + Common patterns: + + Before: @media (max-width: 767px) { ... } + After: @include phone { ... } + + Before: @media (max-width: 768px) { ... } + After: @include mobile { ... } + + Before: @media (max-width: 991.98px) { ... } + After: @include mobile { ... } + + Before: @media (max-width: 1199px) { ... } + After: @include mobile { ... } + + Before: @media (min-width: 768px) { ... } + After: @include tablet-up { ... } + + Before: @media (min-width: 992px) { ... } + After: @include desktop { ... } + + Before: @media (min-width: 1200px) { ... } + After: @include desktop { ... } + + Example file migration: + + Before: + .My_Component { + padding: 1rem; + + @media (max-width: 991.98px) { + padding: 0.5rem; + } + } + + After: + .My_Component { + padding: 1rem; + + @include mobile { + padding: 0.5rem; + } + } + + Remove any local breakpoint variables like: + $mobile-breakpoint: 991.98px; + + 6. Migrate Bootstrap Utility Classes in Templates + ------------------------------------------------------------------------- + Replace Bootstrap's default breakpoint names with RSX names. + + Grid columns: + Before: class="col-12 col-md-6 col-lg-4" + After: class="col-mobile-12 col-tablet-6 col-desktop-4" + + Before: class="col-sm-6 col-xl-3" + After: class="col-phone-6 col-desktop-md-3" + + Display utilities: + Before: class="d-none d-md-block" + After: class="d-none d-tablet-block" or class="d-mobile-none d-tablet-block" + + Before: class="d-lg-none" + After: class="d-desktop-none" + + Spacing: + Before: class="p-2 p-md-4" + After: class="p-2 p-tablet-4" or class="p-mobile-2 p-desktop-4" + + Common mappings: + Bootstrap RSX equivalent + --------- -------------- + xs (use base class, no suffix) + sm phone or mobile + md tablet or mobile + lg desktop + xl desktop or desktop-md + xxl desktop-lg + +CONFIGURATION + + No additional configuration required beyond the file changes above. + + Optional: If you need JavaScript access to breakpoints: + + const styles = getComputedStyle(document.documentElement); + const desktopMin = styles.getPropertyValue('--bp-desktop-min'); + const isMobile = window.innerWidth <= parseInt( + styles.getPropertyValue('--bp-mobile-max') + ); + +VERIFICATION + + 1. Compile bundles and verify no SCSS errors: + php artisan rsx:bundle:compile Frontend_Bundle + + 2. Check that responsive utility classes work: + - Add class="mobile-only" to an element, verify hidden on desktop + - Add class="col-mobile-12 col-desktop-6" to a div, verify layout changes + + 3. Search for orphaned Bootstrap classes: + grep -r "col-sm-\|col-md-\|col-lg-\|col-xl-\|d-sm-\|d-md-\|d-lg-\|d-xl-" rsx/ + + 4. Search for hardcoded media queries that should be migrated: + grep -r "@media.*max-width.*px\|@media.*min-width.*px" rsx/app rsx/theme/components + +DOCUMENTATION + + Man page created: rsx/resource/man/responsive.txt + View with: php artisan rsx:man responsive + + CLAUDE.md and docs.dist/CLAUDE.dist.md updated with: + - Responsive Breakpoints section under SCSS Component-First Architecture + - Tier 1 and Tier 2 definitions + - Mixin and class name reference + - Warning about Bootstrap default classes not working + +PROJECT MAN PAGES + + The rsx:man command now also searches rsx/resource/man/ for project-specific + documentation. Project man pages override framework man pages of the same name. + + Created: rsx/resource/man/CLAUDE.md (guidelines for project man pages) + +REFERENCE + + php artisan rsx:man responsive - Full responsive system documentation + php artisan rsx:man scss - SCSS organization conventions + php artisan rsx:man man - Man page system documentation diff --git a/docs/CLAUDE.dist.md b/docs/CLAUDE.dist.md index 3c5ebd64c..72def22ad 100644 --- a/docs/CLAUDE.dist.md +++ b/docs/CLAUDE.dist.md @@ -446,6 +446,29 @@ The process involves creating Action classes with @route decorators and converti Details: `php artisan rsx:man scss` +### Responsive Breakpoints + +RSX replaces Bootstrap's default breakpoints (xs/sm/md/lg/xl/xxl) with semantic device names. + +**Tier 1 - Semantic**: +- `mobile`: 0 - 1023px (phone + tablet) +- `desktop`: 1024px+ + +**Tier 2 - Granular**: +- `phone`: 0 - 799px | `tablet`: 800 - 1023px | `desktop-sm`: 1024 - 1699px | `desktop-md`: 1700 - 2199px | `desktop-lg`: 2200px+ + +**SCSS Mixins**: `@include mobile { }`, `@include desktop { }`, `@include phone { }`, `@include tablet { }`, `@include desktop-sm { }`, etc. + +**Bootstrap Classes**: `.col-mobile-6`, `.col-desktop-4`, `.d-mobile-none`, `.d-tablet-block`, `.col-phone-12 .col-tablet-6 .col-desktop-sm-4` + +**Utility Classes**: `.mobile-only`, `.desktop-only`, `.phone-only`, `.hide-mobile`, `.hide-tablet` + +**Note**: Bootstrap's default classes like `.col-md-6` or `.d-lg-none` do NOT work - use the RSX breakpoint names instead. + +**JS Detection**: `Responsive.is_mobile()`, `Responsive.is_desktop()` (Tier 1 - broad); `Responsive.is_phone()`, `Responsive.is_tablet()`, `Responsive.is_desktop_sm()`, `Responsive.is_desktop_md()`, `Responsive.is_desktop_lg()` (Tier 2 - specific ranges) + +Details: `php artisan rsx:man responsive` + ### JavaScript for Blade Pages Unlike SPA actions (which use component lifecycle), Blade pages use static `on_app_ready()` with a page guard: @@ -1208,10 +1231,24 @@ class Main extends Main_Abstract ## GETTING HELP ```bash -php artisan rsx:man # Detailed docs +php artisan rsx:man # Framework documentation php artisan list rsx # All commands ``` **Topics**: bundle_api, jqhtml, routing, migrations, console_debug, model_fetch, vs_code_extension, deployment, framework_divergences +--- + +## PROJECT DOCUMENTATION + +Project-specific technical documentation lives in `/rsx/resource/man/`. These are man-page-style text files documenting features specific to your application that build on or extend the framework. + +**When to create a project man page**: +- Feature has non-obvious implementation details +- Multiple components interact in ways that need explanation +- Configuration options or patterns need documentation +- AI agents or future developers need reference material + +**Format**: Plain text files (`.txt`) following Unix man page conventions. See `/rsx/resource/man/CLAUDE.md` for writing guidelines. + **Remember**: RSpade prioritizes simplicity and rapid development. When in doubt, choose the straightforward approach.