Declarative UIs in Emacs with vui.el

News

Let’s Check out vui.el

It’s React.js but for Emacs UI:

https://github.com/d12frosted/vui.el

M-x package-install RET buttercup

(use-package vui
  :vc (:url "https://github.com/d12frosted/vui.el"
            :rev "v1.0.0"))

Here’s the non-working code we were experimenting with:x

;;; -*- lexical-binding: t -*-
(require 'vui)

;; POMODORO UI
;; - Start timer button, potentially that changes to Cancel
;; - See the timer text on the scren (can we center it?
;; - A list of completed timers?  Maybe include cancelled?

(vui-defcomponent pomodoro-timer ()
  :state ((time-text "25:00")
          (timer-start nil)
          (timer-end nil)
          (button-label "Start")
          (timer-history '()))
  :render
  (progn
    (vui-set-state :timer-start (current-time))
    (vui-set-state :timer-end (time-add (current-time) (* 25 60)))

    (vui-use-effect ()
      ;; Setup: start timer (use vui-with-async-context for callback)
      ;; Use #'1+ functional update to avoid stale closure capture
      (let ((timer (run-with-timer
                    1 1
                    (vui-with-async-context
                     (message "Delta is: %s"
                              (format-time-string "%M:%S"
                                                        (time-subtract timer-end
                                                                       (current-time))))

                     (vui-set-state :time-text
                                    (format-time-string "%M:%S"
                                                        (time-subtract timer-end
                                                                       (current-time))))))))
        ;; Cleanup: cancel timer
        (lambda ()
          (cancel-timer timer))))

    (vui-fragment
     (vui-newline)
     (vui-newline)
     (vui-text time-text :face '(nil :foreground red))
     (vui-newline)
     (vui-newline)
     (vui-button button-label
       :on-click (lambda ()
                   (if timer-start
                       (progn
                         ;; TODO: Cancel the existing timer
                         (vui-set-state :timer-start nil)
                         (vui-set-state :time-text "25:00"))
                     (vui-set-state :timer-start (current-time))))))))

;; Mount it
(vui-mount (vui-component 'pomodoro-timer))
Subscribe to the System Crafters Newsletter!
Stay up to date with the latest System Crafters news and updates! Read the Newsletter page for more information.
Name (optional)
Email Address