Forms selectmodern
Modern Select
Custom styled dropdown selector.
Preview
Usage
Copy the full block below to use this component with its imports.
astro
---
import { ModernSelect } from 'astro-component-kit';
---
<ModernSelect id="role" label="Project Role" options={[{label: "Developer", value: "dev"}, {label: "Designer", value: "dsign"}]} /> ---
import { ModernSelect } from 'astro-component-kit';
---
<ModernSelect id="role" label="Project Role" options={[{label: "Developer", value: "dev"}, {label: "Designer", value: "dsign"}]} /> Manual Installation
If you are not using the npm package, create a new file src/components/lib/ModernSelect.astro and paste the following code:
astro
---
/**
* ModernSelect — A styled dropdown selector with a custom arrow and glassmorphism styling.
*
* @param {string} label - Input labeling title.
* @param {string} id - HTML ID for the select element.
* @param {string} name - HTML name binding.
* @param {Array<{label: string, value: string, disabled?: boolean}>} options - List of select options.
* @param {boolean} required - HTML required attribute.
*/
interface Props {
label: string;
id: string;
name?: string;
options: Array<{ label: string; value: string; disabled?: boolean }>;
required?: boolean;
}
const { label, id, name, options = [], required = false } = Astro.props;
---
<div class="select-container">
<label for={id} class="select-label">{label}</label>
<div class="select-wrap">
<select class="custom-select" {id} {name} {required}>
{options.map(opt => (
<option value={opt.value} disabled={opt.disabled}>{opt.label}</option>
))}
</select>
<div class="select-arrow" aria-hidden="true">
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round">
<path d="M6 9l6 6 6-6"/>
</svg>
</div>
</div>
</div>
<style>
.select-container { display: flex; flex-direction: column; gap: var(--sp-2, 0.5rem); width: 100%; }
.select-label { font-size: 0.85rem; font-weight: 600; color: var(--c-text-2, #94a3b8); margin-left: 0.5rem; }
.select-wrap { position: relative; width: 100%; }
.custom-select {
width: 100%;
padding: 0.8rem 2.5rem 0.8rem 1rem;
background: var(--c-bg-elev, rgba(255,255,255,0.04));
border: 1px solid var(--c-border, rgba(255,255,255,0.1));
border-radius: var(--r-md, 12px);
color: var(--c-text-1, #fff);
appearance: none; cursor: pointer; outline: none;
font-family: inherit; font-size: 0.95rem;
transition: border-color 0.2s, background 0.2s;
}
.custom-select:focus {
border-color: var(--c-primary, #6366f1);
background: rgba(255,255,255,0.06);
}
.select-arrow {
position: absolute; right: 1rem; top: 50%; transform: translateY(-50%);
color: var(--c-text-2, #64748b);
pointer-events: none; transition: transform 0.2s;
display: flex; align-items: center; justify-content: center;
}
.custom-select:focus + .select-arrow {
transform: translateY(-50%) rotate(180deg);
color: var(--c-primary, #6366f1);
}
</style> ---
/**
* ModernSelect — A styled dropdown selector with a custom arrow and glassmorphism styling.
*
* @param {string} label - Input labeling title.
* @param {string} id - HTML ID for the select element.
* @param {string} name - HTML name binding.
* @param {Array<{label: string, value: string, disabled?: boolean}>} options - List of select options.
* @param {boolean} required - HTML required attribute.
*/
interface Props {
label: string;
id: string;
name?: string;
options: Array<{ label: string; value: string; disabled?: boolean }>;
required?: boolean;
}
const { label, id, name, options = [], required = false } = Astro.props;
---
<div class="select-container">
<label for={id} class="select-label">{label}</label>
<div class="select-wrap">
<select class="custom-select" {id} {name} {required}>
{options.map(opt => (
<option value={opt.value} disabled={opt.disabled}>{opt.label}</option>
))}
</select>
<div class="select-arrow" aria-hidden="true">
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round">
<path d="M6 9l6 6 6-6"/>
</svg>
</div>
</div>
</div>
<style>
.select-container { display: flex; flex-direction: column; gap: var(--sp-2, 0.5rem); width: 100%; }
.select-label { font-size: 0.85rem; font-weight: 600; color: var(--c-text-2, #94a3b8); margin-left: 0.5rem; }
.select-wrap { position: relative; width: 100%; }
.custom-select {
width: 100%;
padding: 0.8rem 2.5rem 0.8rem 1rem;
background: var(--c-bg-elev, rgba(255,255,255,0.04));
border: 1px solid var(--c-border, rgba(255,255,255,0.1));
border-radius: var(--r-md, 12px);
color: var(--c-text-1, #fff);
appearance: none; cursor: pointer; outline: none;
font-family: inherit; font-size: 0.95rem;
transition: border-color 0.2s, background 0.2s;
}
.custom-select:focus {
border-color: var(--c-primary, #6366f1);
background: rgba(255,255,255,0.06);
}
.select-arrow {
position: absolute; right: 1rem; top: 50%; transform: translateY(-50%);
color: var(--c-text-2, #64748b);
pointer-events: none; transition: transform 0.2s;
display: flex; align-items: center; justify-content: center;
}
.custom-select:focus + .select-arrow {
transform: translateY(-50%) rotate(180deg);
color: var(--c-primary, #6366f1);
}
</style>
Quick Info
- Category
- Forms
- Filename
ModernSelect.astro- Dependencies
- None — pure Astro + CSS
- Tags
- selectmodern