diff --git a/.bumpedrc b/.bumpedrc
index 04826e51..f283773f 100644
--- a/.bumpedrc
+++ b/.bumpedrc
@@ -23,7 +23,7 @@ plugins:
'Commiting new version':
plugin: 'bumped-terminal'
- command: 'git add CHANGELOG.md package.json && git commit package.json -m "Release $newVersion"'
+ command: 'git add CHANGELOG.md package.json && git commit CHANGELOG.md package.json -m "Release $newVersion"'
'Detecting problem before publish':
plugin: 'bumped-terminal'
diff --git a/.sass-lint.yml b/.sass-lint.yml
deleted file mode 100644
index abd6057e..00000000
--- a/.sass-lint.yml
+++ /dev/null
@@ -1,397 +0,0 @@
-options:
- formatter: stylish
- merge-default-rules: false
-rules:
- border-zero: 1
- brace-style:
- - 1
- - allow-single-line: true
- class-name-format:
- - 0
- - convention: hyphenatedlowercase
- clean-import-paths:
- - 1
- - filename-extension: false
- leading-underscore: false
- empty-line-between-blocks:
- - 0
- - ignore-single-line-rulesets: true
- extends-before-declarations: 0
- extends-before-mixins: 0
- final-newline:
- - 1
- - include: true
- force-attribute-nesting: 0
- force-element-nesting: 0
- force-pseudo-nesting: 0
- function-name-format:
- - 1
- - allow-leading-underscore: true
- convention: hyphenatedlowercase
- hex-length:
- - 1
- - style: short
- hex-notation:
- - 1
- - style: lowercase
- id-name-format:
- - 0
- - convention: hyphenatedlowercase
- indentation:
- - 1
- - size: 2
- leading-zero:
- - 0
- - include: false
- mixin-name-format:
- - 1
- - allow-leading-underscore: true
- convention: hyphenatedlowercase
- mixins-before-declarations: 0
- nesting-depth: 0
- no-color-literals: 0
- no-css-comments: 1
- no-debug: 1
- no-duplicate-properties:
- - 1
- - exclude: []
- no-empty-rulesets: 1
- no-ids: 1
- no-important: 0
- no-invalid-hex: 1
- no-mergeable-selectors: 0
- no-misspelled-properties:
- - 1
- - extra-properties:
- - composes
- no-qualifying-elements:
- - 0
- - allow-element-with-attribute: false
- allow-element-with-class: false
- allow-element-with-id: false
- no-trailing-zero: 1
- no-url-protocols: 1
- placeholder-in-extend: 0
- property-sort-order:
- - 1
- - ignore-custom-properties: false
- order:
- - $variable
- - $extend
- - $include
- - composes
- - position
- - top
- - right
- - bottom
- - left
- - z-index
- - '-webkit-box-sizing'
- - '-moz-box-sizing'
- - box-sizing
- - display
- - float
- - width
- - min-width
- - max-width
- - height
- - min-height
- - max-height
- - flex
- - flex-align
- - flex-direction
- - flex-flow
- - flex-grow
- - flex-order
- - flex-pack
- - flex-wrap
- - align-content
- - align-items
- - justify-content
- - padding
- - padding-top
- - padding-right
- - padding-bottom
- - padding-left
- - margin
- - margin-top
- - margin-right
- - margin-bottom
- - margin-left
- - overflow
- - overflow-x
- - overflow-y
- - '-webkit-overflow-scrolling'
- - '-ms-overflow-x'
- - '-ms-overflow-y'
- - '-ms-overflow-style'
- - clip
- - clear
- - font
- - font-family
- - font-size
- - font-style
- - font-weight
- - font-variant
- - font-size-adjust
- - font-stretch
- - font-effect
- - font-emphasize
- - font-emphasize-position
- - font-emphasize-style
- - font-smooth
- - '-webkit-hyphens'
- - '-moz-hyphens'
- - hyphens
- - line-height
- - color
- - text-align
- - '-webkit-text-align-last'
- - '-moz-text-align-last'
- - '-ms-text-align-last'
- - text-align-last
- - text-emphasis
- - text-emphasis-color
- - text-emphasis-style
- - text-emphasis-position
- - text-decoration
- - text-indent
- - text-justify
- - text-outline
- - '-ms-text-overflow'
- - text-overflow
- - text-overflow-ellipsis
- - text-overflow-mode
- - text-shadow
- - text-transform
- - text-wrap
- - '-webkit-text-size-adjust'
- - '-ms-text-size-adjust'
- - letter-spacing
- - '-ms-word-break'
- - word-break
- - word-spacing
- - '-ms-word-wrap'
- - word-wrap
- - '-moz-tab-size'
- - '-o-tab-size'
- - tab-size
- - white-space
- - vertical-align
- - list-style
- - list-style-position
- - list-style-type
- - list-style-image
- - pointer-events
- - '-ms-touch-action'
- - touch-action
- - cursor
- - visibility
- - zoom
- - table-layout
- - empty-cells
- - caption-side
- - border-spacing
- - border-collapse
- - content
- - quotes
- - counter-reset
- - counter-increment
- - resize
- - '-webkit-user-select'
- - '-moz-user-select'
- - '-ms-user-select'
- - '-o-user-select'
- - user-select
- - nav-index
- - nav-up
- - nav-right
- - nav-down
- - nav-left
- - background
- - background-color
- - background-image
- - "-ms-filter:\\'progid:DXImageTransform.Microsoft.gradient"
- - 'filter:progid:DXImageTransform.Microsoft.gradient'
- - 'filter:progid:DXImageTransform.Microsoft.AlphaImageLoader'
- - filter
- - background-repeat
- - background-attachment
- - background-position
- - background-position-x
- - background-position-y
- - '-webkit-background-clip'
- - '-moz-background-clip'
- - background-clip
- - background-origin
- - '-webkit-background-size'
- - '-moz-background-size'
- - '-o-background-size'
- - background-size
- - border
- - border-color
- - border-style
- - border-width
- - border-top
- - border-top-color
- - border-top-style
- - border-top-width
- - border-right
- - border-right-color
- - border-right-style
- - border-right-width
- - border-bottom
- - border-bottom-color
- - border-bottom-style
- - border-bottom-width
- - border-left
- - border-left-color
- - border-left-style
- - border-left-width
- - border-radius
- - border-top-left-radius
- - border-top-right-radius
- - border-bottom-right-radius
- - border-bottom-left-radius
- - '-webkit-border-image'
- - '-moz-border-image'
- - '-o-border-image'
- - border-image
- - '-webkit-border-image-source'
- - '-moz-border-image-source'
- - '-o-border-image-source'
- - border-image-source
- - '-webkit-border-image-slice'
- - '-moz-border-image-slice'
- - '-o-border-image-slice'
- - border-image-slice
- - '-webkit-border-image-width'
- - '-moz-border-image-width'
- - '-o-border-image-width'
- - border-image-width
- - '-webkit-border-image-outset'
- - '-moz-border-image-outset'
- - '-o-border-image-outset'
- - border-image-outset
- - '-webkit-border-image-repeat'
- - '-moz-border-image-repeat'
- - '-o-border-image-repeat'
- - border-image-repeat
- - outline
- - outline-width
- - outline-style
- - outline-color
- - outline-offset
- - '-webkit-box-shadow'
- - '-moz-box-shadow'
- - box-shadow
- - 'filter:progid:DXImageTransform.Microsoft.Alpha(Opacity'
- - "-ms-filter:\\'progid:DXImageTransform.Microsoft.Alpha"
- - opacity
- - '-ms-interpolation-mode'
- - '-webkit-transition'
- - '-moz-transition'
- - '-ms-transition'
- - '-o-transition'
- - transition
- - '-webkit-transition-delay'
- - '-moz-transition-delay'
- - '-ms-transition-delay'
- - '-o-transition-delay'
- - transition-delay
- - '-webkit-transition-timing-function'
- - '-moz-transition-timing-function'
- - '-ms-transition-timing-function'
- - '-o-transition-timing-function'
- - transition-timing-function
- - '-webkit-transition-duration'
- - '-moz-transition-duration'
- - '-ms-transition-duration'
- - '-o-transition-duration'
- - transition-duration
- - '-webkit-transition-property'
- - '-moz-transition-property'
- - '-ms-transition-property'
- - '-o-transition-property'
- - transition-property
- - transform-style
- - '-webkit-transform'
- - '-moz-transform'
- - '-ms-transform'
- - '-o-transform'
- - transform
- - '-webkit-transform-origin'
- - '-moz-transform-origin'
- - '-ms-transform-origin'
- - '-o-transform-origin'
- - transform-origin
- - '-webkit-animation'
- - '-moz-animation'
- - '-ms-animation'
- - '-o-animation'
- - animation
- - '-webkit-animation-name'
- - '-moz-animation-name'
- - '-ms-animation-name'
- - '-o-animation-name'
- - animation-name
- - '-webkit-animation-duration'
- - '-moz-animation-duration'
- - '-ms-animation-duration'
- - '-o-animation-duration'
- - animation-duration
- - '-webkit-animation-play-state'
- - '-moz-animation-play-state'
- - '-ms-animation-play-state'
- - '-o-animation-play-state'
- - animation-play-state
- - '-webkit-animation-timing-function'
- - '-moz-animation-timing-function'
- - '-ms-animation-timing-function'
- - '-o-animation-timing-function'
- - animation-timing-function
- - '-webkit-animation-delay'
- - '-moz-animation-delay'
- - '-ms-animation-delay'
- - '-o-animation-delay'
- - animation-delay
- - '-webkit-animation-iteration-count'
- - '-moz-animation-iteration-count'
- - '-ms-animation-iteration-count'
- - '-o-animation-iteration-count'
- - animation-iteration-count
- - '-webkit-animation-direction'
- - '-moz-animation-direction'
- - '-ms-animation-direction'
- - '-o-animation-direction'
- - animation-direction
- - backface-visibility
- - will-change
- - fill
- quotes:
- - 1
- - style: double
- shorthand-values: 1
- single-line-per-selector: 0
- space-after-bang:
- - 1
- - include: false
- space-after-colon: 1
- space-after-comma: 0
- space-before-bang:
- - 1
- - include: true
- space-before-brace:
- - 1
- - include: true
- space-before-colon: 1
- space-between-parens:
- - 1
- - include: false
- trailing-semicolon: 1
- url-quotes: 1
- variable-name-format:
- - 1
- - allow-leading-underscore: true
- convention: hyphenatedlowercase
- zero-unit: 1
diff --git a/.stylelintrc b/.stylelintrc
new file mode 100644
index 00000000..de1aeda1
--- /dev/null
+++ b/.stylelintrc
@@ -0,0 +1,26 @@
+{
+ "extends": "stylelint-config-standard",
+ "rules": {
+ "at-rule-no-unknown": [true, {
+ ignoreAtRules: ["define-mixin", "mixin", "each"]
+ }],
+ "property-no-unknown": [ true, {
+ "ignoreProperties": [
+ "composes",
+ "font-smoothing"
+ ]
+ }],
+ "color-hex-case": "lower",
+ "declaration-block-properties-order": "alphabetical",
+ "font-family-name-quotes": "always-where-recommended",
+ "string-quotes": "single",
+ "selector-pseudo-class-no-unknown": [
+ true,
+ {
+ "ignorePseudoClasses": [
+ "global"
+ ]
+ }
+ ]
+ }
+}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 743b1706..fcf5dfa0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,108 @@
+
+# 2.0.0-beta.0 (2016-12-07)
+
+* Add CHANGELOG to release command ([50b7a95](https://github.com/react-toolbox/react-toolbox/commit/50b7a95))
+* add default prop className to Layout, NavDrawer and Sidebar ([868c284](https://github.com/react-toolbox/react-toolbox/commit/868c284))
+* Add inner layer to AppBar ([8c541e2](https://github.com/react-toolbox/react-toolbox/commit/8c541e2))
+* Add missing Drawer identifier ([5616697](https://github.com/react-toolbox/react-toolbox/commit/5616697))
+* add smTablet and lgTablet to NavDrawer in Layout readme ([3ef9415](https://github.com/react-toolbox/react-toolbox/commit/3ef9415))
+* Adds onQueryChange callback property to Autocomplete ([e971fb4](https://github.com/react-toolbox/react-toolbox/commit/e971fb4))
+* Build using Gulp ([fbae545](https://github.com/react-toolbox/react-toolbox/commit/fbae545))
+* Enabled HMR for styles by disabling extracting them to a CSS file ([52c4829](https://github.com/react-toolbox/react-toolbox/commit/52c4829))
+* Export ThemeProvider from react-css-themr ([6af337c](https://github.com/react-toolbox/react-toolbox/commit/6af337c))
+* Fix #965 ([c92b3c8](https://github.com/react-toolbox/react-toolbox/commit/c92b3c8)), closes [#965](https://github.com/react-toolbox/react-toolbox/issues/965)
+* Fix #966 ([9944ef8](https://github.com/react-toolbox/react-toolbox/commit/9944ef8)), closes [#966](https://github.com/react-toolbox/react-toolbox/issues/966)
+* fix css linter errors in card and slider ([5ec9d6c](https://github.com/react-toolbox/react-toolbox/commit/5ec9d6c))
+* Fix old sass var in list/config.css ([7d621ed](https://github.com/react-toolbox/react-toolbox/commit/7d621ed))
+* Fixes #1021 ([8c250c6](https://github.com/react-toolbox/react-toolbox/commit/8c250c6)), closes [#1021](https://github.com/react-toolbox/react-toolbox/issues/1021)
+* Fixes #1025 ([c18ffa4](https://github.com/react-toolbox/react-toolbox/commit/c18ffa4)), closes [#1025](https://github.com/react-toolbox/react-toolbox/issues/1025)
+* Fixes #976 ([0e89b2d](https://github.com/react-toolbox/react-toolbox/commit/0e89b2d)), closes [#976](https://github.com/react-toolbox/react-toolbox/issues/976)
+* fixes old sass var in css config ([da0c470](https://github.com/react-toolbox/react-toolbox/commit/da0c470))
+* Input ready to accept visible hint ([577feb3](https://github.com/react-toolbox/react-toolbox/commit/577feb3))
+* Latest build ([f032f68](https://github.com/react-toolbox/react-toolbox/commit/f032f68))
+* Latest build ([170ee4d](https://github.com/react-toolbox/react-toolbox/commit/170ee4d))
+* New layout ([fd79c84](https://github.com/react-toolbox/react-toolbox/commit/fd79c84))
+* New Table implementation ([7d0035a](https://github.com/react-toolbox/react-toolbox/commit/7d0035a))
+* Prepare slider and progress to be disabled ([69f7868](https://github.com/react-toolbox/react-toolbox/commit/69f7868))
+* Refactor Dialog, Drawer and Overlay to be used in Layout ([8e76427](https://github.com/react-toolbox/react-toolbox/commit/8e76427))
+* remove layout playground example ([76c636d](https://github.com/react-toolbox/react-toolbox/commit/76c636d))
+* Remove lib ([6874dbb](https://github.com/react-toolbox/react-toolbox/commit/6874dbb))
+* Remove lib from repo ([d7f743a](https://github.com/react-toolbox/react-toolbox/commit/d7f743a))
+* Remove normalize.css from commons.css ([1b62b78](https://github.com/react-toolbox/react-toolbox/commit/1b62b78))
+* Remove sass lint ([532abd1](https://github.com/react-toolbox/react-toolbox/commit/532abd1))
+* Render Snackbar using Portal ([b293fa1](https://github.com/react-toolbox/react-toolbox/commit/b293fa1))
+* Typings for Table component ([6540226](https://github.com/react-toolbox/react-toolbox/commit/6540226))
+* Update dependencies ([67cec5b](https://github.com/react-toolbox/react-toolbox/commit/67cec5b))
+* Update lib build ([c4f968b](https://github.com/react-toolbox/react-toolbox/commit/c4f968b))
+* Update linter ([23e538f](https://github.com/react-toolbox/react-toolbox/commit/23e538f))
+* Updated css-related dependencies ([292b838](https://github.com/react-toolbox/react-toolbox/commit/292b838))
+* Use Layout in spec ([042ecba](https://github.com/react-toolbox/react-toolbox/commit/042ecba))
+
+
+
+
+# 2.0.0-beta.0 (2016-10-06)
+
+* Add base CSS variables ([05302dd](https://github.com/react-toolbox/react-toolbox/commit/05302dd))
+* Add CSS colors ([624b875](https://github.com/react-toolbox/react-toolbox/commit/624b875))
+* Add CSS custom media queries ([c81dee4](https://github.com/react-toolbox/react-toolbox/commit/c81dee4))
+* Add missing input config variables for Dropdown and Autocomplete ([159da10](https://github.com/react-toolbox/react-toolbox/commit/159da10))
+* Add postcss-mixins and postcss-each ([1f55336](https://github.com/react-toolbox/react-toolbox/commit/1f55336))
+* Add postcss-next postcss-include and reporter ([fa35b84](https://github.com/react-toolbox/react-toolbox/commit/fa35b84))
+* Add shadows to CSS variables ([ac60b21](https://github.com/react-toolbox/react-toolbox/commit/ac60b21))
+* Add some missing nesting notations ([6b2e71d](https://github.com/react-toolbox/react-toolbox/commit/6b2e71d))
+* Add stylelint ([990d159](https://github.com/react-toolbox/react-toolbox/commit/990d159))
+* Bugfix in avatar css ([6c87982](https://github.com/react-toolbox/react-toolbox/commit/6c87982))
+* Build with CSS ([7ddf7e3](https://github.com/react-toolbox/react-toolbox/commit/7ddf7e3))
+* Bye from docs to sass ([9e7121b](https://github.com/react-toolbox/react-toolbox/commit/9e7121b))
+* Fix bug in button theme ([2e16602](https://github.com/react-toolbox/react-toolbox/commit/2e16602))
+* Fix linter errors ([ca19130](https://github.com/react-toolbox/react-toolbox/commit/ca19130))
+* Fix tests ([ac922f6](https://github.com/react-toolbox/react-toolbox/commit/ac922f6))
+* Fix tests ([6dcd36b](https://github.com/react-toolbox/react-toolbox/commit/6dcd36b))
+* Fixed typo in list/config.css ([7aae2fb](https://github.com/react-toolbox/react-toolbox/commit/7aae2fb))
+* Latest build ([9b263ff](https://github.com/react-toolbox/react-toolbox/commit/9b263ff))
+* Migrate animations to PostCSS ([2547c5c](https://github.com/react-toolbox/react-toolbox/commit/2547c5c))
+* Migrate AppBar style to PostCSS ([a5ad4fc](https://github.com/react-toolbox/react-toolbox/commit/a5ad4fc))
+* Migrate Autocomplete style to PostCSS ([6c615d6](https://github.com/react-toolbox/react-toolbox/commit/6c615d6))
+* Migrate Avatar style to PostCSS ([30cf0c8](https://github.com/react-toolbox/react-toolbox/commit/30cf0c8))
+* Migrate Button style to PostCSS ([b7bd84d](https://github.com/react-toolbox/react-toolbox/commit/b7bd84d))
+* Migrate Card style to PostCSS ([e9c2824](https://github.com/react-toolbox/react-toolbox/commit/e9c2824))
+* Migrate Checkbox style to PostCSS ([5f0a25c](https://github.com/react-toolbox/react-toolbox/commit/5f0a25c))
+* Migrate Chip style to PostCSS ([d3520d7](https://github.com/react-toolbox/react-toolbox/commit/d3520d7))
+* Migrate commons to PostCSS ([c02f204](https://github.com/react-toolbox/react-toolbox/commit/c02f204))
+* Migrate DataPicker style to PostCSS ([334620c](https://github.com/react-toolbox/react-toolbox/commit/334620c))
+* Migrate Dialog style to PostCSS ([c85ea04](https://github.com/react-toolbox/react-toolbox/commit/c85ea04))
+* Migrate Drawer style to PostCSS ([ae11fae](https://github.com/react-toolbox/react-toolbox/commit/ae11fae))
+* Migrate Dropdown style to PostCSS ([d6d4dff](https://github.com/react-toolbox/react-toolbox/commit/d6d4dff))
+* Migrate Input style to PostCSS ([090b098](https://github.com/react-toolbox/react-toolbox/commit/090b098))
+* Migrate Layout style to PostCSS ([247e973](https://github.com/react-toolbox/react-toolbox/commit/247e973))
+* Migrate Link style to PostCSS ([95cf291](https://github.com/react-toolbox/react-toolbox/commit/95cf291))
+* Migrate List style to PostCSS ([f8f1edd](https://github.com/react-toolbox/react-toolbox/commit/f8f1edd))
+* Migrate Menu style to PostCSS ([955ca1d](https://github.com/react-toolbox/react-toolbox/commit/955ca1d))
+* Migrate Navigation style to PostCSS ([7524ff0](https://github.com/react-toolbox/react-toolbox/commit/7524ff0))
+* Migrate Overlay style to PostCSS ([9aa9547](https://github.com/react-toolbox/react-toolbox/commit/9aa9547))
+* Migrate ProgressBar style to PostCSS ([47c2621](https://github.com/react-toolbox/react-toolbox/commit/47c2621))
+* Migrate Radio style to PostCSS ([f6bd59b](https://github.com/react-toolbox/react-toolbox/commit/f6bd59b))
+* Migrate Ripple style to PostCSS ([e4bebc8](https://github.com/react-toolbox/react-toolbox/commit/e4bebc8))
+* Migrate Slider style to PostCSS ([59c5ada](https://github.com/react-toolbox/react-toolbox/commit/59c5ada))
+* Migrate Snackbar style to PostCSS ([44849be](https://github.com/react-toolbox/react-toolbox/commit/44849be))
+* Migrate Switch style to PostCSS ([6cc0dc7](https://github.com/react-toolbox/react-toolbox/commit/6cc0dc7))
+* Migrate Table style to PostCSS ([c6b19b6](https://github.com/react-toolbox/react-toolbox/commit/c6b19b6))
+* Migrate Tabs style to PostCSS ([ae0b0fb](https://github.com/react-toolbox/react-toolbox/commit/ae0b0fb))
+* Migrate TimePicker to PostCSS ([153ab93](https://github.com/react-toolbox/react-toolbox/commit/153ab93))
+* Migrate Tooltip styles to PostCSS ([ab74c58](https://github.com/react-toolbox/react-toolbox/commit/ab74c58))
+* Release 2.0.0-beta.0 ([280bf69](https://github.com/react-toolbox/react-toolbox/commit/280bf69))
+* Remove AppBar SASS dependency from spec page ([1011eb3](https://github.com/react-toolbox/react-toolbox/commit/1011eb3))
+* Remove sass from main project ([7b562b8](https://github.com/react-toolbox/react-toolbox/commit/7b562b8))
+* Remove unneded deps for sass in docs subproject ([72fdc19](https://github.com/react-toolbox/react-toolbox/commit/72fdc19))
+* Remove unneeded media CSS import in Avatar ([359d6be](https://github.com/react-toolbox/react-toolbox/commit/359d6be))
+* Update webpack config for testing and tests ([5da2583](https://github.com/react-toolbox/react-toolbox/commit/5da2583))
+* Update webpack test config and linting from npm ([2a735cd](https://github.com/react-toolbox/react-toolbox/commit/2a735cd))
+* use 4p shadow in AppBar as spec indicates ([1da85d3](https://github.com/react-toolbox/react-toolbox/commit/1da85d3))
+* Use dashes for CSS colors ([566b349](https://github.com/react-toolbox/react-toolbox/commit/566b349))
+
+
+
## 1.1.2 (2016-08-11)
diff --git a/components/ThemeProvider.js b/components/ThemeProvider.js
new file mode 100644
index 00000000..2620cb55
--- /dev/null
+++ b/components/ThemeProvider.js
@@ -0,0 +1 @@
+export { ThemeProvider as default } from 'react-css-themr';
diff --git a/components/_colors.scss b/components/_colors.scss
deleted file mode 100644
index c2eb5099..00000000
--- a/components/_colors.scss
+++ /dev/null
@@ -1,301 +0,0 @@
-//-- Color definitions taken from Material Design Lite
-
-// Red
-$palette-red-50: rgb(255,235,238);
-$palette-red-100: rgb(255,205,210);
-$palette-red-200: rgb(239,154,154);
-$palette-red-300: rgb(229,115,115);
-$palette-red-400: rgb(239,83,80);
-$palette-red-500: rgb(244,67,54);
-$palette-red-600: rgb(229,57,53);
-$palette-red-700: rgb(211,47,47);
-$palette-red-800: rgb(198,40,40);
-$palette-red-900: rgb(183,28,28);
-$palette-red-a100: rgb(255,138,128);
-$palette-red-a200: rgb(255,82,82);
-$palette-red-a400: rgb(255,23,68);
-$palette-red-a700: rgb(213,0,0);
-
-// Pink
-$palette-pink-50: rgb(252,228,236);
-$palette-pink-100: rgb(248,187,208);
-$palette-pink-200: rgb(244,143,177);
-$palette-pink-300: rgb(240,98,146);
-$palette-pink-400: rgb(236,64,122);
-$palette-pink-500: rgb(233,30,99);
-$palette-pink-600: rgb(216,27,96);
-$palette-pink-700: rgb(194,24,91);
-$palette-pink-800: rgb(173,20,87);
-$palette-pink-900: rgb(136,14,79);
-$palette-pink-a100: rgb(255,128,171);
-$palette-pink-a200: rgb(255,64,129);
-$palette-pink-a400: rgb(245,0,87);
-$palette-pink-a700: rgb(197,17,98);
-
-// Purple
-$palette-purple-50: rgb(243,229,245);
-$palette-purple-100: rgb(225,190,231);
-$palette-purple-200: rgb(206,147,216);
-$palette-purple-300: rgb(186,104,200);
-$palette-purple-400: rgb(171,71,188);
-$palette-purple-500: rgb(156,39,176);
-$palette-purple-600: rgb(142,36,170);
-$palette-purple-700: rgb(123,31,162);
-$palette-purple-800: rgb(106,27,154);
-$palette-purple-900: rgb(74,20,140);
-$palette-purple-a100: rgb(234,128,252);
-$palette-purple-a200: rgb(224,64,251);
-$palette-purple-a400: rgb(213,0,249);
-$palette-purple-a700: rgb(170,0,255);
-
-//Deep Purple
-$palette-deep-purple-50: rgb(237,231,246);
-$palette-deep-purple-100: rgb(209,196,233);
-$palette-deep-purple-200: rgb(179,157,219);
-$palette-deep-purple-300: rgb(149,117,205);
-$palette-deep-purple-400: rgb(126,87,194);
-$palette-deep-purple-500: rgb(103,58,183);
-$palette-deep-purple-600: rgb(94,53,177);
-$palette-deep-purple-700: rgb(81,45,168);
-$palette-deep-purple-800: rgb(69,39,160);
-$palette-deep-purple-900: rgb(49,27,146);
-$palette-deep-purple-a100: rgb(179,136,255);
-$palette-deep-purple-a200: rgb(124,77,255);
-$palette-deep-purple-a400: rgb(101,31,255);
-$palette-deep-purple-a700: rgb(98,0,234);
-
-// Indigo
-$palette-indigo-50: rgb(232,234,246);
-$palette-indigo-100: rgb(197,202,233);
-$palette-indigo-200: rgb(159,168,218);
-$palette-indigo-300: rgb(121,134,203);
-$palette-indigo-400: rgb(92,107,192);
-$palette-indigo-500: rgb(63,81,181);
-$palette-indigo-600: rgb(57,73,171);
-$palette-indigo-700: rgb(48,63,159);
-$palette-indigo-800: rgb(40,53,147);
-$palette-indigo-900: rgb(26,35,126);
-$palette-indigo-a100: rgb(140,158,255);
-$palette-indigo-a200: rgb(83,109,254);
-$palette-indigo-a400: rgb(61,90,254);
-$palette-indigo-a700: rgb(48,79,254);
-
-// Blue
-$palette-blue-50: rgb(227,242,253);
-$palette-blue-100: rgb(187,222,251);
-$palette-blue-200: rgb(144,202,249);
-$palette-blue-300: rgb(100,181,246);
-$palette-blue-400: rgb(66,165,245);
-$palette-blue-500: rgb(33,150,243);
-$palette-blue-600: rgb(30,136,229);
-$palette-blue-700: rgb(25,118,210);
-$palette-blue-800: rgb(21,101,192);
-$palette-blue-900: rgb(13,71,161);
-$palette-blue-a100: rgb(130,177,255);
-$palette-blue-a200: rgb(68,138,255);
-$palette-blue-a400: rgb(41,121,255);
-$palette-blue-a700: rgb(41,98,255);
-
-// Light Blue
-$palette-light-blue-50: rgb(225,245,254);
-$palette-light-blue-100: rgb(179,229,252);
-$palette-light-blue-200: rgb(129,212,250);
-$palette-light-blue-300: rgb(79,195,247);
-$palette-light-blue-400: rgb(41,182,246);
-$palette-light-blue-500: rgb(3,169,244);
-$palette-light-blue-600: rgb(3,155,229);
-$palette-light-blue-700: rgb(2,136,209);
-$palette-light-blue-800: rgb(2,119,189);
-$palette-light-blue-900: rgb(1,87,155);
-$palette-light-blue-a100: rgb(128,216,255);
-$palette-light-blue-a200: rgb(64,196,255);
-$palette-light-blue-a400: rgb(0,176,255);
-$palette-light-blue-a700: rgb(0,145,234);
-
-// Cyan
-$palette-cyan-50: rgb(224,247,250);
-$palette-cyan-100: rgb(178,235,242);
-$palette-cyan-200: rgb(128,222,234);
-$palette-cyan-300: rgb(77,208,225);
-$palette-cyan-400: rgb(38,198,218);
-$palette-cyan-500: rgb(0,188,212);
-$palette-cyan-600: rgb(0,172,193);
-$palette-cyan-700: rgb(0,151,167);
-$palette-cyan-800: rgb(0,131,143);
-$palette-cyan-900: rgb(0,96,100);
-$palette-cyan-a100: rgb(132,255,255);
-$palette-cyan-a200: rgb(24,255,255);
-$palette-cyan-a400: rgb(0,229,255);
-$palette-cyan-a700: rgb(0,184,212);
-
-// Teal
-$palette-teal-50: rgb(224,242,241);
-$palette-teal-100: rgb(178,223,219);
-$palette-teal-200: rgb(128,203,196);
-$palette-teal-300: rgb(77,182,172);
-$palette-teal-400: rgb(38,166,154);
-$palette-teal-500: rgb(0,150,136);
-$palette-teal-600: rgb(0,137,123);
-$palette-teal-700: rgb(0,121,107);
-$palette-teal-800: rgb(0,105,92);
-$palette-teal-900: rgb(0,77,64);
-$palette-teal-a100: rgb(167,255,235);
-$palette-teal-a200: rgb(100,255,218);
-$palette-teal-a400: rgb(29,233,182);
-$palette-teal-a700: rgb(0,191,165);
-
-// Green
-$palette-green-50: rgb(232,245,233);
-$palette-green-100: rgb(200,230,201);
-$palette-green-200: rgb(165,214,167);
-$palette-green-300: rgb(129,199,132);
-$palette-green-400: rgb(102,187,106);
-$palette-green-500: rgb(76,175,80);
-$palette-green-600: rgb(67,160,71);
-$palette-green-700: rgb(56,142,60);
-$palette-green-800: rgb(46,125,50);
-$palette-green-900: rgb(27,94,32);
-$palette-green-a100: rgb(185,246,202);
-$palette-green-a200: rgb(105,240,174);
-$palette-green-a400: rgb(0,230,118);
-$palette-green-a700: rgb(0,200,83);
-
-// Green
-$palette-light-green-50: rgb(241,248,233);
-$palette-light-green-100: rgb(220,237,200);
-$palette-light-green-200: rgb(197,225,165);
-$palette-light-green-300: rgb(174,213,129);
-$palette-light-green-400: rgb(156,204,101);
-$palette-light-green-500: rgb(139,195,74);
-$palette-light-green-600: rgb(124,179,66);
-$palette-light-green-700: rgb(104,159,56);
-$palette-light-green-800: rgb(85,139,47);
-$palette-light-green-900: rgb(51,105,30);
-$palette-light-green-a100: rgb(204,255,144);
-$palette-light-green-a200: rgb(178,255,89);
-$palette-light-green-a400: rgb(118,255,3);
-$palette-light-green-a700: rgb(100,221,23);
-
-// Lime
-$palette-lime-50: rgb(249,251,231);
-$palette-lime-100: rgb(240,244,195);
-$palette-lime-200: rgb(230,238,156);
-$palette-lime-300: rgb(220,231,117);
-$palette-lime-400: rgb(212,225,87);
-$palette-lime-500: rgb(205,220,57);
-$palette-lime-600: rgb(192,202,51);
-$palette-lime-700: rgb(175,180,43);
-$palette-lime-800: rgb(158,157,36);
-$palette-lime-900: rgb(130,119,23);
-$palette-lime-a100: rgb(244,255,129);
-$palette-lime-a200: rgb(238,255,65);
-$palette-lime-a400: rgb(198,255,0);
-$palette-lime-a700: rgb(174,234,0);
-
-// Yellow
-$palette-yellow-50: rgb(255,253,231);
-$palette-yellow-100: rgb(255,249,196);
-$palette-yellow-200: rgb(255,245,157);
-$palette-yellow-300: rgb(255,241,118);
-$palette-yellow-400: rgb(255,238,88);
-$palette-yellow-500: rgb(255,235,59);
-$palette-yellow-600: rgb(253,216,53);
-$palette-yellow-700: rgb(251,192,45);
-$palette-yellow-800: rgb(249,168,37);
-$palette-yellow-900: rgb(245,127,23);
-$palette-yellow-a100: rgb(255,255,141);
-$palette-yellow-a200: rgb(255,255,0);
-$palette-yellow-a400: rgb(255,234,0);
-$palette-yellow-a700: rgb(255,214,0);
-
-// Amber
-$palette-amber-50: rgb(255,248,225);
-$palette-amber-100: rgb(255,236,179);
-$palette-amber-200: rgb(255,224,130);
-$palette-amber-300: rgb(255,213,79);
-$palette-amber-400: rgb(255,202,40);
-$palette-amber-500: rgb(255,193,7);
-$palette-amber-600: rgb(255,179,0);
-$palette-amber-700: rgb(255,160,0);
-$palette-amber-800: rgb(255,143,0);
-$palette-amber-900: rgb(255,111,0);
-$palette-amber-a100: rgb(255,229,127);
-$palette-amber-a200: rgb(255,215,64);
-$palette-amber-a400: rgb(255,196,0);
-$palette-amber-a700: rgb(255,171,0);
-
-// Orange
-$palette-orange-50: rgb(255,243,224);
-$palette-orange-100: rgb(255,224,178);
-$palette-orange-200: rgb(255,204,128);
-$palette-orange-300: rgb(255,183,77);
-$palette-orange-400: rgb(255,167,38);
-$palette-orange-500: rgb(255,152,0);
-$palette-orange-600: rgb(251,140,0);
-$palette-orange-700: rgb(245,124,0);
-$palette-orange-800: rgb(239,108,0);
-$palette-orange-900: rgb(230,81,0);
-$palette-orange-a100: rgb(255,209,128);
-$palette-orange-a200: rgb(255,171,64);
-$palette-orange-a400: rgb(255,145,0);
-$palette-orange-a700: rgb(255,109,0);
-
-// Deep Orange
-$palette-deep-orange-50: rgb(251,233,231);
-$palette-deep-orange-100: rgb(255,204,188);
-$palette-deep-orange-200: rgb(255,171,145);
-$palette-deep-orange-300: rgb(255,138,101);
-$palette-deep-orange-400: rgb(255,112,67);
-$palette-deep-orange-500: rgb(255,87,34);
-$palette-deep-orange-600: rgb(244,81,30);
-$palette-deep-orange-700: rgb(230,74,25);
-$palette-deep-orange-800: rgb(216,67,21);
-$palette-deep-orange-900: rgb(191,54,12);
-$palette-deep-orange-a100: rgb(255,158,128);
-$palette-deep-orange-a200: rgb(255,110,64);
-$palette-deep-orange-a400: rgb(255,61,0);
-$palette-deep-orange-a700: rgb(221,44,0);
-
-// Brown
-$palette-brown-50: rgb(239,235,233);
-$palette-brown-100: rgb(215,204,200);
-$palette-brown-200: rgb(188,170,164);
-$palette-brown-300: rgb(161,136,127);
-$palette-brown-400: rgb(141,110,99);
-$palette-brown-500: rgb(121,85,72);
-$palette-brown-600: rgb(109,76,65);
-$palette-brown-700: rgb(93,64,55);
-$palette-brown-800: rgb(78,52,46);
-$palette-brown-900: rgb(62,39,35);
-
-// Grey
-$palette-grey-50: rgb(250,250,250);
-$palette-grey-100: rgb(245,245,245);
-$palette-grey-200: rgb(238,238,238);
-$palette-grey-300: rgb(224,224,224);
-$palette-grey-400: rgb(189,189,189);
-$palette-grey-500: rgb(158,158,158);
-$palette-grey-600: rgb(117,117,117);
-$palette-grey-700: rgb(97,97,97);
-$palette-grey-800: rgb(66,66,66);
-$palette-grey-900: rgb(33,33,33);
-
-// Blue Grey
-$palette-blue-grey-50: rgb(236,239,241);
-$palette-blue-grey-100: rgb(207,216,220);
-$palette-blue-grey-200: rgb(176,190,197);
-$palette-blue-grey-300: rgb(144,164,174);
-$palette-blue-grey-400: rgb(120,144,156);
-$palette-blue-grey-500: rgb(96,125,139);
-$palette-blue-grey-600: rgb(84,110,122);
-$palette-blue-grey-700: rgb(69,90,100);
-$palette-blue-grey-800: rgb(55,71,79);
-$palette-blue-grey-900: rgb(38,50,56);
-
-$color-black: rgb(0,0,0);
-$color-white: rgb(255,255,255);
-
-//-- The two possible colors for overlayed text.
-$styleguide-generate-template: false !default;
-$color-dark-contrast: $color-white !default;
-$color-light-contrast: $color-black !default;
diff --git a/components/_globals.scss b/components/_globals.scss
deleted file mode 100644
index 73edd5f9..00000000
--- a/components/_globals.scss
+++ /dev/null
@@ -1,81 +0,0 @@
-//-- Color configuration
-$color-divider: $palette-grey-200 !default;
-$color-background: $color-white !default;
-$color-text: $palette-grey-900 !default;
-$color-text-secondary: $palette-grey-600 !default;
-
-$color-primary: $palette-indigo-500 !default;
-$color-primary-dark: $palette-indigo-700 !default;
-$color-accent: $palette-pink-a200 !default;
-$color-accent-dark: $palette-pink-700 !default;
-$color-primary-contrast: $color-dark-contrast !default;
-$color-accent-contrast: $color-dark-contrast !default;
-
-//-- Sizing
-$unit: 1rem !default;
-
-// -- Fonts
-$preferred-font: "Roboto", "Helvetica", "Arial", sans-serif !default;
-$font-size: 1.6 * $unit !default;
-$font-size-tiny: 1.2 * $unit !default;
-$font-size-small: 1.4 * $unit !default;
-$font-size-normal: $font-size !default;
-$font-size-big: 1.8 * $unit !default;
-$font-weight-thin: 300 !default;
-$font-weight-normal: 400 !default;
-$font-weight-semi-bold: 500 !default;
-$font-weight-bold: 700 !default;
-
-//-- Shadows
-$shadow-key-umbra-opacity: 0.2 !default;
-$shadow-key-penumbra-opacity: 0.14 !default;
-$shadow-ambient-shadow-opacity: 0.12 !default;
-
-//-- Depth Shadows
-$zdepth-shadow-1: 0 1px 6px rgba(0,0,0,.12), 0 1px 4px rgba(0,0,0,.24);
-$zdepth-shadow-2: 0 3px 10px rgba(0,0,0,.16), 0 3px 10px rgba(0,0,0,.23);
-$zdepth-shadow-3: 0 10px 30px rgba(0,0,0,.19), 0 6px 10px rgba(0,0,0,.23);
-$zdepth-shadow-4: 0 14px 45px rgba(0,0,0,.25), 0 10px 18px rgba(0,0,0,.22);
-$zdepth-shadow-5: 0 19px 60px rgba(0,0,0,.3), 0 15px 20px rgba(0,0,0,.22);
-
-//-- Animation
-$animation-duration: .35s;
-$animation-delay: $animation-duration / 5;
-$animation-curve-fast-out-slow-in: cubic-bezier(0.4, 0, 0.2, 1) !default;
-$animation-curve-linear-out-slow-in: cubic-bezier(0, 0, 0.2, 1) !default;
-$animation-curve-fast-out-linear-in: cubic-bezier(0.4, 0, 1, 1) !default;
-$animation-curve-default: $animation-curve-fast-out-slow-in !default;
-
-//-- Indexes
-$z-index-highest: 300 !default;
-$z-index-higher: 200 !default;
-$z-index-high: 100 !default;
-$z-index-normal: 1 !default;
-$z-index-low: -100 !default;
-$z-index-lower: -200 !default;
-
-//-- Breakpoints
-// height of app bar
-// https://material.google.com/layout/metrics-keylines.html#metrics-keylines-keylines-spacing
-$standard-increment-mobile: (5.6 * $unit) !default;
-$standard-increment-desktop: (6.4 * $unit) !default;
-
-// https://material.google.com/layout/metrics-keylines.html#metrics-keylines-baseline-grids
-$baseline-grid: (0.8 * $unit) !default;
-$layout-gutter-width-sm: ($baseline-grid * 2) !default;
-$layout-gutter-width: ($baseline-grid * 3) !default;
-
-// https://material.google.com/layout/responsive-ui.html#responsive-ui-breakpoints
-// 4 columns
-$layout-breakpoint-xxs: 480px !default;
-// 8 columns
-$layout-breakpoint-xs: 600px !default;
-// 12 columns
-$layout-breakpoint-sm-tablet: 720px !default;
-$layout-breakpoint-sm: 840px !default;
-$layout-breakpoint-md: 960px !default;
-$layout-breakpoint-lg-tablet: 1024px !default;
-$layout-breakpoint-lg: 1280px !default;
-$layout-breakpoint-xl: 1440px !default;
-$layout-breakpoint-xxl: 1600px !default;
-$layout-breakpoint-xxxl: 1920px !default;
diff --git a/components/_mixins.scss b/components/_mixins.scss
deleted file mode 100644
index 40490c70..00000000
--- a/components/_mixins.scss
+++ /dev/null
@@ -1,260 +0,0 @@
-// scss-lint:disable VendorPrefix
-@mixin typo-preferred-font($use-preferred: true) {
- @if $use-preferred {
- font-family: $preferred-font;
- }
-}
-
-@mixin typo-display-4($color-contrast: false, $use-preferred: true) {
- @include typo-preferred-font($use-preferred);
- font-size: $unit * 11.2;
- font-weight: 300;
- line-height: 1;
- letter-spacing: -.04em;
-
- @if $color-contrast {
- opacity: .54;
- }
-}
-
-@mixin typo-display-3($color-contrast: false, $use-preferred: true) {
- @include typo-preferred-font($use-preferred);
- font-size: $unit * 5.6;
- font-weight: 400;
- line-height: 1.35;
- letter-spacing: -.02em;
-
- @if $color-contrast {
- opacity: .54;
- }
-}
-
-@mixin typo-display-2($color-contrast: false, $use-preferred: true) {
- @include typo-preferred-font($use-preferred);
- font-size: $unit * 4.5;
- font-weight: 400;
- line-height: $unit * 4.8;
-
- @if $color-contrast {
- opacity: .54;
- }
-}
-
-@mixin typo-display-1($color-contrast: false, $use-preferred: true) {
- @include typo-preferred-font($use-preferred);
- font-size: $unit * 3.4;
- font-weight: 400;
- line-height: $unit * 4;
-
- @if $color-contrast {
- opacity: .54;
- }
-}
-
-@mixin typo-headline($color-contrast: false, $use-preferred: true) {
- @include typo-preferred-font($use-preferred);
- font-size: $unit * 2.4;
- font-weight: 400;
- line-height: $unit * 3.2;
- -moz-osx-font-smoothing: grayscale;
-
- @if $color-contrast {
- opacity: .87;
- }
-}
-
-@mixin typo-title($color-contrast: false, $use-preferred: true) {
- @include typo-preferred-font($use-preferred);
- font-size: $unit * 2;
- font-weight: 500;
- line-height: 1;
- letter-spacing: .02em;
-
- @if $color-contrast {
- opacity: .87;
- }
-}
-
-@mixin typo-subhead($color-contrast: false, $use-preferred: true) {
- @include typo-preferred-font($use-preferred);
- font-size: $unit * 1.6;
- font-weight: 400;
- line-height: $unit * 2.4;
- letter-spacing: .04em;
-
- @if $color-contrast {
- opacity: .87;
- }
-}
-
-@mixin typo-subhead-2($color-contrast: false, $use-preferred: true) {
- @include typo-preferred-font($use-preferred);
- font-size: $unit * 1.6;
- font-weight: 400;
- line-height: $unit * 2.8;
- letter-spacing: .04em;
-
- @if $color-contrast {
- opacity: .87;
- }
-}
-
-@mixin typo-body-2($color-contrast: false, $use-preferred: false) {
- @include typo-preferred-font($use-preferred);
- font-size: $unit * 1.4;
- line-height: $unit * 2.4;
- letter-spacing: 0;
-
- @if $use-preferred {
- font-weight: 500;
- } @else {
- font-weight: bold;
- }
-
- @if $color-contrast {
- opacity: .87;
- }
-}
-
-@mixin typo-body-1($color-contrast: false, $use-preferred: false) {
- @include typo-preferred-font($use-preferred);
- font-size: $unit * 1.4;
- font-weight: 400;
- line-height: $unit * 2.4;
- letter-spacing: 0;
-
- @if $color-contrast {
- opacity: .87;
- }
-}
-
-@mixin typo-caption($color-contrast: false, $use-preferred: false) {
- @include typo-preferred-font($use-preferred);
- font-size: $unit * 1.2;
- font-weight: 400;
- line-height: 1;
- letter-spacing: 0;
-
- @if $color-contrast {
- opacity: .54;
- }
-}
-
-@mixin typo-blockquote($color-contrast: false, $use-preferred: true) {
- @include typo-preferred-font($use-preferred);
- position: relative;
- font-size: $unit * 2.4;
- font-style: italic;
- font-weight: 300;
- line-height: 1.35;
- letter-spacing: .08em;
-
- &:before {
- position: absolute;
- left: -.5em;
- content: "“";
- }
-
- &:after {
- margin-left: -.05em;
- content: "”";
- }
-
- @if $color-contrast {
- opacity: .54;
- }
-}
-
-@mixin typo-menu($color-contrast: false, $use-preferred: true) {
- @include typo-preferred-font($use-preferred);
- font-size: $unit * 1.4;
- font-weight: 500;
- line-height: 1;
- letter-spacing: 0;
-
- @if $color-contrast {
- opacity: .87;
- }
-}
-
-@mixin typo-button($color-contrast: false, $use-preferred: true) {
- @include typo-preferred-font($use-preferred);
- font-size: $unit * 1.4;
- font-weight: 500;
- line-height: 1;
- text-transform: uppercase;
- letter-spacing: 0;
-
- @if $color-contrast {
- opacity: .87;
- }
-}
-
-//-- Shadows
-@mixin focus-shadow() {
- box-shadow: 0 0 8px rgba(0, 0, 0, .18), 0 8px 16px rgba(0, 0, 0, .36);
-}
-
-@mixin shadow-2dp() {
- box-shadow: 0 2px 2px 0 rgba(0, 0, 0, $shadow-key-penumbra-opacity),
- 0 3px 1px -2px rgba(0, 0, 0, $shadow-key-umbra-opacity),
- 0 1px 5px 0 rgba(0, 0, 0, $shadow-ambient-shadow-opacity);
-}
-
-@mixin shadow-3dp() {
- box-shadow: 0 3px 4px 0 rgba(0, 0, 0, $shadow-key-penumbra-opacity),
- 0 3px 3px -2px rgba(0, 0, 0, $shadow-key-umbra-opacity),
- 0 1px 8px 0 rgba(0, 0, 0, $shadow-ambient-shadow-opacity);
-}
-
-@mixin shadow-4dp() {
- box-shadow: 0 4px 5px 0 rgba(0, 0, 0, $shadow-key-penumbra-opacity),
- 0 1px 10px 0 rgba(0, 0, 0, $shadow-ambient-shadow-opacity),
- 0 2px 4px -1px rgba(0, 0, 0, $shadow-key-umbra-opacity);
-}
-
-@mixin shadow-6dp() {
- box-shadow: 0 6px 10px 0 rgba(0, 0, 0, $shadow-key-penumbra-opacity),
- 0 1px 18px 0 rgba(0, 0, 0, $shadow-ambient-shadow-opacity),
- 0 3px 5px -1px rgba(0, 0, 0, $shadow-key-umbra-opacity);
-}
-
-@mixin shadow-8dp() {
- box-shadow: 0 8px 10px 1px rgba(0, 0, 0, $shadow-key-penumbra-opacity),
- 0 3px 14px 2px rgba(0, 0, 0, $shadow-ambient-shadow-opacity),
- 0 5px 5px -3px rgba(0, 0, 0, $shadow-key-umbra-opacity);
-}
-
-@mixin shadow-16dp() {
- box-shadow: 0 16px 24px 2px rgba(0, 0, 0, $shadow-key-penumbra-opacity),
- 0 6px 30px 5px rgba(0, 0, 0, $shadow-ambient-shadow-opacity),
- 0 8px 10px -5px rgba(0, 0, 0, $shadow-key-umbra-opacity);
-}
-
-//-- Animations
-@mixin material-animation-fast-out-slow-in($duration: .2s) {
- transition-timing-function: $animation-curve-fast-out-slow-in;
- transition-duration: $duration;
-}
-
-@mixin material-animation-linear-out-slow-in($duration: .2s) {
- transition-timing-function: $animation-curve-linear-out-slow-in;
- transition-duration: $duration;
-}
-
-@mixin material-animation-fast-out-linear-in($duration: .2s) {
- transition-timing-function: $animation-curve-fast-out-linear-in;
- transition-duration: $duration;
-}
-
-@mixin material-animation-default($duration: .2s) {
- transition-timing-function: $animation-curve-default;
- transition-duration: $duration;
-}
-
-@mixin no-webkit-scrollbar {
- &::-webkit-scrollbar {
- width: 0;
- height: 0;
- }
-}
diff --git a/components/animations/index.js b/components/animations/index.js
deleted file mode 100644
index 3ab27eca..00000000
--- a/components/animations/index.js
+++ /dev/null
@@ -1,4 +0,0 @@
-export SlideLeft from './slide-left.scss';
-export SlideRight from './slide-right.scss';
-export ZoomIn from './zoom-in.scss';
-export ZoomOut from './zoom-out.scss';
diff --git a/components/animations/slide-left.scss b/components/animations/slide-left.scss
deleted file mode 100644
index aba03995..00000000
--- a/components/animations/slide-left.scss
+++ /dev/null
@@ -1,26 +0,0 @@
-.enter, .leave {
- position: absolute;
- transition-timing-function: ease-in-out;
- transition-duration: .35s;
- transition-property: transform, opacity;
-}
-
-.enter {
- opacity: 0;
- transform: translate3d(-100%, 0, 0);
-
- &.enterActive {
- opacity: 1;
- transform: translate3d(0, 0, 0);
- }
-}
-
-.leave {
- opacity: 1;
- transform: translate3d(0, 0, 0);
-
- &.leaveActive {
- opacity: 0;
- transform: translate3d(100%, 0, 0);
- }
-}
diff --git a/components/animations/slide-right.scss b/components/animations/slide-right.scss
deleted file mode 100644
index 95d0e15d..00000000
--- a/components/animations/slide-right.scss
+++ /dev/null
@@ -1,29 +0,0 @@
-.enter, .leave {
- position: absolute;
-}
-
-.enterActive, .leaveActive {
- transition-timing-function: ease-in-out;
- transition-duration: 350ms;
- transition-property: transform, opacity;
-}
-
-.enter {
- opacity: 0;
- transform: translateX(100%);
-
- &.enterActive {
- opacity: 1;
- transform: translateX(0);
- }
-}
-
-.leave {
- opacity: 1;
- transform: translateX(0);
-
- &.leaveActive {
- opacity: 0;
- transform: translateX(-100%);
- }
-}
diff --git a/components/animations/zoom-in.scss b/components/animations/zoom-in.scss
deleted file mode 100644
index d752e940..00000000
--- a/components/animations/zoom-in.scss
+++ /dev/null
@@ -1,33 +0,0 @@
-@import "../colors";
-@import "../globals";
-@import "../mixins";
-
-.enter, .leave {
- position: absolute;
-}
-
-.enterActive, .leaveActive {
- transition: transform, opacity;
- transition-timing-function: $animation-curve-fast-out-slow-in;
- transition-duration: 500ms;
-}
-
-.enter {
- opacity: 0;
- transform: scale(0.85);
-
- &.enterActive {
- opacity: 1;
- transform: scale(1);
- }
-}
-
-.leave {
- opacity: 1;
- transform: scale(1);
-
- &.leaveActive {
- opacity: 0;
- transform: scale(1.25);
- }
-}
diff --git a/components/animations/zoom-out.scss b/components/animations/zoom-out.scss
deleted file mode 100644
index cf1500fc..00000000
--- a/components/animations/zoom-out.scss
+++ /dev/null
@@ -1,33 +0,0 @@
-@import "../colors";
-@import "../globals";
-@import "../mixins";
-
-.enter, .leave {
- position: absolute;
-}
-
-.enterActive, .leaveActive {
- transition: transform, opacity;
- transition-timing-function: $animation-curve-fast-out-slow-in;
- transition-duration: 500ms;
-}
-
-.enter {
- opacity: 0;
- transform: scale(1.25);
-
- &.enterActive {
- opacity: 1;
- transform: scale(1);
- }
-}
-
-.leave {
- opacity: 1;
- transform: scale(1);
-
- &.leaveActive {
- opacity: 0;
- transform: scale(0.85);
- }
-}
diff --git a/components/app_bar/AppBar.js b/components/app_bar/AppBar.js
index 60da12b9..4146158c 100644
--- a/components/app_bar/AppBar.js
+++ b/components/app_bar/AppBar.js
@@ -24,6 +24,7 @@ const factory = (IconButton) => {
scrollHide: PropTypes.bool,
theme: PropTypes.shape({
appBar: PropTypes.string,
+ inner: PropTypes.string,
fixed: PropTypes.string,
flat: PropTypes.string,
leftIcon: PropTypes.string,
@@ -97,20 +98,22 @@ const factory = (IconButton) => {
data-react-toolbox='app-bar'
ref={node => {this.rootNode = node;}}
>
- {leftIcon &&
- }
- {title &&
{title} }
- {children}
- {rightIcon &&
- }
+
+ {leftIcon &&
+ }
+ {title &&
{title} }
+ {children}
+ {rightIcon &&
+ }
+
);
}
diff --git a/components/app_bar/_config.scss b/components/app_bar/_config.scss
deleted file mode 100644
index 5c76b618..00000000
--- a/components/app_bar/_config.scss
+++ /dev/null
@@ -1,8 +0,0 @@
-$appbar-color: $color-primary-dark !default;
-$appbar-contrast: $color-primary-contrast !default;
-$appbar-title-total-distance: 8 * $unit !default;
-$appbar-height: 6.4 * $unit !default;
-$appbar-height-m-portrait: 5.6 * $unit !default;
-$appbar-height-m-landscape: 4.8 * $unit !default;
-$appbar-h-padding: 2.4 * $unit !default;
-$appbar-title-distance: $appbar-title-total-distance - $appbar-h-padding !default;
diff --git a/components/app_bar/config.css b/components/app_bar/config.css
new file mode 100644
index 00000000..ca3ba1b4
--- /dev/null
+++ b/components/app_bar/config.css
@@ -0,0 +1,10 @@
+:root {
+ --appbar-color: var(--color-primary-dark);
+ --appbar-contrast: var(--color-primary-contrast);
+ --appbar-title-total-distance: calc(8 * var(--unit));
+ --appbar-height: calc(6.4 * var(--unit));
+ --appbar-height-m-portrait: calc(5.6 * var(--unit));
+ --appbar-height-m-landscape: calc(4.8 * var(--unit));
+ --appbar-h-padding: calc(2.4 * var(--unit));
+ --appbar-title-distance: calc(var(--appbar-title-total-distance) - var(--appbar-h-padding));
+}
diff --git a/components/app_bar/index.js b/components/app_bar/index.js
index ff38bf7c..83d10d8e 100644
--- a/components/app_bar/index.js
+++ b/components/app_bar/index.js
@@ -2,7 +2,7 @@ import { themr } from 'react-css-themr';
import { APP_BAR } from '../identifiers.js';
import { appBarFactory } from './AppBar.js';
import { IconButton } from '../button';
-import theme from './theme.scss';
+import theme from './theme.css';
const AppBar = appBarFactory(IconButton);
const ThemedAppBar = themr(APP_BAR, theme)(AppBar);
diff --git a/components/app_bar/readme.md b/components/app_bar/readme.md
index f68ecf12..3f1b3f92 100644
--- a/components/app_bar/readme.md
+++ b/components/app_bar/readme.md
@@ -50,6 +50,7 @@ The `AppBar` component provides properties for the common use cases of `title`,
| `appBar` | Used for the component root element.|
| `fixed` | Added to the root element when the app bar is fixed.|
| `flat` | Added to the root element when the app bar is flat.|
+| `inner` | Added to a wrapper to the component main content.|
| `title` | Added to the title element of the app bar.|
| `leftIcon` | Added to the left icon element when the app bar.|
| `rightIcon` | Added to the right icon element when the app bar.|
diff --git a/components/app_bar/theme.css b/components/app_bar/theme.css
new file mode 100644
index 00000000..4dfcf3ab
--- /dev/null
+++ b/components/app_bar/theme.css
@@ -0,0 +1,76 @@
+@import '../colors.css';
+@import '../media.css';
+@import '../variables.css';
+@import './config.css';
+
+.appBar {
+ background: var(--appbar-color);
+ color: var(--appbar-contrast);
+ composes: reset from '../helpers.css';
+ font-family: var(--preferred-font);
+ height: var(--appbar-height);
+ padding: 0 var(--appbar-h-padding);
+ transition-duration: 0.5s;
+ transition-property: transform;
+ transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
+
+ &.scrollHide {
+ transform: translateY(-100%);
+ }
+
+ &:not(.flat) {
+ box-shadow: var(--shadow-4p);
+ z-index: var(--z-index-high);
+ }
+
+ &.fixed {
+ left: 0;
+ position: fixed;
+ right: 0;
+ top: 0;
+ z-index: var(--z-index-highest);
+ }
+
+ & .inner {
+ align-items: center;
+ display: flex;
+ height: 100%;
+ position: relative;
+ width: 100%;
+ }
+
+ & a {
+ color: var(--appbar-contrast);
+ }
+
+ @media screen and (--xxs-viewport) and (--portrait) {
+ height: var(--appbar-height-m-portrait);
+ }
+
+ @media screen and (--xs-viewport) and (--landscape) {
+ height: var(--appbar-height-m-landscape);
+ }
+}
+
+.title {
+ flex-grow: 1;
+ font-size: calc(1.8 * var(--unit));
+ font-weight: bold;
+ overflow-x: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+
+ & > small {
+ font-size: calc(1.8 * var(--unit));
+ font-weight: normal;
+ }
+}
+
+.leftIcon {
+ margin-left: calc(-1.2 * var(--unit));
+}
+
+.rightIcon {
+ margin-left: auto;
+ margin-right: calc(-1.2 * var(--unit));
+}
diff --git a/components/app_bar/theme.scss b/components/app_bar/theme.scss
deleted file mode 100644
index 04584eb6..00000000
--- a/components/app_bar/theme.scss
+++ /dev/null
@@ -1,65 +0,0 @@
-@import "../colors";
-@import "../globals";
-@import "../mixins";
-@import "./config";
-
-.appBar {
- display: flex;
- height: $appbar-height;
- align-items: center;
- padding: 0 $appbar-h-padding;
- color: $appbar-contrast;
- background: $appbar-color;
-
- @media screen and (max-width: $layout-breakpoint-xxs) and (orientation: portrait) {
- height: $appbar-height-m-portrait;
- }
-
- @media screen and (max-width: $layout-breakpoint-xs) and (orientation: landscape) {
- height: $appbar-height-m-landscape;
- }
-
- &:not(.flat) {
- z-index: $z-index-high;
- box-shadow: 0 2px 5px rgba(0,0,0,.26);
- }
-
- &.fixed {
- position: fixed;
- top: 0;
- right: 0;
- left: 0;
- z-index: $z-index-highest;
- }
-
- a {
- color: $appbar-contrast;
- }
-
- .title {
- flex-grow: 1;
- font-size: 1.8 * $unit;
- font-weight: bold;
- > small {
- font-size: 1.8 * $unit;
- font-weight: normal;
- }
- }
-
- .leftIcon {
- margin-left: -1.2 * $unit;
- }
-
- .rightIcon {
- margin-right: -1.2 * $unit;
- margin-left: auto;
- }
-
- transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
- transition-duration: .5s;
- transition-property: transform;
-
- &.scrollHide {
- transform: translateY(-100%);
- }
-}
diff --git a/components/autocomplete/_config.scss b/components/autocomplete/_config.scss
deleted file mode 100644
index e0280558..00000000
--- a/components/autocomplete/_config.scss
+++ /dev/null
@@ -1,7 +0,0 @@
-$autocomplete-color-primary-contrast: $color-primary-contrast !default;
-$autocomplete-color-primary: $color-primary !default;
-$autocomplete-overflow-max-height: 45vh !default;
-$autocomplete-suggestion-active-background: $palette-grey-200 !default;
-$autocomplete-suggestion-padding: $unit !default;
-$autocomplete-suggestions-background: $color-white !default;
-$autocomplete-value-margin: $unit * .25 $unit * .5 $unit * .25 0 !default;
diff --git a/components/autocomplete/config.css b/components/autocomplete/config.css
new file mode 100644
index 00000000..2f98ac0d
--- /dev/null
+++ b/components/autocomplete/config.css
@@ -0,0 +1,10 @@
+:root {
+ --autocomplete-border-size: calc(var(--input-field-height) / 7);
+ --autocomplete-color-primary-contrast: var(--color-primary-contrast);
+ --autocomplete-color-primary: var(--color-primary);
+ --autocomplete-overflow-max-height: 45vh;
+ --autocomplete-suggestion-active-background: var(--palette-grey-200);
+ --autocomplete-suggestion-padding: var(--unit);
+ --autocomplete-suggestions-background: var(--color-white);
+ --autocomplete-value-margin: calc(var(--unit) * 0.25) calc(var(--unit) * 0.5) calc(var(--unit) * 0.25) 0;
+}
diff --git a/components/autocomplete/index.js b/components/autocomplete/index.js
index fce2d72d..1f0842ed 100644
--- a/components/autocomplete/index.js
+++ b/components/autocomplete/index.js
@@ -3,7 +3,7 @@ import { themr } from 'react-css-themr';
import { autocompleteFactory } from './Autocomplete.js';
import Chip from '../chip';
import Input from '../input';
-import theme from './theme.scss';
+import theme from './theme.css';
const Autocomplete = autocompleteFactory(Chip, Input);
const ThemedAutocomplete = themr(AUTOCOMPLETE, theme)(Autocomplete);
diff --git a/components/autocomplete/theme.css b/components/autocomplete/theme.css
new file mode 100644
index 00000000..4c4ef2be
--- /dev/null
+++ b/components/autocomplete/theme.css
@@ -0,0 +1,87 @@
+@import '../colors.css';
+@import '../variables.css';
+@import '../input/config.css';
+@import './config.css';
+
+.autocomplete {
+ composes: reset from '../helpers.css';
+ padding: var(--unit) 0;
+ position: relative;
+
+ &.focus {
+ & .suggestions {
+ box-shadow: var(--zdepth-shadow-1);
+ max-height: var(--autocomplete-overflow-max-height);
+ visibility: visible;
+ }
+ }
+}
+
+.values {
+ flex-direction: row;
+ flex-wrap: wrap;
+ list-style: none;
+ margin: 0;
+ padding: 0 0 calc(var(--unit) / 2) 0;
+}
+
+.value {
+ margin: var(--autocomplete-value-margin);
+}
+
+.suggestions {
+ background-color: var(--autocomplete-suggestions-background);
+ list-style: none;
+ max-height: 0;
+ overflow-x: hidden;
+ overflow-y: auto;
+ padding: 0;
+ position: absolute;
+ transition-duration: var(--animation-duration);
+ transition-property: max-height, box-shadow;
+ transition-timing-function: var(--animation-curve-default);
+ visibility: hidden;
+ width: 100%;
+ z-index: var(--z-index-high);
+
+ &:not(.up) {
+ margin-top: calc(-1 * var(--input-padding));
+ }
+
+ &.up {
+ bottom: 0;
+ }
+
+ &::-webkit-scrollbar {
+ height: 0;
+ width: 0;
+ }
+}
+
+.suggestion {
+ cursor: pointer;
+ font-size: var(--input-field-font-size);
+ padding: var(--autocomplete-suggestion-padding);
+
+ &.active {
+ background-color: var(--autocomplete-suggestion-active-background);
+ }
+}
+
+.input {
+ position: relative;
+
+ &::after {
+ border-left: var(--autocomplete-border-size) solid transparent;
+ border-right: var(--autocomplete-border-size) solid transparent;
+ border-top: var(--autocomplete-border-size) solid var(--input-text-bottom-border-color);
+ content: '';
+ height: 0;
+ pointer-events: none;
+ position: absolute;
+ right: var(--input-chevron-offset);
+ top: 50%;
+ transition: transform var(--animation-duration) var(--animation-curve-default);
+ width: 0;
+ }
+}
diff --git a/components/autocomplete/theme.scss b/components/autocomplete/theme.scss
deleted file mode 100644
index f1213657..00000000
--- a/components/autocomplete/theme.scss
+++ /dev/null
@@ -1,76 +0,0 @@
-@import "../colors";
-@import "../globals";
-@import "../mixins";
-@import "./config";
-@import "../input/config";
-
-.autocomplete {
- position: relative;
- padding: $unit 0;
- &.focus {
- .suggestions {
- max-height: $autocomplete-overflow-max-height;
- visibility: visible;
- box-shadow: $zdepth-shadow-1;
- }
- }
-}
-
-.values {
- flex-direction: row;
- flex-wrap: wrap;
- padding-bottom: $unit / 2;
-}
-
-.value {
- margin: $autocomplete-value-margin;
-}
-
-.suggestions {
- @include no-webkit-scrollbar;
- position: absolute;
- z-index: $z-index-high;
- width: 100%;
- max-height: 0;
- overflow-x: hidden;
- overflow-y: auto;
- visibility: hidden;
- background-color: $autocomplete-suggestions-background;
- transition-timing-function: $animation-curve-default;
- transition-duration: $animation-duration;
- transition-property: max-height, box-shadow;
- &:not(.up) {
- margin-top: - $input-padding;
- }
- &.up {
- bottom: 0;
- }
-}
-
-.suggestion {
- padding: $autocomplete-suggestion-padding;
- font-size: $input-field-font-size;
- cursor: pointer;
- &.active {
- background-color: $autocomplete-suggestion-active-background;
- }
-}
-
-.input {
- position: relative;
- &:after {
- $size: ($input-field-height / 7);
- $border: $size solid transparent;
- position: absolute;
- top: 50%;
- right: $input-chevron-offset;
- width: 0;
- height: 0;
- pointer-events: none;
- content: "";
- border-top: $size solid $input-text-bottom-border-color;
- border-right: $border;
- border-left: $border;
- transition: transform $animation-duration $animation-curve-default;
- }
-}
diff --git a/components/avatar/_config.scss b/components/avatar/_config.scss
deleted file mode 100644
index a2922fb6..00000000
--- a/components/avatar/_config.scss
+++ /dev/null
@@ -1,4 +0,0 @@
-$avatar-color: $color-white !default;
-$avatar-background: $palette-grey-500 !default;
-$avatar-size: 4 * $unit !default;
-$avatar-font-size: 2.4 * $unit !default;
diff --git a/components/avatar/config.css b/components/avatar/config.css
new file mode 100644
index 00000000..453d1954
--- /dev/null
+++ b/components/avatar/config.css
@@ -0,0 +1,6 @@
+:root {
+ --avatar-color: var(--color-white);
+ --avatar-background: var(--palette-grey-500);
+ --avatar-size: calc(4 * var(--unit));
+ --avatar-font-size: calc(2.4 * var(--unit));
+}
diff --git a/components/avatar/index.js b/components/avatar/index.js
index 02ada447..6b2896bc 100644
--- a/components/avatar/index.js
+++ b/components/avatar/index.js
@@ -2,7 +2,7 @@ import { AVATAR } from '../identifiers.js';
import { themr } from 'react-css-themr';
import { avatarFactory } from './Avatar.js';
import FontIcon from '../font_icon/FontIcon.js';
-import theme from './theme.scss';
+import theme from './theme.css';
const Avatar = avatarFactory(FontIcon);
const ThemedAvatar = themr(AVATAR, theme)(Avatar);
diff --git a/components/avatar/theme.scss b/components/avatar/theme.css
similarity index 55%
rename from components/avatar/theme.scss
rename to components/avatar/theme.css
index 9514782a..a0116991 100644
--- a/components/avatar/theme.scss
+++ b/components/avatar/theme.css
@@ -1,44 +1,46 @@
-@import "../colors";
-@import "../globals";
-@import "../mixins";
-@import "./config";
+@import '../colors.css';
+@import '../variables.css';
+@import './config.css';
.avatar {
- position: relative;
+ background-color: var(--avatar-background);
+ border-radius: 50%;
+ color: var(--avatar-color);
+ composes: reset from '../helpers.css';
display: inline-block;
- width: $avatar-size;
- height: $avatar-size;
+ font-size: var(--avatar-font-size);
+ height: var(--avatar-size);
overflow: hidden;
- font-size: $avatar-font-size;
- color: $avatar-color;
+ position: relative;
text-align: center;
vertical-align: middle;
- background-color: $avatar-background;
- border-radius: 50%;
- > svg {
- width: 1em;
- height: $avatar-size;
+ width: var(--avatar-size);
+
+ & > svg {
fill: currentColor;
+ height: var(--avatar-size);
+ width: 1em;
}
- > img {
- max-width: 100%;
+
+ & > img {
height: auto;
+ max-width: 100%;
}
}
.image {
- position: absolute;
- display: block;
- width: 100%;
- height: 100%;
background-color: transparent;
background-position: center;
background-size: cover;
border-radius: 50%;
+ display: block;
+ height: 100%;
+ position: absolute;
+ width: 100%;
}
.letter {
display: block;
+ line-height: var(--avatar-size);
width: 100%;
- line-height: $avatar-size;
}
diff --git a/components/button/__test__/index.spec.js b/components/button/__test__/index.spec.js
index 01cb6ca6..e217195d 100644
--- a/components/button/__test__/index.spec.js
+++ b/components/button/__test__/index.spec.js
@@ -2,7 +2,7 @@ import expect from 'expect';
import React from 'react';
import ReactDOM from 'react-dom';
import TestUtils from 'react-addons-test-utils';
-import theme from '../theme.scss';
+import theme from '../theme.css';
import Button, { Button as RawButton } from '../Button';
const getRenderedClassName = (tree, Component) => {
diff --git a/components/button/_config.scss b/components/button/_config.scss
deleted file mode 100644
index 98aa2c24..00000000
--- a/components/button/_config.scss
+++ /dev/null
@@ -1,23 +0,0 @@
-$button-neutral-color: $color-white !default;
-$button-neutral-color-contrast: $palette-grey-900 !default;
-$button-neutral-color-hover: rgba($palette-grey-900, .2) !default;
-$button-primary-color-contrast: $color-primary-contrast !default;
-$button-primary-color-hover: rgba($color-primary, .2) !default;
-$button-primary-color: $color-primary !default;
-$button-accent-color-contrast: $color-primary-contrast !default;
-$button-accent-color-hover: rgba($color-accent, .2) !default;
-$button-accent-color: $color-accent !default;
-$button-disabled-text-color: rgba($color-black, 0.26) !default;
-$button-disabled-background-color: rgba($color-black, 0.12) !default;
-$button-disabled-text-color-inverse: rgba($color-white, 0.54) !default;
-$button-disabled-background-inverse: rgba($color-white, 0.08) !default;
-$button-border-radius: 0.2 * $unit !default;
-$button-floating-font-size: $unit * 2.4 !default;
-$button-floating-height: $unit * 5.6 !default;
-$button-floating-mini-height: $unit * 4 !default;
-$button-floating-mini-font-size: $button-floating-mini-height / 2.25 !default;
-$button-height: $unit * 3.6 !default;
-$button-squared-icon-margin: $unit * .6 !default;
-$button-squared-min-width: 9 * $unit !default;
-$button-squared-padding: 0 $unit * 1.2 !default;
-$button-toggle-font-size: $unit * 2 !default;
diff --git a/components/button/_mixins.scss b/components/button/_mixins.scss
deleted file mode 100644
index 305be037..00000000
--- a/components/button/_mixins.scss
+++ /dev/null
@@ -1,17 +0,0 @@
-@mixin btn-colors($name, $color, $background, $hover) {
- .#{$name}:not([disabled]) {
- &.raised, &.floating {
- color: $color;
- background: $background;
- }
- &.flat, &.toggle {
- color: $background;
- &:focus:not(:active) {
- background: $hover;
- }
- }
- &.flat:hover {
- background: $hover;
- }
- }
-}
diff --git a/components/button/config.css b/components/button/config.css
new file mode 100644
index 00000000..18865745
--- /dev/null
+++ b/components/button/config.css
@@ -0,0 +1,25 @@
+:root {
+ --button-border-radius: calc(0.2 * var(--unit));
+ --button-height: calc(3.6 * var(--unit));
+ --button-toggle-font-size: calc(2 * var(--unit));
+ --button-primary-color: var(--color-primary);
+ --button-primary-color-hover: color(var(--color-primary) a(20%));
+ --button-primary-color-contrast: var(--color-primary-contrast);
+ --button-accent-color-contrast: var(--color-primary-contrast);
+ --button-accent-color-hover: color(var(--color-accent) a(20%));
+ --button-accent-color: var(--color-accent);
+ --button-neutral-color: var(--color-white);
+ --button-neutral-color-contrast: var(--palette-grey-900);
+ --button-neutral-color-hover: color(var(--palette-grey-900) a(20%));
+ --button-floating-font-size: calc(2.4 * var(--unit));
+ --button-floating-height: calc(5.6 * var(--unit));
+ --button-floating-mini-height: calc(4 * var(--unit));
+ --button-floating-mini-font-size: calc(var(--button-floating-mini-height) / 2.25);
+ --button-disabled-text-color: color(var(--color-black) a(26%));
+ --button-disabled-background-color: color(var(--color-black) a(12%));
+ --button-disabled-text-color-inverse: color(var(--color-black) a(54%));
+ --button-disabled-background-inverse: color(var(--color-black) a(8%));
+ --button-squared-icon-margin: calc(0.6 * var(--unit));
+ --button-squared-min-width: calc(9 * var(--unit));
+ --button-squared-padding: 0 calc(1.2 * var(--unit));
+}
diff --git a/components/button/index.js b/components/button/index.js
index 126272d2..5baa93eb 100644
--- a/components/button/index.js
+++ b/components/button/index.js
@@ -5,7 +5,7 @@ import { browseButtonFactory } from './BrowseButton.js';
import { iconButtonFactory } from './IconButton.js';
import FontIcon from '../font_icon/FontIcon.js';
import themedRippleFactory from '../ripple';
-import theme from './theme.scss';
+import theme from './theme.css';
const Button = buttonFactory(themedRippleFactory({ centered: false }), FontIcon);
const IconButton = iconButtonFactory(themedRippleFactory({centered: true}), FontIcon);
diff --git a/components/button/theme.css b/components/button/theme.css
new file mode 100644
index 00000000..78b5402b
--- /dev/null
+++ b/components/button/theme.css
@@ -0,0 +1,258 @@
+@import '../colors.css';
+@import '../variables.css';
+@import './config.css';
+
+.button {
+ align-content: center;
+ align-items: center;
+ border: 0;
+ composes: reset from '../helpers.css';
+ cursor: pointer;
+ display: inline-block;
+ flex-direction: row;
+ font-size: calc(1.4 * var(--unit));
+ font-weight: 500;
+ height: var(--button-height);
+ justify-content: center;
+ letter-spacing: 0;
+ line-height: var(--button-height);
+ outline: none;
+ padding: 0;
+ position: relative;
+ text-align: center;
+ text-decoration: none;
+ text-transform: uppercase;
+ transition:
+ box-shadow 0.2s var(--animation-curve-fast-out-linear-in),
+ background-color 0.2s var(--animation-curve-default),
+ color 0.2s var(--animation-curve-default);
+ white-space: nowrap;
+
+ & > input {
+ height: 0.1px;
+ margin: 0;
+ opacity: 0;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ width: 0.1px;
+ z-index: 0;
+ }
+
+ &::-moz-focus-inner {
+ border: 0;
+ }
+
+ & > span:not([data-react-toolbox='tooltip']) {
+ display: inline-block;
+ line-height: var(--button-height);
+ vertical-align: top;
+ }
+
+ & > svg {
+ display: inline-block;
+ fill: currentColor;
+ font-size: 120%;
+ height: var(--button-height);
+ vertical-align: top;
+ width: 1em;
+ }
+
+ & > * {
+ pointer-events: none;
+ }
+
+ & > .rippleWrapper {
+ overflow: hidden;
+ }
+
+ &[disabled] {
+ color: var(--button-disabled-text-color);
+ cursor: auto;
+ pointer-events: none;
+ }
+}
+
+.squared {
+ border-radius: var(--button-border-radius);
+ min-width: var(--button-squared-min-width);
+ padding: var(--button-squared-padding);
+
+ & .icon {
+ font-size: 120%;
+ margin-right: var(--button-squared-icon-margin);
+ vertical-align: middle;
+ }
+
+ & > svg {
+ margin-right: calc(0.5 * var(--unit));
+ }
+}
+
+.solid {
+ &[disabled] {
+ background-color: var(--button-disabled-background-color);
+ box-shadow: var(--shadow-2p);
+ }
+
+ &:active {
+ box-shadow: var(--shadow-2p);
+ }
+
+ &:focus:not(:active) {
+ box-shadow:
+ 0 0 8px rgba(0, 0, 0, 0.18),
+ 0 8px 16px rgba(0, 0, 0, 0.36);
+ }
+}
+
+.raised {
+ box-shadow: var(--shadow-2p);
+ composes: button;
+ composes: squared;
+ composes: solid;
+}
+
+.flat {
+ background: transparent;
+ composes: button;
+ composes: squared;
+}
+
+.floating {
+ border-radius: 50%;
+ box-shadow:
+ 0 1px 1.5px 0 rgba(0, 0, 0, 0.12),
+ 0 1px 1px 0 rgba(0, 0, 0, 0.24);
+ composes: button;
+ composes: solid;
+ font-size: var(--button-floating-font-size);
+ height: var(--button-floating-height);
+ width: var(--button-floating-height);
+
+ & .icon {
+ line-height: var(--button-floating-height);
+ }
+
+ & > .rippleWrapper {
+ border-radius: 50%;
+ }
+
+ &.mini {
+ font-size: var(--button-floating-mini-font-size);
+ height: var(--button-floating-mini-height);
+ width: var(--button-floating-mini-height);
+
+ & .icon {
+ line-height: var(--button-floating-mini-height);
+ }
+ }
+}
+
+.toggle {
+ background: transparent;
+ border-radius: 50%;
+ composes: button;
+ vertical-align: middle;
+ width: var(--button-height);
+
+ & > .icon,
+ & svg {
+ font-size: var(--button-toggle-font-size);
+ line-height: var(--button-height);
+ vertical-align: top;
+ }
+
+ & > .rippleWrapper {
+ border-radius: 50%;
+ }
+}
+
+.primary:not([disabled]) {
+ &.raised,
+ &.floating {
+ background: var(--button-primary-color);
+ color: var(--button-primary-color-contrast);
+ }
+
+ &.flat,
+ &.toggle {
+ color: var(--button-primary-color);
+
+ &:focus:not(:active) {
+ background: var(--button-primary-color-hover);
+ }
+ }
+
+ &.flat:hover {
+ background: var(--button-primary-color-hover);
+ }
+}
+
+.accent:not([disabled]) {
+ &.raised,
+ &.floating {
+ background: var(--button-accent-color);
+ color: var(--button-accent-color-contrast);
+ }
+
+ &.flat,
+ &.toggle {
+ color: var(--button-accent-color);
+
+ &:focus:not(:active) {
+ background: var(--button-accent-color-hover);
+ }
+ }
+
+ &.flat:hover {
+ background: var(--button-accent-color-hover);
+ }
+}
+
+.neutral:not([disabled]) {
+ &.raised,
+ &.floating {
+ background-color: var(--button-neutral-color);
+ color: var(--button-neutral-color-contrast);
+ }
+
+ &.flat,
+ &.toggle {
+ color: var(--button-neutral-color-contrast);
+
+ &:focus:not(:active) {
+ background: var(--button-neutral-color-hover);
+ }
+ }
+
+ &.flat:hover {
+ background: var(--button-neutral-color-hover);
+ }
+
+ &.inverse {
+ &.raised,
+ &.floating {
+ background-color: var(--button-neutral-color-contrast);
+ color: var(--button-neutral-color);
+ }
+
+ &.flat,
+ &.toggle {
+ color: var(--button-neutral-color);
+
+ &:focus:not(:active) {
+ background: var(--button-neutral-color-hover);
+ }
+ }
+
+ &.flat:hover {
+ background: var(--button-neutral-color-hover);
+ }
+ }
+}
+
+.neutral.inverse[disabled] {
+ background-color: var(--button-disabled-background-inverse);
+ color: var(--button-disabled-text-color-inverse);
+}
diff --git a/components/button/theme.scss b/components/button/theme.scss
deleted file mode 100644
index 9c450ef8..00000000
--- a/components/button/theme.scss
+++ /dev/null
@@ -1,187 +0,0 @@
-@import "../colors";
-@import "../globals";
-@import "../mixins";
-@import "./config";
-@import "./mixins";
-
-.button {
- position: relative;
-
- > input {
- position: absolute;
- top: 0;
- left: 0;
- z-index: 0;
- width: 0.1px;
- height: 0.1px;
- padding: 0;
- margin: 0;
- overflow: hidden;
- opacity: 0;
- }
-}
-
-%button {
- @include typo-button();
- position: relative;
- display: inline-block;
- height: $button-height;
- flex-direction: row;
- align-content: center;
- align-items: center;
- justify-content: center;
- line-height: $button-height;
- text-align: center;
- text-decoration: none;
- white-space: nowrap;
- cursor: pointer;
- border: 0;
- outline: none;
- transition: box-shadow .2s $animation-curve-fast-out-linear-in, background-color .2s $animation-curve-default, color .2s $animation-curve-default;
- &::-moz-focus-inner {
- border: 0;
- }
- > span:not([data-react-toolbox="tooltip"]) {
- display: inline-block;
- line-height: $button-height;
- vertical-align: top;
- }
- > svg {
- display: inline-block;
- width: 1em;
- height: $button-height;
- font-size: 120%;
- vertical-align: top;
- fill: currentColor;
- }
- > * {
- pointer-events: none;
- }
- > .rippleWrapper {
- overflow: hidden;
- }
- &[disabled] {
- color: $button-disabled-text-color;
- pointer-events: none;
- cursor: auto;
- }
-}
-
-%squared {
- min-width: $button-squared-min-width;
- padding: $button-squared-padding;
- border-radius: $button-border-radius;
- .icon {
- margin-right: $button-squared-icon-margin;
- font-size: 120%;
- vertical-align: middle;
- }
- > svg {
- margin-right: .5 * $unit;
- }
-}
-
-%solid {
- &[disabled] {
- @include shadow-2dp();
- background-color: $button-disabled-background-color;
- }
- &:active {
- @include shadow-4dp();
- }
- &:focus:not(:active) {
- @include focus-shadow();
- }
-}
-
-.raised {
- @extend %button;
- @extend %squared;
- @extend %solid;
- @include shadow-2dp();
-}
-
-.flat {
- @extend %button;
- @extend %squared;
- background: transparent;
-}
-
-.floating {
- @extend %button;
- @extend %solid;
- width: $button-floating-height;
- height: $button-floating-height;
- font-size: $button-floating-font-size;
- border-radius: 50%;
- box-shadow: 0 1px 1.5px 0 rgba(0, 0, 0, .12), 0 1px 1px 0 rgba(0, 0, 0, .24);
- .icon {
- line-height: $button-floating-height;
- }
- > .rippleWrapper {
- border-radius: 50%;
- }
- &.mini {
- width: $button-floating-mini-height;
- height: $button-floating-mini-height;
- font-size: $button-floating-mini-font-size;
- .icon {
- line-height: $button-floating-mini-height;
- }
- }
-}
-
-.toggle {
- @extend %button;
- width: $button-height;
- background: transparent;
- border-radius: 50%;
- > .icon, svg {
- font-size: $button-toggle-font-size;
- line-height: $button-height;
- vertical-align: top;
- }
- > .rippleWrapper {
- border-radius: 50%;
- }
-}
-
-.neutral:not([disabled]) {
- &.raised, &.floating {
- color: $button-neutral-color-contrast;
- background-color: $button-neutral-color;
- }
- &.flat, &.toggle {
- color: $button-neutral-color-contrast;
- &:focus:not(:active) {
- background: $button-neutral-color-hover;
- }
- }
- &.flat:hover {
- background: $button-neutral-color-hover;
- }
-
- &.inverse {
- &.raised, &.floating {
- color: $button-neutral-color;
- background-color: $button-neutral-color-contrast;
- }
- &.flat, &.toggle {
- color: $button-neutral-color;
- &:focus:not(:active) {
- background: $button-neutral-color-hover;
- }
- }
- &.flat:hover {
- background: $button-neutral-color-hover;
- }
- }
-}
-
-.neutral.inverse[disabled] {
- color: $button-disabled-text-color-inverse;
- background-color: $button-disabled-background-inverse;
-}
-
-@include btn-colors("primary", $button-primary-color-contrast, $button-primary-color, $button-primary-color-hover);
-@include btn-colors("accent", $button-accent-color-contrast, $button-accent-color, $button-accent-color-hover);
diff --git a/components/card/_config.scss b/components/card/_config.scss
deleted file mode 100644
index c89b3cb5..00000000
--- a/components/card/_config.scss
+++ /dev/null
@@ -1,7 +0,0 @@
-$card-color-white: $color-white !default;
-$card-text-overlay: rgba($color-black, 0.35) !default;
-$card-background-color: $card-color-white !default;
-$card-padding-sm: .8 * $unit !default;
-$card-padding: 1.6 * $unit !default;
-$card-padding-lg: 2 * $unit !default;
-$card-font-size: $font-size-small !default;
diff --git a/components/card/config.css b/components/card/config.css
new file mode 100644
index 00000000..34715f54
--- /dev/null
+++ b/components/card/config.css
@@ -0,0 +1,9 @@
+:root {
+ --card-color-white: var(--color-white);
+ --card-text-overlay: color(var(--color-black) a(35%));
+ --card-background-color: var(--card-color-white);
+ --card-padding-sm: calc(0.8 * var(--unit));
+ --card-padding: calc(1.6 * var(--unit));
+ --card-padding-lg: calc(2 * var(--unit));
+ --card-font-size: var(--font-size-small);
+}
diff --git a/components/card/index.js b/components/card/index.js
index ef571e9b..a4e6f14a 100644
--- a/components/card/index.js
+++ b/components/card/index.js
@@ -6,7 +6,7 @@ import { CardMedia } from './CardMedia.js';
import { CardText } from './CardText.js';
import { cardTitleFactory } from './CardTitle.js';
import Avatar from '../avatar';
-import theme from './theme.scss';
+import theme from './theme.css';
const CardTitle = cardTitleFactory(Avatar);
const ThemedCard = themr(CARD, theme)(Card);
diff --git a/components/card/theme.css b/components/card/theme.css
new file mode 100644
index 00000000..d827ae3e
--- /dev/null
+++ b/components/card/theme.css
@@ -0,0 +1,182 @@
+@import '../colors.css';
+@import '../variables.css';
+@import './config.css';
+
+.card {
+ background: var(--card-background-color);
+ border-radius: calc(0.2 * var(--unit));
+ box-shadow: var(--shadow-2p);
+ composes: reset from '../helpers.css';
+ display: flex;
+ flex-direction: column;
+ font-size: var(--card-font-size);
+ overflow: hidden;
+ width: 100%;
+
+ &.raised {
+ box-shadow: var(--shadow-8p);
+ }
+
+ & [data-react-toolbox='avatar'] {
+ display: block;
+ }
+}
+
+.cardMedia {
+ background-position: center center;
+ background-repeat: no-repeat;
+ background-size: cover;
+ position: relative;
+
+ &.wide,
+ &.square {
+ width: 100%;
+
+ & .content {
+ height: 100%;
+ position: absolute;
+ }
+
+ & .content > iframe,
+ & .content > video,
+ & .content > img {
+ max-width: 100%;
+ }
+ }
+
+ &::after {
+ content: '';
+ display: block;
+ height: 0;
+ }
+
+ &.wide::after {
+ padding-top: 56.25%;
+ }
+
+ &.square::after {
+ padding-top: 100%;
+ }
+
+ & .content {
+ display: flex;
+ flex-direction: column;
+ justify-content: flex-end;
+ left: 0;
+ overflow: hidden;
+ position: relative;
+ top: 0;
+ width: 100%;
+ }
+
+ & .contentOverlay {
+ & .cardTitle,
+ & .cardActions,
+ & .cardText {
+ background-color: var(--card-text-overlay);
+ }
+ }
+
+ & .cardTitle {
+ & .title,
+ & .subtitle {
+ color: var(--card-color-white);
+ }
+ }
+}
+
+.cardTitle {
+ align-items: center;
+ display: flex;
+
+ & [data-react-toolbox='avatar'] {
+ margin-right: calc(1.3 * var(--unit));
+ }
+
+ & .title {
+ font-size: calc(2 * var(--unit));
+ font-weight: 500;
+ letter-spacing: 0.02em;
+ line-height: 1;
+ margin: 0;
+ padding: 0;
+ }
+
+ & .subtitle {
+ color: var(--color-text-secondary);
+ font-size: calc(1.4 * var(--unit));
+ font-weight: 400;
+ letter-spacing: 0;
+ line-height: calc(2.4 * var(--unit));
+ margin: 0;
+ padding: 0;
+ }
+
+ &.large {
+ padding: var(--card-padding-lg) var(--card-padding) calc(var(--card-padding) - 0.2 * var(--unit));
+
+ & .title {
+ font-size: calc(2.4 * var(--unit));
+ -moz-osx-font-smoothing: grayscale;
+ font-weight: 400;
+ line-height: 1.25;
+ }
+ }
+
+ &.small {
+ padding: var(--card-padding);
+
+ & .title {
+ font-size: 1.4rem;
+ letter-spacing: 0;
+ line-height: 1.4;
+ }
+
+ & .subtitle {
+ font-weight: 500;
+ line-height: 1.4;
+ }
+ }
+}
+
+.cardTitle,
+.cardText {
+ padding: calc(var(--card-padding) - 0.2 * var(--unit)) var(--card-padding);
+
+ & p {
+ font-size: calc(1.4 * var(--unit));
+ font-weight: 400;
+ letter-spacing: 0;
+ line-height: calc(2.4 * var(--unit));
+ margin: 0;
+ }
+
+ &:last-child {
+ padding-bottom: var(--card-padding-lg);
+ }
+
+ & + .cardText {
+ padding-top: 0;
+ }
+}
+
+.cardActions {
+ align-items: center;
+ display: flex;
+ justify-content: flex-start;
+ padding: var(--card-padding-sm);
+
+ & [data-react-toolbox='button'] {
+ margin: 0 calc(var(--card-padding-sm) / 2);
+ min-width: 0;
+ padding: 0 var(--card-padding-sm);
+
+ &:first-child {
+ margin-left: 0;
+ }
+
+ &:last-child {
+ margin-right: 0;
+ }
+ }
+}
diff --git a/components/card/theme.scss b/components/card/theme.scss
deleted file mode 100644
index c49ea5cf..00000000
--- a/components/card/theme.scss
+++ /dev/null
@@ -1,126 +0,0 @@
-@import "../colors";
-@import "../globals";
-@import "../mixins";
-@import "./config";
-
-.card {
- @include shadow-2dp();
- display: flex;
- width: 100%;
- flex-direction: column;
- overflow: hidden;
- font-size: $card-font-size;
- background: $card-background-color;
- border-radius: .2 * $unit;
- &.raised {
- @include shadow-8dp();
- }
- [data-react-toolbox="avatar"] {
- display: block;
- }
-}
-
-.cardMedia {
- position: relative;
- background-repeat: no-repeat;
- background-position: center center;
- background-size: cover;
- &.wide, &.square {
- width: 100%;
- .content {
- position: absolute;
- height: 100%;
- }
- .content > iframe, .content > video, .content > img {
- max-width: 100%;
- }
- }
- &::after {
- display: block;
- height: 0;
- content: "";
- }
- &.wide::after {
- padding-top: 56.25%;
- }
- &.square::after {
- padding-top: 100%;
- }
- .content {
- position: relative;
- top: 0;
- left: 0;
- display: flex;
- width: 100%;
- flex-direction: column;
- justify-content: flex-end;
- overflow: hidden;
- }
- .contentOverlay {
- .cardTitle, .cardActions, .cardText {
- background-color: $card-text-overlay;
- }
- }
-}
-
-.cardTitle {
- display: flex;
- align-items: center;
- [data-react-toolbox="avatar"] {
- margin-right: 1.3 * $unit;
- }
- .subtitle {
- color: $color-text-secondary;
- }
- &.large {
- padding: $card-padding-lg $card-padding ($card-padding - .2 * $unit);
- .title {
- @include typo-headline();
- line-height: 1.25;
- }
- }
- &.small {
- padding: $card-padding;
- .title {
- @include typo-body-2(false, true);
- line-height: 1.4;
- }
- .subtitle {
- font-weight: 500;
- line-height: 1.4;
- }
- }
- .cardMedia & {
- .title, .subtitle {
- color: $card-color-white;
- }
- }
-}
-
-.cardTitle, .cardText {
- padding: ($card-padding - .2 * $unit) $card-padding;
- &:last-child {
- padding-bottom: $card-padding-lg;
- }
- + .cardText {
- padding-top: 0;
- }
-}
-
-.cardActions {
- display: flex;
- align-items: center;
- justify-content: flex-start;
- padding: $card-padding-sm;
- [data-react-toolbox="button"] {
- min-width: 0;
- padding: 0 $card-padding-sm;
- margin: 0 $card-padding-sm / 2;
- &:first-child {
- margin-left: 0;
- }
- &:last-child {
- margin-right: 0;
- }
- }
-}
diff --git a/components/checkbox/_config.scss b/components/checkbox/_config.scss
deleted file mode 100644
index 18266e49..00000000
--- a/components/checkbox/_config.scss
+++ /dev/null
@@ -1,12 +0,0 @@
-$checkbox-color: $color-primary !default;
-$checkbox-disabled-color: rgba($color-black, 0.26) !default;
-$checkbox-field-margin-bottom: 1.5 * $unit !default;
-$checkbox-focus-checked-color: rgba($color-primary, 0.26) !default;
-$checkbox-ripple-duration: 650ms !default;
-$checkbox-size: 1.8 * $unit !default;
-$checkbox-focus-color: rgba($color-black, 0.1) !default;
-$checkbox-focus-size: $checkbox-size * 2.3 !default;
-$checkbox-text-color: $color-black !default;
-$checkbox-text-font-size: $font-size-small !default;
-$checkbox-total-height: 1.8 * $unit !default;
-$checkbox-transition-duration: .2s !default;
diff --git a/components/checkbox/config.css b/components/checkbox/config.css
new file mode 100644
index 00000000..fe33d1e8
--- /dev/null
+++ b/components/checkbox/config.css
@@ -0,0 +1,14 @@
+:root {
+ --checkbox-color: var(--color-primary);
+ --checkbox-disabled-color: color(var(--color-black) a(26%));
+ --checkbox-field-margin-bottom: calc(1.5 * var(--unit));
+ --checkbox-focus-checked-color: color(var(--color-primary) a(26%));
+ --checkbox-ripple-duration: 650ms;
+ --checkbox-size: calc(1.8 * var(--unit));
+ --checkbox-focus-color: color(var(--color-black) a(1%));
+ --checkbox-focus-size: calc(var(--checkbox-size) * 2.3);
+ --checkbox-text-color: var(--color-black);
+ --checkbox-text-font-size: var(--font-size-small);
+ --checkbox-total-height: calc(1.8 * var(--unit));
+ --checkbox-transition-duration: 0.2s;
+}
diff --git a/components/checkbox/index.js b/components/checkbox/index.js
index 5f89939a..8475ead2 100644
--- a/components/checkbox/index.js
+++ b/components/checkbox/index.js
@@ -3,7 +3,7 @@ import { CHECKBOX } from '../identifiers.js';
import themedRippleFactory from '../ripple';
import { checkboxFactory } from './Checkbox.js';
import checkFactory from './Check.js';
-import theme from './theme.scss';
+import theme from './theme.css';
const ThemedCheck = checkFactory(themedRippleFactory({ centered: true, spread: 2.6}));
const ThemedCheckbox = themr(CHECKBOX, theme)(checkboxFactory(ThemedCheck));
diff --git a/components/checkbox/theme.css b/components/checkbox/theme.css
new file mode 100644
index 00000000..d6ccfb52
--- /dev/null
+++ b/components/checkbox/theme.css
@@ -0,0 +1,128 @@
+@import '../colors.css';
+@import '../variables.css';
+@import './config.css';
+
+.field {
+ composes: reset from '../helpers.css';
+ display: block;
+ height: var(--checkbox-size);
+ margin-bottom: var(--checkbox-field-margin-bottom);
+ position: relative;
+ white-space: nowrap;
+
+ & .ripple {
+ background-color: var(--checkbox-color);
+ opacity: 0.3;
+ transition-duration: var(--checkbox-ripple-duration);
+ }
+}
+
+.text {
+ color: var(--checkbox-text-color);
+ display: inline-block;
+ font-size: var(--checkbox-text-font-size);
+ line-height: var(--checkbox-size);
+ padding-left: var(--unit);
+ vertical-align: top;
+ white-space: nowrap;
+}
+
+.input {
+ height: 0;
+ opacity: 0;
+ overflow: hidden;
+ position: absolute;
+ width: 0;
+
+ &:focus ~ .check {
+ &::before {
+ background-color: var(--checkbox-focus-color);
+ border-radius: 50%;
+ content: '';
+ height: var(--checkbox-focus-size);
+ left: 50%;
+ margin-left: calc(-1 * var(--checkbox-focus-size) / 2);
+ margin-top: calc(-1 * var(--checkbox-focus-size) / 2);
+ pointer-events: none;
+ position: absolute;
+ top: 50%;
+ width: var(--checkbox-focus-size);
+ }
+
+ &.checked::before {
+ background-color: var(--checkbox-focus-checked-color);
+ }
+ }
+}
+
+.check {
+ border-color: var(--checkbox-text-color);
+ border-radius: 2px;
+ border-style: solid;
+ border-width: 2px;
+ composes: reset from '../helpers.css';
+ cursor: pointer;
+ display: inline-block;
+ height: var(--checkbox-size);
+ position: relative;
+ transition-duration: var(--checkbox-transition-duration);
+ transition-property: background-color;
+ transition-timing-function: var(--animation-curve-default);
+ vertical-align: top;
+ width: var(--checkbox-size);
+
+ &.checked {
+ background-color: var(--checkbox-color);
+ border-color: var(--checkbox-color);
+
+ &::after {
+ animation: checkmark-expand 140ms ease-out forwards;
+ border-bottom-width: 2px;
+ border-color: var(--color-background);
+ border-left: 0;
+ border-right-width: 2px;
+ border-style: solid;
+ border-top: 0;
+ content: '';
+ height: calc(1.2 * var(--unit));
+ left: calc(0.4 * var(--unit));
+ position: absolute;
+ top: calc(-0.1 * var(--unit));
+ transform: rotate(45deg);
+ width: calc(0.7 * var(--unit));
+ }
+ }
+}
+
+.disabled {
+ & > .text {
+ color: var(--checkbox-disabled-color);
+ }
+
+ & > .check {
+ border-color: var(--checkbox-disabled-color);
+ cursor: auto;
+
+ &.checked {
+ background-color: var(--checkbox-disabled-color);
+ border-color: transparent;
+ cursor: auto;
+ }
+ }
+}
+
+@keyframes checkmark-expand {
+ 0% {
+ height: 0;
+ left: calc(0.6 * var(--unit));
+ top: calc(0.9 * var(--unit));
+ width: 0;
+ }
+
+ 100% {
+ height: calc(1.2 * var(--unit));
+ left: calc(0.4 * var(--unit));
+ top: calc(-0.1 * var(--unit));
+ width: calc(0.7 * var(--unit));
+ }
+}
diff --git a/components/checkbox/theme.scss b/components/checkbox/theme.scss
deleted file mode 100644
index 55b17920..00000000
--- a/components/checkbox/theme.scss
+++ /dev/null
@@ -1,121 +0,0 @@
-@import "../colors";
-@import "../globals";
-@import "../mixins";
-@import "./config";
-
-.field {
- position: relative;
- display: block;
- height: $checkbox-size;
- margin-bottom: $checkbox-field-margin-bottom;
- white-space: nowrap;
- vertical-align: middle;
- .ripple {
- background-color: $checkbox-color;
- opacity: .3;
- transition-duration: $checkbox-ripple-duration;
- }
-}
-
-.text {
- display: inline-block;
- padding-left: $unit;
- font-size: $checkbox-text-font-size;
- line-height: $checkbox-size;
- color: $checkbox-text-color;
- white-space: nowrap;
- vertical-align: top;
-}
-
-.input {
- position: absolute;
- width: 0;
- height: 0;
- overflow: hidden;
- opacity: 0;
- &:focus ~ .check {
- &:before {
- position: absolute;
- top: 50%;
- left: 50%;
- width: $checkbox-focus-size;
- height: $checkbox-focus-size;
- margin-top: - $checkbox-focus-size / 2;
- margin-left: - $checkbox-focus-size / 2;
- pointer-events: none;
- content: "";
- background-color: $checkbox-focus-color;
- border-radius: 50%;
- }
- &.checked:before {
- background-color: $checkbox-focus-checked-color;
- }
- }
-}
-
-.check {
- position: relative;
- display: inline-block;
- width: $checkbox-size;
- height: $checkbox-size;
- vertical-align: top;
- cursor: pointer;
- border-color: $checkbox-text-color;
- border-style: solid;
- border-width: 2px;
- border-radius: 2px;
- transition-timing-function: $animation-curve-default;
- transition-duration: $checkbox-transition-duration;
- transition-property: background-color;
- &.checked {
- background-color: $checkbox-color;
- border-color: $checkbox-color;
- &:after {
- position: absolute;
- top: -.1 * $unit;
- left: .4 * $unit;
- width: .7 * $unit;
- height: 1.2 * $unit;
- content: "";
- border-color: $color-background;
- border-style: solid;
- border-top: 0;
- border-right-width: 2px;
- border-bottom-width: 2px;
- border-left: 0;
- transform: rotate(45deg);
- animation: checkmark-expand 140ms ease-out forwards;
- }
- }
-}
-
-.disabled {
- > .text {
- color: $checkbox-disabled-color;
- }
- > .check {
- cursor: auto;
- border-color: $checkbox-disabled-color;
- &.checked {
- cursor: auto;
- background-color: $checkbox-disabled-color;
- border-color: transparent;
- }
- }
-}
-
-@keyframes checkmark-expand {
- 0% {
- top: .9 * $unit;
- left: .6 * $unit;
- width: 0;
- height: 0;
- }
-
- 100% {
- top: -.1 * $unit;
- left: .4 * $unit;
- width: .7 * $unit;
- height: 1.2 * $unit;
- }
-}
diff --git a/components/chip/_config.scss b/components/chip/_config.scss
deleted file mode 100644
index a335b2f6..00000000
--- a/components/chip/_config.scss
+++ /dev/null
@@ -1,17 +0,0 @@
-$chip-height: 3.2 * $unit !default;
-$chip-padding: 1.2 * $unit !default;
-$chip-margin-right: 0.25 * $unit !default;
-$chip-background: $palette-grey-200 !default;
-
-$chip-icon-font-size: 2 * $unit !default;
-$chip-icon-margin-right: 0.8 * $unit !default;
-
-$chip-color: $color-text-secondary !default;
-$chip-font-size: $font-size-small !default;
-
-$chip-remove-size: 2.4 * $unit !default;
-$chip-remove-margin: 0.4 * $unit !default;
-$chip-remove-stroke-width: 0.4 * $unit !default;
-$chip-remove-background: $palette-grey-400 !default;
-$chip-remove-background-hover: $palette-grey-500 !default;
-$chip-remove-color: $color-white !default;
diff --git a/components/chip/config.css b/components/chip/config.css
new file mode 100644
index 00000000..f44c8ad2
--- /dev/null
+++ b/components/chip/config.css
@@ -0,0 +1,16 @@
+:root {
+ --chip-height: calc(3.2 * var(--unit));
+ --chip-padding: calc(1.2 * var(--unit));
+ --chip-margin-right: calc(0.25 * var(--unit));
+ --chip-background: var(--palette-grey-200);
+ --chip-icon-font-size: calc(2 * var(--unit));
+ --chip-icon-margin-right: calc(0.8 * var(--unit));
+ --chip-color: var(--color-text-secondary);
+ --chip-font-size: var(--font-size-small);
+ --chip-remove-size: calc(2.4 * var(--unit));
+ --chip-remove-margin: calc(0.4 * var(--unit));
+ --chip-remove-stroke-width: calc(0.4 * var(--unit));
+ --chip-remove-background: var(--palette-grey-400);
+ --chip-remove-background-hover: var(--palette-grey-500);
+ --chip-remove-color: var(--color-white);
+}
diff --git a/components/chip/index.js b/components/chip/index.js
index 62dd4d6d..b6802a9f 100644
--- a/components/chip/index.js
+++ b/components/chip/index.js
@@ -2,7 +2,7 @@ import { CHIP } from '../identifiers.js';
import { themr } from 'react-css-themr';
import { chipFactory } from './Chip.js';
import Avatar from '../avatar';
-import theme from './theme.scss';
+import theme from './theme.css';
const Chip = chipFactory(Avatar);
const ThemedChip = themr(CHIP, theme)(Chip);
diff --git a/components/chip/theme.css b/components/chip/theme.css
new file mode 100644
index 00000000..279d6424
--- /dev/null
+++ b/components/chip/theme.css
@@ -0,0 +1,67 @@
+@import '../colors.css';
+@import '../variables.css';
+@import './config.css';
+
+.chip {
+ background-color: var(--chip-background);
+ border-radius: var(--chip-height);
+ color: var(--chip-color);
+ composes: reset from '../helpers.css';
+ display: inline-block;
+ font-size: var(--chip-font-size);
+ line-height: var(--chip-height);
+ margin-right: var(--chip-margin-right);
+ max-width: 100%;
+ overflow: hidden;
+ padding: 0 var(--chip-padding);
+ position: relative;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.avatar {
+ padding-left: 0;
+
+ & > [data-react-toolbox='avatar'] {
+ height: var(--chip-height);
+ margin-right: var(--chip-icon-margin-right);
+ vertical-align: middle;
+ width: var(--chip-height);
+
+ & > span {
+ font-size: var(--chip-icon-font-size);
+ line-height: var(--chip-height);
+ }
+ }
+}
+
+.deletable {
+ padding-right: calc(var(--chip-remove-size) + 2 * var(--chip-remove-margin));
+}
+
+.delete {
+ cursor: pointer;
+ display: inline-block;
+ height: var(--chip-remove-size);
+ margin: var(--chip-remove-margin);
+ padding: var(--chip-remove-margin);
+ position: absolute;
+ right: 0;
+ width: var(--chip-remove-size);
+}
+
+.delete:hover .deleteIcon {
+ background: var(--chip-remove-background-hover);
+}
+
+.deleteIcon {
+ background: var(--chip-remove-background);
+ border-radius: var(--chip-remove-size);
+ vertical-align: top;
+
+ & .deleteX {
+ fill: transparent;
+ stroke: var(--chip-remove-color);
+ stroke-width: var(--chip-remove-stroke-width);
+ }
+}
diff --git a/components/chip/theme.scss b/components/chip/theme.scss
deleted file mode 100644
index 4baa8f9c..00000000
--- a/components/chip/theme.scss
+++ /dev/null
@@ -1,68 +0,0 @@
-@import "../colors";
-@import "../globals";
-@import "../mixins";
-@import "./config";
-
-.chip {
- position: relative;
- display: inline-block;
- max-width: 100%;
- padding: 0 $chip-padding;
- margin-right: $chip-margin-right;
- overflow: hidden;
- font-size: $chip-font-size;
- line-height: $chip-height;
- color: $chip-color;
- text-overflow: ellipsis;
- white-space: nowrap;
- background-color: $chip-background;
- border-radius: $chip-height;
-}
-
-.avatar {
- padding-left: 0;
-
- > [data-react-toolbox="avatar"] {
- width: $chip-height;
- height: $chip-height;
- margin-right: $chip-icon-margin-right;
- vertical-align: middle;
-
- > span {
- font-size: $chip-icon-font-size;
- line-height: $chip-height;
- }
- }
-}
-
-.deletable {
- padding-right: $chip-remove-size + 2 * $chip-remove-margin;
-}
-
-.delete {
- position: absolute;
- right: 0;
- display: inline-block;
- width: $chip-remove-size;
- height: $chip-remove-size;
- padding: $chip-remove-margin;
- margin: $chip-remove-margin;
- vertical-align: middle;
- cursor: pointer;
-}
-
-.delete:hover .deleteIcon {
- background: $chip-remove-background-hover;
-}
-
-.deleteIcon {
- vertical-align: top;
- background: $chip-remove-background;
- border-radius: $chip-remove-size;
-
- .deleteX {
- fill: transparent;
- stroke-width: $chip-remove-stroke-width;
- stroke: $chip-remove-color;
- }
-}
diff --git a/components/colors.css b/components/colors.css
new file mode 100644
index 00000000..b72f5a9f
--- /dev/null
+++ b/components/colors.css
@@ -0,0 +1,279 @@
+:root {
+ --palette-red-50: rgb(255, 235, 238);
+ --palette-red-100: rgb(255, 205, 210);
+ --palette-red-200: rgb(239, 154, 154);
+ --palette-red-300: rgb(229, 115, 115);
+ --palette-red-400: rgb(239, 83, 80);
+ --palette-red-500: rgb(244, 67, 54);
+ --palette-red-600: rgb(229, 57, 53);
+ --palette-red-700: rgb(211, 47, 47);
+ --palette-red-800: rgb(198, 40, 40);
+ --palette-red-900: rgb(183, 28, 28);
+ --palette-red-a100: rgb(255, 138, 128);
+ --palette-red-a200: rgb(255, 82, 82);
+ --palette-red-a400: rgb(255, 23, 68);
+ --palette-red-a700: rgb(213, 0, 0);
+
+ --palette-pink-50: rgb(252, 228, 236);
+ --palette-pink-100: rgb(248, 187, 208);
+ --palette-pink-200: rgb(244, 143, 177);
+ --palette-pink-300: rgb(240, 98, 146);
+ --palette-pink-400: rgb(236, 64, 122);
+ --palette-pink-500: rgb(233, 30, 99);
+ --palette-pink-600: rgb(216, 27, 96);
+ --palette-pink-700: rgb(194, 24, 91);
+ --palette-pink-800: rgb(173, 20, 87);
+ --palette-pink-900: rgb(136, 14, 79);
+ --palette-pink-a100: rgb(255, 128, 171);
+ --palette-pink-a200: rgb(255, 64, 129);
+ --palette-pink-a400: rgb(245, 0, 87);
+ --palette-pink-a700: rgb(197, 17, 98);
+
+ --palette-purple-50: rgb(243, 229, 245);
+ --palette-purple-100: rgb(225, 190, 231);
+ --palette-purple-200: rgb(206, 147, 216);
+ --palette-purple-300: rgb(186, 104, 200);
+ --palette-purple-400: rgb(171, 71, 188);
+ --palette-purple-500: rgb(156, 39, 176);
+ --palette-purple-600: rgb(142, 36, 170);
+ --palette-purple-700: rgb(123, 31, 162);
+ --palette-purple-800: rgb(106, 27, 154);
+ --palette-purple-900: rgb(74, 20, 140);
+ --palette-purple-a100: rgb(234, 128, 252);
+ --palette-purple-a200: rgb(224, 64, 251);
+ --palette-purple-a400: rgb(213, 0, 249);
+ --palette-purple-a700: rgb(170, 0, 255);
+
+ --palette-deep-purple-50: rgb(237, 231, 246);
+ --palette-deep-purple-100: rgb(209, 196, 233);
+ --palette-deep-purple-200: rgb(179, 157, 219);
+ --palette-deep-purple-300: rgb(149, 117, 205);
+ --palette-deep-purple-400: rgb(126, 87, 194);
+ --palette-deep-purple-500: rgb(103, 58, 183);
+ --palette-deep-purple-600: rgb(94, 53, 177);
+ --palette-deep-purple-700: rgb(81, 45, 168);
+ --palette-deep-purple-800: rgb(69, 39, 160);
+ --palette-deep-purple-900: rgb(49, 27, 146);
+ --palette-deep-purple-a100: rgb(179, 136, 255);
+ --palette-deep-purple-a200: rgb(124, 77, 255);
+ --palette-deep-purple-a400: rgb(101, 31, 255);
+ --palette-deep-purple-a700: rgb(98, 0, 234);
+
+ --palette-indigo-50: rgb(232, 234, 246);
+ --palette-indigo-100: rgb(197, 202, 233);
+ --palette-indigo-200: rgb(159, 168, 218);
+ --palette-indigo-300: rgb(121, 134, 203);
+ --palette-indigo-400: rgb(92, 107, 192);
+ --palette-indigo-500: rgb(63, 81, 181);
+ --palette-indigo-600: rgb(57, 73, 171);
+ --palette-indigo-700: rgb(48, 63, 159);
+ --palette-indigo-800: rgb(40, 53, 147);
+ --palette-indigo-900: rgb(26, 35, 126);
+ --palette-indigo-a100: rgb(140, 158, 255);
+ --palette-indigo-a200: rgb(83, 109, 254);
+ --palette-indigo-a400: rgb(61, 90, 254);
+ --palette-indigo-a700: rgb(48, 79, 254);
+
+ --palette-blue-50: rgb(227, 242, 253);
+ --palette-blue-100: rgb(187, 222, 251);
+ --palette-blue-200: rgb(144, 202, 249);
+ --palette-blue-300: rgb(100, 181, 246);
+ --palette-blue-400: rgb(66, 165, 245);
+ --palette-blue-500: rgb(33, 150, 243);
+ --palette-blue-600: rgb(30, 136, 229);
+ --palette-blue-700: rgb(25, 118, 210);
+ --palette-blue-800: rgb(21, 101, 192);
+ --palette-blue-900: rgb(13, 71, 161);
+ --palette-blue-a100: rgb(130, 177, 255);
+ --palette-blue-a200: rgb(68, 138, 255);
+ --palette-blue-a400: rgb(41, 121, 255);
+ --palette-blue-a700: rgb(41, 98, 255);
+
+ --palette-light-blue-50: rgb(225, 245, 254);
+ --palette-light-blue-100: rgb(179, 229, 252);
+ --palette-light-blue-200: rgb(129, 212, 250);
+ --palette-light-blue-300: rgb(79, 195, 247);
+ --palette-light-blue-400: rgb(41, 182, 246);
+ --palette-light-blue-500: rgb(3, 169, 244);
+ --palette-light-blue-600: rgb(3, 155, 229);
+ --palette-light-blue-700: rgb(2, 136, 209);
+ --palette-light-blue-800: rgb(2, 119, 189);
+ --palette-light-blue-900: rgb(1, 87, 155);
+ --palette-light-blue-a100: rgb(128, 216, 255);
+ --palette-light-blue-a200: rgb(64, 196, 255);
+ --palette-light-blue-a400: rgb(0, 176, 255);
+ --palette-light-blue-a700: rgb(0, 145, 234);
+
+ --palette-cyan-50: rgb(224, 247, 250);
+ --palette-cyan-100: rgb(178, 235, 242);
+ --palette-cyan-200: rgb(128, 222, 234);
+ --palette-cyan-300: rgb(77, 208, 225);
+ --palette-cyan-400: rgb(38, 198, 218);
+ --palette-cyan-500: rgb(0, 188, 212);
+ --palette-cyan-600: rgb(0, 172, 193);
+ --palette-cyan-700: rgb(0, 151, 167);
+ --palette-cyan-800: rgb(0, 131, 143);
+ --palette-cyan-900: rgb(0, 96, 100);
+ --palette-cyan-a100: rgb(132, 255, 255);
+ --palette-cyan-a200: rgb(24, 255, 255);
+ --palette-cyan-a400: rgb(0, 229, 255);
+ --palette-cyan-a700: rgb(0, 184, 212);
+
+ --palette-teal-50: rgb(224, 242, 241);
+ --palette-teal-100: rgb(178, 223, 219);
+ --palette-teal-200: rgb(128, 203, 196);
+ --palette-teal-300: rgb(77, 182, 172);
+ --palette-teal-400: rgb(38, 166, 154);
+ --palette-teal-500: rgb(0, 150, 136);
+ --palette-teal-600: rgb(0, 137, 123);
+ --palette-teal-700: rgb(0, 121, 107);
+ --palette-teal-800: rgb(0, 105, 92);
+ --palette-teal-900: rgb(0, 77, 64);
+ --palette-teal-a100: rgb(167, 255, 235);
+ --palette-teal-a200: rgb(100, 255, 218);
+ --palette-teal-a400: rgb(29, 233, 182);
+ --palette-teal-a700: rgb(0, 191, 165);
+
+ --palette-green-50: rgb(232, 245, 233);
+ --palette-green-100: rgb(200, 230, 201);
+ --palette-green-200: rgb(165, 214, 167);
+ --palette-green-300: rgb(129, 199, 132);
+ --palette-green-400: rgb(102, 187, 106);
+ --palette-green-500: rgb(76, 175, 80);
+ --palette-green-600: rgb(67, 160, 71);
+ --palette-green-700: rgb(56, 142, 60);
+ --palette-green-800: rgb(46, 125, 50);
+ --palette-green-900: rgb(27, 94, 32);
+ --palette-green-a100: rgb(185, 246, 202);
+ --palette-green-a200: rgb(105, 240, 174);
+ --palette-green-a400: rgb(0, 230, 118);
+ --palette-green-a700: rgb(0, 200, 83);
+
+ --palette-light-green-50: rgb(241, 248, 233);
+ --palette-light-green-100: rgb(220, 237, 200);
+ --palette-light-green-200: rgb(197, 225, 165);
+ --palette-light-green-300: rgb(174, 213, 129);
+ --palette-light-green-400: rgb(156, 204, 101);
+ --palette-light-green-500: rgb(139, 195, 74);
+ --palette-light-green-600: rgb(124, 179, 66);
+ --palette-light-green-700: rgb(104, 159, 56);
+ --palette-light-green-800: rgb(85, 139, 47);
+ --palette-light-green-900: rgb(51, 105, 30);
+ --palette-light-green-a100: rgb(204, 255, 144);
+ --palette-light-green-a200: rgb(178, 255, 89);
+ --palette-light-green-a400: rgb(118, 255, 3);
+ --palette-light-green-a700: rgb(100, 221, 23);
+
+ --palette-lime-50: rgb(249, 251, 231);
+ --palette-lime-100: rgb(240, 244, 195);
+ --palette-lime-200: rgb(230, 238, 156);
+ --palette-lime-300: rgb(220, 231, 117);
+ --palette-lime-400: rgb(212, 225, 87);
+ --palette-lime-500: rgb(205, 220, 57);
+ --palette-lime-600: rgb(192, 202, 51);
+ --palette-lime-700: rgb(175, 180, 43);
+ --palette-lime-800: rgb(158, 157, 36);
+ --palette-lime-900: rgb(130, 119, 23);
+ --palette-lime-a100: rgb(244, 255, 129);
+ --palette-lime-a200: rgb(238, 255, 65);
+ --palette-lime-a400: rgb(198, 255, 0);
+ --palette-lime-a700: rgb(174, 234, 0);
+
+ --palette-yellow-50: rgb(255, 253, 231);
+ --palette-yellow-100: rgb(255, 249, 196);
+ --palette-yellow-200: rgb(255, 245, 157);
+ --palette-yellow-300: rgb(255, 241, 118);
+ --palette-yellow-400: rgb(255, 238, 88);
+ --palette-yellow-500: rgb(255, 235, 59);
+ --palette-yellow-600: rgb(253, 216, 53);
+ --palette-yellow-700: rgb(251, 192, 45);
+ --palette-yellow-800: rgb(249, 168, 37);
+ --palette-yellow-900: rgb(245, 127, 23);
+ --palette-yellow-a100: rgb(255, 255, 141);
+ --palette-yellow-a200: rgb(255, 255, 0);
+ --palette-yellow-a400: rgb(255, 234, 0);
+ --palette-yellow-a700: rgb(255, 214, 0);
+
+ --palette-amber-50: rgb(255, 248, 225);
+ --palette-amber-100: rgb(255, 236, 179);
+ --palette-amber-200: rgb(255, 224, 130);
+ --palette-amber-300: rgb(255, 213, 79);
+ --palette-amber-400: rgb(255, 202, 40);
+ --palette-amber-500: rgb(255, 193, 7);
+ --palette-amber-600: rgb(255, 179, 0);
+ --palette-amber-700: rgb(255, 160, 0);
+ --palette-amber-800: rgb(255, 143, 0);
+ --palette-amber-900: rgb(255, 111, 0);
+ --palette-amber-a100: rgb(255, 229, 127);
+ --palette-amber-a200: rgb(255, 215, 64);
+ --palette-amber-a400: rgb(255, 196, 0);
+ --palette-amber-a700: rgb(255, 171, 0);
+
+ --palette-orange-50: rgb(255, 243, 224);
+ --palette-orange-100: rgb(255, 224, 178);
+ --palette-orange-200: rgb(255, 204, 128);
+ --palette-orange-300: rgb(255, 183, 77);
+ --palette-orange-400: rgb(255, 167, 38);
+ --palette-orange-500: rgb(255, 152, 0);
+ --palette-orange-600: rgb(251, 140, 0);
+ --palette-orange-700: rgb(245, 124, 0);
+ --palette-orange-800: rgb(239, 108, 0);
+ --palette-orange-900: rgb(230, 81, 0);
+ --palette-orange-a100: rgb(255, 209, 128);
+ --palette-orange-a200: rgb(255, 171, 64);
+ --palette-orange-a400: rgb(255, 145, 0);
+ --palette-orange-a700: rgb(255, 109, 0);
+
+ --palette-deep-orange-50: rgb(251, 233, 231);
+ --palette-deep-orange-100: rgb(255, 204, 188);
+ --palette-deep-orange-200: rgb(255, 171, 145);
+ --palette-deep-orange-300: rgb(255, 138, 101);
+ --palette-deep-orange-400: rgb(255, 112, 67);
+ --palette-deep-orange-500: rgb(255, 87, 34);
+ --palette-deep-orange-600: rgb(244, 81, 30);
+ --palette-deep-orange-700: rgb(230, 74, 25);
+ --palette-deep-orange-800: rgb(216, 67, 21);
+ --palette-deep-orange-900: rgb(191, 54, 12);
+ --palette-deep-orange-a100: rgb(255, 158, 128);
+ --palette-deep-orange-a200: rgb(255, 110, 64);
+ --palette-deep-orange-a400: rgb(255, 61, 0);
+ --palette-deep-orange-a700: rgb(221, 44, 0);
+
+ --palette-brown-50: rgb(239, 235, 233);
+ --palette-brown-100: rgb(215, 204, 200);
+ --palette-brown-200: rgb(188, 170, 164);
+ --palette-brown-300: rgb(161, 136, 127);
+ --palette-brown-400: rgb(141, 110, 99);
+ --palette-brown-500: rgb(121, 85, 72);
+ --palette-brown-600: rgb(109, 76, 65);
+ --palette-brown-700: rgb(93, 64, 55);
+ --palette-brown-800: rgb(78, 52, 46);
+ --palette-brown-900: rgb(62, 39, 35);
+
+ --palette-grey-50: rgb(250, 250, 250);
+ --palette-grey-100: rgb(245, 245, 245);
+ --palette-grey-200: rgb(238, 238, 238);
+ --palette-grey-300: rgb(224, 224, 224);
+ --palette-grey-400: rgb(189, 189, 189);
+ --palette-grey-500: rgb(158, 158, 158);
+ --palette-grey-600: rgb(117, 117, 117);
+ --palette-grey-700: rgb(97, 97, 97);
+ --palette-grey-800: rgb(66, 66, 66);
+ --palette-grey-900: rgb(33, 33, 33);
+
+ --palette-blue-grey-50: rgb(236, 239, 241);
+ --palette-blue-grey-100: rgb(207, 216, 220);
+ --palette-blue-grey-200: rgb(176, 190, 197);
+ --palette-blue-grey-300: rgb(144, 164, 174);
+ --palette-blue-grey-400: rgb(120, 144, 156);
+ --palette-blue-grey-500: rgb(96, 125, 139);
+ --palette-blue-grey-600: rgb(84, 110, 122);
+ --palette-blue-grey-700: rgb(69, 90, 100);
+ --palette-blue-grey-800: rgb(55, 71, 79);
+ --palette-blue-grey-900: rgb(38, 50, 56);
+
+ --color-black: rgb(0, 0, 0);
+ --color-white: rgb(255, 255, 255);
+ --color-dark-contrast: var(--color-white);
+ --color-light-contrast: var(--color-black);
+}
diff --git a/components/commons.scss b/components/commons.scss
deleted file mode 100644
index 54f9ba16..00000000
--- a/components/commons.scss
+++ /dev/null
@@ -1,95 +0,0 @@
-@import "./colors";
-@import "./globals";
-@import "./mixins";
-@import "~normalize.css";
-
-html {
- font-size: 62.5%;
-}
-
-body {
- position: absolute;
- width: 100%;
- height: 100%;
- padding: 0;
- margin: 0;
- font-family: Roboto, sans-serif;
- font-size: 1.6rem;
- -webkit-touch-callout: none;
- * {
- -webkit-tap-highlight-color: rgba(255, 255, 255, 0);
- }
-}
-
-a, abbr, address, article, aside, audio, b, blockquote, body, caption, cite,
-code, dd, del, dfn, dialog, div, dl, dt, em, fieldset, figure, footer, form, h1,
-h2, h3, h4, h5, h6, header, hgroup, hr, html, i, iframe, img, ins, kbd, label,
-legend, li, mark, menu, nav, object, ol, p, pre, q, samp, section, small, span,
-strong, sub, sup, table, tbody, td, tfoot, th, thead, time, tr, ul, var, video {
- padding: 0;
- margin: 0;
- border: 0;
- outline: 0;
-}
-
-*, *:before, *:after {
- box-sizing: border-box;
- padding: 0;
- margin: 0;
-}
-
-h1, h2, h3, h4, h5, h6, label, p, button, abbr, a, span, small {
- font-smoothing: antialiased;
- -webkit-font-smoothing: antialiased;
- text-size-adjust: 100%;
-}
-
-a {
- text-decoration: none;
- -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
-}
-
-input:not([type="checkbox"]):not([type="radio"]), button {
- outline: none;
- appearance: none;
- -webkit-touch-callout: none;
- -webkit-tap-highlight-color: rgba(255, 255, 255, 0);
-}
-
-// -- Remove firefox default style for required inputs
-input[required]:-moz-ui-invalid {
- box-shadow: none;
-}
-
-// -- Material design font sizes
-h1 small, h2 small, h3 small, h4 small, h5 small, h6 small {
- @include typo-display-3($color-contrast: true);
-}
-
-h1 {
- @include typo-display-3;
-}
-
-h2 {
- @include typo-display-2;
-}
-
-h3 {
- @include typo-display-1;
-}
-
-h4 {
- @include typo-headline;
-}
-
-h5 {
- @include typo-title;
-}
-
-h6 {
- @include typo-subhead;
-}
-
-p {
- @include typo-body-1;
-}
diff --git a/components/date_picker/Calendar.js b/components/date_picker/Calendar.js
index b8628fe7..cb4ff1be 100644
--- a/components/date_picker/Calendar.js
+++ b/components/date_picker/Calendar.js
@@ -1,8 +1,7 @@
import React, { Component, PropTypes } from 'react';
import CssTransitionGroup from 'react-addons-css-transition-group';
-import { SlideLeft, SlideRight } from '../animations';
+import { range, getAnimationModule } from '../utils/utils';
import time from '../utils/time.js';
-import utils from '../utils/utils.js';
import CalendarMonth from './CalendarMonth.js';
const DIRECTION_STEPS = { left: -1, right: 1 };
@@ -104,7 +103,7 @@ const factory = (IconButton) => {
renderYears () {
return (
- {utils.range(1900, 2100).map(year => (
+ {range(1900, 2100).map(year => (
{
renderMonths () {
const { theme } = this.props;
- const animation = this.state.direction === 'left' ? SlideLeft : SlideRight;
+ const animation = this.state.direction === 'left' ? 'slideLeft' : 'slideRight';
+ const animationModule = getAnimationModule(animation, theme);
return (
-
+
time.getDayOfWeekLetter(d, this.props.locale));
+ const days = range(0, 7).map(d => time.getDayOfWeekLetter(d, this.props.locale));
const source = (this.props.sundayFirstDayOfWeek) ? days : [...days.slice(1), days[0]];
return source.map((d, i) => ({d} ));
}
renderDays () {
- return utils.range(1, time.getDaysInMonth(this.props.viewDate) + 1).map(i => {
+ return range(1, time.getDaysInMonth(this.props.viewDate) + 1).map(i => {
const date = new Date(this.props.viewDate.getFullYear(), this.props.viewDate.getMonth(), i);
return (
.inputElement {
+ cursor: pointer;
+}
+
+.header {
+ background-color: var(--datepicker-primary-color);
+ color: var(--datepicker-primary-contrast-color);
+ cursor: pointer;
+ padding: calc(1.6 * var(--unit)) calc(2 * var(--unit));
+}
+
+.year {
+ display: inline-block;
+ font-size: var(--datepicker-year-font-size);
+ transition: opacity, font-size var(--animation-duration) var(--animation-curve-default);
+}
+
+.date {
+ display: block;
+ font-size: calc(3.4 * var(--unit));
+ font-weight: 400;
+ font-weight: var(--font-weight-semi-bold);
+ line-height: calc(4 * var(--unit));
+ margin: 0;
+ text-transform: capitalize;
+ transition: opacity var(--animation-duration) var(--animation-curve-default);
+}
+
+.calendarWrapper {
+ padding: var(--unit) calc(0.5 * var(--unit)) 0;
+}
+
+.yearsDisplay {
+ & .date {
+ opacity: var(--datepicker-inactive-opacity);
+ }
+
+ & .year {
+ font-size: var(--font-size-normal);
+ }
+}
+
+.monthsDisplay {
+ & .year {
+ opacity: var(--datepicker-inactive-opacity);
+ }
+}
+
+.dialog {
+ width: var(--datepicker-dialog-width);
+
+ & > [role='body'] {
+ padding: 0;
+ }
+
+ & > [role='navigation'] > .button {
+ color: var(--datepicker-primary-color);
+
+ &:hover {
+ background: var(--datepicker-primary-hover-color);
+ }
+
+ &:focus:not(:active) {
+ background: var(--datepicker-primary-hover-color);
+ }
+ }
+}
+
+.calendar {
+ background: var(--calendar-primary-contrast-color);
+ font-size: var(--font-size-small);
+ height: var(--calendar-total-height);
+ line-height: var(--calendar-row-height);
+ overflow: hidden;
+ position: relative;
+ text-align: center;
+
+ & .prev,
+ & .next {
+ cursor: pointer;
+ height: calc(3.6 * var(--unit));
+ opacity: 0.7;
+ position: absolute;
+ top: 0;
+ z-index: var(--z-index-high);
+ }
+
+ & .prev {
+ left: 0;
+ }
+
+ & .next {
+ right: 0;
+ }
+}
+
+.title {
+ display: inline-block;
+ font-weight: 500;
+ line-height: var(--calendar-row-height);
+}
+
+.years {
+ font-size: var(--font-size-big);
+ height: 100%;
+ list-style: none;
+ margin: 0;
+ overflow-y: auto;
+ padding: 0;
+
+ & > li {
+ cursor: pointer;
+ line-height: 2.4;
+
+ &.active {
+ color: var(--calendar-primary-color);
+ font-size: var(--calendar-year-font-size);
+ font-weight: var(--font-weight-semi-bold);
+ }
+ }
+}
+
+.week {
+ display: flex;
+ flex-wrap: wrap;
+ font-size: var(--calendar-day-font-size);
+ height: var(--calendar-row-height);
+ line-height: var(--calendar-row-height);
+ opacity: 0.5;
+
+ & > span {
+ flex: 0 0 calc(100% / 7);
+ }
+}
+
+.days {
+ display: flex;
+ flex-wrap: wrap;
+ font-size: var(--calendar-day-font-size);
+}
+
+.day {
+ flex: 0 0 calc(100% / 7);
+ padding: var(--calendar-day-padding-topbottom) var(--calendar-day-padding-leftright);
+
+ & > span {
+ border-radius: 50%;
+ display: inline-block;
+ height: var(--calendar-row-height);
+ line-height: var(--calendar-row-height);
+ width: var(--calendar-row-height);
+ }
+
+ &:hover:not(.active):not(.disabled) > span {
+ background: var(--calendar-primary-hover-color);
+ color: var(--calendar-primary-contrast-color);
+ }
+
+ &.active > span {
+ background: var(--calendar-primary-color);
+ color: var(--calendar-primary-contrast-color);
+ }
+
+ &:hover:not(.disabled) > span {
+ cursor: pointer;
+ }
+
+ &.disabled {
+ opacity: var(--calendar-day-disable-opacity);
+ }
+}
+
+.month {
+ background-color: var(--calendar-primary-contrast-color);
+}
+
+.slideRightEnter,
+.slideRightLeave {
+ position: absolute;
+}
+
+.slideRightEnterActive,
+.slideRightLeaveActive {
+ transition-duration: 350ms;
+ transition-property: transform, opacity;
+ transition-timing-function: ease-in-out;
+}
+
+.slideRightEnter {
+ opacity: 0;
+ transform: translateX(100%);
+
+ &.slideRightEnterActive {
+ opacity: 1;
+ transform: translateX(0);
+ }
+}
+
+.slideRightLeave {
+ opacity: 1;
+ transform: translateX(0);
+
+ &.slideRightLeaveActive {
+ opacity: 0;
+ transform: translateX(-100%);
+ }
+}
+
+.slideLeftEnter,
+.slideLeftLeave {
+ position: absolute;
+ transition-duration: 0.35s;
+ transition-property: transform, opacity;
+ transition-timing-function: ease-in-out;
+}
+
+.slideLeftEnter {
+ opacity: 0;
+ transform: translate3d(-100%, 0, 0);
+
+ &.slideLeftEnterActive {
+ opacity: 1;
+ transform: translate3d(0, 0, 0);
+ }
+}
+
+.slideLeftLeave {
+ opacity: 1;
+ transform: translate3d(0, 0, 0);
+
+ &.slideLeftLeaveActive {
+ opacity: 0;
+ transform: translate3d(100%, 0, 0);
+ }
+}
diff --git a/components/date_picker/theme.scss b/components/date_picker/theme.scss
deleted file mode 100644
index a1ee3915..00000000
--- a/components/date_picker/theme.scss
+++ /dev/null
@@ -1,156 +0,0 @@
-@import "../colors";
-@import "../globals";
-@import "../mixins";
-@import "./config";
-
-.input:not(.disabled) > .inputElement {
- cursor: pointer;
-}
-
-.header {
- padding: 1.6 * $unit 2 * $unit;
- color: $datepicker-primary-contrast-color;
- cursor: pointer;
- background-color: $datepicker-primary-color;
-}
-
-.year {
- display: inline-block;
- font-size: $datepicker-year-font-size;
- transition: opacity, font-size $animation-duration $animation-curve-default;
-}
-
-.date {
- display: block;
- font-weight: $font-weight-semi-bold;
- text-transform: capitalize;
- transition: opacity $animation-duration $animation-curve-default;
-}
-
-.calendarWrapper {
- padding: $unit .5 * $unit 0;
-}
-
-.yearsDisplay {
- .date {
- opacity: $datepicker-inactive-opacity;
- }
- .year {
- font-size: $font-size-normal;
- }
-}
-
-.monthsDisplay {
- .year {
- opacity: $datepicker-inactive-opacity;
- }
-}
-
-.dialog {
- width: $datepicker-dialog-width;
- > [role="body"] {
- padding: 0;
- }
- > [role="navigation"] > .button {
- color: $datepicker-primary-color;
- &:hover {
- background: $datepicker-primary-hover-color;
- }
- &:focus:not(:active) {
- background: $datepicker-primary-hover-color;
- }
- }
-}
-
-.calendar {
- position: relative;
- height: $calendar-total-height;
- overflow: hidden;
- font-size: $font-size-small;
- line-height: $calendar-row-height;
- text-align: center;
- background: $calendar-primary-contrast-color;
- .prev, .next {
- position: absolute;
- top: 0;
- z-index: $z-index-high;
- height: 3.6 * $unit;
- cursor: pointer;
- opacity: .7;
- }
- .prev {
- left: 0;
- }
- .next {
- right: 0;
- }
-}
-
-.title {
- display: inline-block;
- font-weight: 500;
- line-height: $calendar-row-height;
-}
-
-.years {
- height: 100%;
- overflow-y: auto;
- font-size: $font-size-big;
- > li {
- line-height: 2.4;
- cursor: pointer;
- &.active {
- font-size: $calendar-year-font-size;
- font-weight: $font-weight-semi-bold;
- color: $calendar-primary-color;
- }
- }
-}
-
-.week {
- display: flex;
- height: $calendar-row-height;
- flex-wrap: wrap;
- font-size: $calendar-day-font-size;
- line-height: $calendar-row-height;
- opacity: .5;
- > span {
- flex: 0 0 (100% / 7);
- }
-}
-
-.days {
- display: flex;
- flex-wrap: wrap;
- font-size: $calendar-day-font-size;
-}
-
-.day {
- flex: 0 0 (100% / 7);
- padding: $calendar-day-padding-topbottom $calendar-day-padding-leftright;
- > span {
- display: inline-block;
- width: $calendar-row-height;
- height: $calendar-row-height;
- line-height: $calendar-row-height;
- border-radius: 50%;
- }
- &:hover:not(.active):not(.disabled) > span {
- color: $calendar-primary-contrast-color;
- background: $calendar-primary-hover-color;
- }
- &.active > span {
- color: $calendar-primary-contrast-color;
- background: $calendar-primary-color;
- }
- &:hover:not(.disabled) > span {
- cursor: pointer;
- }
- &.disabled {
- opacity: $calendar-day-disable-opacity;
- }
-}
-
-.month {
- background-color: $calendar-primary-contrast-color;
-}
diff --git a/components/dialog/Dialog.js b/components/dialog/Dialog.js
index 7e49f274..b788a679 100644
--- a/components/dialog/Dialog.js
+++ b/components/dialog/Dialog.js
@@ -2,6 +2,7 @@ import React, { PropTypes } from 'react';
import { themr } from 'react-css-themr';
import classnames from 'classnames';
import { DIALOG } from '../identifiers.js';
+import Portal from '../hoc/Portal.js';
import ActivableRenderer from '../hoc/ActivableRenderer.js';
import InjectButton from '../button/Button.js';
import InjectOverlay from '../overlay/Overlay.js';
@@ -18,14 +19,15 @@ const factory = (Overlay, Button) => {
}, props.className);
return (
-
+
+
{props.title ? {props.title} : null}
@@ -38,7 +40,7 @@ const factory = (Overlay, Button) => {
: null
}
-
+
);
};
@@ -58,7 +60,8 @@ const factory = (Overlay, Button) => {
button: PropTypes.string,
dialog: PropTypes.string,
navigation: PropTypes.string,
- title: PropTypes.string
+ title: PropTypes.string,
+ wrapper: PropTypes.string
}),
title: PropTypes.string,
type: PropTypes.string
diff --git a/components/dialog/_config.scss b/components/dialog/_config.scss
deleted file mode 100644
index c522075c..00000000
--- a/components/dialog/_config.scss
+++ /dev/null
@@ -1,6 +0,0 @@
-$dialog-border-radius: .2 * $unit !default;
-$dialog-color-title: $color-black !default;
-$dialog-color-white: $color-white !default;
-$dialog-content-padding: 2.4 * $unit !default;
-$dialog-navigation-padding: .8 * $unit !default;
-$dialog-translate-y: 4 * $unit !default;
diff --git a/components/dialog/config.css b/components/dialog/config.css
new file mode 100644
index 00000000..77f0b8c9
--- /dev/null
+++ b/components/dialog/config.css
@@ -0,0 +1,8 @@
+:root {
+ --dialog-border-radius: calc(0.2 * var(--unit));
+ --dialog-color-title: var(--color-black);
+ --dialog-color-white: var(--color-white);
+ --dialog-content-padding: calc(2.4 * var(--unit));
+ --dialog-navigation-padding: calc(0.8 * var(--unit));
+ --dialog-translate-y: calc(4 * var(--unit));
+}
diff --git a/components/dialog/index.js b/components/dialog/index.js
index 1236aebb..2720543e 100644
--- a/components/dialog/index.js
+++ b/components/dialog/index.js
@@ -3,7 +3,7 @@ import { DIALOG } from '../identifiers.js';
import { dialogFactory } from './Dialog.js';
import Overlay from '../overlay';
import Button from '../button';
-import theme from './theme.scss';
+import theme from './theme.css';
const Dialog = dialogFactory(Overlay, Button);
const ThemedDialog = themr(DIALOG, theme)(Dialog);
diff --git a/components/dialog/readme.md b/components/dialog/readme.md
index 5b26bf5e..098eed57 100644
--- a/components/dialog/readme.md
+++ b/components/dialog/readme.md
@@ -69,3 +69,4 @@ Notice that the `fullscreen` option only applies on mobile devices with small sc
| `dialog` | Used for the root element.|
| `navigation` | Used for the navigation element when it implements actions.|
| `title` | Used for the title element of the dialog.|
+| `wrapper` | A wrapper class for the top of the root.|
diff --git a/components/dialog/theme.css b/components/dialog/theme.css
new file mode 100644
index 00000000..903a3d71
--- /dev/null
+++ b/components/dialog/theme.css
@@ -0,0 +1,110 @@
+@import '../colors.css';
+@import '../variables.css';
+@import '../media.css';
+@import './config.css';
+
+.wrapper {
+ align-items: center;
+ composes: reset from '../helpers.css';
+ display: flex;
+ height: 100vh;
+ justify-content: center;
+ position: fixed;
+ top: 0;
+ width: 100vw;
+ z-index: var(--z-index-higher);
+}
+
+.dialog {
+ background-color: var(--dialog-color-white);
+ border-radius: var(--dialog-border-radius);
+ box-shadow: var(--zdepth-shadow-5);
+ display: flex;
+ flex-direction: column;
+ max-height: 96vh;
+ max-width: 96vw;
+ opacity: 0;
+ transform: translateY(calc(-1 * var(--dialog-translate-y)));
+ transition:
+ opacity var(--animation-duration) var(--animation-curve-default),
+ transform var(--animation-duration) var(--animation-curve-default);
+ transition-delay: var(--animation-delay);
+
+ &.active {
+ opacity: 1;
+ transform: translateY(0%);
+ }
+}
+
+.small {
+ width: 30vw;
+
+ @media screen and (--sm-tablet-viewport) {
+ width: 50vw;
+ }
+
+ @media screen and (--xs-viewport) {
+ width: 75vw;
+ }
+}
+
+.normal {
+ width: 50vw;
+
+ @media screen and (--xs-viewport) {
+ width: 96vw;
+ }
+}
+
+.large {
+ width: 96vw;
+}
+
+.fullscreen {
+ width: 96vw;
+
+ @media screen and (--xs-viewport) {
+ border-radius: 0;
+ max-height: 100vh;
+ max-width: 100vw;
+ min-height: 100vh;
+ width: 100vw;
+ }
+}
+
+.title {
+ color: var(--dialog-color-title);
+ flex-grow: 0;
+ font-size: calc(2 * var(--unit));
+ font-weight: 500;
+ letter-spacing: 0.02em;
+ line-height: 1;
+ margin: 0 0 calc(1.6 * var(--unit));
+}
+
+.body {
+ color: var(--color-text-secondary);
+ flex-grow: 2;
+ padding: var(--dialog-content-padding);
+
+ & p {
+ font-size: calc(1.4 * var(--unit));
+ font-weight: 400;
+ letter-spacing: 0;
+ line-height: calc(2.4 * var(--unit));
+ margin: 0;
+ }
+}
+
+.navigation {
+ flex-grow: 0;
+ padding: var(--dialog-navigation-padding);
+ text-align: right;
+}
+
+.button {
+ margin-left: var(--dialog-navigation-padding);
+ min-width: 0;
+ padding-left: var(--dialog-navigation-padding);
+ padding-right: var(--dialog-navigation-padding);
+}
diff --git a/components/dialog/theme.scss b/components/dialog/theme.scss
deleted file mode 100644
index 8757bdf0..00000000
--- a/components/dialog/theme.scss
+++ /dev/null
@@ -1,86 +0,0 @@
-@import "../colors";
-@import "../globals";
-@import "../mixins";
-@import "./config";
-
-.dialog {
- display: flex;
- max-width: 96vw;
- max-height: 96vh;
- flex-direction: column;
- background-color: $dialog-color-white;
- border-radius: $dialog-border-radius;
- box-shadow: $zdepth-shadow-5;
- opacity: 0;
- transition-delay: $animation-delay;
- transition-timing-function: $animation-curve-default;
- transition-duration: $animation-duration;
- transition-property: opacity, transform;
- transform: translateY(-$dialog-translate-y);
- &.active {
- opacity: 1;
- transform: translateY(0%);
- }
-}
-
-.small {
- width: 30vw;
-
- @media screen and (max-width: $layout-breakpoint-sm-tablet) {
- width: 50vw;
- }
-
- @media screen and (max-width: $layout-breakpoint-xs) {
- width: 75vw;
- }
-}
-
-.normal {
- width: 50vw;
-
- @media screen and (max-width: $layout-breakpoint-xs) {
- width: 96vw;
- }
-}
-
-.large {
- width: 96vw;
-}
-
-.fullscreen {
- width: 96vw;
-
- @media screen and (max-width: $layout-breakpoint-xs) {
- width: 100vw;
- max-width: 100vw;
- min-height: 100vh;
- max-height: 100vh;
- border-radius: 0;
- }
-}
-
-.title {
- @include typo-title();
- flex-grow: 0;
- margin-bottom: 1.6 * $unit;
- color: $dialog-color-title;
-}
-
-.body {
- flex-grow: 2;
- padding: $dialog-content-padding;
- color: $color-text-secondary;
-}
-
-.navigation {
- flex-grow: 0;
- padding: $dialog-navigation-padding;
- text-align: right;
-}
-
-.button {
- min-width: 0;
- padding-right: $dialog-navigation-padding;
- padding-left: $dialog-navigation-padding;
- margin-left: $dialog-navigation-padding;
-}
diff --git a/components/drawer/Drawer.js b/components/drawer/Drawer.js
index c2b3ae4a..000ea09f 100644
--- a/components/drawer/Drawer.js
+++ b/components/drawer/Drawer.js
@@ -1,46 +1,74 @@
import React, { PropTypes } from 'react';
import { themr } from 'react-css-themr';
import classnames from 'classnames';
+import Portal from '../hoc/Portal.js';
import { DRAWER } from '../identifiers.js';
import ActivableRenderer from '../hoc/ActivableRenderer.js';
import InjectOverlay from '../overlay/Overlay.js';
const factory = (Overlay) => {
- const Drawer = ({ active, children, className, onOverlayClick, theme, type }) => {
+ const Drawer = ({
+ active,
+ children,
+ className,
+ insideTree,
+ onOverlayClick,
+ theme,
+ type,
+ withOverlay
+ }) => {
const _className = classnames([theme.drawer, theme[type]], {
[theme.active]: active
}, className);
- return (
-
-
-
+ const content = (
+
);
+
+ return React.createElement(insideTree ? 'div' : Portal, {
+ className: theme.wrapper,
+ children: [
+ withOverlay && (
+
+ ),
+ content
+ ]
+ });
};
Drawer.propTypes = {
active: PropTypes.bool,
children: PropTypes.node,
className: PropTypes.string,
+ insideTree: PropTypes.bool,
onOverlayClick: PropTypes.func,
theme: PropTypes.shape({
active: PropTypes.string,
- content: PropTypes.string,
drawer: PropTypes.string,
left: PropTypes.string,
right: PropTypes.string
}),
- type: PropTypes.oneOf(['left', 'right'])
+ type: PropTypes.oneOf([
+ 'left', 'right'
+ ]),
+ withOverlay: PropTypes.bool
};
Drawer.defaultProps = {
active: false,
className: '',
- type: 'left'
+ insideTree: false,
+ type: 'left',
+ withOverlay: true
};
return ActivableRenderer()(Drawer);
diff --git a/components/drawer/_config.scss b/components/drawer/_config.scss
deleted file mode 100644
index 2401bc69..00000000
--- a/components/drawer/_config.scss
+++ /dev/null
@@ -1,4 +0,0 @@
-$drawer-background-color: $palette-grey-50 !default;
-$drawer-border-color: $palette-grey-300 !default;
-$drawer-text-color: $palette-grey-800 !default;
-$drawer-width: 24 * $unit !default;
diff --git a/components/drawer/config.css b/components/drawer/config.css
new file mode 100644
index 00000000..afbdcfbf
--- /dev/null
+++ b/components/drawer/config.css
@@ -0,0 +1,8 @@
+:root {
+ --drawer-background-color: var(--palette-grey-50);
+ --drawer-border-color: var(--palette-grey-300);
+ --drawer-text-color: var(--palette-grey-800);
+ --drawer-width: calc(24 * var(--unit));
+ --drawer-desktop-width: calc(4 * var(--standard-increment-desktop));
+ --drawer-mobile-width: calc(5 * var(--standard-increment-mobile));
+}
diff --git a/components/drawer/index.js b/components/drawer/index.js
index 8196b783..cd5542c7 100644
--- a/components/drawer/index.js
+++ b/components/drawer/index.js
@@ -2,7 +2,7 @@ import { themr } from 'react-css-themr';
import { DRAWER } from '../identifiers.js';
import { Overlay } from '../overlay';
import { drawerFactory } from './Drawer.js';
-import theme from './theme.scss';
+import theme from './theme.css';
const Drawer = drawerFactory(Overlay);
const ThemedDrawer = themr(DRAWER, theme)(Drawer);
diff --git a/components/drawer/readme.md b/components/drawer/readme.md
index 3c2f795c..159fc80a 100644
--- a/components/drawer/readme.md
+++ b/components/drawer/readme.md
@@ -37,8 +37,10 @@ If you want to provide a theme via context, the component key is `RTDrawer`.
|:-----|:-----|:-----|:-----|
| `active` | `Boolean` | `false` | If true, the drawer will be visible.|
| `className` | `String` | `''` | Sets a class to give customized styles to the drawer.|
+| `insideTree` | `Boolean` | `false` | If true the Drawer is rendered inside the normal tree.|
| `onOverlayClick` | `Function` | | Callback function to be invoked when the overlay is clicked.|
| `type` | `String` | `left` | Type of drawer. It can be `left` or `right` to display the drawer on the left or right side of the screen.|
+| `withOverlay` | `String` | `true` | If true display an Overlay that locks the scroll when the Drawer is active.|
## Theme
@@ -49,3 +51,4 @@ If you want to provide a theme via context, the component key is `RTDrawer`.
| `drawer` | Root class.|
| `left` | Added to the root class when drawer is to the left.|
| `right` | Added to the root class when drawer is to the right.|
+| `wrapper` | A wrapper class for the top of the root.|
diff --git a/components/drawer/theme.css b/components/drawer/theme.css
new file mode 100644
index 00000000..f38ca6c2
--- /dev/null
+++ b/components/drawer/theme.css
@@ -0,0 +1,58 @@
+@import '../colors.css';
+@import '../variables.css';
+@import '../media.css';
+@import './config.css';
+
+.wrapper {
+ position: relative;
+ z-index: var(--z-index-higher);
+}
+
+.drawer {
+ background-color: var(--drawer-background-color);
+ box-shadow: var(--shadow-2p);
+ color: var(--drawer-text-color);
+ composes: reset from '../helpers.css';
+ display: block;
+ height: 100vh;
+ overflow-x: hidden;
+ overflow-y: auto;
+ pointer-events: none;
+ position: fixed;
+ top: 0;
+ transform-style: preserve-3d;
+ transition: transform var(--animation-duration) var(--animation-curve-default);
+ transition-delay: 0s;
+ width: var(--drawer-mobile-width);
+ will-change: transform;
+
+ &.active {
+ pointer-events: all;
+ transform: translateX(0);
+ transition-delay: var(--animation-delay);
+ }
+
+ &.right {
+ border-left: 1px solid var(--drawer-border-color);
+ right: 0;
+
+ &:not(.active) {
+ transform: translateX(100%);
+ }
+ }
+
+ &.left {
+ border-right: 1px solid var(--drawer-border-color);
+ left: 0;
+
+ &:not(.active) {
+ transform: translateX(calc(-1 * 100%));
+ }
+ }
+}
+
+@media screen and (--larger-than-xs-viewport) {
+ .drawer {
+ width: var(--drawer-desktop-width);
+ }
+}
diff --git a/components/drawer/theme.scss b/components/drawer/theme.scss
deleted file mode 100644
index a089640a..00000000
--- a/components/drawer/theme.scss
+++ /dev/null
@@ -1,43 +0,0 @@
-@import "../colors";
-@import "../globals";
-@import "../mixins";
-@import "./config";
-
-.drawer {
- @include shadow-2dp();
- position: absolute;
- top: 0;
- display: block;
- width: $drawer-width;
- height: 100%;
- overflow-x: hidden;
- overflow-y: auto;
- color: $drawer-text-color;
- pointer-events: none;
- background-color: $drawer-background-color;
- transition-delay: 0s;
- transition-timing-function: $animation-curve-default;
- transition-duration: $animation-duration;
- transition-property: transform;
- transform-style: preserve-3d;
- will-change: transform;
- &.active {
- pointer-events: all;
- transition-delay: $animation-delay;
- transform: translateX(0);
- }
- &.right {
- right: 0;
- border-left: 1px solid $drawer-border-color;
- &:not(.active) {
- transform: translateX(100%);
- }
- }
- &.left {
- left: 0;
- border-right: 1px solid $drawer-border-color;
- &:not(.active) {
- transform: translateX(- 100%);
- }
- }
-}
diff --git a/components/dropdown/Dropdown.js b/components/dropdown/Dropdown.js
index 5f28dbdc..096af703 100644
--- a/components/dropdown/Dropdown.js
+++ b/components/dropdown/Dropdown.js
@@ -194,11 +194,10 @@ const factory = (Input) => {
data-react-toolbox='dropdown'
onBlur={this.handleBlur}
onFocus={this.handleFocus}
- tabIndex="0"
>
.values {
+ max-height: 0;
+ visibility: hidden;
+ }
+ }
+
+ &.active {
+ & > .label,
+ & > .value {
+ opacity: 0.5;
+ }
+
+ & > .values {
+ box-shadow: var(--zdepth-shadow-1);
+ max-height: var(--dropdown-overflow-max-height);
+ visibility: visible;
+ }
+ }
+
+ &:not(.up) > .values {
+ bottom: auto;
+ top: 0;
+ }
+
+ &.up > .values {
+ bottom: 0;
+ top: auto;
+ }
+
+ &.disabled {
+ cursor: normal;
+ pointer-events: none;
+ }
+}
+
+.value {
+ & > input {
+ cursor: pointer;
+ }
+
+ &::after {
+ border-left: var(--dropdown-value-border-size) solid transparent;
+ border-right: var(--dropdown-value-border-size) solid transparent;
+ border-top: var(--dropdown-value-border-size) solid var(--input-text-bottom-border-color);
+ content: '';
+ height: 0;
+ pointer-events: none;
+ position: absolute;
+ right: var(--input-chevron-offset);
+ top: 50%;
+ transition: transform var(--animation-duration) var(--animation-curve-default);
+ width: 0;
+ }
+}
+
+.field {
+ cursor: pointer;
+ padding: var(--input-padding) 0;
+ position: relative;
+
+ &.errored {
+ padding-bottom: 0;
+
+ & > .label {
+ color: var(--input-text-error-color);
+ }
+
+ & > .templateValue {
+ border-bottom: 1px solid var(--input-text-error-color);
+ }
+
+ & > .label > .required {
+ color: var(--input-text-error-color);
+ }
+ }
+
+ &.disabled {
+ cursor: normal;
+ pointer-events: none;
+
+ & > .templateValue {
+ border-bottom-style: dotted;
+ opacity: 0.7;
+ }
+ }
+}
+
+.templateValue {
+ background-color: var(--input-text-background-color);
+ border-bottom: 1px solid var(--input-text-bottom-border-color);
+ color: var(--color-text);
+ min-height: var(--input-field-height);
+ padding: var(--input-field-padding) 0;
+ position: relative;
+}
+
+.label {
+ color: var(--input-text-label-color);
+ font-size: var(--input-label-font-size);
+ left: 0;
+ line-height: var(--input-field-font-size);
+ position: absolute;
+ top: var(--input-focus-label-top);
+
+ & .required {
+ color: var(--input-text-error-color);
+ }
+}
+
+.error {
+ color: var(--input-text-error-color);
+ font-size: var(--input-label-font-size);
+ line-height: var(--input-underline-height);
+ margin-bottom: calc(-1 * var(--input-underline-height));
+}
+
+.values {
+ background-color: var(--dropdown-color-white);
+ border-radius: var(--dropdown-value-border-radius);
+ list-style: none;
+ margin: 0;
+ overflow-y: auto;
+ padding: 0;
+ position: absolute;
+ transition-duration: var(--animation-duration);
+ transition-property: max-height, box-shadow;
+ transition-timing-function: var(--animation-curve-default);
+ width: 100%;
+ z-index: var(--z-index-high);
+
+ & > * {
+ cursor: pointer;
+ overflow: hidden;
+ padding: var(--unit);
+ position: relative;
+
+ &:hover:not(.disabled) {
+ background-color: var(--dropdown-value-hover-background);
+ }
+
+ &.selected {
+ color: var(--dropdown-color-primary);
+ }
+
+ .disabled {
+ color: var(--dropdown-color-disabled);
+ cursor: not-allowed;
+ }
+ }
+
+ &::-webkit-scrollbar {
+ height: 0;
+ width: 0;
+ }
+}
diff --git a/components/dropdown/theme.scss b/components/dropdown/theme.scss
deleted file mode 100644
index 0401c348..00000000
--- a/components/dropdown/theme.scss
+++ /dev/null
@@ -1,142 +0,0 @@
-@import "../colors";
-@import "../globals";
-@import "../mixins";
-@import "../input/config";
-@import "./config";
-
-.dropdown {
- position: relative;
- &:not(.active) {
- > .values {
- max-height: 0;
- visibility: hidden;
- }
- }
- &.active {
- > .label, > .value {
- opacity: .5;
- }
- > .values {
- max-height: $dropdown-overflow-max-height;
- visibility: visible;
- box-shadow: $zdepth-shadow-1;
- }
- }
- &:not(.up) > .values {
- top: 0;
- bottom: auto;
- }
- &.up > .values {
- top: auto;
- bottom: 0;
- }
- &.disabled {
- pointer-events: none;
- cursor: normal;
- }
-}
-
-.value {
- > input {
- cursor: pointer;
- }
- &:after {
- $size: ($input-field-height / 7);
- $border: $size solid transparent;
- position: absolute;
- top: 50%;
- right: $input-chevron-offset;
- width: 0;
- height: 0;
- pointer-events: none;
- content: "";
- border-top: $size solid $input-text-bottom-border-color;
- border-right: $border;
- border-left: $border;
- transition: transform $animation-duration $animation-curve-default;
- }
-}
-
-.field {
- position: relative;
- padding: $input-padding 0;
- cursor: pointer;
- &.errored {
- padding-bottom: 0;
- > .label {
- color: $input-text-error-color;
- }
- > .templateValue {
- border-bottom: 1px solid $input-text-error-color;
- }
- > .label > .required {
- color: $input-text-required-color;
- }
- }
- &.disabled {
- pointer-events: none;
- cursor: normal;
- > .templateValue {
- border-bottom-style: dotted;
- opacity: .7;
- }
- }
-}
-
-.templateValue {
- position: relative;
- min-height: $input-field-height;
- padding: $input-field-padding 0;
- color: $color-text;
- background-color: $input-text-background-color;
- border-bottom: 1px solid $input-text-bottom-border-color;
-}
-
-.label {
- position: absolute;
- top: $input-focus-label-top;
- left: 0;
- font-size: $input-label-font-size;
- line-height: $input-field-font-size;
- color: $input-text-label-color;
- .required {
- color: $input-text-required-color;
- }
-}
-
-.error {
- margin-bottom: - $input-underline-height;
- font-size: $input-label-font-size;
- line-height: $input-underline-height;
- color: $input-text-error-color;
-}
-
-.values {
- @include no-webkit-scrollbar;
- position: absolute;
- z-index: $z-index-high;
- width: 100%;
- overflow-y: auto;
- list-style: none;
- background-color: $dropdown-color-white;
- border-radius: $dropdown-value-border-radius;
- transition-timing-function: $animation-curve-default;
- transition-duration: $animation-duration;
- transition-property: max-height, box-shadow;
- > * {
- position: relative;
- padding: $unit;
- overflow: hidden;
- cursor: pointer;
- &:hover:not(.disabled) {
- background-color: $dropdown-value-hover-background;
- }
- &.selected {
- color: $dropdown-color-primary;
- }
- &.disabled {
- color: $dropdown-color-disabled;
- cursor: not-allowed;
- }
- }
-}
diff --git a/components/helpers.css b/components/helpers.css
new file mode 100644
index 00000000..b9482141
--- /dev/null
+++ b/components/helpers.css
@@ -0,0 +1,18 @@
+@import './variables.css';
+
+.reset {
+ box-sizing: border-box;
+ font-family: var(--preferred-font);
+ -webkit-font-smoothing: antialiased;
+ font-smoothing: antialiased;
+ text-size-adjust: 100%;
+
+ & *,
+ & *::after,
+ & *::before {
+ box-sizing: border-box;
+ -webkit-font-smoothing: antialiased;
+ font-smoothing: antialiased;
+ text-size-adjust: 100%;
+ }
+}
diff --git a/components/hoc/Portal.js b/components/hoc/Portal.js
index 015dcba8..0e28a2d2 100644
--- a/components/hoc/Portal.js
+++ b/components/hoc/Portal.js
@@ -4,11 +4,13 @@ import ReactDOM from 'react-dom';
class Portal extends Component {
static propTypes = {
children: PropTypes.any,
+ className: PropTypes.string,
container: PropTypes.any,
lockBody: PropTypes.bool
}
static defaultProps = {
+ className: '',
lockBody: true
}
@@ -49,11 +51,13 @@ class Portal extends Component {
this._portalContainerNode = null;
}
- _renderOverlay () {
- const overlay = !this.props.children
- ? null
- : React.Children.only(this.props.children);
+ _getOverlay () {
+ if (!this.props.children) return null;
+ return {this.props.children}
;
+ }
+ _renderOverlay () {
+ const overlay = this._getOverlay();
if (overlay !== null) {
this._mountOverlayTarget();
this._overlayInstance = ReactDOM.unstable_renderSubtreeIntoContainer(
diff --git a/components/identifiers.js b/components/identifiers.js
index fa5902dc..eb5cab56 100644
--- a/components/identifiers.js
+++ b/components/identifiers.js
@@ -7,6 +7,7 @@ export const CHIP = 'RTChip';
export const CHECKBOX = 'RTCheckbox';
export const DATE_PICKER = 'RTDatePicker';
export const DIALOG = 'RTDialog';
+export const DRAWER = 'RTDrawer';
export const DROPDOWN = 'RTDropdown';
export const INPUT = 'RTInput';
export const LAYOUT = 'RTLayout';
diff --git a/components/input/_config.scss b/components/input/_config.scss
deleted file mode 100644
index ff9f58cd..00000000
--- a/components/input/_config.scss
+++ /dev/null
@@ -1,20 +0,0 @@
-$input-padding: 2 * $unit !default;
-$input-field-padding: .8 * $unit !default;
-$input-field-font-size: 1.6 * $unit !default;
-$input-field-height: $input-field-padding * 2 + $input-field-font-size * 1.4 !default;
-$input-label-font-size: 1.2 * $unit !default;
-$input-focus-label-top: .6 * $unit !default;
-$input-text-background-color: transparent !default;
-$input-text-label-color: rgba($color-black, 0.26) !default;
-$input-text-bottom-border-color: rgba($color-black, 0.12) !default;
-$input-text-highlight-color: $color-primary !default;
-$input-text-disabled-color: $input-text-bottom-border-color !default;
-$input-text-disabled-text-color: $input-text-label-color !default;
-$input-text-error-color: rgb(222, 50, 38) !default;
-$input-text-required-color: rgb(222, 50, 38) !default;
-$input-underline-height: 2 * $unit !default;
-$input-icon-font-size: 2.4 * $unit !default;
-$input-icon-size: 2 * $input-icon-font-size !default;
-$input-icon-offset: 1.6 * $unit !default;
-$input-chevron-offset: .8 * $unit !default;
-$input-hint-opacity: 1 !default;
diff --git a/components/input/config.css b/components/input/config.css
new file mode 100644
index 00000000..adfe89c9
--- /dev/null
+++ b/components/input/config.css
@@ -0,0 +1,22 @@
+:root {
+ --input-padding: calc(2 * var(--unit));
+ --input-field-padding: calc(0.8 * var(--unit));
+ --input-field-font-size: calc(1.6 * var(--unit));
+ --input-field-height: calc(var(--input-field-padding) * 2 + var(--input-field-font-size) * 1.4);
+ --input-label-font-size: calc(1.2 * var(--unit));
+ --input-focus-label-top: calc(0.6 * var(--unit));
+ --input-text-background-color: transparent;
+ --input-text-label-color: color(var(--color-black) a(26%));
+ --input-text-bottom-border-color: color(var(--color-black) a(12%));
+ --input-text-highlight-color: var(--color-primary);
+ --input-text-disabled-color: var(--input-text-bottom-border-color);
+ --input-text-disabled-text-color: var(--input-text-label-color);
+ --input-text-error-color: rgb(222, 50, 38);
+ --input-text-required-color: rgb(222, 50, 38);
+ --input-underline-height: calc(2 * var(--unit));
+ --input-icon-font-size: calc(2.4 * var(--unit));
+ --input-icon-size: calc(2 * var(--input-icon-font-size));
+ --input-icon-offset: calc(1.6 * var(--unit));
+ --input-chevron-offset: calc(0.8 * var(--unit));
+ --input-hint-opacity: 1;
+}
diff --git a/components/input/index.js b/components/input/index.js
index fc447423..a079ffcd 100644
--- a/components/input/index.js
+++ b/components/input/index.js
@@ -2,7 +2,7 @@ import { INPUT } from '../identifiers.js';
import { themr } from 'react-css-themr';
import { inputFactory } from './Input.js';
import FontIcon from '../font_icon/FontIcon.js';
-import theme from './theme.scss';
+import theme from './theme.css';
const Input = inputFactory(FontIcon);
const ThemedInput = themr(INPUT, theme, { withRef: true })(Input);
diff --git a/components/input/theme.css b/components/input/theme.css
new file mode 100644
index 00000000..a4b59a4b
--- /dev/null
+++ b/components/input/theme.css
@@ -0,0 +1,183 @@
+@import '../colors.css';
+@import '../variables.css';
+@import './config.css';
+
+.input {
+ composes: reset from '../helpers.css';
+ padding: var(--input-padding) 0;
+ position: relative;
+
+ &.withIcon {
+ margin-left: var(--input-icon-size);
+ }
+}
+
+.icon {
+ color: var(--input-text-label-color);
+ display: block;
+ font-size: var(--input-icon-font-size) !important;
+ height: var(--input-icon-size);
+ left: calc(-1 * var(--input-icon-size));
+ line-height: var(--input-icon-size) !important;
+ position: absolute;
+ text-align: center;
+ top: var(--input-icon-offset);
+ transition: color var(--animation-duration) var(--animation-curve-default);
+ width: var(--input-icon-size);
+}
+
+.inputElement {
+ background-color: var(--input-text-background-color);
+ border-bottom: 1px solid var(--input-text-bottom-border-color);
+ border-left: 0;
+ border-right: 0;
+ border-top: 0;
+ color: var(--color-text);
+ display: block;
+ font-size: var(--input-field-font-size);
+ outline: none;
+ padding: var(--input-field-padding) 0;
+ width: 100%;
+
+ &:focus:not([disabled]):not([readonly]) {
+ & ~ .bar::before,
+ & ~ .bar::after {
+ width: 50%;
+ }
+
+ & ~ .label:not(.fixed) {
+ color: var(--input-text-highlight-color);
+ }
+
+ & ~ .label > .required {
+ color: var(--input-text-required-color);
+ }
+
+ & ~ .hint {
+ display: block;
+ opacity: var(--input-hint-opacity);
+ }
+
+ & ~ .icon {
+ color: var(--input-text-highlight-color);
+ }
+
+ &.filled ~ .hint {
+ opacity: 0;
+ }
+ }
+
+ &:focus:not([disabled]):not([readonly]),
+ &.filled,
+ &[type='date'],
+ &[type='time'] {
+ & ~ .label:not(.fixed) {
+ font-size: var(--input-label-font-size);
+ top: var(--input-focus-label-top);
+ }
+ }
+
+ &.filled ~ .label.fixed,
+ &.filled ~ .hint {
+ display: none;
+ }
+}
+
+.label {
+ color: var(--input-text-label-color);
+ font-size: var(--input-field-font-size);
+ left: 0;
+ line-height: var(--input-field-font-size);
+ pointer-events: none;
+ position: absolute;
+ top: calc(var(--input-padding) + 1.5 * var(--input-field-padding));
+ transition-duration: var(--animation-duration);
+ transition-property: top, font-size, color;
+ transition-timing-function: var(--animation-curve-default);
+
+ &.fixed ~ .hint {
+ display: none;
+ }
+}
+
+.hint {
+ color: var(--input-text-label-color);
+ font-size: var(--input-field-font-size);
+ left: 0;
+ line-height: var(--input-field-font-size);
+ opacity: var(--input-hint-opacity);
+ pointer-events: none;
+ position: absolute;
+ top: calc(var(--input-padding) + 1.5 * var(--input-field-padding));
+ transition-duration: var(--animation-duration);
+ transition-property: opacity;
+ transition-timing-function: var(--animation-curve-default);
+}
+
+.bar {
+ display: block;
+ position: relative;
+ width: 100%;
+
+ &::before,
+ &::after {
+ background-color: var(--input-text-highlight-color);
+ bottom: 0;
+ content: '';
+ height: 2px;
+ position: absolute;
+ transition-duration: 0.2s;
+ transition-property: width, background-color;
+ transition-timing-function: var(--animation-curve-default);
+ width: 0;
+ }
+
+ &::before {
+ left: 50%;
+ }
+
+ &::after {
+ right: 50%;
+ }
+}
+
+.error,
+.counter {
+ color: var(--input-text-error-color);
+ font-size: var(--input-label-font-size);
+ line-height: var(--input-underline-height);
+ margin-bottom: calc(-1 * var(--input-underline-height));
+}
+
+.counter {
+ color: var(--input-text-label-color);
+ position: absolute;
+ right: 0;
+}
+
+.disabled > .inputElement {
+ border-bottom-style: dotted;
+ color: var(--input-text-disabled-text-color);
+}
+
+.errored {
+ padding-bottom: 0;
+
+ & > .inputElement {
+ border-bottom-color: var(--input-text-error-color);
+ margin-top: 1px;
+ }
+
+ & > .counter,
+ & > .label {
+ color: var(--input-text-error-color);
+ }
+
+ & > .label > .required {
+ color: var(--input-text-required-color);
+ }
+}
+
+.hidden {
+ display: none;
+}
diff --git a/components/input/theme.scss b/components/input/theme.scss
deleted file mode 100644
index 9e29b9b4..00000000
--- a/components/input/theme.scss
+++ /dev/null
@@ -1,156 +0,0 @@
-@import "../colors";
-@import "../globals";
-@import "../mixins";
-@import "./config";
-
-.input {
- position: relative;
- padding: $input-padding 0;
- &.withIcon {
- margin-left: $input-icon-size;
- }
-}
-
-.icon {
- position: absolute;
- top: $input-icon-offset;
- left: -$input-icon-size;
- display: block;
- width: $input-icon-size;
- height: $input-icon-size;
- font-size: $input-icon-font-size !important;
- line-height: $input-icon-size !important;
- color: $input-text-label-color;
- text-align: center;
- transition: color $animation-duration $animation-curve-default;
-}
-
-.inputElement {
- display: block;
- width: 100%;
- padding: $input-field-padding 0;
- font-size: $input-field-font-size;
- color: $color-text;
- background-color: $input-text-background-color;
- border: 0;
- border-bottom: 1px solid $input-text-bottom-border-color;
- outline: none;
- &:focus:not([disabled]):not([readonly]) {
- ~ .bar:before, ~ .bar:after {
- width: 50%;
- }
- ~ .label:not(.fixed) {
- color: $input-text-highlight-color;
- }
- ~ .label > .required {
- color: $input-text-required-color;
- }
- ~ .hint {
- display: block;
- opacity: $input-hint-opacity;
- }
- ~ .icon {
- color: $input-text-highlight-color;
- }
- }
- &:focus:not([disabled]):not([readonly]), &.filled, &[type="date"], &[type="time"] {
- ~ .label:not(.fixed) {
- top: $input-focus-label-top;
- font-size: $input-label-font-size;
- }
- &.filled ~ .hint {
- opacity: 0;
- }
- }
- &.filled ~ .label.fixed, &.filled ~ .hint {
- display: none;
- }
-}
-
-.label {
- position: absolute;
- top: $input-padding + (1.5 * $input-field-padding);
- left: 0;
- font-size: $input-field-font-size;
- line-height: $input-field-font-size;
- color: $input-text-label-color;
- pointer-events: none;
- transition-timing-function: $animation-curve-default;
- transition-duration: $animation-duration;
- transition-property: top, font-size, color;
- &.fixed ~ .hint {
- display: none;
- }
-}
-
-.hint {
- position: absolute;
- top: $input-padding + (1.5 * $input-field-padding);
- left: 0;
- font-size: $input-field-font-size;
- line-height: $input-field-font-size;
- color: $input-text-label-color;
- pointer-events: none;
- opacity: $input-hint-opacity;
- transition-timing-function: $animation-curve-default;
- transition-duration: $animation-duration;
- transition-property: opacity;
-}
-
-.bar {
- position: relative;
- display: block;
- width: 100%;
- &:before, &:after {
- @include material-animation-default();
- position: absolute;
- bottom: 0;
- width: 0;
- height: 2px;
- content: "";
- background-color: $input-text-highlight-color;
- transition-property: width, background-color;
- }
- &:before {
- left: 50%;
- }
- &:after {
- right: 50%;
- }
-}
-
-.error, .counter {
- margin-bottom: - $input-underline-height;
- font-size: $input-label-font-size;
- line-height: $input-underline-height;
- color: $input-text-error-color;
-}
-
-.counter {
- position: absolute;
- right: 0;
- color: $input-text-label-color;
-}
-
-.disabled > .inputElement {
- color: $input-text-disabled-text-color;
- border-bottom-style: dotted;
-}
-
-.errored {
- padding-bottom: 0;
- > .inputElement {
- margin-top: 1px;
- border-bottom-color: $input-text-error-color;
- }
- > .counter, > .label {
- color: $input-text-error-color;
- }
- > .label > .required {
- color: $input-text-required-color;
- }
-}
-
-.hidden {
- display: none;
-}
diff --git a/components/layout/Layout.js b/components/layout/Layout.js
index 0e356395..b3bc733d 100644
--- a/components/layout/Layout.js
+++ b/components/layout/Layout.js
@@ -1,28 +1,113 @@
-import React, { PropTypes } from 'react';
-import { themr } from 'react-css-themr';
+import React, { cloneElement, Component, PropTypes } from 'react';
import classnames from 'classnames';
-import { LAYOUT } from '../identifiers.js';
+import { themr } from 'react-css-themr';
+import { getViewport } from '../utils/utils';
+import filterReactChildren from '../utils/filter-react-children.js';
+import isComponentOfType from '../utils/is-component-of-type.js';
+import InjectAppBar from '../app_bar/AppBar';
+import InjectNavDrawer from './NavDrawer';
+import InjectSidebar from './Sidebar';
+import isBrowser from '../utils/is-browser';
+import breakpoints from '../utils/breakpoints';
+import { LAYOUT } from '../identifiers';
-const Layout = ({ className, children, theme }) => (
-
- {React.Children.map(children, (child) => React.cloneElement(child, { theme }))}
-
-);
+const factory = (AppBar, NavDrawer, Sidebar) => {
+ const isNavDrawer = child => isComponentOfType(NavDrawer, child);
+ const isSidebar = child => isComponentOfType(Sidebar, child);
+ const isAppBar = child => isComponentOfType(AppBar, child);
+ const isUnknown = child => !isNavDrawer(child) && !isSidebar(child) && !isAppBar(child);
-Layout.propTypes = {
- children: PropTypes.oneOfType([
- PropTypes.arrayOf(PropTypes.element),
- PropTypes.element
- ]),
- className: PropTypes.string,
- theme: PropTypes.shape({
- layout: PropTypes.string
- })
-};
-
-Layout.defaultProps = {
- className: ''
+ class Layout extends Component {
+ static propTypes = {
+ children: PropTypes.node,
+ className: PropTypes.string,
+ theme: PropTypes.object
+ };
+
+ static defaultProps = {
+ className: ''
+ };
+
+ state = {
+ width: isBrowser() && getViewport().width
+ };
+
+ componentDidMount () {
+ if (!this.state.width) this.handleResize();
+ window.addEventListener('resize', this.handleResize);
+ }
+
+ componentWillUnmount () {
+ window.removeEventListener('resize', this.handleResize);
+ }
+
+ handleResize = () => {
+ this.setState({ width: getViewport().width });
+ }
+
+ isPinned = sideNav => {
+ if (sideNav) {
+ const { permanentAt, pinned } = sideNav.props;
+ const { width } = this.state;
+ return width > breakpoints[permanentAt] || pinned;
+ }
+ return undefined;
+ }
+
+ render () {
+ const { children, className, theme, ...rest } = this.props;
+ const appBar = filterReactChildren(children, isAppBar)[0];
+ const navDrawer = filterReactChildren(children, isNavDrawer)[0];
+ const sidebar = filterReactChildren(children, isSidebar)[0];
+ const unknown = filterReactChildren(children, isUnknown);
+ const appBarFixed = appBar && appBar.props.fixed;
+ const navDrawerPinned = this.isPinned(navDrawer);
+ const navDrawerClipped = navDrawer && navDrawer.props.clipped;
+ const sidebarWidth = sidebar && sidebar.props.width;
+ const sidebarPinned = this.isPinned(sidebar);
+ const sidebarClipped = sidebar && sidebar.props.clipped;
+
+ const clonedAppBar = appBar && cloneElement(appBar, {
+ theme,
+ themeNamespace: 'appbar'
+ });
+
+ const clonedLeftSideNav = navDrawer && cloneElement(navDrawer, {
+ clipped: navDrawerClipped,
+ pinned: navDrawerPinned
+ });
+
+ const clonedRightSideNav = sidebar && cloneElement(sidebar, {
+ clipped: sidebarClipped,
+ pinned: sidebarPinned
+ });
+
+ const _className = classnames(theme.layout,
+ theme[`sidebarWidth${sidebarWidth}`], {
+ [theme.navDrawerPinned]: navDrawerPinned,
+ [theme.navDrawerClipped]: navDrawerClipped,
+ [theme.sidebarPinned]: sidebarPinned,
+ [theme.sidebarClipped]: sidebarClipped,
+ [theme.appbarFixed]: appBarFixed
+ }, className);
+
+ return (
+
+ {clonedLeftSideNav}
+ {clonedAppBar}
+
+ {unknown}
+
+ {clonedRightSideNav}
+
+ );
+ }
+ }
+
+ return Layout;
};
+const Layout = factory(InjectAppBar, InjectNavDrawer, InjectSidebar);
export default themr(LAYOUT)(Layout);
+export { factory as layoutFactory };
export { Layout };
diff --git a/components/layout/NavDrawer.js b/components/layout/NavDrawer.js
index 631ea5e3..58aa1a9e 100644
--- a/components/layout/NavDrawer.js
+++ b/components/layout/NavDrawer.js
@@ -1,64 +1,57 @@
import React, { PropTypes } from 'react';
import classnames from 'classnames';
import { themr } from 'react-css-themr';
-import { LAYOUT } from '../identifiers.js';
+import InjectDrawer from '../drawer/Drawer';
+import { LAYOUT } from '../identifiers';
-const NavDrawer = ({ active, children, className, onOverlayClick, permanentAt, pinned, scrollY, theme, width }) => {
- const rootClasses = classnames([theme.navDrawer], {
- [theme[permanentAt + 'Permanent']]: permanentAt,
- [theme.wide]: (width === 'wide'),
- [theme.active]: active,
- [theme.pinned]: pinned
- }, className);
+const factory = Drawer => {
+ const NavDrawer = ({
+ active,
+ className,
+ clipped,
+ permanentAt, // eslint-disable-line
+ pinned,
+ theme,
+ ...rest
+ }) => {
+ const _className = classnames({
+ [theme.pinned]: pinned,
+ [theme.clipped]: clipped
+ }, className);
- const drawerClasses = classnames(theme.drawerContent, {
- [theme.scrollY]: scrollY
- });
+ return (
+
+ );
+ };
- return (
-
- );
-};
-
-NavDrawer.propTypes = {
- active: PropTypes.bool,
- children: PropTypes.any,
- className: PropTypes.string,
- onOverlayClick: PropTypes.func,
- permanentAt: PropTypes.oneOf(['sm', 'smTablet', 'md', 'lg', 'lgTablet', 'xl', 'xxl', 'xxxl']),
- pinned: PropTypes.bool,
- scrollY: PropTypes.bool,
- theme: PropTypes.shape({
- active: PropTypes.string,
- drawerContent: PropTypes.string,
- lgPermanent: PropTypes.string,
- lgTabletPermanent: PropTypes.string,
- mdPermanent: PropTypes.string,
- navDrawer: PropTypes.string,
- pinned: PropTypes.string,
- scrim: PropTypes.string,
- scrollY: PropTypes.string,
- smPermanent: PropTypes.string,
- smTabletPermanent: PropTypes.string,
- wide: PropTypes.string,
- xlPermanent: PropTypes.string,
- xxlPermanent: PropTypes.string,
- xxxlPermanent: PropTypes.string
- }),
- width: PropTypes.oneOf(['normal', 'wide'])
-};
-
-NavDrawer.defaultProps = {
- active: false,
- className: '',
- scrollY: false,
- width: 'normal'
+ NavDrawer.propTypes = {
+ active: PropTypes.bool,
+ children: PropTypes.node,
+ className: PropTypes.string,
+ clipped: PropTypes.bool,
+ permanentAt: PropTypes.oneOf(['sm', 'smTablet', 'md', 'lg', 'lgTablet', 'xl', 'xxl', 'xxxl']),
+ pinned: PropTypes.bool,
+ right: PropTypes.bool,
+ theme: PropTypes.object
+ };
+
+ NavDrawer.defaultProps = {
+ className: '',
+ pinned: false
+ };
+
+ return NavDrawer;
};
+const NavDrawer = factory(InjectDrawer);
export default themr(LAYOUT)(NavDrawer);
+export { factory as navDrawerFactory };
export { NavDrawer };
diff --git a/components/layout/Panel.js b/components/layout/Panel.js
index 658b2ae4..41785e8a 100644
--- a/components/layout/Panel.js
+++ b/components/layout/Panel.js
@@ -3,32 +3,29 @@ import classnames from 'classnames';
import { themr } from 'react-css-themr';
import { LAYOUT } from '../identifiers.js';
-const Panel = ({ children, className, onScroll, scrollY, theme }) => {
- const _className = classnames(theme.panel, {
- [theme.scrollY]: scrollY
- }, className);
-
- return (
-
- {children}
-
- );
-};
+const Panel = ({ bodyScroll, children, className, theme, ...other }) => (
+
+);
Panel.propTypes = {
+ bodyScroll: PropTypes.bool,
children: PropTypes.any,
className: PropTypes.string,
- onScroll: PropTypes.func,
- scrollY: PropTypes.bool,
theme: PropTypes.shape({
- panel: PropTypes.string,
- scrollY: PropTypes.string
+ panel: PropTypes.string
})
};
Panel.defaultProps = {
- className: '',
- scrollY: false
+ bodyScroll: true,
+ className: ''
};
export default themr(LAYOUT)(Panel);
diff --git a/components/layout/Sidebar.js b/components/layout/Sidebar.js
index 7b8923a2..869c1620 100644
--- a/components/layout/Sidebar.js
+++ b/components/layout/Sidebar.js
@@ -1,46 +1,59 @@
import React, { PropTypes } from 'react';
import classnames from 'classnames';
import { themr } from 'react-css-themr';
-import { LAYOUT } from '../identifiers.js';
+import InjectDrawer from '../drawer/Drawer';
+import { LAYOUT } from '../identifiers';
-const Sidebar = ({ children, className, pinned, scrollY, theme, width }) => {
- const wrapperClasses = classnames(theme.sidebar, theme[`width-${width}`], {
- [theme.pinned]: pinned
- }, className);
+const factory = Drawer => {
+ const Sidebar = ({
+ active,
+ className,
+ clipped,
+ permanentAt, // eslint-disable-line
+ pinned,
+ theme,
+ ...rest
+ }) => {
+ const _className = classnames({
+ [theme.pinned]: pinned,
+ [theme.clipped]: clipped
+ }, className);
- const innerClasses = classnames(theme.sidebarContent, {
- [theme.scrollY]: scrollY
- });
+ return (
+
+ );
+ };
- return (
-
- );
-};
-
-Sidebar.propTypes = {
- children: PropTypes.any,
- className: PropTypes.string,
- pinned: PropTypes.bool,
- scrollY: PropTypes.bool,
- theme: PropTypes.shape({
- pinned: PropTypes.string,
- scrollY: PropTypes.string,
- sidebar: PropTypes.string,
- sidebarContent: PropTypes.string
- }),
- width: PropTypes.oneOf([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 25, 33, 50, 66, 75, 100])
-};
-
-Sidebar.defaultProps = {
- className: '',
- pinned: false,
- scrollY: false,
- width: 5
+ Sidebar.propTypes = {
+ active: PropTypes.bool,
+ children: PropTypes.node,
+ className: PropTypes.string,
+ clipped: PropTypes.bool,
+ permanentAt: PropTypes.oneOf(['sm', 'smTablet', 'md', 'lg', 'lgTablet', 'xl', 'xxl', 'xxxl']),
+ pinned: PropTypes.bool,
+ theme: PropTypes.object,
+ width: PropTypes.oneOf([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 25, 33, 50, 66, 75, 100])
+ };
+
+ Sidebar.defaultProps = {
+ className: '',
+ pinned: false,
+ right: false
+ };
+
+ return Sidebar;
};
+const Sidebar = factory(InjectDrawer);
export default themr(LAYOUT)(Sidebar);
+export { factory as sidebarFactory };
export { Sidebar };
diff --git a/components/layout/_config.scss b/components/layout/_config.scss
deleted file mode 100644
index 16f778f1..00000000
--- a/components/layout/_config.scss
+++ /dev/null
@@ -1,18 +0,0 @@
-$drawer-background-color: $palette-grey-50 !default;
-$drawer-border-color: $palette-grey-300 !default;
-$drawer-text-color: $palette-grey-800 !default;
-
-$drawer-overlay-color: $color-black !default;
-$drawer-overlay-opacity: .6 !default;
-
-// from: https://material.google.com/layout/structure.html#structure-side-nav
-$navigation-drawer-desktop-width: 5 * $standard-increment-desktop !default;
-$navigation-drawer-max-desktop-width: 40 * $unit !default;
-
-// Mobile:
-// Width = Screen width − 56 dp
-// Maximum width: 320dp
-$navigation-drawer-mobile-width: 5 * $standard-increment-mobile !default;
-
-// sass doesn't like use of variable here: calc(100% - $standard-increment-mobile);
-$navigation-drawer-max-mobile-width: calc(100% - 5.6rem) !default;
diff --git a/components/layout/_mixins.scss b/components/layout/_mixins.scss
deleted file mode 100644
index e998d174..00000000
--- a/components/layout/_mixins.scss
+++ /dev/null
@@ -1,27 +0,0 @@
-@mixin open() {
- transition-delay: $animation-delay;
- .drawerContent {
- pointer-events: all;
- transition-delay: $animation-delay;
- transform: translateX(0);
- }
-}
-
-@mixin permanent() {
- @include open();
-
- width: $navigation-drawer-desktop-width;
- max-width: $navigation-drawer-desktop-width;
-
- &.wide {
- width: $navigation-drawer-max-desktop-width;
- max-width: $navigation-drawer-max-desktop-width;
- }
-
- &.active {
- & > .scrim {
- width: 0;
- background-color: rgba($drawer-overlay-color, 0);
- }
- }
-}
diff --git a/components/layout/index.js b/components/layout/index.js
index d44ec77d..37258c11 100644
--- a/components/layout/index.js
+++ b/components/layout/index.js
@@ -1,17 +1,21 @@
import { themr } from 'react-css-themr';
-import { LAYOUT } from '../identifiers.js';
-import { Layout } from './Layout.js';
-import { Panel } from './Panel.js';
-import { NavDrawer } from './NavDrawer.js';
-import { Sidebar } from './Sidebar.js';
-import theme from './theme.scss';
+import { LAYOUT } from '../identifiers';
+import { layoutFactory } from './Layout';
+import { sidebarFactory } from './Sidebar';
+import { navDrawerFactory } from './NavDrawer';
+import Panel from './Panel';
+import AppBar from '../app_bar';
+import Drawer from '../drawer';
+import theme from './theme.css';
-const ThemedLayout = themr(LAYOUT, theme)(Layout);
-const ThemedPanel = themr(LAYOUT, theme)(Panel);
-const ThemedNavDrawer = themr(LAYOUT, theme)(NavDrawer);
-const ThemedSidebar = themr(LAYOUT, theme)(Sidebar);
+const injectTheme = component => themr(LAYOUT, theme)(component);
+const ThemedNavDrawer = injectTheme(navDrawerFactory(Drawer));
+const ThemedSidebar = injectTheme(sidebarFactory(Drawer));
+const ThemedPanel = injectTheme(Panel);
+const ThemedLayout = injectTheme(layoutFactory(AppBar, ThemedNavDrawer, ThemedSidebar));
+export default ThemedLayout;
export { ThemedLayout as Layout };
-export { ThemedPanel as Panel };
-export { ThemedNavDrawer as NavDrawer };
export { ThemedSidebar as Sidebar };
+export { ThemedNavDrawer as NavDrawer };
+export { ThemedPanel as Panel };
diff --git a/components/layout/readme.md b/components/layout/readme.md
index 7a0d88d8..bd07b67f 100644
--- a/components/layout/readme.md
+++ b/components/layout/readme.md
@@ -4,56 +4,102 @@ A Layout is a container that can hold a main content area with an optional navig
```jsx
-import { AppBar, Checkbox, IconButton } from 'react-toolbox';
-import { Layout, NavDrawer, Panel, Sidebar } from 'react-toolbox';
+import React, { Component } from 'react';
+import { Layout, NavDrawer, Sidebar, Panel } from '../../components/layout';
+import { AppBar } from '../../components/app_bar';
+import Checkbox from '../../components/checkbox';
-class LayoutTest extends React.Component {
- state = {
- drawerActive: false,
- drawerPinned: false,
- sidebarPinned: false
- };
+class LayoutExample extends Component {
+ state = {
+ bodyScrolled: true,
+ sideNavActive: false,
+ sideNavPinned: false,
+ sideNavClipped: false,
+ rightSideNavActive: false,
+ rightSideNavPinned: false,
+ rightSideNavClipped: false
+ };
- toggleDrawerActive = () => {
- this.setState({ drawerActive: !this.state.drawerActive });
- };
+ handleToggle = param => {
+ this.setState({ [param]: !this.state[param] });
+ }
- toggleDrawerPinned = () => {
- this.setState({ drawerPinned: !this.state.drawerPinned });
- }
+ render () {
+ const { sideNavActive, rightSideNavActive } = this.state;
+ return (
+
+
+ I'm a NavDrawer content.
+
- toggleSidebar = () => {
- this.setState({ sidebarPinned: !this.state.sidebarPinned });
- };
+
- render() {
- return (
-
-
-
- Navigation, account switcher, etc. go here.
-
-
-
-
-
-
Main Content
-
Main content goes here.
-
-
-
-
-
-
-
-
Supplemental content goes here.
-
-
-
- );
- }
+
+
+ SideNav State
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ I'm a Sidebar content.
+
+
+ );
+ }
}
```
@@ -91,15 +137,23 @@ If the column layout does not suit your needs, simply fill the content area with
### Properties
| Name | Type | Default | Description |
|:-----|:-----|:-----|:-----|
-| `children` | `Nodes` | | A `Panel`, optionally preceded by a `NavDrawer` and/or followed by a `Sidebar` |
+| `children` | `Nodes` | | Can hold a `Panel`, along with a `NavDrawer`, a `Sidebar` and an `AppBar` |
| `className` | `string` | | Additional class(es) for custom styling. |
### Theme
-The themed key the `Layout` in general is `ToolboxLayout`. For the `Layout` wrapper it should only provide one class interface:
+The themed key the `Layout` in general is `ToolboxLayout`. We add classes to the root element depending on the parsed children:
| Name | Description|
|:---------|:-----------|
-| `layout` | Class used in the container to position and align inner items.|
+| `appbarFixed` | Added to the root class if there is a fixed `AppBar` present.|
+| `layout` | The root class that wraps the whole layout.|
+| `navDrawerPinned` | Added to the root if there is a pinned `NavDrawer`.|
+| `navDrawerClipped` | Added to the root if there is a clipped NavDrawer.|
+| `sidebarPinned` | Added to the root if there is a pinned sidebar.|
+| `sidebarClipped` | Added to the root if there is a clipped sidebar.|
+| `sidebarWidth${width}` | Added to the root element in case there is a sidebar present. width correspond to the value passed to the `Sidebar`.|
+
+Note that you can also pass namespaced properties under `appbar` to override styles of a nested `AppBar` inside the layout.
## NavDrawer
@@ -111,52 +165,42 @@ The [navigation drawer](https://material.google.com/patterns/navigation-drawer.h
| > `xs` | 320px | |
| > `xs` | 400px | If property `width` is set to `wide` |
-The drawer can be docked to the left side of the screen or can float temporarily as an overlay. You can control the drawer's display manually `active` and `pinned` properties, and can also specify a breakpoint at which the drawer automatically becomes permanently docked.
+The drawer can be docked to the left side of the screen or can float temporarily as an overlay. You can control the drawer's display manually `active` and `pinned` properties, and can also specify a breakpoint at which the drawer automatically becomes permanently docked. You can also use a `clipped` property when it's pinned so the `AppBar` would stick over the Drawer.
### Properties
| Name | Type | Default | Description |
|:-----|:-----|:-----|:-----|
-| `width` | `enum`(`'normal'`,`'wide'`) | `normal` | 320px or 400px. Only applicable above the `sm` breakpoint. |
| `active` | `bool` | `false` | If true, the drawer will be shown as an overlay. |
-| `pinned` | `bool` | `false` | If true, the drawer will be pinned open. `pinned` takes precedence over `active`. |
-| `permanentAt` | `enum`(`'sm'`,`'md'`,`'lg'`,`'xl'`,`'xxl'`,`'xxxl'`) | | The breakpoint at which the drawer is automatically pinned. |
-| `scrollY` | `bool` | `false` | If true, the drawer will vertically scroll all content. |
-| `onOverlayClick` | `Function` | | Callback function to be invoked when the overlay is clicked.|
| `className` | `string` | | Additional class(es) for custom styling. |
+| `clipped` | `bool` | `false` | If true, when the `AppBar` gets pinned, it will stand over the `Drawer`. |
+| `permanentAt` | `enum`(`'sm'`,`'smTablet'`,`'md'`,`'lg'`,`'lgTablet'`,`'xl'`,`'xxl'`,`'xxxl'`) | | The breakpoint at which the drawer is automatically pinned. |
+| `pinned` | `bool` | `false` | If true, the drawer will be pinned open. `pinned` takes precedence over `active`. |
+| `onOverlayClick` | `Function` | | Callback function to be invoked when the overlay is clicked. It only works if the `Drawer` is actually displaying and Overlay|
### Theme
+
+The `navDrawer` uses a `Drawer` component under the covers the theme is the same as for it but namespaced under `navDrawer`. It takes the following extra properties:
+
| Name | Description|
|:---------|:-----------|
-| `active` | Used when the drawer is active.|
-| `drawerContent` | Used for the content of the drawer.|
-| `lgPermanent` | Added to the root class for large drawer.|
-| `mdPermanent` | Added to the root class for medium drawer.|
-| `navDrawer` | Root class for the drawer.|
-| `pinned` | Added to the root class if positioning is pinned.|
-| `scrim` | Used as a wrapper for the drawer content.|
-| `scrollY` | Added to the drawer content if its scrollable.|
-| `smPermanent` | Added to the root class for small drawer.|
-| `wide` | Added to the root class if width is wide.|
-| `xlPermanent` | Added to the root class for extra big drawer.|
-| `xxlPermanent` | Added to the root class for super big drawer.|
-| `xxxlPermanent` | Added to the root class for largest possible drawer.|
+| `pinned` | Added to the root class when it is pinned.|
+| `clipped` | Added to the root class when it is clipped.|
## Panel
-The `Panel` is the main content area within a `Layout`. It is a full-height flexbox column that takes up all remaining horizontal space after the `NavDrawer` and `Sidebar` are laid out.
+The `Panel` is the main content area within a `Layout`. By default we assume it is rendered in the body using the `document` scroll but you can use a `bodyScroll` to `false` property to make it look like a scrolled `div`.
### Properties
| Name | Type | Default | Description |
|:-----|:-----|:-----|:-----|
-| `onScroll` | `Function` | | Callback function to be invoked when the component scrolls. |
-| `scrollY` | `bool` | `false` | If true, the panel will vertically scroll all content. |
+| `bodyScroll` | `Boolean` | | You can set it to true in case you are using a pinned Sidebar so it takes an scrolled `div` instead of using the document scroll. |
| `className` | `string` | | Additional class(es) for custom styling. |
### Theme
| Name | Description|
|:---------|:-----------|
+| `bodyScroll` | Used in the root class in case the panel has bodyScroll.|
| `panel` | Used as the root class of the panel component.|
-| `scrollY` | Used in case the panel is scrollable.|
## Sidebar
@@ -171,31 +215,10 @@ The `Sidebar` is an extra drawer that docks to the right side of the `Layout`. T
| `className` | `string` | | Additional class(es) for custom styling. |
### Theme
+
+The `Sidebar` uses a `Drawer` component under the covers the theme is the same as for it but namespaced under `sidebar`. It takes the following extra properties:
+
| Name | Description|
|:---------|:-----------|
-| `pinned` | Added to the root class if sidebar is pinned.|
-| `scrollY` | Add to the content of sidebar if its scrollable.|
-| `sidebar` | Root class of the sidebar.|
-| `sidebarContent` | Used in for the content element of the sidebar.|
-
-## Nesting Layouts
-
-The `Layout` is meant to be used near the top level of your application, so that it occupies the entire screen. However, it is possible to nest one layout inside another:
-
-```jsx
-
- [navigation here]
-
-
-
- [main content here]
-
-
- [supplemental info here]
-
-
-
-
-```
-
-The main reason you would want to do something like this would be so that the navigation could be rendered at a high level, while the contents of the inner `Layout` would be controlled by react-router or something like that.
+| `clipped` | Added to the root class when it is clipped.|
+| `pinned` | Added to the root class when it is pinned.|
diff --git a/components/layout/theme.css b/components/layout/theme.css
new file mode 100644
index 00000000..be2f9296
--- /dev/null
+++ b/components/layout/theme.css
@@ -0,0 +1,236 @@
+@import '../colors.css';
+@import '../media.css';
+@import '../variables.css';
+@import '../app_bar/config.css';
+@import '../drawer/config.css';
+
+:root {
+ --layout-side-transition: all var(--animation-duration) var(--animation-curve-default);
+}
+
+.layout {
+ align-items: stretch;
+ composes: reset from '../helpers.css';
+ display: flex;
+ flex: 1;
+ flex-direction: column;
+ justify-content: space-between;
+ min-height: 100vh;
+ min-width: 100%;
+ position: relative;
+}
+
+.panel {
+ left: 0;
+ position: absolute;
+ right: 0;
+ top: 0;
+
+ &:not(.bodyScroll) {
+ height: 100vh;
+ max-height: 100vh;
+ overflow-y: scroll;
+ }
+}
+
+.sidebarDrawer,
+.navDrawerDrawer {
+ z-index: var(--z-index-high);
+
+ &.pinned {
+ box-shadow: none;
+ }
+
+ &.clipped {
+ height: calc(100vh - var(--appbar-height));
+ padding-top: calc(0.5 * var(--unit));
+ top: var(--appbar-height);
+
+ @media screen and (--xxs-viewport) and (--portrait) {
+ height: calc(100vh - var(--appbar-height-m-portrait));
+ top: var(--appbar-height-m-portrait);
+ }
+
+ @media screen and (--xs-viewport) and (--landscape) {
+ height: calc(100vh - var(--appbar-height-m-landscape));
+ top: var(--appbar-height-m-landscape);
+ }
+ }
+}
+
+.appbarInner,
+.panel {
+ transition: var(--layout-side-transition);
+}
+
+.appbarFixed {
+ &.appbarAppBar {
+ z-index: var(--z-index-high);
+ }
+
+ & .panel {
+ top: var(--appbar-height);
+
+ &:not(.bodyScroll) {
+ height: calc(100vh - var(--appbar-height));
+ max-height: calc(100vh - var(--appbar-height));
+ overflow-y: scroll;
+ }
+
+ @media screen and (--xxs-viewport) and (--portrait) {
+ top: var(--appbar-height-m-portrait);
+ }
+
+ @media screen and (--xs-viewport) and (--landscape) {
+ top: var(--appbar-height-m-landscape);
+ }
+ }
+}
+
+.navDrawerPinned {
+ & .appbarLeftIcon {
+ display: none;
+ }
+
+ & .panel {
+ left: var(--drawer-mobile-width);
+ }
+
+ &:not(.navDrawerClipped) {
+ & .appbarAppBar {
+ padding-left: calc(var(--drawer-mobile-width) + var(--appbar-h-padding));
+ }
+ }
+
+ @media screen and (--larger-than-xs-viewport) {
+ & .panel {
+ left: var(--drawer-desktop-width);
+ }
+
+ &:not(.navDrawerClipped) {
+ & .appbarAppBar {
+ padding-left: calc(var(--drawer-desktop-width) + var(--appbar-h-padding));
+ }
+ }
+ }
+}
+
+.navDrawerClipped {
+ & .navDrawerWrapper {
+ position: relative;
+ z-index: var(--z-index-normal);
+ }
+}
+
+.sidebarPinned {
+ & .appbarLeftIcon {
+ display: none;
+ }
+
+ & .panel {
+ right: var(--drawer-mobile-width);
+ }
+
+ &:not(.sidebarClipped) {
+ & .appbarAppBar {
+ padding-right: calc(var(--drawer-mobile-width) + var(--appbar-h-padding));
+ }
+ }
+
+ @media screen and (--larger-than-xs-viewport) {
+ & .panel {
+ right: var(--drawer-desktop-width);
+ }
+
+ &:not(.sidebarClipped) {
+ & .appbarAppBar {
+ padding-right: calc(var(--drawer-desktop-width) + var(--appbar-h-padding));
+ }
+ }
+ }
+}
+
+.sidebarClipped {
+ & .sidebarWrapper {
+ position: relative;
+ z-index: var(--z-index-normal);
+ }
+}
+
+@define-mixin sidebarIncrements $platform {
+ & .sidebarDrawer {
+ width: calc(var(--standard-increment-$(platform)) * $(increment));
+ }
+
+ &.sidebarPinned {
+ & .panel {
+ right: calc(var(--standard-increment-$(platform)) * $(increment));
+ }
+
+ &:not(.sidebarClipped) {
+ & .appbarAppBar {
+ padding-right: calc(var(--standard-increment-$(platform)) * $(increment) + var(--appbar-h-padding));
+ }
+ }
+ }
+}
+
+@each $increment in 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 {
+ .sidebarWidth$(increment) {
+ & .sidebarDrawer {
+ width: 100%;
+ }
+
+ @media screen and (--larger-than-sm-viewport) {
+ @mixin sidebarIncrements desktop;
+ }
+ }
+}
+
+@each $increment in 1, 2, 3, 4, 5, 6, 7, 8, 9 {
+ .sidebarWidth$(increment) {
+ @media screen and (--larger-than-xs-viewport) and (--landscape) {
+ @mixin sidebarIncrements mobile;
+ }
+
+ @media screen and (--larger-than-xs-viewport) and (orientation: portrait) {
+ @mixin sidebarIncrements desktop;
+ }
+ }
+}
+
+@each $increment in 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 {
+ .sidebarWidth$(increment) {
+ @media screen and (--larger-than-sm-tablet-viewport) {
+ @mixin sidebarIncrements desktop;
+ }
+ }
+}
+
+@each $pct in 25, 33, 50, 66, 75, 100 {
+ .sidebarWidth$(pct) {
+ & .sidebarDrawer {
+ width: 100%;
+ }
+ }
+}
+
+@media screen and (--larger-than-sm-tablet-viewport) {
+ @each $pct in 25, 33, 50, 66, 75, 100 {
+ .sidebarWidth$(pct) {
+ & .panel {
+ right: calc($(pct) * 1%);
+ }
+
+ & .sidebarDrawer {
+ width: calc($(pct) * 1%);
+ }
+
+ &:not(.sidebarClipped) {
+ & .appbarAppBar {
+ padding-right: calc(calc($(pct) * 1%) + var(--appbar-h-padding));
+ }
+ }
+ }
+ }
+}
diff --git a/components/layout/theme.scss b/components/layout/theme.scss
deleted file mode 100644
index 405d5121..00000000
--- a/components/layout/theme.scss
+++ /dev/null
@@ -1,325 +0,0 @@
-@import "../colors";
-@import "../globals";
-@import "../mixins";
-@import "./config";
-@import "./mixins";
-
-.layout {
- position: relative;
- display: flex;
- width: 100%;
- height: 100%;
- flex-direction: row;
- align-items: stretch;
- justify-content: space-between;
- overflow-y: hidden;
-
- .navDrawer {
- width: 0;
- min-width: 0;
- height: 100%;
- overflow-x: hidden;
- overflow-y: hidden;
- transition-timing-function: $animation-curve-default;
- transition-duration: $animation-duration;
- transition-property: width, min-width;
-
- .scrim {
- position: absolute;
- top: 0;
- bottom: 0;
- left: 0;
- z-index: $z-index-higher;
- width: 0;
- height: 100%;
- background-color: rgba($drawer-overlay-color, 0);
- transition: background-color $animation-duration $animation-curve-default, width 10ms linear $animation-duration;
- }
-
- .drawerContent {
- @include shadow-2dp();
- position: absolute;
- z-index: $z-index-highest;
- display: flex;
- width: $navigation-drawer-mobile-width;
- max-width: $navigation-drawer-max-mobile-width;
- height: 100%;
- flex-direction: column;
- align-items: stretch;
- justify-content: space-between;
- overflow-x: hidden;
- overflow-y: hidden;
- color: $drawer-text-color;
- pointer-events: none;
- background-color: $drawer-background-color;
- border-right: 1px solid $drawer-border-color;
- transition: transform $animation-duration $animation-curve-default;
- transform: translateX(-100%);
-
- &.scrollY {
- overflow-y: auto;
- }
- }
-
- &.pinned {
- @include open();
- width: $navigation-drawer-mobile-width;
- max-width: $navigation-drawer-max-mobile-width;
- }
-
- &.active {
- &:not(.pinned) {
- @include open();
- .scrim {
- width: 100%;
- background-color: rgba($drawer-overlay-color, $drawer-overlay-opacity);
- transition: background-color $animation-duration $animation-curve-default;
- }
- }
- }
-
- // Larger than mobile width drawer
- @media screen and (min-width: $layout-breakpoint-xs) {
- &.pinned {
- width: $navigation-drawer-desktop-width;
- max-width: $navigation-drawer-desktop-width;
- }
-
- .drawerContent {
- width: $navigation-drawer-desktop-width;
- max-width: $navigation-drawer-desktop-width;
- }
-
- &.wide {
- &.pinned {
- width: $navigation-drawer-max-desktop-width;
- max-width: $navigation-drawer-max-desktop-width;
- }
-
- .drawerContent {
- width: $navigation-drawer-max-desktop-width;
- max-width: $navigation-drawer-max-desktop-width;
- }
- }
- }
-
- // Permanent screen, ignore .active and make part of layout
- @media screen and (min-width: $layout-breakpoint-sm) {
- &.smPermanent {
- @include permanent();
- }
- }
-
- @media screen and (min-width: $layout-breakpoint-sm-tablet) {
- &.smTabletPermanent {
- @include permanent();
- }
- }
-
- @media screen and (min-width: $layout-breakpoint-md) {
- &.mdPermanent {
- @include permanent();
- }
- }
-
- @media screen and (min-width: $layout-breakpoint-lg) {
- &.lgPermanent {
- @include permanent();
- }
- }
-
- @media screen and (min-width: $layout-breakpoint-lg-tablet) {
- &.lgTabletPermanent {
- @include permanent();
- }
- }
-
- @media screen and (min-width: $layout-breakpoint-xl) {
- &.xlPermanent {
- @include permanent();
- }
- }
-
- @media screen and (min-width: $layout-breakpoint-xxl) {
- &.xxlPermanent {
- @include permanent();
- }
- }
-
- @media screen and (min-width: $layout-breakpoint-xxxl) {
- &.xxxlPermanent {
- @include permanent();
- }
- }
- }
-
- & .layout {
- .scrim {
- z-index: $z-index-highest - 1;
- }
- & .layout {
- .scrim {
- z-index: $z-index-highest - 2;
- }
- }
- }
-
- .panel {
- position: relative;
- display: flex;
- height: 100%;
- flex: 1;
- flex-direction: column;
- align-items: stretch;
- justify-content: space-between;
- overflow-y: hidden;
-
- &.scrollY {
- overflow-y: auto;
- }
- }
-
- .sidebar {
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- z-index: $z-index-highest - 1;
- width: 0;
- height: 100%;
- overflow-x: hidden;
- overflow-y: hidden;
- color: $drawer-text-color;
- background-color: $drawer-background-color;
- transition-timing-function: $animation-curve-default;
- transition-duration: $animation-duration;
- transition-property: width;
-
- .sidebarContent {
- display: flex;
- height: 100%;
- flex-direction: column;
- align-items: stretch;
- justify-content: space-between;
- overflow-y: hidden;
-
- &.scrollY {
- overflow-y: auto;
- }
- }
-
- $increments: (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);
-
- @each $increment in $increments {
- &.width-#{$increment} {
- $mobile: $standard-increment-mobile * $increment;
- $desktop: $standard-increment-desktop * $increment;
-
- .sidebarContent {
- min-width: 100%;
- }
-
- &.pinned {
- width: 100%;
- }
-
- @if $increment < 10 {
- @media screen and (min-width: $layout-breakpoint-xs) and (orientation: landscape) {
- position: relative;
-
- .sidebarContent {
- min-width: $mobile;
- }
-
- &.pinned {
- width: $mobile;
- }
- }
-
- @media screen and (min-width: $layout-breakpoint-xs) and (orientation: portrait) {
- position: relative;
-
- .sidebarContent {
- min-width: $desktop;
- }
-
- &.pinned {
- width: $desktop;
- }
- }
- }
-
- @if $increment < 11 {
- @media screen and (min-width: $layout-breakpoint-sm-tablet) {
- position: relative;
-
- .sidebarContent {
- min-width: $desktop;
- }
-
- &.pinned {
- width: $desktop;
- }
- }
- }
-
- @media screen and (min-width: $layout-breakpoint-sm) {
- position: relative;
-
- .sidebarContent {
- min-width: $desktop;
- }
-
- &.pinned {
- width: $desktop;
- }
- }
- }
- }
-
-
- $percentages: (25, 33, 50, 66, 75);
-
- &.width-100 {
- position: absolute;
-
- .sidebarContent {
- min-width: 100%;
- }
-
- &.pinned {
- width: 100%;
- }
- }
-
- @each $pct in $percentages {
- &.width-#{$pct} {
- position: absolute;
-
- .sidebarContent {
- min-width: 100%;
- }
-
- &.pinned {
- width: 100%;
- }
- }
- }
-
- @media screen and (min-width: $layout-breakpoint-sm-tablet) {
- @each $pct in $percentages {
- &.width-#{$pct} {
- position: relative;
-
- .sidebarContent {
- min-width: $pct * 1%;
- }
-
- &.pinned {
- width: $pct * 1%;
- }
- }
- }
- }
- }
-}
diff --git a/components/link/index.js b/components/link/index.js
index 3dcfcf1b..b4f15266 100644
--- a/components/link/index.js
+++ b/components/link/index.js
@@ -1,7 +1,7 @@
import { themr } from 'react-css-themr';
import { LINK } from '../identifiers.js';
import { Link } from './Link.js';
-import theme from './theme.scss';
+import theme from './theme.css';
const ThemedLink = themr(LINK, theme)(Link);
diff --git a/components/link/theme.css b/components/link/theme.css
new file mode 100644
index 00000000..30246422
--- /dev/null
+++ b/components/link/theme.css
@@ -0,0 +1,43 @@
+@import '../colors.css';
+@import '../variables.css';
+
+.icon {
+ font-size: calc(1.8 * var(--unit));
+ margin-right: var(--unit);
+}
+
+.link {
+ align-content: center;
+ align-items: center;
+ composes: reset from '../helpers.css';
+ cursor: pointer;
+ display: flex;
+ flex-direction: row;
+ justify-content: center;
+ line-height: 1.5;
+ position: relative;
+ transition: opacity var(--animation-duration) var(--animation-curve-default);
+
+ &:not(.active) {
+ opacity: 0.5;
+ }
+
+ &:hover,
+ &:active {
+ opacity: 1;
+ }
+
+ & > * {
+ vertical-align: middle;
+ }
+
+ & > abbr {
+ text-transform: capitalize;
+ }
+
+ & > small {
+ font-size: var(--font-size-tiny);
+ margin-left: calc(0.8 * var(--unit));
+ text-align: center;
+ }
+}
diff --git a/components/link/theme.scss b/components/link/theme.scss
deleted file mode 100644
index 11eb9084..00000000
--- a/components/link/theme.scss
+++ /dev/null
@@ -1,37 +0,0 @@
-@import "../colors";
-@import "../globals";
-@import "../mixins";
-
-.icon {
- margin-right: $unit;
- font-size: 1.8 * $unit;
-}
-
-.link {
- position: relative;
- display: flex;
- flex-direction: row;
- align-content: center;
- align-items: center;
- justify-content: center;
- line-height: 1.5;
- cursor: pointer;
- transition: opacity $animation-duration $animation-curve-default;
- &:not(.active) {
- opacity: .5;
- }
- &:hover, &:active {
- opacity: 1;
- }
- > * {
- vertical-align: middle;
- }
- > abbr {
- text-transform: capitalize;
- }
- > small {
- margin-left: .8 * $unit;
- font-size: $font-size-tiny;
- text-align: center;
- }
-}
diff --git a/components/list/_config.scss b/components/list/_config.scss
deleted file mode 100644
index a8814551..00000000
--- a/components/list/_config.scss
+++ /dev/null
@@ -1,18 +0,0 @@
-$list-vertical-padding: .8 * $unit !default;
-$list-horizontal-padding: 1.6 * $unit !default;
-$list-content-left-spacing: 7.2 * $unit !default;
-$list-subheader-height: 4.8 * $unit !default;
-$list-subheader-font-size: 1.4 * $unit !default;
-$list-subheader-font-weight: 500 !default;
-$list-divider-height: .1 * $unit !default;
-$list-item-min-height: 4.8 * $unit !default;
-$list-item-min-height-legend: 7.2 * $unit !default;
-$list-item-hover-color: $palette-grey-200 !default;
-$list-item-legend-margin-top: .3 * $unit !default;
-$list-item-icon-font-size: 2.4 * $unit !default;
-$list-item-icon-size: 1.8 * $unit !default;
-$list-item-right-icon-margin: $list-content-left-spacing - 2 * $list-horizontal-padding - $list-item-icon-size !default;
-$list-item-right-checkbox-margin: $list-item-right-icon-margin + $list-horizontal-padding !default;
-$list-item-avatar-height: 4 * $unit !default;
-$list-item-avatar-margin: .8 * $unit !default;
-$list-item-child-margin: .8 * $unit !default;
diff --git a/components/list/config.css b/components/list/config.css
new file mode 100644
index 00000000..741b86b6
--- /dev/null
+++ b/components/list/config.css
@@ -0,0 +1,20 @@
+:root {
+ --list-vertical-padding: calc(0.8 * var(--unit));
+ --list-horizontal-padding: calc(1.6 * var(--unit));
+ --list-content-left-spacing: calc(7.2 * var(--unit));
+ --list-subheader-height: calc(4.8 * var(--unit));
+ --list-subheader-font-size: calc(1.4 * var(--unit));
+ --list-subheader-font-weight: 500;
+ --list-divider-height: calc(0.1 * var(--unit));
+ --list-item-min-height: calc(4.8 * var(--unit));
+ --list-item-min-height-legend: calc(7.2 * var(--unit));
+ --list-item-hover-color: var(--palette-grey-200);
+ --list-item-legend-margin-top: calc(0.3 * var(--unit));
+ --list-item-icon-font-size: calc(2.4 * var(--unit));
+ --list-item-icon-size: calc(1.8 * var(--unit));
+ --list-item-right-icon-margin: calc(var(--list-content-left-spacing) - 2 * var(--list-horizontal-padding) - var(--list-item-icon-size));
+ --list-item-right-checkbox-margin: calc(var(--list-item-right-icon-margin) + var(--list-horizontal-padding));
+ --list-item-avatar-height: calc(4 * var(--unit));
+ --list-item-avatar-margin: calc(0.8 * var(--unit));
+ --list-item-child-margin: calc(0.8 * var(--unit));
+}
diff --git a/components/list/index.js b/components/list/index.js
index 06edbf81..df158130 100644
--- a/components/list/index.js
+++ b/components/list/index.js
@@ -13,7 +13,7 @@ import { listItemActionsFactory } from './ListItemActions.js';
import { listItemContentFactory } from './ListItemContent.js';
import { listItemLayoutFactory } from './ListItemLayout.js';
import themedRippleFactory from '../ripple';
-import theme from './theme.scss';
+import theme from './theme.css';
const applyTheme = (Component) => themr(LIST, theme)(Component);
const ripple = themedRippleFactory({ centered: false, listItemIgnore: true });
diff --git a/components/list/theme.css b/components/list/theme.css
new file mode 100644
index 00000000..4ec4fd74
--- /dev/null
+++ b/components/list/theme.css
@@ -0,0 +1,172 @@
+@import '../colors.css';
+@import '../variables.css';
+@import './config.css';
+
+.list {
+ composes: reset from '../helpers.css';
+ display: inline-block;
+ list-style: none;
+ margin: 0;
+ padding: var(--list-vertical-padding) 0;
+ position: relative;
+ text-align: left;
+ white-space: nowrap;
+ width: 100%;
+
+ & + .divider {
+ margin-top: calc(-1 * var(--list-vertical-padding));
+ }
+}
+
+.subheader {
+ color: var(--color-text-secondary);
+ font-size: var(--list-subheader-font-size);
+ font-weight: var(--list-subheader-font-weight);
+ line-height: var(--list-subheader-height);
+ margin: calc(-1 * var(--list-vertical-padding)) 0 0;
+ padding-left: var(--list-horizontal-padding);
+}
+
+.divider {
+ background-color: var(--color-divider);
+ border: 0;
+ height: var(--list-divider-height);
+ margin: calc(-1 * var(--list-divider-height)) 0 0;
+
+ &.inset {
+ margin-left: var(--list-content-left-spacing);
+ margin-right: var(--list-horizontal-padding);
+ }
+}
+
+.listItem {
+ position: relative;
+
+ & > [data-react-toolbox='ripple'] {
+ overflow: hidden;
+ }
+
+ & .ripple {
+ color: var(--color-text-secondary);
+ }
+
+ & ~ .divider {
+ margin-bottom: var(--list-vertical-padding);
+ margin-top: var(--list-vertical-padding);
+ }
+}
+
+.item {
+ align-items: center;
+ color: var(--color-text);
+ display: flex;
+ min-height: var(--list-item-min-height);
+ padding: 0 var(--list-horizontal-padding);
+ position: relative;
+
+ &.selectable:not(.disabled):hover {
+ background-color: var(--list-item-hover-color);
+ cursor: pointer;
+ }
+
+ &.disabled {
+ pointer-events: none;
+
+ &:not(.checkboxItem) {
+ opacity: 0.5;
+ }
+
+ & > .checkbox > [data-react-toolbox='label'] {
+ opacity: 0.5;
+ }
+ }
+}
+
+.left {
+ & [data-react-toolbox='font-icon'] {
+ width: var(--list-item-icon-size);
+ }
+
+ & :last-child {
+ & > [data-react-toolbox='font-icon'] {
+ margin-right: var(--list-item-right-icon-margin);
+ }
+ }
+}
+
+.right {
+ & > :last-child {
+ margin-right: 0;
+ }
+
+ & > :first-child {
+ margin-left: var(--list-horizontal-padding);
+ }
+}
+
+.left,
+.right {
+ align-items: center;
+ display: flex;
+ flex: 0 0 auto;
+}
+
+.itemAction {
+ display: flex;
+ margin: var(--list-item-child-margin) var(--list-horizontal-padding) var(--list-item-child-margin) 0;
+
+ & > * {
+ padding: 0;
+ }
+
+ & > [data-react-toolbox='font-icon'] {
+ color: var(--color-text-secondary);
+ font-size: var(--list-item-icon-font-size);
+ }
+}
+
+.itemContentRoot {
+ display: block;
+ flex-grow: 1;
+
+ &.large {
+ display: flex;
+ flex-direction: column;
+ height: var(--list-item-min-height-legend);
+ justify-content: center;
+ }
+}
+
+.checkbox {
+ align-items: center;
+ cursor: pointer;
+ display: flex;
+ height: 100%;
+ margin: 0;
+ min-height: var(--list-item-min-height);
+ width: 100%;
+
+ & > [data-react-toolbox='check'] {
+ margin-right: var(--list-item-right-checkbox-margin);
+ }
+
+ & > [data-react-toolbox='label'] {
+ padding-left: 0;
+ }
+}
+
+.itemText {
+ display: block;
+
+ &:not(.primary) {
+ color: var(--color-text-secondary);
+ font-size: var(--font-size-small);
+ padding-top: var(--list-item-legend-margin-top);
+ white-space: normal;
+ }
+
+ &.primary {
+ color: var(--color-text);
+ font-size: var(--font-size-normal);
+ }
+}
diff --git a/components/list/theme.scss b/components/list/theme.scss
deleted file mode 100644
index c2e77962..00000000
--- a/components/list/theme.scss
+++ /dev/null
@@ -1,169 +0,0 @@
-@import "../colors";
-@import "../globals";
-@import "../mixins";
-@import "./config";
-
-.list {
- position: relative;
- display: inline-block;
- width: 100%;
- padding: $list-vertical-padding 0;
- text-align: left;
- white-space: nowrap;
- list-style: none;
-
- & > a {
- display: block;
- text-decoration: none;
- cursor: pointer;
-
- &:hover {
- background-color: $list-item-hover-color;
- }
- }
-}
-
-.subheader {
- padding-left: $list-horizontal-padding;
- margin: - $list-vertical-padding 0 0;
- font-size: $list-subheader-font-size;
- font-weight: $list-subheader-font-weight;
- line-height: $list-subheader-height;
- color: $color-text-secondary;
-}
-
-.divider {
- height: $list-divider-height;
- margin: - $list-divider-height 0 0;
- background-color: $color-divider;
- border: 0;
- &.inset {
- margin-right: $list-horizontal-padding;
- margin-left: $list-content-left-spacing;
- }
- .list + & {
- margin-top: - $list-vertical-padding;
- }
- .listItem ~ & {
- margin-top: $list-vertical-padding;
- margin-bottom: $list-vertical-padding;
- }
-}
-
-.listItem {
- position: relative;
- > [data-react-toolbox="ripple"] {
- overflow: hidden;
- }
-
- .ripple {
- color: $color-text-secondary;
- }
-}
-
-.item {
- position: relative;
- display: flex;
- min-height: $list-item-min-height;
- align-items: center;
- padding: 0 $list-horizontal-padding;
- color: $color-text;
- &.selectable:not(.disabled):hover {
- cursor: pointer;
- background-color: $list-item-hover-color;
- }
- &.disabled {
- pointer-events: none;
- &:not(.checkboxItem) {
- opacity: .5;
- }
- > .checkbox > [data-react-toolbox="label"] {
- opacity: .5;
- }
- }
-}
-
-.left {
- [data-react-toolbox="font-icon"] {
- width: $list-item-icon-size;
- }
- & :last-child {
- > [data-react-toolbox="font-icon"] {
- margin-right: $list-item-right-icon-margin;
- }
- }
-}
-
-.right {
- > :last-child {
- margin-right: 0;
- }
-
- > :first-child {
- margin-left: $list-horizontal-padding;
- }
-}
-
-.left, .right {
- display: flex;
- flex: 0 0 auto;
- align-items: center;
- vertical-align: middle;
-}
-
-.itemAction {
- display: flex;
- margin: $list-item-child-margin $list-horizontal-padding $list-item-child-margin 0;
-
- > * {
- padding: 0;
- }
-
- > [data-react-toolbox="font-icon"] {
- font-size: $list-item-icon-font-size;
- color: $color-text-secondary;
- }
-}
-
-.itemContentRoot {
- display: block;
- flex-grow: 1;
- &.large {
- display: flex;
- height: $list-item-min-height-legend;
- flex-direction: column;
- justify-content: center;
- }
-}
-
-.checkbox {
- display: flex;
- width: 100%;
- height: 100%;
- min-height: $list-item-min-height;
- align-items: center;
- margin: 0;
- cursor: pointer;
- > [data-react-toolbox="check"] {
- margin-right: $list-item-right-checkbox-margin;
- }
- > [data-react-toolbox="label"] {
- padding-left: 0;
- }
-}
-
-.itemText {
- display: block;
-
- &:not(.primary) {
- padding-top: $list-item-legend-margin-top;
- font-size: $font-size-small;
- color: $color-text-secondary;
- white-space: normal;
- }
-
- &.primary {
- font-size: $font-size-normal;
- color: $color-text;
- }
-}
diff --git a/components/media.css b/components/media.css
new file mode 100644
index 00000000..465de5bb
--- /dev/null
+++ b/components/media.css
@@ -0,0 +1,32 @@
+/* Orientation */
+@custom-media --portrait (orientation: portrait);
+@custom-media --landscape (orientation: landscape);
+
+/* Devices (defined by max width) */
+@custom-media --xxs-viewport (max-width: 480px);
+@custom-media --xs-viewport (max-width: 600px);
+@custom-media --sm-tablet-viewport (max-width: 720px);
+@custom-media --sm-viewport (max-width: 840px);
+@custom-media --md-viewport (max-width: 960px);
+@custom-media --lg-tablet-viewport (max-width: 1024px);
+@custom-media --lg-viewport (max-width: 1280px);
+@custom-media --xl-viewport (max-width: 1440px);
+@custom-media --xxl-viewport (max-width: 1600px);
+@custom-media --xxxl-viewport (max-width: 1920px);
+
+/* Devices (defined by min-width) */
+@custom-media --larger-than-xxs-viewport (min-width: 480px);
+@custom-media --larger-than-xs-viewport (min-width: 600px);
+@custom-media --larger-than-sm-tablet-viewport (min-width: 720px);
+@custom-media --larger-than-sm-viewport (min-width: 840px);
+@custom-media --larger-than-md-viewport (min-width: 960px);
+@custom-media --larger-than-lg-tablet-viewport (min-width: 1024px);
+@custom-media --larger-than-lg-viewport (min-width: 1280px);
+@custom-media --larger-than-xl-viewport (min-width: 1440px);
+@custom-media --larger-than-xxl-viewport (min-width: 1600px);
+@custom-media --larger-than-xxxl-viewport (min-width: 1920px);
+
+:root {
+ --standard-increment-mobile: calc(5.6 * var(--unit));
+ --standard-increment-desktop: calc(6.4 * var(--unit));
+}
diff --git a/components/menu/Menu.js b/components/menu/Menu.js
index 67bc5e49..2be53511 100644
--- a/components/menu/Menu.js
+++ b/components/menu/Menu.js
@@ -3,7 +3,8 @@ import ReactDOM from 'react-dom';
import classnames from 'classnames';
import { themr } from 'react-css-themr';
import { MENU } from '../identifiers.js';
-import { events, utils } from '../utils';
+import { events } from '../utils';
+import { getViewport } from '../utils/utils';
import InjectMenuItem from './MenuItem.js';
const POSITION = {
@@ -154,7 +155,7 @@ const factory = (MenuItem) => {
const parentNode = ReactDOM.findDOMNode(this).parentNode;
if (!parentNode) return;
const {top, left, height, width} = parentNode.getBoundingClientRect();
- const {height: wh, width: ww} = utils.getViewport();
+ const {height: wh, width: ww} = getViewport();
const toTop = top < ((wh / 2) - height / 2);
const toLeft = left < ((ww / 2) - width / 2);
return `${toTop ? 'top' : 'bottom'}${toLeft ? 'Left' : 'Right'}`;
diff --git a/components/menu/_config.scss b/components/menu/_config.scss
deleted file mode 100644
index 0b534366..00000000
--- a/components/menu/_config.scss
+++ /dev/null
@@ -1,16 +0,0 @@
-$menu-expand-duration: .3s !default;
-$menu-fade-duration: .2s !default;
-$menu-ripple-delay: .3s !default;
-$menu-background-color: $color-white !default;
-$menu-padding: .8 * $unit 0 !default;
-$menu-outline-border-radius: .2 * $unit !default;
-$menu-item-hover-background: $palette-grey-200 !default;
-$menu-item-selected-background: transparent !default;
-$menu-item-icon-font-size: 2.4 * $unit !default;
-$menu-item-icon-size: 1.6 * $menu-item-icon-font-size !default;
-$menu-item-height: 4.8 * $unit !default;
-$menu-item-padding: 1.6 * $unit !default;
-$menu-item-font-size: 1.6 * $unit !default;
-$menu-divider-height: (4.8 * $unit) / 4 !default;
-$menu-icon-size: 2.3 * $unit !default;
-$menu-icon-ripple-duration: 650ms !default;
diff --git a/components/menu/config.css b/components/menu/config.css
new file mode 100644
index 00000000..58e2a786
--- /dev/null
+++ b/components/menu/config.css
@@ -0,0 +1,18 @@
+:root {
+ --menu-expand-duration: 0.3s;
+ --menu-fade-duration: 0.2s;
+ --menu-ripple-delay: 0.3s;
+ --menu-background-color: var(--color-white);
+ --menu-padding: calc(0.8 * var(--unit)) 0;
+ --menu-outline-border-radius: calc(0.2 * var(--unit));
+ --menu-item-hover-background: var(--palette-grey-200);
+ --menu-item-selected-background: transparent;
+ --menu-item-icon-font-size: calc(2.4 * var(--unit));
+ --menu-item-icon-size: calc(1.6 * var(--menu-item-icon-font-size));
+ --menu-item-height: calc(4.8 * var(--unit));
+ --menu-item-padding: calc(1.6 * var(--unit));
+ --menu-item-font-size: calc(1.6 * var(--unit));
+ --menu-divider-height: calc((4.8 / 4) * var(--unit)));
+ --menu-icon-size: calc(2.3 * var(--unit));
+ --menu-icon-ripple-duration: 650ms;
+}
diff --git a/components/menu/index.js b/components/menu/index.js
index e5a52a3c..f5d71dba 100644
--- a/components/menu/index.js
+++ b/components/menu/index.js
@@ -6,7 +6,7 @@ import { menuItemFactory } from './MenuItem.js';
import { menuFactory } from './Menu.js';
import { iconMenuFactory } from './IconMenu.js';
import themedRippleFactory from '../ripple';
-import theme from './theme.scss';
+import theme from './theme.css';
const applyTheme = (Component) => themr(MENU, theme)(Component);
const ThemedMenuDivider = applyTheme(MenuDivider);
diff --git a/components/menu/theme.css b/components/menu/theme.css
new file mode 100644
index 00000000..3b3606af
--- /dev/null
+++ b/components/menu/theme.css
@@ -0,0 +1,181 @@
+@import '../colors.css';
+@import '../variables.css';
+@import './config.css';
+
+.iconMenu {
+ composes: reset from '../helpers.css';
+ display: inline-block;
+ position: relative;
+ text-align: center;
+
+ & .icon {
+ cursor: pointer;
+ }
+}
+
+.menu {
+ display: inline-block;
+ position: relative;
+
+ &.topLeft {
+ left: 0;
+ position: absolute;
+ top: 0;
+
+ & > .outline {
+ transform-origin: 0 0;
+ }
+ }
+
+ &.topRight {
+ position: absolute;
+ right: 0;
+ top: 0;
+
+ & > .outline {
+ transform-origin: 100% 0;
+ }
+ }
+
+ &.bottomLeft {
+ bottom: 0;
+ left: 0;
+ position: absolute;
+
+ & > .outline {
+ transform-origin: 0 100%;
+ }
+ }
+
+ &.bottomRight {
+ bottom: 0;
+ position: absolute;
+ right: 0;
+
+ & > .outline {
+ transform-origin: 100% 100%;
+ }
+ }
+
+ &:not(.static) {
+ pointer-events: none;
+ z-index: var(--z-index-higher);
+
+ & > .outline {
+ opacity: 0;
+ transform: scale(0);
+ transition:
+ transform var(--menu-expand-duration) var(--animation-curve-default),
+ opacity var(--menu-fade-duration) var(--animation-curve-default);
+ will-change: transform;
+ }
+
+ & > .menuInner {
+ left: 0;
+ margin: 0;
+ opacity: 0;
+ position: absolute;
+ top: 0;
+ }
+
+ &.rippled:not(.active) {
+ & > .outline {
+ transition-delay: var(--menu-ripple-delay);
+ }
+
+ & > .menuInner {
+ transition-delay: var(--menu-ripple-delay);
+ }
+ }
+
+ &.active {
+ pointer-events: all;
+
+ & > .outline {
+ opacity: 1;
+ transform: scale(1);
+ }
+
+ & > .menuInner {
+ opacity: 1;
+ transition:
+ opacity var(--menu-fade-duration) var(--animation-curve-default),
+ clip var(--menu-expand-duration) var(--animation-curve-default);
+ }
+ }
+ }
+}
+
+.outline {
+ background-color: var(--menu-background-color);
+ border-radius: var(--menu-outline-border-radius);
+ box-shadow: var(--shadow-2p);
+ display: block;
+ left: 0;
+ position: absolute;
+ top: 0;
+}
+
+.menuInner {
+ display: block;
+ list-style: none;
+ padding: var(--menu-padding);
+ position: relative;
+ text-align: left;
+ white-space: nowrap;
+}
+
+.menuItem {
+ align-items: center;
+ color: var(--color-text);
+ display: flex;
+ font-size: var(--menu-item-font-size);
+ height: var(--menu-item-height);
+ overflow: hidden;
+ padding: 0 var(--menu-item-padding);
+ position: relative;
+
+ &:not(.disabled):hover {
+ background-color: var(--menu-item-hover-background);
+ cursor: pointer;
+ }
+
+ &.disabled {
+ opacity: 0.5;
+ pointer-events: none;
+ }
+
+ &.selected {
+ background-color: var(--menu-item-selected-background);
+ font-weight: 500;
+ }
+
+ & .ripple {
+ color: var(--color-text-secondary);
+ }
+
+ & .icon {
+ font-size: var(--menu-item-icon-font-size);
+ width: var(--menu-item-icon-size);
+ }
+}
+
+.caption {
+ flex-grow: 1;
+ font-size: var(--font-size-normal);
+}
+
+.shortcut {
+ margin-left: var(--menu-item-padding);
+}
+
+.menuDivider {
+ background-color: var(--color-divider);
+ border: 0;
+ display: block;
+ height: 1px;
+ margin: var(--menu-divider-height) 0;
+ outline: 0;
+ padding: 0;
+ width: 100%;
+}
diff --git a/components/menu/theme.scss b/components/menu/theme.scss
deleted file mode 100644
index 9f4ec9b3..00000000
--- a/components/menu/theme.scss
+++ /dev/null
@@ -1,154 +0,0 @@
-@import "../colors";
-@import "../globals";
-@import "../mixins";
-@import "./config";
-
-.iconMenu {
- position: relative;
- display: inline-block;
- text-align: center;
- .icon {
- cursor: pointer;
- }
-}
-
-.menu {
- position: relative;
- display: inline-block;
- &.topLeft {
- position: absolute;
- top: 0;
- left: 0;
- > .outline {
- transform-origin: 0 0;
- }
- }
- &.topRight {
- position: absolute;
- top: 0;
- right: 0;
- > .outline {
- transform-origin: 100% 0;
- }
- }
- &.bottomLeft {
- position: absolute;
- bottom: 0;
- left: 0;
- > .outline {
- transform-origin: 0 100%;
- }
- }
- &.bottomRight {
- position: absolute;
- right: 0;
- bottom: 0;
- > .outline {
- transform-origin: 100% 100%;
- }
- }
- &:not(.static) {
- z-index: $z-index-higher;
- pointer-events: none;
- > .outline {
- opacity: 0;
- transition: transform $menu-expand-duration $animation-curve-default,
- opacity $menu-fade-duration $animation-curve-default;
- transform: scale(0);
- will-change: transform;
- }
- > .menuInner {
- position: absolute;
- top: 0;
- left: 0;
- opacity: 0;
- }
- &.rippled:not(.active) {
- > .outline {
- transition-delay: $menu-ripple-delay;
- }
- > .menuInner {
- transition-delay: $menu-ripple-delay;
- }
- }
- &.active {
- pointer-events: all;
- > .outline {
- opacity: 1;
- transform: scale(1);
- }
- > .menuInner {
- opacity: 1;
- transition: opacity $menu-fade-duration $animation-curve-default,
- clip $menu-expand-duration $animation-curve-default;
- }
- }
- }
-}
-
-.outline {
- @include shadow-2dp();
- position: absolute;
- top: 0;
- left: 0;
- display: block;
- background-color: $menu-background-color;
- border-radius: $menu-outline-border-radius;
-}
-
-.menuInner {
- position: relative;
- display: block;
- padding: $menu-padding;
- text-align: left;
- white-space: nowrap;
- list-style: none;
-}
-
-.menuItem {
- position: relative;
- display: flex;
- height: $menu-item-height;
- align-items: center;
- padding: 0 $menu-item-padding;
- overflow: hidden;
- font-size: $menu-item-font-size;
- color: $color-text;
- &:not(.disabled):hover {
- cursor: pointer;
- background-color: $menu-item-hover-background;
- }
- &.disabled {
- pointer-events: none;
- opacity: .5;
- }
- &.selected {
- font-weight: 500;
- background-color: $menu-item-selected-background;
- }
- .ripple {
- color: $color-text-secondary;
- }
-
- .icon {
- width: $menu-item-icon-size;
- font-size: $menu-item-icon-font-size !important;
- }
-}
-
-.caption {
- flex-grow: 1;
- font-size: $font-size-normal;
-}
-
-.shortcut {
- margin-left: $menu-item-padding;
-}
-
-.menuDivider {
- display: block;
- width: 100%;
- height: 1px;
- margin: $menu-divider-height 0;
- background-color: $color-divider;
-}
diff --git a/components/navigation/_config.scss b/components/navigation/_config.scss
deleted file mode 100644
index 6b654ac7..00000000
--- a/components/navigation/_config.scss
+++ /dev/null
@@ -1,2 +0,0 @@
-$navigation-space: $unit !default;
-$navigation-color: $color-black !default;
diff --git a/components/navigation/config.css b/components/navigation/config.css
new file mode 100644
index 00000000..a70c1905
--- /dev/null
+++ b/components/navigation/config.css
@@ -0,0 +1,4 @@
+:root {
+ --navigation-space: var(--unit);
+ --navigation-color: var(--color-black);
+}
diff --git a/components/navigation/index.js b/components/navigation/index.js
index d02ab54d..e7bef03d 100644
--- a/components/navigation/index.js
+++ b/components/navigation/index.js
@@ -3,7 +3,7 @@ import { NAVIGATION } from '../identifiers.js';
import { navigationFactory } from './Navigation.js';
import { Button } from '../button';
import { Link } from '../link';
-import theme from './theme.scss';
+import theme from './theme.css';
const ThemedNavigation = themr(NAVIGATION, theme)(navigationFactory(Button, Link));
export default ThemedNavigation;
diff --git a/components/navigation/theme.css b/components/navigation/theme.css
new file mode 100644
index 00000000..3cf23c36
--- /dev/null
+++ b/components/navigation/theme.css
@@ -0,0 +1,29 @@
+@import '../colors.css';
+@import '../variables.css';
+@import './config.css';
+
+.horizontal {
+ & > [data-react-toolbox='button'],
+ & > [data-react-toolbox='link'] {
+ display: inline-block;
+ margin: 0 calc(var(--navigation-space) / 2);
+ }
+}
+
+.vertical {
+ & > [data-react-toolbox='button'],
+ & > [data-react-toolbox='link'] {
+ display: block;
+ margin: calc(var(--navigation-space) / 2);
+ }
+}
+
+.vertical,
+.horizontal {
+ composes: reset from '../helpers.css';
+ padding: calc(var(--navigation-space) / 2);
+
+ & > [data-react-toolbox='link'] {
+ color: var(--navigation-color);
+ }
+}
diff --git a/components/navigation/theme.scss b/components/navigation/theme.scss
deleted file mode 100644
index 2d8375fd..00000000
--- a/components/navigation/theme.scss
+++ /dev/null
@@ -1,26 +0,0 @@
-@import "../colors";
-@import "../globals";
-@import "../mixins";
-@import "./config";
-
-.horizontal {
- > [data-react-toolbox="button"], > [data-react-toolbox="link"] {
- display: inline-block;
- margin: 0 $navigation-space / 2;
- }
-}
-
-.vertical {
- > [data-react-toolbox="button"], > [data-react-toolbox="link"] {
- display: block;
- margin: $navigation-space / 2;
- }
-}
-
-.vertical, .horizontal {
- padding: $navigation-space / 2;
-
- > [data-react-toolbox="link"] {
- color: $navigation-color;
- }
-}
diff --git a/components/overlay/Overlay.js b/components/overlay/Overlay.js
index ffce05dc..312ffbe5 100644
--- a/components/overlay/Overlay.js
+++ b/components/overlay/Overlay.js
@@ -2,49 +2,63 @@ import React, { Component, PropTypes } from 'react';
import classnames from 'classnames';
import { themr } from 'react-css-themr';
import { OVERLAY } from '../identifiers.js';
-import Portal from '../hoc/Portal.js';
class Overlay extends Component {
static propTypes = {
active: PropTypes.bool,
children: PropTypes.node,
className: PropTypes.string,
- invisible: PropTypes.bool,
+ lockScroll: PropTypes.bool,
onClick: PropTypes.func,
onEscKeyDown: PropTypes.func,
theme: PropTypes.shape({
active: PropTypes.string,
backdrop: PropTypes.string,
- invisible: PropTypes.string,
overlay: PropTypes.string
})
};
static defaultProps = {
- invisible: false
+ lockScroll: true
};
componentDidMount () {
- if (this.props.active) {
- document.body.addEventListener('keydown', this.handleEscKey);
- document.body.style.overflow = 'hidden';
- }
+ const { active, lockScroll, onEscKeyDown } = this.props;
+ if (onEscKeyDown) document.body.addEventListener('keydown', this.handleEscKey.bind(this));
+ if (active && lockScroll) document.body.style.overflow = 'hidden';
}
componentWillUpdate (nextProps) {
- if (nextProps.active && !this.props.active) document.body.style.overflow = 'hidden';
- if (!nextProps.active && this.props.active && !document.querySelectorAll('[data-react-toolbox="overlay"]')[1]) document.body.style.overflow = '';
+ if (this.props.lockScroll) {
+ const becomingActive = nextProps.active && !this.props.active;
+ const becomingUnactive = !nextProps.active && this.props.active;
+
+ if (becomingActive) {
+ document.body.style.overflow = 'hidden';
+ }
+
+ if (becomingUnactive && !document.querySelectorAll('[data-react-toolbox="overlay"]')[1]) {
+ document.body.style.overflow = '';
+ }
+ }
}
- componentDidUpdate () {
- if (this.props.active) {
- document.body.addEventListener('keydown', this.handleEscKey);
+ componentDidUpdate (prevProps) {
+ if (this.props.active && !prevProps.active && this.props.onEscKeyDown) {
+ document.body.addEventListener('keydown', this.handleEscKey.bind(this));
}
}
componentWillUnmount () {
- if (!document.querySelectorAll('[data-react-toolbox="overlay"]')[1]) document.body.style.overflow = '';
- document.body.removeEventListener('keydown', this.handleEscKey);
+ if (this.props.active && this.props.lockScroll) {
+ if (!document.querySelectorAll('[data-react-toolbox="overlay"]')[1]) {
+ document.body.style.overflow = '';
+ }
+ }
+
+ if (this.props.onEscKeyDown) {
+ document.body.removeEventListener('keydown', this.handleEscKey);
+ }
}
handleEscKey = (e) => {
@@ -53,20 +67,24 @@ class Overlay extends Component {
}
}
- render () {
- const { active, className, children, invisible, onClick, theme } = this.props;
- const _className = classnames(theme.overlay, {
- [theme.active]: active,
- [theme.invisible]: invisible
- }, className);
+ handleClick = event => {
+ event.preventDefault();
+ event.stopPropagation();
+ if (this.props.onClick) {
+ this.props.onClick(event);
+ }
+ }
+ render () {
+ const { active, className, lockScroll, theme, onEscKeyDown, ...other } = this.props; // eslint-disable-line
return (
-
-
-
+
);
}
}
diff --git a/components/overlay/_config.scss b/components/overlay/_config.scss
deleted file mode 100644
index ccba4d3c..00000000
--- a/components/overlay/_config.scss
+++ /dev/null
@@ -1,2 +0,0 @@
-$overlay-color: $color-black !default;
-$overlay-opacity: .6 !default;
diff --git a/components/overlay/config.css b/components/overlay/config.css
new file mode 100644
index 00000000..ff6676a1
--- /dev/null
+++ b/components/overlay/config.css
@@ -0,0 +1,4 @@
+:root {
+ --overlay-color: var(--color-black);
+ --overlay-opacity: 0.6;
+}
diff --git a/components/overlay/index.js b/components/overlay/index.js
index 818edb28..7f1bf55a 100644
--- a/components/overlay/index.js
+++ b/components/overlay/index.js
@@ -1,7 +1,7 @@
import { themr } from 'react-css-themr';
import { OVERLAY } from '../identifiers.js';
import { Overlay } from './Overlay.js';
-import theme from './theme.scss';
+import theme from './theme.css';
const ThemedOverlay = themr(OVERLAY, theme)(Overlay);
export default ThemedOverlay;
diff --git a/components/overlay/theme.css b/components/overlay/theme.css
new file mode 100644
index 00000000..e8b1328f
--- /dev/null
+++ b/components/overlay/theme.css
@@ -0,0 +1,21 @@
+@import '../colors.css';
+@import '../variables.css';
+@import './config.css';
+
+.overlay {
+ background-color: var(--overlay-color);
+ bottom: 0;
+ height: 100vh;
+ left: 0;
+ opacity: 0;
+ pointer-events: none;
+ position: fixed;
+ top: 0;
+ transition: opacity var(--animation-duration) var(--animation-curve-default);
+ width: 100vw;
+
+ &.active {
+ opacity: var(--overlay-opacity);
+ pointer-events: all;
+ }
+}
diff --git a/components/overlay/theme.scss b/components/overlay/theme.scss
deleted file mode 100644
index e740884e..00000000
--- a/components/overlay/theme.scss
+++ /dev/null
@@ -1,42 +0,0 @@
-@import "../colors";
-@import "../globals";
-@import "../mixins";
-@import "./config";
-
-.overlay {
- position: fixed;
- top: 0;
- left: 0;
- z-index: $z-index-highest;
- display: flex;
- width: 100vw;
- height: 100vh;
- flex-direction: column;
- align-content: center;
- align-items: center;
- justify-content: center;
- pointer-events: none;
- &.invisible > *:not(.backdrop) {
- pointer-events: all;
- }
-}
-
-.backdrop {
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- background-color: $overlay-color;
- opacity: 0;
- transition-timing-function: $animation-curve-default;
- transition-duration: $animation-duration;
- transition-property: opacity;
-}
-
-.active {
- pointer-events: all;
- > .backdrop {
- opacity: $overlay-opacity;
- }
-}
diff --git a/components/progress_bar/__test__/index.spec.js b/components/progress_bar/__test__/index.spec.js
index 52e9ae17..46d659c7 100644
--- a/components/progress_bar/__test__/index.spec.js
+++ b/components/progress_bar/__test__/index.spec.js
@@ -2,7 +2,7 @@ import React from 'react';
import expect from 'expect';
import TestUtils from 'react-addons-test-utils';
import ProgressBar, { ProgressBar as RawProgressBar } from '../ProgressBar';
-import theme from '../theme.scss';
+import theme from '../theme.css';
import utils from '../../utils/testing';
describe('ProgressBar', function () {
diff --git a/components/progress_bar/_config.scss b/components/progress_bar/_config.scss
deleted file mode 100644
index 143a8096..00000000
--- a/components/progress_bar/_config.scss
+++ /dev/null
@@ -1,7 +0,0 @@
-$progress-height: .4 * $unit !default;
-$progress-main-color: $color-primary !default;
-$progress-secondary-color: rgba($color-primary-contrast, 0.7) !default;
-$progress-disabled-color: rgba($color-black, 0.26) !default;
-$circle-wrapper-width: 60 !default;
-$circle-radius: 25 !default;
-$scale-ratio: $circle-radius / 20 !default;
diff --git a/components/progress_bar/config.css b/components/progress_bar/config.css
new file mode 100644
index 00000000..c9ecfd78
--- /dev/null
+++ b/components/progress_bar/config.css
@@ -0,0 +1,9 @@
+:root {
+ --progress-height: calc(0.4 * var(--unit));
+ --progress-main-color: var(--color-primary);
+ --progress-secondary-color: color(var(--color-primary-contrast) a(70%));
+ --progress-disabled-color: color(var(--color-black) a(26%));
+ --circle-wrapper-width: 60;
+ --circle-radius: 25;
+ --scale-ratio: calc(var(--circle-radius) / 20);
+}
diff --git a/components/progress_bar/index.js b/components/progress_bar/index.js
index 6c4a36d1..f4694375 100644
--- a/components/progress_bar/index.js
+++ b/components/progress_bar/index.js
@@ -1,7 +1,7 @@
import { themr } from 'react-css-themr';
import { PROGRESS_BAR } from '../identifiers.js';
import { ProgressBar } from './ProgressBar.js';
-import theme from './theme.scss';
+import theme from './theme.css';
const ThemedProgressBar = themr(PROGRESS_BAR, theme)(ProgressBar);
diff --git a/components/progress_bar/theme.css b/components/progress_bar/theme.css
new file mode 100644
index 00000000..305897ca
--- /dev/null
+++ b/components/progress_bar/theme.css
@@ -0,0 +1,154 @@
+@import '../colors.css';
+@import '../variables.css';
+@import './config.css';
+
+.linear {
+ background: var(--color-divider);
+ display: inline-block;
+ height: var(--progress-height);
+ overflow: hidden;
+ position: relative;
+ width: 100%;
+
+ &.indeterminate .value {
+ animation: linear-indeterminate-bar 1s linear infinite;
+ transform-origin: center center;
+ }
+}
+
+.value,
+.buffer {
+ bottom: 0;
+ left: 0;
+ position: absolute;
+ right: 0;
+ top: 0;
+ transform: scaleX(0);
+ transform-origin: left center;
+ transition-duration: var(--animation-duration);
+ transition-timing-function: var(--animation-curve-default);
+}
+
+.value {
+ background-color: var(--progress-main-color);
+}
+
+.buffer {
+ background-image:
+ linear-gradient(to right, var(--progress-secondary-color), var(--progress-secondary-color)),
+ linear-gradient(to right, var(--progress-main-color), var(--progress-main-color));
+}
+
+.circular {
+ display: inline-block;
+ height: calc(var(--circle-wrapper-width) * 1px);
+ position: relative;
+ transform: rotate(-90deg);
+ width: calc(var(--circle-wrapper-width) * 1px);
+
+ &.indeterminate {
+ & .circle {
+ animation: circular-indeterminate-bar-rotate 2s linear infinite;
+ }
+
+ & .path {
+ animation: circular-indeterminate-bar-dash 1.5s ease-in-out infinite;
+ stroke-dasharray: calc(var(--scale-ratio) * 1), calc(var(--scale-ratio) * 200);
+ stroke-dashoffset: 0;
+ }
+
+ &.multicolor .path {
+ animation:
+ circular-indeterminate-bar-dash 1.5s ease-in-out infinite,
+ colors calc(1.5s * 4) ease-in-out infinite;
+ }
+ }
+}
+
+.circular[disabled],
+.linear[disabled] {
+ & .value {
+ background-color: var(--progress-disabled-color);
+ }
+
+ & .buffer {
+ background-image:
+ linear-gradient(to right, var(--progress-secondary-color), var(--progress-secondary-color)),
+ linear-gradient(to right, var(--progress-disabled-color), var(--progress-disabled-color));
+ }
+}
+
+.circle {
+ height: 100%;
+ width: 100%;
+}
+
+.path {
+ fill: none;
+ stroke: var(--progress-main-color);
+ stroke-dasharray: 0, calc(var(--scale-ratio) * 200);
+ stroke-dashoffset: 0;
+ stroke-linecap: round;
+ stroke-miterlimit: 20;
+ stroke-width: 4;
+ transition: stroke-dasharray var(--animation-duration) var(--animation-curve-default);
+}
+
+@keyframes linear-indeterminate-bar {
+ 0% {
+ transform: translate(-50%) scaleX(0);
+ }
+
+ 50% {
+ transform: translate(-0%) scaleX(0.3);
+ }
+
+ 100% {
+ transform: translate(50%) scaleX(0);
+ }
+}
+
+@keyframes circular-indeterminate-bar-rotate {
+ 100% {
+ transform: rotate(360deg);
+ }
+}
+
+@keyframes circular-indeterminate-bar-dash {
+ 0% {
+ stroke-dasharray: calc(var(--scale-ratio) * 1), calc(var(--scale-ratio) * 200);
+ stroke-dashoffset: calc(var(--scale-ratio) * 0);
+ }
+
+ 50% {
+ stroke-dasharray: calc(var(--scale-ratio) * 89), calc(var(--scale-ratio) * 200);
+ stroke-dashoffset: calc(var(--scale-ratio) * -35);
+ }
+
+ 100% {
+ stroke-dasharray: calc(var(--scale-ratio) * 89), calc(var(--scale-ratio) * 200);
+ stroke-dashoffset: calc(var(--scale-ratio) * -124);
+ }
+}
+
+@keyframes colors {
+ 0% {
+ stroke: #4285f4;
+ }
+
+ 25% {
+ stroke: #de3e35;
+ }
+
+ 50% {
+ stroke: #f7c223;
+ }
+
+ 75% {
+ stroke: #1b9a59;
+ }
+
+ 100% {
+ stroke: #4285f4;
+ }
+}
diff --git a/components/progress_bar/theme.scss b/components/progress_bar/theme.scss
deleted file mode 100644
index 6f5cc2c1..00000000
--- a/components/progress_bar/theme.scss
+++ /dev/null
@@ -1,146 +0,0 @@
-@import "../colors";
-@import "../globals";
-@import "../mixins";
-@import "./config";
-
-.linear {
- position: relative;
- display: inline-block;
- width: 100%;
- height: $progress-height;
- overflow: hidden;
- background: $color-divider;
- &.indeterminate .value {
- transform-origin: center center;
- animation: linear-indeterminate-bar 1s linear infinite;
- }
-}
-
-.value, .buffer {
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- transition-timing-function: $animation-curve-default;
- transition-duration: $animation-duration;
- transform: scaleX(0);
- transform-origin: left center;
-}
-
-.value {
- background-color: $progress-main-color;
-}
-
-[disabled] .value {
- background-color: $progress-disabled-color;
-}
-
-.buffer {
- background-image: linear-gradient(to right, $progress-secondary-color, $progress-secondary-color),
- linear-gradient(to right, $progress-main-color, $progress-main-color);
-}
-
-[disabled] .buffer {
- background-image: linear-gradient(to right, $progress-secondary-color, $progress-secondary-color),
- linear-gradient(to right, $progress-disabled-color, $progress-disabled-color);
-}
-
-.circular {
- position: relative;
- display: inline-block;
- width: $circle-wrapper-width * 1px;
- height: $circle-wrapper-width * 1px;
- transform: rotate(-90deg);
- &.indeterminate {
- .circle {
- animation: circular-indeterminate-bar-rotate 2s linear infinite;
- }
- .path {
- animation: circular-indeterminate-bar-dash 1.5s ease-in-out infinite;
-
- stroke-dasharray: $scale-ratio * 1, $scale-ratio * 200;
- stroke-dashoffset: 0;
- }
- &.multicolor .path {
- animation: circular-indeterminate-bar-dash 1.5s ease-in-out infinite,
- colors (1.5s * 4) ease-in-out infinite;
- }
- }
-}
-
-.circle {
- width: 100%;
- height: 100%;
-}
-
-.path {
- transition: stroke-dasharray $animation-duration $animation-curve-default;
- fill: none;
-
- stroke-dasharray: 0, $scale-ratio * 200;
- stroke-dashoffset: 0;
- stroke-linecap: round;
- stroke-miterlimit: 20;
- stroke-width: 4;
- stroke: $progress-main-color;
-}
-
-@keyframes linear-indeterminate-bar {
- 0% {
- transform: translate(-50%) scaleX(0);
- }
-
- 50% {
- transform: translate(-0%) scaleX(.3);
- }
-
- 100% {
- transform: translate(50%) scaleX(0);
- }
-}
-
-@keyframes circular-indeterminate-bar-rotate {
- 100% {
- transform: rotate(360deg);
- }
-}
-
-@keyframes circular-indeterminate-bar-dash {
- 0% {
- stroke-dasharray: $scale-ratio * 1, $scale-ratio * 200;
- stroke-dashoffset: $scale-ratio * 0;
- }
-
- 50% {
- stroke-dasharray: $scale-ratio * 89, $scale-ratio * 200;
- stroke-dashoffset: $scale-ratio * -35;
- }
-
- 100% {
- stroke-dasharray: $scale-ratio * 89, $scale-ratio * 200;
- stroke-dashoffset: $scale-ratio * -124;
- }
-}
-
-@keyframes colors {
- 0% {
- stroke: #4285f4;
- }
-
- 25% {
- stroke: #de3e35;
- }
-
- 50% {
- stroke: #f7c223;
- }
-
- 75% {
- stroke: #1b9a59;
- }
-
- 100% {
- stroke: #4285f4;
- }
-}
diff --git a/components/radio/_config.scss b/components/radio/_config.scss
deleted file mode 100644
index 0c335c7c..00000000
--- a/components/radio/_config.scss
+++ /dev/null
@@ -1,9 +0,0 @@
-$radio-field-margin-bottom: 1.5 * $unit !default;
-$radio-button-size: 2 * $unit !default;
-$radio-inner-margin: $radio-button-size / 4 !default;
-$radio-inner-color: $color-primary !default;
-$radio-focus-color: rgba($color-black, 0.1) !default;
-$radio-checked-focus-color: rgba($color-primary, 0.26) !default;
-$radio-text-color: $color-black !default;
-$radio-disabled-color: rgba($color-black, 0.26) !default;
-$radio-text-font-size: 1.4 * $unit !default;
diff --git a/components/radio/config.css b/components/radio/config.css
new file mode 100644
index 00000000..5c35d83d
--- /dev/null
+++ b/components/radio/config.css
@@ -0,0 +1,11 @@
+:root {
+ --radio-field-margin-bottom: calc(1.5 * var(--unit));
+ --radio-button-size: calc(2 * var(--unit));
+ --radio-inner-margin: calc(var(--radio-button-size) / 4);
+ --radio-inner-color: var(--color-primary);
+ --radio-focus-color: color(var(--color-black) a(10%));
+ --radio-checked-focus-color: color(var(--color-primary) a(26%));
+ --radio-text-color: var(--color-black);
+ --radio-disabled-color: color(var(--color-black) a(26%));
+ --radio-text-font-size: calc(1.4 * var(--unit));
+}
diff --git a/components/radio/index.js b/components/radio/index.js
index 62167cce..bf8419e1 100644
--- a/components/radio/index.js
+++ b/components/radio/index.js
@@ -4,7 +4,7 @@ import themedRippleFactory from '../ripple';
import radioFactory from './Radio.js';
import { radioButtonFactory } from './RadioButton.js';
import { radioGroupFactory } from './RadioGroup.js';
-import theme from './theme.scss';
+import theme from './theme.css';
const ThemedRadio = radioFactory(themedRippleFactory({ centered: true, spread: 2.6}));
const ThemedRadioButton = themr(RADIO, theme)(radioButtonFactory(ThemedRadio));
diff --git a/components/radio/theme.css b/components/radio/theme.css
new file mode 100644
index 00000000..f6792268
--- /dev/null
+++ b/components/radio/theme.css
@@ -0,0 +1,102 @@
+@import '../colors.css';
+@import '../variables.css';
+@import './config.css';
+
+.radio {
+ border: calc(0.2 * var(--unit)) solid var(--radio-text-color);
+ border-radius: 50%;
+ composes: reset from '../helpers.css';
+ cursor: pointer;
+ display: inline-block;
+ height: var(--radio-button-size);
+ position: relative;
+ vertical-align: top;
+ width: var(--radio-button-size);
+
+ &::before {
+ background-color: var(--radio-inner-color);
+ border-radius: 50%;
+ content: '';
+ height: 100%;
+ left: 0;
+ position: absolute;
+ top: 0;
+ transform: scale(0);
+ transition: transform 0.2s var(--animation-curve-default);
+ width: 100%;
+ }
+
+ & .ripple {
+ background-color: var(--radio-inner-color);
+ opacity: 0.3;
+ transition-duration: 650ms;
+ }
+}
+
+.radioChecked {
+ border: calc(0.2 * var(--unit)) solid var(--radio-inner-color);
+ composes: radio;
+
+ &::before {
+ transform: scale(0.65);
+ }
+}
+
+.field {
+ display: block;
+ height: var(--radio-button-size);
+ margin-bottom: var(--radio-field-margin-bottom);
+ position: relative;
+ white-space: nowrap;
+}
+
+.text {
+ color: var(--radio-text-color);
+ display: inline-block;
+ font-size: var(--radio-text-font-size);
+ line-height: var(--radio-button-size);
+ padding-left: var(--unit);
+ vertical-align: top;
+ white-space: nowrap;
+}
+
+.input {
+ appearance: none;
+ border: 0;
+ height: 0;
+ margin: 0;
+ opacity: 0;
+ padding: 0;
+ position: absolute;
+ width: 0;
+
+ &:focus ~ .radio {
+ box-shadow: 0 0 0 var(--unit) var(--radio-focus-color);
+ }
+
+ &:focus ~ .radioChecked {
+ box-shadow: 0 0 0 var(--unit) var(--radio-checked-focus-color);
+ }
+}
+
+.disabled {
+ composes: field;
+
+ & .text {
+ color: var(--radio-disabled-color);
+ }
+
+ & .radio {
+ border-color: var(--radio-disabled-color);
+ cursor: auto;
+ }
+
+ & .radioChecked {
+ border-color: var(--radio-disabled-color);
+ cursor: auto;
+
+ &::before {
+ background-color: var(--radio-disabled-color);
+ }
+ }
+}
diff --git a/components/radio/theme.scss b/components/radio/theme.scss
deleted file mode 100644
index 93eac42e..00000000
--- a/components/radio/theme.scss
+++ /dev/null
@@ -1,95 +0,0 @@
-@import "../colors";
-@import "../globals";
-@import "../mixins";
-@import "./config";
-
-.radio {
- position: relative;
- display: inline-block;
- width: $radio-button-size;
- height: $radio-button-size;
- vertical-align: top;
- cursor: pointer;
- border: .2 * $unit solid $radio-text-color;
- border-radius: 50%;
- &:before {
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- content: "";
- background-color: $radio-inner-color;
- border-radius: 50%;
- transition: transform $animation-duration $animation-curve-default;
- transform: scale(0);
- }
-
- .ripple {
- background-color: $radio-inner-color;
- opacity: .3;
- transition-duration: 650ms;
- }
-}
-
-.radioChecked {
- @extend .radio;
- border: .2 * $unit solid $radio-inner-color;
- &:before {
- transform: scale(0.65);
- }
-}
-
-.field {
- position: relative;
- display: block;
- height: $radio-button-size;
- margin-bottom: $radio-field-margin-bottom;
- white-space: nowrap;
- vertical-align: middle;
-}
-
-.text {
- display: inline-block;
- padding-left: $unit;
- font-size: $radio-text-font-size;
- line-height: $radio-button-size;
- color: $radio-text-color;
- white-space: nowrap;
- vertical-align: top;
-}
-
-.input {
- position: absolute;
- width: 0;
- height: 0;
- padding: 0;
- margin: 0;
- border: 0;
- opacity: 0;
- appearance: none;
- &:focus ~ .radio {
- box-shadow: 0 0 0 $unit $radio-focus-color;
- }
- &:focus ~ .radioChecked {
- box-shadow: 0 0 0 $unit $radio-checked-focus-color;
- }
-}
-
-.disabled {
- @extend .field;
- .text {
- color: $radio-disabled-color;
- }
- .radio {
- cursor: auto;
- border-color: $radio-disabled-color;
- }
- .radioChecked {
- cursor: auto;
- border-color: $radio-disabled-color;
- &:before {
- background-color: $radio-disabled-color;
- }
- }
-}
diff --git a/components/ripple/Ripple.js b/components/ripple/Ripple.js
index cbf0d6b9..26275a5d 100644
--- a/components/ripple/Ripple.js
+++ b/components/ripple/Ripple.js
@@ -1,12 +1,11 @@
import React, { Component, PropTypes } from 'react';
import ReactDOM from 'react-dom';
import classnames from 'classnames';
-import update from 'immutability-helper';
import { themr } from 'react-css-themr';
+import dissoc from 'ramda/src/dissoc';
import { RIPPLE } from '../identifiers.js';
import events from '../utils/events';
import prefixer from '../utils/prefixer';
-import utils from '../utils/utils';
const defaults = {
centered: false,
@@ -85,7 +84,7 @@ const rippleFactory = (options = {}) => {
if (e.propertyName === 'opacity') {
if (self.props.onRippleEnded) self.props.onRippleEnded(e);
events.removeEventListenerOnTransitionEnded(self.refs[rippleKey], onOpacityEnd);
- self.setState({ ripples: utils.removeObjectKey(rippleKey, self.state.ripples) });
+ self.setState({ ripples: dissoc(rippleKey, self.state.ripples) });
}
});
}
@@ -109,9 +108,13 @@ const rippleFactory = (options = {}) => {
const endRipple = this.addRippleDeactivateEventListener(isTouch, key);
const initialState = { active: false, restarting: true, top, left, width, endRipple };
const runningState = { active: true, restarting: false };
- this.setState(update(this.state, { ripples: { [key]: { $set: initialState } } }), () => {
+ const ripples = {...this.state.ripples, [key]: initialState };
+ this.setState({ ripples }, () => {
this.refs[key].offsetWidth; //eslint-disable-line no-unused-expressions
- this.setState(update(this.state, { ripples: { [key]: { $merge: runningState } } }));
+ this.setState({ ripples: {
+ ...this.state.ripples,
+ [key]: Object.assign({}, this.state.ripples[key], runningState)
+ } });
});
}
}
@@ -198,9 +201,10 @@ const rippleFactory = (options = {}) => {
const self = this;
return function endRipple () {
document.removeEventListener(eventType, endRipple);
- self.setState({ ripples: update(self.state.ripples, {
- [rippleKey]: { $merge: { active: false } }
- }) });
+ self.setState({ ripples: {
+ ...self.state.ripples,
+ [rippleKey]: Object.assign({}, self.state.ripples[rippleKey], { active: false })
+ } });
};
}
diff --git a/components/ripple/_config.scss b/components/ripple/_config.scss
deleted file mode 100644
index 8c26b6f1..00000000
--- a/components/ripple/_config.scss
+++ /dev/null
@@ -1,3 +0,0 @@
-$ripple-duration: 800ms !default;
-$ripple-final-opacity: .3 !default;
-$ripple-size: 15 * $unit !default;
diff --git a/components/ripple/config.css b/components/ripple/config.css
new file mode 100644
index 00000000..c1946024
--- /dev/null
+++ b/components/ripple/config.css
@@ -0,0 +1,5 @@
+:root {
+ --ripple-duration: 800ms;
+ --ripple-final-opacity: 0.3;
+ --ripple-size: calc(15 * var(--unit));
+}
diff --git a/components/ripple/index.js b/components/ripple/index.js
index 7299f9fb..4779785a 100644
--- a/components/ripple/index.js
+++ b/components/ripple/index.js
@@ -1,4 +1,4 @@
import rippleFactory from './Ripple.js';
-import theme from './theme.scss';
+import theme from './theme.css';
export default (options) => rippleFactory({ ...options, theme });
diff --git a/components/ripple/theme.scss b/components/ripple/theme.css
similarity index 64%
rename from components/ripple/theme.scss
rename to components/ripple/theme.css
index 6212078d..4b4153c6 100644
--- a/components/ripple/theme.scss
+++ b/components/ripple/theme.css
@@ -1,40 +1,37 @@
-@import "../colors";
-@import "../globals";
-@import "../mixins";
-@import "./config";
-
-%ripple {
- position: absolute;
- top: 50%;
- left: 50%;
- z-index: $z-index-high;
- pointer-events: none;
- background-color: currentColor;
- border-radius: 50%;
- transform-origin: 50% 50%;
-}
+@import '../variables.css';
+@import './config.css';
.rippleWrapper {
- position: absolute;
- top: 0;
- right: 0;
bottom: 0;
left: 0;
- z-index: $z-index-normal;
pointer-events: none;
+ position: absolute;
+ right: 0;
+ top: 0;
+ z-index: var(--z-index-normal);
}
.ripple {
- @extend %ripple;
- transition-duration: $ripple-duration;
+ background-color: currentColor;
+ border-radius: 50%;
+ left: 50%;
+ pointer-events: none;
+ position: absolute;
+ top: 50%;
+ transform-origin: 50% 50%;
+ transition-duration: var(--ripple-duration);
+ z-index: var(--z-index-high);
+
&.rippleRestarting {
- opacity: $ripple-final-opacity;
+ opacity: var(--ripple-final-opacity);
transition-property: none;
}
+
&.rippleActive {
- opacity: $ripple-final-opacity;
+ opacity: var(--ripple-final-opacity);
transition-property: transform;
}
+
&:not(.rippleActive):not(.rippleRestarting) {
opacity: 0;
transition-property: opacity, transform;
diff --git a/components/slider/Slider.js b/components/slider/Slider.js
index df1abd89..ae24700a 100644
--- a/components/slider/Slider.js
+++ b/components/slider/Slider.js
@@ -2,9 +2,9 @@ import React, { Component, PropTypes } from 'react';
import ReactDOM from 'react-dom';
import classnames from 'classnames';
import { themr } from 'react-css-themr';
+import { round, range } from '../utils/utils';
import { SLIDER } from '../identifiers.js';
import events from '../utils/events.js';
-import utils from '../utils/utils.js';
import InjectProgressBar from '../progress_bar/ProgressBar.js';
import InjectInput from '../input/Input.js';
@@ -216,7 +216,7 @@ const factory = (ProgressBar, Input) => {
trimValue (value) {
if (value < this.props.min) return this.props.min;
if (value > this.props.max) return this.props.max;
- return utils.round(value, this.stepDecimals());
+ return round(value, this.stepDecimals());
}
valueForInput (value) {
@@ -228,7 +228,7 @@ const factory = (ProgressBar, Input) => {
if (this.props.snaps) {
return (
- {utils.range(0, (this.props.max - this.props.min) / this.props.step).map(i => {
+ {range(0, (this.props.max - this.props.min) / this.props.step).map(i => {
return
;
})}
diff --git a/components/slider/__tests__/index.spec.js b/components/slider/__tests__/index.spec.js
index bf4e3ab1..b5d155cf 100644
--- a/components/slider/__tests__/index.spec.js
+++ b/components/slider/__tests__/index.spec.js
@@ -6,7 +6,7 @@ import { ProgressBar } from '../../progress_bar/ProgressBar.js';
import Input, { Input as RawInput } from '../../input/Input.js';
import Slider, { Slider as RawSlider } from '../Slider.js';
import utils from '../../utils/testing';
-import theme from '../theme.scss';
+import theme from '../theme.css';
describe('Slider', function () {
let slider, progress, input, onChange;
diff --git a/components/slider/_config.scss b/components/slider/_config.scss
deleted file mode 100644
index 6563e301..00000000
--- a/components/slider/_config.scss
+++ /dev/null
@@ -1,13 +0,0 @@
-$slider-main-color: $color-primary !default;
-$slider-main-color-contrast: $color-primary-contrast !default;
-$slider-disabled-color: rgba(177, 177, 177, 1) !default;
-$slider-snap-color: $color-black !default;
-$slider-knob-size: 3.2 * $unit !default;
-$slider-inner-knob-size: 1.2 * $unit !default;
-$slider-snap-size: .2 * $unit !default;
-$slider-input-width: 5 * $unit !default;
-$slider-bar-height: .2 * $unit !default;
-$slider-pin-size: 2.6 * $unit !default;
-$slider-pin-elevation: 1.7 * $unit !default;
-$slider-side-separation: 1 * $unit !default;
-$slider-empty-knob-border: .2 * $unit !default;
diff --git a/components/slider/config.css b/components/slider/config.css
new file mode 100644
index 00000000..a27470e2
--- /dev/null
+++ b/components/slider/config.css
@@ -0,0 +1,15 @@
+:root {
+ --slider-main-color: var(--color-primary);
+ --slider-main-color-contrast: var(--color-primary-contrast);
+ --slider-snap-color: var(--color-black);
+ --slider-disabled-color: rgba(177, 177, 177, 1);
+ --slider-knob-size: calc(3.2 * var(--unit));
+ --slider-inner-knob-size: calc(1.2 * var(--unit));
+ --slider-snap-size: calc(0.2 * var(--unit));
+ --slider-input-width: calc(5 * var(--unit));
+ --slider-bar-height: calc(0.2 * var(--unit));
+ --slider-pin-size: calc(2.6 * var(--unit));
+ --slider-pin-elevation: calc(1.7 * var(--unit));
+ --slider-side-separation: calc(1 * var(--unit));
+ --slider-empty-knob-border: calc(0.2 * var(--unit));
+}
diff --git a/components/slider/index.js b/components/slider/index.js
index 629a3457..925278c1 100644
--- a/components/slider/index.js
+++ b/components/slider/index.js
@@ -3,7 +3,7 @@ import { SLIDER } from '../identifiers.js';
import { ProgressBar } from '../progress_bar';
import { Input} from '../input';
import { sliderFactory } from './Slider.js';
-import theme from './theme.scss';
+import theme from './theme.css';
const ThemedSlider = themr(SLIDER, theme)(sliderFactory(ProgressBar, Input));
export default ThemedSlider;
diff --git a/components/slider/theme.css b/components/slider/theme.css
new file mode 100644
index 00000000..7bad0089
--- /dev/null
+++ b/components/slider/theme.css
@@ -0,0 +1,227 @@
+@import '../colors.css';
+@import '../variables.css';
+@import './config.css';
+
+.container {
+ composes: reset from '../helpers.css';
+ height: var(--slider-knob-size);
+ margin-right: var(--slider-knob-size);
+ position: relative;
+ user-select: none;
+ width: calc(100% - var(--slider-knob-size));
+
+ &:not(:last-child) {
+ margin-right: calc(var(--slider-side-separation) + var(--slider-knob-size));
+ }
+
+ &:not(:first-child) {
+ margin-left: var(--slider-side-separation);
+ }
+}
+
+.knob {
+ align-items: center;
+ background-color: transparent;
+ display: flex;
+ flex-direction: row;
+ height: var(--slider-knob-size);
+ justify-content: center;
+ left: 0;
+ position: relative;
+ top: 0;
+ width: var(--slider-knob-size);
+ z-index: var(--z-index-higher);
+}
+
+.innerknob {
+ background-color: var(--slider-main-color);
+ border-radius: 50%;
+ height: var(--slider-inner-knob-size);
+ transition-duration: 0.1s;
+ transition-property: height, width, background-color, border;
+ transition-timing-function: var(--animation-curve-default);
+ width: var(--slider-inner-knob-size);
+ z-index: var(--z-index-high);
+}
+
+.snaps {
+ display: flex;
+ flex-direction: row;
+ height: var(--slider-snap-size);
+ left: 0;
+ pointer-events: none;
+ position: absolute;
+ top: calc(var(--slider-knob-size) / 2 - var(--slider-snap-size) / 2);
+ width: calc(100% + var(--slider-snap-size));
+
+ &::after {
+ background-color: var(--slider-snap-color);
+ border-radius: 50%;
+ content: '';
+ display: block;
+ height: var(--slider-snap-size);
+ width: var(--slider-snap-size);
+ }
+}
+
+.snap {
+ flex: 1;
+
+ &::after {
+ background-color: var(--slider-snap-color);
+ border-radius: 50%;
+ content: '';
+ display: block;
+ height: var(--slider-snap-size);
+ width: var(--slider-snap-size);
+ }
+}
+
+.input {
+ margin-bottom: 0;
+ padding: 0;
+ width: var(--slider-input-width);
+
+ & > input {
+ text-align: center;
+ }
+}
+
+.progress {
+ height: 100%;
+ left: calc(var(--slider-knob-size) / 2);
+ position: absolute;
+ top: 0;
+ width: 100%;
+
+ & .innerprogress {
+ height: var(--slider-bar-height);
+ position: absolute;
+ top: calc(var(--slider-knob-size) / 2 - var(--slider-bar-height) / 2);
+
+ & [data-ref='value'] {
+ transition-duration: 0s;
+ }
+ }
+}
+
+.slider {
+ &:focus .knob::before {
+ background-color: var(--slider-main-color);
+ border-radius: 50%;
+ bottom: 0;
+ content: '';
+ left: 0;
+ opacity: 0.26;
+ position: absolute;
+ right: 0;
+ top: 0;
+ z-index: var(--z-index-normal);
+ }
+
+ &[disabled] {
+ cursor: auto;
+ pointer-events: none;
+
+ & .innerknob {
+ background-color: var(--slider-disabled-color);
+ }
+ }
+
+ &.editable {
+ align-items: center;
+ display: flex;
+ flex-direction: row;
+ }
+
+ &.pinned .innerknob {
+ &::before {
+ background-color: var(--slider-main-color);
+ border-radius: 50% 50% 50% 0;
+ content: '';
+ height: var(--slider-pin-size);
+ left: 0;
+ margin-left: calc((var(--slider-knob-size) - var(--slider-pin-size)) / 2);
+ position: absolute;
+ top: 0;
+ transform: rotate(-45deg) scale(0) translate(0);
+ transition:
+ transform 0.2s ease,
+ background-color 0.18s ease;
+ width: var(--slider-pin-size);
+ }
+
+ &::after {
+ color: var(--color-background);
+ content: attr(data-value);
+ font-size: 10px;
+ height: var(--slider-pin-size);
+ left: 0;
+ position: absolute;
+ text-align: center;
+ top: 0;
+ transform: scale(0) translate(0);
+ transition:
+ transform 0.2s ease,
+ background-color 0.18s ease;
+ width: var(--slider-knob-size);
+ }
+ }
+
+ &.pressed {
+ &.pinned .innerknob {
+ &::before {
+ transform: rotate(-45deg) scale(1) translate(var(--slider-pin-elevation), calc(-1 * var(--slider-pin-elevation)));
+ transition-delay: 100ms;
+ }
+
+ &::after {
+ transform: scale(1) translate(0, calc(-1 * var(--slider-pin-elevation)));
+ transition-delay: 100ms;
+ }
+ }
+
+ &:not(.pinned) {
+ &.ring .progress {
+ left: calc(var(--slider-knob-size) / 2 + (var(--slider-knob-size) - var(--slider-empty-knob-border) * 2) / 2);
+ width: calc(100% - ((var(--slider-knob-size) - var(--slider-empty-knob-border) * 2) / 2));
+ }
+
+ & .innerknob {
+ height: 100%;
+ transform: translateZ(0);
+ width: 100%;
+ }
+ }
+ }
+
+ &.ring {
+ & .innerknob {
+ background-color: transparent;
+ border: var(--slider-empty-knob-border) solid var(--color-divider);
+
+ &::before {
+ background-color: var(--slider-main-color);
+ }
+ }
+
+ & .progress {
+ left: calc(var(--slider-knob-size) / 2 + var(--slider-empty-knob-border) * 2);
+ transition:
+ left 0.18s ease,
+ width 0.18s ease;
+ width: calc(100% - var(--slider-empty-knob-border) * 2);
+ }
+
+ &.pinned {
+ & .innerknob {
+ background-color: var(--color-background);
+ }
+
+ & .progress {
+ left: calc(var(--slider-knob-size) / 2);
+ width: 100%;
+ }
+ }
+ }
+}
diff --git a/components/slider/theme.scss b/components/slider/theme.scss
deleted file mode 100644
index 310e8009..00000000
--- a/components/slider/theme.scss
+++ /dev/null
@@ -1,200 +0,0 @@
-@import "../colors";
-@import "../globals";
-@import "../mixins";
-@import "./config";
-
-.container {
- position: relative;
- width: calc(100% - #{$slider-knob-size});
- height: $slider-knob-size;
- margin-right: $slider-knob-size;
- user-select: none;
- &:not(:last-child) {
- margin-right: $slider-side-separation + $slider-knob-size;
- }
- &:not(:first-child) {
- margin-left: $slider-side-separation;
- }
-}
-
-.knob {
- position: relative;
- top: 0;
- left: 0;
- z-index: $z-index-higher;
- display: flex;
- width: $slider-knob-size;
- height: $slider-knob-size;
- flex-direction: row;
- align-items: center;
- justify-content: center;
- background-color: transparent;
-}
-
-.innerknob {
- z-index: $z-index-high;
- width: $slider-inner-knob-size;
- height: $slider-inner-knob-size;
- background-color: $slider-main-color;
- border-radius: 50%;
- transition-timing-function: $animation-curve-default;
- transition-duration: .1s;
- transition-property: height, width, background-color, border;
-}
-
-.snaps {
- position: absolute;
- top: $slider-knob-size / 2 - $slider-snap-size / 2;
- left: 0;
- display: flex;
- width: calc(100% + #{$slider-snap-size});
- height: $slider-snap-size;
- flex-direction: row;
- pointer-events: none;
- &:after {
- display: block;
- width: $slider-snap-size;
- height: $slider-snap-size;
- content: "";
- background-color: $slider-snap-color;
- border-radius: 50%;
- }
-}
-
-.snap {
- flex: 1;
- &:after {
- display: block;
- width: $slider-snap-size;
- height: $slider-snap-size;
- content: "";
- background-color: $slider-snap-color;
- border-radius: 50%;
- }
-}
-
-.input {
- width: $slider-input-width;
- padding: 0;
- margin-bottom: 0;
- > input {
- text-align: center;
- }
-}
-
-.progress {
- position: absolute;
- top: 0;
- left: $slider-knob-size / 2;
- width: 100%;
- height: 100%;
- .innerprogress {
- position: absolute;
- top: $slider-knob-size / 2 - $slider-bar-height / 2;
- height: $slider-bar-height;
- [data-ref="value"] {
- transition-duration: 0s;
- }
- }
-}
-
-.slider {
- &:focus .knob:before {
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- z-index: $z-index-normal;
- content: "";
- background-color: $slider-main-color;
- border-radius: 50%;
- opacity: .26;
- }
- &[disabled] {
- pointer-events: none;
- cursor: auto;
- .innerknob {
- background-color: $slider-disabled-color;
- }
- }
- &.editable {
- display: flex;
- flex-direction: row;
- align-items: center;
- }
- &.pinned .innerknob {
- &:before {
- position: absolute;
- top: 0;
- left: 0;
- width: $slider-pin-size;
- height: $slider-pin-size;
- margin-left: ($slider-knob-size - $slider-pin-size) / 2;
- content: "";
- background-color: $slider-main-color;
- border-radius: 50% 50% 50% 0;
- transition: transform .2s ease, background-color .18s ease;
- transform: rotate(-45deg) scale(0) translate(0);
- }
- &:after {
- position: absolute;
- top: 0;
- left: 0;
- width: $slider-knob-size;
- height: $slider-pin-size;
- font-size: 10px;
- color: $color-background;
- text-align: center;
- content: attr(data-value);
- transition: transform .2s ease, background-color .18s ease;
- transform: scale(0) translate(0);
- }
- }
- &.pressed {
- &.pinned .innerknob {
- &:before {
- transition-delay: 100ms;
- transform: rotate(-45deg) scale(1) translate($slider-pin-elevation, - $slider-pin-elevation);
- }
- &:after {
- transition-delay: 100ms;
- transform: scale(1) translate(0, - $slider-pin-elevation);
- }
- }
- &:not(.pinned) {
- &.ring .progress {
- left: $slider-knob-size / 2 + ($slider-knob-size - $slider-empty-knob-border * 2) / 2;
- width: calc(100% - #{($slider-knob-size - $slider-empty-knob-border * 2) / 2});
- }
- .innerknob {
- width: 100%;
- height: 100%;
- transform: translateZ(0);
- }
- }
- }
- &.ring {
- .innerknob {
- background-color: transparent;
- border: $slider-empty-knob-border solid $color-divider;
- &:before {
- background-color: $slider-main-color;
- }
- }
- .progress {
- left: $slider-knob-size / 2 + $slider-empty-knob-border * 2;
- width: calc(100% - #{$slider-empty-knob-border * 2});
- transition: left .18s ease, width .18s ease;
- }
- &.pinned {
- .innerknob {
- background-color: $color-background;
- }
- .progress {
- left: $slider-knob-size / 2;
- width: calc(100%);
- }
- }
- }
-}
diff --git a/components/snackbar/Snackbar.js b/components/snackbar/Snackbar.js
index 399a8118..c6e5052b 100644
--- a/components/snackbar/Snackbar.js
+++ b/components/snackbar/Snackbar.js
@@ -3,10 +3,10 @@ import classnames from 'classnames';
import { themr } from 'react-css-themr';
import { SNACKBAR } from '../identifiers.js';
import ActivableRenderer from '../hoc/ActivableRenderer.js';
-import InjectOverlay from '../overlay/Overlay.js';
import InjectButton from '../button/Button.js';
+import Portal from '../hoc/Portal.js';
-const factory = (Overlay, Button) => {
+const factory = (Button) => {
class Snackbar extends Component {
static propTypes = {
action: PropTypes.string,
@@ -64,7 +64,7 @@ const factory = (Overlay, Button) => {
}, this.props.className);
return (
-
+
{label}
@@ -72,7 +72,7 @@ const factory = (Overlay, Button) => {
{action ? : null}
-
+
);
}
}
@@ -80,7 +80,7 @@ const factory = (Overlay, Button) => {
return ActivableRenderer()(Snackbar);
};
-const Snackbar = factory(InjectOverlay, InjectButton);
+const Snackbar = factory(InjectButton);
export default themr(SNACKBAR)(Snackbar);
export { factory as snackbarFactory };
export { Snackbar };
diff --git a/components/snackbar/_config.scss b/components/snackbar/_config.scss
deleted file mode 100644
index 69f7cdf5..00000000
--- a/components/snackbar/_config.scss
+++ /dev/null
@@ -1,9 +0,0 @@
-$snackbar-color-cancel: $palette-red-500 !default;
-$snackbar-color-accept: $palette-green-500 !default;
-$snackbar-color-warning: $palette-lime-a200 !default;
-$snackbar-background-color: $color-text !default;
-$snackbar-border-radius: .2 * $unit !default;
-$snackbar-button-offset: 4.8 * $unit !default;
-$snackbar-color: $color-white !default;
-$snackbar-horizontal-offset: 2.4 * $unit !default;
-$snackbar-vertical-offset: 1.4 * $unit !default;
diff --git a/components/snackbar/index.js b/components/snackbar/index.js
index 5825088c..e2e4ea03 100644
--- a/components/snackbar/index.js
+++ b/components/snackbar/index.js
@@ -1,11 +1,10 @@
import { themr } from 'react-css-themr';
import { SNACKBAR } from '../identifiers.js';
import { snackbarFactory } from './Snackbar.js';
-import { Overlay } from '../overlay';
import { Button } from '../button';
-import theme from './theme.scss';
+import theme from './theme.css';
-const ThemedSnackbar = themr(SNACKBAR, theme)(snackbarFactory(Overlay, Button));
+const ThemedSnackbar = themr(SNACKBAR, theme)(snackbarFactory(Button));
export default ThemedSnackbar;
export { ThemedSnackbar as Snackbar };
diff --git a/components/snackbar/readme.md b/components/snackbar/readme.md
index 7728354a..fcc943c9 100644
--- a/components/snackbar/readme.md
+++ b/components/snackbar/readme.md
@@ -57,5 +57,6 @@ This component can be styled by context providing a theme with the key `RTSnackb
| `button` | Used for the button inside the component.|
| `cancel` | Added to the root element in case it's cancel type.|
| `label` | Used for the label element.|
+| `portal` | Used for the portal container element.|
| `snackbar` | Used as the className for the root element of the component.|
| `warning` | Added to the root element in case it's warning type.|
diff --git a/components/snackbar/theme.css b/components/snackbar/theme.css
new file mode 100644
index 00000000..069a0d58
--- /dev/null
+++ b/components/snackbar/theme.css
@@ -0,0 +1,65 @@
+@import '../colors.css';
+@import '../variables.css';
+
+:root {
+ --snackbar-color-cancel: var(--palette-red-500);
+ --snackbar-color-accept: var(--palette-green-500);
+ --snackbar-color-warning: var(--palette-lime-a200);
+ --snackbar-background-color: var(--color-text);
+ --snackbar-border-radius: calc(0.2 * var(--unit));
+ --snackbar-button-offset: calc(4.8 * var(--unit));
+ --snackbar-color: var(--color-white);
+ --snackbar-horizontal-offset: calc(2.4 * var(--unit));
+ --snackbar-vertical-offset: calc(1.4 * var(--unit));
+}
+
+.snackbar {
+ align-items: center;
+ background-color: var(--snackbar-background-color);
+ border-radius: var(--snackbar-border-radius);
+ bottom: 0;
+ color: var(--snackbar-color);
+ composes: reset from '../helpers.css';
+ display: flex;
+ left: var(--snackbar-horizontal-offset);
+ margin: var(--snackbar-vertical-offset) auto 0;
+ padding: var(--snackbar-vertical-offset) var(--snackbar-horizontal-offset);
+ position: fixed;
+ right: var(--snackbar-horizontal-offset);
+ transition: all var(--animation-duration) var(--animation-curve-default) var(--animation-duration);
+ z-index: var(--z-index-higher);
+
+ &.accept .button {
+ color: var(--snackbar-color-accept);
+ }
+
+ &.warning .button {
+ color: var(--snackbar-color-warning);
+ }
+
+ &.cancel .button {
+ color: var(--snackbar-color-cancel);
+ }
+
+ &:not(.active) {
+ transform: translateY(100%);
+ }
+
+ &.active {
+ transform: translateY(0%);
+ }
+}
+
+.label {
+ flex-grow: 1;
+ font-size: var(--font-size-small);
+}
+
+.button {
+ margin:
+ calc(-1 * var(--snackbar-vertical-offset) / 2)
+ calc(-1 * var(--snackbar-horizontal-offset) / 2)
+ calc(-1 * var(--snackbar-vertical-offset) / 2)
+ var(--snackbar-button-offset);
+ min-width: inherit;
+}
diff --git a/components/snackbar/theme.scss b/components/snackbar/theme.scss
deleted file mode 100644
index 4c7d0770..00000000
--- a/components/snackbar/theme.scss
+++ /dev/null
@@ -1,49 +0,0 @@
-@import "../colors";
-@import "../globals";
-@import "../mixins";
-@import "./config";
-
-.snackbar {
- position: fixed;
- right: $snackbar-horizontal-offset;
- bottom: 0;
- left: $snackbar-horizontal-offset;
- z-index: $z-index-higher;
- display: flex;
- align-items: center;
- padding: $snackbar-vertical-offset $snackbar-horizontal-offset;
- margin: 0 auto;
- margin-top: $snackbar-vertical-offset;
- color: $snackbar-color;
- background-color: $snackbar-background-color;
- border-radius: $snackbar-border-radius;
- transition: all $animation-duration $animation-curve-default $animation-duration;
- &.accept .button {
- color: $snackbar-color-accept;
- }
- &.warning .button {
- color: $snackbar-color-warning;
- }
- &.cancel .button {
- color: $snackbar-color-cancel;
- }
- &:not(.active) {
- transform: translateY(100%);
- }
- &.active {
- transform: translateY(0%);
- }
-}
-
-.label {
- flex-grow: 1;
- font-size: $font-size-small;
-}
-
-.button {
- min-width: inherit;
- margin-top: - $snackbar-vertical-offset / 2;
- margin-right: - $snackbar-horizontal-offset / 2;
- margin-bottom: - $snackbar-vertical-offset / 2;
- margin-left: $snackbar-button-offset;
-}
diff --git a/components/switch/_config.scss b/components/switch/_config.scss
deleted file mode 100644
index 78408471..00000000
--- a/components/switch/_config.scss
+++ /dev/null
@@ -1,22 +0,0 @@
-$switch-color: $color-primary !default;
-$switch-text-color: $color-black !default;
-$switch-thumb-off-color: $palette-grey-50 !default;
-$switch-track-on-color: rgba($color-primary, 0.5) !default;
-$switch-track-off-color: rgba($color-black, 0.26) !default;
-$switch-off-ripple-color: rgba($color-black, 0.4) !default;
-$switch-on-focus-color: rgba($color-primary, 0.26) !default;
-$switch-off-focus-color: rgba($color-black, 0.1) !default;
-$switch-disabled-thumb-color: $palette-grey-400 !default;
-$switch-disabled-track-color: rgba($color-black, 0.12) !default;
-$switch-disabled-text-color: rgba($color-black, 0.26) !default;
-$switch-total-height: 2.4 * $unit !default;
-$switch-track-length: 3.6 * $unit !default;
-$switch-track-height: 1.4 * $unit !default;
-$switch-thumb-size: 2 * $unit !default;
-$switch-thumb-on-color: $switch-color !default;
-$switch-focus-init-size: .8 * $unit !default;
-$switch-focus-size: $switch-total-height * 2 !default;
-$switch-focus-diff: ($switch-focus-size - $switch-focus-init-size) / 2 !default;
-$switch-ripple-duration: 650ms !default;
-$switch-font-size: $font-size-small !default;
-$switch-field-margin-bottom: 1.5 * $unit !default;
diff --git a/components/switch/config.css b/components/switch/config.css
new file mode 100644
index 00000000..703bf969
--- /dev/null
+++ b/components/switch/config.css
@@ -0,0 +1,24 @@
+:root {
+ --switch-color: var(--color-primary);
+ --switch-text-color: var(--color-black);
+ --switch-thumb-off-color: var(--palette-grey-50);
+ --switch-track-on-color: color(var(--color-primary) a(50%));
+ --switch-track-off-color: color(var(--color-black) a(26%));
+ --switch-off-ripple-color: color(var(--color-black) a(40%));
+ --switch-on-focus-color: color(var(--color-primary) a(26%));
+ --switch-off-focus-color: color(var(--color-black) a(10%));
+ --switch-disabled-thumb-color: var(--palette-grey-400);
+ --switch-disabled-track-color: color(var(--color-black) a(12%));
+ --switch-disabled-text-color: color(var(--color-black) a(26%));
+ --switch-total-height: calc(2.4 * var(--unit));
+ --switch-track-length: calc(3.6 * var(--unit));
+ --switch-track-height: calc(1.4 * var(--unit));
+ --switch-thumb-size: calc(2 * var(--unit));
+ --switch-thumb-on-color: var(--switch-color);
+ --switch-focus-init-size: calc(0.8 * var(--unit));
+ --switch-focus-size: calc(var(--switch-total-height) * 2);
+ --switch-focus-diff: calc((var(--switch-focus-size) - var(--switch-focus-init-size)) / 2);
+ --switch-ripple-duration: 650ms;
+ --switch-font-size: var(--font-size-small);
+ --switch-field-margin-bottom: calc(1.5 * var(--unit));
+}
diff --git a/components/switch/index.js b/components/switch/index.js
index 28c3ec38..8a9db2ad 100644
--- a/components/switch/index.js
+++ b/components/switch/index.js
@@ -3,7 +3,7 @@ import { switchFactory } from './Switch.js';
import { SWITCH } from '../identifiers.js';
import thumbFactory from './Thumb.js';
import themedRippleFactory from '../ripple';
-import theme from './theme.scss';
+import theme from './theme.css';
const applyTheme = (Component) => themr(SWITCH, theme)(Component);
const ripple = themedRippleFactory({ centered: true, spread: 2.6 });
diff --git a/components/switch/theme.css b/components/switch/theme.css
new file mode 100644
index 00000000..4aa3a666
--- /dev/null
+++ b/components/switch/theme.css
@@ -0,0 +1,130 @@
+@import '../colors.css';
+@import '../variables.css';
+@import './config.css';
+
+.field {
+ composes: reset from '../helpers.css';
+ display: block;
+ margin-bottom: var(--switch-field-margin-bottom);
+ position: relative;
+ white-space: normal;
+}
+
+.text {
+ color: var(--switch-text-color);
+ display: inline-block;
+ font-size: var(--switch-font-size);
+ line-height: var(--switch-total-height);
+ padding-left: var(--unit);
+ vertical-align: top;
+ white-space: nowrap;
+}
+
+.thumb {
+ border-radius: 50%;
+ composes: reset from '../helpers.css';
+ cursor: pointer;
+ height: var(--switch-thumb-size);
+ position: absolute;
+ top: calc((var(--switch-track-height) - var(--switch-thumb-size)) / 2);
+ transition-duration: 0.28s;
+ transition-property: left;
+ transition-timing-function: var(--animation-curve-default);
+ width: var(--switch-thumb-size);
+
+ & .ripple {
+ background-color: var(--switch-color);
+ opacity: 0.3;
+ transition-duration: var(--switch-ripple-duration);
+ }
+}
+
+.on,
+.off {
+ border-radius: var(--switch-track-height);
+ cursor: pointer;
+ display: inline-block;
+ height: var(--switch-track-height);
+ margin-top: calc((var(--switch-total-height) - var(--switch-track-height)) / 2);
+ position: relative;
+ vertical-align: top;
+ width: var(--switch-track-length);
+}
+
+.on {
+ background: var(--switch-track-on-color);
+
+ & .thumb {
+ background: var(--switch-thumb-on-color);
+ box-shadow: var(--shadow-3p);
+ left: calc(var(--switch-track-length) - var(--switch-thumb-size));
+ }
+}
+
+.off {
+ background: var(--switch-track-off-color);
+
+ & .thumb {
+ background: var(--switch-thumb-off-color);
+ box-shadow: var(--shadow-2p);
+ left: 0;
+ }
+
+ & .ripple {
+ background: var(--switch-off-ripple-color);
+ }
+}
+
+.input {
+ height: 0;
+ opacity: 0;
+ overflow: hidden;
+ width: 0;
+
+ &:focus:not(:active) {
+ & + .switch-on > .thumb::before,
+ & + .switch-off > .thumb::before {
+ background-color: transparent;
+ border-radius: 50%;
+ box-sizing: border-box;
+ content: '';
+ display: inline-block;
+ height: var(--switch-focus-init-size);
+ left: 50%;
+ position: absolute;
+ top: 50%;
+ transform: translate(calc(-1 * var(--switch-focus-init-size) / 2), calc(-1 * var(--switch-focus-init-size) / 2));
+ width: var(--switch-focus-init-size);
+ }
+
+ & + .switch-on > .thumb::before {
+ background-color: var(--switch-on-focus-color);
+ box-shadow: 0 0 0 var(--switch-focus-diff) var(--switch-on-focus-color);
+ }
+
+ & + .switch-off > .thumb::before {
+ background-color: var(--switch-off-focus-color);
+ box-shadow: 0 0 0 var(--switch-focus-diff) var(--switch-off-focus-color);
+ }
+ }
+}
+
+.disabled {
+ composes: field;
+
+ & .text {
+ color: var(--switch-disabled-text-color);
+ }
+
+ & .on,
+ & .off {
+ background: var(--switch-disabled-track-color);
+ cursor: auto;
+ }
+
+ & .thumb {
+ background-color: var(--switch-disabled-thumb-color);
+ border-color: transparent;
+ cursor: auto;
+ }
+}
diff --git a/components/switch/theme.scss b/components/switch/theme.scss
deleted file mode 100644
index 08a5c290..00000000
--- a/components/switch/theme.scss
+++ /dev/null
@@ -1,123 +0,0 @@
-@import "../colors";
-@import "../globals";
-@import "../mixins";
-@import "./config";
-
-.field {
- position: relative;
- display: block;
- height: auto;
- margin-bottom: $switch-field-margin-bottom;
- white-space: nowrap;
- vertical-align: middle;
-}
-
-.text {
- display: inline-block;
- padding-left: $unit;
- font-size: $switch-font-size;
- line-height: $switch-total-height;
- color: $switch-text-color;
- white-space: normal;
- vertical-align: top;
-}
-
-%switch {
- position: relative;
- display: inline-block;
- width: $switch-track-length;
- height: $switch-track-height;
- margin-top: ($switch-total-height - $switch-track-height) / 2;
- vertical-align: top;
- cursor: pointer;
- border-radius: $switch-track-height;
-}
-
-.thumb {
- @include material-animation-default(.28s);
- position: absolute;
- top: ($switch-track-height - $switch-thumb-size) / 2;
- width: $switch-thumb-size;
- height: $switch-thumb-size;
- cursor: pointer;
- border-radius: 50%;
- transition-property: left;
-
- .ripple {
- background-color: $switch-color;
- opacity: .3;
- transition-duration: $switch-ripple-duration;
- }
-}
-
-.on {
- @extend %switch;
- background: $switch-track-on-color;
- .thumb {
- @include shadow-3dp();
- left: $switch-track-length - $switch-thumb-size;
- background: $switch-thumb-on-color;
- }
-}
-
-.off {
- @extend %switch;
- background: $switch-track-off-color;
- .thumb {
- @include shadow-2dp();
- left: 0;
- background: $switch-thumb-off-color;
- }
- .ripple {
- background: $switch-off-ripple-color;
- }
-}
-
-%thumb-focus {
- position: absolute;
- top: 50%;
- left: 50%;
- box-sizing: border-box;
- display: inline-block;
- width: $switch-focus-init-size;
- height: $switch-focus-init-size;
- content: "";
- background-color: transparent;
- border-radius: 50%;
- transform: translate(- $switch-focus-init-size / 2, - $switch-focus-init-size / 2);
-}
-
-.input {
- width: 0;
- height: 0;
- overflow: hidden;
- opacity: 0;
- &:focus:not(:active) {
- + .switch-on > .thumb:before {
- @extend %thumb-focus;
- background-color: $switch-on-focus-color;
- box-shadow: 0 0 0 $switch-focus-diff $switch-on-focus-color;
- }
- + .switch-off > .thumb:before {
- @extend %thumb-focus;
- background-color: $switch-off-focus-color;
- box-shadow: 0 0 0 $switch-focus-diff $switch-off-focus-color;
- }
- }
-}
-
-.disabled {
- @extend .field;
- .text {
- color: $switch-disabled-text-color;
- }
- .on, .off {
- cursor: auto;
- background: $switch-disabled-track-color;
- }
- .thumb {
- cursor: auto;
- background-color: $switch-disabled-thumb-color;
- border-color: transparent;
- }
-}
diff --git a/components/table/Table.js b/components/table/Table.js
index ec01b9c7..703d7c31 100644
--- a/components/table/Table.js
+++ b/components/table/Table.js
@@ -1,118 +1,98 @@
-import React, { Component, PropTypes } from 'react';
+import React, { PropTypes, Component, cloneElement } from 'react';
import classnames from 'classnames';
import { themr } from 'react-css-themr';
+import filterReactChildren from '../utils/filter-react-children.js';
+import isComponentOfType from '../utils/is-component-of-type.js';
import { TABLE } from '../identifiers.js';
-import InjectCheckbox from '../checkbox/Checkbox.js';
-import tableHeadFactory from './TableHead.js';
-import tableRowFactory from './TableRow.js';
+import InjectTableHead from './TableHead.js';
+import InjectTableRow from './TableRow.js';
const factory = (TableHead, TableRow) => {
+ const isTableHead = child => isComponentOfType(TableHead, child);
+ const isTableRow = child => isComponentOfType(TableRow, child);
+
class Table extends Component {
static propTypes = {
+ children: PropTypes.node,
className: PropTypes.string,
- heading: PropTypes.bool,
- model: PropTypes.object,
multiSelectable: PropTypes.bool,
- onChange: PropTypes.func,
- onRowClick: PropTypes.func,
- onSelect: PropTypes.func,
+ onRowSelect: PropTypes.func,
selectable: PropTypes.bool,
- selected: PropTypes.array,
- source: PropTypes.array,
theme: PropTypes.shape({
+ head: PropTypes.string,
table: PropTypes.string
})
};
static defaultProps = {
className: '',
- heading: true,
- selectable: true,
- multiSelectable: true,
- selected: [],
- source: []
+ multiSelectable: false,
+ selectable: true
};
- handleFullSelect = () => {
- if (this.props.onSelect) {
- const {source, selected} = this.props;
- const newSelected = source.length === selected.length ? [] : source.map((i, idx) => idx);
- this.props.onSelect(newSelected);
+ getRowTuples = () => React.Children
+ .toArray(filterReactChildren(this.props.children, isTableRow))
+ .map((child, index) => [index, Boolean(child.props.selected)]);
+
+ handleHeadSelect = value => {
+ if (this.props.onRowSelect) {
+ this.props.onRowSelect(value
+ ? this.getRowTuples().map(item => item[0])
+ : []);
}
};
- handleRowSelect = (index) => {
- if (this.props.onSelect) {
- let newSelection = [...this.props.selected];
+ handleRowSelect = idx => {
+ if (this.props.onRowSelect) {
if (this.props.multiSelectable) {
- const position = this.props.selected.indexOf(index);
- newSelection = position !== -1
- ? newSelection.filter((el, idx) => idx !== position)
- : newSelection.concat([index]);
+ const current = this.getRowTuples().filter(item => item[1]).map(item => item[0]);
+ const rowIndex = current.indexOf(idx);
+ const indexes = rowIndex !== -1
+ ? [...current.slice(0, rowIndex), ...current.slice(rowIndex + 1)]
+ : [...current, idx];
+ this.props.onRowSelect(indexes);
} else {
- newSelection = [index];
+ this.props.onRowSelect([idx]);
}
- this.props.onSelect(newSelection);
}
};
- handleRowChange = (index, key, value) => {
- if (this.props.onChange) {
- this.props.onChange(index, key, value);
- }
- };
-
- handleRowClick = (index, event) => {
- if (this.props.onRowClick) {
- this.props.onRowClick(index, event);
- }
- }
-
- renderHead () {
- if (this.props.heading) {
- const {model, selected, source, selectable, multiSelectable} = this.props;
- const isSelected = selected.length === source.length;
- return (
-
- );
- }
- }
-
- renderBody () {
- const { source, model, onChange, selectable, selected, theme } = this.props;
- return (
-
- {source.map((data, index) => (
-
- ))}
-
+ renderHead = () => {
+ const tuples = this.getRowTuples();
+ const selected = tuples.filter(item => item[1]).length === tuples.length;
+ return React.Children.map(
+ filterReactChildren(this.props.children, isTableHead),
+ child => cloneElement(child, {
+ selected,
+ multiSelectable: this.props.multiSelectable,
+ onSelect: this.handleHeadSelect,
+ selectable: this.props.selectable
+ })
);
- }
+ };
+
+ renderRows = () => React.Children.map(
+ filterReactChildren(this.props.children, isTableRow),
+ (child, idx) => cloneElement(child, {
+ idx,
+ onSelect: this.handleRowSelect,
+ selectable: this.props.selectable
+ })
+ );
render () {
- const { className, theme } = this.props;
+ const {
+ className,
+ multiSelectable, // eslint-disable-line
+ onRowSelect, // eslint-disable-line
+ selectable, // eslint-disable-line
+ theme,
+ ...rest
+ } = this.props;
return (
-
- {this.renderHead()}
- {this.renderBody()}
+
+ {this.renderHead()}
+ {this.renderRows()}
);
}
@@ -121,10 +101,7 @@ const factory = (TableHead, TableRow) => {
return Table;
};
-const TableHead = tableHeadFactory(InjectCheckbox);
-const TableRow = tableRowFactory(InjectCheckbox);
-const Table = factory(TableHead, TableRow);
-
+const Table = factory(InjectTableHead, InjectTableRow);
export default themr(TABLE)(Table);
export { factory as tableFactory };
export { Table };
diff --git a/components/table/TableCell.js b/components/table/TableCell.js
new file mode 100644
index 00000000..bb58ed65
--- /dev/null
+++ b/components/table/TableCell.js
@@ -0,0 +1,89 @@
+import React, { Component, PropTypes } from 'react';
+import classnames from 'classnames';
+import { themr } from 'react-css-themr';
+import { TABLE } from '../identifiers.js';
+import InjectFontIcon from '../font_icon/FontIcon.js';
+
+const ASC = 'asc';
+const DESC = 'desc';
+
+const factory = (FontIcon) => {
+ class TableCell extends Component {
+ static propTypes = {
+ children: PropTypes.any,
+ className: PropTypes.string,
+ column: PropTypes.number,
+ numeric: PropTypes.bool,
+ onClick: PropTypes.func,
+ row: PropTypes.number,
+ sorted: PropTypes.oneOf([ASC, DESC]),
+ tagName: PropTypes.oneOf(['td', 'th']),
+ theme: PropTypes.shape({
+ asc: PropTypes.string,
+ headCell: PropTypes.string,
+ numeric: PropTypes.string,
+ rowCell: PropTypes.string,
+ sorted: PropTypes.string,
+ sortIcon: PropTypes.string,
+ tableCell: PropTypes.string
+ })
+ };
+
+ static defaultProps = {
+ children: PropTypes.node,
+ className: '',
+ numeric: false,
+ tagName: 'td'
+ };
+
+ handleClick = event => {
+ const { onClick, row, column } = this.props;
+ if (onClick) onClick(event, column, row);
+ }
+
+ render () {
+ const {
+ children,
+ className,
+ numeric,
+ row, // eslint-disable-line
+ column, // eslint-disable-line
+ sorted,
+ tagName,
+ theme,
+ ...other
+ } = this.props;
+
+ const _className = classnames(theme.tableCell, {
+ [theme.headCell]: tagName === 'th',
+ [theme.rowCell]: tagName === 'td',
+ [theme.sorted]: sorted,
+ [theme.numeric]: numeric
+ }, className);
+
+ const props = {
+ ...other,
+ className: _className,
+ onClick: this.handleClick
+ };
+
+ return (
+ React.createElement(tagName, props, [
+ sorted && ,
+ children
+ ])
+ );
+ }
+ }
+
+ return TableCell;
+};
+
+const TableCell = factory(InjectFontIcon);
+export default themr(TABLE)(TableCell);
+export { factory as tableCellFactory };
+export { TableCell };
diff --git a/components/table/TableHead.js b/components/table/TableHead.js
index 884699c3..11ea62ea 100644
--- a/components/table/TableHead.js
+++ b/components/table/TableHead.js
@@ -1,50 +1,65 @@
-import React, { PropTypes } from 'react';
+import React, { Component, PropTypes, cloneElement } from 'react';
+import { themr } from 'react-css-themr';
+import { TABLE } from '../identifiers.js';
+import InjectCheckbox from '../checkbox/Checkbox.js';
+import InjectTableCell from './TableCell.js';
-const factory = (Checkbox) => {
- const TableHead = ({model, onSelect, selectable, multiSelectable, selected, theme}) => {
- let selectCell;
- const contentCells = Object.keys(model).map((key) => {
- const name = model[key].title || key;
- return {name} ;
- });
+const factory = (Checkbox, TableCell) => {
+ class TableHead extends Component {
+ static propTypes = {
+ children: PropTypes.node,
+ className: PropTypes.string,
+ displaySelect: PropTypes.bool,
+ multiSelectable: PropTypes.bool,
+ onSelect: PropTypes.func,
+ selectable: PropTypes.bool,
+ selected: PropTypes.bool,
+ theme: PropTypes.shape({
+ checkboxCell: PropTypes.string
+ })
+ }
- if (selectable && multiSelectable) {
- selectCell = (
-
-
-
- );
- } else if (selectable) {
- selectCell = (
-
+ static defaultProps = {
+ displaySelect: true
+ }
+
+ handleSelect = (value, event) => {
+ this.props.onSelect(value, event);
+ };
+
+ render () {
+ const {
+ children,
+ displaySelect,
+ multiSelectable,
+ onSelect, // eslint-disable-line
+ selectable,
+ selected,
+ theme,
+ ...other
+ } = this.props;
+ return (
+
+ {selectable &&
+ {displaySelect && }
+ }
+ {React.Children.map(children, (child, index) => cloneElement(child, {
+ column: index,
+ tagName: 'th'
+ }))}
+
);
}
- return (
-
- {[selectCell, ...contentCells]}
-
- );
- };
-
- TableHead.propTypes = {
- className: PropTypes.string,
- model: PropTypes.object,
- multiSelectable: PropTypes.bool,
- onSelect: PropTypes.func,
- selectable: PropTypes.bool,
- selected: PropTypes.bool,
- theme: PropTypes.shape({
- selectable: PropTypes.string
- })
- };
-
- TableHead.defaultProps = {
- className: '',
- model: {},
- selected: false
- };
+ }
return TableHead;
};
-export default factory;
+const TableHead = factory(InjectCheckbox, InjectTableCell);
+export default themr(TABLE)(TableHead);
+export { factory as tableHeadFactory };
+export { TableHead };
diff --git a/components/table/TableRow.js b/components/table/TableRow.js
index 8b47c13f..67eb3ae6 100644
--- a/components/table/TableRow.js
+++ b/components/table/TableRow.js
@@ -1,113 +1,45 @@
-import React, { Component, PropTypes } from 'react';
+import React, { cloneElement, Component, PropTypes } from 'react';
import classnames from 'classnames';
-import utils from '../utils/utils';
+import { themr } from 'react-css-themr';
+import { TABLE } from '../identifiers.js';
+import InjectCheckbox from '../checkbox/Checkbox.js';
+import InjectTableCell from './TableCell.js';
-const factory = (Checkbox) => {
+const factory = (Checkbox, TableCell) => {
class TableRow extends Component {
static propTypes = {
- data: PropTypes.object,
- index: PropTypes.number,
- model: PropTypes.object,
- onChange: PropTypes.func,
- onRowClick: PropTypes.func,
+ children: PropTypes.node,
+ className: PropTypes.string,
+ idx: PropTypes.number,
onSelect: PropTypes.func,
selectable: PropTypes.bool,
selected: PropTypes.bool,
theme: PropTypes.shape({
- editable: PropTypes.string,
+ checkboxCell: PropTypes.string,
row: PropTypes.string,
- selectable: PropTypes.string,
selected: PropTypes.string
})
};
- handleInputChange = (index, key, type, event) => {
- let value;
- switch (type) {
- case 'checkbox':
- value = event.target.checked;
- break;
- // Handle contentEditable
- case 'text':
- value = event.target.textContent;
- break;
- default:
- value = event.target.value;
- break;
- }
-
- const onChange = this.props.model[key].onChange || this.props.onChange;
- onChange(index, key, value);
+ handleSelect = value => {
+ const { idx, onSelect } = this.props;
+ if (onSelect) onSelect(idx, value);
};
- renderSelectCell () {
- if (this.props.selectable) {
- return (
-
-
-
- );
- }
- }
-
- renderCells () {
- return Object.keys(this.props.model).map((key) => {
- return {this.renderCell(key)} ;
- });
- }
-
- renderCell (key) {
- const value = this.props.data[key];
-
- // if the value is a valid React element return it directly, since it
- // cannot be edited and should not be converted to a string...
- if (React.isValidElement(value)) { return value; }
-
- const onChange = this.props.model[key].onChange || this.props.onChange;
- if (onChange) {
- return this.renderInput(key, value);
- } else if (value) {
- return value.toString();
- }
- }
-
- renderInput (key, value) {
- const index = this.props.index;
- const inputType = utils.inputTypeForPrototype(this.props.model[key].type);
- const inputValue = utils.prepareValueForInput(value, inputType);
- const checked = inputType === 'checkbox' && value ? true : null;
-
- if (inputType === 'text') {
- return (
-
- );
- }
-
- return (
-
- );
- }
-
render () {
- const className = classnames(this.props.theme.row, {
- [this.props.theme.editable]: this.props.onChange,
- [this.props.theme.selected]: this.props.selected
- });
-
+ const { children, className, selectable, idx, selected, theme, ...other } = this.props; // eslint-disable-line
+ const _className = classnames(theme.row, {
+ [theme.selected]: selectable && selected
+ }, className);
return (
-
- {this.renderSelectCell()}
- {this.renderCells()}
+
+ {selectable &&
+
+ }
+ {React.Children.map(children, (child, index) => cloneElement(child, {
+ column: index,
+ tagName: 'td'
+ }))}
);
}
@@ -116,4 +48,7 @@ const factory = (Checkbox) => {
return TableRow;
};
-export default factory;
+const TableRow = factory(InjectCheckbox, InjectTableCell);
+export default themr(TABLE)(TableRow);
+export { factory as tableRowFactory };
+export { TableRow };
diff --git a/components/table/_config.scss b/components/table/_config.scss
deleted file mode 100644
index 7ec3b5a2..00000000
--- a/components/table/_config.scss
+++ /dev/null
@@ -1,5 +0,0 @@
-$table-row-height: 48px !default;
-$table-row-divider: solid 1px rgba(0,0,0,.12) !default;
-$table-row-offset: 1.8 * $unit !default;
-$table-row-highlight: #eee !default;
-$table-text-color: #757575 !default;
diff --git a/components/table/index.d.ts b/components/table/index.d.ts
deleted file mode 100644
index a4946bd3..00000000
--- a/components/table/index.d.ts
+++ /dev/null
@@ -1,151 +0,0 @@
-import * as React from "react";
-import ReactToolbox from "../index";
-
-export interface TableTheme extends TableRowTheme {
- /**
- * Classname used for the root element.
- */
- table?: string;
-}
-
-export interface TableProps extends ReactToolbox.Props {
- /**
- * If true, component will show a heading using model field names.
- * @default true
- */
- heading?: boolean;
- /**
- * Object describing the data model that represents each object in the source.
- */
- model?: any;
- /**
- * Callback function that is fired when an item in a row changes. If set, rows are editable.
- */
- onChange?: Function;
- /**
- * Callback fired when row was clicked.
- */
- onRowClick?: Function;
- /**
- * Callback function invoked when the row selection changes.
- */
- onSelect?: Function;
- /**
- * If true, each row will display a checkbox to allow the user to select that one row.
- * @default true
- */
- selectable?: boolean;
- /**
- * If true, the header and each row will display a checkbox to allow the user to select multiple rows.
- * @default true
- */
- multiSelectable?: boolean;
- /**
- * Array of indexes of the items in the source that should appear as selected.
- */
- selected?: any[];
- /**
- * Array of objects representing each item to show.
- */
- source?: any[];
- /**
- * Classnames object defining the component style.
- */
- theme?: TableTheme;
-}
-
-export class Table extends React.Component { }
-
-export interface TableHeadTheme {
- /**
- * It will be added to a row in case it is selectable.
- */
- selectable?: string;
-}
-
-export interface TableHeadProps extends ReactToolbox.Props {
- /**
- * Object describing the data model that represents each object in the source.
- */
- model?: any;
- /**
- * If true, the header and each row will display a checkbox to allow the user to select multiple rows.
- */
- multiSelectable?: boolean;
- /**
- * Callback function invoked when the row selection changes.
- */
- onSelect?: Function;
- /**
- * If true, each row will display a checkbox to allow the user to select that one row.
- * @default true
- */
- selectable?: boolean;
- /**
- * Whether header should look selected.
- * @default false
- */
- selected?: boolean;
- /**
- * Classnames object defining the component style.
- */
- theme?: TableHeadTheme;
-}
-
-export class TableHead extends React.Component { }
-
-export interface TableRowTheme extends TableHeadTheme {
- /**
- * It will be added to a row in case it is editable.
- */
- editable?: string;
- /**
- * Used for the row element.
- */
- row?: string;
- /**
- * Added to a row in case it is selected.
- */
- selected?: string;
-}
-
-export interface TableRowProps {
- /**
- * Single row data.
- */
- data?: any;
- /**
- * Row index.
- */
- index?: number;
- /**
- * Object describing the data model that represents each object in the source.
- */
- model?: any;
- /**
- * Callback function that is fired when an item in a row changes. If set, rows are editable.
- */
- onChange?: Function;
- /**
- * Callback fired when row was clicked.
- */
- onRowClick?: Function;
- /**
- * Callback function invoked when the row selection changes.
- */
- onSelect?: Function;
- /**
- * If true, each row will display a checkbox to allow the user to select that one row.
- * @default true
- */
- selectable?: boolean;
- /**
- * Whether table row should look selected.
- * @default false
- */
- selected?: boolean;
-}
-
-export class TableRow extends React.Component { }
-
-export default Table;
diff --git a/components/table/index.js b/components/table/index.js
index 77e1c775..e59d877b 100644
--- a/components/table/index.js
+++ b/components/table/index.js
@@ -1,15 +1,22 @@
import { themr } from 'react-css-themr';
import { TABLE } from '../identifiers.js';
import { Checkbox } from '../checkbox';
+import { FontIcon } from '../font_icon';
+
import { tableFactory } from './Table.js';
-import tableHeadFactory from './TableHead.js';
-import tableRowFactory from './TableRow.js';
-import theme from './theme.scss';
+import { tableHeadFactory } from './TableHead.js';
+import { tableRowFactory } from './TableRow.js';
+import { tableCellFactory } from './TableCell.js';
+import theme from './theme.css';
const applyTheme = (Component) => themr(TABLE, theme)(Component);
-const ThemedTableHead = applyTheme(tableHeadFactory(Checkbox));
-const ThemedTableRow = applyTheme(tableRowFactory(Checkbox));
+const ThemedTableCell = applyTheme(tableCellFactory(FontIcon));
+const ThemedTableHead = applyTheme(tableHeadFactory(Checkbox, ThemedTableCell));
+const ThemedTableRow = applyTheme(tableRowFactory(Checkbox, ThemedTableCell));
const ThemedTable = applyTheme(tableFactory(ThemedTableHead, ThemedTableRow));
export default ThemedTable;
export { ThemedTable as Table };
+export { ThemedTableHead as TableHead };
+export { ThemedTableRow as TableRow };
+export { ThemedTableCell as TableCell };
diff --git a/components/table/readme.md b/components/table/readme.md
index 4a385374..3d99021b 100644
--- a/components/table/readme.md
+++ b/components/table/readme.md
@@ -1,91 +1,158 @@
-# Table
+# Data Table
-The Table component is an enhanced version of the standard HTML ``. A data-table consists of rows and columns of well-formatted data, presented with appropriate user interaction capabilities. This component uses a solid typed model, helping you to create formatted cells. These cells can be editable if you subscribe to `onChange` method who dispatch then new source with each change.
-
-*A note about models and table headers*: By default, the table header text uses name of the property in the model. Additionally, the table header text is automatically set in title case (first letter of each word capitalized). Thus, if you use the property name `twitter` in your model, the displayed table header will be `Twitter`. You can override the default text by including a `title` attribute, as demonstrated in the example below for the `birthdate` property. You may also override the title case in your own theme's css. In the following example, we force the first letter of the table header text to lowercase, using SCSS syntax:
-
-```
-.table {
- th {
- &:first-letter {
- text-transform: lowercase;
- }
- }
-}
-```
+The [Table component](https://material.google.com/components/data-tables.html) is an enhanced version of the standard HTML ``. A data-table consists of rows and columns of well-formatted data, presented with appropriate user interaction capabilities. You can compose your Table with similar components to those you use directly in HTML.
```jsx
-import Table from 'react-toolbox/lib/table';
+import React, { Component } from 'react';
+import { Table, TableHead, TableRow, TableCell } from '../../components/table2';
+import Tooltip from '../../components/tooltip';
-const UserModel = {
- name: {type: String},
- twitter: {type: String},
- birthdate: {type: Date,
- title: 'Date of Birth'},
- cats: {type: Number},
- dogs: {type: Number},
- active: {type: Boolean}
-};
-
-const users = [
- {name: 'Javi Jimenez', twitter: '@soyjavi', birthdate: new Date(1980, 3, 11), cats: 1},
- {name: 'Javi Velasco', twitter: '@javivelasco', birthdate: new Date(1987, 1, 1), dogs: 1, active: true}
+const data = [
+ {name: 'Cupcake', calories: 305, fat: 3.7, sodium: 413, calcium: '3%', iron: '8%'},
+ {name: 'Donut', calories: 452, fat: 25.0, sodium: 326, calcium: '2%', iron: '22%'},
+ {name: 'Eclair', calories: 262, fat: 16.0, sodium: 337, calcium: '6%', iron: '7%'},
+ {name: 'Frozen yogurt', calories: 159, fat: 6.0, sodium: 87, calcium: '14%', iron: '1%'},
+ {name: 'Gingerbread', calories: 356, fat: 16.0, sodium: 327, calcium: '7%', iron: '16%'},
+ {name: 'Ice cream sandwich', calories: 237, fat: 9.0, sodium: 129, calcium: '8%', iron: '1%'},
+ {name: 'Jelly bean', calories: 375, fat: 0.0, sodium: 50, calcium: '0%', iron: '0%'},
+ {name: 'KitKat', calories: 518, fat: 26.0, sodium: 54, calcium: '12%', iron: '6%'}
];
-class TableTest extends React.Component {
- state = { selected: [], source: users };
+const TooltipCell = Tooltip(TableCell);
- handleChange = (row, key, value) => {
- const source = this.state.source;
- source[row][key] = value;
- this.setState({source});
+const sortByCaloriesAsc = (a, b) => {
+ if (a.calories < b.calories) return -1;
+ if (a.calories > b.calories) return 1;
+ return 0;
+};
+
+const sortByCaloriesDesc = (a, b) => {
+ if (a.calories > b.calories) return -1;
+ if (a.calories < b.calories) return 1;
+ return 0;
+};
+
+class TableTest extends Component {
+ state = {
+ selected: ['Donut'],
+ sorted: 'asc'
};
- handleSelect = (selected) => {
- this.setState({selected});
+ getSortedData = () => {
+ const compare = this.state.sorted === 'asc' ? sortByCaloriesAsc : sortByCaloriesDesc;
+ return data.sort(compare);
+ }
+
+ handleRowSelect = selected => {
+ const sortedData = this.getSortedData();
+ this.setState({ selected: selected.map(item => sortedData[item].name) });
+ };
+
+ handleSortClick = () => {
+ const { sorted } = this.state;
+ const nextSorting = sorted === 'asc' ? 'desc' : 'asc';
+ this.setState({ sorted: nextSorting });
};
render () {
+ const { sorted } = this.state;
+ const sortedData = this.getSortedData();
return (
-
+
+
+
+ Dessert (100g serving)
+
+ Calories
+ Fat (g)
+ Sodium (mg)
+ Calcium (%)
+ Iron (%)
+
+ {sortedData.map((item, idx) => (
+
+ {item.name}
+ {item.calories}
+ {item.fat}
+ {item.sodium}
+ {item.calcium}
+ {item.iron}
+
+ ))}
+
);
}
}
-`
+
+export default TableTest;
```
-This component can be styled by context providing a theme with the key `RTTable` through the theme provider.
+If you want to provide styles via context to this components, you should use the key `RTTable`.
-## Properties
+## Table
+
+This is the `Table` main wrapper component. It parses children to generate an appropriated structure passing also some additional props so it's important to keep an eye on nesting.
+
+### Properties
Name | Type | Default | Description
-:---------------- | :--------- | :------ | :--------------------------------------------------------------------------------------------------
-`className` | `String` | `''` | Sets a custom class to style the Component.
-`heading` | `Boolean` | `true` | If true, component will show a heading using model field names.
-`model` | `Object` | | Object describing the data model that represents each object in the `source`.
-`onChange` | `Function` | | Callback function that is fired when an item in a row changes. If set, rows are editable.
-`onSelect` | `Function` | | Callback function invoked when the row selection changes.
+:---------------- | :--------- | :------ | :-------------------------------------------------------------
+`children` | `Node` | | Pass `TableHead` and `TableRow` components as children always.
+`className` | `String` | `''` | Sets a custom class to style the component.
+`multiSelectable` | `Boolean` | `false` | If true, the header and each row will display a checkbox to allow the user to select multiple rows at the same time.
+`onRowSelect` | `Function` | | Will be called when the row selection changes. It passes an array of selected indexes as first parameter so you can figure out changes in your local state.
`selectable` | `Boolean` | `true` | If true, each row will display a checkbox to allow the user to select that one row.
-`multiSelectable` | `Boolean` | `true` | If true, the header and each row will display a checkbox to allow the user to select multiple rows.
-`selected` | `Array` | | Array of indexes of the items in the source that should appear as selected.
-`source` | `Array` | | Array of objects representing each item to show.
+
+## TableHead
+
+Header element that should be place as a direct descendant of `Table` and whose children should be `TableCells` that will be rendered as header cells. It receives properties from the parent to decide whether a select column should be placed/disabled or not.
+
+### Properties
+
+Name | Type | Default | Description
+:---------------- | :--------- | :------ | :----------------------------------------------
+`children` | `Node` | | Pass `TableCell` components always either decorated or not.
+`className` | `String` | `''` | Sets a custom class to style the header row.
+`displaySelect` | `Boolean` | `true` | If true, a checkbox will be displayed to select every row. In case the table is not multi-selectable, it will be disabled though.
+
+## TableRow
+
+An element that represents a row in the Table. It should be place as a direct descendant of `Table` and it should has `TableCells` children. It receives extra properties from `Table` to decide if checkboxes should be placed as a first column.
+
+### Properties
+
+Name | Type | Default | Description
+:---------------- | :--------- | :------ | :----------------------------------------------
+`children` | `Node` | | Pass `TableCell` components always either decorated or not.
+`className` | `String` | `''` | Sets a custom class to style the row.
+`selected` | `Boolean` | `false` | If true, the row will be considered as selected so the row will display a selected style with the selection control activated. This property is used by `Table` to figure out the selection when you interact with the Table.
+
+## TableCell
+
+Displays a cell of the `Table`. It renders a tag `td` or `th` depending on if it's set as direct children of `TableRow` or `TableHead`.
+
+Name | Type | Default | Description
+:---------------- | :--------- | :------ | :----------------------------------------------
+`children` | `Any` | | Any content you want to render inside the cell.
+`className` | `String` | `''` | Sets a custom class to style that particular cell.
+`numeric` | `Boolean` | `false` | If true the cell is considered as numeric and the content will be displayed aligned to right.
+`onClick` | `Function` | | Called when the cell is clicked with the click event, column number and row number.
+`sorted` | `Bool` | `asc` or `desc` | Optional. If you provide a value the cell will show an arrow pointing down or up depending on the value to indicate it is a sorted element. Useful only for columns.
## Theme
-Name | Description
-:----------- | :--------------------------------------------------
-`editable` | It will be added to a row in case it is editable.
-`row` | Used for the row element.
-`selectable` | It will be added to a row in case it is selectable.
-`selected` | Added to a row in case it is selected.
-`table` | Classname used for the root element.
+Name | Description
+:------------- | :--------------------------------------------------
+`table` | Used the root element of the component (`table`).
+`head` | Used for the `thead` element.
+`row` | Added to each row in the table except for the header.
+`selected` | Modifier for rows that are selected.
+`headCell` | Added to each cell displayed in the head.
+`rowCell` | Added to each cell displayed in the table body.
+`sorted` | Modifier for cells that are sorted asc or desc.
+`numeric` | Modifier for cells that are numeric.
+`checkboxCell` | Modifier for cells that include a select checkbox.
+`sortIcon` | Used for the sort icon included in sorted cells.
+`asc` | Modifier for the icon in case the order is ascendent.
diff --git a/components/table/theme.css b/components/table/theme.css
new file mode 100644
index 00000000..b53ffa42
--- /dev/null
+++ b/components/table/theme.css
@@ -0,0 +1,110 @@
+@import '../colors.css';
+@import '../variables.css';
+
+:root {
+ --table-font-size: calc(1.3 * var(--unit));
+ --table-header-font-size: calc(1.2 * var(--unit));
+ --table-header-sort-icon-size: calc(1.6 * var(--unit));
+ --table-header-color: color(#000 a(54%));
+ --table-header-sorted-color: color(#000 a(87%));
+ --table-header-sorted-icon-hover-color: color(#000 a(26%));
+ --table-dividers: 1px solid #e6e6e6;
+ --table-row-color: color(#000 a(87%));
+ --table-hover-color: #eee;
+ --table-selection-color: #f5f5f5;
+ --table-row-height: calc(4.8 * var(--unit));
+ --table-column-spacing: calc(3.6 * var(--unit));
+ --table-column-padding: calc(var(--table-column-spacing) / 2);
+ --table-cell-padding: calc(2.4 * var(--unit));
+ --table-cell-top: calc(var(--table-cell-padding) / 2);
+}
+
+.table {
+ background-color: var(--color-white);
+ border-collapse: collapse;
+ composes: reset from '../helpers.css';
+ font-size: var(--table-font-size);
+ width: 100%;
+}
+
+.head {
+ padding-bottom: calc(0.3 * var(--unit));
+ white-space: nowrap;
+}
+
+.row {
+ color: var(--table-row-color);
+ height: var(--table-row-height);
+ transition-duration: 0.28s;
+ transition-property: background-color;
+ transition-timing-function: var(--animation-curve-default);
+
+ &:hover { background-color: var(--table-hover-color); }
+ &.selected { background-color: var(--table-selection-color); }
+}
+
+.rowCell,
+.headCell {
+ padding: 0 var(--table-column-padding) 12px var(--table-column-padding);
+ text-align: left;
+
+ &:first-of-type { padding-left: 24px; }
+ &:last-of-type { padding-right: 24px; }
+ &.numeric { text-align: right; }
+}
+
+.rowCell {
+ border-bottom: var(--table-dividers);
+ border-top: var(--table-dividers);
+ height: var(--table-row-height);
+ padding-top: var(--table-cell-top);
+ vertical-align: middle;
+
+ &.checkboxCell {
+ width: calc(1.8 * var(--unit));
+
+ & > * {
+ margin: 0;
+ }
+ }
+}
+
+.headCell {
+ color: var(--table-header-color);
+ font-size: var(--table-header-font-size);
+ font-weight: 500;
+ height: var(--table-row-height);
+ line-height: calc(2.4 * var(--unit));
+ padding-bottom: 8px;
+ text-overflow: ellipsis;
+ vertical-align: bottom;
+
+ &.checkboxCell {
+ width: calc(1.8 * var(--unit));
+
+ & > * {
+ margin: 0 0 3px;
+ }
+ }
+
+ &.sorted {
+ color: var(--table-header-sorted-color);
+ cursor: pointer;
+
+ &:hover .sortIcon {
+ color: var(--table-header-sorted-icon-hover-color);
+ }
+ }
+}
+
+.sortIcon {
+ display: inline-block;
+ font-size: calc(1.6 * var(--unit));
+ margin-right: 3px;
+ transition: 0.28s transform var(--animation-curve-default);
+ vertical-align: sub;
+
+ &.asc {
+ transform: rotate(180deg);
+ }
+}
diff --git a/components/table/theme.scss b/components/table/theme.scss
deleted file mode 100644
index 232ed426..00000000
--- a/components/table/theme.scss
+++ /dev/null
@@ -1,59 +0,0 @@
-@import "../colors";
-@import "../globals";
-@import "../mixins";
-@import "./config";
-
-.table {
- width: 100%;
- font-size: $font-size-tiny;
- color: $table-text-color;
- text-align: left;
- border-spacing: 0;
- tr {
- height: $table-row-height;
- line-height: $table-row-height;
- }
- th {
- font-weight: $font-weight-bold;
- &:first-letter {
- text-transform: capitalize;
- }
- }
- th, td {
- position: relative;
- padding: 0 $table-row-offset;
- border-bottom: $table-row-divider;
- &.selectable {
- width: 1.8 * $unit;
- padding-right: 0;
- > * {
- margin: 0;
- }
- }
- }
-}
-
-.row {
- transition: background-color $animation-duration $animation-curve-default;
- &:last-child {
- td {
- border-color: transparent;
- }
- }
- > td {
- > input {
- display: block;
- width: 100%;
- background-color: transparent;
- border: 0;
- }
- }
-}
-
-.selected, .row:hover {
- background-color: $table-row-highlight;
-}
-
-.editable > * {
- cursor: pointer;
-}
diff --git a/components/tabs/__tests__/index.spec.js b/components/tabs/__tests__/index.spec.js
index 522e5c22..985dcb8a 100644
--- a/components/tabs/__tests__/index.spec.js
+++ b/components/tabs/__tests__/index.spec.js
@@ -8,7 +8,7 @@ import ReactDOM from 'react-dom';
import Tabs, { Tabs as RawTabs } from '../Tabs';
import Tab from '../Tab';
import TabContent from '../TabContent';
-import theme from '../theme.scss';
+import theme from '../theme.css';
const getRenderedClassName = (tree, TargetComponent) => {
const rendered = ReactTestUtils.findRenderedComponentWithType(tree, TargetComponent);
diff --git a/components/tabs/_config.scss b/components/tabs/_config.scss
deleted file mode 100644
index e5ee9c8e..00000000
--- a/components/tabs/_config.scss
+++ /dev/null
@@ -1,20 +0,0 @@
-$tab-label-disabled-opacity: .2 !default;
-$tab-label-h-padding: 1.2 * $unit !default;
-$tab-label-height: 4.8 * $unit !default;
-$tab-icon-height: 2.4 * $unit !default;
-$tab-icon-margin-bottom: .8 * $unit !default;
-$tab-text-height: 1.4 * $unit !default;
-$tab-label-v-padding: ($tab-label-height - $tab-text-height) / 2 !default;
-$tab-navigation-border-color: $color-divider !default;
-$tab-pointer-color: $color-primary !default;
-$tab-pointer-height: .2 * $unit !default;
-$tab-text: $color-black !default;
-$tab-text-color: $tab-text !default;
-$tab-text-inactive-color: rgba($tab-text, .7) !default;
-
-// Inverse
-$tab-inverse-bar-color: $color-primary !default;
-$tab-inverse-pointer-color: $color-accent !default;
-$tab-inverse-text: $color-primary-contrast !default;
-$tab-inverse-text-color: $tab-inverse-text !default;
-$tab-inverse-text-inactive-color: rgba($tab-inverse-text, .7) !default;
diff --git a/components/tabs/config.css b/components/tabs/config.css
new file mode 100644
index 00000000..957a9c87
--- /dev/null
+++ b/components/tabs/config.css
@@ -0,0 +1,20 @@
+:root {
+ --tab-label-disabled-opacity: 0.2;
+ --tab-label-h-padding: calc(1.2 * var(--unit));
+ --tab-label-height: calc(4.8 * var(--unit));
+ --tab-icon-height: calc(2.4 * var(--unit));
+ --tab-icon-margin-bottom: calc(0.8 * var(--unit));
+ --tab-text-height: calc(1.4 * var(--unit));
+ --tab-label-v-padding: calc((var(--tab-label-height) - var(--tab-text-height)) / 2);
+ --tab-navigation-border-color: var(--color-divider);
+ --tab-pointer-color: var(--color-primary);
+ --tab-pointer-height: calc(0.2 * var(--unit));
+ --tab-text: var(--color-black);
+ --tab-text-color: var(--tab-text);
+ --tab-text-inactive-color: color(var(--tab-text) a(70%));
+ --tab-inverse-bar-color: var(--color-primary);
+ --tab-inverse-pointer-color: var(--color-accent);
+ --tab-inverse-text: var(--color-primary-contrast);
+ --tab-inverse-text-color: var(--tab-inverse-text);
+ --tab-inverse-text-inactive-color: color(var(--tab-inverse-text) a(30%));
+}
diff --git a/components/tabs/index.js b/components/tabs/index.js
index 72802054..8772cd22 100644
--- a/components/tabs/index.js
+++ b/components/tabs/index.js
@@ -4,7 +4,7 @@ import { tabsFactory } from './Tabs.js';
import { TabContent } from './TabContent.js';
import { Tab } from './Tab.js';
import FontIcon from '../font_icon/FontIcon.js';
-import theme from './theme.scss';
+import theme from './theme.css';
const applyTheme = (Component) => themr(TABS, theme)(Component);
const ThemedTabContent = applyTheme(TabContent);
diff --git a/components/tabs/theme.css b/components/tabs/theme.css
new file mode 100644
index 00000000..8cb478ea
--- /dev/null
+++ b/components/tabs/theme.css
@@ -0,0 +1,139 @@
+@import '../colors.css';
+@import '../variables.css';
+@import './config.css';
+
+.tabs {
+ composes: reset from '../helpers.css';
+ display: flex;
+ flex-direction: column;
+}
+
+.navigation {
+ box-shadow: inset 0 -1px var(--tab-navigation-border-color);
+ display: flex;
+ flex-direction: row;
+ overflow-x: hidden;
+ position: relative;
+}
+
+.navigationContainer {
+ display: flex;
+
+ & .navigation {
+ flex: 1;
+ }
+}
+
+.arrow {
+ color: var(--tab-text-color);
+ padding: 0 var(--tab-label-h-padding);
+}
+
+.arrowContainer {
+ align-items: center;
+ box-shadow: inset 0 -1px var(--tab-navigation-border-color);
+ cursor: pointer;
+ display: flex;
+}
+
+.label {
+ color: var(--tab-text-inactive-color);
+ font-size: var(--tab-text-height);
+ font-weight: var(--font-weight-semi-bold);
+ line-height: 1;
+ padding: var(--tab-label-v-padding) var(--tab-label-h-padding);
+ text-transform: uppercase;
+ transition-duration: var(--animation-duration);
+ transition-property: box-shadow, color;
+ transition-timing-function: var(--animation-curve-default);
+
+ &.active {
+ color: var(--tab-text-color);
+ }
+
+ &.disabled {
+ opacity: var(--tab-label-disabled-opacity);
+ }
+
+ &:not(.disabled) {
+ cursor: pointer;
+ }
+
+ &.hidden {
+ display: none;
+ }
+
+ &.withIcon {
+ padding-bottom: calc(var(--tab-label-v-padding) - var(--tab-icon-margin-bottom) / 2);
+ padding-top: calc(var(--tab-label-v-padding) - var(--tab-icon-margin-bottom) / 2);
+ text-align: center;
+ }
+
+ &.withText {
+ & .icon {
+ margin-bottom: var(--tab-icon-margin-bottom);
+ }
+ }
+}
+
+.icon {
+ display: block;
+ height: var(--tab-icon-height);
+ line-height: var(--tab-icon-height);
+ margin: 0 auto;
+}
+
+.pointer {
+ background-color: var(--tab-pointer-color);
+ height: var(--tab-pointer-height);
+ margin-top: calc(-1 * var(--tab-pointer-height));
+ position: absolute;
+ transition-duration: var(--animation-duration);
+ transition-property: left, width;
+ transition-timing-function: var(--animation-curve-default);
+ width: 0;
+}
+
+.tab {
+ display: flex;
+ flex-direction: column;
+ padding: var(--tab-label-v-padding) var(--tab-label-h-padding);
+
+ &:not(.active) {
+ display: none;
+ }
+
+ &.active {
+ display: flex;
+ }
+}
+
+.fixed {
+ & .label {
+ flex: 1;
+ text-align: center;
+ }
+}
+
+.inverse {
+ & .navigation,
+ & .arrowContainer {
+ background-color: var(--tab-inverse-bar-color);
+ }
+
+ & .label {
+ color: var(--tab-inverse-text-inactive-color);
+
+ &.active {
+ color: var(--tab-inverse-text-color);
+ }
+ }
+
+ & .arrow {
+ color: var(--tab-inverse-text-color);
+ }
+
+ & .pointer {
+ background-color: var(--tab-inverse-pointer-color);
+ }
+}
diff --git a/components/tabs/theme.scss b/components/tabs/theme.scss
deleted file mode 100644
index 85ae18be..00000000
--- a/components/tabs/theme.scss
+++ /dev/null
@@ -1,142 +0,0 @@
-@import "../colors";
-@import "../globals";
-@import "../mixins";
-@import "./config";
-
-.tabs {
- display: flex;
- flex-direction: column;
-}
-
-.navigation {
- position: relative;
- display: flex;
- flex-direction: row;
- overflow-x: hidden;
- box-shadow: inset 0 -1px $tab-navigation-border-color;
-}
-
-.navigationContainer {
- display: flex;
-
- .navigation {
- flex: 1;
- }
-}
-
-.arrow {
- padding: 0 $tab-label-h-padding;
- color: $tab-text-color;
-}
-
-.arrowContainer {
- display: flex;
- align-items: center;
- cursor: pointer;
- box-shadow: inset 0 -1px $tab-navigation-border-color;
-}
-
-.label {
- padding: $tab-label-v-padding $tab-label-h-padding;
- font-size: $tab-text-height;
- font-weight: $font-weight-semi-bold;
- line-height: 1;
- color: $tab-text-inactive-color;
- text-align: center;
- text-transform: uppercase;
- transition-timing-function: $animation-curve-default;
- transition-duration: $animation-duration;
- transition-property: box-shadow, color;
-
- &.active {
- color: $tab-text-color;
- }
-
- &.disabled {
- opacity: $tab-label-disabled-opacity;
- }
-
- &:not(.disabled) {
- cursor: pointer;
- }
-
- &.hidden {
- display: none;
- }
-
- &.withIcon {
- padding-top: ($tab-label-v-padding - $tab-icon-margin-bottom / 2);
- padding-bottom: ($tab-label-v-padding - $tab-icon-margin-bottom / 2);
- }
-
- &.withText {
- .icon {
- margin-bottom: $tab-icon-margin-bottom;
- }
- }
-}
-
-.icon {
- display: block;
- height: $tab-icon-height;
- margin: 0 auto;
- line-height: $tab-icon-height;
-}
-
-.pointer {
- position: absolute;
- width: 0;
- height: $tab-pointer-height;
- margin-top: - $tab-pointer-height;
- background-color: $tab-pointer-color;
- transition-timing-function: $animation-curve-default;
- transition-duration: $animation-duration;
- transition-property: left, width;
-
- &.disableAnimation {
- transition: none;
- }
-}
-
-.tab {
- display: flex;
- flex-direction: column;
- padding: $tab-label-v-padding $tab-label-h-padding;
-
- &:not(.active) {
- display: none;
- }
-
- &.active {
- display: flex;
- }
-}
-
-.fixed {
- .label {
- flex: 1;
- text-align: center;
- }
-}
-
-.inverse {
- .navigation, .arrowContainer {
- background-color: $tab-inverse-bar-color;
- }
-
- .label {
- color: $tab-inverse-text-inactive-color;
-
- &.active {
- color: $tab-inverse-text-color;
- }
- }
-
- .arrow {
- color: $tab-inverse-text-color;
- }
-
- .pointer {
- background-color: $tab-inverse-pointer-color;
- }
-}
diff --git a/components/time_picker/Clock.js b/components/time_picker/Clock.js
index 3ef97fbc..a56a5bb0 100644
--- a/components/time_picker/Clock.js
+++ b/components/time_picker/Clock.js
@@ -1,6 +1,6 @@
import React, { Component, PropTypes } from 'react';
import CssTransitionGroup from 'react-addons-css-transition-group';
-import { ZoomIn, ZoomOut } from '../animations';
+import { getAnimationModule } from '../utils/utils';
import time from '../utils/time.js';
import Hours from './ClockHours.js';
import Minutes from './ClockMinutes.js';
@@ -106,11 +106,16 @@ class Clock extends Component {
render () {
const { theme } = this.props;
- const animation = this.props.display === 'hours' ? ZoomOut : ZoomIn;
+ const animation = this.state.display === 'hours' ? 'zoomOut' : 'zoomIn';
+ const animationModule = getAnimationModule(animation, theme);
return (
-
+
{this.props.display === 'hours' ? this.renderHours() : null}
{this.props.display === 'minutes' ? this.renderMinutes() : null}
diff --git a/components/time_picker/ClockHand.js b/components/time_picker/ClockHand.js
index 904c4968..40be31bd 100644
--- a/components/time_picker/ClockHand.js
+++ b/components/time_picker/ClockHand.js
@@ -1,7 +1,7 @@
import React, { Component, PropTypes } from 'react';
+import { angle360FromPositions } from '../utils/utils.js';
import events from '../utils/events.js';
import prefixer from '../utils/prefixer.js';
-import utils from '../utils/utils.js';
class Hand extends Component {
static propTypes = {
@@ -92,7 +92,7 @@ class Hand extends Component {
}
positionToAngle (position) {
- return utils.angle360FromPositions(this.props.origin.x, this.props.origin.y, position.x, position.y);
+ return angle360FromPositions(this.props.origin.x, this.props.origin.y, position.x, position.y);
}
end (evts) {
diff --git a/components/time_picker/ClockHours.js b/components/time_picker/ClockHours.js
index 5e37cd2e..9c6929b7 100644
--- a/components/time_picker/ClockHours.js
+++ b/components/time_picker/ClockHours.js
@@ -1,10 +1,10 @@
import React, { Component, PropTypes } from 'react';
-import utils from '../utils/utils.js';
+import { range } from '../utils/utils.js';
import Hand from './ClockHand.js';
import Face from './ClockFace.js';
-const outerNumbers = [0, ...utils.range(13, 24)];
-const innerNumbers = [12, ...utils.range(1, 12)];
+const outerNumbers = [0, ...range(13, 24)];
+const innerNumbers = [12, ...range(1, 12)];
const innerSpacing = 1.7;
const step = 360 / 12;
diff --git a/components/time_picker/ClockMinutes.js b/components/time_picker/ClockMinutes.js
index 0debec80..32bf4db9 100644
--- a/components/time_picker/ClockMinutes.js
+++ b/components/time_picker/ClockMinutes.js
@@ -1,9 +1,9 @@
import React, { Component, PropTypes } from 'react';
-import utils from '../utils/utils.js';
+import { range } from '../utils/utils.js';
import Hand from './ClockHand.js';
import Face from './ClockFace.js';
-const minutes = utils.range(0, 60, 5);
+const minutes = range(0, 60, 5);
const step = 360 / 60;
class Minutes extends Component {
diff --git a/components/time_picker/_config.scss b/components/time_picker/_config.scss
deleted file mode 100644
index 51fbd509..00000000
--- a/components/time_picker/_config.scss
+++ /dev/null
@@ -1,27 +0,0 @@
-$timepicker-header-font-size: 5.2 * $unit !default;
-$timepicker-header-padding: $unit !default;
-$timepicker-ampm-font-size: 1.6 * $unit !default;
-$timepicker-primary: $color-primary !default;
-$timepicker-primary-contrast: $color-primary-contrast !default;
-$timepicker-primary-dark: $color-primary-dark !default;
-$timepicker-primary-color: $timepicker-primary !default;
-$timepicker-primary-hover-color: rgba($timepicker-primary, .2) !default;
-$timepicker-primary-contrast-color: $timepicker-primary-contrast !default;
-$timepicker-primary-dark-color: $timepicker-primary-dark !default;
-$timepicker-ampm-height: 2.2 * $unit !default;
-$timepicker-ampm-width: 4 * $unit !default;
-$timepicker-dialog-width: 30 * $unit !default;
-
-$clock-padding: 1.5 * $unit 2 * $unit !default;
-$clock-primary: $color-primary !default;
-$clock-primary-contrast: $color-primary-contrast !default;
-$clock-primary-dark: $color-primary-dark !default;
-$clock-primary-color: $clock-primary !default;
-$clock-primary-hover-color: rgba($clock-primary, .2) !default;
-$clock-primary-contrast-color: $clock-primary-contrast !default;
-$clock-primary-dark-color: $clock-primary-dark !default;
-$clock-number-size: 2 * $unit !default;
-$clock-hand-width: .4 * $unit !default;
-$clock-hand-dot-size: 1 * $unit !default;
-$clock-knob-size: 3.4 * $unit !default;
-$clock-knob-small-size: 1.2 * $unit !default;
diff --git a/components/time_picker/config.css b/components/time_picker/config.css
new file mode 100644
index 00000000..d0490c8b
--- /dev/null
+++ b/components/time_picker/config.css
@@ -0,0 +1,28 @@
+:root {
+ --timepicker-header-font-size: calc(5.2 * var(--unit));
+ --timepicker-header-padding: var(--unit);
+ --timepicker-ampm-font-size: calc(1.6 * var(--unit));
+ --timepicker-primary: var(--color-primary);
+ --timepicker-primary-contrast: var(--color-primary-contrast);
+ --timepicker-primary-dark: var(--color-primary-dark);
+ --timepicker-primary-color: var(--timepicker-primary);
+ --timepicker-primary-hover-color: color(var(--timepicker-primary) a(20%));
+ --timepicker-primary-contrast-color: var(--timepicker-primary-contrast);
+ --timepicker-primary-dark-color: var(--timepicker-primary-dark);
+ --timepicker-ampm-height: calc(2.2 * var(--unit));
+ --timepicker-ampm-width: calc(4 * var(--unit));
+ --timepicker-dialog-width: calc(30 * var(--unit));
+ --clock-padding: calc(1.5 * var(--unit)) calc(2 * var(--unit));
+ --clock-primary: var(--color-primary);
+ --clock-primary-contrast: var(--color-primary-contrast);
+ --clock-primary-dark: var(--color-primary-dark);
+ --clock-primary-color: var(--clock-primary);
+ --clock-primary-hover-color: color(var(--clock-primary) a(20%));
+ --clock-primary-contrast-color: var(--clock-primary-contrast);
+ --clock-primary-dark-color: var(--clock-primary-dark);
+ --clock-number-size: calc(2 * var(--unit));
+ --clock-hand-width: calc(0.4 * var(--unit));
+ --clock-hand-dot-size: calc(1 * var(--unit));
+ --clock-knob-size: calc(3.4 * var(--unit));
+ --clock-knob-small-size: calc(1.2 * var(--unit));
+}
diff --git a/components/time_picker/index.js b/components/time_picker/index.js
index c9ec8b8f..712818a4 100644
--- a/components/time_picker/index.js
+++ b/components/time_picker/index.js
@@ -4,7 +4,7 @@ import { timePickerFactory } from './TimePicker.js';
import timePickerDialogFactory from './TimePickerDialog.js';
import Dialog from '../dialog';
import Input from '../input';
-import theme from './theme.scss';
+import theme from './theme.css';
const TimePickerDialog = timePickerDialogFactory(Dialog);
const ThemedTimePicker = themr(TIME_PICKER, theme)(timePickerFactory(TimePickerDialog, Input));
diff --git a/components/time_picker/theme.css b/components/time_picker/theme.css
new file mode 100644
index 00000000..95be0baa
--- /dev/null
+++ b/components/time_picker/theme.css
@@ -0,0 +1,245 @@
+@import '../colors.css';
+@import '../variables.css';
+@import './config.css';
+
+.input:not(.disabled) > .inputElement {
+ cursor: pointer;
+}
+
+.header {
+ background: var(--timepicker-primary-color);
+ color: var(--timepicker-primary-contrast-color);
+ font-size: var(--timepicker-header-font-size);
+ padding: var(--timepicker-header-padding);
+ position: relative;
+ text-align: center;
+ width: 100%;
+}
+
+.hours,
+.minutes {
+ cursor: pointer;
+ display: inline-block;
+ opacity: 0.6;
+}
+
+.separator {
+ margin: 0 calc(var(--timepicker-header-padding) / 2);
+ opacity: 0.6;
+}
+
+.ampm {
+ font-size: var(--timepicker-ampm-font-size);
+ height: calc(var(--timepicker-ampm-height) * 2);
+ line-height: var(--timepicker-ampm-height);
+ margin-top: calc(-1 * var(--timepicker-ampm-height));
+ position: absolute;
+ right: calc(2 * var(--unit));
+ text-align: center;
+ top: 50%;
+ width: var(--timepicker-ampm-width);
+}
+
+.am,
+.pm {
+ cursor: pointer;
+ display: block;
+ opacity: 0.6;
+}
+
+.dialog {
+ width: var(--timepicker-dialog-width);
+
+ & > [role='body'] {
+ overflow-y: visible;
+ padding: 0;
+ }
+
+ & > [role='navigation'] > .button {
+ color: var(--timepicker-primary-color);
+
+ &:hover {
+ background: var(--timepicker-primary-hover-color);
+ }
+
+ &:focus:not(:active) {
+ background: var(--timepicker-primary-hover-color);
+ }
+ }
+
+ &.hoursDisplay .hours,
+ &.minutesDisplay .minutes,
+ &.amFormat .am,
+ &.pmFormat .pm {
+ opacity: 1;
+ }
+}
+
+.clock {
+ padding: var(--clock-padding);
+}
+
+.placeholder {
+ position: relative;
+ z-index: var(--z-index-high);
+}
+
+.clockWrapper {
+ background-color: var(--color-divider);
+ border-radius: 50%;
+ position: absolute;
+ width: 100%;
+}
+
+.face {
+ border-radius: 50%;
+ cursor: pointer;
+ left: 50%;
+ position: absolute;
+ top: 50%;
+ transform: translateX(-50%) translateY(-50%);
+ z-index: var(--z-index-high);
+}
+
+.number {
+ height: var(--clock-number-size);
+ margin-left: calc(-1 * var(--clock-number-size) / 2);
+ margin-top: calc(-1 * var(--clock-number-size) / 2);
+ pointer-events: none;
+ position: relative;
+ text-align: center;
+ user-select: none;
+ width: var(--clock-number-size);
+
+ &.active {
+ color: var(--clock-primary-contrast-color);
+ }
+}
+
+.hand {
+ background-color: var(--clock-primary-color);
+ bottom: 50%;
+ display: block;
+ left: 50%;
+ margin-left: calc(-1 * var(--clock-hand-width) / 2);
+ position: absolute;
+ transform-origin: 50% 100%;
+ width: var(--clock-hand-width);
+
+ &::before {
+ background-color: var(--clock-primary-color);
+ border-radius: 50%;
+ bottom: 0;
+ content: '';
+ height: var(--clock-hand-dot-size);
+ left: 50%;
+ margin-bottom: calc(-1 * var(--clock-hand-dot-size) / 2);
+ margin-left: calc(-1 * var(--clock-hand-dot-size) / 2);
+ position: absolute;
+ width: var(--clock-hand-dot-size);
+ }
+
+ &.small > .knob {
+ background-color: var(--clock-primary-hover-color);
+
+ &::after {
+ background: var(--clock-primary-color);
+ border-radius: 50%;
+ content: '';
+ height: var(--clock-knob-small-size);
+ left: 50%;
+ margin-left: calc(-1 * var(--clock-knob-small-size) / 2);
+ margin-top: calc(-1 * var(--clock-knob-small-size) / 2);
+ position: absolute;
+ top: 50%;
+ width: var(--clock-knob-small-size);
+ }
+
+ &::before {
+ background: var(--clock-primary-color);
+ bottom: 0;
+ content: '';
+ height: calc(var(--clock-knob-size) - var(--clock-knob-small-size));
+ left: 50%;
+ margin-left: calc(-1 * var(--clock-hand-width) / 2);
+ position: absolute;
+ width: var(--clock-hand-width);
+ }
+ }
+}
+
+.knob {
+ background-color: var(--clock-primary-color);
+ border-radius: 50%;
+ cursor: pointer;
+ height: var(--clock-knob-size);
+ left: 50%;
+ margin-left: calc(-1 * var(--clock-knob-size) / 2);
+ position: absolute;
+ top: calc(-1 * var(--clock-knob-size));
+ width: var(--clock-knob-size);
+}
+
+.zoomInEnter,
+.zoomInLeave {
+ position: absolute;
+}
+
+.zoomInEnterActive,
+.zoomInLeaveActive {
+ transition: transform, opacity;
+ transition-duration: 500ms;
+ transition-timing-function: var(--animation-curve-fast-out-slow-in);
+}
+
+.zoomInEnter {
+ opacity: 0;
+ transform: scale(0.85);
+
+ &.zoomInEnterActive {
+ opacity: 1;
+ transform: scale(1);
+ }
+}
+
+.zoomInLeave {
+ opacity: 1;
+ transform: scale(1);
+
+ &.zoomInLeaveActive {
+ opacity: 0;
+ transform: scale(1.25);
+ }
+}
+
+.zoomOutEnter,
+.zoomOutLeave {
+ position: absolute;
+}
+
+.zoomOutEnterActive,
+.zoomOutLeaveActive {
+ transition: transform, opacity;
+ transition-duration: 500ms;
+ transition-timing-function: var(--animation-curve-fast-out-slow-in);
+}
+
+.zoomOutEnter {
+ opacity: 0;
+ transform: scale(1.25);
+
+ &.zoomOutEnterActive {
+ opacity: 1;
+ transform: scale(1);
+ }
+}
+
+.zoomOutLeave {
+ opacity: 1;
+ transform: scale(1);
+
+ &.zoomOutLeaveActive {
+ opacity: 0;
+ transform: scale(0.85);
+ }
+}
diff --git a/components/time_picker/theme.scss b/components/time_picker/theme.scss
deleted file mode 100644
index 328cdc43..00000000
--- a/components/time_picker/theme.scss
+++ /dev/null
@@ -1,168 +0,0 @@
-@import "../colors";
-@import "../globals";
-@import "../mixins";
-@import "./config";
-
-.input:not(.disabled) > .inputElement {
- cursor: pointer;
-}
-
-.header {
- position: relative;
- width: 100%;
- padding: $timepicker-header-padding;
- font-size: $timepicker-header-font-size;
- color: $timepicker-primary-contrast-color;
- text-align: center;
- background: $timepicker-primary-color;
-}
-
-.hours, .minutes {
- display: inline-block;
- cursor: pointer;
- opacity: .6;
-}
-
-.separator {
- margin: 0 $timepicker-header-padding / 2;
- opacity: .6;
-}
-
-.ampm {
- position: absolute;
- top: 50%;
- right: 2 * $unit;
- width: $timepicker-ampm-width;
- height: $timepicker-ampm-height * 2;
- margin-top: - $timepicker-ampm-height;
- font-size: $timepicker-ampm-font-size;
- line-height: $timepicker-ampm-height;
- text-align: center;
-}
-
-.am, .pm {
- display: block;
- cursor: pointer;
- opacity: .6;
-}
-
-.dialog {
- width: $timepicker-dialog-width;
- > [role="body"] {
- padding: 0;
- overflow-y: visible;
- }
- > [role="navigation"] > .button {
- color: $timepicker-primary-color;
- &:hover {
- background: $timepicker-primary-hover-color;
- }
- &:focus:not(:active) {
- background: $timepicker-primary-hover-color;
- }
- }
- &.hoursDisplay .hours, &.minutesDisplay .minutes, &.amFormat .am,
- &.pmFormat .pm {
- opacity: 1;
- }
-}
-
-.clock {
- padding: $clock-padding;
-}
-
-.placeholder {
- position: relative;
- z-index: $z-index-high;
-}
-
-.clockWrapper {
- position: absolute;
- width: 100%;
- background-color: $color-divider;
- border-radius: 50%;
-}
-
-.face {
- position: absolute;
- top: 50%;
- left: 50%;
- z-index: $z-index-high;
- cursor: pointer;
- border-radius: 50%;
- transform: translateX(-50%) translateY(-50%);
-}
-
-.number {
- position: relative;
- width: $clock-number-size;
- height: $clock-number-size;
- margin-top: - $clock-number-size / 2;
- margin-left: - $clock-number-size / 2;
- text-align: center;
- pointer-events: none;
- user-select: none;
- &.active {
- color: $clock-primary-contrast-color;
- }
-}
-
-.hand {
- position: absolute;
- bottom: 50%;
- left: 50%;
- display: block;
- width: $clock-hand-width;
- margin-left: - $clock-hand-width / 2;
- background-color: $clock-primary-color;
- transform-origin: 50% 100%;
- &:before {
- position: absolute;
- bottom: 0;
- left: 50%;
- width: $clock-hand-dot-size;
- height: $clock-hand-dot-size;
- margin-bottom: - $clock-hand-dot-size / 2;
- margin-left: - $clock-hand-dot-size / 2;
- content: "";
- background-color: $clock-primary-color;
- border-radius: 50%;
- }
- &.small > .knob {
- background-color: $clock-primary-hover-color;
- &:after {
- position: absolute;
- top: 50%;
- left: 50%;
- width: $clock-knob-small-size;
- height: $clock-knob-small-size;
- margin-top: - $clock-knob-small-size / 2;
- margin-left: - $clock-knob-small-size / 2;
- content: "";
- background: $clock-primary-color;
- border-radius: 50%;
- }
- &:before {
- position: absolute;
- bottom: 0;
- left: 50%;
- width: $clock-hand-width;
- height: $clock-knob-size - $clock-knob-small-size;
- margin-left: - $clock-hand-width / 2;
- content: "";
- background: $clock-primary-color;
- }
- }
-}
-
-.knob {
- position: absolute;
- top: - $clock-knob-size;
- left: 50%;
- width: $clock-knob-size;
- height: $clock-knob-size;
- margin-left: - $clock-knob-size / 2;
- cursor: pointer;
- background-color: $clock-primary-color;
- border-radius: 50%;
-}
diff --git a/components/tooltip/Tooltip.js b/components/tooltip/Tooltip.js
index 34ee5419..d0310ac7 100644
--- a/components/tooltip/Tooltip.js
+++ b/components/tooltip/Tooltip.js
@@ -2,9 +2,9 @@ import React, { Component, PropTypes } from 'react';
import Portal from '../hoc/Portal';
import classnames from 'classnames';
import { themr } from 'react-css-themr';
+import { getViewport } from '../utils/utils';
import { TOOLTIP } from '../identifiers.js';
import events from '../utils/events';
-import utils from '../utils/utils';
const POSITION = {
BOTTOM: 'bottom',
@@ -75,6 +75,7 @@ const tooltipFactory = (options = {}) => {
if (this.refs.tooltip) {
events.removeEventListenerOnTransitionEnded(this.refs.tooltip, this.onTransformEnd);
}
+ if (this.timeout) clearTimeout(this.timeout);
}
activate ({ top, left, position }) {
@@ -99,12 +100,12 @@ const tooltipFactory = (options = {}) => {
const { tooltipPosition } = this.props;
if (tooltipPosition === POSITION.HORIZONTAL) {
const origin = element.getBoundingClientRect();
- const { width: ww } = utils.getViewport();
+ const { width: ww } = getViewport();
const toRight = origin.left < ((ww / 2) - origin.width / 2);
return toRight ? POSITION.RIGHT : POSITION.LEFT;
} else if (tooltipPosition === POSITION.VERTICAL) {
const origin = element.getBoundingClientRect();
- const { height: wh } = utils.getViewport();
+ const { height: wh } = getViewport();
const toBottom = origin.top < ((wh / 2) - origin.height / 2);
return toBottom ? POSITION.BOTTOM : POSITION.TOP;
} else {
diff --git a/components/tooltip/_config.scss b/components/tooltip/_config.scss
deleted file mode 100644
index 04241051..00000000
--- a/components/tooltip/_config.scss
+++ /dev/null
@@ -1,8 +0,0 @@
-$tooltip-background: rgba(97,97,97,.9) !default;
-$tooltip-margin: 0.5 * $unit !default;
-$tooltip-border-radius: .2 * $unit !default;
-$tooltip-color: #fff !default;
-$tooltip-font-size: $unit !default;
-$tooltip-max-width: 17 * $unit !default;
-$tooltip-padding: .8 * $unit !default;
-$tooltip-animation-duration: 200ms !default;
diff --git a/components/tooltip/config.css b/components/tooltip/config.css
new file mode 100644
index 00000000..31acfbf6
--- /dev/null
+++ b/components/tooltip/config.css
@@ -0,0 +1,10 @@
+:root {
+ --tooltip-background: color(rgb(97, 97, 97) a(90%));
+ --tooltip-margin: calc(0.5 * var(--unit));
+ --tooltip-border-radius: calc(0.2 * var(--unit));
+ --tooltip-color: var(--color-white);
+ --tooltip-font-size: var(--unit);
+ --tooltip-max-width: calc(17 * var(--unit));
+ --tooltip-padding: calc(0.8 * var(--unit));
+ --tooltip-animation-duration: 200ms;
+}
diff --git a/components/tooltip/index.js b/components/tooltip/index.js
index 9612facd..054beee0 100644
--- a/components/tooltip/index.js
+++ b/components/tooltip/index.js
@@ -1,5 +1,5 @@
import tooltipFactory from './Tooltip.js';
-import theme from './theme.scss';
+import theme from './theme.css';
const themedTooltipFactory = (options) => tooltipFactory({ ...options, theme });
export default tooltipFactory({ theme });
diff --git a/components/tooltip/theme.scss b/components/tooltip/theme.css
similarity index 56%
rename from components/tooltip/theme.scss
rename to components/tooltip/theme.css
index 3daa20a8..bc9a2af8 100644
--- a/components/tooltip/theme.scss
+++ b/components/tooltip/theme.css
@@ -1,24 +1,24 @@
-@import "../colors";
-@import "../globals";
-@import "../mixins";
-@import "./config";
+@import '../colors.css';
+@import '../variables.css';
+@import './config.css';
.tooltip {
- position: absolute;
- z-index: $z-index-higher;
+ composes: reset from '../helpers.css';
display: block;
- max-width: $tooltip-max-width;
- padding: $tooltip-margin;
- font-family: Roboto, sans-serif;
- font-size: $tooltip-font-size;
- font-weight: $font-weight-bold;
- line-height: $font-size-small;
+ font-family: var(--preferred-font);
+ font-size: var(--tooltip-font-size);
+ font-weight: var(--font-weight-bold);
+ line-height: var(--font-size-small);
+ max-width: var(--tooltip-max-width);
+ padding: var(--tooltip-margin);
+ pointer-events: none;
+ position: absolute;
text-align: center;
text-transform: none;
- pointer-events: none;
- transition: $animation-curve-default $tooltip-animation-duration transform;
transform: scale(0) translateX(-50%);
transform-origin: top left;
+ transition: var(--animation-curve-default) var(--tooltip-animation-duration) transform;
+ z-index: var(--z-index-higher);
&.tooltipActive {
transform: scale(1) translateX(-50%);
@@ -26,6 +26,7 @@
&.tooltipTop {
transform: scale(0) translateX(-50%) translateY(-100%);
+
&.tooltipActive {
transform: scale(1) translateX(-50%) translateY(-100%);
}
@@ -33,6 +34,7 @@
&.tooltipLeft {
transform: scale(0) translateX(-100%) translateY(-50%);
+
&.tooltipActive {
transform: scale(1) translateX(-100%) translateY(-50%);
}
@@ -40,6 +42,7 @@
&.tooltipRight {
transform: scale(0) translateX(0) translateY(-50%);
+
&.tooltipActive {
transform: scale(1) translateX(0) translateY(-50%);
}
@@ -47,9 +50,9 @@
}
.tooltipInner {
+ background: var(--tooltip-background);
+ border-radius: var(--tooltip-border-radius);
+ color: var(--tooltip-color);
display: block;
- padding: $tooltip-padding;
- color: $tooltip-color;
- background: $tooltip-background;
- border-radius: $tooltip-border-radius;
+ padding: var(--tooltip-padding);
}
diff --git a/components/utils/breakpoints.js b/components/utils/breakpoints.js
new file mode 100644
index 00000000..dd55604d
--- /dev/null
+++ b/components/utils/breakpoints.js
@@ -0,0 +1,12 @@
+export default {
+ xxs: 480,
+ xs: 600,
+ smTablet: 720,
+ sm: 840,
+ md: 960,
+ lgTablet: 1024,
+ lg: 1280,
+ xl: 1440,
+ xxl: 1600,
+ xxxl: 1920
+};
diff --git a/components/utils/filter-react-children.js b/components/utils/filter-react-children.js
new file mode 100644
index 00000000..8f4676c9
--- /dev/null
+++ b/components/utils/filter-react-children.js
@@ -0,0 +1,22 @@
+import React from 'react';
+
+/**
+ * Looks through a collection of React children elements, filtering them
+ * according to the predicate passed.
+ *
+ * @param {Array/Object} children - colleciton of >=1 react elements
+ * @param {function} predicate - function returning true when provided with an entry as argument
+ */
+export default function (children, predicate) {
+ if (children) {
+ const result = [];
+ React.Children.forEach(children, (entry, idx) => {
+ if (predicate && predicate.call(this, entry, idx)) {
+ result.push(entry);
+ }
+ });
+ return result;
+ }
+
+ return undefined;
+}
diff --git a/components/utils/index.js b/components/utils/index.js
index 5e804193..039e92ee 100644
--- a/components/utils/index.js
+++ b/components/utils/index.js
@@ -1,10 +1,9 @@
import events from './events.js';
import prefixer from './prefixer.js';
import time from './time.js';
-import utils from './utils.js';
-export default {events, prefixer, time, utils};
+export default {events, prefixer, time};
export {events};
export {prefixer};
export {time};
-export {utils};
+export * from './utils';
diff --git a/components/utils/is-browser.js b/components/utils/is-browser.js
new file mode 100644
index 00000000..a5d17b60
--- /dev/null
+++ b/components/utils/is-browser.js
@@ -0,0 +1,3 @@
+export default function isBrowser () {
+ return typeof window !== 'undefined' && window.document;
+}
diff --git a/components/utils/is-component-of-type.js b/components/utils/is-component-of-type.js
new file mode 100644
index 00000000..bac11601
--- /dev/null
+++ b/components/utils/is-component-of-type.js
@@ -0,0 +1,9 @@
+/**
+ * Returns true if the provided element is a component of the provided type.
+ *
+ * @param classType {ReactElement class} - the class of a React Element
+ * @param reactElement {ReactElement} - any React Element (not a real DOM node)
+ */
+export default function isComponentOfType (classType, reactElement) {
+ return reactElement && reactElement.type === classType;
+}
diff --git a/components/utils/utils.js b/components/utils/utils.js
index bc024a07..8811f1d6 100644
--- a/components/utils/utils.js
+++ b/components/utils/utils.js
@@ -1,68 +1,76 @@
-export default {
- angleFromPositions (cx, cy, ex, ey) {
- const theta = Math.atan2(ey - cy, ex - cx) + Math.PI / 2;
- return theta * 180 / Math.PI;
- },
+import assoc from 'ramda/src/assoc';
+import compose from 'ramda/src/compose';
+import keys from 'ramda/src/keys';
+import reduce from 'ramda/src/reduce';
+import pickBy from 'ramda/src/pickBy';
- angle360FromPositions (cx, cy, ex, ey) {
- const angle = this.angleFromPositions(cx, cy, ex, ey);
- return angle < 0 ? 360 + angle : angle;
- },
-
- range (start = 0, stop = null, step = 1) {
- let [_start, _stop] = [0, start];
- if (stop !== null) {
- [_start, _stop] = [start, stop];
- }
- const length = Math.max(Math.ceil((_stop - _start) / step), 0);
- const range = Array(length);
-
- for (let idx = 0; idx < length; idx++, _start += step) {
- range[idx] = _start;
- }
-
- return range;
- },
-
- round (number, decimals) {
- if (!isNaN(parseFloat(number)) && isFinite(number)) {
- const decimalPower = Math.pow(10, decimals);
- return Math.round(parseFloat(number) * decimalPower) / decimalPower;
- }
- return NaN;
- },
-
- getViewport () {
- return {
- height: window.innerHeight || document.documentElement.offsetHeight,
- width: window.innerWidth || document.documentElement.offsetWidth
- };
- },
-
- cloneObject (object) {
- return JSON.parse(JSON.stringify(object));
- },
-
- inputTypeForPrototype (prototype) {
- if (prototype === Date) return 'date';
- if (prototype === Number) return 'number';
- if (prototype === Boolean) return 'checkbox';
- return 'text';
- },
-
- prepareValueForInput (value, type) {
- if (type === 'date') return new Date(value).toISOString().slice(0, 10);
- if (type === 'checkbox') {
- return value ? 'on' : '';
- }
- return value;
- },
-
- removeObjectKey (key, object) {
- const newObject = {};
- Object.keys(object)
- .filter(k => k !== key)
- .forEach(k => { newObject[k] = object[k]; });
- return newObject;
- }
+export const angleFromPositions = (cx, cy, ex, ey) => {
+ const theta = Math.atan2(ey - cy, ex - cx) + Math.PI / 2;
+ return theta * 180 / Math.PI;
};
+
+export const angle360FromPositions = (cx, cy, ex, ey) => {
+ const angle = angleFromPositions(cx, cy, ex, ey);
+ return angle < 0 ? 360 + angle : angle;
+};
+
+export const range = (start = 0, stop = null, step = 1) => {
+ let [_start, _stop] = [0, start];
+ if (stop !== null) {
+ [_start, _stop] = [start, stop];
+ }
+ const length = Math.max(Math.ceil((_stop - _start) / step), 0);
+ const _range = Array(length);
+
+ for (let idx = 0; idx < length; idx++, _start += step) {
+ _range[idx] = _start;
+ }
+
+ return _range;
+};
+
+export const round = (number, decimals) => {
+ if (!isNaN(parseFloat(number)) && isFinite(number)) {
+ const decimalPower = Math.pow(10, decimals);
+ return Math.round(parseFloat(number) * decimalPower) / decimalPower;
+ }
+ return NaN;
+};
+
+export const getViewport = () => ({
+ height: window.innerHeight || document.documentElement.offsetHeight,
+ width: window.innerWidth || document.documentElement.offsetWidth
+});
+
+export const cloneObject = object =>
+ JSON.parse(JSON.stringify(object));
+
+export const inputTypeForPrototype = prototype => {
+ if (prototype === Date) return 'date';
+ if (prototype === Number) return 'number';
+ if (prototype === Boolean) return 'checkbox';
+ return 'text';
+};
+
+export const prepareValueForInput = (value, type) => {
+ if (type === 'date') return new Date(value).toISOString().slice(0, 10);
+ if (type === 'checkbox') {
+ return value ? 'on' : '';
+ }
+ return value;
+};
+
+export const transformKeys = fn => obj => {
+ const addTransformedKey = (result, key) => assoc(fn(key), obj[key], result);
+ return reduce(addTransformedKey, {}, keys(obj));
+};
+
+export const removeNamespace = namespace => key => {
+ const capitalized = key.substr(namespace.length);
+ return capitalized.slice(0, 1).toLowerCase() + capitalized.slice(1);
+};
+
+export const getAnimationModule = (animation, theme) => compose(
+ transformKeys(removeNamespace(animation)),
+ pickBy((v, k) => k.startsWith(animation))
+)(theme);
diff --git a/components/variables.css b/components/variables.css
new file mode 100644
index 00000000..3c1a0a08
--- /dev/null
+++ b/components/variables.css
@@ -0,0 +1,80 @@
+:root {
+ --color-divider: var(--palette-grey-200);
+ --color-background: var(--color-white);
+ --color-text: var(--palette-grey-900);
+ --color-text-secondary: var(--palette-grey-600);
+
+ --color-primary: var(--palette-indigo-500);
+ --color-primary-dark: var(--palette-indigo-700);
+ --color-accent: var(--palette-pink-a200);
+ --color-accent-dark: var(--palette-pink-700);
+ --color-primary-contrast: var(--color-dark-contrast);
+ --color-accent-contrast: var(--color-dark-contrast);
+
+ --unit: 10px;
+
+ --preferred-font: 'Roboto', 'Helvetica', 'Arial', sans-serif;
+ --font-size: calc(1.6 * var(--unit));
+ --font-size-tiny: calc(1.2 * var(--unit));
+ --font-size-small: calc(1.4 * var(--unit));
+ --font-size-normal: var(--font-size);
+ --font-size-big: calc(1.8 * var(--unit));
+ --font-weight-thin: 300;
+ --font-weight-normal: 400;
+ --font-weight-semi-bold: 500;
+ --font-weight-bold: 700;
+
+ --shadow-2p:
+ 0 2px 2px 0 rgba(0, 0, 0, 0.14),
+ 0 3px 1px -2px rgba(0, 0, 0, 0.2),
+ 0 1px 5px 0 rgba(0, 0, 0, 0.12);
+
+ --shadow-3p:
+ 0 3px 4px 0 rgba(0, 0, 0, 0.14),
+ 0 3px 3px -2px rgba(0, 0, 0, 0.2),
+ 0 1px 8px 0 rgba(0, 0, 0, 0.12);
+
+ --shadow-4p:
+ 0 4px 5px 0 rgba(0, 0, 0, 0.14),
+ 0 1px 10px 0 rgba(0, 0, 0, 0.12),
+ 0 2px 4px -1px rgba(0, 0, 0, 0.2);
+
+ --shadow-6p:
+ 0 6px 10px 0 rgba(0, 0, 0, 0.14),
+ 0 1px 18px 0 rgba(0, 0, 0, 0.12),
+ 0 3px 5px -1px rgba(0, 0, 0, 0.2);
+
+ --shadow-8p:
+ 0 8px 10px 1px rgba(0, 0, 0, 0.14),
+ 0 3px 14px 2px rgba(0, 0, 0, 0.12),
+ 0 5px 5px -3px rgba(0, 0, 0, 0.2);
+
+ --shadow-16p:
+ 0 16px 24px 2px rgba(0, 0, 0, 0.14),
+ 0 6px 30px 5px rgba(0, 0, 0, 0.12),
+ 0 8px 10px -5px rgba(0, 0, 0, 0.2);
+
+ --shadow-key-umbra-opacity: 0.2;
+ --shadow-key-penumbra-opacity: 0.14;
+ --shadow-ambient-shadow-opacity: 0.12;
+
+ --zdepth-shadow-1: 0 1px 6px rgba(0, 0, 0, 0.12), 0 1px 4px rgba(0, 0, 0, 0.24);
+ --zdepth-shadow-2: 0 3px 10px rgba(0, 0, 0, 0.16), 0 3px 10px rgba(0, 0, 0, 0.23);
+ --zdepth-shadow-3: 0 10px 30px rgba(0, 0, 0, 0.19), 0 6px 10px rgba(0, 0, 0, 0.23);
+ --zdepth-shadow-4: 0 14px 45px rgba(0, 0, 0, 0.25), 0 10px 18px rgba(0, 0, 0, 0.22);
+ --zdepth-shadow-5: 0 19px 60px rgba(0, 0, 0, 0.3), 0 15px 20px rgba(0, 0, 0, 0.22);
+
+ --animation-duration: 0.35s;
+ --animation-delay: calc(var(--animation-duration) / 5);
+ --animation-curve-fast-out-slow-in: cubic-bezier(0.4, 0, 0.2, 1);
+ --animation-curve-linear-out-slow-in: cubic-bezier(0, 0, 0.2, 1);
+ --animation-curve-fast-out-linear-in: cubic-bezier(0.4, 0, 1, 1);
+ --animation-curve-default: var(--animation-curve-fast-out-slow-in);
+
+ --z-index-highest: 300;
+ --z-index-higher: 200;
+ --z-index-high: 100;
+ --z-index-normal: 1;
+ --z-index-low: -100;
+ --z-index-lower: -200;
+}
diff --git a/docs/app/components/_globals.scss b/docs/app/components/_globals.scss
deleted file mode 100644
index 7e32be88..00000000
--- a/docs/app/components/_globals.scss
+++ /dev/null
@@ -1,12 +0,0 @@
-@import "~react-toolbox/colors";
-@import "~react-toolbox/globals";
-@import "~react-toolbox/mixins";
-@import "../theme/theme";
-
-$unit: 1rem;
-$color-primary-dark: $color-primary-dark;
-$color-primary-light: $color-primary-light;
-$color-primary-contrast: $color-primary-contrast;
-$color-accent: $color-accent;
-$color-divider: $color-divider;
-$color-content: #fafafa;
diff --git a/docs/app/components/_mixins.scss b/docs/app/components/_mixins.scss
deleted file mode 100644
index e01c4f67..00000000
--- a/docs/app/components/_mixins.scss
+++ /dev/null
@@ -1,5 +0,0 @@
-@mixin code-typography {
- font-family: 'source-code-pro', Menlo, Consolas, Monaco, 'Andale Mono', 'Courier New', monospace;
- font-size: 13px;
- line-height: 1.4;
-}
diff --git a/docs/app/components/appbar/_config.scss b/docs/app/components/appbar/_config.scss
deleted file mode 100644
index 83838dfb..00000000
--- a/docs/app/components/appbar/_config.scss
+++ /dev/null
@@ -1,4 +0,0 @@
-$appbar-height: 6.4 * $unit;
-$appbar-logo-size: 3.6 * $unit;
-$appbar-shadow: 0 1px rgba(255,255,255,.65);
-$appbar-navigation-offset: 6.5 * $unit;
diff --git a/docs/app/components/appbar/index.js b/docs/app/components/appbar/index.js
index e416be45..62c6a864 100644
--- a/docs/app/components/appbar/index.js
+++ b/docs/app/components/appbar/index.js
@@ -3,7 +3,7 @@ import { AppBar } from 'react-toolbox';
import { Link } from 'react-router';
import Logo from '../logo';
import Navigation from '../navigation';
-import style from './style';
+import style from './style.css';
const MainAppBar = (props) => {
let className = style.appbar;
diff --git a/docs/app/components/appbar/style.css b/docs/app/components/appbar/style.css
new file mode 100644
index 00000000..14636cb4
--- /dev/null
+++ b/docs/app/components/appbar/style.css
@@ -0,0 +1,63 @@
+@import 'colors.css';
+@import 'variables.css';
+
+:root {
+ --appbar-height: calc(6.4 * var(--unit));
+ --appbar-logo-size: calc(3.6 * var(--unit));
+ --appbar-shadow: 0 1px rgba(255, 255, 255, 0.65);
+ --appbar-navigation-offset: calc(6.5 * var(--unit));
+}
+
+.appbar {
+ align-items: flex-start;
+ box-shadow: var(--appbar-shadow);
+ display: flex;
+ flex-direction: row;
+ justify-content: flex-start;
+ min-height: var(--appbar-height);
+ z-index: var(--z-index-higher);
+}
+
+.logo {
+ display: block;
+ fill: var(--color-primary-contrast);
+ height: var(--appbar-logo-size);
+ margin-top: calc((var(--appbar-height) - var(--appbar-logo-size)) / 2);
+ width: var(--appbar-logo-size);
+}
+
+.navigation {
+ flex-grow: 1;
+ text-align: right;
+
+ & > ul {
+ list-style: none;
+
+ & > li {
+ display: inline-block;
+
+ & > a {
+ color: var(--color-primary-contrast);
+ display: inline-block;
+ font-size: 1.4rem;
+ font-weight: 500;
+ letter-spacing: 0;
+ line-height: var(--appbar-height);
+ margin-right: var(--unit);
+ padding: 0 calc(1.5 * var(--unit));
+ position: relative;
+
+ &.active::after {
+ background-color: var(--color-accent);
+ bottom: 0;
+ content: '';
+ display: block;
+ height: calc(0.3 * var(--unit));
+ left: 0;
+ position: absolute;
+ width: 100%;
+ }
+ }
+ }
+ }
+}
diff --git a/docs/app/components/appbar/style.scss b/docs/app/components/appbar/style.scss
deleted file mode 100644
index 4cbcc944..00000000
--- a/docs/app/components/appbar/style.scss
+++ /dev/null
@@ -1,48 +0,0 @@
-@import "../globals";
-@import "./config";
-
-.appbar {
- z-index: $z-index-higher;
- display: flex;
- min-height: $appbar-height;
- flex-direction: row;
- align-items: flex-start;
- justify-content: flex-start;
- box-shadow: $appbar-shadow;
-}
-
-.logo {
- width: $appbar-logo-size;
- height: $appbar-logo-size;
- fill: $color-primary-contrast;
-}
-
-.navigation {
- flex-grow: 1;
- text-align: right;
- > ul {
- list-style: none;
- > li {
- display: inline-block;
- > a {
- @include typo-menu;
- position: relative;
- display: inline-block;
- padding: 0 1.5 * $unit;
- margin-right: $unit;
- line-height: $appbar-height;
- color: $color-primary-contrast;
- &.active:after {
- position: absolute;
- bottom: 0;
- left: 0;
- display: block;
- width: 100%;
- height: .3 * $unit;
- content: '';
- background-color: $color-accent;
- }
- }
- }
- }
-}
diff --git a/docs/app/components/editor/_custom.scss b/docs/app/components/editor/_custom.scss
deleted file mode 100644
index c3db3c2b..00000000
--- a/docs/app/components/editor/_custom.scss
+++ /dev/null
@@ -1,19 +0,0 @@
-$editor-height: 28 * $unit;
-$editor-padding: $unit;
-
-div.CodeMirror {
- height: $editor-height;
- flex-grow: 1;
-}
-
-.CodeMirror-lines {
- padding: $editor-padding 0;
-}
-
-pre.CodeMirror-line {
- padding: 0 $editor-padding;
-}
-
-div.CodeMirror pre, div.CodeMirror-linenumber, code {
- @include code-typography;
-}
diff --git a/docs/app/components/editor/_one-dark.scss b/docs/app/components/editor/_one-dark.scss
deleted file mode 100644
index 0a86b389..00000000
--- a/docs/app/components/editor/_one-dark.scss
+++ /dev/null
@@ -1,34 +0,0 @@
-// /* General */
-
-.cm-s-one-dark {
- &.CodeMirror { background: #282C34; color: #ABB2BF;}
- div.CodeMirror-selected { background: #3E4451; }
- .CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: rgba(73, 72, 62, .99); }
- .CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: rgba(73, 72, 62, .99); }
- .CodeMirror-gutters { background: #282C34; border-right: 1px solid #282C34; }
- .CodeMirror-guttermarker { color: white; }
- .CodeMirror-guttermarker-subtle { color: #d0d0d0; }
- .CodeMirror-linenumber { color: #4B5363; }
- .CodeMirror-cursor { border-left: 1px solid #528BFF; }
-
- span.cm-comment { color: #667689; }
- span.cm-atom { color: #64B6C3; }
- span.cm-number { color: #D19A66; }
-
- span.cm-property, span.cm-attribute { color: #ABB2BF; }
- span.cm-keyword { color: #D86C74; }
- span.cm-string { color: #98C379; }
-
- span.cm-variable { color: #ABB2BF; }
- span.cm-variable-2 { color: #C678DD; }
- span.cm-variable-3 { color: #64B6C3; }
- span.cm-def { color: #6CAFF2; }
- span.cm-bracket { color: #ABB2BF; }
- span.cm-tag { color: #D86C74; }
- span.cm-header { color: #ABB2BF; }
- span.cm-link { color: #98C379; }
- span.cm-error { background: #f92672; color: red; }
-
- .CodeMirror-activeline-background { background: #2C323B; }
- .CodeMirror-matchingbracket { text-decoration: underline; color: #ABB2BF !important; }
-}
diff --git a/docs/app/components/editor/index.js b/docs/app/components/editor/index.js
index cf7c5bda..2b6536dd 100644
--- a/docs/app/components/editor/index.js
+++ b/docs/app/components/editor/index.js
@@ -1,7 +1,9 @@
import React from 'react';
-import style from './style';
import CodeMirror from 'codemirror';
-import 'codemirror/mode/javascript/javascript';
+import style from './style.css';
+import 'codemirror/lib/codemirror.css';
+import 'codemirror/mode/javascript/javascript.js';
+import './one-dark.css';
class Editor extends React.Component {
static propTypes = {
diff --git a/docs/app/components/editor/one-dark.css b/docs/app/components/editor/one-dark.css
new file mode 100644
index 00000000..b2c9802a
--- /dev/null
+++ b/docs/app/components/editor/one-dark.css
@@ -0,0 +1,114 @@
+:global .cm-s-one-dark {
+ &.CodeMirror {
+ background: #282c34;
+ color: #abb2bf;
+ }
+
+ & div.CodeMirror-selected {
+ background: #3e4451;
+ }
+
+ & .CodeMirror-line::selection,
+ & .CodeMirror-line > span::selection,
+ & .CodeMirror-line > span > span::selection {
+ background: rgba(73, 72, 62, 0.99);
+ }
+
+ & .CodeMirror-line::-moz-selection,
+ & .CodeMirror-line > span::-moz-selection,
+ & .CodeMirror-line > span > span::-moz-selection {
+ background: rgba(73, 72, 62, 0.99);
+ }
+
+ & .CodeMirror-gutters {
+ background: #282c34;
+ border-right: 1px solid #282c34;
+ }
+
+ & .CodeMirror-guttermarker {
+ color: white;
+ }
+
+ & .CodeMirror-guttermarker-subtle {
+ color: #d0d0d0;
+ }
+
+ & .CodeMirror-linenumber {
+ color: #4b5363;
+ }
+
+ & .CodeMirror-cursor {
+ border-left: 1px solid #528bff;
+ }
+
+ & span.cm-comment {
+ color: #667689;
+ }
+
+ & span.cm-atom {
+ color: #64b6c3;
+ }
+
+ & span.cm-number {
+ color: #d19a66;
+ }
+
+ & span.cm-property,
+ & span.cm-attribute {
+ color: #abb2bf;
+ }
+
+ & span.cm-keyword {
+ color: #d86c74;
+ }
+
+ & span.cm-string {
+ color: #98c379;
+ }
+
+ & span.cm-variable {
+ color: #abb2bf;
+ }
+
+ & span.cm-variable-2 {
+ color: #c678dd;
+ }
+
+ & span.cm-variable-3 {
+ color: #64b6c3;
+ }
+
+ & span.cm-def {
+ color: #6caff2;
+ }
+
+ & span.cm-bracket {
+ color: #abb2bf;
+ }
+
+ & span.cm-tag {
+ color: #d86c74;
+ }
+
+ & span.cm-header {
+ color: #abb2bf;
+ }
+
+ & span.cm-link {
+ color: #98c379;
+ }
+
+ & span.cm-error {
+ background: #f92672;
+ color: red;
+ }
+
+ & .CodeMirror-activeline-background {
+ background: #2c323b;
+ }
+
+ & .CodeMirror-matchingbracket {
+ color: #abb2bf !important;
+ text-decoration: underline;
+ }
+}
diff --git a/docs/app/components/editor/style.css b/docs/app/components/editor/style.css
new file mode 100644
index 00000000..eef4dfe1
--- /dev/null
+++ b/docs/app/components/editor/style.css
@@ -0,0 +1,33 @@
+@import 'variables.css';
+
+:root {
+ --editor-height: 28 * var(--unit);
+ --editor-padding: var(--unit);
+}
+
+:global {
+ & div.CodeMirror {
+ flex-grow: 1;
+ height: var(--editor-height);
+ }
+
+ & .CodeMirror-lines {
+ padding: var(--editor-padding) 0;
+ }
+
+ & pre.CodeMirror-line {
+ padding: 0 var(--editor-padding);
+ }
+
+ & div.CodeMirror pre,
+ & div.CodeMirror-linenumber,
+ & code {
+ font-family: source-code-pro, Menlo, Consolas, Monaco, 'Andale Mono', 'Courier New', monospace;
+ font-size: 13px;
+ line-height: 1.4;
+ }
+}
+
+.editor {
+ position: relative;
+}
diff --git a/docs/app/components/editor/style.scss b/docs/app/components/editor/style.scss
deleted file mode 100644
index f2c34bfa..00000000
--- a/docs/app/components/editor/style.scss
+++ /dev/null
@@ -1,12 +0,0 @@
-@import "../globals";
-@import "../mixins";
-
-.editor {
- position: relative;
-
- :global {
- @import "~codemirror/lib/codemirror";
- @import "one-dark";
- @import "custom";
- }
-}
diff --git a/docs/app/components/layout/home/_config.scss b/docs/app/components/layout/home/_config.scss
deleted file mode 100644
index 928862b9..00000000
--- a/docs/app/components/layout/home/_config.scss
+++ /dev/null
@@ -1,10 +0,0 @@
-$hero-gradient-dark: $color-primary-dark;
-$hero-gradient-light: $color-primary-light;
-$hero-text-color: $color-primary-contrast;
-$hero-max-width: 62 * $unit;
-$hero-text-secondary-opacity: .75;
-$hero-item-spacing: 5 * $unit;
-$hero-logo-size: 12 * $unit;
-$hero-logo-opacity: .85;
-
-$github-buttons-height: 4 * $unit;
diff --git a/docs/app/components/layout/home/index.js b/docs/app/components/layout/home/index.js
index 7151e329..6e256316 100644
--- a/docs/app/components/layout/home/index.js
+++ b/docs/app/components/layout/home/index.js
@@ -4,7 +4,7 @@ import Button from 'react-toolbox/button';
import {Card, CardTitle, CardMedia, CardText, CardActions} from 'react-toolbox/card';
import Logo from '../../logo';
import Navigation from '../../navigation';
-import style from './style';
+import style from './style.css';
const GithubIcon = () => (
@@ -64,7 +64,7 @@ const Home = () => (
Software gardener • Film, music & comic lover • Frontend Engineer at Audiense • Any biographer in the room?
Github
- Twitter
+ Twitter
@@ -74,7 +74,7 @@ const Home = () => (
Creative Doer · A complicated #human who builds stuff · #author · #opensource lover · #traveller · with a dark past being CEO & CTO
Github
- Twitter
+ Twitter
diff --git a/docs/app/components/layout/home/style.css b/docs/app/components/layout/home/style.css
new file mode 100644
index 00000000..60a292f5
--- /dev/null
+++ b/docs/app/components/layout/home/style.css
@@ -0,0 +1,220 @@
+@import 'colors.css';
+@import 'variables.css';
+
+:root {
+ --hero-gradient-dark: var(--color-primary-dark);
+ --hero-gradient-light: var(--color-primary-light);
+ --hero-text-color: var(--color-primary-contrast);
+ --hero-max-width: calc(62 * var(--unit));
+ --hero-text-secondary-opacity: 0.75;
+ --hero-item-spacing: calc(5 * var(--unit));
+ --hero-logo-size: calc(12 * var(--unit));
+ --hero-logo-opacity: 0.85;
+ --github-buttons-height: calc(4 * var(--unit));
+ --twitter-color: #55acee;
+ --content-offset: calc(4.8 * var(--unit));
+ --content-width: 740px;
+ --color-content: #fafafa;
+}
+
+.header {
+ background: linear-gradient(45deg, var(--hero-gradient-dark) 0%, var(--hero-gradient-light) 100%);
+ background-position: top right;
+ background-size: 120%;
+ color: var(--hero-text-color);
+ padding: 0 calc((100% - var(--hero-max-width)) / 2);
+ text-align: center;
+
+ & .logo {
+ fill: var(--hero-text-color);
+ height: var(--hero-logo-size);
+ margin-top: calc(var(--hero-item-spacing) + var(--github-buttons-height));
+ opacity: var(--hero-logo-opacity);
+ width: var(--hero-logo-size);
+ }
+
+ & .title {
+ font-size: calc(5.6 * var(--unit));
+ font-weight: 400;
+ letter-spacing: -0.02em;
+ line-height: 1.35;
+ margin-top: var(--hero-item-spacing);
+ }
+
+ & .subtitle {
+ font-size: calc(2.4 * var(--unit));
+ font-weight: 400;
+ line-height: 1.2;
+ margin-top: var(--unit);
+ opacity: var(--hero-text-secondary-opacity);
+ }
+
+ & .github {
+ left: calc(2 * var(--unit));
+ position: fixed;
+ text-align: center;
+ top: calc(2 * var(--unit));
+ z-index: var(--z-index-higher);
+
+ & iframe {
+ display: inline-block;
+ height: calc(2 * var(--unit));
+ vertical-align: top;
+ width: calc(10 * var(--unit));
+ }
+ }
+
+ & .navigation > ul {
+ list-style: none;
+ margin-top: var(--hero-item-spacing);
+
+ & li {
+ display: inline-block;
+ position: relative;
+
+ &:not(:last-child) > a::after {
+ content: '·';
+ display: inline-block;
+ font-size: 50px;
+ line-height: 60px;
+ margin: 0 10px;
+ vertical-align: middle;
+ }
+
+ & > a {
+ color: var(--hero-text-color);
+ display: inline-block;
+ font-size: calc(2 * var(--unit));
+ font-weight: 400;
+ letter-spacing: 0.02em;
+ line-height: 60px;
+ opacity: var(--hero-text-secondary-opacity);
+ position: relative;
+ vertical-align: middle;
+
+ &:hover {
+ opacity: 1;
+ }
+ }
+ }
+ }
+}
+
+.twitterButton {
+ &.neutral.flat:not([disabled]) {
+ color: var(--twitter-color);
+ }
+}
+
+.content {
+ align-items: center;
+ background-color: var(--color-content);
+ display: flex;
+ flex-direction: column;
+ flex-wrap: wrap;
+ padding: var(--content-offset);
+
+ &:nth-child(3) {
+ background-color: color(var(--color-content) blackness(5%));
+ }
+
+ & > .authors {
+ align-items: flex-start;
+ display: flex;
+ justify-content: center;
+
+ & > * {
+ flex: 1 auto;
+ margin: 0 var(--unit);
+ max-width: calc(32 * var(--unit));
+ }
+ }
+
+ & > p {
+ font-size: calc(1.8 * var(--unit));
+ line-height: 1.5;
+ margin-bottom: var(--content-offset);
+ max-width: var(--content-width);
+ opacity: 0.6;
+ text-align: justify;
+ }
+
+ & > h2 {
+ color: var(--hero-gradient-dark);
+ font-size: calc(2 * var(--unit));
+ margin-bottom: var(--content-offset);
+ }
+
+ & > h3 {
+ color: var(--color-primary-dark);
+ font-size: calc(2.4 * var(--unit));
+ margin-bottom: calc(var(--content-offset) / 2);
+ }
+}
+
+.footer {
+ background-color: var(--color-text);
+ color: var(--color-content);
+ padding: calc(2 * var(--unit)) 0;
+ text-align: center;
+
+ & .love {
+ color: var(--color-accent);
+ font-size: var(--font-size-normal);
+ }
+
+ & small {
+ color: rgba(255, 255, 255, 0.5);
+ }
+}
+
+.donate {
+ border-radius: 3px;
+ color: #fff;
+ display: inline-block;
+ font-size: calc(1.1 * var(--unit));
+ overflow: hidden;
+ vertical-align: top;
+
+ & .legend {
+ background-color: #555;
+ display: inline-block;
+ line-height: calc(2 * var(--unit));
+ padding: 0 calc(0.5 * var(--unit));
+ }
+
+ & .paypal {
+ background-color: #007ec6;
+ display: inline-block;
+ line-height: calc(2 * var(--unit));
+ padding: 0 calc(0.5 * var(--unit));
+ }
+}
+
+@media all and (max-width: 768px) {
+ & .header {
+ & .github {
+ position: absolute;
+ }
+ }
+
+ & .content {
+ padding: calc(var(--content-offset) / 2);
+
+ & > .authors {
+ flex-direction: column;
+
+ & > * {
+ margin: var(--unit) 0;
+ }
+ }
+
+ & > p {
+ max-width: 100%;
+ }
+ }
+
+ & .second-content {
+ background-color: transparent;
+ }
+}
diff --git a/docs/app/components/layout/home/style.scss b/docs/app/components/layout/home/style.scss
deleted file mode 100644
index 7203229b..00000000
--- a/docs/app/components/layout/home/style.scss
+++ /dev/null
@@ -1,177 +0,0 @@
-@import "../../globals";
-@import "./config";
-
-$twitter-color: #55acee;
-$content-offset: 4.8 * $unit;
-$content-width: 740px;
-
-.header {
- padding: 0 calc((100% - #{$hero-max-width}) / 2);
- color: $hero-text-color;
- text-align: center;
- background: linear-gradient(45deg, $hero-gradient-dark 0%, $hero-gradient-light 100%);
- background-position: top right;
- background-size: 120%;
- .logo {
- width: $hero-logo-size;
- height: $hero-logo-size;
- margin-top: $hero-item-spacing + $github-buttons-height;
- opacity: $hero-logo-opacity;
- fill: $hero-text-color;
- }
- .title {
- @include typo-display-3;
- margin-top: $hero-item-spacing;
- }
- .subtitle {
- @include typo-headline;
- margin-top: 10px;
- font-weight: 400;
- line-height: 1.2;
- opacity: $hero-text-secondary-opacity;
- }
- .github {
- position: fixed;
- top: 2 * $unit;
- left: 2 * $unit;
- z-index: $z-index-higher;
- text-align: center;
- iframe {
- display: inline-block;
- width: 10 * $unit;
- height: 2 * $unit;
- vertical-align: top;
- }
- }
- .navigation > ul {
- margin-top: $hero-item-spacing;
- list-style: none;
- li {
- position: relative;
- display: inline-block;
- &:not(:last-child) > a:after {
- display: inline-block;
- margin: 0 10px;
- font-size: 50px;
- line-height: 60px;
- vertical-align: middle;
- content: "·";
- }
- > a {
- @include typo-title;
- position: relative;
- display: inline-block;
- font-weight: 400;
- line-height: 60px;
- color: $hero-text-color;
- vertical-align: middle;
- opacity: $hero-text-secondary-opacity;
- &:hover {
- opacity: 1;
- }
- }
- }
- }
-}
-
-.content {
- display: flex;
- flex-direction: column;
- flex-wrap: wrap;
- align-items: center;
- padding: $content-offset;
- background-color: $color-content;
- &:nth-child(3) {
- background-color: darken($color-content, 5%);
- }
- > .authors {
- display: flex;
- align-items: flex-start;
- justify-content: center;
- > * {
- max-width: 32 * $unit;
- flex: 1 auto;
- margin: 0 $unit;
- }
- .twitter {
- color: $twitter-color !important;
- }
- }
- > p {
- max-width: $content-width;
- margin-bottom: $content-offset;
- font-size: 1.8 * $unit;
- line-height: 1.5;
- text-align: justify;
- opacity: .6;
- }
- > h2 {
- margin-bottom: $content-offset;
- font-size: 2 * $unit;
- color: $hero-gradient-dark;
- }
- > h3 {
- margin-bottom: $content-offset / 2;
- font-size: 2.4 * $unit;
- color: $color-primary-dark;
- }
-}
-
-.footer {
- padding: 2 * $unit 0;
- color: $color-content;
- text-align: center;
- background-color: $color-text;
- .love {
- font-size: $font-size-normal;
- color: $color-accent;
- }
- small {
- color: rgba(255,255,255,.5);
- }
-}
-
-.donate {
- display: inline-block;
- overflow: hidden;
- font-size: 1.1 * $unit;
- color: #fff;
- vertical-align: top;
- border-radius: 3px;
- .legend {
- display: inline-block;
- padding: 0 .5 * $unit;
- line-height: 2 * $unit;
- background-color: #555;
- }
- .paypal {
- display: inline-block;
- padding: 0 .5 * $unit;
- line-height: 2 * $unit;
- background-color: #007ec6;
- }
-}
-
-@media all and (max-width: 768px) {
- .header {
- .github {
- position: absolute;
- }
- }
- .content {
- padding: $content-offset / 2;
- > .authors {
- flex-direction: column;
- > * {
- margin: $unit 0;
- }
- }
- > p {
- max-width: 100%;
- }
- }
-
- .second-content {
- background-color: transparent;
- }
-}
diff --git a/docs/app/components/layout/install/index.js b/docs/app/components/layout/install/index.js
index 0d3e6c5b..5e8b9553 100644
--- a/docs/app/components/layout/install/index.js
+++ b/docs/app/components/layout/install/index.js
@@ -2,7 +2,7 @@ import React from 'react';
import Appbar from '../../../components/appbar';
import Markdown from '../../../components/markdown';
import installMD from './install';
-import style from './style';
+import style from './style.css';
class Install extends React.Component {
render () {
diff --git a/docs/app/components/layout/install/style.css b/docs/app/components/layout/install/style.css
new file mode 100644
index 00000000..eb7e6cc6
--- /dev/null
+++ b/docs/app/components/layout/install/style.css
@@ -0,0 +1,6 @@
+@import 'variables.css';
+@import 'app_bar/config.css';
+
+.install {
+ margin-top: var(--appbar-height);
+}
diff --git a/docs/app/components/layout/install/style.scss b/docs/app/components/layout/install/style.scss
deleted file mode 100644
index 968a90a4..00000000
--- a/docs/app/components/layout/install/style.scss
+++ /dev/null
@@ -1,6 +0,0 @@
-@import "../../globals";
-@import "~react-toolbox/app_bar/config";
-
-.install {
- margin-top: $appbar-height;
-}
diff --git a/docs/app/components/layout/main/_config.scss b/docs/app/components/layout/main/_config.scss
deleted file mode 100644
index d564a848..00000000
--- a/docs/app/components/layout/main/_config.scss
+++ /dev/null
@@ -1,11 +0,0 @@
-@import "../../globals";
-
-$media-min-width: 1440px;
-$playground-max-width: $media-min-width / 2;
-$playground-width: 50%;
-$navigation-width: 22 * $unit;
-$navigation-h-padding: 2.4 * $unit;
-$navigation-v-padding: 1.2 * $unit;
-$navigation-footer-border: solid 1px rgb(224, 224, 224);
-$documentation-left-shadow: 0 4px 5px 0 rgba(0,0,0,.14),0 1px 10px 0 rgba(0,0,0,.12),0 2px 4px -1px rgba(0,0,0,.2);
-$documentation-right-shadow: -2px 0 4px rgba(0,0,0,.14);
diff --git a/docs/app/components/layout/main/button-theme.scss b/docs/app/components/layout/main/button-theme.scss
deleted file mode 100644
index a2900e34..00000000
--- a/docs/app/components/layout/main/button-theme.scss
+++ /dev/null
@@ -1,2 +0,0 @@
-@import "../../globals";
-@import "~react-toolbox/button/theme";
diff --git a/docs/app/components/layout/main/components/navigation.css b/docs/app/components/layout/main/components/navigation.css
new file mode 100644
index 00000000..0d203027
--- /dev/null
+++ b/docs/app/components/layout/main/components/navigation.css
@@ -0,0 +1,48 @@
+@import 'colors.css';
+@import 'variables.css';
+@import '../config.css';
+
+.root {
+ background-color: var(--color-background);
+ display: flex;
+ flex-direction: column;
+ width: var(--navigation-width);
+}
+
+.list {
+ flex-grow: 1;
+ overflow-y: auto;
+
+ &::-webkit-scrollbar {
+ height: 0;
+ width: 0;
+ }
+}
+
+.item {
+ & > span {
+ padding: var(--navigation-v-padding) var(--navigation-h-padding);
+ }
+
+ & [data-react-toolbox='list-item-text'] {
+ font-size: var(--font-size-small);
+ font-weight: var(--font-weight-semi-bold);
+ }
+}
+
+.active {
+ background: $color-divider;
+}
+
+.footer {
+ border-top: var(--navigation-footer-border);
+ color: var(--color-text-secondary);
+ flex-grow: 0;
+ font-size: var(--font-size-small);
+ overflow: hidden;
+ padding: var(--navigation-h-padding);
+
+ & > * {
+ display: block;
+ }
+}
diff --git a/docs/app/components/layout/main/components/navigation.js b/docs/app/components/layout/main/components/navigation.js
index 8d6a5a24..77efea2d 100644
--- a/docs/app/components/layout/main/components/navigation.js
+++ b/docs/app/components/layout/main/components/navigation.js
@@ -2,7 +2,7 @@ import React, { PropTypes } from 'react';
import { List, ListItem } from 'react-toolbox';
import classnames from 'classnames';
import components from '../modules/components';
-import style from './navigation.scss';
+import style from './navigation.css';
const MainNavigation = ({ className }, { router }) => {
const drawerItems = Object.keys(components).map((key) => {
diff --git a/docs/app/components/layout/main/components/navigation.scss b/docs/app/components/layout/main/components/navigation.scss
deleted file mode 100644
index 37203cc2..00000000
--- a/docs/app/components/layout/main/components/navigation.scss
+++ /dev/null
@@ -1,40 +0,0 @@
-@import "../config";
-
-.root {
- display: flex;
- width: $navigation-width;
- flex-direction: column;
- background-color: $color-background;
-}
-
-.list {
- @include no-webkit-scrollbar;
- flex-grow: 1;
- overflow-y: auto;
-}
-
-.item {
- > span{
- padding: $navigation-v-padding $navigation-h-padding;
- }
- [data-react-toolbox="list-item-text"] {
- font-size: $font-size-small;
- font-weight: $font-weight-semi-bold;
- }
-}
-
-.active {
- background: $color-divider;
-}
-
-.footer {
- flex-grow: 0;
- padding: $navigation-h-padding;
- overflow: hidden;
- font-size: $font-size-small;
- color: $color-text-secondary;
- border-top: $navigation-footer-border;
- > * {
- display: block;
- }
-}
diff --git a/docs/app/components/layout/main/components/playground.scss b/docs/app/components/layout/main/components/playground.css
similarity index 62%
rename from docs/app/components/layout/main/components/playground.scss
rename to docs/app/components/layout/main/components/playground.css
index b10e7987..d059090c 100644
--- a/docs/app/components/layout/main/components/playground.scss
+++ b/docs/app/components/layout/main/components/playground.css
@@ -1,29 +1,37 @@
-@import "../config";
+@import 'colors.css';
+@import 'variables.css';
+@import '../config.css';
-.editor, .preview {
- @include no-webkit-scrollbar;
+.editor,
+.preview {
+ overflow-y: auto;
position: absolute;
right: 0;
- overflow-y: auto;
+
+ &::-webkit-scrollbar {
+ height: 0;
+ width: 0;
+ }
}
.editor {
- top: 0;
bottom: 50%;
left: 0;
- div:global(.CodeMirror) {
+ top: 0;
+
+ & div:global(.CodeMirror) {
display: flex;
- height: 100%;
- min-height: 100%;
- max-height: 100%;
flex-direction: column;
flex-grow: 1;
+ height: 100%;
+ max-height: 100%;
+ min-height: 100%;
}
}
.preview {
- top: 50%;
bottom: 0;
- left: 0;
display: flex;
+ left: 0;
+ top: 50%;
}
diff --git a/docs/app/components/layout/main/components/playground.js b/docs/app/components/layout/main/components/playground.js
index c848fec2..dc79285f 100644
--- a/docs/app/components/layout/main/components/playground.js
+++ b/docs/app/components/layout/main/components/playground.js
@@ -2,7 +2,7 @@ import React from 'react';
import Editor from '../../../editor';
import Preview from '../../../preview';
import codeText from '../modules/examples/example.txt';
-import style from './playground.scss';
+import style from './playground.css';
class Playground extends React.Component {
static propTypes = {
diff --git a/docs/app/components/layout/main/config.css b/docs/app/components/layout/main/config.css
new file mode 100644
index 00000000..145f4fcb
--- /dev/null
+++ b/docs/app/components/layout/main/config.css
@@ -0,0 +1,14 @@
+:root {
+ --media-min-width: 1440px;
+ --playground-max-width: calc(var(--media-min-width) / 2);
+ --playground-width: 50%;
+ --navigation-width: calc(22 * var(--unit));
+ --navigation-h-padding: calc(2.4 * var(--unit));
+ --navigation-v-padding: calc(1.2 * var(--unit));
+ --navigation-footer-border: solid 1px rgb(224, 224, 224);
+ --documentation-left-shadow:
+ 0 4px 5px 0 color(var(--color-black) a(14%)),
+ 0 1px 10px 0 color(var(--color-black) a(12%)),
+ 0 2px 4px -1px color(var(--color-black) a(20%));
+ --documentation-right-shadow: -2px 0 4px color(var(--color-black) a(14%));
+}
diff --git a/docs/app/components/layout/main/index.js b/docs/app/components/layout/main/index.js
index 7685e20f..4ada79ac 100644
--- a/docs/app/components/layout/main/index.js
+++ b/docs/app/components/layout/main/index.js
@@ -7,15 +7,14 @@ import Playground from './components/playground.js';
import MainNavigation from './components/navigation.js';
import BaseDocs from './modules/components.md';
import components from './modules/components.js';
-import buttonTheme from './button-theme.scss';
-import style from './style';
+import style from './style.css';
const LoadExampleButton = (props) => (
diff --git a/docs/app/components/layout/main/modules/components.js b/docs/app/components/layout/main/modules/components.js
index 8e647774..e860fd4b 100644
--- a/docs/app/components/layout/main/modules/components.js
+++ b/docs/app/components/layout/main/modules/components.js
@@ -42,7 +42,6 @@ import DrawerExample1 from './examples/drawer_example_1.txt';
import DrodpownExample1 from './examples/dropdown_example_1.txt';
import FontIconExample1 from './examples/font_icon_example_1.txt';
import InputExample1 from './examples/input_example_1.txt';
-import LayoutExample1 from './examples/layout_example_1.txt';
import LinkExample1 from './examples/link_example_1.txt';
import ListExample1 from './examples/list_example_1.txt';
import MenuExample1 from './examples/menu_example_1.txt';
@@ -140,8 +139,7 @@ export default {
layout: {
name: 'Layout',
docs: Layout,
- path: '/components/layout',
- examples: [LayoutExample1]
+ path: '/components/layout'
},
link: {
name: 'Link',
diff --git a/docs/app/components/layout/main/modules/examples/layout_example_1.txt b/docs/app/components/layout/main/modules/examples/layout_example_1.txt
deleted file mode 100644
index 77aa21e6..00000000
--- a/docs/app/components/layout/main/modules/examples/layout_example_1.txt
+++ /dev/null
@@ -1,50 +0,0 @@
-class LayoutTest extends React.Component {
- state = {
- drawerActive: false,
- drawerPinned: false,
- sidebarPinned: false
- };
-
- toggleDrawerActive = () => {
- this.setState({ drawerActive: !this.state.drawerActive });
- };
-
- toggleDrawerPinned = () => {
- this.setState({ drawerPinned: !this.state.drawerPinned });
- }
-
- toggleSidebar = () => {
- this.setState({ sidebarPinned: !this.state.sidebarPinned });
- };
-
- render() {
- return (
-
-
-
- Navigation, account switcher, etc. go here.
-
-
-
-
-
-
Main Content
-
Main content goes here.
-
-
-
-
-
-
-
-
Supplemental content goes here.
-
-
-
- );
- }
-}
-
-return ;
diff --git a/docs/app/components/layout/main/style.css b/docs/app/components/layout/main/style.css
new file mode 100644
index 00000000..ee68f681
--- /dev/null
+++ b/docs/app/components/layout/main/style.css
@@ -0,0 +1,109 @@
+@import 'colors.css';
+@import 'variables.css';
+@import 'app_bar/config.css';
+@import 'button/config.css';
+@import 'button/theme.css';
+@import './config.css';
+
+hr {
+ border-top: 1px solid var(--color-divider);
+ margin: 4rem 0;
+}
+
+.appbar {
+ padding-right: calc(8 * var(--unit));
+}
+
+.playground-button {
+ position: fixed;
+ right: calc(var(--button-floating-height) / 2);
+ top: calc(var(--appbar-height) - (var(--button-floating-height) / 2));
+ z-index: var(--z-index-highest);
+}
+
+.documentation {
+ bottom: 0;
+ left: 0;
+ position: fixed;
+ right: 0;
+ top: var(--appbar-height);
+ transition: padding var(--animation-duration) var(--animation-curve-default);
+ z-index: var(--z-index-normal);
+}
+
+.navigation {
+ bottom: 0;
+ box-shadow: var(--documentation-left-shadow);
+ left: 0;
+ position: fixed;
+ top: var(--appbar-height);
+ transition: transform var(--animation-duration) var(--animation-curve-default);
+ z-index: var(--z-index-high);
+}
+
+.playground {
+ background: var(--color-background);
+ bottom: 0;
+ box-shadow: var(--documentation-right-shadow);
+ position: fixed;
+ right: 0;
+ top: var(--appbar-height);
+ transition: transform var(--animation-duration) var(--animation-curve-default);
+ width: var(--playground-width);
+ z-index: var(--z-index-high);
+}
+
+.root {
+ &:not(.with-playground) {
+ & > .playground {
+ transform: translateX(100%);
+ }
+
+ & > .documentation {
+ padding-left: var(--navigation-width);
+ padding-right: 0;
+ }
+
+ & > .navigation {
+ transform: translateX(0);
+ }
+ }
+
+ &.with-playground {
+ & > .playground {
+ transform: translateY(0);
+ }
+
+ & > .documentation {
+ padding-left: 0;
+ padding-right: var(--playground-width);
+ }
+
+ & > .navigation {
+ transform: translateX(calc(-1 * 100%));
+ }
+ }
+}
+
+.load-button {
+ display: inline-block;
+}
+
+@media and (min-width: 1440px) {
+ .root {
+ & .playground {
+ width: var(--playground-max-width);
+ }
+
+ &.with-playground {
+ & > .documentation {
+ padding-left: var(--navigation-width);
+ padding-right: var(--playground-max-width);
+ }
+
+ & > .navigation {
+ transform: translateX(0);
+ }
+ }
+ }
+}
diff --git a/docs/app/components/layout/main/style.scss b/docs/app/components/layout/main/style.scss
deleted file mode 100644
index 764d0e50..00000000
--- a/docs/app/components/layout/main/style.scss
+++ /dev/null
@@ -1,99 +0,0 @@
-@import "./config";
-@import "~react-toolbox/app_bar/config";
-@import "~react-toolbox/button/config";
-
-hr {
- margin: 4rem 0;
- border-top: 1px solid $color-divider;
-}
-
-.appbar {
- padding-right: 8 * $unit;
-}
-
-.playground-button {
- position: fixed;
- top: $appbar-height - ($button-floating-height / 2);
- right: $button-floating-height / 2;
- z-index: $z-index-highest;
-}
-
-.documentation {
- position: fixed;
- top: $appbar-height;
- right: 0;
- bottom: 0;
- left: 0;
- z-index: $z-index-normal;
- transition: padding $animation-duration $animation-curve-default;
-}
-
-.navigation {
- position: fixed;
- top: $appbar-height;
- bottom: 0;
- left: 0;
- z-index: $z-index-high;
- box-shadow: $documentation-left-shadow;
- transition: transform $animation-duration $animation-curve-default;
-}
-
-.playground {
- position: fixed;
- top: $appbar-height;
- right: 0;
- bottom: 0;
- z-index: $z-index-high;
- width: $playground-width;
- background: $color-background;
- box-shadow: $documentation-right-shadow;
- transition: transform $animation-duration $animation-curve-default;
-}
-
-.root {
- &:not(.with-playground) {
- > .playground {
- transform: translateX(100%);
- }
- > .documentation {
- padding-right: 0;
- padding-left: $navigation-width;
- }
- > .navigation {
- transform: translateX(0);
- }
- }
- &.with-playground {
- > .playground {
- transform: translateY(0);
- }
- > .documentation {
- padding-right: $playground-width;
- padding-left: 0;
- }
- > .navigation {
- transform: translateX(- 100%);
- }
- }
-}
-
-.load-button {
- display: inline-block;
-}
-
-@media(min-width: $media-min-width) {
- .root {
- .playground {
- width: $playground-max-width;
- }
- &.with-playground {
- > .documentation {
- padding-right: $playground-max-width;
- padding-left: $navigation-width;
- }
- > .navigation {
- transform: translateX(0);
- }
- }
- }
-}
diff --git a/docs/app/components/logo/index.js b/docs/app/components/logo/index.js
index 58007acd..2be62a21 100644
--- a/docs/app/components/logo/index.js
+++ b/docs/app/components/logo/index.js
@@ -1,5 +1,5 @@
import React from 'react';
-import style from './style';
+import style from './style.css';
const Logo = (props) => {
let className = style.logo;
diff --git a/docs/app/components/logo/style.css b/docs/app/components/logo/style.css
new file mode 100644
index 00000000..df54b8d4
--- /dev/null
+++ b/docs/app/components/logo/style.css
@@ -0,0 +1,8 @@
+@import 'variables.css';
+
+.logo {
+ display: inline-block;
+ fill: #fff;
+ height: calc(20 * var(--unit));
+ width: calc(20 * var(--unit));
+}
diff --git a/docs/app/components/logo/style.scss b/docs/app/components/logo/style.scss
deleted file mode 100644
index f6585f29..00000000
--- a/docs/app/components/logo/style.scss
+++ /dev/null
@@ -1,9 +0,0 @@
-@import "../globals";
-@import "../mixins";
-
-.logo {
- display: inline-block;
- width: 20 * $unit;
- height: 20 * $unit;
- fill: #fff;
-}
diff --git a/docs/app/components/markdown/index.js b/docs/app/components/markdown/index.js
index 095859d3..3d85d7ab 100644
--- a/docs/app/components/markdown/index.js
+++ b/docs/app/components/markdown/index.js
@@ -1,5 +1,6 @@
+import 'highlight.js/styles/github-gist';
import React from 'react';
-import style from './style';
+import style from './style.css';
const Markdown = (props) => {
let className = style.markdown;
diff --git a/docs/app/components/markdown/style.css b/docs/app/components/markdown/style.css
new file mode 100644
index 00000000..aa5aa859
--- /dev/null
+++ b/docs/app/components/markdown/style.css
@@ -0,0 +1,118 @@
+@import 'colors.css';
+@import 'variables.css';
+
+:root {
+ --documentation-h1-size: calc(3.4 * var(--unit));
+ --documentation-h2-size: calc(2.4 * var(--unit));
+ --documentation-h-offset: calc(4 * var(--unit));
+ --documentation-v-offset: calc(var(--documentation-h-offset) / 2);
+ --documentation-code-background: rgba(0, 0, 0, 0.05);
+ --documentation-playground-button-height: calc(3 * var(--unit));
+ --documentation-playground-button-font-size: calc(1.2 * var(--unit));
+ --documentation-table-font-size: calc(1.4 * var(--unit));
+}
+
+.markdown {
+ color: var(--color-text);
+ display: block;
+ flex-grow: 1;
+ font-size: var(--font-size-normal);
+ max-height: 100%;
+ overflow-y: auto;
+ padding-bottom: calc(4 * var(--unit));
+
+ & > *:not(pre) {
+ margin: var(--documentation-v-offset) var(--documentation-h-offset);
+ }
+
+ & h1 {
+ font-size: var(--documentation-h1-size);
+ }
+
+ & h2 {
+ font-size: var(--documentation-h2-size);
+ }
+
+ & h3,
+ & h4,
+ & h5,
+ & h6 {
+ font-size: inherit;
+ font-weight: var(--font-weight-bold);
+ }
+
+ & h1,
+ & h2 {
+ color: var(--color-primary-dark);
+ padding-top: var(--documentation-v-offset);
+ }
+
+ & p {
+ font-size: inherit;
+ line-height: 1.5;
+
+ & a {
+ color: var(--color-text);
+ text-decoration: underline;
+ }
+ }
+
+ & code {
+ background-color: var(--documentation-code-background);
+ border-radius: 2px;
+ font-family: source-code-pro, Menlo, Consolas, Monaco, 'Andale Mono', 'Courier New', monospace;
+ font-size: 13px;
+ line-height: 1.4;
+ padding: calc(0.3 * var(--unit)) calc(0.5 * var(--unit));
+ }
+
+ & pre {
+ background-color: var(--documentation-code-background);
+ font-family: source-code-pro, Menlo, Consolas, Monaco, 'Andale Mono', 'Courier New', monospace;
+ font-size: 13px;
+ line-height: 1.4;
+ padding: var(--documentation-v-offset) var(--documentation-h-offset);
+ }
+
+ & > :global(.playground-button) {
+ display: block;
+ text-align: left;
+
+ & > button {
+ font-size: var(--documentation-playground-button-font-size);
+ height: var(--documentation-playground-button-height);
+ line-height: var(--documentation-playground-button-height);
+
+ & > span {
+ line-height: var(--documentation-playground-button-height);
+ }
+ }
+ }
+
+ & ul {
+ -webkit-font-smoothing: antialiased;
+ font-smoothing: antialiased;
+ margin-left: 7 * var(--unit);
+
+ & > li {
+ margin-bottom: var(--unit);
+ }
+ }
+
+ & table {
+ font-size: var(--documentation-table-font-size);
+ width: auto;
+
+ & thead th {
+ -webkit-font-smoothing: antialiased;
+ font-smoothing: antialiased;
+ }
+
+ & th,
+ & td {
+ -webkit-font-smoothing: antialiased;
+ font-smoothing: antialiased;
+ padding: var(--unit);
+ }
+ }
+}
diff --git a/docs/app/components/markdown/style.scss b/docs/app/components/markdown/style.scss
deleted file mode 100644
index 14f503e1..00000000
--- a/docs/app/components/markdown/style.scss
+++ /dev/null
@@ -1,96 +0,0 @@
-@import "../globals";
-@import "../mixins";
-
-$documentation-h1-size: 3.4 * $unit;
-$documentation-h2-size: 2.4 * $unit;
-$documentation-h-offset: 4 * $unit;
-$documentation-v-offset: ($documentation-h-offset / 2);
-$documentation-code-background: rgba(0, 0, 0, .05);
-$documentation-playground-button-height: 3 * $unit;
-$documentation-playground-button-font-size: 1.2 * $unit;
-$documentation-table-font-size: 1.4 * $unit;
-
-:global {
- @import "~highlight.js/styles/github-gist";
-}
-
-.markdown {
- display: block;
- max-height: 100%;
- flex-grow: 1;
- padding-bottom: 4 * $unit;
- overflow-y: auto;
- font-size: $font-size-normal;
- color: $color-text;
- > *:not(pre) {
- margin: $documentation-v-offset $documentation-h-offset;
- }
- h1 {
- font-size: $documentation-h1-size;
- }
- h2 {
- font-size: $documentation-h2-size;
- }
- h3, h4, h5, h6 {
- font-size: inherit;
- font-weight: $font-weight-bold;
- }
- h1, h2 {
- padding-top: $documentation-v-offset;
- color: $color-primary-dark;
- }
- p {
- font-size: inherit;
- line-height: 1.5;
- a {
- color: $color-text;
- text-decoration: underline;
- }
- }
- code {
- @include code-typography;
- padding: .3 * $unit .5 * $unit;
- background-color: $documentation-code-background;
- border-radius: 2px;
- }
- pre {
- @include code-typography;
- padding: $documentation-v-offset $documentation-h-offset;
- background-color: $documentation-code-background;
- }
- > :global(.playground-button) {
- display: block;
- text-align: left;
- > button {
- height: $documentation-playground-button-height;
- font-size: $documentation-playground-button-font-size;
- line-height: $documentation-playground-button-height;
- > span {
- line-height: $documentation-playground-button-height;
- }
- }
- }
- ul {
- margin-left: 7 * $unit;
-
- -webkit-font-smoothing: antialiased;
- font-smoothing: antialiased;
- > li {
- margin-bottom: $unit;
- }
- }
- table {
- width: auto;
- font-size: $documentation-table-font-size;
- thead th {
- -webkit-font-smoothing: antialiased;
- font-smoothing: antialiased;
- }
- th, td {
- padding: $unit;
-
- -webkit-font-smoothing: antialiased;
- font-smoothing: antialiased;
- }
- }
-}
diff --git a/docs/app/components/preview/index.js b/docs/app/components/preview/index.js
index e9b45aed..72e9a7b5 100644
--- a/docs/app/components/preview/index.js
+++ b/docs/app/components/preview/index.js
@@ -1,11 +1,9 @@
/*eslint-disable no-eval*/
import React from 'react';
import ReactDOM from 'react-dom';
-import { ThemeProvider } from 'react-css-themr';
import { transform } from 'babel-standalone';
import * as ReactToolbox from 'react-toolbox';
-import theme from '../../theme/theme.js';
-import style from './style';
+import style from './style.css';
const ERROR_TIMEOUT = 500;
@@ -73,11 +71,7 @@ const Preview = React.createClass({
}
try {
- ReactDOM.render(
-
- {eval(this.compileCode())(...scope)}
-
- , mountNode);
+ ReactDOM.render(eval(this.compileCode())(...scope), mountNode);
if (this.state.error) {
this.setState({error: null});
}
diff --git a/docs/app/components/preview/style.css b/docs/app/components/preview/style.css
new file mode 100644
index 00000000..bd2c96ea
--- /dev/null
+++ b/docs/app/components/preview/style.css
@@ -0,0 +1,27 @@
+@import 'variables';
+
+:root {
+ --preview-error-background: #f2777a;
+ --preview-error-color: #fff;
+}
+
+.preview {
+ display: flex;
+ flex-direction: column;
+}
+
+.content {
+ flex-grow: 1;
+ margin: calc(2 * var(--unit));
+}
+
+.error {
+ background: var(--preview-error-background);
+ border-bottom: 1px solid color(var(--preview-error-background) blackness(60%));
+ color: var(--preview-error-color);
+ font-family: source-code-pro, Menlo, Consolas, Monaco, 'Andale Mono', 'Courier New', monospace;
+ font-size: 13px;
+ letter-spacing: calc(-0.05 * var(--unit));
+ line-height: 1.4;
+ padding: calc(0.5 * var(--unit));
+}
diff --git a/docs/app/components/preview/style.scss b/docs/app/components/preview/style.scss
deleted file mode 100644
index 5f1a1d7e..00000000
--- a/docs/app/components/preview/style.scss
+++ /dev/null
@@ -1,24 +0,0 @@
-@import "../globals";
-@import "../mixins";
-
-$preview-error-background: #f2777a;
-$preview-error-color: #fff;
-
-.preview {
- display: flex;
- flex-direction: column;
-}
-
-.content {
- flex-grow: 1;
- margin: 2 * $unit;
-}
-
-.error {
- @include code-typography;
- padding: .5 * $unit;
- color: $preview-error-color;
- letter-spacing: -.05 * $unit;
- background: $preview-error-background;
- border-bottom: 1px solid darken($preview-error-background, 6);
-}
diff --git a/docs/app/index.js b/docs/app/index.js
index 1b5ecc87..6b1a5779 100644
--- a/docs/app/index.js
+++ b/docs/app/index.js
@@ -1,3 +1,4 @@
+import 'react-toolbox/commons.css';
import React from 'react';
import ReactDOM from 'react-dom';
import { Router, Route, useRouterHistory } from 'react-router';
diff --git a/docs/app/theme/_theme.scss b/docs/app/theme/_theme.scss
deleted file mode 100644
index 96be0e6b..00000000
--- a/docs/app/theme/_theme.scss
+++ /dev/null
@@ -1,9 +0,0 @@
-@import "~react-toolbox/colors"; // Import minimal colors
-
-$color-primary: $palette-indigo-500;
-$color-primary-dark: $palette-indigo-700;
-$color-primary-light: $palette-indigo-500;
-$color-accent: $palette-pink-a200;
-$color-accent-dark: $palette-pink-700;
-$color-primary-contrast: $color-dark-contrast;
-$color-accent-contrast: $color-dark-contrast;
diff --git a/docs/app/theme/theme.js b/docs/app/theme/theme.js
deleted file mode 100644
index 68c3ea1c..00000000
--- a/docs/app/theme/theme.js
+++ /dev/null
@@ -1,61 +0,0 @@
-import 'react-toolbox/commons';
-
-import ToolboxAppBar from 'react-toolbox/app_bar/theme.scss';
-import ToolboxAutocomplete from 'react-toolbox/autocomplete/theme.scss';
-import ToolboxAvatar from 'react-toolbox/avatar/theme.scss';
-import ToolboxButton from 'react-toolbox/button/theme.scss';
-import ToolboxCard from 'react-toolbox/card/theme.scss';
-import ToolboxCheckbox from 'react-toolbox/checkbox/theme.scss';
-import ToolboxChip from 'react-toolbox/chip/theme.scss';
-import ToolboxDatePicker from 'react-toolbox/date_picker/theme.scss';
-import ToolboxDialog from 'react-toolbox/dialog/theme.scss';
-import ToolboxDrawer from 'react-toolbox/drawer/theme.scss';
-import ToolboxDropdown from 'react-toolbox/dropdown/theme.scss';
-import ToolboxInput from 'react-toolbox/input/theme.scss';
-import ToolboxLayout from 'react-toolbox/layout/theme.scss';
-import ToolboxLink from 'react-toolbox/link/theme.scss';
-import ToolboxList from 'react-toolbox/list/theme.scss';
-import ToolboxMenu from 'react-toolbox/menu/theme.scss';
-import ToolboxNavigation from 'react-toolbox/navigation/theme.scss';
-import ToolboxOverlay from 'react-toolbox/overlay/theme.scss';
-import ToolboxProgress from 'react-toolbox/progress_bar/theme.scss';
-import ToolboxRadio from 'react-toolbox/radio/theme.scss';
-import ToolboxRipple from 'react-toolbox/ripple/theme.scss';
-import ToolboxSlider from 'react-toolbox/slider/theme.scss';
-import ToolboxSnackbar from 'react-toolbox/snackbar/theme.scss';
-import ToolboxSwitch from 'react-toolbox/switch/theme.scss';
-import ToolboxTable from 'react-toolbox/table/theme.scss';
-import ToolboxTabs from 'react-toolbox/tabs/theme.scss';
-import ToolboxTimePicker from 'react-toolbox/time_picker/theme.scss';
-import ToolboxTooltip from 'react-toolbox/tooltip/theme.scss';
-
-export default {
- ToolboxAppBar,
- ToolboxAutocomplete,
- ToolboxAvatar,
- ToolboxButton,
- ToolboxCard,
- ToolboxCheckbox,
- ToolboxChip,
- ToolboxDatePicker,
- ToolboxDialog,
- ToolboxDrawer,
- ToolboxDropdown,
- ToolboxInput,
- ToolboxLayout,
- ToolboxLink,
- ToolboxList,
- ToolboxMenu,
- ToolboxNavigation,
- ToolboxOverlay,
- ToolboxProgress,
- ToolboxRadio,
- ToolboxRipple,
- ToolboxSlider,
- ToolboxSnackbar,
- ToolboxSwitch,
- ToolboxTable,
- ToolboxTabs,
- ToolboxTimePicker,
- ToolboxTooltip
-};
diff --git a/docs/package.json b/docs/package.json
index cb6db167..5d393b31 100644
--- a/docs/package.json
+++ b/docs/package.json
@@ -38,13 +38,16 @@
"html-loader": "^0.4.3",
"html-webpack-plugin": "^2.16.1",
"markdown-loader": "^0.1.7",
- "node-sass": "^3.7.0",
- "postcss-loader": "^1.2.1",
+ "postcss-cssnext": "^2.7.0",
+ "postcss-each": "^0.9.3",
+ "postcss-import": "^8.1.2",
+ "postcss-loader": "^0.9.1",
+ "postcss-mixins": "^5.0.0",
+ "postcss-reporter": "^1.4.1",
"raw-loader": "^0.5.1",
"react-transform-catch-errors": "^1.0.2",
"react-transform-hmr": "^1.0.4",
"redbox-react": "^1.2.4",
- "sass-loader": "^4.0.0",
"style-loader": "^0.13.1",
"transfer-webpack-plugin": "^0.1.4",
"webpack": "^1.13.0",
diff --git a/docs/toolbox-variables.js b/docs/toolbox-variables.js
new file mode 100644
index 00000000..324d1dfd
--- /dev/null
+++ b/docs/toolbox-variables.js
@@ -0,0 +1,9 @@
+module.exports = {
+ 'color-primary': 'var(--palette-indigo-500)',
+ 'color-primary-dark': 'var(--palette-indigo-700)',
+ 'color-primary-light': 'var(--palette-indigo-500)',
+ 'color-accent': 'var(--palette-pink-a200)',
+ 'color-accent-dark': 'var(--palette-pink-700)',
+ 'color-primary-contrast': 'var(--color-dark-contrast)',
+ 'color-accent-contrast': 'var(--color-dark-contrast)'
+};
diff --git a/docs/webpack.config.development.js b/docs/webpack.config.development.js
index 7d4857f8..b7a08089 100644
--- a/docs/webpack.config.development.js
+++ b/docs/webpack.config.development.js
@@ -1,8 +1,8 @@
const path = require('path');
const webpack = require('webpack');
-const autoprefixer = require('autoprefixer');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const TransferWebpackPlugin = require('transfer-webpack-plugin');
+const toolboxVariables = require('./toolbox-variables');
module.exports = {
context: __dirname,
@@ -17,11 +17,9 @@ module.exports = {
publicPath: '/'
},
resolve: {
- extensions: ['', '.scss', '.js', '.json', '.md'],
+ extensions: ['', '.js', '.scss', '.css', '.json', '.md'],
packageMains: ['browser', 'web', 'browserify', 'main', 'style'],
- alias: {
- 'react-toolbox': path.resolve(__dirname + './../components')
- },
+ alias: { 'react-toolbox': path.resolve(__dirname + './../components') },
modulesDirectories: [
'node_modules',
path.resolve(__dirname, './node_modules'),
@@ -30,27 +28,49 @@ module.exports = {
]
},
module: {
- loaders: [
- {
- test: /\.js$/,
- exclude: /(node_modules)/,
- loader: 'babel'
- }, {
- test: /\.(scss|css)$/,
- loader: ExtractTextPlugin.extract('style', 'css?sourceMap&modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!postcss!sass?sourceMap')
- }, {
- test: /\.(txt)$/,
- loader: 'raw',
- include: path.resolve(__dirname, './app/components/layout/main/modules')
- }, {
- test: /\.(md)$/,
- loader: 'html!highlight!markdown'
- }
- ]
+ loaders: [{
+ test: /\.js$/,
+ include: [path.resolve(__dirname, './app'), path.resolve(__dirname, './../components')],
+ loader: 'babel'
+ }, {
+ test: /\.css$/,
+ include: /node_modules/,
+ loaders: ['style-loader', 'css-loader']
+ }, {
+ test: /\.css$/,
+ include: [path.resolve(__dirname, './app'), path.resolve(__dirname + './../components')],
+ loader: ExtractTextPlugin.extract('style', 'css?sourceMap&modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!postcss')
+ }, {
+ test: /\.txt$/,
+ include: path.resolve(__dirname, './app/components/layout/main/modules'),
+ loader: 'raw'
+ }, {
+ test: /\.md$/,
+ include: [path.join(__dirname, './../components'), path.join(__dirname, './app')],
+ loader: 'html!highlight!markdown'
+ }]
},
- postcss: [autoprefixer],
- sassLoader: {
- data: '@import "' + path.resolve(__dirname, 'app/theme/_theme.scss') + '";'
+ postcss (webpackInstance) {
+ return [
+ require('postcss-import')({
+ addDependencyTo: webpackInstance,
+ root: path.join(__dirname, './../'),
+ path: [
+ path.join(__dirname, './app'),
+ path.join(__dirname, './../components')
+ ]
+ }),
+ require('postcss-mixins')(),
+ require('postcss-each')(),
+ require('postcss-cssnext')({
+ features: {
+ customProperties: {
+ variables: toolboxVariables
+ }
+ }
+ }),
+ require('postcss-reporter')({ clearMessages: true })
+ ];
},
plugins: [
new ExtractTextPlugin('docs.css', { allChunks: true }),
diff --git a/docs/webpack.config.production.js b/docs/webpack.config.production.js
index 1eda4769..c398240e 100644
--- a/docs/webpack.config.production.js
+++ b/docs/webpack.config.production.js
@@ -1,9 +1,9 @@
const path = require('path');
const webpack = require('webpack');
-const autoprefixer = require('autoprefixer');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const TransferWebpackPlugin = require('transfer-webpack-plugin');
+const toolboxVariables = require('./toolbox-variables');
module.exports = {
context: __dirname,
@@ -13,11 +13,9 @@ module.exports = {
filename: 'docs.js'
},
resolve: {
- extensions: ['', '.scss', '.js', '.json', '.md'],
+ extensions: ['', '.js', '.scss', '.css', '.json', '.md'],
packageMains: ['browser', 'web', 'browserify', 'main', 'style'],
- alias: {
- 'react-toolbox': path.resolve(__dirname + './../components')
- },
+ alias: { 'react-toolbox': path.resolve(__dirname + './../components') },
modulesDirectories: [
'node_modules',
path.resolve(__dirname, './node_modules'),
@@ -26,27 +24,49 @@ module.exports = {
]
},
module: {
- loaders: [
- {
- test: /\.js$/,
- exclude: /(node_modules)/,
- loader: 'babel'
- }, {
- test: /\.(scss|css)$/,
- loader: ExtractTextPlugin.extract('style', 'css?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!postcss!sass')
- }, {
- test: /\.(txt)$/,
- loader: 'raw',
- include: path.resolve(__dirname, './app/components/layout/main/modules')
- }, {
- test: /\.(md)$/,
- loader: 'html?removeComments=false!highlight!markdown'
- }
- ]
+ loaders: [{
+ test: /\.js$/,
+ include: [path.resolve(__dirname, './app'), path.resolve(__dirname, './../components')],
+ loader: 'babel'
+ }, {
+ test: /\.css$/,
+ include: /node_modules/,
+ loaders: ['style-loader', 'css-loader']
+ }, {
+ test: /\.css$/,
+ include: [path.resolve(__dirname, './app'), path.resolve(__dirname + './../components')],
+ loader: ExtractTextPlugin.extract('style', 'css?sourceMap&modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!postcss')
+ }, {
+ test: /\.txt$/,
+ include: path.resolve(__dirname, './app/components/layout/main/modules'),
+ loader: 'raw'
+ }, {
+ test: /\.md$/,
+ include: [path.join(__dirname, './../components'), path.join(__dirname, './app')],
+ loader: 'html?removeComments=false!highlight!markdown'
+ }]
},
- postcss: [autoprefixer],
- sassLoader: {
- data: '@import "' + path.resolve(__dirname, 'app/theme/_theme.scss') + '";'
+ postcss (webpackInstance) {
+ return [
+ require('postcss-import')({
+ addDependencyTo: webpackInstance,
+ root: path.join(__dirname, './../'),
+ path: [
+ path.join(__dirname, './app'),
+ path.join(__dirname, './../components')
+ ]
+ }),
+ require('postcss-mixins')(),
+ require('postcss-each')(),
+ require('postcss-cssnext')({
+ features: {
+ customProperties: {
+ variables: toolboxVariables
+ }
+ }
+ }),
+ require('postcss-reporter')({ clearMessages: true })
+ ];
},
plugins: [
new ExtractTextPlugin('docs.css', { allChunks: true }),
diff --git a/gulpfile.js b/gulpfile.js
new file mode 100644
index 00000000..694e816f
--- /dev/null
+++ b/gulpfile.js
@@ -0,0 +1,31 @@
+const path = require('path');
+const gulp = require('gulp');
+const babel = require('gulp-babel');
+const postcss = require('gulp-postcss');
+
+gulp.task('js', function () {
+ return gulp.src(['./components/**/*.js'])
+ .pipe(babel())
+ .pipe(gulp.dest('./lib'));
+});
+
+gulp.task('css', function () {
+ const plugins = [
+ require('postcss-import')({
+ root: __dirname,
+ path: [path.join(__dirname, './components')]
+ }),
+ require('postcss-mixins')(),
+ require('postcss-each')(),
+ require('postcss-reporter')({ clearMessages: true })
+ ];
+
+ return gulp.src([
+ './components/*.css',
+ './components/**/*.css'
+ ])
+ .pipe(postcss(plugins))
+ .pipe(gulp.dest('./lib'));
+});
+
+gulp.task('default', ['js', 'css']);
diff --git a/package.json b/package.json
index 3fa44021..6affe361 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "react-toolbox",
"description": "A set of React components implementing Google's Material Design specification with the power of CSS Modules.",
"homepage": "http://www.react-toolbox.com",
- "version": "1.3.4",
+ "version": "2.0.0-beta.4",
"main": "./lib",
"author": {
"name": "React Toolbox Team",
@@ -38,12 +38,13 @@
"dependencies": {
"classnames": "^2.2.5",
"core-js": "^2.4.0",
- "immutability-helper": "^2.0.0",
+ "gulp-rimraf": "^0.2.1",
"normalize.css": "^4.2.0",
+ "ramda": "^0.22.1",
+ "react-addons-css-transition-group": "^15.4.0",
"react-css-themr": "^1.7.1"
},
"devDependencies": {
- "autoprefixer": "^6.5.4",
"babel-cli": "^6.18.0",
"babel-core": "^6.21.0",
"babel-eslint": "^7.1.1",
@@ -67,7 +68,9 @@
"extract-text-webpack-plugin": "^1.0.1",
"git-dirty": "^1.0.2",
"glob": "^7.1.1",
- "immutability-helper": "^2.0.0",
+ "gulp": "^3.9.1",
+ "gulp-babel": "^6.1.2",
+ "gulp-postcss": "^6.2.0",
"internal-ip": "^1.2.0",
"karma": "^1.3.0",
"karma-cli": "^1.0.0",
@@ -75,40 +78,43 @@
"karma-phantomjs-launcher": "^1.0.0",
"karma-webpack": "^1.8.0",
"lint-staged": "^3.2.3",
- "mocha": "^3.2.0",
- "node-sass": "^3.13.0",
+ "mocha": "^3.1.2",
"phantomjs-prebuilt": "^2.1.14",
+ "postcss-cssnext": "^2.8.0",
+ "postcss-each": "^0.9.3",
+ "postcss-import": "8.1.0",
"postcss-loader": "^1.2.1",
+ "postcss-mixins": "^5.4.0",
+ "postcss-reporter": "^3.0.0",
"pre-commit": "^1.2.2",
- "react": "^15.4.1",
- "react-addons-css-transition-group": "^15.4.1",
- "react-addons-test-utils": "^15.4.1",
- "react-dom": "^15.4.1",
+ "react": "^15.4.0",
+ "react-addons-test-utils": "^15.4.0",
+ "react-dom": "^15.4.0",
"react-transform-catch-errors": "^1.0.2",
"react-transform-hmr": "^1.0.4",
"redbox-react": "^1.3.2",
"rimraf": "^2.5.2",
- "sass-lint": "^1.10.2",
- "sass-loader": "^4.1.0",
"sinon": "^2.0.0-pre.2",
"style-loader": "^0.13.1",
+ "stylelint": "^7.5.0",
+ "stylelint-config-standard": "^15.0.0",
"webpack": "^1.14.0",
"webpack-dev-middleware": "^1.9.0",
"webpack-hot-middleware": "^2.13.0"
},
"scripts": {
"babel": "babel ./components --out-dir ./lib",
- "build": "cross-env NODE_ENV=production npm run babel && npm run sass && npm run tsd",
+ "build": "cross-env NODE_ENV=production gulp && npm run tsd",
"clean": "rimraf ./lib",
- "lint": "npm run lint:js && npm run lint:scss",
+ "css": "cpx \"./components/**/*.css\" ./lib",
+ "lint": "npm run lint:js && npm run lint:css",
+ "lint:css": "stylelint ./components/**/*.css",
"lint:js": "eslint ./ --ext .js",
- "lint:scss": "sass-lint ./components/**/*.scss -v -i ./components/slider/style.scss",
"lint:staged": "lint-staged",
"patch": "bumped release patch",
"prebuild": "npm run clean",
"prepublish": "npm run build",
"release": "bumped release",
- "sass": "cpx \"./components/**/*.scss\" ./lib",
"start": "cross-env NODE_ENV=development UV_THREADPOOL_SIZE=100 node ./server",
"test": "cross-env NODE_ENV=test karma start",
"test:watch": "cross-env NODE_ENV=test karma start --no-single-run",
@@ -116,6 +122,7 @@
},
"license": "MIT",
"peerDependencies": {
+ "classnames": "^2.2.0",
"react": "^0.14 || ~15.4.0",
"react-addons-css-transition-group": "^0.14.0 || ~15.4.0",
"react-dom": "^0.14.0 || ~15.4.0"
diff --git a/spec/components/drawer.js b/spec/components/drawer.js
index 2ae7ab5e..cc82d2c0 100644
--- a/spec/components/drawer.js
+++ b/spec/components/drawer.js
@@ -1,6 +1,7 @@
import React from 'react';
import Button from '../../components/button';
import Drawer from '../../components/drawer';
+import style from '../style.css';
class DrawerTest extends React.Component {
state = {
@@ -22,7 +23,11 @@ class DrawerTest extends React.Component {
Drawer
You can navigate using a drawer to the left or right.
-
+
Officia deserunt mollit.
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
diff --git a/spec/components/dropdown.js b/spec/components/dropdown.js
index 5688f414..8cd642b2 100644
--- a/spec/components/dropdown.js
+++ b/spec/components/dropdown.js
@@ -16,6 +16,7 @@ class DropdownTest extends React.Component {
};
handleChange = (dropdown, value) => {
+ console.log('selected', value);
const newState = {};
newState[dropdown] = value;
this.setState(newState);
@@ -69,6 +70,7 @@ class DropdownTest extends React.Component {
ref="dropdown5"
onChange={this.handleChange.bind(this, 'dropdown5')}
source={countries}
+ value={this.state.dropdown5}
required
/>
diff --git a/spec/components/layout.js b/spec/components/layout.js
deleted file mode 100644
index 6d74aa18..00000000
--- a/spec/components/layout.js
+++ /dev/null
@@ -1,153 +0,0 @@
-import React from 'react';
-import { AppBar, Checkbox, Dropdown, IconButton, RadioGroup, RadioButton } from '../../components';
-import { Layout, NavDrawer, Panel, Sidebar } from '../../components';
-
-const dummyText = 'Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry\'s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.';
-
-const drawerItems = dummyText.split(/\s/).map(function (word, index) {
- return ({word} );
-});
-
-const sidebarWidths = [
- { value: 4, label: '4 incr' },
- { value: 5, label: '5 incr' },
- { value: 6, label: '6 incr' },
- { value: 7, label: '7 incr' },
- { value: 8, label: '8 incr' },
- { value: 9, label: '9 incr' },
- { value: 10, label: '10 incr' },
- { value: 25, label: '25%'},
- { value: 33, label: '33%'},
- { value: 50, label: '50%'},
- { value: 66, label: '66%'},
- { value: 75, label: '75%'}
-];
-
-class LayoutTest extends React.Component {
-
- state = {
- permanentAt: 'lg',
- drawerOpen: false,
- drawerPinned: false,
- sidebarPinned: false,
- sidebarWidth: 5,
- loremIpsums: 1
- };
-
- toggleDrawer = (event) => {
- event.stopPropagation();
- this.setState({ drawerOpen: !this.state.drawerOpen });
- };
-
- toggleDrawerPinned = () => {
- this.setState({ drawerPinned: !this.state.drawerPinned });
- };
-
- changeDrawerPermanentAt = (value) => {
- this.setState({ permanentAt: value });
- };
-
- toggleSidebar = (value) => {
- this.setState({ sidebarPinned: (value === true) });
- };
-
- changeSidebarWidth = (value) => {
- this.setState({ sidebarWidth: value });
- };
-
- fewer = (event) => {
- event.preventDefault();
- this.setState({ loremIpsums: Math.max(0, this.state.loremIpsums - 1) });
- };
-
- more = (event) => {
- event.preventDefault();
- this.setState({ loremIpsums: this.state.loremIpsums + 1 });
- };
-
- render () {
-
- const rng = Array.from(new Array(this.state.loremIpsums), (x, i) => i);
-
- return (
-
- Layout
-
-
-
-
-
-
-
-
-
-
-
- NavDrawer State
- Drawer becomes permanent when window is....
-
-
-
-
-
-
-
-
-
-
-
- Sidebar State
-
-
-
-
- Sidebar Width
-
-
-
-
-
- Scrollable Content
-
- The center pane should scroll independently from
- the sides. Show
- [- ]
- {`${this.state.loremIpsums}`}
- [+ ] paragraph(s) below this one.
-
- {rng.map((x, i) => {dummyText}
)}
-
-
-
-
-
-
-
Sidebar
-
- Sidebar content should be secondary to the main content on a page.
-
-
- The width of the sidebar can be set either in increments
- (where 1 increment = height of the app bar) or in percentages.
-
-
- As per the spec, the right sidebar expands to cover the entire
- screen at small screen sizes.
-
-
-
-
-
-
- );
- }
-}
-
-export default LayoutTest;
diff --git a/spec/components/pickers.js b/spec/components/pickers.js
index 2f3c128b..3ec958c9 100644
--- a/spec/components/pickers.js
+++ b/spec/components/pickers.js
@@ -2,7 +2,6 @@ import React from 'react';
import DatePicker from '../../components/date_picker';
import TimePicker from '../../components/time_picker';
-
const datetime = new Date(2015, 10, 16);
const min_datetime = new Date(new Date(datetime).setDate(8));
const max_datetime = new Date(new Date(datetime).setDate(24));
@@ -109,6 +108,7 @@ class PickersTest extends React.Component {
/>
console.log('esc key down')}
diff --git a/spec/components/progress.js b/spec/components/progress.js
index e032fe2b..2751a813 100644
--- a/spec/components/progress.js
+++ b/spec/components/progress.js
@@ -1,6 +1,6 @@
import React from 'react';
import ProgressBar from '../../components/progress_bar';
-import style from '../style';
+import style from '../style.css';
const initialState = {
progress: 0,
diff --git a/spec/components/table.js b/spec/components/table.js
index 8598aa63..2fbabd7b 100644
--- a/spec/components/table.js
+++ b/spec/components/table.js
@@ -1,49 +1,88 @@
-import React from 'react';
-import Table from '../../components/table';
+import React, { Component } from 'react';
+import { Table, TableHead, TableRow, TableCell } from '../../components/table';
+import Tooltip from '../../components/tooltip';
-const UserModel = {
- name: {type: String},
- twitter: {type: String, title: '@twitter'},
- birthdate: {type: Date},
- cats: {type: Number, onChange (...args) { console.log('changes:', ...args); } },
- dogs: {type: Number},
- owner: {type: Boolean }
-};
-
-const users = [
- {name: 'Javi Jimenez', twitter: '@soyjavi', birthdate: new Date(1980, 3, 11), cats: 1},
- {name: 'Javi Velasco', twitter: '@javivelasco', birthdate: new Date(1987, 1, 1), dogs: 1, owner: true}
+const data = [
+ { name: 'Cupcake', calories: 305, fat: 3.7, carbs: 67, protein: 4.3, sodium: 413, calcium: '3%', iron: '8%' },
+ { name: 'Donut', calories: 452, fat: 25.0, carbs: 51, protein: 4.9, sodium: 326, calcium: '2%', iron: '22%' },
+ { name: 'Eclair', calories: 262, fat: 16.0, carbs: 24, protein: 6.0, sodium: 337, calcium: '6%', iron: '7%' },
+ { name: 'Frozen yogurt', calories: 159, fat: 6.0, carbs: 24, protein: 4.0, sodium: 87, calcium: '14%', iron: '1%' },
+ { name: 'Gingerbread', calories: 356, fat: 16.0, carbs: 49, protein: 3.9, sodium: 327, calcium: '7%', iron: '16%' },
+ { name: 'Ice cream sandwich', calories: 237, fat: 9.0, carbs: 37, protein: 4.3, sodium: 129, calcium: '8%', iron: '1%' },
+ { name: 'Jelly bean', calories: 375, fat: 0.0, carbs: 94, protein: 0.0, sodium: 50, calcium: '0%', iron: '0%' },
+ { name: 'KitKat', calories: 518, fat: 26.0, carbs: 65, protein: 7, sodium: 54, calcium: '12%', iron: '6%' }
];
-class TableTest extends React.Component {
+const TooltippedCell = Tooltip(TableCell);
+
+const sortByCaloriesAsc = (a, b) => {
+ if (a.calories < b.calories) return -1;
+ if (a.calories > b.calories) return 1;
+ return 0;
+};
+
+const sortByCaloriesDesc = (a, b) => {
+ if (a.calories > b.calories) return -1;
+ if (a.calories < b.calories) return 1;
+ return 0;
+};
+
+class TableTest extends Component {
state = {
- selected: [],
- source: users
+ selected: ['Donut'],
+ sorted: 'asc'
};
- handleChange = (row, key, value) => {
- const source = this.state.source;
- source[row][key] = value;
- this.setState({source});
+ getSortedData = () => {
+ const compare = this.state.sorted === 'asc' ? sortByCaloriesAsc : sortByCaloriesDesc;
+ return data.sort(compare);
+ }
+
+ handleRowSelect = selected => {
+ const sortedData = this.getSortedData();
+ this.setState({ selected: selected.map(item => sortedData[item].name) });
};
- handleSelect = (selected) => {
- this.setState({selected});
+ handleSortClick = () => {
+ const { sorted } = this.state;
+ const nextSorting = sorted === 'asc' ? 'desc' : 'asc';
+ this.setState({ sorted: nextSorting });
};
render () {
+ const { sorted } = this.state;
+ const sortedData = this.getSortedData();
return (
Table
- Organized data.
-
+ Organized data.
+
+
+
+
+ Dessert (100g serving)
+
+ Calories
+ Fat (g)
+ Carbs (g)
+ Protein (g)
+ Sodium (mg)
+ Calcium (%)
+ Iron (%)
+
+ {sortedData.map((item, idx) => (
+
+ {item.name}
+ {item.calories}
+ {item.fat}
+ {item.carbs}
+ {item.protein}
+ {item.sodium}
+ {item.calcium}
+ {item.iron}
+
+ ))}
+
);
}
diff --git a/spec/components/tabs.js b/spec/components/tabs.js
index 0ce6018d..c4b85b6c 100644
--- a/spec/components/tabs.js
+++ b/spec/components/tabs.js
@@ -42,6 +42,8 @@ class TabsTest extends React.Component {
First Content
Second Content
Third Content
+ Fourth Content
+ Fifth Content
Inverse Tabs
These tabs have an inverted theme.
diff --git a/spec/index.html b/spec/index.html
index 61f5c7ab..3747b100 100644
--- a/spec/index.html
+++ b/spec/index.html
@@ -15,10 +15,8 @@
-
-