<popin-form>
is a lightweight pop-up form component that displays content in a dialog-like overlay. It can handle focus management, closing behavior, and form submission. It provides named slots for header, body, and footer, and also supports custom styles through CSS properties.
Note: This component is part of a bigger project: Silex no-code website builder.
Demo: Interactive CodePen
<popin-form>
is a component that combines a pop-up overlay with a form container. It is designed to be a self-contained form that can be integrated into a parent form. It supports the following features:
-
Pop-up Overlay:
- Appears above other content, can capture focus, and closes when users click outside or press Escape.
- You can disable automatic closing by using
no-auto-close
. - Supports two events when showing or hiding:
popin-opened
andpopin-closed
.
-
Form Container:
- Embeds a native
<form>
element inside the overlay. - Can be integrated with a parent
<form>
via thefor
andname
attributes. - Submits its internal fields through standard form submission events or
FormData
usage.
- Embeds a native
-
Slots:
slot="header"
: Header area (often contains a title).- default slot: Main body content (place your fields, text, etc.).
slot="footer"
: Footer area (often contains buttons like “Submit” or “Cancel”).
<popin-form hidden style="width: 400px">
<div slot="header">Header</div>
<div slot="body">
<!-- Form elements here -->
<label>
Name:
<input type="text" name="username" />
</label>
</div>
<div slot="footer">
<button type="button" class="secondary" onclick="this.closest('popin-form').close()">Cancel</button>
<button type="submit">Apply</button>
</div>
</popin-form>
<!-- Show the popin via removing the 'hidden' attribute -->
<button onclick="document.querySelector('popin-form').removeAttribute('hidden')">
Open Popin
</button>
- The
hidden
attribute keeps the pop-up hidden initially. - Clicking the “Open Popin” button removes
hidden
, making it visible. - By default, clicking outside the pop-up or pressing Escape closes it (unless
no-auto-close
is set).
Attribute | Type | Description |
---|---|---|
hidden |
boolean | If present, the pop-up is hidden. Remove the attribute to show the pop-up. |
no-auto-close |
boolean | If set, the pop-up does not close when the user clicks outside or loses focus. |
for |
string | The id of a parent <form> to integrate with. If not set, <popin-form> finds the nearest <form> ancestor. |
name |
string | Name used to prefix internal form data keys, e.g. myPopinField-username . |
Event | Description |
---|---|
popin-opened |
Dispatched when the pop-up becomes visible (i.e., hidden is removed). |
popin-closed |
Dispatched when the pop-up is hidden (i.e., hidden is added). |
change |
Fired after the pop-up form is submitted (the “Apply” button by default). |
- Clicking outside the pop-up or pressing Escape will close it by default.
- Disable with
no-auto-close
. - Programmatically close by calling
close()
method or settinghidden
attribute.
<popin-form>
internally wraps its content in a<form>
element.- When users submit (e.g., pressing “Apply”), it dispatches a
change
event and closes. - If you specify
for="mainForm"
and have a<form id="mainForm">
in the page,<popin-form>
can merge its data into the parent form’s submission using the standard FormData event. - Each input inside
<popin-form>
is collected into an internalFormData
. The keys are prefixed by<popin-form name>-<input name>
ifname
is set.
<form id="mainForm">
<popin-form for="mainForm" name="popinField" hidden style="width: 300px">
<div slot="header">Edit Fields</div>
<div slot="body">
<input type="text" name="title" placeholder="Title" />
<select name="category">
<option value="News">News</option>
<option value="Blog" selected>Blog</option>
</select>
</div>
<div slot="footer">
<button type="button" class="secondary" onclick="this.closest('popin-form').close()">Cancel</button>
<button type="submit">Apply</button>
</div>
</popin-form>
<!-- The main form can have other fields too -->
<label>
Main Form Field:
<input type="text" name="mainField" value="Hello" />
</label>
<button type="submit">Submit All</button>
</form>
<script>
document.getElementById('mainForm').addEventListener('submit', (e) => {
e.preventDefault();
const fd = new FormData(e.target);
// popinField-title and popinField-category are included if changed in the popin
for (const pair of fd.entries()) {
console.log(pair[0] + ': ' + pair[1]);
}
});
</script>
The pop-up/form layout can be styled with CSS variables:
CSS Property | Description |
---|---|
--popin-form-header-background |
Background color of the header area |
--popin-form-header-color |
Text color of the header |
--popin-form-body-background |
Background color of the body area |
--popin-form-body-color |
Text color of the body |
--popin-form-footer-background |
Background color of the footer area |
--popin-form-footer-color |
Text color of the footer |
--popin-form-header-border-bottom |
Border style for the header-bottom (e.g., 1px solid #ccc ) |
--popin-form-footer-border-top |
Border style for the footer-top |
--popin-form-header-padding |
Padding for the header |
--popin-form-body-padding |
Padding for the body |
--popin-form-footer-padding |
Padding for the footer |
--popin-button-background |
Background color of the primary button(s) |
--popin-button-color |
Text color of the primary button(s) |
--popin-button-hover-background |
Hover background color of the primary button(s) |
--popin-button-hover-color |
Hover text color of the primary button(s) |
--popin-button-border |
Border of the primary button(s) |
--popin-button-hover-border |
Hover border of the primary button(s) |
--popin-button-padding |
Padding of the primary button(s) |
--popin-button-hover-padding |
Hover padding of the primary button(s) |
--popin-button-margin |
Margin of the primary button(s) |
--popin-button-hover-margin |
Hover margin of the primary button(s) |
--popin-form-border-radius |
Border radius of the form container |
--popin-button-background--secondary |
Background color of the secondary button(s) |
--popin-button-color--secondary |
Text color of the secondary button(s) |
--popin-button-hover-background--secondary |
Hover background for the secondary button(s) |
--popin-button-hover-color--secondary |
Hover text color for the secondary button(s) |
--popin-button-border--secondary |
Border of the secondary button(s) |
--popin-button-hover-border--secondary |
Hover border of the secondary button(s) |
--popin-button-padding--secondary |
Padding of the secondary button(s) |
--popin-button-hover-padding--secondary |
Hover padding of the secondary button(s) |
--popin-button-margin--secondary |
Margin of the secondary button(s) |
--popin-button-hover-margin--secondary |
Hover margin of the secondary button(s) |
Method | Description |
---|---|
close() |
Hides the pop-up, adds the hidden attribute, and fires popin-closed . |
<popin-form hidden id="myPopin" style="width: 300px;">
<div slot="header">Edit Something</div>
<div slot="body">
<input type="text" name="myField" placeholder="Type here..." />
</div>
<div slot="footer">
<button type="button" class="secondary" onclick="this.closest('popin-form').close()">Cancel</button>
<button type="submit">Ok</button>
</div>
</popin-form>
<button
onclick="document.getElementById('myPopin').removeAttribute('hidden')">
Show Popin
</button>
- Pressing Escape closes the pop-in unless
no-auto-close
is set. - By default, when
<popin-form>
is shown, focus is set to it. Once it loses focus (user clicks outside), it closes automatically (again, unlessno-auto-close
is set). - Upon form submission,
<popin-form>
triggers its ownchange
event and closes by default. If you need to prevent closure, override the defaultsubmit(event)
handler, or remove/replace the default footer buttons.
That’s it! For more details on complementary components, see:
Enjoy creating rich pop-up forms with <popin-form>
!