Modular Interaction Layer (MIL)

- Published on
Decoupling Interaction from Implementation
Overview
The Modular Interaction Layer (MIL) introduces a powerful abstraction for defining, managing, and orchestrating user interactions in a completely decoupled and composable manner. It allows UI developers to describe how interfaces respond to user intent, without hardwiring interaction logic to specific components, views, or platforms.
MIL provides a declarative interaction protocol where individual units of user interaction (taps, inputs, selections, gestures, voice, etc.) are captured and processed by reusable, platform-agnostic interaction modules. These modules can be registered, composed, and reused across any frontend surface or rendering context.
Why MIL?
Traditionally, UI interaction is entangled with components:
- Event handlers live next to JSX or HTML
- Gesture logic is embedded in views
- Component trees define interaction flows
This tight coupling introduces friction:
- Harder to reuse logic across components or platforms
- Difficult to test or trace
- Rewriting the same logic for web, native, and embedded
MIL solves this by turning interactions into modular, testable units that exist alongside rendering—not inside it.
Core Principles
Interaction as Modules
Events likeclick
,swipe
,submit
,select
,voice command
are mapped to standalone functions (or finite state machines) that handle behavior.Composition over Conditionals
Complex behaviors are composed from smaller interactions instead of deeply nested handlers.Platform Abstraction
Inputs and gestures are abstracted into canonical actions (onSelect
,onTrigger
, etc.), mapped differently for web, mobile, or AR/VR.Declarative Interaction Binding
Components declare which interaction modules they want to use—not how they implement it.
Conceptual Architecture
[User Event]
↓
[Input Adapter (web, mobile, voice)]
↓
[Interaction Module (MIL)]
↓
[Behavior Pipeline]
↓
[Effect: State Change, Command, Animation, Navigation]
Code Example: Declarative Interaction Handling
Let’s say we want to handle a login form submission.
1. Create a Modular Interaction
// interactions/onLoginSubmit.js
export const onLoginSubmit = ({ emit, getState, run }) => async () => {
const { username, password } = getState('form');
emit('login:started');
try {
const result = await run('authService.login', { username, password });
emit('login:success', result);
} catch (error) {
emit('login:failed', error);
}
};
2. Declare Interaction in Component
// LoginForm.jsx
import { useInteraction } from 'mil-react';
import { onLoginSubmit } from '../interactions/onLoginSubmit';
export function LoginForm() {
const [form, setForm] = useState({ username: '', password: '' });
const handleSubmit = useInteraction(onLoginSubmit, {
getState: (key) => key === 'form' ? form : undefined,
run: async (service, data) => {
if (service === 'authService.login') {
return fetch('/api/login', {
method: 'POST',
body: JSON.stringify(data),
headers: { 'Content-Type': 'application/json' }
}).then((res) => res.json());
}
},
emit: (event, payload) => console.log(event, payload),
});
return (
<form onSubmit={(e) => { e.preventDefault(); handleSubmit(); }}>
<input
type="text"
value={form.username}
onChange={(e) => setForm({ ...form, username: e.target.value })}
placeholder="Username"
/>
<input
type="password"
value={form.password}
onChange={(e) => setForm({ ...form, password: e.target.value })}
placeholder="Password"
/>
<button type="submit">Login</button>
</form>
);
}
Input Adapters
Adapters translate native inputs into MIL interaction triggers:
Input Surface | Adapter Behavior |
---|---|
Web Browser | Maps onClick , onChange , onSubmit to canonical events |
Mobile | Maps touch , gesture , keyboard |
Voice UI | Converts spoken commands to triggers |
Game/Embedded | Maps controller or sensor input |
Interaction Module Types
- Trigger Module: Single action (e.g. button press)
- Gesture Module: Multi-step input (e.g. drag, swipe)
- FSM Module: Stateful flow (e.g. multi-step form)
- Declarative Flow: DSL-like structure for describing complex behaviors
Use Cases for MIL
- 🔁 Reusable Interactions across components, apps, platforms
- 📱 Cross-Device Gesture Handling
- 🎙️ Voice to UI Control Mapping
- 🧪 Easy Unit Testing of interaction logic
- 🧩 Composable UX Patterns (e.g. tooltips, modals, onboarding)
- 🧠 Behavior-Driven Development (BDD) at the interaction level
Benefits of MIL
✅ Clear separation of interaction and UI
✅ Easier to test, compose, and reuse logic
✅ Platform-agnostic handling of input and feedback
✅ Reduces boilerplate in components
✅ Declarative and scalable interaction mapping
Integration with Other Layers
- With CEL: MIL triggers composable execution flows
- With APC: MIL drives dynamic presentation logic
- With UIF: MIL maps user input into cross-channel intent
- With CSEE: MIL interactions trigger surface-aware executions
Conclusion
The Modular Interaction Layer (MIL) redefines how we architect UI interactions—decoupling them from components, enabling reuse, and elevating them to first-class modular logic in your application stack.
It’s a key building block in composable systems, empowering teams to deliver scalable, maintainable, and cross-platform user experiences.