Senren UI
Components / Typography

Typography

Stable

page titles

Display heading

Section heading

Subsection

Card title

Body copy renders with comfortable rhythm and a measured line length.

Muted supporting text.

Smaller secondary text.

Usage example #

Copy this ERB into a Rails view after installing the component. The snippet below is the same code used by the live preview above.

app/views/.../typography_example.html.erb
<div class="space-y-3 text-left w-full">
  <%= render(Senren::TypographyComponent.new(variant: :h1))      { "Display heading" } %>
  <%= render(Senren::TypographyComponent.new(variant: :h2))      { "Section heading" } %>
  <%= render(Senren::TypographyComponent.new(variant: :h3))      { "Subsection" } %>
  <%= render(Senren::TypographyComponent.new(variant: :h4))      { "Card title" } %>
  <%= render(Senren::TypographyComponent.new(variant: :p))       { "Body copy renders with comfortable rhythm and a measured line length." } %>
  <%= render(Senren::TypographyComponent.new(variant: :muted))   { "Muted supporting text." } %>
  <%= render(Senren::TypographyComponent.new(variant: :small))   { "Smaller secondary text." } %>
</div>

Install this component #

Copy the official component into your app

Use this when you want the Senren-maintained implementation copied into app/components/senren.

Terminal
bin/rails senren:add typography

Create a custom component with the same conventions

Use this when you need an app-specific static component that follows Senren's ViewComponent structure.

Terminal
bin/rails generate senren:component typography --no-client

At a glance #

Category Layout
Class name Senren::TypographyComponent
Stimulus
Variants h1, h2, h3, h4, p, lead, large, small, muted
Depends on
Pairs with card, page_header

Source #

app/components/senren/typography_component.html.erb
<%= content_tag(html_tag, content, **root_attrs("")) %>
app/components/senren/typography_component.rb
module Senren
  class TypographyComponent < BaseComponent
    VARIANTS = {
      h1: 'scroll-m-20 text-4xl font-bold tracking-tight',
      h2: 'scroll-m-20 text-3xl font-semibold tracking-tight',
      h3: 'scroll-m-20 text-2xl font-semibold tracking-tight',
      h4: 'scroll-m-20 text-xl font-semibold tracking-tight',
      p: 'leading-7',
      lead: 'text-xl text-[hsl(var(--senren-muted-foreground))]',
      large: 'text-lg font-semibold',
      small: 'text-sm font-medium leading-none',
      muted: 'text-sm text-[hsl(var(--senren-muted-foreground))]'
    }.freeze

    SIZES = { md: '' }.freeze

    TAG_FOR = {
      h1: :h1, h2: :h2, h3: :h3, h4: :h4,
      p: :p, lead: :p, large: :p, small: :small, muted: :p
    }.freeze

    def html_tag = TAG_FOR[variant]
  end
end

AI agent rules #

Use for

  • +page titles
  • +body copy
  • +captions

Avoid

  • -styling without semantic tag matching

Accessibility #

  • Heading levels must be sequential; do not skip levels.