Class: Plutonium::UI::Component::Section
- Defined in:
- lib/plutonium/ui/component/section.rb
Overview
Shared chrome for a declared layout section — a card with a header row (accent bar, heading, optional description, optional collapse caret) over a body that holds the fields. Subclassed (not copied) by both Form::Components::Section and Display::Components::Section so a form section and a show-page section always read the same; the only difference between the two is which grid class the caller passes in.
Each section is its OWN card rather than a band inside one shared card. The card boundary does the grouping — no amount of heading typography separates two field groups as unambiguously as an actual edge does, and the header row then only has to name the group rather than carry the whole structural signal. Callers therefore must NOT wrap sections in a card of their own; they supply a plain stacking container.
The caller supplies the fields as a block and owns what a "field" means.
Direct Known Subclasses
Constant Summary collapse
- DEFAULT_THEME =
Default section chrome, merged into BOTH Form::Theme and Display::Theme so the two read identically out of the box while each stays independently overridable — the same contract every other themed key has. Defined here rather than written out twice so the shipped defaults cannot drift between the form and the show page.
Structure (which element gets which key, the
group/[open] mechanics) stays in this component; themes own the classes. { # Merged into the section's {Plutonium::UI::Block} card — Block # supplies `pu-card` itself, so this only adds what is specific to a # section. `overflow-hidden` keeps the header row's fill and border # inside the card's rounded corners. section_wrapper: "overflow-hidden", # Header row. Its bottom border is the line between the header and # the fields — the card edge already separates one section from the # next, so nothing else has to. section_header: "px-4 py-3 flex items-center gap-3 " \ "border-b border-[var(--pu-border)] bg-[var(--pu-surface-alt)]", # A short primary bar at the head of the row. A standalone element # rather than a border on the text block, so the heading and its # description stay vertically centred against it. section_accent: "shrink-0 w-1 h-5 rounded-full bg-primary-500", # Sized to sit under the page title (text-xl semibold) while # out-ranking display values (text-lg regular) and field labels. # With the card doing the separating, the heading no longer has to # shout to be read as a header. section_heading: "text-base font-bold tracking-tight text-[var(--pu-text)]", section_description: "text-sm font-normal text-[var(--pu-text-muted)]", # `list-none` + the WebKit marker reset remove the native disclosure # triangle, which the browser pins to the LEFT of the summary — where # it would displace the accent bar and knock the heading out of the # alignment every other section keeps. The caret is re-drawn on the # right instead, so headers stay identical whether or not a section # happens to be collapsible. # The divider only exists to separate the header from the fields, so # a COLLAPSED section must not draw one — there is nothing below it, # and the line would land directly on the card's own bottom border. # `group-open:` keys it to the parent <details>'s [open] state. section_summary: "px-4 py-3 flex items-center gap-3 cursor-pointer select-none " \ "border-b-0 group-open:border-b border-[var(--pu-border)] " \ "bg-[var(--pu-surface-alt)] " \ "list-none [&::-webkit-details-marker]:hidden", section_caret: "shrink-0 w-3 h-3 text-[var(--pu-text-muted)] " \ "transition-transform duration-200 group-open:rotate-180", # Padding box between the card edge and the field grid. Roomier than # the stock `pu-card-body` (16px): a section card holds inputs, not # the dense label/value rows a card body is sized for, and the form # this replaced was a single `p-8` card — at 16px the fields sit # noticeably tighter against the edge than they used to. section_body: "p-6" }.freeze
Class Method Summary collapse
-
.theme_class ⇒ Object
The theme this section's chrome resolves against.
Instance Method Summary collapse
-
#initialize(resolved, grid_class:) ⇒ Section
constructor
A new instance of Section.
-
#view_template(&fields_block) ⇒ Object
Every section is a Block — the shared card primitive — so a section card and any other card on the page are the same surface by construction rather than by two lists of classes that happen to agree today.
Methods included from Behaviour
Methods included from Tokens
Methods included from Kit
#BuildActionButton, #BuildActionsDropdown, #BuildAvatar, #BuildBlock, #BuildBreadcrumbs, #BuildBulkActionsToolbar, #BuildColorModeSelector, #BuildDynaFrameContent, #BuildDynaFrameHost, #BuildEmptyCard, #BuildFrameNavigatorPanel, #BuildModalCentered, #BuildModalSlideover, #BuildPageHeader, #BuildPanel, #BuildRowActionsDropdown, #BuildSkeletonTable, #BuildTabList, #BuildTableFilterPills, #BuildTableInfo, #BuildTablePagination, #BuildTableScopesBar, #BuildTableScopesPills, #BuildTableSearchBar, #BuildTableToolbar, #BuildTableViewSwitcher, #method_missing, #respond_to_missing?
Constructor Details
#initialize(resolved, grid_class:) ⇒ Section
Returns a new instance of Section.
92 93 94 95 |
# File 'lib/plutonium/ui/component/section.rb', line 92 def initialize(resolved, grid_class:) @section = resolved.section @grid_class = grid_class end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method in the class Plutonium::UI::Component::Kit
Class Method Details
.theme_class ⇒ Object
The theme this section's chrome resolves against. Subclasses name their own, so a form section follows Form::Theme and a show-page section follows Display::Theme.
88 89 90 |
# File 'lib/plutonium/ui/component/section.rb', line 88 def self.theme_class raise NotImplementedError, "#{self} must implement .theme_class" end |
Instance Method Details
#view_template(&fields_block) ⇒ Object
Every section is a Block — the shared card primitive — so a section card and any other card on the page are the same surface by construction rather than by two lists of classes that happen to agree today.
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/plutonium/ui/component/section.rb', line 101 def view_template(&fields_block) Block(class: themed_section(:section_wrapper)) do if @section.collapsible? # `group` lets the caret rotate off the <details>'s [open] state. details(open: !@section.collapsed?, class: "group") do # <summary> must be the first child of <details> and can't be # wrapped, so it IS the header row. summary(class: themed_section(:section_summary)) do span(class: themed_section(:section_accent)) heading_block render_caret end body(&fields_block) end else header_row body(&fields_block) end end end |