--- name: bulma-java description: Use when writing Java code that generates HTML with Bulma CSS components using the bulma-java library (com.github.t1:bulma-java). Triggers include imports of com.github.t1.bulmajava or com.github.t1.htmljava, or when generating server-side HTML with Bulma styling. --- # bulma-java Type-safe, fluent Java API for generating HTML with Bulma CSS components. Zero runtime dependencies in core. ## Maven ```xml com.github.t1 bulma-java ${bulma-java.version} ``` This is the only dependency you need. It transitively includes `java-html` which provides the core HTML elements (`div`, `ul`, `li`, `span`, `p`, `strong`, `em`, `html`, etc.) — all under the `com.github.t1.htmljava` package. Both packages are part of the same library. ## Quick Reference — Imports ```java // Core HTML (provided by java-html, included transitively) import static com.github.t1.htmljava.Html.html; import static com.github.t1.htmljava.HtmlBasics.*; // div, span, p, ul, li, h1-h6, strong, em, nav, header, footer, etc. import static com.github.t1.htmljava.Anchor.a; // Bulma layout import static com.github.t1.bulmajava.layout.Section.section; import static com.github.t1.bulmajava.layout.Container.container; import static com.github.t1.bulmajava.layout.Hero.hero; // Bulma columns import static com.github.t1.bulmajava.columns.Columns.columns; import static com.github.t1.bulmajava.columns.Column.column; // Bulma elements import static com.github.t1.bulmajava.elements.Title.*; // title(), subtitle() import static com.github.t1.bulmajava.elements.Button.button; import static com.github.t1.bulmajava.elements.Box.box; import static com.github.t1.bulmajava.elements.Tag.*; // tag(), tags(), tagsAddon() import static com.github.t1.bulmajava.elements.Block.block; import static com.github.t1.bulmajava.elements.Content.content_; import static com.github.t1.bulmajava.elements.Delete.delete; import static com.github.t1.bulmajava.elements.Icon.icon; import static com.github.t1.bulmajava.elements.Image.*; // image(), img(), figure() import static com.github.t1.bulmajava.elements.Notification.notification; import static com.github.t1.bulmajava.elements.ProgressBar.progress; import static com.github.t1.bulmajava.elements.Table.*; // table(), row(), td(), th(), tbody() // Bulma components import static com.github.t1.bulmajava.components.Navbar.navbar; import static com.github.t1.bulmajava.components.Menu.menu; import static com.github.t1.bulmajava.components.Breadcrumb.breadcrumb; import static com.github.t1.bulmajava.components.Dropdown.dropdown; import static com.github.t1.bulmajava.components.Message.message; import static com.github.t1.bulmajava.components.Pagination.pagination; import static com.github.t1.bulmajava.components.Panel.panel; // Bulma layout (additional) import static com.github.t1.bulmajava.layout.Footer.footer; import static com.github.t1.bulmajava.layout.Level.level; import static com.github.t1.bulmajava.layout.Media.media; // Bulma grid import static com.github.t1.bulmajava.grid.Grid.*; // grid(), fixedGrid(), cell() // Bulma form import static com.github.t1.bulmajava.form.Form.form; import static com.github.t1.bulmajava.form.Field.field; import static com.github.t1.bulmajava.form.Input.input; import static com.github.t1.bulmajava.form.InputType.*; import static com.github.t1.bulmajava.form.Checkbox.checkbox; import static com.github.t1.bulmajava.form.Select.select; import static com.github.t1.bulmajava.form.Textarea.textarea; // Modifiers import static com.github.t1.bulmajava.basic.Color.*; // PRIMARY, LINK, INFO, SUCCESS, WARNING, DANGER import static com.github.t1.bulmajava.basic.Size.*; // SMALL, NORMAL, MEDIUM, LARGE import static com.github.t1.bulmajava.basic.Style.*; // LIGHT, DARK, ROUNDED, FULLWIDTH, etc. ``` ## Element Types Type hierarchy: `Renderable` → `AbstractElement` → `Element` - `HtmlBasics.*` factories (`div()`, `ul()`, `li()`, `span()`, `p()`, etc.) return `com.github.t1.htmljava.Element` - `Element` extends `AbstractElement` which has all the builder methods: `.content()`, `.attr()`, `.id()`, `.classes()`, `.style()`, etc. - `Renderable` is the base interface — has only `.render()`. Use it for return types or collections, but you lose builder methods. - Bulma components (`section()`, `container()`, `button()`, etc.) return their own types extending `AbstractElement` **Use `Element` (not `Renderable`) when you need to chain builder methods:** ```java import com.github.t1.htmljava.Element; Element list=ul(); list.content(li("item 1")); // .content() works on Element list.attr("role","tree"); // .attr() works on Element list.style("display:none"); // .style() works on Element list.id("my-list"); // .id() works on Element list.classes("custom"); // .classes() works on Element // For mixed collections or return types where you don't need builder methods: import com.github.t1.htmljava.Renderable; Renderable fragment = div().content(p("Hello")); ``` **Key `.content()` overloads on `AbstractElement`:** - `.content(String)` — text content - `.content(Renderable)` — single child - `.content(Renderable...)` — varargs children - `.content(Collection)` — collection of children - `.content(Stream)` — stream of children **Content querying methods on `AbstractElement`:** - `.content()` — returns the raw `Renderable` content (null if empty) - `.contentStream()` — returns `Stream` of all children (empty stream if none) - `.contentIsA(Class)` — tests if content is of a specific type - `.contentAs(Class)` — casts content to a specific type - `.findElement(String className)` — finds child by CSS class, returns `Optional>` - `.findElement(Predicate>)` — finds child by predicate, returns `Optional` - `.getOrCreate(String className)` — gets existing child by class or creates a default div - `.getOrCreate(String className, Supplier)` — gets or creates with custom factory - `.getOrCreate(Predicate>, Supplier)` — gets or creates with predicate - `.notClasses(String...)` — removes CSS classes; removes the `class` attribute entirely if empty - `.hasAttribute(String key)` — checks if attribute with given key exists (on `AbstractElement` directly) - `.hasAttribute(String key, String value)` — checks if attribute with given key and value exists (on `AbstractElement` directly) - `.findAttribute(String name)` — returns `Optional` for the named attribute - `.attributes()` — returns the `@NonNull Attributes` object (never null) - `.hasAttribute(String key)` — checks if an attribute with the given key exists - `.hasAttribute(String key, String value)` — checks if an attribute with the given key and value exists - `.findAttribute(Predicate)` — returns `Optional` ## Rendering Call `.render()` on any element. Returns a `String`. ```java // Full page — produces ... String page = html("Page Title").body(div().content(p("Hello"))).render(); // Fragment — no doctype/html/head wrapper String fragment = div().content(p("Hello")).render(); ``` ## Building Pages ```java html("My App") .stylesheet("https://cdn.jsdelivr.net/npm/bulma@1.0.0/css/bulma.min.css") .script("app.js") .body( section().content(container().content( title("Welcome"), p("Hello world") )) ) .render(); ``` ### Adding Body Content There are several ways to add content to the `` of an `Html` page, each useful in different situations: **Multiple elements** — the most common case with several top-level children: ```java html("My App").body(navbar(), section(), footer()) ``` **Single element** — when the body has one root element: ```java html("My App").body(section().content(title("Hello"))) ``` **Chained calls** — building up the body incrementally: ```java html("My App") .body(navbar()) .body(section()) .body(footer()) ``` **Implicit routing** — `content()` on `Html` automatically routes to the body: ```java html("My App").content(h1("Hello")) // equivalent to .body(h1("Hello")) ``` **Body with attributes** — when you need classes or attributes on the `` tag itself, pass an explicit `Body` element via `content()`: ```java html("My App").content(body().has(NAVBAR_FIXED_TOP).content( container().content(section().content(title("Hello"))) )) ``` **Functional modification** — an alternative for setting body attributes inline: ```java html("My App").body(e -> e.classes("custom").content(h1("Hello"))) ``` **Positional insertion** — insert at a specific position (0 = first): ```java html("My App").body(section()).body(navbar(), 0) // navbar before section ``` **Retrieve and mutate** — get the existing body element for later modification: ```java var page = html("My App").body(section()); page.body().content(footer()); // add to existing body ``` ## Custom Attributes ```java div(). id("main"). classes("custom-class"). attr("data-value","42"). attr("hx-get","/api") a("Link text"). href("/path") // Anchor has a dedicated .href() method ``` ## Columns (Responsive) ```java // Auto-sized columns columns(). content( column(). content(p("Left")), column(). content(p("Right")) ) // Sized columns — use .classes() for Bulma column size classes column(). classes("is-one-third"). content(sidebar) column(). classes("is-two-thirds"). content(main) // Desktop-only side-by-side (stacks on mobile/tablet) columns(). classes("is-desktop"). content( column(). classes("is-one-quarter"). content(sidebar), column(). content(mainContent) ) ``` Available size classes: `is-1` through `is-12`, `is-one-third`, `is-two-thirds`, `is-one-quarter`, `is-three-quarters`, `is-half`, `is-narrow`. ## Forms ```java form(). post("/submit"). content( field("Username"). content(input(TEXT). attr("name","user"). placeholder("Enter name")), field("Email"). content(input(EMAIL). attr("name","email")) . help("We won't share this"), field("Role"). content(select("role") . option("admin","Admin") . option("user","User")), field(). content(button("Submit"). is(PRIMARY)) ) ``` Key form patterns: - `field(label)` creates labeled field with a plain string; `field()` for no label - `.label(Renderable...)` sets a rich label with arbitrary content (e.g. spans, tags). The label is rendered as `