Components
hop implements a strongly typed component system.
Defining and using components
Components are defined by placing them at the outermost scope of a .hop file. To render a component inside another component, simply refer to it by name.
// 1. Define a component called Greeting
<Greeting {subject: String}>
<div>Hello {subject}!</div>
</Greeting>
// 2. Define another component
<AnotherComponent>
// 3. Render the Greeting component
<Greeting {subject: "world"} />
</AnotherComponent>Importing components
In hop, every .hop file corresponds to a module.
The import declaration imports a component from another module.
import user_list::{
UserList,
}
<Index>
<UserList {users: ["jane", "tobi"]} />
</Index>All components are visible to other modules by default. To disallow other modules from importing a component, prefix it with Internal, e.g. <InternalButton>.
Styling components
hop uses Tailwind 4 for styling. The hop compiler compiles Tailwind to CSS natively, so no external dependencies need to be installed.
To add CSS classes to an HTML element, use the class attribute.
<Component {css: String}>
<div class="p-2 bg-green-300">
// ...
</div>
</Component>If you have multiple CSS classes it is idiomatic to break them up into multiple strings and use the classes! macro to concatenate them.
<div class={
classes!(
"inline-flex",
"items-center",
"justify-center",
"rounded-full",
"border",
"px-2",
"py-0.5",
"text-xs",
"font-medium",
"w-fit",
"whitespace-nowrap",
"overflow-hidden",
)
}>Passing children to a component
To make a component accept children, declare a parameter called children.
// 1. Define a component that accepts children
<Button {children: HTMLNode}>
<button class="border p-2 flex gap-2">
{children}
</button>
</Button>
<Component>
// 2. Render the Button component
<Button>
<IconBack /> Go back
</Button>
</Component>Iterating over data
The <for> tag renders its content once for each item in an array.
<Component {items: Array[String]}>
<for {item in items}>
<div>{item}</div>
</for>
</Component>Conditional rendering
The <if> tag renders its content when a condition is true.
<Component {year: Int}>
<if {year < 2000}>
<div>The year is in a previous millenium</div>
</if>
</Component>The <match> tag is used to match an expression to a certain form.
<Component {name: Option[String]}>
<match {name}>
<case {Some(n)}>
Name is {n}
</case>
<case {None}>
Unknown name
</case>
</match>
</Component>