E-Components
E-Components are reusable, Ethereum-specific components that encapsulate common patterns across explorations. They live in src/eComponents/ and are designed to let you build new explorations quickly without duplicating logic.
While the shared UI components (src/eComponents/ui/) provide generic building blocks like buttons and input fields, E-Components go a level higher: they package complete Ethereum-domain patterns — precompile testing interfaces, bytecode steppers, and more — into components with a clean configuration API.
For the list of ready-to-use E-Components, see Available E-Components.
Integration Contract
Each E-Component follows a shared integration model. Understanding this contract helps you wire explorations consistently and know where to add custom behavior.
| Concern | Where it lives | Pattern |
|---|---|---|
| Page chrome | E-Component | Wraps ExplorationC (title, intro, examples, powered-by) |
| Variation between explorations | config.ts in the exploration folder | Typed config object, testable separately |
| Library / execution ownership | Exploration (MyC.vue and exploration-local modules) | Exploration creates EVM instances, run callbacks, or fork-specific setup; E-Component receives them as props |
| Domain-specific visualization | Exploration | Via slots or companion components wired into the E-Component |
| Shared runtime state | E-Component composable, optionally exposed via provide/inject | For panels that need live state without prop-drilling |
Standard Props
Most E-Components accept a common set of props:
| Prop | Description |
|---|---|
config | Exploration-specific configuration (see the E-Component's config type) |
examples | Example presets from the exploration's examples.ts |
exploration | Metadata from the exploration's info.ts |
Beyond these, E-Components accept props for exploration-owned execution — for example a run callback or a pre-configured EVM instance. E-Components do not import third-party libraries themselves; see Third-Party Libraries.
Extension Points
E-Components deliberately cover repeatable patterns, not every pedagogical idea an exploration might need. When the core API is not enough, use the E-Component's extension hooks before wrapping or forking it:
| Mechanism | Best for | Notes |
|---|---|---|
| Scoped slots | Custom UI at a specific render point inside the E-Component | Slot props pass data back to the exploration (e.g. execution results) |
| Named layout slots | Additional panels or regions alongside the core UI | Mount exploration-local components inside the slot |
| Provide/inject context | Companion panels that react to live runtime state | Injection only works for descendants — extension UI must be mounted inside the E-Component's slot tree, not as a sibling next to it |
Keep exploration-specific teaching UI, helpers, and domain logic in the exploration folder. Promote code to a shared utility or E-Component only when a second exploration needs the same thing.
How E-Components Work
Each E-Component is a self-contained folder in src/eComponents/ with a consistent internal structure:
src/eComponents/<name>EC/
├── <Name>EC.vue # Main component (the primary entry point)
├── types.ts # Configuration interfaces
├── use<Name>.ts # Composable: shared state and logic
├── <Name><Sub>EC.vue # Optional sub-components
└── <utility>.ts # Optional utility modulesNaming Convention
E-Component folders and files are post-fixed with EC (for E-Component):
- Folder:
src/eComponents/precompileInterfaceEC/ - Main component:
PrecompileInterfaceEC.vue - Sub-components:
PrecompileInterfaceResultEC.vue,PrecompileValueInputEC.vue - Composable:
usePrecompileState.ts - Types:
types.ts
Using an E-Component in Your Exploration
The typical pattern is:
- Check Available E-Components for a matching building block
- Define a
config.tsdescribing your specific use case - Wire execution in
MyC.vue(EVM setup,runfunction, etc.) - Render the E-Component with config, examples, and exploration metadata
- Add exploration-local UI via slots or companion components if needed
This keeps MyC.vue short and declarative — often under 30 lines for straightforward cases. See Adding an Exploration for the full walkthrough.
Composing E-Components
Today, each major E-Component wraps the full exploration shell (ExplorationC). That means one primary E-Component per exploration is the supported, documented path.
Exploration-specific additions compose on top of that E-Component via slots and inject — not by nesting two full E-Components side by side.
As the project grows, we expect explorations that combine capabilities from multiple E-Components (for example, a precompile comparison alongside a bytecode walkthrough). To prepare for that:
- E-Component authors should separate "page chrome" from "capability" where feasible — sub-components that can be used standalone, not only as part of the full wrapper
- Exploration authors should keep custom additions local until a composition pattern is established project-wide
- Future direction: an exploration-level layout that owns
ExplorationConce and hosts multiple E-Component fragments
If you are designing an E-Component or an exploration that might need multi-component composition, open an issue to discuss the approach before investing in a one-off structure.
Creating a New E-Component
If you spot a pattern shared across two or more explorations, it is a strong candidate for a new E-Component. Contributions of new E-Components are very welcome — they directly help other contributors build explorations faster.
Steps
- Create a folder in
src/eComponents/following the naming convention:<name>EC/ - Define a
types.tswith a configuration interface that captures the variation between use cases - Extract shared logic into a composable (
use<Name>.ts) - Build the component(s) following the integration contract above
- Document usage on the Available E-Components page
Design Principles
A good E-Component should:
- Accept a config object rather than many individual props — this keeps the consumer API minimal and easy to extend
- Provide sensible defaults where possible, so simple use cases stay simple
- Expose clear extension hooks — slots and/or typed inject context for exploration-local additions
- Keep execution ownership in the exploration — accept callbacks or library instances as props, never import third-party libraries directly
- Keep the consumer's
MyC.vueshort and declarative — ideally config + wiring + a single component tag - Encapsulate state and logic in a composable, keeping the Vue component focused on rendering
- Favor composable fragments over monolithic widgets — sub-components usable on their own make future multi-E-Component explorations easier
Ideas for Future E-Components
Some patterns that might become E-Components as the project grows:
- Transaction builder — interactive transaction construction and signing
- Gas calculator — compare gas costs across hardforks for different operations
- Storage layout — visualize contract storage slot changes
If you are interested in building any of these (or have other ideas), feel free to open an issue to discuss the design.