<m-input> FORM 4 SLOTS 17 PROPS 2 EVENTS
overview examples properties methods events slots css parts

Drop-in replacement for native text-type <input> elements with form participation, validation, clear buttons, and slot-based customization.

Basic Usage


Code
<form class="form" id="example-form">
  <label for="normal-input">Normal input</label>
  <input name="normal-input" />

  <m-input 
      label="m-input disabled" 
      name="m-input-example-disabled" 
      disabled
  ></m-input>

  <m-input 
      label="m-input default value" 
      name="m-input-example-default-value" 
      value="Default value"
  ></m-input>

  <m-input 
      label="m-input readonly" 
      name="m-input-example-readonly-value" 
      value="Readonly" 
      readonly
  ></m-input>

  <m-input 
      label="m-input placeholder" 
      name="m-input-example-placeholder" 
      placeholder="Placeholder..."
  ></m-input>

  <m-input 
      label="m-input clearable" 
      name="m-input-example-clearable" 
      clearable
  ></m-input>

  <m-input 
      label="m-input size" 
      name="m-input-size" size="4"
  ></m-input>

  <button type="submit">Submit</button>
  <button type="reset">Reset</button>
</form>
<pre id="example-form-output"></pre>


<script>
document.querySelector('#example-form').addEventListener('submit', function(e) {
  e.preventDefault();
  const outputEl = document.querySelector("#example-form-output");
  const formData = new FormData(e.target);
  if(outputEl){
    outputEl.textContent = JSON.stringify(Object.fromEntries(formData));
  }
});

</script>

Form Submission

Form Data:

  
Code
<form id="demo-form" class="form">
  <m-input
    label="Your name"
    name="username"
    placeholder="Type here…"
  ></m-input>

  <button type="submit">Submit</button>
  
  <div id="demo-output" class="box" data-variant="surface" data-span="2">
    <strong>Form Data:</strong>
    <pre id="demo-output-text" style="margin: 0.5rem 0 0 0;"></pre>
  </div>
</form>


<script>
document.querySelector('#demo-form').addEventListener('submit', (e) => {
  e.preventDefault();
  const data = Object.fromEntries(new FormData(e.target));
  document.querySelector('#demo-output-text').textContent =
    JSON.stringify(data, null, 2);
});

</script>

Layout And Labeling

Code
<div class="form">
  <m-input 
    label="Email" 
    name="email"
    placeholder="you@example.com"
  ></m-input>
  
  <m-input 
    label="Vertical layout" 
    name="vertical"
    self-orientation="vertical"
    placeholder="Label appears above input"
  ></m-input>
</div>

Clearable Input

Code
<form class="form" id="clearable-form">
  <m-input 
    label="Default button" 
    name="default-clear"
    value="Clear me"
    clearable
  ></m-input>
  
  <m-input 
    label="Custom button" 
    name="custom-clear"
    value="Custom clear"
    clearable
  >
    <button slot="clear" style="padding: 0 0.5rem;">✕</button>
  </m-input>
  
  <button type="reset" data-span="2">Reset</button>
</form>

Slots

Code
<div class="form">
    <m-input label="Before">
      <svg slot="before" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
    </m-input>

    <m-input label="After">
      <svg slot="after" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></svg>
    </m-input>

    <m-input label="Both" placeholder="Search...">
     <div slot="before" class="stack" data-direction="row" data-gap="1">
      <button data-background="surface-raised" data-padding="i-3" data-border>tag 1</button>
      <button data-background="surface-raised" data-padding="i-3" data-border>tag 2</button>
      <button data-background="surface-raised" data-padding="i-3" data-border>tag 3</button>
      </div>
      <svg slot="after" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21 21-4.34-4.34"/><circle cx="11" cy="11" r="8"/></svg>
    </m-input>
</div>

Validation


Code
<form class="form" id="example-required-form">
  <label for="normal-required-input">Normal input</label>
  <input name="normal-required-input" required />
  <label for="normal-min-input">Normal min 3</label>
  <input name="normal-min-input" minlength="3" />

  <m-input 
      label="Required" 
      name="m-input-required" 
      required="true"
  ></m-input>

  <m-input 
      label="Min length" 
      name="m-input-min-length" 
      minlength="3"
  ></m-input>

  <m-input 
      label="Max length" 
      name="m-input-max-length" 
      maxlength="3"
  ></m-input>

  <m-input 
      label="Pattern [0-9]" 
      name="m-input-pattern" 
      pattern="[0-9]"
  ></m-input>

  <button type="submit">Submit</button>
  <button type="reset">Reset</button>
</form>
<pre id="example-required-form-output"></pre>


<script>
document.querySelector('#example-required-form').addEventListener('submit', function(e) {
  e.preventDefault();
  const outputEl = document.querySelector("#example-required-form-output");
  const formData = new FormData(e.target);
  if(outputEl){
    outputEl.textContent = JSON.stringify(Object.fromEntries(formData));
  }
});

</script>

Events

Event Log:
    Code
    <form class="form" id="events-form">
      <m-input 
        id="email-input"
        label="Email (required)" 
        name="email" 
        type="email"
        required
        clearable
        value="test@example.com"
      ></m-input>
      
      <div id="event-log" class="box" data-variant="surface" data-span="2">
        <strong>Event Log:</strong>
        <ul id="log-list" style="margin: 0; padding-left: 1.5rem;"></ul>
      </div>
      
      <button type="submit">Submit</button>
    </form>
    
    
    <script>
    const emailInput = document.querySelector('#email-input');
    const logList = document.querySelector('#log-list');
    
    emailInput.addEventListener('m-invalid', (e) => {
      const li = document.createElement('li');
      li.textContent = `m-invalid: "${e.detail.validationMessage}"`;
      li.style.color = 'var(--color-destructive-fill-mid)';
      logList.appendChild(li);
    });
    
    emailInput.addEventListener('m-input-clear', (e) => {
      const li = document.createElement('li');
      li.textContent = `m-input-clear: Previous value was "${e.detail.value}"`;
      li.style.color = 'var(--color-neutral-fill-mid)';
      logList.appendChild(li);
    });
    
    emailInput.addEventListener('input', () => {
      if (emailInput.validity.valid && emailInput.value) {
        const li = document.createElement('li');
        li.textContent = 'Valid email entered';
        li.style.color = 'var(--color-success-fill-mid)';
        logList.appendChild(li);
      }
    });
    
    </script>

    Css Parts

    Code
    <style>
      .styled-input::part(input) {
        font-family: var(--ff-display);
      }
      
      .styled-input::part(input-wrapper) {
        border-radius: 20px;
        color: var(--color-primary-fill-mid);
      }
      
      .styled-input::part(label) {
        color: var(--color-primary-fill-mid);
      }
      
      .styled-input::part(error) {
        background: var(--color-neutral-fill-mid);
        border-color: var(--color-neutral-stroke-mid);
      }
      
      .styled-input::part(clear-button) {
        color: var(--color-primary-fill-mid);
      }
      
      .styled-input::part(clear-button):hover {
        color: var(--color-destructive-fill-mid);
      }
    </style>
    
    <div class="form">
      <m-input 
        class="styled-input" 
        label="Styled input" 
        placeholder="Custom styled..." 
        clearable
      ></m-input>
      
      <m-input 
        class="styled-input" 
        label="With validation" 
        placeholder="Type at least 3 chars..." 
        minlength="3"
        clearable
      ></m-input>
    </div>
    NAMETYPEDEFAULT
    type "text" | "search" | "tel" | "url" | "email" | "password" "text"
    minLength number | undefined
    maxLength number | undefined
    pattern string | undefined
    placeholder string | undefined
    autocomplete string | undefined
    size number | undefined
    clearable boolean false
    autofocus boolean false
    clearSlotHasContent
    selectionStart number | null
    selectionEnd number | null
    selectionDirection "forward" | "backward" | "none" | null
    handleKeydown
    handleBlur
    handleInput
    adoptedStyleSheets array [baseStyleSheet]
    NAMERETURNS
    select void
    focus void
    blur void
    setSelectionRange void
    setRangeText void
    setRangeText void
    setRangeText void
    NAMEDETAIL TYPE
    m-invalid CustomEvent
    Fires when validation fails. Detail: { validity: ValidityState, validationMessage: string, value: string }
    m-input-clear CustomEvent
    Fires when clear button is clicked (cancelable). Detail: { value: string }
    NAME
    (default)
    Default slot for component content
    before
    Content before the input element (icons, chips, buttons)
    after
    Content after the input element
    clear
    Override the default clear button
    NAME
    ::part(label)
    The label element
    ::part(input-wrapper)
    The wrapper containing the input and slots
    ::part(input)
    The native input element
    ::part(clear-button)
    The clear button
    ::part(clear-icon)
    The icon inside the clear button
    ::part(error)
    The error message container
    Open palette