Forms inputanimated

Animated Input

Input with floating label animation.

Preview

Usage

Copy the full block below to use this component with its imports.

astro
---
import { AnimatedInput } from 'astro-component-kit';
---

<form class="stack-v gap-6">
  <AnimatedInput 
    id="email" 
    name="email"
    label="Email Address" 
    type="email" 
    required 
  />
  
  <AnimatedInput 
    id="user" 
    name="username"
    label="Username" 
    required 
  />
</form>
--- import { AnimatedInput } from 'astro-component-kit'; --- <form class="stack-v gap-6"> <AnimatedInput id="email" name="email" label="Email Address" type="email" required /> <AnimatedInput id="user" name="username" label="Username" required /> </form>

Manual Installation

If you are not using the npm package, create a new file src/components/lib/AnimatedInput.astro and paste the following code:

astro
---
/**
 * AnimatedInput — A form input with a floating label animation and focus glow effect.
 * 
 * @param {string} label - The visible indicator for the input field.
 * @param {string} id - The HTML id and for attribute linkage.
 * @param {string} type - Input element type. Default is 'text'.
 * @param {string} placeholder - Passed placeholder. Default is ' '. (Space is needed for CSS :placeholder-shown to work).
 * @param {boolean} required - HTML required attribute parameter. Default is false.
 * @param {string} name - HTML input name binding.
 */
interface Props { 
  label: string; 
  id: string; 
  type?: 'text' | 'email' | 'password' | 'number' | 'tel' | 'url'; 
  placeholder?: string; 
  required?: boolean; 
  name?: string; 
}

const { label, id, type = 'text', placeholder = ' ', required = false, name } = Astro.props;
---

<div class="anim-input-wrap">
  <input {id} {name} {type} {placeholder} {required} class="anim-input" autocomplete="off" />
  <label for={id} class="anim-input-label">{label}</label>
</div>

<style>
  .anim-input-wrap { position: relative; width: 100%; }
  .anim-input { 
    width: 100%; 
    padding: 1.1rem 1rem 0.5rem; 
    font-family: inherit; font-size: 0.95rem; 
    color: var(--c-text-1, #e2e8f0); 
    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); box-sizing: border-box; 
    outline: none; transition: border-color 0.25s ease, background 0.25s ease; 
  }
  .anim-input::placeholder { color: transparent; }
  .anim-input:focus { 
    background: rgba(99, 102, 241, 0.06); 
    border-color: rgba(99, 102, 241, 0.5); 
    box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.12); 
  }
  .anim-input-label { 
    position: absolute; top: 0.9rem; left: 1rem; 
    font-size: 0.9rem; color: var(--c-text-2, #64748b); 
    pointer-events: none; transition: top 0.2s ease, font-size 0.2s ease, color 0.2s ease; 
  }
  .anim-input:focus ~ .anim-input-label, 
  .anim-input:not(:placeholder-shown) ~ .anim-input-label { 
    top: 0.28rem; font-size: 0.68rem; 
    color: var(--c-primary-light, #818cf8); 
    font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; 
  }
</style>
--- /** * AnimatedInput — A form input with a floating label animation and focus glow effect. * * @param {string} label - The visible indicator for the input field. * @param {string} id - The HTML id and for attribute linkage. * @param {string} type - Input element type. Default is 'text'. * @param {string} placeholder - Passed placeholder. Default is ' '. (Space is needed for CSS :placeholder-shown to work). * @param {boolean} required - HTML required attribute parameter. Default is false. * @param {string} name - HTML input name binding. */ interface Props { label: string; id: string; type?: 'text' | 'email' | 'password' | 'number' | 'tel' | 'url'; placeholder?: string; required?: boolean; name?: string; } const { label, id, type = 'text', placeholder = ' ', required = false, name } = Astro.props; --- <div class="anim-input-wrap"> <input {id} {name} {type} {placeholder} {required} class="anim-input" autocomplete="off" /> <label for={id} class="anim-input-label">{label}</label> </div> <style> .anim-input-wrap { position: relative; width: 100%; } .anim-input { width: 100%; padding: 1.1rem 1rem 0.5rem; font-family: inherit; font-size: 0.95rem; color: var(--c-text-1, #e2e8f0); 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); box-sizing: border-box; outline: none; transition: border-color 0.25s ease, background 0.25s ease; } .anim-input::placeholder { color: transparent; } .anim-input:focus { background: rgba(99, 102, 241, 0.06); border-color: rgba(99, 102, 241, 0.5); box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.12); } .anim-input-label { position: absolute; top: 0.9rem; left: 1rem; font-size: 0.9rem; color: var(--c-text-2, #64748b); pointer-events: none; transition: top 0.2s ease, font-size 0.2s ease, color 0.2s ease; } .anim-input:focus ~ .anim-input-label, .anim-input:not(:placeholder-shown) ~ .anim-input-label { top: 0.28rem; font-size: 0.68rem; color: var(--c-primary-light, #818cf8); font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; } </style>

Quick Info

Category
Forms
Filename
AnimatedInput.astro
Dependencies
None — pure Astro + CSS
Tags
inputanimated