PageSectionComponent - Consistent Page Section Wrapper
Overview
Section titled “Overview”The Www::PageSectionComponent provides a standardized way to create page sections with consistent styling across all static pages. It handles:
- Container sizing (container-lg, container-fluid, etc.)
- Vertical padding (py-2, py-4, py-5)
- Border styles (top, bottom, both, none)
- Background styles (white, light, mint-green, gradients)
- Motion/reveal animations via the motion Stimulus controller
Using the ViewComponent directly
Section titled “Using the ViewComponent directly”<%= render Www::PageSectionComponent.new( id: 'features', border: :bottom, padding: 'py-4') do %> <h2>Features</h2> <p>Your content here...</p><% end %>Using the helper method (recommended)
Section titled “Using the helper method (recommended)”<%= page_section(id: 'features', border: :bottom) do %> <h2>Features</h2> <p>Your content here...</p><% end %>Options
Section titled “Options”| Option | Type | Default | Description |
|---|---|---|---|
id | String | nil | Optional section ID for anchor links |
container | String | ’container-lg’ | Container class. Use nil for no container |
padding | String | ’py-4’ | Vertical padding class |
border | Symbol | :bottom | Border style: :none, :top, :bottom, :both |
background | Symbol/String | :default | Background style or custom class |
motion | Symbol/Hash | nil | Motion animation preset or custom options |
extra_classes | String | nil | Additional CSS classes for the section |
data | Hash | {} | Additional data attributes |
Note: The default border: :bottom provides consistent visual separation between sections. Override with border: :none when a component handles its own borders or when using a colored background.
Background Options
Section titled “Background Options”| Value | CSS Class | Description |
|---|---|---|
:default | (none) | No background color |
:white | bg-white | White background |
:light | bg-light | Light gray background |
:mint_green | mint-green-patterned-background | Mint green patterned background |
:gradient_light | bg-gradient-light | Light gradient |
:gradient_danger | bg-gradient-danger | Red/danger gradient |
| Custom string | (your class) | Any custom class |
Motion Animation Presets
Section titled “Motion Animation Presets”The helper method supports these motion presets:
| Preset | Animation | Description |
|---|---|---|
:fade_up | fadeInUp | Fade in from below |
:fade_left | fadeInLeft | Fade in from left |
:fade_right | fadeInRight | Fade in from right |
:zoom | zoomPop | Zoom/pop in |
:pulse | pulse | Subtle pulse effect |
For custom motion options, pass a hash:
<%= page_section(motion: { animation: 'fadeInUp', distance: 80, duration: 0.9, stagger: 0.1 }) do %> ...<% end %>Examples
Section titled “Examples”Basic section with border
Section titled “Basic section with border”<%= page_section(border: :bottom) do %> <%= page_header_h2 "Section Title" %> <p>Content goes here...</p><% end %>Section with colored background
Section titled “Section with colored background”<%= page_section(background: :mint_green, padding: 'py-5') do %> <%= page_header_h2 "Why Choose Us?" %> <%= render Www::FeatureListComponent.new(...) %><% end %>Section with reveal animation
Section titled “Section with reveal animation”<%= page_section(id: 'faq', motion: :fade_up) do %> <%= render Www::FaqListComponent.new(...) %><% end %>Two-column section with image
Section titled “Two-column section with image”<%= page_section(id: 'about', border: :bottom) do %> <div class="row gx-4 gy-3 align-items-stretch"> <div class="col-12 col-lg-5"> <%= page_header_h2 "About Section" %> <p class="fw-light">Description text...</p> </div> <div class="col-12 col-lg-6 d-flex my-3 my-lg-0"> <%= image_asset_tag 'image-id', width: 1200, class: 'img-fluid w-100 h-100 object-fit-cover rounded o-hidden' %> </div> </div><% end %>Full-width section (no container)
Section titled “Full-width section (no container)”<%= page_section(container: nil, background: :light, padding: 'py-5') do %> <div class="container-fluid"> <!-- Custom container/layout --> </div><% end %>Before/After Example
Section titled “Before/After Example”Before (manual markup)
Section titled “Before (manual markup)”<section class="container-lg py-2" id="showcases"> <% showcases = ... %> <%= render Www::ShowcaseGridComponent.new( section_title: 'Projects', showcases: showcases, border: :bottom ) %></section><section class="container-lg py-4"> <div class="row gx-4 gy-3 align-items-stretch"> <div class="col-12 col-lg-5"> <%= page_header_h2 "Title" %> <p>Content...</p> </div> <div class="col-12 col-lg-6 d-flex my-3 my-lg-0"> <%= image_asset_tag 'image', width: 1200 %> </div> </div></section>After (using component)
Section titled “After (using component)”<%= page_section(id: 'showcases', padding: 'py-2') do %> <% showcases = ... %> <%= render Www::ShowcaseGridComponent.new( section_title: 'Projects', showcases: showcases, border: :bottom ) %><% end %>
<%= page_section do %> <div class="row gx-4 gy-3 align-items-stretch"> <div class="col-12 col-lg-5"> <%= page_header_h2 "Title" %> <p>Content...</p> </div> <div class="col-12 col-lg-6 d-flex my-3 my-lg-0"> <%= image_asset_tag 'image', width: 1200, class: 'img-fluid w-100 h-100 object-fit-cover rounded o-hidden' %> </div> </div><% end %>Consistent Section Structure
Section titled “Consistent Section Structure”All sections follow this consistent structure:
<section id="section-name" class="py-4 border-bottom"> <!-- PageSectionComponent --> <div class="container-lg"> <!-- Container --> <div class="d-flex align-items-start pb-3"> <!-- SectionHeaderComponent --> <div class="me-3 pt-1"><!-- icon --></div> <div class="flex-grow-1"> <h2>Section Title</h2> </div> </div> <!-- Content directly here, no extra wrapper padding --> </div></section>Spacing Rules
Section titled “Spacing Rules”| Element | Spacing | Purpose |
|---|---|---|
PageSectionComponent | py-4 (default) | Outer section padding |
SectionHeaderComponent | pb-3 | Space below header before content |
| Inner components | No wrapper padding | Content spacing handled by components themselves |
border-bottom | Default on sections | Visual separation between sections |
Related: SectionHeaderComponent
Section titled “Related: SectionHeaderComponent”The Www::SectionHeaderComponent renders consistent section headers with optional icon and description.
Important: The header’s border (<hr>) is now disabled by default since PageSectionComponent handles section borders. Only enable it when the header is used outside of a PageSectionComponent.
<%# Default: no border (used inside PageSectionComponent) %><%= render Www::SectionHeaderComponent.new(title: 'Products', icon: 'box') %>
<%# With border (for standalone use outside PageSectionComponent) %><%= render Www::SectionHeaderComponent.new(title: 'Products', icon: 'box', border: true) %>Inner Components Should NOT Add Wrapper Padding
Section titled “Inner Components Should NOT Add Wrapper Padding”When creating or updating components that render inside PageSectionComponent:
DO:
<div> <% if section_title.present? %> <%= render Www::SectionHeaderComponent.new(title: section_title, icon: icon) %> <% end %> <!-- content --></div>DON’T:
<div class="py-2"> <%# NO - don't add wrapper padding %> ...</div>Benefits
Section titled “Benefits”- Consistency: All sections use the same padding, borders, and structure
- Maintainability: Change section styling in one place
- Animation Support: Easy to add reveal animations
- Fewer Errors: Less manual HTML means fewer typos/inconsistencies
- Documentation: Component API is self-documenting
- No Redundant Borders: Section borders are controlled at one level (PageSectionComponent)