From 22e8d87f92f3d22473b5788115d677c23f1d54b8 Mon Sep 17 00:00:00 2001 From: Andreas Pfohl Date: Thu, 9 Nov 2023 10:32:43 +0100 Subject: [PATCH] Added "width" attribute to inputs - TextField - Select --- .changeset/added-width-to-inputs.md | 10 ++++++++ .gitignore | 3 +++ app/components/primer/alpha/text_field.pcss | 27 ++++++++++++++++++++ app/forms/custom_width_fields_form.rb | 28 +++++++++++++++++++++ lib/primer/forms/dsl/input.rb | 16 ++++++++++++ lib/primer/forms/select.rb | 5 +++- lib/primer/forms/text_field.rb | 1 + previews/primer/alpha/select_preview.rb | 7 ++++-- previews/primer/alpha/text_field_preview.rb | 7 ++++-- 9 files changed, 99 insertions(+), 5 deletions(-) create mode 100644 .changeset/added-width-to-inputs.md create mode 100644 app/forms/custom_width_fields_form.rb diff --git a/.changeset/added-width-to-inputs.md b/.changeset/added-width-to-inputs.md new file mode 100644 index 0000000000..949e894265 --- /dev/null +++ b/.changeset/added-width-to-inputs.md @@ -0,0 +1,10 @@ +--- +'@openproject/primer-view-components': minor +--- + +Added a "width" attribute to control how wide an input is rendered on screen. + +It is active for: + +- TextField +- Select diff --git a/.gitignore b/.gitignore index f48032404c..3505ad1055 100644 --- a/.gitignore +++ b/.gitignore @@ -48,3 +48,6 @@ tmp/ # Simplecov folder coverage/ demo/public/assets/ + +# IDE folders +.idea diff --git a/app/components/primer/alpha/text_field.pcss b/app/components/primer/alpha/text_field.pcss index 49d622d36a..42c7fce38e 100644 --- a/app/components/primer/alpha/text_field.pcss +++ b/app/components/primer/alpha/text_field.pcss @@ -216,11 +216,36 @@ gap: var(--base-size-16); } +/* widths */ +@define-mixin FormControl-input-width { + &.FormControl-xlarge { + width: 96rem; + } + + &.FormControl-large { + width: 72rem; + } + + &.FormControl-medium { + width: 48rem; + } + + &.FormControl-narrow { + width: 32rem; + } + + &.FormControl-small { + width: 16rem; + } +} + /* positioning for leading/trailing items for TextInput */ .FormControl-input-wrap { position: relative; display: grid; + @mixin FormControl-input-width; + & .FormControl-input-leadingVisualWrap { position: absolute; top: var(--base-size-8); @@ -479,6 +504,8 @@ display: grid; grid-template-columns: minmax(0, auto) var(--base-size-16); + @mixin FormControl-input-width; + /* mask allows for background-color to respect themes */ &::after { width: var(--base-size-16); diff --git a/app/forms/custom_width_fields_form.rb b/app/forms/custom_width_fields_form.rb new file mode 100644 index 0000000000..9ed09563cd --- /dev/null +++ b/app/forms/custom_width_fields_form.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +# :nodoc: +class CustomWidthFieldsForm < ApplicationForm + form do |my_form| + my_form.text_field( + name: :ultimate_answer, + label: "Ultimate answer", + required: true, + caption: "The answer to life, the universe, and everything", + width: :narrow + ) + + form do |select_form| + select_form.select_list( + name: "cities", + label: "Cool cities", + caption: "Select your favorite!", + include_blank: true, + width: :medium + ) do |city_list| + city_list.option(label: "Lopez Island", value: "lopez_island") + city_list.option(label: "Bellevue", value: "bellevue") + city_list.option(label: "Seattle", value: "seattle") + end + end + end +end diff --git a/lib/primer/forms/dsl/input.rb b/lib/primer/forms/dsl/input.rb index d357b5f7aa..79e69237e2 100644 --- a/lib/primer/forms/dsl/input.rb +++ b/lib/primer/forms/dsl/input.rb @@ -45,6 +45,14 @@ class Input }.freeze SIZE_OPTIONS = SIZE_MAPPINGS.keys + WIDTH_MAPPINGS = { + :small => "FormControl-small", + :narrow => "FormControl-narrow", + :medium => "FormControl-medium", + :large => "FormControl-large", + :xlarge => "FormControl-xlarge" + }.freeze + include Primer::ClassNameHelper attr_reader :builder, :form, :input_arguments, :label_arguments, :caption, :validation_message, :ids, :form_control, :base_id @@ -73,6 +81,7 @@ def initialize(builder:, form:, **system_arguments) @invalid = @input_arguments.delete(:invalid) @full_width = @input_arguments.delete(:full_width) @size = @input_arguments.delete(:size) + @width = @input_arguments.delete(:width) # If scope_name_to_model is false, the name of the input for eg. `my_field` # will be `my_field` instead of the Rails default of `model[my_field]`. @@ -152,6 +161,7 @@ def add_input_data(key, value) def remove_input_data(key) input_data.delete(key) end + # :nocov: def merge_input_arguments!(arguments) @@ -226,6 +236,10 @@ def size @size ||= SIZE_MAPPINGS.include?(@size) ? @size : DEFAULT_SIZE end + def width + @width ||= WIDTH_MAPPINGS.include?(@width) ? @width : nil + end + def validation_messages @validation_messages ||= if validation_message @@ -257,6 +271,7 @@ def type def to_component raise_for_abstract_method!(__method__) end + # :nocov: def focusable? @@ -309,6 +324,7 @@ def aria_join(*values) def raise_for_abstract_method!(method_name) raise NotImplementedError, "subclasses must implement ##{method_name}." end + # :nocov: end end diff --git a/lib/primer/forms/select.rb b/lib/primer/forms/select.rb index 6c76a789f1..4b1b31b421 100644 --- a/lib/primer/forms/select.rb +++ b/lib/primer/forms/select.rb @@ -14,7 +14,10 @@ def initialize(input:) ) @field_wrap_arguments = { - class: "FormControl-select-wrap", + class: class_names( + "FormControl-select-wrap", + Primer::Forms::Dsl::Input::WIDTH_MAPPINGS[@input.width] + ), hidden: @input.hidden? } end diff --git a/lib/primer/forms/text_field.rb b/lib/primer/forms/text_field.rb index 1840f92434..8cec9fcf74 100644 --- a/lib/primer/forms/text_field.rb +++ b/lib/primer/forms/text_field.rb @@ -23,6 +23,7 @@ def initialize(input:) class: class_names( "FormControl-input-wrap", INPUT_WRAP_SIZE[input.size], + Primer::Forms::Dsl::Input::WIDTH_MAPPINGS[@input.width], "FormControl-input-wrap--trailingAction": @input.show_clear_button?, "FormControl-input-wrap--leadingVisual": @input.leading_visual? ), diff --git a/previews/primer/alpha/select_preview.rb b/previews/primer/alpha/select_preview.rb index 99f289b834..31d4a65884 100644 --- a/previews/primer/alpha/select_preview.rb +++ b/previews/primer/alpha/select_preview.rb @@ -17,6 +17,7 @@ class SelectPreview < ViewComponent::Preview # @param disabled toggle # @param invalid toggle # @param validation_message text + # @param width [Symbol] select [nil, small, narrow, medium, large, xlarge] def playground( name: "my-select-list", id: "my-select-list", @@ -28,7 +29,8 @@ def playground( full_width: false, disabled: false, invalid: false, - validation_message: nil + validation_message: nil, + width: nil ) system_arguments = { name: name, @@ -41,7 +43,8 @@ def playground( full_width: full_width, disabled: disabled, invalid: invalid, - validation_message: validation_message + validation_message: validation_message, + width: width } render(Primer::Alpha::Select.new(**system_arguments)) do |component| diff --git a/previews/primer/alpha/text_field_preview.rb b/previews/primer/alpha/text_field_preview.rb index 7fd6836bda..2142af8021 100644 --- a/previews/primer/alpha/text_field_preview.rb +++ b/previews/primer/alpha/text_field_preview.rb @@ -23,6 +23,7 @@ class TextFieldPreview < ViewComponent::Preview # @param inset toggle # @param monospace toggle # @param leading_visual_icon octicon + # @param width [Symbol] select [nil, small, narrow, medium, large, xlarge] def playground( name: "my-text-field", id: "my-text-field", @@ -40,7 +41,8 @@ def playground( placeholder: nil, inset: false, monospace: false, - leading_visual_icon: nil + leading_visual_icon: nil, + width: nil ) system_arguments = { name: name, @@ -58,7 +60,8 @@ def playground( validation_message: validation_message, placeholder: placeholder, inset: inset, - monospace: monospace + monospace: monospace, + width: width } if leading_visual_icon