Skip to content

Commit

Permalink
create navbar
Browse files Browse the repository at this point in the history
  • Loading branch information
sritchie committed Aug 26, 2014
1 parent 9277cf0 commit 1f99c39
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 30 deletions.
7 changes: 4 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ From https://github.com/racehub/om-bootstrap/pull/13:

### New Components

- dropdown-mixin (mixins.cljs)
- menu-item, dropdown-menu, dropdown (button.cljs)
- split (ie, SplitButton) (button.cljs)
- `dropdown-mixin` (mixins.cljs)
- `menu-item`, `dropdown-menu`, `dropdown` (button.cljs)
- `split` (ie, SplitButton) (button.cljs)
- `navbar` (ie, SplitButton) (button.cljs)

## 0.2.5

Expand Down
8 changes: 3 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,17 @@ This project's goal is to provide wrappers for all Bootstrap 3 components, activ
Om-Bootstrap's [documentation site](http://om-bootstrap.herokuapp.com/) has usage examples for all components that exist so far. The following components are currently complete:

* `button`, `button-group`, `toolbar` (button.cljs)
* `dropdown-menu`, `menu-item`, `dropdown` (button.cljs)
* `dropdown-menu`, `menu-item`, `dropdown`, `split` (button.cljs)
* `input` (input.cljs)
* `jumbotron` (random.cljs)
* `label` (random.cljs)
* `well` (random.cljs)
* PageHeader (random.cljs)
* `page-header` (random.cljs)
* `grid`, `row`, `col` (grid.cljs)
* `glyphicon` (random.cljs)
* `tooltip` (random.cljs)
* `alert` (random.cljs)
* `nav`, `nav-item` (nav.cljs)
* `nav`, `nav-item`, `navbar` (nav.cljs)
* `popover` (random.cljs)
* `badge` (random.cljs)
* `table` (table.cljs)
Expand All @@ -49,10 +49,8 @@ The project contains a few mixins that help in writing active Om components. THe

These, and the mixins below, are the project's biggest TODOs.

* SplitButton
* Subnav (?)
* Panel (hard), PanelGroup (easy), Accordion (easy)
* NavBar
* TabbedArea, TabPane
* Pager
* Carousel
Expand Down
21 changes: 11 additions & 10 deletions dev/snippets/nav/bar_basic.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@
(:require [om-bootstrap.button :as b]
[om-bootstrap.nav :as n])

;; TODO: Surround with a Navbar.
(n/nav
(n/navbar
{}
(n/nav-item {:key 1 :href "#"} "Link")
(n/nav-item {:key 2 :href "#"} "Link")
(b/dropdown {:key 3, :title "Dropdown"}
(b/menu-item {:key 1} "Action")
(b/menu-item {:key 2} "Another action")
(b/menu-item {:key 3} "Something else here")
(b/menu-item {:divider? true})
(b/menu-item {:key 4} "Separated link")))
(n/nav
{:collapsible? true}
(n/nav-item {:key 1 :href "#"} "Link")
(n/nav-item {:key 2 :href "#"} "Link")
(b/dropdown {:key 3, :title "Dropdown"}
(b/menu-item {:key 1} "Action")
(b/menu-item {:key 2} "Another action")
(b/menu-item {:key 3} "Something else here")
(b/menu-item {:divider? true})
(b/menu-item {:key 4} "Separated link"))))
3 changes: 1 addition & 2 deletions docs/src/cljs/om_bootstrap/docs.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -380,8 +380,7 @@
"navbars"
["Navbars " (d/small "nav.cljs")]
(d/h3 "Example navbars")
#_(->example (slurp-example "nav/bar_basic"))
(TODO)))
(->example (slurp-example "nav/bar_basic"))))

;; ## Toggleable Tabs

Expand Down
137 changes: 127 additions & 10 deletions src/om_bootstrap/nav.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -84,15 +84,132 @@
(fn [child]
(u/clone-with-props child prop-fn))))

(defcomponentk nav* [owner]
(render
[_]
(let [{:keys [opts children]} (om/get-props owner)
[bs props] (t/separate Nav opts {:bs-class "nav"})
classes {:navbar-collapse (:collapsible? bs)}
ul-props {:ref "ul"
:class (d/class-set
(merge (t/bs-class-set bs)
{:nav-stacked (:stacked? bs)
:nav-justified (:justified? bs)
:navbar-nav (:navbar? bs)
:pull-right (:pull-right? bs)}))}
children (map (clone-nav-item opts) children)]
(if (and (:navbar? bs)
(not (:collapsible? bs)))
(d/ul (u/merge-props props ul-props) children)
(d/nav (u/merge-props props {:class (d/class-set classes)})
(d/ul ul-props children))))))

(sm/defn nav :- t/Component
[opts :- Nav & children]
(let [[bs _] (t/separate Nav opts {:bs-class "nav"})]
(d/nav
(d/ul {:ref "ul"
:class (d/class-set
(merge (t/bs-class-set bs)
{:nav-stacked (:stacked? bs)
:nav-justified (:justified? bs)
:navbar-nav (:navbar? bs)
:pull-right (:pull-right? bs)}))}
(map (clone-nav-item opts) children)))))
(->nav* {:opts opts
:children children}))

;; ## SubNav


;; ## NavBar

(def NavBar
(t/bootstrap
{(s/optional-key :component-fn) (sm/=> s/Any s/Any)
(s/optional-key :fixed-top?) s/Bool
(s/optional-key :fixed-bottom?) s/Bool
(s/optional-key :static-top?) s/Bool
(s/optional-key :inverse?) s/Bool
(s/optional-key :role) s/Str
(s/optional-key :brand) t/Renderable
(s/optional-key :on-toggle) (sm/=> s/Any s/Any)
(s/optional-key :toggle-nav-key) s/Str
(s/optional-key :nav-expanded?) s/Bool
(s/optional-key :default-nav-expanded?) s/Bool}))

(defn render-toggle-button [owner bs]
(let [handle-toggle (fn []
(when-let [f (:on-toggle bs)]
(om/set-state-nr! owner [:changing?] true)
(f)
(om/set-state-nr! owner [:changing?] false))
(om/update-state-nr! owner [:changing?] not))
tb (u/clone-with-props (:toggle-button bs)
{:class "navbar-toggle"
:on-click handle-toggle})]
(d/button {:class "navbar-toggle"
:type "button"
:on-click handle-toggle}
(or tb [(d/span {:class "sr-only" :key 0} "Toggle navigation")
(d/span {:class "icon-bar" :key 1})
(d/span {:class "icon-bar" :key 2})
(d/span {:class "icon-bar" :key 3})]))))

(defn render-header [owner bs]
(d/div {:class "navbar-header"}
(if (u/strict-valid-component? (:brand bs))
(u/clone-with-props (:brand bs) {:class "navbar-brand"})
(d/span {:class "navbar-brand"} (:brand bs)))
(when (or (:toggle-button bs)
(:toggle-nav-key bs))
(render-toggle-button owner bs))))

(sm/defn clone-nav-item
"Takes the options supplied to the top level nav and returns a
function that will CLONE the inner nav items, transferring all
relevant props from the outer code to the inner code."
[opts]
(letfn [(prop-fn [props]
(let [base (-> (select-keys opts [:on-select :active-key :active-href])
(assoc :active? (child-active? (:opts props) opts)
:nav-item? true))]
(update-in props [:opts] u/merge-props base)))]
(fn [child]
(u/clone-with-props child prop-fn))))

(defn render-navbar-child [owner child bs]
(let [f (fn [props]
(let [opts (:opts props)
collapsible? (when (:toggle-nav-key bs)
(= (:key opts) (:toggle-nav-key bs)))
base {:navbar? true
:collapsible? collapsible?
:expanded? (and collapsible?
(or (:nav-expanded? bs)
(om/get-state owner :nav-open?)))}]
(update-in props [:opts] u/merge-props base)))]
(u/clone-with-props child f)))

(defcomponentk navbar*
[[:data opts children] owner]
(init-state [_] {:nav-open? (:default-nav-expanded? opts)
:changing? false})
(should-update [_ _ next-state]
(not (:changing? next-state)))
(render
[_]
(let [[bs props] (t/separate NavBar opts
{:bs-class "navbar"
:bs-style "default"
:role "navigation"
:component-fn (fn [opts & c]
(d/nav opts c))})
classes (assoc (t/bs-class-set bs)
:navbar-fixed-top (:fixed-top? bs)
:navbar-fixed-bottom (:fixed-bottom? bs)
:navbar-static-top (:static-top? bs)
:navbar-inverse (:inverse? bs))]
((:component-fn bs) (u/merge-props (merge bs props)
{:class (d/class-set classes)})
(d/div {:class (if (:fluid props) "container-fluid" "container")}
(when (or (:brand bs)
(:toggle-button bs)
(:toggle-nav-key bs))
(render-header owner bs))
(map #(render-navbar-child owner % bs) children))))))

(sm/defn navbar
[opts :- NavBar & children]
(->navbar* {:opts opts
:children children}))

0 comments on commit 1f99c39

Please sign in to comment.