🚨 You are viewing the legacy v1.x docs. See the new v2 documentation →
v1.5.5

Custom Inputs for @params

Lookbook ships with a number of pre-defined input types that are used when adding dynamic preview parameters to your previews.

However if you need an input type that isn’t provided by Lookbook (or want to override one of the existing ones) you can easily add your own and then reference them in your @param tags.

Adding a custom param input

To define a custom input you can do so using the Lookbook.define_param_input method when configuring your Lookbook installation:

Lookbook.define_param_input(<name>, <partial_path>, <opts?>)
<name>

A unique name for the input

Type: Symbol | String
<partial_path>

Path to the partial template used to render the input

Type: String
<opts>

Set of default options to be passed to the input. Any supplied param options will override these values.

Type: Hash

For example, to create a customised url input with a https:// prefix in front of it you could do the following:

# config/application.rb
Lookbook.define_param_input(:url, "inputs/url")
<!-- app/views/inputs/_url.html.erb -->
<div style="display: flex; align-items: center;">
  <strong>https://</strong>
  <div style="padding-left: 6px">
    <%= text_field_tag(name, value,
        **input_options,
        type: "url",
        "x-model": "value"
      ) %>
  </div>
</div>

This input field will then be rendered when using the url input type in @param tags:

class IframeComponentPreview < ViewComponent::Preview
  # @param src url
  def default(src: 'example.com')
    render IframeComponent.new(src: src)
  end
end

Template variables

The following local variables are available to input partial templates:

name

The name of the param this input should update.

<input name="<% name %>" />

value

The current value of the param.

<input value="<% value %>" />

input

The input type currently being rendered

<input type="<% input %>" />

input_options

Hash of options specified by the @param tag. Generally expected to be passed to a tag helper to be turned into a set of HTML attributes on the input, where appropriate.

<%= text_field_tag(name, value, **input_options) %>

choices

Array of selection options specified by the @param tag, if available.

<%= select_tag(name, options_for_select(choices, value)) %>

Handling updates

Lookbook uses AlpineJS under the hood for all JavaScript interactions.

Custom input templates are automatically wrapped up as an Alpine component that takes care of handling updates to the preview when it’s value property changes.

To bind the value of an input to the Alpine component’s value property you can add an x-model attribute to the input, like so:

<input x-model="value">

Any changes to the input value will then automatically update the preview and the URL.

To ensure that the preview does not get refreshed too often you may wish to throttle or debounce changes using a modifier:

<input x-model.debounce.300ms="value">

See the Alpine documentation on the x-model directive for full details of all available modifiers.

This technique will work for most types of <input> elements, plus <textarea> <select> elements.

Manually triggering an update

If your custom input does not use a standard input element, you will need to manually update the Alpine component’s value property.

This could be done in an @click handler or however makes sense for the input you are building.

<button @click="value = 'YES'">Set to YES</button>

See the Alpine documentation on event handling for details on listening and responding to events.

Styling inputs

If you wish to specify custom CSS rules to style the contents of the input partial, just include a <style> element in the template:

<style>
  input {
    border: 1px solid hotpink;
  }
</style>

<input type="text"> <!-- will have a hotpink border -->

The <style> element will be removed when the input is rendered and any styles will be automagically scoped to the input partial that they are defined in, so they will not affect other inputs or leak out to affect the styling of the UI in general.