A library to interface with Semantic UI React.
This library offers improved integration with the semantic-ui-react cljsjs package with predefined React factories and doc strings generated directly from the Semantic-UI source. It also includes symbols for all icon names. Shadow-cljs users also have the choice to include individual modules for reduced build sizes.
There are two ways of using this library, depending on whether your project uses the clojurescript compiler or shadow-cljs.
-
Add the dependency to your project. Be sure to include your desired version of cljsjs semantic-ui-react as well. The latest version of both are:
-
Make sure you’ve include the semantic UI CSS (via CDN or by pulling them from that project)
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.4.1/semantic.min.css"></link>
-
Use the provided factories and icons!
(ns app.ui (:require [fulcrologic.semantic-ui.factories :as f] [fulcrologic.semantic-ui.icons :as i]) ... (f/ui-button {:content "Like" :icon i/heart-icon :label {:as "a" :basic true :pointing "right" :content "2,000"} :labelPosition "left"}) ...
Make sure you have a consistent version of React by analyzing your dependencies. Libraries like fulcro have direct dependencies on React, as does the cljsjs semantic ui package.
-
Make sure to exclude react from all cljs deps
-
Add react and react-dom to your npm-deps
-
Add a foreign lib config to cause the npm version to appear like the cljsjs version
...
:dependencies [...
;; STEP 1: Make sure React isn't pulled in by dependencies
[org.omcljs/om "1.0.0-beta1" :exclusions [cljsjs/react cljsjs/react-dom]]
...]
...
:cljsbuild {:builds
[{:id "blah"
:source-paths ["src/main"]
:compiler {:asset-path "js/cards"
:main blah.core
:optimizations :none
:output-dir "resources/public/js/blah"
:output-to "resources/public/js/blah.js"
;; STEP 2: Make the NPM react also acts AS IF it were the cljsjs version
:foreign-libs [{:provides ["cljsjs.react"]
:file "node_modules/react/dist/react.js"
:global-exports {cljsjs.react React}}
{:provides ["cljsjs.react.dom"]
:file "node_modules/react-dom/dist/react-dom.js"
:global-exports {cljsjs.react.dom ReactDOM}}]
;; STEP 3: Add in the correct NPM dependencies
:install-deps true
:npm-deps {:react "16.3.0"
:react-dom "16.3.0"}}}]}
...
Shadow-cljs is highly recommended. It has much better integration with the NPM ecosystem, which allows you to
easily upgrade your semantic-ui-react dependency without worrying about cljsjs at all. Simply add
semantic-ui-react
to your package.json
:
$ npm install --save-dev semantic-ui-react
Projects using the shadow-cljs compiler have a choice of methods for using the semantic-ui-react classes:
Include the semantic-ui-wrappers jar as a dependency and use the factories, exactly as for cljs above.
For a potential reduction in build size, include the semantic-ui-wrappers-shadow
jar instead:
Individual factories can be found in namespaces that mirror the semantic-ui-react module structure:
e.g. Collections > Form > FormInput
is available as
(:require [fulcrologic.semantic-ui.collections.form.form-input :as form-input])
and Elements > Button > Button
is available as
(:require [fulcrologic.semantic-ui.button.ui-button :as ui-button])
You also have the option of using the NPM modules directly, i.e. not using this library at all.
(ns your-app
(:require
[fulcro.client.dom :as dom]
["semantic-ui-react" :refer [Dropdown DropdownItem DropdownMenu]]))
(defn ui-dropdown [& args] (dom/macro-create-element Dropdown args))
(defn ui-dropdown-menu [& args] (dom/macro-create-element DropdownMenu args))
(defn ui-dropdown-item [& args] (dom/macro-create-element DropdownItem args))
(defsc SomeComponent [this props]
(ui-dropdown {:text "Filter"}
(ui-dropdown-menu {}
(ui-dropdown-item {} "A")
(ui-dropdown-item {} "B"))))
You can also require individual modules with this approach by doing require on the module files instead of
the top-level semantic-ui-react
name, which can result in a smaller production build.
(ns your-app
(:require
[fulcro.client.dom :as dom]
["semantic-ui-react/dist/commonjs/modules/Dropdown/Dropdown" :default Dropdown]
["semantic-ui-react/dist/commonjs/modules/Dropdown/DropdownItem" :default DropdownItem]
["semantic-ui-react/dist/commonjs/modules/Dropdown/DropdownMenu" :default DropdownMenu]))
(defn ui-dropdown [& args] (dom/macro-create-element Dropdown args))
(defn ui-dropdown-menu [& args] (dom/macro-create-element DropdownMenu args))
(defn ui-dropdown-item [& args] (dom/macro-create-element DropdownItem args))
(defsc SomeComponent [this props]
(ui-dropdown {:text "Filter"}
(ui-dropdown-menu {}
(ui-dropdown-item {} "A")
(ui-dropdown-item {} "B"))))
Props are required. The factories will convert them to js for you, but if you want every ounce of
possible speed you can pre-tag your props with #js
. Note that the "nested" elements with dot
notation become just hyphenated names (e.g. Button.Group
→ ui-button-group
,
and List.List
→ ui-list-list
):
React Version:
<Button
content='Like'
icon='heart'
label={{ as: 'a', basic: true, content: '2,048' }}
labelPosition='right'/>
<Button.Group>
<Button icon>
<Icon name='align left' />
</Button>
<Button icon>
<Icon name='align center' />
</Button>
<Button icon>
<Icon name='align right' />
</Button>
<Button icon>
<Icon name='align justify' />
</Button>
</Button.Group>
This library:
(f/ui-button {:content "Like"
:icon i/heart-icon ; or just "heart"
:label {:as "a" :basic true :content "2,048"}
:labelPosition "right"}))
(f/ui-button-group nil
(f/ui-button {:icon true}
(f/ui-icon {:name i/align-left-icon}))
(f/ui-button {:icon true}
(f/ui-icon {:name i/align-center-icon}))
(f/ui-button {:icon true}
(f/ui-icon {:name i/align-right-icon}))
(f/ui-button {:icon true}
(f/ui-icon {:name i/align-justify-icon})))
The icons
namespace simply has symbol definitions for each legal string icon name. This
allows you to use your IDE’s code completion to find icon names as long as
you can remember something about that name. You may, of course, simply use a known icon
name as a string instead.
There are examples of usage semantic-ui-wrappers
(using cljs, figwheel and devcards) and
semantic-ui-wrappers-shadow
(using shadow-cljs and workspaces).
Help is welcome in expanding the coverage of the examples!
cd semantic-ui-wrappers
lein run -m clojure.main script/figwheel.clj
Navigate to http://localhost:8023
cd semantic-ui-wrappers-shadow
npm install
npx shadow-cljs server
Navigate to http://localhost:9630 and start the workspaces build
Then navigate to http://localhost:8023
Ping the Fulcro slack channel with your idea, or create a github issue. It is a good idea to do that before trying to help.
The factories files are generated from a checkout of the (Semantic-UI
source (to automatically get the docstrings). The user
namespace can be run in a normal Clojure REPL, and
contains the function to generate the files.
First clone the semantic-ui-react repo:
git clone https://github.com/Semantic-Org/Semantic-UI-React
In the cloned repository, run:
yarn install
yarn build:docs
Then using the path to the generated docs/src/componentInfo folder, start a repl and run
(gen-factories "path/to/generated/componentInfo")
To regenerate the jar files:
lein modules jar