Picture by Andrew Neel | Unsplash

Demo: customized collection

Both the Attachment and Collection components can be customized. You can customize the CSS and even add extra fields.

The collection above will display files that are uploaded in this session. We'll delete any files that are older than 10 minutes. You can test out the component with any file under 1 Mb. We've configured this collection so it can hold a maximum of three files.

Source

<!-- Livewire and Blade -->
<x-media-library-collection
    name="downloads"
    :model="$formSubmission"
    collection="downloads"
    max-items="3"
    rules="mimes:png,jpeg"
    fields-view="uploads.blade.partials.fields"
/>
        
/* React */
<MediaLibraryCollection
    name="downloads"
    initialValue={downloads}
    maxItems={3}
    validationRules={{ accept: ['image/png', 'image/jpeg'], maxSizeInKB: 1024  }}
    validationErrors={{ errors }}
    fieldsView={({
        getCustomPropertyInputProps,
        getCustomPropertyInputErrors,
        getNameInputErrors,
        getNameInputProps,
    }) => (
        <div className="media-library-properties">
            <div className="media-library-field">
                <label className="media-library-label">Name</label>
                <input
                    className="media-library-input"
                    {...getNameInputProps()}
                />

                {getNameInputErrors().map(error => (
                    <p key={error} className="media-library-text-error">
                        {error}
                    </p>
                ))}
            </div>

            <div className="media-library-field">
                <label className="media-library-label">Extra field</label>
                <input
                    className="media-library-input"
                    {...getCustomPropertyInputProps('extra_field')}
                />

                {getCustomPropertyInputErrors('extra_field').map(error => (
                    <p key={error} className="media-library-text-error">
                        {error}
                    </p>
                ))}
            </div>
        </div>
    )}
/>
        
<!-- Vue -->
<media-library-collection
    name="downloads"
    :initial-value="{{ $downloads }}"
    :max-items="3"
    :validation-rules="{ accept: ['image/png', 'image/jpeg'], maxSizeInKB: 1024  }"
    :validation-errors="{{ $errors }}"
>
    <template
        slot="fields"
        slot-scope="{
            object,
            getCustomPropertyInputProps,
            getCustomPropertyInputListeners,
            getCustomPropertyInputErrors,
            getNameInputProps,
            getNameInputListeners,
            getNameInputErrors,
        }"
    >
        <!-- Vue 3 scoped slot: #fields="{ getCustomPropertyInputProps, … } -->
        <div class="media-library-properties">
            <div class="media-library-field">
                <label class="media-library-label">Name</label>
                <input
                    class="media-library-input"
                    v-bind="getNameInputProps()"
                    v-on="getNameInputListeners()"
                />
                <p v-for="error in getNameInputErrors()" :key="error" class="media-library-text-error">
                    {{ error }}
                </p>
            </div>

            <div class="media-library-field">
                <label class="media-library-label">Extra field</label>
                <input
                    class="media-library-input"
                    v-bind="getCustomPropertyInputProps('extra_field')"
                    v-on="getCustomPropertyInputListeners('extra_field')"
                />
                <p v-for="error in getCustomPropertyInputErrors('extra_field')" :key="error" class="media-library-text-error">
                    {{ error }}
                </p>
            </div>
        </div>
    </template>
</media-library-collection>