Skip to content

Commit

Permalink
Cleanups for 0.1.0 release
Browse files Browse the repository at this point in the history
  • Loading branch information
deg committed Aug 13, 2017
1 parent 28a3351 commit 6c372df
Show file tree
Hide file tree
Showing 5 changed files with 209 additions and 82 deletions.
223 changes: 171 additions & 52 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,97 +1,216 @@
# Sodium

A wrapper around [soda-ash](https://github.com/gadfly361/soda-ash)
and [semantic-ui-react](https://github.com/Semantic-Org/Semantic-UI-React) that is
friendlier to re-frame. And the name? Simple, Sodium is highly reactive, and starts
with an "S", like Soda-ash and Semantic-UI.
## Introduction

Sodium is still an early work in progress. I am using it to help me with other projects.
It will only grow as it helps me (or other contributers) accomplish what they need. If
you need features now, PRs are welcome.
Sodium is a wrapper around [soda-ash](https://github.com/gadfly361/soda-ash) which, in
turn is a ClojureScript wrapper
around [semantic-ui-react](https://github.com/Semantic-Org/Semantic-UI-React). Sodium
adds two sets of features into the mix, both aimed at making it easier to include
Semantic UI in re-frame projects:

Sodium offers the following:
1. Utility functions to get values in and out of components.
2. Validity-checking aids to help avoid typos.

## Cleaner inter-op between Semantic-UI and [re-frame](https://github.com/Day8/re-frame)
### Why "Sodium"?

`sodium.core/>event` and `sodium.core/>atom` - Create `:on-*` handlers to pass a value
to a re-frame event or react atom.
The element sodium is highly reactive. It also starts with an "S", like Soda-ash and
Semantic-UI. In addition, the chemical symbol for sodium is "NA", nicely similar to the
"SA" abbreviation used for the Soda-ash namespace. And, hey, I like puns.

`sodium.core/<atom` - Get a value from a react atom.
### State of this project

`sodium.core/defcontrol` and `sodium.core/def-simple-control` Define a control;
typically a thin wrapper around the Soda-ash control, to give parameter checking,
etc. (see below). Soon, Sodium will contain definitions wrapping all the Soda-ash
(Semantic-UI) controls, but we are not there yet.
Sodium is still an early work in progress. I am using it to help me with other projects
and have only addded functionality that I need and can test. Sodium will only grow as
it helps me (or other contributers) accomplish what they need. If you need features now,
PRs are welcome.

### Background

I have used [re-com](https://github.com/Day8/re-com) for a while in my
[re-frame](https://github.com/Day8/re-frame) projects. Re-com is a wonderful, reliable,
easy to use, and opinionated library of UI components. In many ways, it was
perfect. But, as the authors warn, it is designed for desktop applications. When I tried
using it for mobile and portable pages, I kept running into little annoyances.

I recently discovered Semantic UI and its Soda-ash wrapper. I switched to it, and my
pages became much more usable on mobile devices. But, I miss the slick features and
re-frame integration of re-com. Sodium is an attempt to bridge this gap.


## Setup

[![Clojars Project](https://img.shields.io/clojars/v/com.degel/sodium.svg)](https://clojars.org/com.degel/sodium)

Sodium is a wrapper around Soda-ash, Semantic UI React, and Semantic UI. Setup requires
a couple of steps:

## Clojure-friendly naming conventions
- Your project.clj should include a dependency on Sodium: `[com.degel/sodium "0.1.0"]`
- It will probably (see below) also need a dependency on Soda-ash (currently `[soda-ash
"0.3.0"]`, but see the [Soda-ash README](https://github.com/gadfly361/soda-ash) for
any recent changes).
- You will also need to include the Semantic UI stylesheet in your _index.html_:
`<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.10/semantic.min.css">`
- Finally, you will need to require Sodium, and maybe also Soda-ash, in your namespace:
- `[sodium.core :as na]` - Most of Sodium's functionality
- `[sodium.utils :refer [<sub >evt]]` - Useful utilities
- `[sodium.chars :as chars]` - Minor Unicocde support
- `[soda-ash.core :as sa]` - Soda-ash functions

Controls and parameters in kebab-case (`:on-change`) rather than JavaScript-friendly
camel-case (`onChange`).

## Parameter type-checking
If you want to contribute to this project, you will want to test your changes. You can
extend the (very minimal) tests inside Sodium, but you will probably need to really test
by using Sodium in a ClojureScript project. The easiest way to do this, while you are
changing Sodium, is by using Leiningen's
[checkout directory](https://github.com/technomancy/leiningen/blob/master/doc/TUTORIAL.md#checkout-dependencies)
feature by sym-linking directly to your copy of Sodium.

For now, just starting to check if parameters are valid. This is a bit of a mixed
blessing, because I've not yet found a definitive list of all the valid parameters. So,
this may be overly restrictive.
## Using Sodium

I will, soon, add an option to partially disable checking. But, NYI. For now, you can
call the Soda-ash function directly. `>event` and friends will work just fine.
Sodium is a library, with a grab-bag of functions to enhance the usability of Semantic
UI from your re-frame projects. You can use it in several ways:

## A few helpful utility functions
### Data-in and -out

Sodium offers the following:

### In `sodium.utils`
- `na/>event` and `na/>atom` - Create `:on-*` handlers to pass a value
to a re-frame event or react atom.
- `sodium.core/<atom` - Get a value from a react atom.

#### Typical usage

````
(defn login-panel []
(let [email (reagent/atom "")
password (reagent/atom "")]
(fn []
[na/form {}
[na/form-input {:label "Email"
:type "email"
:on-change (na/>atom email)}]
[na/form-input {:label "Password"
:type "password"
:on-change (na/>atom password)}]
[na/form-button {:content "Login"
:on-click (na/>event [:login @email @password])}]])))
````

These functions work equally with with Sodium components and bare Soda-ash ones. I
recommend using Sodium components where available. But, see below, you will still often
need to use Soda-ash components.

### Helper functions

These are some some of the functions that I've needed often in re-frame projects. I
expect this will grow rapidly with time. PRs are welcome here, though I'm likely to be
opinionated about what I accept.

#### In `sodium.utils`
- `validate` - Wrapper for Clojure specs checking in pre-conditions.
- "Camelize" functions - Convert Clojure-style names to JavaScript style

### In `sodium.re-utils`
#### In `sodium.re-utils`
- `<sub` and `>evt` - Re-frame wrappers, taken from <https://lambdaisland.com/blog/11-02-2017-re-frame-form-1-subscriptions>

### In `sodium.chars`
#### In `sodium.chars`

Definitions for a few common Unicode characters.


## Useful links (for now)
### Semantic enhancements

- https://react.semantic-ui.com/introduction
- https://github.com/Semantic-Org/Semantic-UI-React
HTML controls offer a lot of freedom, and sometimes too many choices. Our front-end code
can be much more readable if we define controls with relatively constrained and
consistent behavior. But, there is an art to doing this right; constrain a control too
much, and it is perfect for one project, but too limited to be useful in other
projects. Semantic UI helps a lot, but still offers too many choices for a consistent,
simple, web page.

I am trying, slowly, to create a set of components that meet my needs yet are general
purpose. Most of them are still in my other projects, mostly not public, that use
Sodium. But, I intend to migrate them into Sodium as I gain comfort.

One component is already here:

## Usage
- `form-button` - HTML forms are, by default, very tied to the old-school HTML notions
of page submission. This does not play well with the re-frame philosophy that a form
handler should simply trigger a re-frame event. When I naively use the Soda-ash
sa/FormButton component at first, I was hit with unexpected extra connections to my
server, trying to submit the form. The fix for this, once I realized the problem, was
simple: the component needs to explicitly speicify a type of "button." The
`na/form-button` component handles this automatically.

[![Clojars Project](https://img.shields.io/clojars/v/com.degel/sodium.svg)](https://clojars.org/com.degel/sodium)
### Type-checked wrappers

You will need to include a dependency `[com.degel/sodium "0.1.0-SNAPSHOT"]` and `require`
- `[sodium.core :as na]` - Most of Sodium's functionality
- `[sodium.chars :as chars]` - Minor Unicocde support
- `[sodium.utils :refer [<sub >evt]]` - Useful utilities
This is the most experimental part of Sodium and, sadly, still mostly incomplete.

So far, it includes the following components, each a very thin wrapper around the
corresponding Soda-ash / Semantic UI one:

### Running
- `na/checkbox`: `sa/Checkbox`
- `na/container`: `sa/Container`
- `na/dropdown`: `sa/Dropdown`
- `na/form`: `sa/Form`
- `na/form-input`: `sa/FormInput`
- `na/form-group`: `sa/FormGroup`
- `na/grid`: `sa/Grid`
- `na/header`: `sa/Header`
- `na/input`: `sa/Input`
- `na/menu`: `sa/Menu`
- `na/menu-item`: `sa/MenuItem`
- `na/rail`: `sa/Rail`
- `na/text-area`: `sa/TextArea`

At this stage, I expect that most users of Sodium will be myself or contributers. If
you will be changing Sodium, it is easier to run this library from within the project
using it.

Sym-link to Sodium from the checkouts directory of your project. (See the
[Leiningen notes](https://github.com/technomancy/leiningen/blob/master/doc/TUTORIAL.md#checkout-dependencies)
for a discussion of this feature). If you are me, a working example is at
~/Documents/git/projects/receipts/client/checkouts.
These wrappers improve the components in two ways (both admittedly arguable):
- The names are in Clojure-friendly kebab-case, rather than camelCase.
- The valid parameters are listed in the arglist. Parameters you supply are
checked for validity, catching typos and undefind parameters.

These improvements have some drawbacks, which make Sodium still less usable that
Soda-ash in many circumstances. For that reason, I deliberately designed the Sodium
functions to work with both Sodium and Soda-ash components.

Some current limitations:

- I've only defined some components so far; only about a dozen of the 140+ exported by Soda-ash.
- I've tried to list all the valid parameters for each component. I built these lists
mostly from the Semantic UI React [documentation](https://react.semantic-ui.com/), but
discovered them to be incomplete. I've added missing parameters as I discovered them,
but have surely missed some. [PRs *very* eagerly welcome here].
- The params map is mandatory in Sodium components. It is not valid, e.g., to say
`[na/form [na/...]]`. Instead, you have to explicitly specify even an empty map:
`[na/form {} [na/...]]`


### Internals

`sodium.core/defcomponent` and `sodium.core/def-simple-component` Define a component;
typically a thin wrapper around the Soda-ash component, to give parameter checking,
etc. (see below). Soon, Sodium will contain definitions wrapping all the Soda-ash
(Semantic-UI) components, but we are not there yet.

You will also need to follow the instruction in
the [soda-ash README](https://github.com/gadfly361/soda-ash), particularly to include
the stylesheet and dependency.

### Testing

`lein doo phantom test auto` will run the few unit tests I've written so far.
`lein doo phantom test auto` will run the few unit tests I've written so far. More are
needed. PRs especially welcome here.

## License
## Useful references

Licensed under the Eclipse Public License.
- https://semantic-ui.com/
- https://react.semantic-ui.com/introduction
- https://github.com/Semantic-Org/Semantic-UI-React
- https://github.com/gadfly361/soda-ashsoda


## Questions

I can usually be found on the [Clojurians Slack](https://clojurians.net) #reagent or
#re-frame slack channels. My handle is @deg. Email is also fine.

## License

Copyright © 2017, David Goldfarb <[email protected]>

Licensed under the Eclipse Public License.
2 changes: 1 addition & 1 deletion project.clj
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
(defproject
com.degel/sodium "0.1.0-SNAPSHOT"
com.degel/sodium "0.1.0"
:description "A wrapper around soda-ash and semantic-ui-react"
:url "https://github.com/deg/sodium"
:license {:name "Eclipse Public License"
Expand Down
38 changes: 19 additions & 19 deletions src/sodium/core.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

(ns sodium.core
(:require-macros
[sodium.macros :refer [defcontrol def-simple-control]])
[sodium.macros :refer [defcomponent def-simple-component]])
(:require
[clojure.spec.alpha :as s]
[soda-ash.core :as sa]
Expand Down Expand Up @@ -68,7 +68,7 @@

(defn <atom
"Get a value from an atom. Suitable to use, e.g., as the :value or
:default-value parameter to a control.
:default-value parameter to a component.
Atom is the atom to be dereferenced. It will be translated by access-fn.
If null, default will be supplied instead."
([atom]
Expand All @@ -79,28 +79,28 @@
(or (access-fn @atom) default)))


;;; Controls that we supply so far. More coming soon.
;;; Components that we supply so far. More coming soon.
;;; The final argument here is a descriptor the acceptable parameters.
;;; For more details about this, see keys.clj and macros.clj
(def-simple-control checkbox sa/Checkbox [:basic :checkbox])
(def-simple-control container sa/Container [:basic :container])
(def-simple-control dropdown sa/Dropdown [:basic :dropdown])
(def-simple-control form sa/Form [:basic :form])
(def-simple-control form-input sa/FormInput [:basic :form-field :input :input-html])
(def-simple-control form-group sa/FormGroup [:basic :form-group])
(def-simple-control grid sa/Grid [:basic :grid])
(def-simple-control header sa/Header [:basic :header])
(def-simple-control input sa/Input [:basic :form-field :input :input-html])
(def-simple-control menu sa/Menu [:basic :menu])
(def-simple-control menu-item sa/MenuItem [:basic :menu-item])
(def-simple-control rail sa/Rail [:basic :rail])
(def-simple-control text-area sa/TextArea [:basic :form-field :input :input-html :text-area])
(def-simple-component checkbox sa/Checkbox [:basic :checkbox])
(def-simple-component container sa/Container [:basic :container])
(def-simple-component dropdown sa/Dropdown [:basic :dropdown])
(def-simple-component form sa/Form [:basic :form])
(def-simple-component form-input sa/FormInput [:basic :form-field :input :input-html])
(def-simple-component form-group sa/FormGroup [:basic :form-group])
(def-simple-component grid sa/Grid [:basic :grid])
(def-simple-component header sa/Header [:basic :header])
(def-simple-component input sa/Input [:basic :form-field :input :input-html])
(def-simple-component menu sa/Menu [:basic :menu])
(def-simple-component menu-item sa/MenuItem [:basic :menu-item])
(def-simple-component rail sa/Rail [:basic :rail])
(def-simple-component text-area sa/TextArea [:basic :form-field :input :input-html :text-area])

;;; This is (at least for now) how we define controls that don't fit
;;; into the def-simple-control cookie-cutter regime.
;;; This is (at least for now) how we define components that don't fit
;;; into the def-simple-component cookie-cutter regime.
;;; Actually, all that's really non-standard here is the supplying
;;; of "button" as the default type.
(defcontrol form-button [params]
(defcomponent form-button [params]
{::key-sets [:basic :form-field :button]
::keys [data-tooltip]
:pre [(utils/validate (s/nilable ifn?) on-click)
Expand Down
9 changes: 9 additions & 0 deletions src/sodium/keys.clj
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@

(ns sodium.keys)

;;; [TODO] Fill in more keys
;;; For mapping of HTML attributes to elements, see https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes
;;; For list of all HTML tags, see http://www.fillster.com/htmlcodes/htmltags.html
;;; also, https://developer.mozilla.org/en/docs/Web/HTML/Element
;;; and https://www.w3schools.com/TAGs/default.asp
;;; See also http://learnsemantic.com/




(def ui-key-set-map (atom {}))

Expand Down
Loading

0 comments on commit 6c372df

Please sign in to comment.