Forms layoutgroup
Form Group
Wrapper for labeling and help text.
Preview
Form Group
Usage
Copy the full block below to use this component with its imports.
astro
---
import { FormGroup } from 'astro-component-kit';
---
<FormGroupVertical label="Username" forId="u" helpText="Characters only."><input id="u" class="custom-input" /></FormGroupVertical> ---
import { FormGroup } from 'astro-component-kit';
---
<FormGroupVertical label="Username" forId="u" helpText="Characters only."><input id="u" class="custom-input" /></FormGroupVertical> Manual Installation
If you are not using the npm package, create a new file src/components/lib/FormGroup.astro and paste the following code:
astro
---
/**
* FormGroupVertical — A structural wrapper component for grouping an input with its label and validation messaging.
*
* @param {string} label - The descriptive title for the field.
* @param {string} forId - The target ID of the child input (for label association).
* @param {string} helpText - Optional secondary guidance text below the input.
* @param {string} error - Optional error message that applies error styling.
* @param {boolean} required - Displays a required indicator if true.
*/
interface Props {
label: string;
forId: string;
helpText?: string;
error?: string;
required?: boolean;
}
const { label, forId, helpText, error, required = false } = Astro.props;
---
<div class:list={["form-group", { "form-group--error": error }]}>
<div class="form-group__header">
<label for={forId} class="form-group__label">
{label}
{required && <span class="form-group__req" aria-hidden="true">*</span>}
</label>
</div>
<div class="form-group__content">
<slot />
</div>
{error ? (
<p class="form-group__error" id={`${forId}-error`} role="alert">{error}</p>
) : helpText ? (
<p class="form-group__help" id={`${forId}-help`}>{helpText}</p>
) : null}
</div>
<style>
.form-group { display: flex; flex-direction: column; gap: var(--sp-2, 0.5rem); width: 100%; margin-bottom: var(--sp-4, 1rem); }
.form-group__label {
font-size: 0.8rem; font-weight: 700;
color: var(--c-text-1, #e2e8f0);
text-transform: uppercase;
letter-spacing: 0.05em;
margin-left: 0.5rem;
cursor: pointer;
}
.form-group__req { color: var(--c-error, #f87171); margin-left: 2px; }
.form-group__content { width: 100%; }
.form-group__help { font-size: 0.75rem; color: var(--c-text-2, #64748b); margin: 0 0 0 0.5rem; }
.form-group__error { font-size: 0.75rem; color: var(--c-error, #f87171); font-weight: 600; margin: 0 0 0 0.5rem; }
/* Deep selector to style any input nested inside the group content if it's in an error state */
.form-group--error :global(input),
.form-group--error :global(textarea),
.form-group--error :global(select) {
border-color: var(--c-error, #ef4444) !important;
background-color: rgba(239, 68, 68, 0.03) !important;
}
</style> ---
/**
* FormGroupVertical — A structural wrapper component for grouping an input with its label and validation messaging.
*
* @param {string} label - The descriptive title for the field.
* @param {string} forId - The target ID of the child input (for label association).
* @param {string} helpText - Optional secondary guidance text below the input.
* @param {string} error - Optional error message that applies error styling.
* @param {boolean} required - Displays a required indicator if true.
*/
interface Props {
label: string;
forId: string;
helpText?: string;
error?: string;
required?: boolean;
}
const { label, forId, helpText, error, required = false } = Astro.props;
---
<div class:list={["form-group", { "form-group--error": error }]}>
<div class="form-group__header">
<label for={forId} class="form-group__label">
{label}
{required && <span class="form-group__req" aria-hidden="true">*</span>}
</label>
</div>
<div class="form-group__content">
<slot />
</div>
{error ? (
<p class="form-group__error" id={`${forId}-error`} role="alert">{error}</p>
) : helpText ? (
<p class="form-group__help" id={`${forId}-help`}>{helpText}</p>
) : null}
</div>
<style>
.form-group { display: flex; flex-direction: column; gap: var(--sp-2, 0.5rem); width: 100%; margin-bottom: var(--sp-4, 1rem); }
.form-group__label {
font-size: 0.8rem; font-weight: 700;
color: var(--c-text-1, #e2e8f0);
text-transform: uppercase;
letter-spacing: 0.05em;
margin-left: 0.5rem;
cursor: pointer;
}
.form-group__req { color: var(--c-error, #f87171); margin-left: 2px; }
.form-group__content { width: 100%; }
.form-group__help { font-size: 0.75rem; color: var(--c-text-2, #64748b); margin: 0 0 0 0.5rem; }
.form-group__error { font-size: 0.75rem; color: var(--c-error, #f87171); font-weight: 600; margin: 0 0 0 0.5rem; }
/* Deep selector to style any input nested inside the group content if it's in an error state */
.form-group--error :global(input),
.form-group--error :global(textarea),
.form-group--error :global(select) {
border-color: var(--c-error, #ef4444) !important;
background-color: rgba(239, 68, 68, 0.03) !important;
}
</style>
Quick Info
- Category
- Forms
- Filename
FormGroup.astro- Dependencies
- None — pure Astro + CSS
- Tags
- layoutgroup