Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Form Components #62

Open
wants to merge 31 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
5ccad1f
initial set of form components. See COMPONENTS.md
richmarisa Dec 19, 2023
d03725c
components and docs updates
richmarisa Dec 21, 2023
fe7834e
forgot no-margin in radios
richmarisa Dec 21, 2023
35f143b
update doc file
richmarisa Dec 21, 2023
15c55d5
fix attribute arguments in COMPONENTS.md
richmarisa Dec 21, 2023
1b5f344
Merge branch 'main' into components
richmarisa Dec 21, 2023
c2b55a0
update handling of required attribute
richmarisa Dec 22, 2023
bd54ded
rename COMPONENTS.md to FORM_COMPONENTS
richmarisa Dec 22, 2023
10f16e0
include a link to FORM_COMPONENTS.md in README.md
richmarisa Dec 22, 2023
cdf88a0
Merge branch 'components' of https://github.com/CU-CommunityApps/CD-L…
richmarisa Dec 22, 2023
cd72c27
account for required parameter missing
richmarisa Jan 4, 2024
ee181a7
Modal Dialog support and doc file
richmarisa Jan 9, 2024
a27a422
component updates
richmarisa Feb 5, 2024
b485975
update README for form components
richmarisa Feb 5, 2024
8950492
fix description in checkbox
richmarisa Feb 5, 2024
91ed3b7
output field_title as raw
richmarisa Feb 5, 2024
0e0f130
some updates for checkboxes
richmarisa Feb 6, 2024
0fd4407
Update resources/views/components/cd/form/checkbox.blade.php
richmarisa Feb 8, 2024
c511aac
Update resources/views/components/cd/form/form-item.blade.php
richmarisa Mar 28, 2024
144e8a8
remove unneeded divs
richmarisa Apr 2, 2024
a7b77a0
merge changes in form-item
richmarisa Apr 2, 2024
f80c3d5
update livewire version
richmarisa Apr 2, 2024
b072093
move dialog script and update documentation
richmarisa Apr 2, 2024
d69cca8
Update resources/views/components/cd/form/checkbox-inline.blade.php
richmarisa Apr 3, 2024
6aea959
behavior of Livewire 3 checkboxes
richmarisa Apr 4, 2024
e588f38
Merge branch 'components' of https://github.com/CU-CommunityApps/CD-L…
richmarisa Apr 4, 2024
c60f74d
use wire:model.live in README
richmarisa Apr 4, 2024
05659cd
Update resources/views/components/cd/form/select.blade.php
richmarisa Apr 5, 2024
8a425cc
rename components to kebab case
richmarisa Apr 5, 2024
3b7d469
Merge branch 'components' of https://github.com/CU-CommunityApps/CD-L…
richmarisa Apr 5, 2024
a30806a
Document inline radio buttons
richmarisa Apr 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,12 @@ The libraries included in the Starter Kit are documented in their respective REA

- [Contact/PhoneNumber](src/Contact/README.md): A library for parsing and formatting a phone number.

## Components

Blade components included in the Starter Kit are documented in their respective files:

- [Form Components](resources/views/components/cd/form/README.md): A set of Blade components for creating form components styled with the CSS Framework.
- [Dialog Components](resources/views/components/cd/dialog/README.md): A set of Blade components for creating modal dialogs.

## Deploying a site
Once a Media3 site has been created, you have confirmed you can reach the default site via a web browser, and you have access to the site login by command line, the code can be deployed.
Expand Down
47 changes: 47 additions & 0 deletions resources/views/components/cd/dialog/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# DIALOG

NOTE: you must add the component
```
<x-cd.component-scripts />
```
to the head element of the page before using the `cd.dialog` component.

The modal dialog component is used as follows:

```
<x-cd.dialog>
<x-cd.dialog.button>
<x-cd.form.submitbutton value="Open Modal"/>
</x-cd.dialog.button>
<x-cd.dialog.panel>
<div>
<h2>This is my modal</h2>
<p>Isn't it great?</p>
</div>
</x-cd.dialog.panel>
</x-cd.dialog>

```

You can use any markup in `<x-cd.dialog.button>`, e.g., a button, link, etc. The click handler is already included in `cd-dialog.button`, so clicking on your element will open the dialog.

If you would like to open the dialog from a Livewire component, add a `wire:model` atribute to the `<x-cd.dialog>` tag, like the following:

```
<x-cd-dialog wire:model="dialogFlag">
....
</x-cd-dialog>
```

When dialogFlag (or whatever property you use) becomes true, the dialog will open.

Any content you include in `<x-cd.dialog.panel>` will be displayed in the dialog when it opens.

The modal dialog has a close button in the upper right corner. You can add a close button to your panel content by including

```
<x-cd.dialog.close-button value="Close" />
```



3 changes: 3 additions & 0 deletions resources/views/components/cd/dialog/button.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<span x-on:click="dialogOpen = true">
{{ $slot }}
</span>
3 changes: 3 additions & 0 deletions resources/views/components/cd/dialog/close-button.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<span x-on:click="dialogOpen = false">
{{ $slot }}
</span>
3 changes: 3 additions & 0 deletions resources/views/components/cd/dialog/index.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div x-data="{ dialogOpen: false }" x-modelable="dialogOpen" {{$attributes}}>
{{ $slot }}
</div>
70 changes: 70 additions & 0 deletions resources/views/components/cd/dialog/panel.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<div
x-dialog
x-model="dialogOpen"
style="display: none;
position:fixed;
top: 0; right: 0; bottom: 0; left: 0;
overflow-y:auto;
z-index: 10"
{{-- tailwindclass="fixed inset-0 overflow-y-auto z-10" --}}
>
<div>In panel, open is <span x-text="open"></span></div>
<!-- Overlay -->
<div x-dialog:overlay x-transition.opacity
style="position:fixed;
top: 0; right: 0; bottom: 0; left: 0;
--bg-opacity: 1;
background-color: #000;
background-color: rgba(0, 0, 0, .25);"
{{-- tailwindclass="fixed inset-0 bg-black/25" --}}

></div>

<!-- Panel -->
<div
{{-- tailwindclass="relative min-h-screen flex items-center justify-center p-4" --}}
style="position:relative; min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 1rem;"
>
<div
x-dialog:panel
x-transition.in x-transition.out.opacity
{{-- tailwindclass="relative max-w-2xl w-full bg-white rounded-xl shadow-lg overflow-y-auto" --}}
style="position: relative; max-width: 42rem; width: 100%;
--bg-opacity: 1; background-color: #fff; background-color: rgba(255,255,255,var(--bg-opacity));
border-radius: 0.75rem;
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
overflow-y: auto;"
>
<!-- Close Button -->
<div
{{-- tailwindclass="absolute top-0 right-0 pt-4 pr-4" --}}
style="position:absolute; top: 0; right: 0; padding-top: 1rem; padding-right: 1rem;"
>
<button type="button" @click="$dialog.close()"
{{-- tailwindclass="bg-gray-50 rounded-lg p-2 text-gray-600 focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2" --}}
style="--bg-opacity: 1;
background-color: #a0aec0;
background-color: rgba(160, 174, 192, var(--bg-opacity));
border-radius: 0.5rem;
padding: 0.5rem;
--text-opacity: 1;
color: #718096;
color: rgba(113, 128, 150, var(--text-opacity));"
>
<span class="sr-only">Close modal</span>
<svg xmlns="http://www.w3.org/2000/svg" tailwindclass="h-4 w-4" style="height: 1rem; width: 1 rem;" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd" />
</svg>
</button>
</div>

<!-- Panel -->
<div
{{-- tailwindclass="p-8" --}}
style="padding: 2rem;"
>
{{ $slot }}
</div>
</div>
</div>
</div>
165 changes: 165 additions & 0 deletions resources/views/components/cd/form/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
# Form Components

A set of form components provides support the the styled form elements in the CD Framework.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
A set of form components provides support the the styled form elements in the CD Framework.
A set of form components provides support for the styled form elements in the CD Framework.

Typo


## Form

The form component creates the required fieldset and legend.

Use wire:submit on the form component rather than wire:click on the submit button to maintain the
expected behavior of submitting the form if the user hits enter in a text element.

Here is an example of a simple form:

```
<x-cd.form.form legend="Simple form" wire:submit="submit">
<x-cd.form.text label="Name" wire:model="name"/>
<div>
<x-cd.form.submitbutton/>
<x-cd.form.resetbutton/>
</div>
</x-cd.form.form>
```

## Form elements

The `name` and `id` attributes on the form inputs default to the same value as
that used in the `wire:model` attribute. You may supply different values for `name` and `id `.
Inputs are not required by default; you can supply the `:required="true"` attribute if the input
should be required for your form.

Use the `description` attribute to provide additional instruction or formatting hints. The description text is displayed below the input. The component will add an `aria-describedby` attribute to the input to associate the description text with the input.

## Text

The `placeholder` attribute can be used on text inputs.

To adjust the width of the text input, use the `size` attribute and add the class `use-size-attr`.

Example:
```
<x-cd.form.text label="Text Input" wire:model="name"/>
```
## Select

The select form input requires an array of options.
The options and the component call are demonstrated below. The required attribute is optional.
Making the first option disabled gives it the function of placeholder text.

```
$this->roleoptions = [
[ 'value'=>'', 'option'=>'Select a Role', 'disabled'=>true],
[ 'value'=>'administrator', 'option'=>'Administrator', 'disabled'=>false],
[ 'value'=>'editor', 'option'=>'Editor', 'disabled'=>false],
[ 'value'=>'subscriber', 'option'=>'Subscriber', 'disabled'=>false],
];
```

```
<x-cd.form.select :options="$roleoptions" required="1" label="Select" wire:model="role" />
```
You may add the attribute `multiple="multiple"` to create a multiselect. Multiselect with groups are not yet supported.

## Checkbox

The checkbox component implements a single checkbox (see Checkboxes for multiple checkboxes).
The checkbox component needs a value to return when the box is checked. The checkbox-inline variant places the label next to the checkbox input rather than above it.

Note: single checkboxes cannot be required.

```
<x-cd.form.checkbox label="Subscription" text="Subscribe" value="1" wire:model="subscribe" />
```

```
<x-cd.form.checkbox-inline name="inline" value="1" label="Select me" description="description" wire:model="subscribe"/>
```
## Checkboxes

The checkboxes component implements a set of related checkboxes which are bound to one Livewire variable.
An array of options define the set of checkboxes as demonstrated here.

```
$this->checkboxoptions = [
[ 'value' => "tomato", "label" => "Tomato"],
[ 'value' => "lettuce", "label" => "Lettuce"],
[ 'value' => "pickle", "label" => "Pickle"],
[ 'value' => "onion", "label" => "Onion"],
];
richmarisa marked this conversation as resolved.
Show resolved Hide resolved
```

```
<x-cd.form.checkboxes :checkboxes="$checkboxoptions" wire:model="toppings" label="Topping Choices"/>
```

## Special text inputs

The CD Framework provides styling for several special-purpose text inputs. These may be selected
using the `type` attribute, as in the following examples:


```
<x-cd.form.text type="search" label="Search" wire:model="search"/>
<x-cd.form.text type="telephone" label="Telephone" wire:model="telephone"/>
<x-cd.form.text type="url" label="URL" wire:model="url"/>
<x-cd.form.text type="email" label="Email" wire:model="email"/>
<x-cd.form.text type="password" label="Password" wire:model="password"/>
<x-cd.form.text type="number" label="Number" wire:model="number"/>
<x-cd.form.text type="datetime" label="Datetime" wire:model="datetime"/>
<x-cd.form.text type="datetimelocal" label="Datetime Local" wire:model="datetimelocal"/>
<x-cd.form.text type="date" label="Date" wire:model="date"/>
<x-cd.form.text type="month" label="Month" wire:model="month"/>
<x-cd.form.text type="week" label="Week" wire:model="week"/>
<x-cd.form.text type="time" label="Time" wire:model="time"/>
```
## Range

A range input rendered as a slider may be specified using this special text input which requires
`max` and `min` attributes.

```
<x-cd.form.text type="range" required="1" label="Range" min="1" max="10" wire:model="range"/>
```

## File

The file selector input is also a variant of the text input.
```
<x-cd.form.text type="file" required="1" label="File" wire:model="file"/>
```

## Color

The color picker is also a variant of the text input. Take care to initialize the value of this
input to a valid `value`, which is a hash (#) character followed by six hexadecimal digits.
```
<x-cd.form.text type="color" label="Color" wire:model="color" value="#ff0000"/>
```

# Radio Buttons

The `radios` component implements a set of related radio buttons defined by an array of options, as demonstrated below.</p>

```
<x-cd.form.radios label="Radios" wire:model="radios" :radiobuttons="$radiooptions" />
```

# Submit, Reset and Cancel Buttons

Components are provided for the submit and reset buttons often used in forms. Since the submit button will cause
the form to call the `wire:submit` function specified in the form element, no `wire:click` is required in that element.

The reset button will clear the form.

The cancel button requires a `wire:click` or `x-on:click` attribute to specify the action which should be
taken when the button is pressed.

```
<x-cd.form.submitbutton />
<x-cd.form.resetbutton />
<x-cd.form.cancelbutton wire:click"closemodal">
woodseowl marked this conversation as resolved.
Show resolved Hide resolved
```




3 changes: 3 additions & 0 deletions resources/views/components/cd/form/cancelbutton.blade.php
richmarisa marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<span>
<input type="button" class="button js-form-submit form-submit" value="{{$value??"Cancel"}}" {{$attributes}}/>
</span>
19 changes: 19 additions & 0 deletions resources/views/components/cd/form/checkbox-inline.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
@php
$field = $name ?? $attributes->whereStartsWith('wire:model')->first();
@endphp
<div class="form-item">
<input type="checkbox" id="{{ $id ?? $field }}"
name="{{ $field }}"
value="{{ $value }}"
{{ $attributes->whereStartsWith('wire:model') }}
{{ $attributes->whereStartsWith('aria') }}
{{ $attributes->whereStartsWith('checked') }}
@if (!empty($description))
aria-describedby="{{ $field }}_desc"
@endif
/>
<label class="option-label" id="{{$field}}_desc">{{$label}}</label>
@if (!empty($description))
<div class="description">{{$description}}</div>
@endif
richmarisa marked this conversation as resolved.
Show resolved Hide resolved
</div>
23 changes: 23 additions & 0 deletions resources/views/components/cd/form/checkbox.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<x-cd.form.form-item field="{{ $name ?? $attributes->whereStartsWith('wire:model')->first() }}"
classes="{{ $classes ?? '' }}"
required="false"
richmarisa marked this conversation as resolved.
Show resolved Hide resolved
:description="$description??''"
>
@php
$field = $name ?? $attributes->whereStartsWith('wire:model')->first();
@endphp
<x-slot name="field_title">{!! $label !!}</x-slot>
<div class="form-item">
richmarisa marked this conversation as resolved.
Show resolved Hide resolved
<input type="checkbox" id="{{ $id ?? $field }}"
name="{{ $field }}"
value="{{ $value }}"
{{ $attributes->whereStartsWith('wire:model') }}
{{ $attributes->whereStartsWith('aria') }}
{{ $attributes->whereStartsWith('checked') }}
@if (!empty($description))
aria-describedby="{{ $field }}_desc"
@endif
/>
<span class="option-label" for="{{$field}}">{!!$text??''!!}</span>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<span class="option-label" for="{{$field}}">{!!$text??''!!}</span>
<span class="option-label">{!! $text ?? $slot !!}</span>

Two suggestions here:

  • Remove the "for", because this is not a <label> tag and the attribute has no meaning
  • Supplement $text with $slot. I think in this layout this content is probably required, so taking advantage of the slot style seems like a nice implementation to me. But it's just an idea.

Regardless of whether you want to use text or slot, it needs to be documented in the README example, because I only found it when I couldn't figure out why my checkbox didn't show anything.

</div>
</x-cd.form.form-item>
24 changes: 24 additions & 0 deletions resources/views/components/cd/form/checkboxes.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<x-cd.form.form-item field="{{ $name ?? $attributes->whereStartsWith('wire:model')->first() }}"
classes="{{ $classes ?? '' }}"
required="{{ (($required??'') === 'false') ? 0 : (boolval($required??'')?1:0) }}"
:description="$description ?? ''"
>
Comment on lines +1 to +5
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this usage of form-item for the checkboxes is creating more problems than it is solving, but I don't see a simple solution. Here are the issues when I try to create a list of checkboxes like the CSSF example:

  • It nests the checkboxes as form-items inside a single form item
  • It adds a label, but there is no element with the id it says it's for
  • If a description is provided, it's placed after the list, which seems unlikely as a typical design pattern

I think the CSSF example would suggest just removing this wrapper entirely. But we lose the "required" feature and the automatic wiring for the description. It's easy enough to pull the description code up to this component. Not sure what to do for labeling and requiredness, though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think other changes fix the form-items nesting; the trailing description is for consistency with other components. If you don't specify it, it doesn't appear. To fix the label issue, I think we need a div with the same styling as the label; I'll work on that.

@php
$field=$name ?? $attributes->whereStartsWith('wire:model')->first();
@endphp
<x-slot name="field_title">{!! $label !!}</x-slot>
<div class="flex-grid compact-rows">
Comment on lines +9 to +10
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What would you think of putting $slot between these:

Suggested change
<x-slot name="field_title">{!! $label !!}</x-slot>
<div class="flex-grid compact-rows">
<x-slot name="field_title">{!! $label !!}</x-slot>
{!! $slot !!}
<div class="flex-grid compact-rows">

That would make it possible to include content between the heading and the options, like in the "A Plethora of Checkboxes" example

@foreach ($checkboxes as $cb)
<div class="form-item">
<input type="checkbox" id="{{$field}}-{{$loop->index}}" name="{{ $field }}" value="{{ $cb['value']}}"
{{ $attributes->whereStartsWith('wire:model') }}
{{ $attributes->whereStartsWIth('aria') }}
@if (!empty($description))
aria-describedby="{{ $field }}_desc"
@endif
>
richmarisa marked this conversation as resolved.
Show resolved Hide resolved
<label class="option-label" for="{{$field}}-{{$loop->index}}">{{$cb["label"]}}</label>
</div>
@endforeach
</div>
</x-cd.form.form-item>
Loading
Loading