Elements are the primary building block for Torque Admin’s UI layer. Rather than scattering markup across view templates, an element encapsulates a logical component definition — its nodes, properties, and rendering instructions — completely separately from the HTML output. This decoupling lets you reuse, extend, or theme the same structural description across different controllers and UI frameworks without duplicating template code.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/crashtech/torque-admin/llms.txt
Use this file to discover all available pages before exploring further.
The Element Hierarchy
Every element ultimately subclassesTorque::Elements::Base, which composes five core concerns:
| Concern | Responsibility |
|---|---|
Core::Index | Named lookup via [], fetch, key?, size; maintains the id → Node index |
Core::Nodes | Tree of Node objects; traverse, move, append_node, etc. |
Core::Render | render_in pipeline — triggers load → render → produces HTML |
Core::Helpers | i18n text resolution, option sanitisation |
Core::Definition | Lifecycle (initiated → loading → loaded → rendering → rendered) and lazy config |
app/elements/:
Torque::Admin::BaseElement— the direct ancestor for admin elements; addsplacementtoelement_settings.Torque::Admin::MenuElement— aBaseElementsubclass with full menu-item, divider, icon, and current-page detection logic built in.
BaseElement (or any other admin element class) rather than Torque::Elements::Base directly.
How Element Resolution Works
The config optionelements_lookup_context holds an ordered list of module names that the engine searches when resolving an element class. Lookup happens in reverse order, so the last entry wins — meaning modules added by your application shadow gem-level element definitions.
The default lookup context for every new application is:
Admin::MyWidgetElement will shadow Torque::Admin::MyWidgetElement if both exist, because 'Admin' is searched first.
Creating a Custom Element
Step 1 — Subclass BaseElement
Create a file inapp/elements/ of your Rails application:
Step 2 — Register it on a controller
Useelement (defined by the controller concern) to attach the element definition and its config block to a specific action context. The config block is executed lazily at render time, with self bound to the element instance via SimpleDelegator, so you call element-level node-building methods directly:
alias_element:
The Lazy Config Lifecycle
An element’s config block is not executed at definition time. The call sequence is:element(name, of_type:, ...)— stores the class and options; no instantiation yet.- First access via
elements[:revenue_card]— theRegistryinstantiates the class. render_in(view_context)is called from the template — this triggers:load_config!— executes the stored@configblock (only once; guarded byloaded?).- Marks state as
renderingthenrendered. - Calls
render_node(root)to produce the final HTML string.
Node Structure
Inside a config block, nodes are built through the element’s own node-building methods (such asitem and divider on MenuElement). The block is executed via instance_exec on a SimpleDelegator wrapping the element, so all element instance methods are available directly. The Core::Index concern provides [], fetch, and key? for node lookup by identifier. Nodes can be positioned relative to each other using the insert_after:, insert_before:, prepend_to:, and append_to: options:
insert_after:, insert_before:, prepend_to:, append_to:.
UiBuilder DSL Properties Reference
The UiBuilder DSL is used insidedefine blocks when authoring framework helper modules (e.g. Bootstrap or Semantic UI element definitions). It is not available inside ordinary element config blocks. The b argument is a HelperConstructor proxy, and the following chainable methods are available on it:
| Method | Purpose |
|---|---|
b.argument(:name) | Positional argument; often assigns(:class) or assigns(:data_x) |
b.property(:color) | Named keyword; chainable with .formats, .maps, .applies, .assigns |
b.toggles(:active, :disabled) | Boolean flags — each adds a CSS class matching the toggle name when truthy |
b.imports(:icon, :size) | Pulls in a shared property definition from the framework’s import registry |
b.preset(:name, as: 'div', class: 'my-class') | Named visual variant; selected at render time with fetch_presets(:variant, from: :element_name) |
Preset example from Bootstrap elements
UiBuilder and Framework Integration
Elements call UiBuilder helpers (ui.button(...), ui.menu(...), etc.) to produce framework-specific HTML. The UiBuilder class maintains a registry of framework-aware subclasses:
add_framework accepts a module that is a HelperConstructor-extended module — the same pattern used by the built-in :bootstrap and :semantic_ui frameworks. The method creates a new Class.new(UiBuilder) and includes the module, then stores it under the normalised framework name.
When the admin application boots it selects its framework via the theme: config option and calls UiBuilder.add_framework internally, wiring the resulting class to the application’s ui_builder accessor.
