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. The class attribute of HTML elements accepts multiple arguments which are merged and deduplicated during compilation.
<Component {css: String}>
<div class={"p-2 bg-green-300", css}>
// ...
</div>
</Component>
<AnotherComponent>
<Component {css: "mb-4"} />
</AnotherComponent>If you have a large number of CSS classes you can break them up into separate strings to improve readability.
<div class={
"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>