• Stars
    star
    222
  • Rank 179,123 (Top 4 %)
  • Language
    Clojure
  • License
    Eclipse Public Li...
  • Created about 2 years ago
  • Updated 5 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Portfolio

Develop ClojureScript UI components in isolation in a "visual REPL". Increase your visual bandwidth by seeing your components in various states, screen resolutions, and other configurations simultaneously.

Portfolio brings some of the best features of Storybook.js to ClojureScript, and adds a few of its own. While Storybook.js was its starting point, Portfolio does not aspire to feature-parity with it, and instead caters to the REPL-oriented ClojureScript development process.

Status

Portfolio is stable and ready to use. APIs documented in this document are final and will not change. APIs not explicitly documented in this document, especially those pertaining to extending and customizing the UI, may still be subject to change.

Is Portfolio good enough that you can port over from Storybook? Probably, yes. If you're using Storybook extensions not covered by Portfolio, open an issue.

Show me, don't tell me

I recently presented Portfolio at London Clojurians, you can watch it on YouTube.

Sample

The Portfolio UI

There is a live sample to check out. The source code for the sample is also available.

Install

With tools.deps:

no.cjohansen/portfolio {:mvn/version "2023.07.15"}

With Leiningen:

[no.cjohansen/portfolio "2023.07.15"]

Usage

Portfolio displays your components in "scenes". A scene is a component in a specific state. At its most minimal, a scene is just a named instance of a component:

(defscene button
  [:button.button "I am a button"])

Read more about defscene.

Starting the Portfolio UI

After you have created your scenes, start the UI:

(require '[portfolio.ui :as ui])

(ui/start!)

Custom CSS and HTML

You can add custom CSS and custom HTML to render your scenes with.

shadow-cljs

To use Portfolio with shadow-cljs, you must ensure that Portfolio's resources are served by the development HTTP server. Include "classpath:public" in your :dev-http sources:

:dev-http {8080 ["public" "classpath:public"]}

This will serve files from public in your project (where presumably your index.html and CSS files are), and resources in public on the classpath (e.g. Portfolio's resources). Adjust as necessary.

shadow-cljs + separate dev server

If you are using shadow-cljs to build the front-end and leiningen to run the dev server separately you need to make sure that you add classpath:public to the :resource-paths and the dependency to Portfolio to the :dependencies in project.clj. This will then serve the necessary assets to make Portfolio work.

Customizing the Portfolio UI

Portfolio comes with a bunch of handy (and optional) tools to help you develop components:

  • Control background colors and body classes
  • Control viewport sizes
  • Display a grid
  • Display component documentation
  • Display scene source code
  • Split windows
  • Compare different scenes side-by-side

Read about UI customization.

Organizing scenes

Portfolio automatically organizes your scenes by component and application layer, and offers many knobs and tweaks to give you full control. Read about organization.

Search

Search your scenes and collections. This feature is not enabled by default, as it's assumed not to be very useful until you have enough content. To enable it, create an index and pass it when you start the UI:

(require '[portfolio.ui.search :as search]
         '[portfolio.ui :as ui])

(ui/start!
 {:config
  {:css-paths ["/styles/app.css"]}
  :index (search/create-index)})

create-index returns an implementation of portfolio.ui.search.protocols/Index. You can provide custom implementations of this protocol to completely customize the search. More documentation on this will follow.

REPL usage

If you just want to see what a specific component looks like with some data you caught in your REPL, but don't necessarily want to commit a new scene, you can tap> components, and Portfolio will render it under a dedicated folder.

;; Evaluate this expression
(tap> (MyComponent {:text "Test"}))

Try it out

You can take the Portfolio UI for a spin by cloning this repo, starting figwheel, and then checking out http://localhost:5995, which will show you all the scenes defined in [./sample/src/portfolio](the sample project). There are also some scenes in the "mirror" build, which demonstrates some of Portfolio's own UI components, available at http://localhost:5995/mirror.html.

Disabling Portfolio in production

The defscene macro can be placed anywhere you like - in separate files, or inline in production code alongside the implementation being demonstrated. In the latter case, you probably want to strip the macros from you production builds. It is assumed that most people will put Portfolio scenes in a separate directory that can easily be excluded from production builds, so Portfolio is enabled by default. To disable it in your build, use any of the following two options.

Adding a compiler option

Add :portfolio/enabled? false to your ClojureScript compiler options:

{:main "myns.prod"
 :optimizations :advanced
 :source-map true
 :portfolio/enabled? false}

Using a Closure define

Your second option is to set the portfolio.core/enabled Closure define to false. Closure defines can be set several ways, see the link.

Contributions

Yes please! Feel free to contribute more framework adapters, UI extensions or whatever. Please open an issue or a draft PR to discuss larger changes before pouring too much work into them, so we're sure we're one the same page.

Portfolio is proudly sponsored by Clojurists Together.

Wishlist

Some features and fixes that are likely to be explored in the close future:

  • Improved 404 page when namespaces disappear
  • Search in mobile view
  • Better error-handling for things like :on-mount
  • Better first use experience: display some documentation when there are no scenes
  • Generate scenes from a component and specs

Changelog

2023.07.15

  • Improved error handling in multiple places. If you encounter an uncaught exception, report it as a bug.
  • React components are now rendered with an error boundary. This allows Portfolio to present errors from within your React component lifecycle like any other error
  • The React adapter now supports the use of hooks directly in scene definitions.
  • tap> components from your code or the REPL to render them in Portfolio.
  • Serve browsable documentation directly inside Portfolio (there's a book icon in the top left corner).

2023.05.12

  • Render icons via phosphor-clj
  • Fix bug: Using a custom canvas HTML failed if Portfolio's rendering target wasn't hard-coded.
  • Adjust implementation of CSS reloading to also work for shadow-cljs

2023.04.26

  • Now works properly with advanced compilation mode in shadow-cljs (e.g. production builds)
  • Add back a missing close icon
  • Remove some unnecessary scrollbars in the UI
  • Don't trip on scenes with multiple lines of code in their body
  • Render compare mode menus with the proper background
  • Slightly improved code formatting for scene code

2023.04.21

UI improvements

  • Many improvements to the UI, big and small
  • Portfolio now works well on mobile devices
  • Split panes can be resized with drag'n'drop
  • Persist the state of tools like background and viewport
  • Portfolio's console logs are disabled by default
  • Added a small intro page for new setups when there are no scenes

Compare mode

When running Portfolio in split mode, you can select specific scenes for either of the panes. This way you can not only compare different versions of the same scene, but compare different scenes to each other.

Documentation and code

Scenes and collections can now have Markdown docstrings. These render above the scenes, and there is a new toolbar button to toggle their display on or off.

Portfolio can now also optionally display the scene code. This is toggled off by default, and can be enabled by clicking the brackets button in the toolbar.

Organization improvements

There are some improvements to Portfolio's default organization into packages and folders, and particularly their interaction with your custom collection configuration.

You can now specify default scene icons for collections.

Improved atom param support

Portfolio now watches all atoms in :param. This means you can set :param to e.g. a map or a vector, put several atoms inside (arbitrarily nested), and Portfolio will re-render the scene whenever any of them change. To reflect that :param is no longer necessarily just one thing, it has also been aliased as :params.

Search

Add search, including APIs for customizing indexing, searching, and result preparation.

2023.04.05

Added new APIs for organizing scenes in the sidebar.

License

Copyright Β© 2022-2023 Christian Johansen

Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.

More Repositories

1

juicer

A command line tool for JavaScript and CSS developers
Ruby
632
star
2

twibot

Simple framework for creating Twitter bots, inspired by Sinatra
Ruby
178
star
3

dumdom

Efficiently render and re-render immutable data
Clojure
157
star
4

.emacs.d

My Emacs config
Emacs Lisp
152
star
5

react-sweeper

Minesweeper in ES6 using React/immutable-js
JavaScript
106
star
6

replicant

A native ClojureScript virtual DOM renderer - render hiccup directly
Clojure
78
star
7

js-atom

Clojure(Script) atoms, in JavaScript
JavaScript
60
star
8

use_case

A small abstraction for encapsulating non-trivial business logic in Ruby applications
Ruby
48
star
9

courier

A high-level http client for Clojure and ClojureScript
Clojure
38
star
10

powerpack

A batteries-included static web site toolkit for Clojure
Clojure
35
star
11

validatious

Client side form validation with unobtrusive JavaScript
JavaScript
27
star
12

sinon-qunit

A small Sinon.JS adapter for QUnit that provides automatic sandboxing of mocks and stubs
JavaScript
26
star
13

om-sweeper

An (almost complete) implementation of Minesweeper in ClojureScript/Om (React.js)
Clojure
24
star
14

jstdutil

Small wrapper around Google's JsTestDriver to add colors, autotest and easier command invocation
Ruby
23
star
15

m1p

Map interpolation and DIY i18n/theming toolkit
Clojure
21
star
16

sinon-web

Single-page website for Sinon.JS
JavaScript
21
star
17

hiccup-find

Utilities to help you test hiccup markup generating functions
Clojure
19
star
18

phosphor-clj

Phosphor Icons as hiccup for Clojure and ClojureScript
Clojure
19
star
19

gadget-inspector

ClojureScript data browser - use from a Chrome extension or over a server in any browser
Clojure
18
star
20

powerblog

A step-by-step tutorial for building a static site with Stasis Powerpack
Clojure
16
star
21

auth0-ring

A ring middleware for OpenID Connect authentication with Auth0 in your Clojure app
Clojure
13
star
22

cjohansen-no

Source code and content for cjohansen.no doubling as a demo of Clojure/Stasis powered static sites.
JavaScript
13
star
23

imagine

Image engine for web apps: Crop, resize and filter images on the fly or to disk
Clojure
11
star
24

pharmacist

Declarative data fetching for Clojure(Script)
Clojure
9
star
25

when-rb

Ruby port of when.js
Ruby
9
star
26

form-app

Demonstrating how to build frontends around stateless, data-driven components
Clojure
8
star
27

sinon-nodeunit

A small Sinon.JS adapter for nodeunit that provides automatic sandboxing of mocks and stubs
JavaScript
8
star
28

asciidoclj

Clojure API for Asciidoc
Clojure
8
star
29

node-assert-extras

Additional assertions for Node.js
JavaScript
7
star
30

jscontext

Syntactical sugar for JsUnitTest tests - should and contexts
JavaScript
6
star
31

watch-tree

Watch directories recursively for changes using inotify for Linux
JavaScript
6
star
32

austin-repl-example

A sample Austin ClojureScript REPL setup
Clojure
6
star
33

spasm

"Just enough structure" for React-based single page web apps
JavaScript
6
star
34

Juicer2

Some initial thoughts and sketches for Juicer 2, partial rewrite of Juicer
Ruby
6
star
35

portable-text-clj

Render sanity.io Portable Text to HTML with Clojure
Clojure
6
star
36

em_pessimistic

popen with stderr and DeferrableChildProcess with errback for EventMachine
Ruby
6
star
37

fontawesome-clj

FontAwesome icons as hiccup for Clojure(Script)
Clojure
6
star
38

ubc_monitor

Monitor resource usage in OpenVZ backed VPS'.
Ruby
5
star
39

svn_import

Rake task for importing a brand new Rails project to subversion - ignoring certain files
5
star
40

live-search

A simple live search jQuery plugin, developed to showcase TDD with JavaScript
JavaScript
5
star
41

cullquery

Convenience functions for Cull.JS that use jQuery
JavaScript
4
star
42

funlines

A tiny function pipelining utility for Clojure
Clojure
4
star
43

mysql_foreign_keys

MySQL foreign keys for Rails migraitons
4
star
44

shufflify

A Spotify multi-playlist weighted shuffler
Go
3
star
45

internote

A fork of the abandoned Firefox plugin that allows sticky post-it notes on web pages
3
star
46

dumdom-devcards

Devcards for dumdom
Clojure
3
star
47

ezgravatar

A template that enables Gravatars for eZ Publish
3
star
48

clj-nats

Clojure wrapper for the official NATS.io Java SDK
Clojure
3
star
49

mmouse

Mouse movement utilities for JavaScript
JavaScript
3
star
50

clj-event-source

Clojure server-sent events Event Source client
Clojure
3
star
51

parrot

Stub HTTP responses for Clojure tests
Clojure
3
star
52

sasha

Stateless component libary for ClojureScript and dumdom
Clojure
2
star
53

libdolt

The core Dolt APIs, without any web framework dependencies
Ruby
2
star
54

chainable

A simple implementation of the chain of responsibility pattern in Ruby
2
star
55

ranger

Custom range input control for JavaScript
JavaScript
2
star
56

acts_as_prototype

A Rails plugin that adds a prototype and a property list to ActiveRecord objects (prototypes can be chained)
Ruby
2
star
57

dolt

Stand-alone Git repository browser
Ruby
2
star
58

cjohansen.github.io

Github pages
JavaScript
1
star
59

makeup

Markup and syntax highlighting
Ruby
1
star
60

cf-apply-template

A small wrapper for cloudfont create-stack/update-stack
Shell
1
star
61

revealjs-mode

An Emacs minor-mode for working with revealjs HTML files
Emacs Lisp
1
star
62

boosterconf2014

Node.js and React workshop at boosterconf.no 2014
1
star
63

om-tutorial-austin

The Om basic tutorial with the Austin browser repl
Clojure
1
star
64

cljs-compiler-woes

A reproduction of a ClojureScript compiler issue
Clojure
1
star
65

cider-figwheel-main

A demonstration of flaky CIDER/figwheel.main behavior
Clojure
1
star
66

facenode

Code from a live-coding talk. You had to be there.
JavaScript
1
star
67

docker-lein-slimer

A Docker image with Clojure, Leiningen and Slimer.JS
1
star
68

eval-lines.el

Evaluate Ruby code in Emacs. Lines ending in #=> will have the value of evaluating the line inserted after it
Emacs Lisp
1
star
69

validate

Form validation logic. Code is written for educational purposes, do not expect this to be maintained as a library.
JavaScript
1
star
70

origize.el

Emacs Lisp
1
star
71

cljsjs-moment-node

Demonstrating an issue with cljsjs/moment, node and optimizations: simple
Clojure
1
star
72

tddjs-com

The tddjs.com site
Shell
1
star
73

cljsns

Reproducing a surprising ClojureScript build snag
HTML
1
star
74

adventofcode2022

My Advent of code 2022 entries
Clojure
1
star
75

loose-client

A lean and relaxed chatting client
HTML
1
star
76

execration-no

execration.no
HTML
1
star
77

varnish-vmods-docker

A Varnish Dockerfile that includes compiled vmods
Dockerfile
1
star
78

tempcalc

A temperature calculator
Clojure
1
star
79

virtuoso-ui

Clojure
1
star
80

connect-four

The classic game of connect four
JavaScript
1
star
81

yahtzee-cljs

A functional programming implementation of Yahtzee, in ClojureScript
Clojure
1
star
82

em_rugged

Asynchronous Rugged (libgit2 bindings for Ruby) for EventMachine.
Ruby
1
star
83

compojure-api-tools-deps

Example of metosin/compojure-api not working with tools.deps
Clojure
1
star
84

replicant-sweeper

Minesweeper in Replicant
Clojure
1
star
85

recall-position.el

Remember position and window scroll in an Emacs buffer and restore it with a key-binding
Emacs Lisp
1
star
86

minesweeper-ui

JavaScript
1
star
87

uinit

An initialization system for your UI modules. Declare dependencies between features, scalars, data and elements and have you modules loaded as soon as possible.
JavaScript
1
star
88

ndc-2021

The code from my ClojureScript talk at NDC 2021: https://www.youtube.com/watch?v=yFVk3D76wQw
Clojure
1
star
89

lookup

Find content of interest in hiccup data
Clojure
1
star