MDC

Field

Demo

Align End

Code
<style>
    .demo-row {
        display: flex;
        flex-direction: column;
        gap: 24px;
    }
</style>

<div class="demo-row">
    <mdc-field variant="filled" label="Start aligned (default)">
        <input type="text" value="hello" />
    </mdc-field>

    <mdc-field variant="filled" label="End aligned" align-end>
        <input type="text" value="hello" />
    </mdc-field>

    <mdc-field variant="outlined" label="End aligned (outlined)" align-end prefix-text="$">
        <input type="number" value="0.00" />
    </mdc-field>
</div>

Counter

Code
<mdc-field variant="filled" label="Message" supporting-text="Helper text" counter-text="10 / 50">
    <input value="Hello MDC" />
</mdc-field>

<mdc-field variant="outlined" label="Description" counter-text="25 / 100">
    <input value="Sample outlined text" />
</mdc-field>

Disabled

Code
<style>
    .demo-row {
        display: flex;
        flex-direction: column;
        gap: 24px;
    }
</style>

<div class="demo-row">
    <mdc-field variant="filled" label="Disabled (empty)" disabled>
        <input type="text" disabled />
    </mdc-field>

    <mdc-field variant="filled" label="Disabled (populated)" disabled populated>
        <input type="text" value="read only" disabled />
    </mdc-field>

    <mdc-field variant="outlined" label="Disabled (outlined)" disabled supporting-text="This field is disabled">
        <input type="text" disabled />
    </mdc-field>
</div>

Error Text

Code
<style>
    .demo-row {
        display: flex;
        flex-direction: column;
        gap: 24px;
    }
</style>

<div class="demo-row">
    <mdc-field variant="filled" label="Username" error-text="Username is already taken" invalid populated>
        <input type="text" value="johndoe" />
    </mdc-field>

    <mdc-field variant="filled" label="Email" error-text="Invalid email address" invalid>
        <input type="email" value="not-an-email" />
    </mdc-field>

    <mdc-field variant="filled" label="Password" error-text="Password too short" supporting-text="At least 8 characters">
        <input type="password" value="abc" />
    </mdc-field>

    <mdc-field variant="filled" label="Silent error" error-text="This won't display because invalid=false">
        <input type="text" />
    </mdc-field>
</div>

Floating Label Behavior

Code
<style>
    .demo-row {
        display: flex;
        gap: 24px;
        align-items: flex-start;
        flex-wrap: wrap;
    }
    .demo-row > * {
        flex: 1 1 240px;
        min-width: 240px;
    }
</style>

<div class="demo-row">
    <mdc-field variant="filled" label="Auto" floating-label-behavior="auto">
        <input type="text" />
    </mdc-field>

    <mdc-field variant="filled" label="Always" floating-label-behavior="always">
        <input type="text" />
    </mdc-field>

    <mdc-field variant="filled" label="Never" floating-label-behavior="never">
        <input type="text" />
    </mdc-field>
</div>

Focused

Code
<style>
    .demo-row {
        display: flex;
        flex-direction: column;
        gap: 24px;
    }
    button {
        margin-block-end: 16px;
        padding: 8px 16px;
        border: 1px solid #ccc;
        border-radius: 4px;
        background: white;
        cursor: pointer;
    }
</style>

<button id="toggle-focus">Toggle focused on all fields below</button>

<div class="demo-row">
    <mdc-field id="f1" variant="filled" label="Unfocused">
        <input type="text" />
    </mdc-field>

    <mdc-field id="f2" variant="filled" label="Focused" focused>
        <input type="text" />
    </mdc-field>

    <mdc-field id="f3" variant="outlined" label="Focused (outlined)" focused>
        <input type="text" />
    </mdc-field>
</div>

<script type="module">
    const button = document.getElementById('toggle-focus')
    const fields = [
        document.getElementById('f1'),
        document.getElementById('f2'),
        document.getElementById('f3'),
    ]
    button?.addEventListener('click', () => {
        for (const field of fields) {
            if (field) field.focused = !field.focused
        }
    })
</script>

Interval

Code
<style>
    .demo-wrapper {
        display: flex;
        flex-direction: column;
        gap: 24px;
        font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
        color: #1d1b20;
    }

    /* ---------- Control Panel & Inspector ---------- */
    .control-panel {
        background: #f8f8fc;
        border: 1px solid #e2e2ec;
        border-radius: 12px;
        padding: 16px 20px;
        display: flex;
        flex-direction: column;
        gap: 16px;
        box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
    }

    .panel-header {
        display: flex;
        align-items: center;
        justify-content: space-between;
        flex-wrap: wrap;
        gap: 12px;
    }

    .state-title-group {
        display: flex;
        align-items: center;
        gap: 12px;
    }

    .state-badge {
        background: #6750a4;
        color: #ffffff;
        font-size: 12px;
        font-weight: 700;
        letter-spacing: 0.5px;
        padding: 4px 10px;
        border-radius: 16px;
        white-space: nowrap;
    }

    .state-name {
        font-size: 16px;
        font-weight: 600;
        color: #1d1b20;
    }

    .state-description {
        font-size: 13px;
        color: #49454f;
        margin-top: 2px;
    }

    .button-group {
        display: flex;
        align-items: center;
        gap: 8px;
        flex-wrap: wrap;
    }

    .control-btn {
        display: inline-flex;
        align-items: center;
        gap: 6px;
        padding: 6px 14px;
        border: 1px solid #79747e;
        border-radius: 8px;
        background: #ffffff;
        color: #1d1b20;
        font-size: 13px;
        font-weight: 500;
        cursor: pointer;
        transition: all 150ms ease;
    }

    .control-btn:hover {
        background: #ececf4;
        border-color: #6750a4;
        color: #6750a4;
    }

    .control-btn:active {
        background: #dedee8;
    }

    .control-btn.primary {
        background: #6750a4;
        color: #ffffff;
        border-color: #6750a4;
    }

    .control-btn.primary:hover {
        background: #523e85;
    }

    .select-dropdown {
        padding: 6px 12px;
        border: 1px solid #79747e;
        border-radius: 8px;
        background: #ffffff;
        font-size: 13px;
        color: #1d1b20;
        cursor: pointer;
        outline: none;
    }

    /* Timeline progress indicator */
    .timeline-track {
        width: 100%;
        height: 4px;
        background: #e2e2ec;
        border-radius: 2px;
        overflow: hidden;
        position: relative;
    }

    .timeline-bar {
        height: 100%;
        width: 0%;
        background: #6750a4;
        transition: width linear;
    }

    /* Live Properties Inspector Pills */
    .props-inspector {
        display: flex;
        flex-wrap: wrap;
        gap: 8px;
        padding-top: 4px;
        border-top: 1px dashed #d8d8e4;
    }

    .prop-pill {
        display: inline-flex;
        align-items: center;
        gap: 4px;
        font-size: 11px;
        font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
        padding: 2px 8px;
        border-radius: 6px;
        background: #e8e8f0;
        color: #49454f;
    }

    .prop-pill.active {
        background: #e8def8;
        color: #1d192b;
        font-weight: 600;
    }

    .prop-pill.error {
        background: #f9dedc;
        color: #601410;
        font-weight: 600;
    }

    /* ---------- Field Grid Showcase ---------- */
    .section-title {
        font-size: 14px;
        font-weight: 600;
        color: #49454f;
        text-transform: uppercase;
        letter-spacing: 0.5px;
        margin-bottom: 12px;
    }

    .demo-grid {
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
        gap: 28px;
    }

    .demo-card {
        display: flex;
        flex-direction: column;
        gap: 8px;
    }

    .demo-card-label {
        font-size: 13px;
        font-weight: 500;
        color: #49454f;
        display: flex;
        align-items: center;
        justify-content: space-between;
    }

    .demo-card-tag {
        font-size: 11px;
        padding: 2px 6px;
        border-radius: 4px;
        background: #f0f0f4;
        color: #6750a4;
        font-weight: 600;
    }
</style>

<div class="demo-wrapper">
    <!-- State Controller Dashboard -->
    <div class="control-panel">
        <div class="panel-header">
            <div class="state-title-group">
                <span id="state-badge" class="state-badge">State 1 / 8</span>
                <div>
                    <div id="state-name" class="state-name">1. Idle (Resting, Empty)</div>
                    <div id="state-desc" class="state-description">Unfocused and empty: label rests in the center, input placeholder and affixes remain hidden.</div>
                </div>
            </div>

            <div class="button-group">
                <select id="state-select" class="select-dropdown" aria-label="Select state directly">
                    <!-- Populated via script -->
                </select>
                <select id="speed-select" class="select-dropdown" aria-label="Playback speed">
                    <option value="1500">Fast (1.5s)</option>
                    <option value="2500" selected>Normal (2.5s)</option>
                    <option value="4000">Slow (4.0s)</option>
                </select>
                <button id="btn-prev" class="control-btn" type="button" title="Previous State">◀ Prev</button>
                <button id="btn-toggle" class="control-btn primary" type="button" title="Pause / Resume Timer">⏸ Pause</button>
                <button id="btn-next" class="control-btn" type="button" title="Next State">Next ▶</button>
            </div>
        </div>

        <!-- Progress Timeline Track -->
        <div class="timeline-track">
            <div id="timeline-bar" class="timeline-bar"></div>
        </div>

        <!-- Live Property Inspector -->
        <div id="props-inspector" class="props-inspector">
            <!-- Dynamic pills rendered via JS -->
        </div>
    </div>

    <!-- Group 1: Standard Single-Line Text Fields (Filled vs Outlined) -->
    <div>
        <div class="section-title">Standard Single-Line Fields</div>
        <div class="demo-grid">
            <div class="demo-card">
                <div class="demo-card-label">
                    <span>Filled Variant</span>
                    <span class="demo-card-tag">variant="filled"</span>
                </div>
                <mdc-field id="field-filled" variant="filled" label="User Account" prefix-text="@">
                    <mdc-icon slot="leading-icon">person</mdc-icon>
                    <input id="input-filled" type="text" placeholder="Enter account name..." />
                    <mdc-icon slot="trailing-icon">info</mdc-icon>
                </mdc-field>
            </div>

            <div class="demo-card">
                <div class="demo-card-label">
                    <span>Outlined Variant</span>
                    <span class="demo-card-tag">variant="outlined"</span>
                </div>
                <mdc-field id="field-outlined" variant="outlined" label="User Account" prefix-text="@">
                    <mdc-icon slot="leading-icon">person</mdc-icon>
                    <input id="input-outlined" type="text" placeholder="Enter account name..." />
                    <mdc-icon slot="trailing-icon">info</mdc-icon>
                </mdc-field>
            </div>
        </div>
    </div>

    <!-- Group 2: Advanced Configurations (Suffix / Domain & Multiline Textarea) -->
    <div>
        <div class="section-title">Suffix & Multiline (Textarea) Configurations</div>
        <div class="demo-grid">
            <div class="demo-card">
                <div class="demo-card-label">
                    <span>Outlined with Suffix & Trailing Action</span>
                    <span class="demo-card-tag">suffix-text=".com"</span>
                </div>
                <mdc-field id="field-suffix" variant="outlined" label="Server Domain" suffix-text=".com">
                    <mdc-icon slot="leading-icon">language</mdc-icon>
                    <input id="input-suffix" type="text" placeholder="example" />
                    <mdc-icon slot="trailing-icon">dns</mdc-icon>
                </mdc-field>
            </div>

            <div class="demo-card">
                <div class="demo-card-label">
                    <span>Multiline (Textarea) Field</span>
                    <span class="demo-card-tag">multiline</span>
                </div>
                <mdc-field id="field-textarea" variant="filled" label="Bio / Notes" multiline resizable>
                    <mdc-icon slot="leading-icon">notes</mdc-icon>
                    <textarea id="input-textarea" rows="2" placeholder="Tell us about yourself..."></textarea>
                </mdc-field>
            </div>
        </div>
    </div>
</div>

<script type="module">
    const stateSteps = [
        {
            title: '1. Idle (Resting, Empty)',
            description: 'Unfocused and empty: label rests at 16px in the center, input placeholder and affixes remain hidden.',
            value: '',
            suffixValue: '',
            textareaValue: '',
            focused: false,
            populated: false,
            invalid: false,
            disabled: false,
            required: false,
            floatingLabelBehavior: 'auto',
            supportingText: 'Supports letter, number, and underscore',
            errorText: '',
            counterText: '0 / 30',
        },
        {
            title: '2. Focus Gained (Empty)',
            description: 'Field receives focus: label smoothly floats with MD3 curve, bottom active indicator expands from center (Filled) / 2px border smoothly fades in (Outlined).',
            value: '',
            suffixValue: '',
            textareaValue: '',
            focused: true,
            populated: false,
            invalid: false,
            disabled: false,
            required: false,
            floatingLabelBehavior: 'auto',
            supportingText: 'Typing will expand and populate the value...',
            errorText: '',
            counterText: '0 / 30',
        },
        {
            title: '3. Populated & Typing (Focused)',
            description: 'User enters text: populated=true, counter updates in real time, prefix/suffix and text align on baseline.',
            value: 'sandlada_core',
            suffixValue: 'cluster-01',
            textareaValue: 'Full-stack engineering with Material Design 3 and Web Components.',
            focused: true,
            populated: true,
            invalid: false,
            disabled: false,
            required: true,
            floatingLabelBehavior: 'auto',
            supportingText: 'Valid account identifier format',
            errorText: '',
            counterText: '13 / 30',
        },
        {
            title: '4. Focus Lost (Populated & Idle)',
            description: 'User blurs field with value: label stays floated above text, focus indicator smoothly recedes to idle state without layout shift.',
            value: 'sandlada_core',
            suffixValue: 'cluster-01',
            textareaValue: 'Full-stack engineering with Material Design 3 and Web Components.',
            focused: false,
            populated: true,
            invalid: false,
            disabled: false,
            required: true,
            floatingLabelBehavior: 'auto',
            supportingText: 'Account identifier saved',
            errorText: '',
            counterText: '13 / 30',
        },
        {
            title: '5. Validation Error (Invalid & Focused)',
            description: 'Validation failed: error color triggers on label, bottom active indicator, outline border, and required asterisk. Error text replaces supporting text.',
            value: 'invalid#account!!',
            suffixValue: 'invalid..com',
            textareaValue: 'Invalid multiline content with forbidden syntax error.',
            focused: true,
            populated: true,
            invalid: true,
            disabled: false,
            required: true,
            floatingLabelBehavior: 'auto',
            supportingText: '',
            errorText: 'Account name cannot contain special characters (#, !)',
            counterText: '17 / 30',
        },
        {
            title: '6. Validation Error (Invalid & Unfocused)',
            description: 'Unfocused error state: label and outline maintain error color; error message remains announced for accessibility.',
            value: 'invalid#account!!',
            suffixValue: 'invalid..com',
            textareaValue: 'Invalid multiline content with forbidden syntax error.',
            focused: false,
            populated: true,
            invalid: true,
            disabled: false,
            required: true,
            floatingLabelBehavior: 'auto',
            supportingText: '',
            errorText: 'Account name cannot contain special characters (#, !)',
            counterText: '17 / 30',
        },
        {
            title: '7. Floating Label Behavior: Always',
            description: 'floatingLabelBehavior="always": label stays floated at top even when the field is empty and unfocused.',
            value: '',
            suffixValue: '',
            textareaValue: '',
            focused: false,
            populated: false,
            invalid: false,
            disabled: false,
            required: false,
            floatingLabelBehavior: 'always',
            supportingText: 'Label is permanently floated above the content',
            errorText: '',
            counterText: '0 / 30',
        },
        {
            title: '8. Disabled State',
            description: 'disabled=true: container, label, icons, and text transition to 38% opacity with disabled token colors; non-interactive.',
            value: 'sandlada_core',
            suffixValue: 'cluster-01',
            textareaValue: 'Field disabled by system permissions.',
            focused: false,
            populated: true,
            invalid: false,
            disabled: true,
            required: false,
            floatingLabelBehavior: 'auto',
            supportingText: 'Field is locked and cannot be edited',
            errorText: '',
            counterText: '13 / 30',
        },
    ]

    let currentIndex = 0
    let isRunning = true
    let timerId = null
    let speedMs = 2500

    // DOM Elements
    const badgeEl = document.getElementById('state-badge')
    const nameEl = document.getElementById('state-name')
    const descEl = document.getElementById('state-desc')
    const selectEl = document.getElementById('state-select')
    const speedSelectEl = document.getElementById('speed-select')
    const propsInspectorEl = document.getElementById('props-inspector')
    const timelineBarEl = document.getElementById('timeline-bar')

    const btnToggle = document.getElementById('btn-toggle')
    const btnPrev = document.getElementById('btn-prev')
    const btnNext = document.getElementById('btn-next')

    const fields = [
        document.getElementById('field-filled'),
        document.getElementById('field-outlined'),
        document.getElementById('field-suffix'),
        document.getElementById('field-textarea'),
    ]

    const inputFilled = document.getElementById('input-filled')
    const inputOutlined = document.getElementById('input-outlined')
    const inputSuffix = document.getElementById('input-suffix')
    const inputTextarea = document.getElementById('input-textarea')

    // Populate dropdown options
    stateSteps.forEach((s, idx) => {
        const opt = document.createElement('option')
        opt.value = String(idx)
        opt.textContent = s.title
        selectEl.appendChild(opt)
    })

    function renderPropsPills(state) {
        if (!propsInspectorEl) return
        const pills = [
            { label: 'focused', value: state.focused, active: state.focused },
            { label: 'populated', value: state.populated, active: state.populated },
            { label: 'invalid', value: state.invalid, error: state.invalid },
            { label: 'disabled', value: state.disabled, active: state.disabled },
            { label: 'required', value: state.required, active: state.required },
            { label: `behavior: ${state.floatingLabelBehavior}`, active: state.floatingLabelBehavior !== 'auto' },
            { label: `counter: "${state.counterText}"`, active: true },
        ]

        propsInspectorEl.innerHTML = pills.map((p) => {
            const cls = p.error ? 'prop-pill error' : p.active ? 'prop-pill active' : 'prop-pill'
            return `<span class="${cls}">${p.label}</span>`
        }).join('')
    }

    function applyState(index) {
        currentIndex = (index + stateSteps.length) % stateSteps.length
        const s = stateSteps[currentIndex]

        if (badgeEl) badgeEl.textContent = `State ${currentIndex + 1} / ${stateSteps.length}`
        if (nameEl) nameEl.textContent = s.title
        if (descEl) descEl.textContent = s.description
        if (selectEl) selectEl.value = String(currentIndex)

        renderPropsPills(s)

        // Update inputs
        if (inputFilled) { inputFilled.value = s.value; inputFilled.disabled = s.disabled; }
        if (inputOutlined) { inputOutlined.value = s.value; inputOutlined.disabled = s.disabled; }
        if (inputSuffix) { inputSuffix.value = s.suffixValue; inputSuffix.disabled = s.disabled; }
        if (inputTextarea) { inputTextarea.value = s.textareaValue; inputTextarea.disabled = s.disabled; }

        // Update all field components
        fields.forEach((field) => {
            if (!field) return
            field.focused = s.focused
            field.populated = s.populated
            field.invalid = s.invalid
            field.disabled = s.disabled
            field.required = s.required
            field.floatingLabelBehavior = s.floatingLabelBehavior
            field.supportingText = s.supportingText
            field.errorText = s.errorText
            field.counterText = s.counterText
        })

        resetTimelineAnimation()
    }

    function resetTimelineAnimation() {
        if (!timelineBarEl) return
        timelineBarEl.style.transition = 'none'
        timelineBarEl.style.width = '0%'
        if (isRunning) {
            requestAnimationFrame(() => {
                timelineBarEl.style.transition = `width ${speedMs}ms linear`
                timelineBarEl.style.width = '100%'
            })
        }
    }

    function startTimer() {
        stopTimer()
        resetTimelineAnimation()
        timerId = setInterval(() => {
            applyState(currentIndex + 1)
        }, speedMs)
    }

    function stopTimer() {
        if (timerId) {
            clearInterval(timerId)
            timerId = null
        }
        if (timelineBarEl) {
            timelineBarEl.style.transition = 'none'
            timelineBarEl.style.width = '0%'
        }
    }

    btnToggle?.addEventListener('click', () => {
        isRunning = !isRunning
        if (isRunning) {
            btnToggle.textContent = '⏸ Pause'
            btnToggle.classList.add('primary')
            startTimer()
        } else {
            btnToggle.textContent = '▶ Resume'
            btnToggle.classList.remove('primary')
            stopTimer()
        }
    })

    btnPrev?.addEventListener('click', () => {
        applyState(currentIndex - 1)
        if (isRunning) startTimer()
    })

    btnNext?.addEventListener('click', () => {
        applyState(currentIndex + 1)
        if (isRunning) startTimer()
    })

    selectEl?.addEventListener('change', (e) => {
        applyState(parseInt(e.target.value, 10))
        if (isRunning) startTimer()
    })

    speedSelectEl?.addEventListener('change', (e) => {
        speedMs = parseInt(e.target.value, 10)
        if (isRunning) startTimer()
    })

    // Start on step 0
    applyState(0)
    startTimer()
</script>

Invalid

Code
<style>
    .demo-row {
        display: flex;
        flex-direction: column;
        gap: 24px;
    }
</style>

<div class="demo-row">
    <mdc-field variant="filled" label="Valid">
        <input type="text" value="hello" />
    </mdc-field>

    <mdc-field variant="filled" label="Invalid" invalid error-text="This field has an error">
        <input type="text" value="bad" />
    </mdc-field>

    <mdc-field variant="outlined" label="Invalid (outlined)" invalid error-text="Please enter a valid email">
        <input type="email" value="not-an-email" />
    </mdc-field>
</div>

Label

Code
<style>
    .demo-row {
        display: flex;
        flex-direction: column;
        gap: 24px;
    }
</style>

<div class="demo-row">
    <mdc-field variant="filled" label="Email address">
        <input type="email" />
    </mdc-field>

    <mdc-field variant="filled" label="Email address" required>
        <input type="email" />
    </mdc-field>

    <mdc-field variant="filled" label="Email address" required no-asterisk>
        <input type="email" />
    </mdc-field>

    <mdc-field variant="filled">
        <input type="text" />
    </mdc-field>
</div>

Leading Icon

Code
<style>
    .demo-row {
        display: flex;
        flex-direction: column;
        gap: 24px;
    }
</style>

<div class="demo-row">
    <mdc-field variant="filled" label="Search">
        <mdc-icon slot="leading-icon">search</mdc-icon>
        <input type="search" />
    </mdc-field>

    <mdc-field variant="filled" label="Search">
        <mdc-icon-button slot="leading-icon">
            <mdc-icon>menu</mdc-icon>
        </mdc-icon-button>
        <input type="search" />
    </mdc-field>

    <mdc-field variant="filled" label="No icon">
        <input type="text" />
    </mdc-field>
</div>

Populated

Code
<style>
    .demo-row {
        display: flex;
        flex-direction: column;
        gap: 24px;
    }
</style>

<div class="demo-row">
    <mdc-field variant="filled" label="Empty">
        <input type="text" />
    </mdc-field>

    <mdc-field variant="filled" label="Populated" populated>
        <input type="text" value="hello world" />
    </mdc-field>

    <mdc-field variant="outlined" label="Empty (outlined)">
        <input type="text" />
    </mdc-field>

    <mdc-field variant="outlined" label="Populated (outlined)" populated>
        <input type="text" value="hello world" />
    </mdc-field>
</div>

Prefix Text

Code
<style>
    .demo-row {
        display: flex;
        flex-direction: column;
        gap: 24px;
    }
</style>

<div class="demo-row">
    <mdc-field variant="filled" label="Price" prefix-text="$">
        <input type="number" value="0.00" />
    </mdc-field>

    <mdc-field variant="filled" label="Website">
        <span slot="prefix">https://</span>
        <input type="url" value="example.com" />
    </mdc-field>

    <mdc-field variant="filled" label="Weight" prefix-text="Weight">
        <span slot="prefix"><mdc-icon>scale</mdc-icon></span>
        <input type="number" value="70" />
    </mdc-field>
</div>

Required

Code
<style>
    .demo-row {
        display: flex;
        flex-direction: column;
        gap: 24px;
    }
</style>

<div class="demo-row">
    <mdc-field variant="filled" label="Email" required>
        <input type="email" />
    </mdc-field>

    <mdc-field variant="filled" label="Email" required no-asterisk>
        <input type="email" />
    </mdc-field>

    <mdc-field variant="outlined" label="Password" required>
        <input type="password" />
    </mdc-field>
</div>

Suffix Text

Code
<style>
    .demo-row {
        display: flex;
        flex-direction: column;
        gap: 24px;
    }
</style>

<div class="demo-row">
    <mdc-field variant="filled" label="Amount" suffix-text=".00">
        <input type="number" value="0" />
    </mdc-field>

    <mdc-field variant="filled" label="Weight">
        <input type="number" value="70" />
        <span slot="suffix">kg</span>
    </mdc-field>

    <mdc-field variant="filled" label="Email">
        <input type="email" value="user" />
        <span slot="suffix"><mdc-icon>mail</mdc-icon></span>
    </mdc-field>
</div>

Supporting Text

Code
<style>
    .demo-row {
        display: flex;
        flex-direction: column;
        gap: 24px;
    }
</style>

<div class="demo-row">
    <mdc-field variant="filled" label="Username" supporting-text="Choose a unique username">
        <input type="text" />
    </mdc-field>

    <mdc-field variant="filled" label="Email">
        <input type="email" />
    </mdc-field>
</div>

Trailing Icon

Code
<style>
    .demo-row {
        display: flex;
        flex-direction: column;
        gap: 24px;
    }
</style>

<div class="demo-row">
    <mdc-field variant="filled" label="Search" populated>
        <input type="search" value="hello" />
        <mdc-icon slot="trailing-icon">close</mdc-icon>
    </mdc-field>

    <mdc-field variant="filled" label="Password">
        <input type="password" value="secret" />
        <mdc-icon slot="trailing-icon">visibility</mdc-icon>
    </mdc-field>

    <mdc-field variant="filled" label="No trailing icon">
        <input type="text" />
    </mdc-field>
</div>

Variant

Code
<style>
    .demo-row {
        display: flex;
        gap: 32px;
        align-items: flex-start;
        flex-wrap: wrap;
    }
    .demo-row > * {
        flex: 1 1 240px;
        min-width: 240px;
    }
</style>

<div class="demo-row">
    <mdc-field variant="filled" label="Filled">
        <input type="text" />
    </mdc-field>

    <mdc-field variant="outlined" label="Outlined">
        <input type="text" />
    </mdc-field>
</div>