Api Key Field
Stable Stimulus:senren--api-key-field
secret key display with reveal/copy/regenerate
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/.../api_key_field_example.html.erb
<div class="w-full max-w-md">
<%= render Senren::ApiKeyFieldComponent.new(
value: "sk_live_1234abcd5678",
label: "Production API key",
reveal_label: "Reveal",
hide_label: "Hide",
copy_label: "Copy"
) %>
</div>
Install this component #
Copy the official component into your app
This component requires Stimulus. Keep --client so the controller is copied with the ViewComponent.
Terminal
bin/rails senren:add api_key_field --client
Create a custom component with the same conventions
Use this when you need an app-specific component that follows Senren's ViewComponent and Stimulus structure. --client is required for this behavior.
Terminal
bin/rails generate senren:component api_key_field --client
Dependencies are resolved by senren:add:
input, button, clipboard.
At a glance #
Category
Saas
Class name
Senren::ApiKeyFieldComponent
Stimulus
senren--api-key-field
Variants
default
Depends on
input, button, clipboard
Pairs with
settings_section
Source #
app/components/senren/api_key_field_component.html.erb
<%= tag.div(**root_attrs("space-y-2", data: { controller: "senren--api-key-field", "senren--api-key-field-reveal-label-value": reveal_label, "senren--api-key-field-hide-label-value": hide_label, "senren--api-key-field-copy-label-value": copy_label })) do %>
<% if content? && value.blank? %>
<%= content %>
<% else %>
<label class="block text-sm font-medium text-[hsl(var(--senren-foreground))]"><%= label %></label>
<div class="flex flex-col gap-2 sm:flex-row">
<input type="password" readonly value="<%= value %>" data-senren--api-key-field-target="input" class="h-10 min-w-0 flex-1 rounded-(--senren-radius) border border-[hsl(var(--senren-input))] bg-[hsl(var(--senren-muted)/0.35)] px-3 font-mono text-sm text-[hsl(var(--senren-foreground))] outline-none focus:ring-2 focus:ring-[hsl(var(--senren-ring))]">
<button type="button" data-senren--api-key-field-target="revealButton" data-action="click->senren--api-key-field#toggle" class="inline-flex h-10 cursor-pointer items-center justify-center rounded-(--senren-radius) border border-[hsl(var(--senren-border))] px-3 text-sm font-medium hover:bg-[hsl(var(--senren-accent))]"><%= reveal_label %></button>
<button type="button" data-action="click->senren--api-key-field#copy" class="inline-flex h-10 cursor-pointer items-center justify-center rounded-(--senren-radius) bg-[hsl(var(--senren-primary))] px-3 text-sm font-medium text-[hsl(var(--senren-primary-foreground))] hover:opacity-90"><%= copy_label %></button>
</div>
<span class="sr-only" aria-live="polite" data-senren--api-key-field-target="status"></span>
<% end %>
<% end %>
app/components/senren/api_key_field_component.rb
# frozen_string_literal: true
module Senren
class ApiKeyFieldComponent < BaseComponent
VARIANTS = { default: '' }.freeze
SIZES = { md: '' }.freeze
def initialize(value: nil, label: 'API key', reveal_label: 'Reveal', hide_label: 'Hide', copy_label: 'Copy',
class_name: nil, **html)
super(variant: :default, size: :md, class_name: class_name, **html)
@value = value
@label = label
@reveal_label = reveal_label
@hide_label = hide_label
@copy_label = copy_label
end
attr_reader :value, :label, :reveal_label, :hide_label, :copy_label
end
end
AI agent rules #
Use for
- +secret key display with reveal/copy/regenerate
Avoid
- -storing secrets in plain text on the server side
Accessibility #
- Reveal/hide must be reachable by keyboard; copy via clipboard with announcement.