It's mainly meant for my game framework, but perhaps some inspiration on some of these problems can be rung out of <https://github.com/beef331/gooey/>
Instead of using a DSL for declaring the GUI it just uses tuples(This would be a smidgen nicer with object constructor having generic inference). The benefit of this is it's just normal Nim code with no caveats. let # these only are here cause `template named(name, val: untyped): untyped = let name = val` # does not work myLabel = Label( color: (0, 255, 127, 255), text: "Huh", anchor: {bottom, right}, size: Vec2.init(100, 50) ) slider = Slider[float32]( rng: 1f..5f, pos: (10, 10, 0), size: (100, 30), color: (123, 155, 200, 255), slideBar: Element(color: (62, 88, 170, 255)), anchor: {bottom, left}, onChange: proc(f: float32) = myLabel.size.y = f * 50 myLabel.size.x = f * 100 ) ( Button( pos: Vec3.init(10, 10, 0), anchor: {top, left}, size: Vec2.init(100, 50), clickCb: proc() = echo("Hello"), label: Label(text: "Hello", color: (0, 0, 0, 255)) ), Label(text: "Hmmm", anchor: {bottom, right}, size: Vec2.init(300, 200)), myLabel, slider, HGroup[(Label, Button)]( pos: (10, 10, 0), anchor: {top, right}, entries: ( Label(text: "Test:", size: (100, 50)), Button( size: (100, 50), color: (99, 64, 99, 255), hoveredColor: (188, 124, 188, 255), label: Label(text: "Really!", color: (0, 35, 127, 255))) ) ),... Run It's also backend/vector agnostic using generics, inheritance, and concepts to implement most logic the gooey implementation followed by implementation in my sdl api can be seen below. (I use proc instead of methods as I had a desire to have it purely statically type and never rely on type information to reason dispatch, in any sensible library probably would use methods or pointer procs created from constructors for generics.) # gooey/buttons.nim import gooey, mathtypes type ButtonBase*[Base] = ref object of Base # This exists so we can be vector/renderer agnostic, the user passes in our data as a sort of dependency injection clickCb*: proc() proc layout*[Base](button: ButtonBase[Base], parent: Base, offset: Vec3, state: UiState) = mixin layout Base(button).layout(parent, offset, state) proc onClick*[Base](button: ButtonBase[Base], uiState: var UiState) = if button.clickCb != nil: button.clickCb() # sdlimpl.nim type Button = ref object of ButtonBase[Element] baseColor: Color hoveredColor: Color = (127, 127, 127, 255) label: Label proc upload(button: Button, state: UiState, target: var RenderTarget) = Element(button).upload(state, target) if button.label != nil: button.label.upload(state, target) proc layout(button: Button, parent: Element, offset: Vec3, state: UiState) = buttons.layout(button, parent, offset, state) if button.label != nil: button.label.size = button.size button.label.layout(button, (0f, 0f, 0f), state) proc onEnter(button: Button, uiState: var UiState) = button.flags.incl {hovered} button.baseColor = button.color button.color = button.hoveredColor proc onExit(button: Button, uiState: var UiState) = button.color = button.baseColor proc onClick(button: Button, uiState: var UiState) = buttons.onClick(button, uiState) Run Though this is likely much lower level and limited than desired, I think it might be a good source of inspiration for agnosticism. As I already have implemented an Opengl implementation along with an SDL implementation for this UI "framework which can be viewed in their entirety below. <https://github.com/beef331/gooey/blob/master/example/sdlimpl.nim> <https://github.com/beef331/truss3d/blob/master/src/truss3D/gui.nim>