diff --git a/CHANGELOG.md b/CHANGELOG.md index 6897c48a..c1df1c85 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# 3.2.0 + +June 13, 2021 + +- `::stylefy/media` and `::stylefy/supports` can now be defined using vector syntax. This is useful if the order of the rules matter in CSS. +- All stylefy's special keywords now work inside `stylefy/supports` style map (manual mode and scoping were previously missing) + # 3.1.0 June 7, 2021 diff --git a/README.md b/README.md index dff28591..b3c716e1 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ stylefy consists of modules that are optimised for specific UI libraries / frame First, add stylefy core as a dependency: ```clj -[stylefy "3.1.0"] +[stylefy "3.2.0"] ``` Then, based on the UI library you are using, add a corresponding module. The main purpose of the module is to handle asynchronous DOM updates when components are rendered. @@ -353,6 +353,13 @@ Define how your style looks on various screen sizes: [:p "This is column 3"]]]) ``` +Alternative version using vector syntax. This is useful if the order of the rules matter in CSS. + +```clojure +{::stylefy/media [[{:max-width phone-width} {:flex-direction :column}] + [{:max-width tablet-with} {:flex-direction :row}]]} +``` + stylefy features supported in media queries: modes, scope and vendor prefixes. For syntax help, see Garden's [documentation](https://github.com/noprompt/garden/wiki/Media-Queries). @@ -380,6 +387,13 @@ Define how your style looks when certain CSS features are supported by the brows ``` +Alternative version using vector syntax. This is useful if the order of the rules matter in CSS. + +```clojure +{::stylefy/supports [["display: flex" {:color :green}] + ["display: grid" {:color :purple}]]} +``` + stylefy features supported in feature queries: modes, media queries and vendor prefixes. ## 3rd party classes diff --git a/examples/reagent/src/cljs/stylefy/examples/reagent/grid.cljs b/examples/reagent/src/cljs/stylefy/examples/reagent/grid.cljs index 00a77f7f..563d0a8c 100644 --- a/examples/reagent/src/cljs/stylefy/examples/reagent/grid.cljs +++ b/examples/reagent/src/cljs/stylefy/examples/reagent/grid.cljs @@ -3,23 +3,26 @@ [stylefy.core :as stylefy :refer [use-style use-sub-style]] [stylefy.examples.reagent.styles :as styles])) -(def grid-style {; Default style uses Flexbox as fallback - :display "flex" - :flex-direction "row" - :flex-wrap "wrap" - ::stylefy/media {{:max-width styles/phone-width} - {:display "block"}} - ; Use CSS Grid style if it is supported by the browser. - ; If the browser does not support CSS Grid or feature queries at all, this - ; block is simply ignored. - ::stylefy/supports {"display: grid" - {:display "grid" - :grid-template-columns "1fr 1fr 1fr" - ; Make CSS Grid responsive - ::stylefy/media {{:max-width styles/phone-width} - {:grid-template-columns "1fr"}}}}}) - -(defn create-box-style [color] +; Map syntax + +(def grid-style-map-syntax {; Default style uses Flexbox as fallback + :display "flex" + :flex-direction "row" + :flex-wrap "wrap" + :margin-bottom "1rem" + ::stylefy/media {{:max-width styles/phone-width} + {:display "block"}} + ; Use CSS Grid style if it is supported by the browser. + ; If the browser does not support CSS Grid or feature queries at all, this + ; block is simply ignored. + ::stylefy/supports {"display: grid" + {:display "grid" + :grid-template-columns "1fr 1fr 1fr" + ; Make CSS Grid responsive + ::stylefy/media {{:max-width styles/phone-width} + {:grid-template-columns "1fr"}}}}}) + +(defn create-box-style-map-syntax [color] {:background-color color :width "33.333%" :height "200px" @@ -29,12 +32,56 @@ ; Element width is always well managed by grid. {:width "auto"}}}) -(defn grid [] - [:div (use-style grid-style) - [:div (use-style (create-box-style "#000000"))] - [:div (use-style (create-box-style "#AA0000"))] - [:div (use-style (create-box-style "#00AA00"))] - [:div (use-style (create-box-style "#0000AA"))] - [:div (use-style (create-box-style "#00AAAA"))] - [:div (use-style (create-box-style "#AAAA00"))] - [:div (use-style (create-box-style "#AA00AA"))]]) \ No newline at end of file +(defn grid-map-syntax [] + [:<> + [:h3 "Map syntax"] + [:div (use-style grid-style-map-syntax) + [:div (use-style (create-box-style-map-syntax "#000000"))] + [:div (use-style (create-box-style-map-syntax "#AA0000"))] + [:div (use-style (create-box-style-map-syntax "#00AA00"))] + [:div (use-style (create-box-style-map-syntax "#0000AA"))] + [:div (use-style (create-box-style-map-syntax "#00AAAA"))] + [:div (use-style (create-box-style-map-syntax "#AAAA00"))] + [:div (use-style (create-box-style-map-syntax "#AA00AA"))]]]) + +; Vector syntax + +(def grid-style-vector-syntax {; Default style uses Flexbox as fallback + :display "flex" + :flex-direction "row" + :flex-wrap "wrap" + :margin-bottom "1rem" + ::stylefy/media {{:max-width styles/phone-width} + {:display "block"}} + ; Use CSS Grid style if it is supported by the browser. + ; If the browser does not support CSS Grid or feature queries at all, this + ; block is simply ignored. + ::stylefy/supports [["display: grid" + {:display "grid" + :grid-template-columns "1fr 1fr 1fr" + ; Make CSS Grid responsive + ::stylefy/media {{:max-width styles/phone-width} + {:grid-template-columns "1fr"}}}]]}) + +(defn create-box-style-vector-syntax [color] + {:background-color color + :width "33.333%" + :height "200px" + ::stylefy/media {{:max-width styles/phone-width} + {:width "100%"}} + ::stylefy/supports [["display: grid" + ; Element width is always well managed by grid. + {:width "auto"}]]}) + +(defn grid-vector-syntax [] + [:<> + [:h3 "Vector syntax"] + [:div (use-style grid-style-vector-syntax) + + [:div (use-style (create-box-style-vector-syntax "#000000"))] + [:div (use-style (create-box-style-vector-syntax "#AA0000"))] + [:div (use-style (create-box-style-vector-syntax "#00AA00"))] + [:div (use-style (create-box-style-vector-syntax "#0000AA"))] + [:div (use-style (create-box-style-vector-syntax "#00AAAA"))] + [:div (use-style (create-box-style-vector-syntax "#AAAA00"))] + [:div (use-style (create-box-style-vector-syntax "#AA00AA"))]]]) \ No newline at end of file diff --git a/examples/reagent/src/cljs/stylefy/examples/reagent/main.cljs b/examples/reagent/src/cljs/stylefy/examples/reagent/main.cljs index b20c120c..c36e3dc6 100644 --- a/examples/reagent/src/cljs/stylefy/examples/reagent/main.cljs +++ b/examples/reagent/src/cljs/stylefy/examples/reagent/main.cljs @@ -147,24 +147,47 @@ [bs-navbar-item 0 active-index "Hello"] [bs-navbar-item 1 active-index "World!"]]))) -(defn- responsive-layout [] - [:div (use-style styles/responsive-layout) - ; The easiest way to use a sub-style is to call use-sub-style function: - [:div (use-sub-style styles/responsive-layout :column1) - [:p "This is column 1"] - [:p "This is column 1"] - [:p "This is column 1"] - [:p "This is column 1"] - [:p "This is column 1"]] - [:div (use-sub-style styles/responsive-layout :column2) - [:p "This is column 2"] - [:p "This is column 2"] - [:p "This is column 2"]] - [:div (use-sub-style styles/responsive-layout :column3) - ; If there are more than one level of sub-style nesting, call sub-style to get - ; the desired sub-style and use it. - [:p (use-style (sub-style styles/responsive-layout :column3 :text)) "This is column 3"] - [:p (use-style (sub-style styles/responsive-layout :column3 :text)) "This is column 3"]]]) +(defn- responsive-layout-map-syntax [] + [:<> + [:h3 "Map syntax"] + [:div (use-style styles/responsive-layout-map-syntax) + ; The easiest way to use a sub-style is to call use-sub-style function: + [:div (use-sub-style styles/responsive-layout-map-syntax :column1) + [:p "This is column 1"] + [:p "This is column 1"] + [:p "This is column 1"] + [:p "This is column 1"] + [:p "This is column 1"]] + [:div (use-sub-style styles/responsive-layout-map-syntax :column2) + [:p "This is column 2"] + [:p "This is column 2"] + [:p "This is column 2"]] + [:div (use-sub-style styles/responsive-layout-map-syntax :column3) + ; If there are more than one level of sub-style nesting, call sub-style to get + ; the desired sub-style and use it. + [:p (use-style (sub-style styles/responsive-layout-map-syntax :column3 :text)) "This is column 3"] + [:p (use-style (sub-style styles/responsive-layout-map-syntax :column3 :text)) "This is column 3"]]]]) + +(defn- responsive-layout-vector-syntax [] + [:<> + [:h3 "Vector syntax"] + [:div (use-style styles/responsive-layout-vector-syntax) + ; The easiest way to use a sub-style is to call use-sub-style function: + [:div (use-sub-style styles/responsive-layout-vector-syntax :column1) + [:p "This is column 1"] + [:p "This is column 1"] + [:p "This is column 1"] + [:p "This is column 1"] + [:p "This is column 1"]] + [:div (use-sub-style styles/responsive-layout-vector-syntax :column2) + [:p "This is column 2"] + [:p "This is column 2"] + [:p "This is column 2"]] + [:div (use-sub-style styles/responsive-layout-vector-syntax :column3) + ; If there are more than one level of sub-style nesting, call sub-style to get + ; the desired sub-style and use it. + [:p (use-style (sub-style styles/responsive-layout-vector-syntax :column3 :text)) "This is column 3"] + [:p (use-style (sub-style styles/responsive-layout-vector-syntax :column3 :text)) "This is column 3"]]]]) (defn animation [] [:div (use-style styles/animated-box)]) @@ -327,7 +350,8 @@ [:h2 "Simple responsive layout"] [:p "stylefy supports media queries out of the box"] - [responsive-layout] + [responsive-layout-map-syntax] + [responsive-layout-vector-syntax] [:h2 "Animations"] [:p "stylefy also supports keyframes"] @@ -343,7 +367,8 @@ [:h2 "Feature queries"] [:p "The following example is rendered using CSS Grid if supported by the browser. If not, it uses Flexbox fallback as the default style. stylefy also supports media queries inside feature queries!"] - [grid/grid] + [grid/grid-map-syntax] + [grid/grid-vector-syntax] [garden-units] diff --git a/examples/reagent/src/cljs/stylefy/examples/reagent/styles.cljs b/examples/reagent/src/cljs/stylefy/examples/reagent/styles.cljs index 8d6da78b..068077ae 100644 --- a/examples/reagent/src/cljs/stylefy/examples/reagent/styles.cljs +++ b/examples/reagent/src/cljs/stylefy/examples/reagent/styles.cljs @@ -82,7 +82,7 @@ (def column {:padding "5px" :color "white"}) -(def responsive-layout +(def responsive-layout-map-syntax {:display :flex :flex-direction :row ::stylefy/sub-styles @@ -100,6 +100,24 @@ ::stylefy/media {{:max-width phone-width} {:background-color "#000000"}}})} ::stylefy/media {{:max-width phone-width} {:display :block}}}) +(def responsive-layout-vector-syntax + {:display :flex + :flex-direction :row + ::stylefy/sub-styles + {:column1 (merge column + {:background-color "#AA0000" + :flex 1}) + :column2 (merge column + {:background-color "#00AA00" + :flex 2}) + :column3 (merge column + {:background-color "#0000AA" + :flex 1 + ; sub-styles can also contain sub-styles + ::stylefy/sub-styles {:text {:color "red"}} + ::stylefy/media [[{:max-width phone-width} {:background-color "#000000"}]]})} + ::stylefy/media {{:max-width phone-width} {:display :block}}}) + (def animated-box (merge simple-box {:animation-name "simple-animation" :animation-duration "3s" diff --git a/project.clj b/project.clj index cce957e3..554089f4 100644 --- a/project.clj +++ b/project.clj @@ -1,4 +1,4 @@ -(defproject stylefy "3.1.0" +(defproject stylefy "3.2.0" :description "Library for styling UI components" :url "https://github.com/Jarzka/stylefy" :dependencies [[org.clojure/clojure "1.9.0"] diff --git a/src/cljc/stylefy/impl/conversion.cljc b/src/cljc/stylefy/impl/conversion.cljc index 27f65914..87e8fccf 100644 --- a/src/cljc/stylefy/impl/conversion.cljc +++ b/src/cljc/stylefy/impl/conversion.cljc @@ -8,6 +8,8 @@ [clojure.string :as str] [garden.compiler :as compiler])) +(declare style->css) + (defn garden-units->css "Checks all values in the map and converts all Garden units to CSS." [props] @@ -107,62 +109,46 @@ stylefy features supported in media query style map: - modes + - scope - vendor prefixes - stylefy/manual is not supported here since one can use it to create + ::stylefy/manual is not supported here since one can use it to create media queries." - ; TODO Media queries could also be defined in a vector (just like modes can be defined as a map or vector) [{:keys [props hash custom-selector] :as _style} options] - (when-let [stylefy-media-queries (:stylefy.core/media props)] + (when-let [media-queries (:stylefy.core/media props)] (let [css-selector (or custom-selector (class-selector hash)) - css-media-queries (map - (fn [media-query] - (let [media-query-props (get stylefy-media-queries media-query) - media-query-css-props (utils/remove-special-keywords media-query-props) - scoped-styles-garden (map - (fn [scoping-rule] - (find-and-handle-scoped-style-map scoping-rule css-selector)) - (:stylefy.core/scope media-query-props)) - garden-class-definition [css-selector media-query-css-props] - garden-pseudo-classes (convert-stylefy-modes-to-garden media-query-props) - garden-vendors (convert-stylefy-vendors-to-garden media-query-props) - garden-options (or (merge options garden-vendors) {})] - (css garden-options [(at-media media-query (into garden-class-definition - garden-pseudo-classes)) - (at-media media-query scoped-styles-garden)]))) - (keys stylefy-media-queries))] + handle-media-query (fn [media-query media-query-props] + (let [media-query-css-props (utils/remove-special-keywords media-query-props) + scoped-styles-garden (map + (fn [scoping-rule] + (find-and-handle-scoped-style-map scoping-rule css-selector)) + (:stylefy.core/scope media-query-props)) + garden-class-definition [css-selector media-query-css-props] + garden-pseudo-classes (convert-stylefy-modes-to-garden media-query-props) + garden-vendors (convert-stylefy-vendors-to-garden media-query-props) + garden-options (or (merge options garden-vendors) {})] + (css garden-options [(at-media media-query (into garden-class-definition + garden-pseudo-classes)) + (at-media media-query scoped-styles-garden)]))) + css-media-queries (cond + (map? media-queries) (mapv #(handle-media-query % (get media-queries %)) (keys media-queries)) + (vector? media-queries) (mapv #(handle-media-query (first %) (second %)) media-queries))] (apply str css-media-queries)))) (defn- convert-feature-queries - "Converts stylefy/supports definition into CSS feature query. - - stylefy features supported in feature query style map: - - modes - - media queries - - vendor prefixes" - ; TODO Manual mode and scoping should also be supported here - [{:keys [props hash custom-selector] :as _style} options] - (when-let [stylefy-supports (:stylefy.core/supports props)] - (let [css-selector (or custom-selector (class-selector hash)) - css-supports (map - (fn [supports-selector] - (let [supports-props (get stylefy-supports supports-selector) - supports-css-props (utils/remove-special-keywords supports-props) - garden-class-definition [css-selector supports-css-props] - garden-pseudo-classes (convert-stylefy-modes-to-garden supports-props) - garden-vendors (convert-stylefy-vendors-to-garden supports-props) - garden-options (or (merge options garden-vendors) {}) - css-media-queries-inside-supports (convert-media-queries - {:props supports-props - :hash hash - :custom-selector custom-selector} - options)] - (str "@supports (" supports-selector ") {" - (css garden-options (into garden-class-definition - garden-pseudo-classes)) - css-media-queries-inside-supports - "}"))) - (keys stylefy-supports))] + "Converts stylefy/supports definition into CSS feature query." + [{:keys [hash props custom-selector] :as _style} options] + (when-let [supports-rules (:stylefy.core/supports props)] + (let [handle-supports-rule (fn [supports-query supports-props] + (str "@supports (" supports-query ") {" + (style->css {:props supports-props + :hash hash ; Hash of the whole map + :custom-selector custom-selector} + options) + "}")) + css-supports (cond + (map? supports-rules) (mapv #(handle-supports-rule % (get supports-rules %)) (keys supports-rules)) + (vector? supports-rules) (mapv #(handle-supports-rule (first %) (second %)) supports-rules))] (apply str css-supports)))) (defn- convert-manual-styles diff --git a/test/stylefy/tests/conversion_test.cljs b/test/stylefy/tests/conversion_test.cljs index 4e6ca11d..a2728d7c 100644 --- a/test/stylefy/tests/conversion_test.cljs +++ b/test/stylefy/tests/conversion_test.cljs @@ -93,47 +93,147 @@ ; Media queries -(def responsive-style {:background-color "red" - :border-radius "10px" - ::stylefy/vendors ["webkit" "moz" "o"] - ::stylefy/auto-prefix #{:border-radius} - ::stylefy/mode {:hover {:background-color "white"}} - ::stylefy/media {{:max-width "500px"} - {:background-color "blue" - :border-radius "5px" - ::stylefy/mode {:hover {:background-color "grey"}} - ::stylefy/vendors ["webkit" "moz" "o"] - ::stylefy/auto-prefix #{:border-radius}}}}) +(def responsive-style-map-syntax {:background-color "red" + :border-radius "10px" + ::stylefy/vendors ["webkit" "moz" "o"] + ::stylefy/auto-prefix #{:border-radius} + ::stylefy/mode {:hover {:background-color "white"}} + ::stylefy/media {{:max-width "500px"} + {:background-color "blue" + :border-radius "5px" + ::stylefy/mode {:hover {:background-color "grey"}} + ::stylefy/vendors ["webkit" "moz" "o"] + ::stylefy/auto-prefix #{:border-radius}}}}) + +(def responsive-style-vector-syntax {:background-color "red" + :border-radius "10px" + ::stylefy/vendors ["webkit" "moz" "o"] + ::stylefy/auto-prefix #{:border-radius} + ::stylefy/mode {:hover {:background-color "white"}} + ::stylefy/media [[{:max-width "500px"} + {:background-color "blue" + :border-radius "5px" + ::stylefy/mode {:hover {:background-color "grey"}} + ::stylefy/vendors ["webkit" "moz" "o"] + ::stylefy/auto-prefix #{:border-radius}}]]}) (deftest responsive-style->css - (is (= (conversion/style->css {:props responsive-style :hash (hashing/hash-style responsive-style)} - {:pretty-print? false}) - "._stylefy_628215496{background-color:red;border-radius:10px;-webkit-border-radius:10px;-moz-border-radius:10px;-o-border-radius:10px}._stylefy_628215496:hover{background-color:white}@media(max-width:500px){._stylefy_628215496{background-color:blue;border-radius:5px;-webkit-border-radius:5px;-moz-border-radius:5px;-o-border-radius:5px}._stylefy_628215496:hover{background-color:grey}}"))) - -(def grid-layout-with-fallback {:display "flex" - :flex-direction "row" - :flex-wrap "wrap" - ::stylefy/mode {:hover {:background-color "white"}} - ::stylefy/media {{:max-width "500px"} - {:display "block"}} - ::stylefy/supports - {"display: grid" - {:display "grid" - :grid-template-columns "1fr 1fr 1fr" - ::stylefy/mode {:hover {:background-color "#111111"}} - ; Make CSS Grid responsive - ::stylefy/media {{:max-width "500px"} - {:grid-template-columns "1fr" - ::stylefy/mode {:hover - {:background-color "grey"}}}}}}}) + (testing "Map syntax" + (is (= (conversion/style->css {:props responsive-style-map-syntax :hash (hashing/hash-style responsive-style-map-syntax)} + {:pretty-print? false}) + "._stylefy_628215496{background-color:red;border-radius:10px;-webkit-border-radius:10px;-moz-border-radius:10px;-o-border-radius:10px}._stylefy_628215496:hover{background-color:white}@media(max-width:500px){._stylefy_628215496{background-color:blue;border-radius:5px;-webkit-border-radius:5px;-moz-border-radius:5px;-o-border-radius:5px}._stylefy_628215496:hover{background-color:grey}}"))) + + (testing "Vector syntax" + (is (= (conversion/style->css {:props responsive-style-vector-syntax :hash (hashing/hash-style responsive-style-vector-syntax)} + {:pretty-print? false}) + "._stylefy_720265521{background-color:red;border-radius:10px;-webkit-border-radius:10px;-moz-border-radius:10px;-o-border-radius:10px}._stylefy_720265521:hover{background-color:white}@media(max-width:500px){._stylefy_720265521{background-color:blue;border-radius:5px;-webkit-border-radius:5px;-moz-border-radius:5px;-o-border-radius:5px}._stylefy_720265521:hover{background-color:grey}}"))) + + (testing "Same output with both syntaxes (excluding hash)" + (is (= (conversion/style->css {:props responsive-style-map-syntax + :hash "test"} + {:pretty-print? false}) + (conversion/style->css {:props responsive-style-vector-syntax + :hash "test"} + {:pretty-print? false})))) + + (testing "Rules are rendered in the right order" + (let [style {::stylefy/media [[{:min-width "200px"} {:color "red"}] + [{:min-width "300px"} {:color "green"}] + [{:min-width "400px"} {:color "blue"}] + [{:min-width "500px"} {:color "purple"}] + [{:min-width "600px"} {:color "yellow"}]]}] + (is (= (conversion/style->css {:props style + :hash (hashing/hash-style style)} + {:pretty-print? false}) + "._stylefy_1197239522{}@media(min-width:200px){._stylefy_1197239522{color:red}}@media(min-width:300px){._stylefy_1197239522{color:green}}@media(min-width:400px){._stylefy_1197239522{color:blue}}@media(min-width:500px){._stylefy_1197239522{color:purple}}@media(min-width:600px){._stylefy_1197239522{color:yellow}}"))))) ; Feature queries +(def grid-layout-with-fallback-map-syntax {:display "flex" + :flex-direction "row" + :flex-wrap "wrap" + ::stylefy/mode {:hover {:background-color "white"}} + ::stylefy/media {{:max-width "500px"} + {:display "block"}} + ::stylefy/supports + {"display: grid" + {:display "grid" + :grid-template-columns "1fr 1fr 1fr" + ::stylefy/mode {:hover {:background-color "#111111"}} + ; Make CSS Grid responsive + ::stylefy/media {{:max-width "500px"} + {:grid-template-columns "1fr" + ::stylefy/mode {:hover + {:background-color "grey"}}}}}}}) + +(def grid-layout-with-fallback-vector-syntax {:display "flex" + :flex-direction "row" + :flex-wrap "wrap" + ::stylefy/mode {:hover {:background-color "white"}} + ::stylefy/media {{:max-width "500px"} + {:display "block"}} + ::stylefy/supports [["display: grid" + {:display "grid" + :grid-template-columns "1fr 1fr 1fr" + ::stylefy/mode {:hover {:background-color "#111111"}} + ; Make CSS Grid responsive + ::stylefy/media {{:max-width "500px"} + {:grid-template-columns "1fr" + ::stylefy/mode {:hover + {:background-color "grey"}}}}}]]}) + +(def supports-with-many-stylefy-features {::stylefy/supports [["display: grid" + {:color :green + ::stylefy/mode [[:hover {:color :blue}]] + ::stylefy/scope [[:.scope {:color :yellow + ::stylefy/manual [[:.child-in-scope {:color :red}]]}]] + ::stylefy/manual [[:.child {:color :purple}]]}]]}) + (deftest supports->css - (is (= (conversion/style->css {:props grid-layout-with-fallback - :hash (hashing/hash-style grid-layout-with-fallback)} - {:pretty-print? false}) - "._stylefy_-782791788{display:flex;flex-direction:row;flex-wrap:wrap}._stylefy_-782791788:hover{background-color:white}@media(max-width:500px){._stylefy_-782791788{display:block}}@supports (display: grid) {._stylefy_-782791788{display:grid;grid-template-columns:1fr 1fr 1fr}._stylefy_-782791788:hover{background-color:#111111}@media(max-width:500px){._stylefy_-782791788{grid-template-columns:1fr}._stylefy_-782791788:hover{background-color:grey}}}"))) + (testing "Map syntax" + (is (= (conversion/style->css {:props grid-layout-with-fallback-map-syntax + :hash (hashing/hash-style grid-layout-with-fallback-map-syntax)} + {:pretty-print? false}) + "._stylefy_-782791788{display:flex;flex-direction:row;flex-wrap:wrap}._stylefy_-782791788:hover{background-color:white}@media(max-width:500px){._stylefy_-782791788{display:block}}@supports (display: grid) {._stylefy_-782791788{display:grid;grid-template-columns:1fr 1fr 1fr}._stylefy_-782791788:hover{background-color:#111111}@media(max-width:500px){._stylefy_-782791788{grid-template-columns:1fr}._stylefy_-782791788:hover{background-color:grey}}}"))) + + (testing "Vector syntax" + (is (= (conversion/style->css {:props grid-layout-with-fallback-vector-syntax + :hash (hashing/hash-style grid-layout-with-fallback-vector-syntax)} + {:pretty-print? false}) + "._stylefy_-683353920{display:flex;flex-direction:row;flex-wrap:wrap}._stylefy_-683353920:hover{background-color:white}@media(max-width:500px){._stylefy_-683353920{display:block}}@supports (display: grid) {._stylefy_-683353920{display:grid;grid-template-columns:1fr 1fr 1fr}._stylefy_-683353920:hover{background-color:#111111}@media(max-width:500px){._stylefy_-683353920{grid-template-columns:1fr}._stylefy_-683353920:hover{background-color:grey}}}")) + + (testing "Rules are rendered in the right order" + (let [style {::stylefy/supports [["display: grid" + {:color "green"}] + ["display: flex" + {:color "blue"}]]}] + (is (= (conversion/style->css {:props style + :hash (hashing/hash-style style)} + {:pretty-print? false}) + "._stylefy_-1712366838{}@supports (display: grid) {._stylefy_-1712366838{color:green}}@supports (display: flex) {._stylefy_-1712366838{color:blue}}"))) + + (let [style {::stylefy/supports [["display: flex" + {:color "blue"}] + ["display: grid" + {:color "green"}]]}] + (is (= (conversion/style->css {:props style + :hash (hashing/hash-style style)} + {:pretty-print? false}) + "._stylefy_-2028302377{}@supports (display: flex) {._stylefy_-2028302377{color:blue}}@supports (display: grid) {._stylefy_-2028302377{color:green}}"))))) + + (testing "Same output with both syntaxes (excluding hash)" + (is (= (conversion/style->css {:props grid-layout-with-fallback-map-syntax + :hash "test"} + {:pretty-print? false}) + (conversion/style->css {:props grid-layout-with-fallback-vector-syntax + :hash "test"} + {:pretty-print? false})))) + + (testing "Other stylefy features also work in the supports query" + (is (= (conversion/style->css {:props supports-with-many-stylefy-features + :hash (hashing/hash-style supports-with-many-stylefy-features)} + {:pretty-print? false}) + "._stylefy_1494431776{}@supports (display: grid) {._stylefy_1494431776{color:green}._stylefy_1494431776:hover{color:blue}.scope ._stylefy_1494431776{color:yellow}.scope ._stylefy_1494431776 .child-in-scope{color:red}._stylefy_1494431776 .child{color:purple}}")))) (deftest custom-selector (let [style {:color "red"}] @@ -205,7 +305,7 @@ (let [style {:color :red ::stylefy/manual [["> .box:hover" {:color "black"}]]}] (is (= (conversion/style->css {:props style :hash (hashing/hash-style style)} {:pretty-print? false}) - "._stylefy_696232348{color:red}._stylefy_696232348 > .box:hover{color:black}")))) + "._stylefy_696232348{color:red}._stylefy_696232348 > .box:hover{color:black}")))) (testing "Manual mode with nested at-supports and at-media" (let [style {:color "red"