Inputs
Form elements, buttons, and handling user interactions in Hypen
Inputs
Input components allow users to interact with your application through forms, buttons, and other controls.
Button
A clickable element that triggers an action when pressed.
Button { Text("Submit") }
.onClick(@actions.submit)Styling Buttons
// Primary button
Button { Text("Primary Action") }
.onClick(@actions.primary)
.backgroundColor("#3B82F6")
.padding(horizontal: 24, vertical: 12)
.borderRadius(8)
// Secondary/outline button
Button { Text("Secondary") }
.onClick(@actions.secondary)
.backgroundColor("transparent")
.borderWidth(1)
.borderColor("#3B82F6")
.padding(horizontal: 24, vertical: 12)
.borderRadius(8)Button with Icon
Button {
Row {
Image("cart-icon.svg").size(20)
Text("Add to Cart")
}
.gap(8)
}
.onClick(@actions.addToCart)Disabled State
Button { Text("Submit") }
.onClick(@actions.submit)
.disabled(${state.isSubmitting})
.opacity(${state.isSubmitting} ? 0.5 : 1)Platform Support: Web, Android, iOS
Input
A single-line text input field.
Input(placeholder: "Enter your name")
.onInput(@actions.updateName)Input Events
Input(placeholder: "Email address")
.value(${state.email})
.onInput(@actions.updateEmail)
.onFocus(@actions.emailFocused)
.onBlur(@actions.emailBlurred)Enter Key Handling
Input(placeholder: "Search...")
.onInput(@actions.updateSearch)
.onKey(@actions.submitSearch)The onKey event fires when the Enter key is pressed.
Styling Inputs
Input(placeholder: "Username")
.padding(12)
.borderWidth(1)
.borderColor("#E5E7EB")
.borderRadius(6)
.fontSize(16)Platform Support: Web, Android, iOS
Textarea
A multi-line text input field for longer content.
Textarea(placeholder: "Enter your message...")
.onInput(@actions.updateMessage)
.height(120)
.padding(12)
.borderRadius(8)Textarea with Character Limit
Column {
Textarea(placeholder: "Bio (max 200 characters)")
.value(${state.bio})
.onInput(@actions.updateBio)
.height(100)
Text("${state.bio.length}/200")
.fontSize(12)
.color("#6B7280")
.textAlign("right")
}Platform Support: Web, Android, iOS
Checkbox
A toggleable checkbox for boolean selections.
Checkbox {}
.checked(${state.agreeToTerms})
.onChange(@actions.toggleTerms)Checkbox with Label
Row {
Checkbox {}
.checked(${state.rememberMe})
.onChange(@actions.toggleRememberMe)
Text("Remember me")
}
.gap(8)
.alignItems("center")Platform Support: Web, Android, iOS
Switch
A toggle switch for binary on/off settings.
Switch {}
.checked(${state.darkMode})
.onChange(@actions.toggleDarkMode)Switch with Label
Row {
Text("Dark Mode")
Spacer()
Switch {}
.checked(${state.darkMode})
.onChange(@actions.toggleDarkMode)
}
.padding(16)Platform Support: Web, Android, iOS
Select
A dropdown selection component.
Select {}
.value(${state.country})
.onChange(@actions.updateCountry)Platform Support: Web, Android, iOS
Slider
A range slider for numeric input.
Slider {}
.value(${state.volume})
.onChange(@actions.updateVolume)Slider with Value Display
Column {
Text("Volume: ${state.volume}%")
Slider {}
.value(${state.volume})
.onChange(@actions.updateVolume)
}
.gap(8)Platform Support: Web, Android, iOS
Form Example
A complete form with multiple input types:
module ContactForm {
Column {
Text("Contact Us")
.fontSize(24)
.fontWeight("bold")
Input(placeholder: "Name")
.value(${state.name})
.onInput(@actions.updateName)
.padding(12)
.borderRadius(6)
.borderWidth(1)
.borderColor("#E5E7EB")
Input(placeholder: "Email")
.value(${state.email})
.onInput(@actions.updateEmail)
.padding(12)
.borderRadius(6)
.borderWidth(1)
.borderColor("#E5E7EB")
Textarea(placeholder: "Message")
.value(${state.message})
.onInput(@actions.updateMessage)
.height(120)
.padding(12)
.borderRadius(6)
.borderWidth(1)
.borderColor("#E5E7EB")
Row {
Checkbox {}
.checked(${state.subscribe})
.onChange(@actions.toggleSubscribe)
Text("Subscribe to newsletter")
}
.gap(8)
Button { Text("Send Message") }
.onClick(@actions.submit)
.backgroundColor("#3B82F6")
.padding(horizontal: 24, vertical: 12)
.borderRadius(8)
.fillMaxWidth(true)
}
.gap(16)
.padding(24)
.maxWidth(500)
}Handling Form State
import { app } from "@hypen-space/core";
interface FormState {
name: string;
email: string;
message: string;
subscribe: boolean;
isSubmitting: boolean;
}
export default app
.defineState<FormState>({
name: "",
email: "",
message: "",
subscribe: false,
isSubmitting: false
})
.onAction("updateName", async ({ action, state }) => {
state.name = action.payload.value;
})
.onAction("updateEmail", async ({ action, state }) => {
state.email = action.payload.value;
})
.onAction("updateMessage", async ({ action, state }) => {
state.message = action.payload.value;
})
.onAction("toggleSubscribe", async ({ state }) => {
state.subscribe = !state.subscribe;
})
.onAction("submit", async ({ state }) => {
state.isSubmitting = true;
try {
await fetch("/api/contact", {
method: "POST",
body: JSON.stringify({
name: state.name,
email: state.email,
message: state.message,
subscribe: state.subscribe
})
});
// Reset form
state.name = "";
state.email = "";
state.message = "";
state.subscribe = false;
} finally {
state.isSubmitting = false;
}
});Next Steps
- Styling - Complete applicator reference
- State & Modules - State management
- Components - All built-in components