jb-image-input
v4.2.0
Published
image input web component
Maintainers
Readme
jb-image-input
Image input web component that lets the user select an image, preview it, and validate it.
- Supports custom placeholder and overlay slots.
- Supports required and max file size validation through
jb-validation.
When to use
Use jb-image-input when the user must select an image and see an image preview inside the JB Design System UI. The basic setup is shown in the normal image input demo.
Use jb-file-input for non-image files or when previewing the selected file as an image is not required.
Demo
Using With JS Frameworks
See the React documentation.
Other integrations: Angular · Vue · Nuxt · Svelte · SvelteKit · SolidJS · Lit · Next.js · Astro · Blazor · Server-rendered templates · WordPress · Alpine.js and HTMX
Installation
npm i jb-image-inputimport 'jb-image-input';<jb-image-input label="Profile image"></jb-image-input>API reference
Attributes
| name | type | default | description |
| --- | --- | --- | --- |
| name | string | "" | Form field name returned by the name property. Demo |
| label | string | localized text | Placeholder title text and accessible aria label. Demo |
| message | string | "" | Helper text shown in the placeholder message area and exposed as aria description. Demo |
| required | boolean \| string | false | Enables required validation. A string value is used as the required error message. See required validation and the required message demo. |
| multiple | boolean | false | Lets the hidden native file input accept multiple files. The component still previews the first file. See multi image selector and the multiple selection demo. |
| accept | string | common image types | Native file accept string forwarded to the hidden file input. Demo |
| is-uploading | boolean | false | Shows externally controlled upload loading state. |
| disabled | boolean | false | Disables file selection and overlay actions. Demo |
Properties
| name | type | readonly | description |
| --- | --- | --- | --- |
| value | TValue \| null | no | Canonical value and form value. Selecting an image sets this to the selected File. Setting another value calls the optional downloader, or automatically loads a string URL. Demo |
| file | File \| null | yes | Currently selected local file. Demo |
| imageBase64Value | string \| null | no | Preview image data URL after the selected file is read or downloader resolves. Demo |
| accept | string | no | Native file accept string forwarded to the hidden file input. Demo |
| maxFileSize | number \| null | no | Maximum accepted file size in bytes. See max file size and the max-size demo. |
| downloader | JBImageInputDownloader<TValue> | no | Optional function used to turn a stored value into a preview image. |
| uploadPercent | number \| null | no | Visual upload progress percentage controlled by your upload flow. |
| config | JBImageInputConfig | no | Developer-defined object passed to downloader. Demo |
| multiple | boolean | no | Controls the hidden native file input multiple attribute. Demo |
| required | boolean | no | Enables required validation. Demo |
| disabled | boolean | no | Disables file selection and overlay actions, and sets disabled accessibility/custom state. Demo |
| isUploading | boolean | no | Shows externally managed upload loading state. |
| isLoading | boolean | yes | Computed aggregate loading state. |
| status | 'empty' \| 'uploading' \| 'uploaded' \| 'downloaded' \| null | yes | Current visual state. Demo |
| form | HTMLFormElement \| null | yes | Associated form from ElementInternals. |
| selectedImageType | string \| undefined | yes | MIME type of the selected file, or undefined before a file is selected. |
| validation | ValidationHelper<ValidationValue<TValue>> | yes | Validation helper from jb-validation; set validation.list for custom rules. Demo |
| validationMessage | string | yes | Current native validation message from ElementInternals. Demo |
| initialValue | TValue \| null | no | Default and reset value. It initializes value until the live value is explicitly set. |
| isDirty | boolean | yes | true when current value differs from initialValue. Demo |
Methods
| name | returns | description |
| --- | --- | --- |
| openImageSelector() | void | Opens the hidden native file picker unless the component is disabled. Demo |
| reset() | void | Restores initialValue and clears displayed validation. |
| selectImageByFile(file) | Promise<void> | Injects a File as if the user selected it, validates it, previews it, and dispatches change when valid. Demo |
| checkValidity() | boolean | Runs validation without showing the error message. Dispatches invalid when invalid. Demo |
| reportValidity() | boolean | Runs validation and shows the first error message. Dispatches invalid when invalid. Demo |
| JBImageInputWebComponent.ExtractBase64ImageFromFile(file) | Promise<string> | Static helper that reads a File and resolves its data URL. Demo |
Events
| event | detail | description |
| --- | --- | --- |
| change | none | Fired when a file is selected or the selected image is deleted. Uploading is handled by the application. Demo |
| download-start | { value: TValue } | Cancelable event fired before a non-File value is converted to a preview. Prevent it when your application handles preview loading itself. |
| image-selected | { files: FileList } | Fired after the hidden native file input changes. Use this for multi-image flows. Demo |
| max-size-exceed | { file: File } | Fired when the selected file is larger than maxFileSize. Demo |
| invalid | none | Fired when checkValidity() or reportValidity() finds an invalid value. Demo |
Value, file, and preview
file is the selected local File. The initial value demo shows how the local file, current value, initial value, and dirty state relate.
value is the value your app stores and the value passed to ElementInternals.setFormValue(). Selecting an image sets value to the selected File; upload the file in your change handler and assign any returned application value yourself.
For native form submission, keep the value compatible with setFormValue: File, string, FormData, or null. If your API returns an object, store a string id/URL for form submission or serialize the object before assigning it as value.
When you set value programmatically:
- If
valueis aFile, the component reads it and shows a preview. - If
valueis not aFile, the component dispatchesdownload-start. If it is not canceled, it callsdownloader(value, config)when configured, or fetches string URL values itself.
Upload and download behavior
jb-image-input does not own your upload request. Listen for change, upload event.target.value yourself, and set isUploading/uploadPercent while the request is in progress. The optional downloader handles stored values that need custom preview conversion.
The default delete action uses jb-icon-delete; its lid animation plays while the delete control is hovered.
const imageInput = document.querySelector('jb-image-input');
imageInput.downloader = (value, config) => {
return fetch(value)
.then((response) => response.blob())
.then((blob) => new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result);
reader.onerror = reject;
reader.readAsDataURL(blob);
}));
};| downloader argument | description |
| --- | --- |
| file | The File value selected by the user. |
| config | Developer-defined config object stored on the component and passed to downloader. |
| value | Current component value passed to downloader; commonly an id or URL. |
Validation
jb-image-input uses jb-validation. Built-in validation covers required and maxFileSize; custom validations can be added with validation.list. See the required validation demo and max-size demo.
const imageInput = document.querySelector('jb-image-input');
imageInput.validation.list = [
{
validator: ({ file }) => !file || file.size < 500 * 1024,
message: 'Image must be smaller than 500KB',
},
];
const isValid = imageInput.reportValidity();Required validation
<jb-image-input required></jb-image-input>
<jb-image-input required="Please select an image"></jb-image-input>Max file size
Set maxFileSize in bytes; the max-size demo shows the rejection event:
const imageInput = document.querySelector('jb-image-input');
imageInput.maxFileSize = 2 * 1024 * 1024;
imageInput.addEventListener('max-size-exceed', (event) => {
alert(`Selected image is ${event.detail.file.size} bytes`);
});Multi image selector
jb-image-input previews and uploads one image. To build a multi-image UI, set multiple, listen to image-selected, render one component per extra file, and call selectImageByFile(file) on each new component. The multiple selection demo shows the native input configuration.
<jb-image-input multiple="true"></jb-image-input>const imageInputs = document.querySelector('#image-inputs');
const firstInput = imageInputs.querySelector('jb-image-input');
firstInput.addEventListener('image-selected', (event) => {
const [, ...extraFiles] = Array.from(event.detail.files);
extraFiles.forEach((file) => {
const input = document.createElement('jb-image-input');
imageInputs.appendChild(input);
input.selectImageByFile(file);
});
});Image accept type
Set accept to constrain the native file picker; the multiple selection demo shows the accepted MIME types.
document.querySelector('jb-image-input').accept = 'image/jpeg,image/jpg,image/png,image/svg+xml';Slots
Use the custom placeholder demo to see the placeholder slot in context.
| slot | description |
| --- | --- |
| placeholder | Custom content shown while the component status is empty. |
| overlay | Replaces the full image overlay shown over the preview image. |
| overlay-content | Replaces the default overlay controls while keeping the default overlay container. |
<jb-image-input label="Profile image">
<div slot="placeholder">
Select profile image
</div>
</jb-image-input>CSS parts and states
| part | description |
| --- | --- |
| message | Helper or validation message inside the default placeholder. |
| custom state | description |
| --- | --- |
| disabled | Applied when disabled is true. |
jb-image-input::part(message) {
font-weight: 600;
}
jb-image-input:state(disabled) {
opacity: 0.5;
}Custom style
Set CSS variables in the parent scope of the component.
For complete styling guidance, live examples, official parts and states, and the full CSS variable reference, see Styling or the style gallery.
jb-image-input.avatar-input {
--jb-image-input-width: 10rem;
--jb-image-input-height: 10rem;
--jb-image-input-border-radius: 50%;
}Accessibility notes
The normal image input demo includes the label and helper message used for the accessible name and description.
- The shadow root uses
delegatesFocus. - The component is form-associated and passes
valuetoElementInternals.setFormValue(). labelis exposed as the component aria label and default placeholder title.messageis exposed as the component aria description.- Validation state is synchronized with
ElementInternalswhere the browser supports it.
Related Docs
- See
jb-image-input/reactif you want to use this component in React. - See All JB Design System Component List for more components.
- Use Contribution Guide if you want to contribute to this component.
AI agent notes
- Import
jb-image-inputonce before using<jb-image-input>. - Use
valuefor the stored/submitted image value andfilefor the selected localFile. - Provide
downloaderwhen a stored value needs custom preview conversion. - Keep submitted values compatible with
ElementInternals.setFormValue():File,string,FormData, ornull. - Use
image-selectedwhen implementing multi-image selection; the component itself previews/uploads the first selected file. - Use
accept,maxFileSize,validation.list, andrequiredinstead of custom file filtering logic when possible. - This package includes
custom-elements.jsonand points to it with the package.jsoncustomElementsfield. The field is documented by the Custom Elements Manifest project in Referencing manifests from npm packages. - In
custom-elements.json,exports.kind: "js"describes the JavaScript/TypeScript class export andexports.kind: "custom-element-definition"maps thejb-image-inputtag name to that class.
