Skip to content

CzaxStudio/proton

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

97 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Proton

A GUI library for Go that doesn't make you want to switch to web dev.

Currently under development for v0.2.5

Go Report Card Mentioned in Awesome Go

Our First Stargazers

Thank you to the early adopters who supported Proton from the very beginning!


@VioGrafu
(First Stargazer)

@bigwhite

@TanmayCzax

@aurax

@DemonK1

@pekim

@fbaube

@gorilacrocodille

@alanmsant2

Documentation


Example apps

Note: I have created basic apps, you can create even better apps with Proton.

GUI demo Demo2

Logo

Proton

Getting Started

package main

import "github.com/CzaxStudio/proton"

func main() {
    a := proton.New("hello")
    a.Window("Hello", 400, 200, func(ctx proton.Context) {
        proton.H3(ctx, "Hello from Proton!")
    })
    a.Run()
}

Install

go get github.com/CzaxStudio/proton

Then run once to pull Gio's dependencies:

go mod tidy

Linux — three system packages required:

sudo apt install libwayland-dev libxkbcommon-dev libvulkan-dev

macOS and Windows need nothing extra.


How it works

Your draw function runs every frame. Call widget functions in order — they stack vertically by default. State lives in your own struct. No setState, no component trees, no XML.

type UI struct {
    btn     proton.Clickable    // button
    name    proton.Editor       // text input
    checked proton.Bool         // checkbox / toggle
    choice  proton.Enum         // radio group
    vol     proton.Float        // slider
    scroll  proton.Scrollable   // list / scroll area
}

Widgets

Text

Label H1H6 Body2 Caption Text Muted ColoredText ErrorText SuccessText WarningText

Buttons

Button OutlineButton IconButton Tappable Link LinkSmall

Inputs

Input TextArea Checkbox Toggle RadioButton Slider ProgressBar NumberInput SelectBox SearchInput

Lists

List HList Scroll TextView LogView

Layout

Row Column RowSpread RowEnd GrowRow GrowColumn GrowItem FixedItem FlexSpacer Split HSplit ResizeSplit ResizeHSplit Center ZStack Pad PadH PadV PadSides Gap Grid MinSize MaxWidth

Visual

Divider LabeledDivider Rect RoundRect Card HoverCard Badge StatusDot Avatar Tag Image Logo CodeBlock ShortcutHint ColorSwatch

Data

Table ProgressRing Stepper

Feedback

Toast Alert AlertDismissable Tooltip Spinner

Overlays & Dialogs

Overlay Tabs Accordion ContextMenu

Utilities

If OnKey FocusArea


Layout

// side by side
proton.Row(ctx,
    func(ctx proton.Context) { proton.Label(ctx, "left") },
    func(ctx proton.Context) { proton.Label(ctx, "right") },
)

// one child fills remaining space
proton.GrowRow(ctx,
    proton.FixedItem(ctx, func(ctx proton.Context) { proton.Label(ctx, "Search:") }),
    proton.GrowItem(ctx, func(ctx proton.Context) { proton.Input(ctx, &e, "") }),
    proton.FixedItem(ctx, func(ctx proton.Context) { proton.Button(ctx, &b, "Go") }),
)

// draggable split pane
proton.ResizeSplit(ctx, &u.split, 0.35, leftFn, rightFn)

// padding
proton.Pad(ctx, 16, func(ctx proton.Context) { ... })
proton.PadSides(ctx, 8, 16, 8, 16, func(ctx proton.Context) { ... })

// blank space
proton.Gap(ctx, 12)

Theming

46 built-in palettes. One line to apply any of them.

a.ApplyPalette(proton.NordPalette)
a.ApplyPalette(proton.CatppuccinPalette)
a.ApplyPalette(proton.DraculaPalette)
a.ApplyPalette(proton.TokyoNightPalette)
a.ApplyPalette(proton.GruvboxDarkPalette)
a.ApplyPalette(proton.RosePinePalette)
// ... 40 more

Custom palette

a.ApplyPalette(proton.Palette{
    Bg:        proton.RGB(0x1e1e2e),
    Fg:        proton.RGB(0xcdd6f4),
    Primary:   proton.RGB(0x89b4fa),
    PrimaryFg: proton.RGB(0x1e1e2e),
})

Hex color codes

No structs needed — just pass the hex string:

a.ThemeBuilder().
    Bg("#1e1e2e").
    Fg("#cdd6f4").
    Primary("#89b4fa").
    PrimaryFg("#1e1e2e").
    Apply()

// patch one color on the current theme
a.ColorCode("primary", "#ff6b6b")
a.ColorCode("bg", "#0d1117")

Accepted formats: "#rrggbb", "rrggbb", "#rgb", "#rrggbbaa".

Background colors

a.SetBackgroundCode("#1a1b26")
a.SetBackgroundRGB(26, 27, 38)
a.SetBackgroundGradient("#1a1b26", "#2d1b69", "vertical")
a.SetBackgroundRainbow() // animated full-spectrum gradient

Font scale

a.SetFontScale(1.1)

Live theme picker

Drop into a settings window to let users switch themes at runtime:

type UI struct {
    picker proton.ThemePickerState
}

proton.ThemePicker(ctx, &u.picker, a)

Logo

Load once at startup, draw anywhere.

//go:embed assets/logo.png
var logoBytes []byte

func main() {
    a := proton.New("myapp")
    a.SetLogoBytes(logoBytes)

    a.Window("My App", 480, 300, func(ctx proton.Context) {
        proton.Row(ctx,
            func(ctx proton.Context) { proton.Logo(ctx, 40, 40) },
            func(ctx proton.Context) { proton.Gap(ctx, 10) },
            func(ctx proton.Context) { proton.H5(ctx, "My App") },
        )
    })
    a.Run()
}

Or load from a file path:

a.SetLogo("assets/logo.png")

PNG and JPEG both work. The image is decoded once and cached — not re-read per frame.


Alerts and Feedback

proton.Alert(ctx, proton.AlertInfo,    "Informational message.")
proton.Alert(ctx, proton.AlertSuccess, "Operation completed.")
proton.Alert(ctx, proton.AlertWarning, "Proceed with caution.")
proton.Alert(ctx, proton.AlertError,   "Something went wrong.")

// dismissable
if proton.AlertDismissable(ctx, &u.closeBtn, proton.AlertInfo, "Click x to close") {
    u.showAlert = false
}

// toast — call last in your draw function
u.toast.Show("Saved!", 2*time.Second)
proton.Toast(ctx, &u.toast)

New in v0.2.x

Table

proton.Table(ctx,
    []string{"Name", "Status", "Score"},
    []proton.TableRow{
        {"Alice", "Active", "98"},
        {"Bob",   "Away",   "74"},
    },
)

Stepper

proton.Stepper(ctx, currentStep, []string{"Build", "Test", "Stage", "Deploy"})

ProgressRing

proton.ProgressRing(ctx, 0.72, 48, 5, proton.RGB(0x88c0d0))

SearchInput

q := proton.SearchInput(ctx, &u.search, "Search notes...")

Avatar

proton.Avatar(ctx, "AJ", proton.RGB(0x5e81ac), proton.RGB(0xeceff4), 40)

NumberInput

qty := proton.NumberInput(ctx, &u.qty, 1, 99, 1)

Overlay / modal

proton.Overlay(ctx, &u.modal, func(ctx proton.Context) {
    proton.Card(ctx, proton.RGB(0x2e3440), 12, 24, func(ctx proton.Context) {
        proton.H5(ctx, "Confirm?")
        proton.Gap(ctx, 16)
        proton.Pad(ctx, 4, func(ctx proton.Context) {
            if proton.Button(ctx, &u.closeBtn, "Close") {
                u.modal.Hide()
            }
        })
    })
})

Async Updates

go func() {
    result := fetchFromAPI()
    u.data = result
    ctx.Invalidate()
}()

Keyboard Shortcuts

proton.OnKey(ctx, proton.ModCtrl, "S", func() { save() })
proton.OnKey(ctx, proton.ModNone, proton.KeyEscape, func() { closeDialog() })
proton.OnKey(ctx, proton.ModCtrl|proton.ModShift, "N", func() { newWindow() })

Window Options

a.WindowEx("App", 800, 600, []proton.WindowOption{
    proton.Fullscreen(),
}, draw)

Android

Same code runs on Android. No rewrites.

go install gioui.org/cmd/gogio@latest
gogio -target android -appid com.yourname.yourapp .
adb install yourapp.apk

Full guide: docs/10-android.md


API Immunity

Every draw function takes proton.Context — an interface. No Gio types appear in the public API. If Gio's internals change in a future version, only Proton's implementation updates. Your code keeps compiling unchanged.

func (app *MyApp) draw(ctx proton.Context) {
    proton.Button(ctx, &app.btn, "Click")
}

Examples

go run ./examples/hello        # minimal — one window, one label
go run ./examples/todo         # todo list
go run ./examples/calculator   # grid of buttons
go run ./examples/notes        # note-taking app with search and split pane
go run ./examples/dashboard    # dev dashboard with charts, logs, and tables
go run ./examples/showcase     # every widget in one place
go run ./examples/themes       # live theme picker
go run ./examples/logoapp      # custom logo with go:embed
go run ./examples/kitchen      # stress test for all features

License

MIT

About

A framework(library) for building GUI applications in Go without any need of CGO.

Topics

Resources

License

Contributing

Stars

23 stars

Watchers

1 watching

Forks

Packages

 
 
 

Contributors

Languages