livewire / flux

The official Livewire UI component library
https://fluxui.dev
488 stars 42 forks source link

`disabled` not added to `flux:select variant="listbox"` on submit #725

Open jeffchown opened 2 days ago

jeffchown commented 2 days ago

When submitting a form, either a readonly or disabled attribute are added to controls (depending upon the control type). This stops the user from being able to edit the form during submit and allows us to style the controls for visual feedback.

A flux:select variant="listbox" doesn't seem to receive any such attribute upon submit - which means I can't style it, and also it is still active/editable during submit.

If you use the code below and inspect the different controls in the browser's devtools, you'll see the attributes being added (or not, in the case of the listbox) during the sleep(3) I added to the save() method.

To reproduce, add the following to your app.css:

input:read-only,
textarea:read-only,
input:disabled,
textarea:disabled,
select:disabled { @apply !bg-gray-50 dark:!bg-white/[7%] hover:cursor-not-allowed; }

button:disabled, fieldset:disabled button { @apply hover:cursor-not-allowed; }

Then, this Volt component shows a listbox next to a few other controls:

<?php

use Livewire\Volt\Component;

new class extends Component {
    public function save()
    {
        sleep(3);
    }
}; 
?>

<div>
    <form wire:submit="save" class="space-y-2">
        <flux:input label="Flux:input" />

        <flux:select placeholder="Choose industry" label="Native select">
            <flux:option>Photography</flux:option>
            <flux:option>Design services</flux:option>
            <flux:option>Web development</flux:option>
            <flux:option>Accounting</flux:option>
            <flux:option>Legal services</flux:option>
            <flux:option>Consulting</flux:option>
            <flux:option>Other</flux:option>
        </flux:select>

        <flux:select variant="listbox" placeholder="Choose industry" label="Listbox variant">
            <flux:option>Photography</flux:option>
            <flux:option>Design services</flux:option>
            <flux:option>Web development</flux:option>
            <flux:option>Accounting</flux:option>
            <flux:option>Legal services</flux:option>
            <flux:option>Consulting</flux:option>
            <flux:option>Other</flux:option>
        </flux:select>

        <flux:select variant="combobox" placeholder="Choose industry" label="Combobox variant">
            <flux:option>Photography</flux:option>
            <flux:option>Design services</flux:option>
            <flux:option>Web development</flux:option>
            <flux:option>Accounting</flux:option>
            <flux:option>Legal services</flux:option>
            <flux:option>Consulting</flux:option>
            <flux:option>Other</flux:option>
        </flux:select>

        <flux:button type="submit">Save</flux:button>
    </form>
</div>
tjgore commented 23 hours ago

The problem is that the flux:select variant="listbox" renders as <button type="button" ... />. Livewire does not add the readonly or disabled attribute to buttons with type="button". Based on the docs here, It adds the attributes to input fields and buttons with type="submit".

Ideally, the listbox should be handled similarly to other input fields when located in a form. This seems to be a Livewire concern rather than a flux component one. A workaround to this could be to use wire loading on the flux:select component as shown below.

 <flux:select variant="listbox" ... wire:loading.attr="disabled" wire:target="save">
  ...
</flux:select>

And update the css to target the listbox button when disabled.

button[aria-haspopup="listbox"]:disabled { @apply !bg-gray-50 dark:!bg-white/[7%] hover:cursor-not-allowed; }

I hope that fixes your issue.

The Livewire fix for this could be to check if a button within a form has the aria-haspopup="listbox" attribute and add disabled to the listbox field (button) while the form is being submitted.

jeffchown commented 23 hours ago

Nice, @tjgore !

I figured it had something to do with the button in the listbox, your workaround worked perfectly.

Thanks!

jeffchown commented 23 hours ago

I also think it would be a good idea if the disabled attribute was dynamically added to allui-selects (no matter what variant) on submit events, to be consistent with the native select.

That way the visual component of this issue could be handled with a variation of your suggested CSS that is closer to the CSS selectors used for native selects:

ui-select:disabled [data-flux-select-button] {
    @apply !bg-gray-50 dark:!bg-white/[7%] hover:cursor-not-allowed;
}

cc @calebporzio @joshhanley