Code Block
A syntax-highlighted code panel with a copy button and optional line numbers.
Installation
Included in poetry-ui — available as
poetry_code_block
the moment you've installed Poetry,
with no per-component step. To own the source and edit it, copy it into your app:
bin/rails g poetry:add code-block
Default
class Invoice < ApplicationRecord
belongs_to :customer
scope :settled, -> { where(status: "settled") }
end
<% code = <<~RUBY
class Invoice < ApplicationRecord
belongs_to :customer
scope :settled, -> { where(status: "settled") }
end
RUBY
%>
<div class="w-full max-w-xl">
<%= poetry_code_block(code: code, language: "ruby", label: "Invoice model") %>
</div>
Numbered and highlighted
def total
line_items.sum(&:amount)
end
<%# line_numbers: renders CSS counters (never in copied text);
highlight_lines: tints the named 1-based lines. %>
<% code = <<~RUBY
def total
line_items.sum(&:amount)
end
RUBY
%>
<div class="w-full max-w-xl">
<%= poetry_code_block(code: code, language: "ruby", label: "Total method",
line_numbers: true, highlight_lines: [2]) %>
</div>
API
Poetry::Ui::CodeBlock::Component — options are
constructor keywords (the poetry_* helper forwards them);
slots are composed inside the block. Generated from the gem's source documentation.
| Option | Type | Details | Description |
|---|---|---|---|
| code: | String | required | The source text to highlight - required. |
| copy: | Boolean | defaults to true |
Renders the copy button in the panel's corner. |
| highlight_lines: | Object | 1-based line numbers to tint via the theme's highlight hook. | |
| label: | String | The scroll region's accessible name; defaults to the localized \"Code\" (a focusable scrollable region must be named - axe). | |
| language: | String | defaults to "text" |
The lexer name (\"ruby\", \"js\", ...); unknown languages fall back to plain text. |
| line_numbers: | Boolean | defaults to false |
Renders CSS-counter line numbers - never part of selection or copied text. |
Styling
Every part carries a stable data-slot attribute — target
[data-slot=…] from your own CSS to restyle it. State rides
data attributes on the parts below. This contract is verified against rendered DOM in CI.
| Part | Description |
|---|---|
| [data-slot=code-block] | Root - the syntax-palette surface (cn-code-block) |
| [data-slot=code-block-pre] | The scroll container - tabindex 0 + role region + label (a scrollable region must be keyboard-reachable and named) |
| [data-slot=code-block-code] | The code element - rouge's .line/.hll spans and the seven --syntax-* token maps live under it; the copy affordance reads ITS textContent |
State attributes
| Part | Attribute | Condition | Values |
|---|---|---|---|
| code-block | data-language | always - the lexer name, a styling/tooling hook | — |
| code-block | data-line-numbers | line_numbers: - turns on the ::before CSS counters | — |
| code-block | data-copied | copy: only - stamped for a beat after a successful copy (the clipboard-text engine) | — |
Wiring
The Stimulus surface each element carries — declared in the component, verified against rendered DOM in CI. Bare actions fire on the element's default event.
| Element | Controller | Wiring |
|---|---|---|
| root (if copy) | poetry--core--clipboard-text | registers · value message |
| source (if copy) | poetry--core--clipboard-text | target source |
| copy_button | poetry--core--clipboard-text | copy on click |