SemanticUI DSL
A Kotlin DSL for the FomanticUI CSS framework.
Write ui.blue.button instead of class="ui blue button".
How it works
The DSL starts with ui (or noui for non-UI classes) and chains modifiers using Kotlin properties:
// This:
ui.inverted.blue.segment {
ui.header H2 { +"Welcome" }
ui.basic.button { +"Click me" }
}
// Generates this HTML:
// <div class="ui inverted blue segment">
// <h2 class="ui header">Welcome</h2>
// <button class="ui basic button">Click me</button>
// </div> Every modifier is a Kotlin property that adds a CSS class. The final call (segment {}, button {}, header H2 {}) creates the HTML element and opens a block for its children.
Core elements
Buttons
ui.button { +"Default" }
ui.blue.button { +"Blue" }
ui.basic.green.button { +"Outlined green" }
ui.icon.button { icon.heart() }
ui.labeled.icon.button { icon.download(); +"Download" }
// Button group
ui.buttons {
ui.button { +"One" }
ui.button { +"Two" }
ui.button { +"Three" }
} Segments
ui.segment { +"Basic segment" }
ui.raised.segment { +"Raised" }
ui.padded.segment { +"Extra padding" }
ui.inverted.segment { +"Dark background" }
ui.placeholder.segment { +"Empty state placeholder" }
// Stacked segments
ui.segments {
ui.segment { +"First" }
ui.segment { +"Second" }
} Headers
ui.header H1 { +"Page title" }
ui.header H2 { +"Section header" }
ui.sub.header { +"Sub-header" }
ui.icon.header {
icon.settings()
noui.content { +"Settings" }
} Grid system
ui.two.column.grid {
noui.column {
+"Left column"
}
noui.column {
+"Right column"
}
}
// Responsive
ui.four.column.doubling.stackable.grid {
noui.column { +"A" }
noui.column { +"B" }
noui.column { +"C" }
noui.column { +"D" }
} Cards
ui.three.cards {
noui.card {
noui.content {
ui.header { +"Card title" }
noui.description { +"Card content" }
}
noui.extra.content {
icon.user()
+"4 members"
}
}
} Labels
ui.label { +"Default" }
ui.red.label { +"Error" }
ui.green.label { +"Success" }
ui.circular.blue.label { +"42" } Menus
ui.vertical.inverted.menu {
noui.item A {
onClick { evt -> router.navToUri(evt, Nav.home()) }
+"Home"
}
noui.item A {
onClick { evt -> router.navToUri(evt, Nav.about()) }
+"About"
}
} Tables
ui.celled.table Table {
thead {
tr {
th { +"Name" }
th { +"Status" }
}
}
tbody {
users.forEach { user ->
tr {
td { +user.name }
td { ui.green.label { +"Active" } }
}
}
}
} Conditional styling
The given() modifier applies styles based on a condition:
// Disable button when form is invalid
ui.blue.button.given(!isValid) { disabled }.then {
onClick { submit() }
+"Submit"
}
// Highlight active menu item
ui.item.given(isActive) { active }.then A {
+"Dashboard"
}
// Add loading state
ui.button.given(isLoading) { loading }.then {
+"Save"
} How it reads: "A blue button, given it's not valid, make it disabled, then render it."
Colors
16 named colors plus brand colors:
ui.red.label { +"Red" }
ui.orange.label { +"Orange" }
ui.yellow.label { +"Yellow" }
ui.olive.label { +"Olive" }
ui.green.label { +"Green" }
ui.teal.label { +"Teal" }
ui.blue.label { +"Blue" }
ui.violet.label { +"Violet" }
ui.purple.label { +"Purple" }
ui.pink.label { +"Pink" }
ui.brown.label { +"Brown" }
ui.grey.label { +"Grey" }
ui.black.label { +"Black" }
ui.white.label { +"White" } Sizes
ui.mini.button { +"Mini" }
ui.tiny.button { +"Tiny" }
ui.small.button { +"Small" }
ui.medium.button { +"Medium" }
ui.large.button { +"Large" }
ui.big.button { +"Big" }
ui.huge.button { +"Huge" }
ui.massive.button { +"Massive" } Icons
FomanticUI includes Font Awesome icons:
icon.home()
icon.user()
icon.search()
icon.trash()
icon.check_circle()
icon.exclamation_circle()
icon.sign_out_alternate()
icon.grip_vertical()
icon.eraser()
icon.dollar_sign()
icon.heart()
icon.settings()
icon.download() Modals
ui.button {
onClick {
modals.show { handle ->
OkCancelModal {
mini(
handle = handle,
header = { ui.header { +"Confirm" } },
content = {
ui.content {
+"Are you sure you want to delete this?"
}
},
) { result ->
when (result) {
OkCancelModal.Result.Ok -> deleteItem()
OkCancelModal.Result.Cancel -> { /* do nothing */ }
}
}
}
}
}
+"Delete"
} Modal sizes: mini(), tiny(), small(), large(), and full-size.
Toast notifications
// Info toast
toasts.info("Settings saved successfully")
// Warning
toasts.warning("Your session expires in 5 minutes")
// Error
toasts.error("Failed to save changes")
// Random type
toasts.append(Message.Type.entries.random(), "Some message") Context menus and popups
// Context menu on right-click
ui.segment {
onContextMenuStoppingEvent { evt ->
popups.showContextMenu(evt, PopupsManager.Positioning.BottomLeft) {
ui.vertical.menu {
noui.item { +"Copy" }
noui.item { +"Paste" }
noui.item { +"Delete" }
}
}
}
+"Right-click me"
}
// Hover popup
ui.button {
popups.showHoverPopup.topLeft(tag = this) {
+"This is a tooltip"
}
+"Hover me"
} Custom CSS
Combine the DSL with inline CSS when needed:
div {
css {
marginTop = 16.px
marginLeft = 250.px
width = 100.pct
height = 50.vh
}
+"Styled content"
} See it in action
The full SemanticUI component showcase — buttons, cards, menus, tables, grids, and more: