├── .gitignore ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE.txt ├── README.md ├── active_material.gemspec ├── app └── assets │ ├── javascripts │ ├── active_material.js │ └── active_material │ │ └── actions-toggle.js │ └── stylesheets │ ├── active_material.scss │ └── active_material │ ├── atoms │ ├── clearfix.scss │ ├── color.scss │ ├── family.scss │ ├── fill.scss │ ├── hidden.scss │ ├── links.scss │ ├── lists.scss │ ├── paper.scss │ └── type.scss │ ├── components │ ├── avatar.scss │ ├── blank_slate.scss │ ├── breadcrumbs.scss │ ├── buttons.scss │ ├── checkbox.scss │ ├── clearfix.scss │ ├── comments.scss │ ├── date-select.scss │ ├── datepicker.scss │ ├── dialog.scss │ ├── dropdown.scss │ ├── featured-blocks.scss │ ├── filter.scss │ ├── flash.scss │ ├── footer.scss │ ├── forms.scss │ ├── header.scss │ ├── hidden.scss │ ├── login.scss │ ├── overlay.scss │ ├── pagination.scss │ ├── panels.scss │ ├── photo_select.scss │ ├── scopes.scss │ ├── select.scss │ ├── sortable.scss │ ├── structure.scss │ ├── tables.scss │ ├── tabs.scss │ ├── tag.scss │ ├── title_bar.scss │ └── utility_nav.scss │ ├── generators │ ├── functions.scss │ └── mixins.scss │ ├── global │ ├── .sass-cache │ │ └── 1fcec96287fa9894a38a2c1051b448f8568d6277 │ │ │ └── foundation.scssc │ └── foundation.scss │ ├── prototypes │ ├── actions-footer.scss │ ├── avatar.scss │ ├── btn-icon.scss │ ├── button.scss │ ├── datepicker.scss │ ├── dialog.scss │ ├── menu.scss │ ├── multiselect.scss │ ├── select.scss │ ├── snackbar.scss │ ├── subheader.scss │ ├── table.scss │ ├── tabs.scss │ ├── tag.scss │ ├── textfield.scss │ ├── toolbar.scss │ └── underlay.scss │ └── values │ ├── breakpoints.scss │ ├── colors.scss │ ├── elevation.scss │ ├── fonts.scss │ └── units.scss ├── config └── importmap.rb ├── docs └── customization.md ├── lib ├── active_material.rb └── active_material │ ├── font_loader.rb │ └── version.rb └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | /.bundle/ 2 | /.yardoc 3 | /Gemfile.lock 4 | /_yardoc/ 5 | /coverage/ 6 | /doc/ 7 | /pkg/ 8 | /spec/reports/ 9 | /tmp/ 10 | *.bundle 11 | *.so 12 | *.o 13 | *.a 14 | mkmf.log 15 | *.gem 16 | node_modules 17 | yarn.lock 18 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # CHANGELOG 2 | 3 | ## 2.1.5 4 | 5 | - Add package.json entry-point, so non-importmap JS usage can just be `import "active_material";` 6 | - Update and improve docs 7 | 8 | ## 2.1.4 9 | 10 | - #103 - Fix dropdown menu 11 | 12 | ## 2.1.3 13 | 14 | - #102 - Resolve Darsass deprecation warnings 15 | 16 | ## 2.1.2 17 | 18 | - #100 - Avoid using ruby 3.1 methods to keep gem compatible with older ruby versions (thanks @alexeyschepin) 19 | 20 | ## 2.1.1 21 | 22 | - Update included files in gemspec 23 | 24 | ## 2.1.0 25 | 26 | - Convert JS from jquery to vanilla JS 27 | - Add support for importmap 28 | - Update SCSS to support dartsass-rails 29 | 30 | ## 2.0.3 31 | 32 | - #90: Wrap divisions in calc() - This fixes a deprecation in Dart Sass: https://sass-lang.com/documentation/breaking-changes/slash-div/ 33 | 34 | ## 2.0.2 35 | 36 | - Fix broken account menu icon 37 | 38 | ## 2.0.1 39 | 40 | - Removes dependency on globbing extension (#85) 41 | 42 | ## 2.0.0 43 | 44 | This activeadmin theme is entirely JS and CSS, and there is no custom ruby code. Therefore, since v2, active_material has been converted from a ruby gem to an npm/JS package. As part of this process, sprockets is also no longer supported. 45 | 46 | ### Breaking changes 47 | - Sprockets is no longer supported 48 | - The library is converted from ruby gem to npm/JS package 49 | 50 | ### Upgrading 51 | 52 | To upgrade from v1 to v2, follow these steps: 53 | 1. Follow the instructions in the readme for "installation" to add the npm/JS version 54 | 2. Remove references to active_material in `app/assets/stylesheets/active_admin.scss`. Any customizations should be moved over to wherever the new scss import is. 55 | 3. Remove references to active_material in `app/assets/javascripts/active_admin.js`. 56 | 4. Remove the `gem 'active_material'` from your Gemfile (and run `bundle install` to update Gemfile.lock) 57 | 58 | ## 1.4.1 59 | 60 | - Add `!default` flag to `$am-theme-error-400` color 61 | 62 | ## 1.4.0 63 | 64 | - Enhance dialog styles. These are viewable when conducting batch operations 65 | 66 | ## 1.3.1 67 | 68 | - Fix typo in active state of dropdown menu that caused batch actions 69 | to be invisible. 70 | 71 | ## 1.3.0 72 | 73 | - Added coverage for sortable table rows. 74 | - Moved icons to `active_material` folder to avoid conflicts. 75 | 76 | ## 1.2.0 77 | 78 | - Significant updates to fix datepicker styles and expose new 79 | configuration variables. 80 | - Webfonts are now configured by pulling in `active_material` in the 81 | JavaScript main entrypoint 82 | 83 | ### Upgrading 84 | 85 | Include `active_material` in the main JavaScript endpoint like: 86 | 87 | ``` 88 | //= require active_material 89 | ``` 90 | 91 | ## 1.1.0 92 | 93 | - Remove restrictive cascading list styles to prevent conflicts with rich text 94 | editors such as Redactor. 95 | 96 | ## 1.0.0 97 | 98 | This version includes several important structural changes to 99 | eliminate the possibility of rule collisions outside of ActiveMaterial 100 | and paves the way for future enhancements to the project. 101 | 102 | Release: 103 | https://github.com/dkniffin/active_material/releases/tag/v1.0.0 104 | 105 | ### Breaking Changes 106 | 107 | - The main stylesheet is now imported using `@import "active_material";` 108 | - All variables, functions, mixins, and rules are namespaced with `am-*`. 109 | - All pseudo-selectors (`%rule {}`) are now mixins. 110 | 111 | ### Upgrading 112 | 113 | #### Variables 114 | 115 | Projects using ActiveMaterial internal variables should consult the 116 | [API documentation's list of variable definitions](http://code.viget.com/active_material/docs/api/#undefined-variable). In 117 | almost all cases, the variable names have simply been prepended with 118 | `am-`. 119 | 120 | For example, `$theme-primary` is now `$am-theme-primary`. 121 | 122 | #### Pseudo Selectors 123 | 124 | Instead of relying upon `@extend`, components now utilize 125 | mixins. Projects that rely upon `@extend` to pull in ActiveMaterial 126 | styles should replace these lines with `@include am-*`, where `am-*` 127 | is the associated style chunks reimplemented as mixins. 128 | 129 | For example, `@extend %am-btn` is now `@include am-btn`. 130 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Thank you for considering a contribution to this project! 4 | 5 | ## Create an issue 6 | 7 | If you find an issue, or you'd like to request a new feature, [open a github issue](https://github.com/dkniffin/active_material/issues/new). 8 | 9 | ## Submit a pull request 10 | 11 | If you know how to make the change, please submit a pull request (PR). This makes it much easier to 12 | accept the change 13 | 14 | 1. Fork it ( https://github.com/[my-github-username]/active_material/fork ) 15 | 2. Create your feature branch (`git checkout -b my-new-feature`) 16 | 3. Commit your changes (`git commit -am "Add some feature"`) 17 | 4. Push to the branch (`git push origin my-new-feature`) 18 | 5. Create a new Pull Request 19 | 20 | In order for the PR to be merged, the test suite must pass, there must be no conflicts on the 21 | merge, and it must be merged by a maintainer. 22 | 23 | ## Issue and PR reviews 24 | 25 | Another way you can help is by reviewing issues, trying to reproduce bugs, and providing feedback on PRs. 26 | 27 | ## Pushing a new version 28 | 29 | First, you must be authorized on both rubygems.org and npmjs.com. Then: 30 | 31 | 1. Update the ruby gem: 32 | - Update the version in `lib/active_material/version.rb` 33 | - `gem build active_material.gemspec` 34 | - `gem push active_material-X.Y.Z.gem` 35 | 36 | 2. Update the npm package: 37 | - Update the version in `package.json` 38 | - `npm publish` 39 | 40 | 3. Update the changelog. 41 | 42 | 4. Commit and push changes 43 | 44 | 5. Tag the version in git: 45 | - `git tag -a X.Y.Z` 46 | - Add the same text as the changelog to the tag description 47 | - `git push origin X.Y.Z` 48 | 49 | 6. Create a new release in Github: https://github.com/dkniffin/active_material/releases 50 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 David Eisinger 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ActiveMaterial 2 | 3 | An ActiveAdmin skin based on Google's Material Design. 4 | 5 | 6 | 7 | ## Installation 8 | 9 | ### Importmap 10 | - Add `gem 'active_material'` to `Gemfile` and run `bundle install` 11 | 12 | NOTE: no need to pin the import in your application. That's handled internally by the gem. 13 | 14 | ### npm 15 | - `npm install --save active_material` or `yarn add active_material` 16 | 17 | ## Usage 18 | - Add `import "active_material"` to JS entrypoint (a JS file that is included for activeadmin) 19 | - Add `@use "active_material";` in your CSS style file 20 | - NOTE: the active_material SCSS files are included in the asset path automatically for importmap, but you will need to have SCSS build capabilities, using dartsass-rails or similar 21 | 22 | ## Customization 23 | For customization options, see [customization.md](./docs/customization.md) 24 | 25 | ## Contributing 26 | 27 | See [CONTRIBUTING.md](./CONTRIBUTING.md) 28 | -------------------------------------------------------------------------------- /active_material.gemspec: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | lib = File.expand_path('../lib', __FILE__) 3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 4 | require 'active_material/version' 5 | 6 | Gem::Specification.new do |spec| 7 | spec.name = "active_material" 8 | spec.version = ActiveMaterial::VERSION 9 | spec.authors = ["Derek Kniffin"] 10 | spec.email = ["derek.kniffin@gmail.com"] 11 | spec.summary = %q{ActiveAdmin skin based on Google's Material Design.} 12 | spec.description = %q{ActiveAdmin skin based on Google's Material Design.} 13 | spec.homepage = "" 14 | spec.license = "MIT" 15 | 16 | spec.files = Dir["{app,lib,config}/**/*", "LICENSE.txt", "package.json", "README.md"] 17 | spec.require_paths = ["lib"] 18 | 19 | spec.add_development_dependency "bundler", "~> 1.7" 20 | spec.add_development_dependency "rake", "~> 10.0" 21 | spec.add_development_dependency "sass-rails" 22 | end 23 | -------------------------------------------------------------------------------- /app/assets/javascripts/active_material.js: -------------------------------------------------------------------------------- 1 | 2 | import "./active_material/actions-toggle" 3 | 4 | document.querySelector('html').className += ' am-js' 5 | -------------------------------------------------------------------------------- /app/assets/javascripts/active_material/actions-toggle.js: -------------------------------------------------------------------------------- 1 | document.addEventListener("DOMContentLoaded", () => { 2 | const actions = document.querySelectorAll("tbody .col-actions") 3 | 4 | function waitForOutsideClick (el) { 5 | const body = document.querySelector("body") 6 | body.addEventListener("click", (e) => { 7 | if (el.contains(e.currentTarget) === false) { 8 | el.classList.remove('active') 9 | } 10 | }) 11 | } 12 | 13 | actions.forEach((action) => { 14 | // Make actions focusable 15 | action.setAttribute('tabindex', 0) 16 | action.setAttribute('role', 'button') 17 | 18 | action.addEventListener('click', () => { 19 | action.classList.add('active'); 20 | waitForOutsideClick(action); 21 | }) 22 | 23 | action.addEventListener('keydown', (e) => { 24 | const space = 32; 25 | const enter = 13; 26 | const escape = 27; 27 | 28 | if (e.keyCode == space || e.keyCode == enter) { 29 | e.preventDefault() 30 | action.classList.add('active') 31 | waitForOutsideClick(action) 32 | } else if (e.keyCode == escape) { 33 | e.preventDefault() 34 | action.classList.remove('active') 35 | } 36 | }) 37 | }) 38 | }) 39 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material.scss: -------------------------------------------------------------------------------- 1 | //// 2 | /// Active Material 3 | /// A redesign of ActiveAdmin that follows Material Design standards 4 | /// www.google.com/design/spec/material-design/introduction.html 5 | /// @author Derek Kniffin 6 | //// 7 | 8 | /// $variables, these should always end with !default 9 | /// so that they can be overriden 10 | @import "active_material/values/colors"; 11 | @import "active_material/values/units"; 12 | @import "active_material/values/fonts"; 13 | @import "active_material/values/breakpoints"; 14 | @import "active_material/values/elevation"; 15 | 16 | /// Generators describe functions, mixins, and classes 17 | /// intended for extension. More or less, they are "style builders" 18 | /// instead of "style descriptors" 19 | @import "active_material/generators/functions"; 20 | @import "active_material/generators/mixins"; 21 | 22 | /// Atoms are individual styles to enhance reusability 23 | @import "active_material/atoms/clearfix"; 24 | @import "active_material/atoms/color"; 25 | @import "active_material/atoms/family"; 26 | @import "active_material/atoms/fill"; 27 | @import "active_material/atoms/hidden"; 28 | @import "active_material/atoms/links"; 29 | @import "active_material/atoms/lists"; 30 | @import "active_material/atoms/paper"; 31 | @import "active_material/atoms/type"; 32 | 33 | /// Foundational rules that setup the page 34 | @import "active_material/global/foundation"; 35 | 36 | /// Prototypes are collections of mixins that allow for css design 37 | /// without the constraints of limiting ActiveAdmin selectors 38 | @import "active_material/prototypes/actions-footer"; 39 | @import "active_material/prototypes/avatar"; 40 | @import "active_material/prototypes/btn-icon"; 41 | @import "active_material/prototypes/button"; 42 | @import "active_material/prototypes/datepicker"; 43 | @import "active_material/prototypes/dialog"; 44 | @import "active_material/prototypes/menu"; 45 | @import "active_material/prototypes/multiselect"; 46 | @import "active_material/prototypes/select"; 47 | @import "active_material/prototypes/snackbar"; 48 | @import "active_material/prototypes/subheader"; 49 | @import "active_material/prototypes/table"; 50 | @import "active_material/prototypes/tabs"; 51 | @import "active_material/prototypes/tag"; 52 | @import "active_material/prototypes/textfield"; 53 | @import "active_material/prototypes/toolbar"; 54 | @import "active_material/prototypes/underlay"; 55 | 56 | /// Components describe actual implementation within Active Admin 57 | @import "active_material/components/avatar"; 58 | @import "active_material/components/blank_slate"; 59 | @import "active_material/components/breadcrumbs"; 60 | @import "active_material/components/buttons"; 61 | @import "active_material/components/checkbox"; 62 | @import "active_material/components/clearfix"; 63 | @import "active_material/components/comments"; 64 | @import "active_material/components/date-select"; 65 | @import "active_material/components/datepicker"; 66 | @import "active_material/components/dialog"; 67 | @import "active_material/components/dropdown"; 68 | @import "active_material/components/featured-blocks"; 69 | @import "active_material/components/filter"; 70 | @import "active_material/components/flash"; 71 | @import "active_material/components/footer"; 72 | @import "active_material/components/forms"; 73 | @import "active_material/components/header"; 74 | @import "active_material/components/hidden"; 75 | @import "active_material/components/login"; 76 | @import "active_material/components/overlay"; 77 | @import "active_material/components/pagination"; 78 | @import "active_material/components/panels"; 79 | @import "active_material/components/photo_select"; 80 | @import "active_material/components/scopes"; 81 | @import "active_material/components/select"; 82 | @import "active_material/components/sortable"; 83 | @import "active_material/components/structure"; 84 | @import "active_material/components/tables"; 85 | @import "active_material/components/tabs"; 86 | @import "active_material/components/tag"; 87 | @import "active_material/components/title_bar"; 88 | @import "active_material/components/utility_nav"; 89 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/atoms/clearfix.scss: -------------------------------------------------------------------------------- 1 | /// Injects standard clearfix rules 2 | @mixin am-clearfix { 3 | *zoom: 1; 4 | 5 | &:before, 6 | &:after { 7 | content: " "; 8 | display: table; 9 | } 10 | 11 | &:after { 12 | clear: both; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/atoms/color.scss: -------------------------------------------------------------------------------- 1 | /// Injects a color property given a key within $am-color. 2 | /// @param {any} $key - A key within $am-color 3 | @mixin am-color($key) { 4 | color: am-color($key); 5 | } 6 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/atoms/family.scss: -------------------------------------------------------------------------------- 1 | /// Injects a font-family property given a key within $am-font-family. 2 | /// @param {any} $key - A key within $am-font-family 3 | @mixin am-font-family($key) { 4 | font-family: am-font-family($key) 5 | } 6 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/atoms/fill.scss: -------------------------------------------------------------------------------- 1 | /// Injects a background-color property given a key within $am-color. 2 | /// @param {any} $key - A key within $am-color 3 | @mixin am-fill($key) { 4 | background-color: am-color($key); 5 | } 6 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/atoms/hidden.scss: -------------------------------------------------------------------------------- 1 | /// Injects rules to visually hide an element 2 | @mixin am-hidden { 3 | clip: rect(0, 0, 0, 0) !important; 4 | position: absolute !important; 5 | } 6 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/atoms/links.scss: -------------------------------------------------------------------------------- 1 | /// Assigns a color rule and rules to adjust color to the 2 | /// accent color upon hover/focus 3 | /// 4 | /// @param {any} $initial - A color key for the initial text color 5 | /// @param {any} $focus - A color key for the focus/hover text color 6 | @mixin am-link($initial:text, $focus:accent) { 7 | @include am-color($initial); 8 | 9 | &:hover, 10 | &:focus { 11 | @include am-color($focus); 12 | } 13 | } 14 | 15 | /// Strips away text decoration, applying an underline on hover/focus 16 | @mixin am-link-no-decoration { 17 | text-decoration: none; 18 | 19 | &:hover, 20 | &:focus { 21 | text-decoration: none; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/atoms/lists.scss: -------------------------------------------------------------------------------- 1 | /// Nullify default list rules 2 | @mixin am-list-blank { 3 | list-style: none; 4 | margin: 0; 5 | padding: 0; 6 | } 7 | 8 | /// Inject a rule for child
  • tags to use inline-block. 9 | @mixin am-list-inline { 10 | li { 11 | display: inline-block; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/atoms/paper.scss: -------------------------------------------------------------------------------- 1 | /// Inject rules for generic, elevated surfaces. This is used for 2 | /// elements that overlap other content, such as panels and sidebars. 3 | @mixin am-paper { 4 | @include am-fill(paper); 5 | border-radius: 2px; 6 | box-shadow: 0 1px 2px rgba(#000, 0.24), 0 0 2px rgba(#000, 0.15); 7 | } 8 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/atoms/type.scss: -------------------------------------------------------------------------------- 1 | /// Type Atoms 2 | /// 3 | /// Mixins for manipulation of typography. These styles mirror the 4 | /// Material Design standard 5 | /// 6 | /// https://www.google.com/design/spec/style/typography.html 7 | 8 | /// Applies rules for subheader text. 9 | @mixin am-type-subheader { 10 | @include am-font-size(16px); 11 | font-weight: $am-font-weight-regular; 12 | line-height: am-sp(24px); 13 | letter-spacing: am-tracking(10); 14 | } 15 | 16 | /// Applies rules for heavier, more emphasized, body text. 17 | @mixin am-type-body-2 { 18 | @include am-font-size(14px); 19 | font-weight: $am-font-weight-semi-bold; 20 | line-height: am-sp(24px); 21 | letter-spacing: am-tracking(10); 22 | } 23 | 24 | /// Applies rules for standard body text. 25 | @mixin am-type-body-1 { 26 | @include am-font-size(14px); 27 | font-weight: $am-font-weight-regular; 28 | line-height: am-sp(20px); 29 | letter-spacing: am-tracking(10); 30 | } 31 | 32 | /// Applies rules for caption text. 33 | @mixin am-type-caption { 34 | @include am-font-size(12px); 35 | font-style: normal; 36 | font-weight: $am-font-weight-medium; 37 | letter-spacing: am-tracking(20); 38 | line-height: am-sp(12px); 39 | } 40 | 41 | /// Applies rules for button text. 42 | @mixin am-type-btn { 43 | @include am-font-size(14px); 44 | font-weight: $am-font-weight-medium; 45 | letter-spacing: am-tracking(10); 46 | line-height: am-sp(12px); 47 | text-transform: uppercase; 48 | } 49 | 50 | /// Applies rules for smooth text anti-aliasing. 51 | @mixin am-type-smooth { 52 | -moz-osx-font-smoothing: grayscale; 53 | -webkit-font-smoothing: antialiased; 54 | } 55 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/components/avatar.scss: -------------------------------------------------------------------------------- 1 | .avatar { 2 | @include am-avatar; 3 | } 4 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/components/blank_slate.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Blank Slate 3 | * This element appears whenever a resource can not display 4 | * any information. For example, the default homescreen. 5 | */ 6 | 7 | .blank_slate_container { 8 | @include am-color(tertiary-text); 9 | @include am-type-body-1; 10 | @include am-type-smooth; 11 | font-weight: $am-font-weight-semi-bold; 12 | padding: am-unit(3) am-unit(2); 13 | text-align: center; 14 | } 15 | 16 | .blank_slate { 17 | border: 1px dashed rgba(#000, 0.2); 18 | border-radius: 3px; 19 | display: inline-block; 20 | padding: 16px 24px; 21 | 22 | small { 23 | display: block; 24 | margin-top: am-unit(1); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/components/breadcrumbs.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Breadcrumbs 3 | * Appear above the title to help users return to previous 4 | * steps in their flow. 5 | */ 6 | 7 | .breadcrumb { 8 | @include am-type-caption; 9 | display: block; 10 | margin-bottom: am-unit(1); 11 | } 12 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/components/buttons.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Buttons 3 | * Various selectors for button like elements 4 | */ 5 | 6 | .clear_filters_btn { 7 | @include am-btn; 8 | } 9 | 10 | .button, 11 | .cancel > a { 12 | @include am-btn; 13 | } 14 | 15 | input[type="submit"], 16 | input[type="reset"], 17 | input[type="button"] { 18 | @include am-btn; 19 | @include am-btn-raised; 20 | } 21 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/components/checkbox.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Checkboxes 3 | * Inputs given the "boolean" class. They have been seperated 4 | * from general form styles because of some hairy nesting. 5 | */ 6 | 7 | .input.boolean { 8 | 9 | > label { 10 | font-size: 14px; 11 | } 12 | 13 | > label > input { 14 | display: inline-block; 15 | margin-right: am-unit(1); 16 | position: relative; 17 | top: -1px; 18 | width: auto; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/components/clearfix.scss: -------------------------------------------------------------------------------- 1 | .clearfix { 2 | @include am-clearfix; 3 | } 4 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/components/comments.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Comments 3 | * Active Admin comments 4 | */ 5 | 6 | div.active_admin_comment { 7 | margin: 0 16px; 8 | 9 | & + & { 10 | border-top: 1px solid am-color(divider); 11 | padding-top: am-unit(2); 12 | } 13 | } 14 | 15 | .active_admin_comment_meta { 16 | @include am-color(secondary-text); 17 | @include am-type-caption; 18 | } 19 | 20 | .comments { 21 | .pagination_information { 22 | margin: 16px; 23 | } 24 | 25 | .empty { 26 | margin: 16px; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/components/date-select.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Date Selects 3 | */ 4 | 5 | .date_select, 6 | .datetime_select, 7 | .time_select { 8 | 9 | .fragments-group { 10 | @include am-list-blank; 11 | @include am-list-inline; 12 | @include am-select; 13 | } 14 | 15 | .fragment { 16 | @include am-select-unit; 17 | 18 | select { 19 | @include am-select-input-borderless; 20 | } 21 | } 22 | 23 | .fragment label { 24 | @include am-hidden; 25 | } 26 | 27 | .fragment select { 28 | @include am-select-input; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/components/datepicker.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Datepicker 3 | * An input with a dropdown calendar that appears on focus 4 | */ 5 | 6 | .ui-datepicker { 7 | @include am-datepicker; 8 | } 9 | 10 | .ui-datepicker-header { 11 | @include am-datepicker-header; 12 | 13 | .ui-icon { 14 | @include am-hidden; 15 | } 16 | } 17 | 18 | .ui-datepicker-title { 19 | @include am-datepicker-title; 20 | } 21 | 22 | .ui-datepicker-prev { 23 | @include am-datepicker-prev; 24 | } 25 | 26 | .ui-datepicker-next { 27 | @include am-datepicker-next; 28 | } 29 | 30 | .ui-datepicker-calendar { 31 | @include am-datepicker-calendar; 32 | 33 | th { 34 | @include am-datepicker-calendar-heading; 35 | } 36 | 37 | td { 38 | @include am-datepicker-calendar-day; 39 | } 40 | 41 | a { 42 | @include am-datepicker-calendar-day-link; 43 | 44 | &.ui-state-active, 45 | &:hover, 46 | &:focus { 47 | @include am-datepicker-calendar-day-link-focus 48 | } 49 | 50 | &.ui-state-highlight { 51 | @include am-datepicker-calendar-day-link-current; 52 | } 53 | } 54 | } 55 | 56 | .ui-datepicker-unselectable { 57 | @include am-datepicker-calendar-day-disabled; 58 | } 59 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/components/dialog.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Dialog 3 | * A full page takeover action panel 4 | */ 5 | 6 | .ui-dialog { 7 | @include am-dialog; 8 | } 9 | 10 | .ui-dialog-toolbar { 11 | @include am-toolbar; 12 | } 13 | 14 | .ui-dialog-title { 15 | @include am-dialog-title; 16 | } 17 | 18 | .ui-dialog-content { 19 | display: inline; 20 | 21 | ul { 22 | margin: 0; 23 | } 24 | } 25 | 26 | .ui-dialog-buttonset { 27 | @include am-dialog-footer; 28 | } 29 | 30 | .ui-button { 31 | @include am-btn; 32 | @include am-link(primary, text); 33 | } 34 | 35 | .ui-dialog-titlebar-close { 36 | @include am-dialog-close; 37 | } 38 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/components/dropdown.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Dropdowns 3 | */ 4 | 5 | .dropdown_menu { 6 | @include am-menu; 7 | } 8 | 9 | .dropdown_menu_button { 10 | @include am-menu-button; 11 | 12 | &:after { 13 | @include am-menu-carat; 14 | } 15 | 16 | &.disabled { 17 | @include am-btn-disabled; 18 | } 19 | } 20 | 21 | .dropdown_menu_list { 22 | @include am-menu-list; 23 | @include am-menu-list-open; 24 | 25 | li { 26 | @include am-menu-item; 27 | } 28 | 29 | li a { 30 | @include am-menu-link; 31 | 32 | & { 33 | @include am-menu-item-open; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/components/featured-blocks.scss: -------------------------------------------------------------------------------- 1 | .featured-blocks-message { 2 | display: block; 3 | padding: 0 am-unit(2) am-unit(2); 4 | } 5 | 6 | .new-featured-block { 7 | @include am-actions-footer; 8 | 9 | .button { 10 | @include am-btn-raised; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/components/filter.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Filters 3 | * Filters show up as sidebars on most index pages 4 | */ 5 | 6 | .filter_form_field, 7 | .select_and_search, 8 | .filter_date_range { 9 | @include am-textfield; 10 | @include am-textfield-inline; 11 | 12 | label { 13 | @include am-textfield-label; 14 | @include am-textfield-label-inline; 15 | } 16 | 17 | > select:not([multiple]) { 18 | @include am-select-input; 19 | border-bottom-right-radius: 0; 20 | border-top-right-radius: 0; 21 | flex-basis: 100px; 22 | } 23 | 24 | > select[multiple] { 25 | flex-basis: 100%; 26 | } 27 | 28 | > select { 29 | &:last-child { 30 | border-bottom-right-radius: 3px; 31 | border-top-right-radius: 3px; 32 | } 33 | 34 | + input[type="text"], 35 | + input[type="number"] { 36 | border-bottom-left-radius: 0; 37 | border-top-left-radius: 0; 38 | border-left: 0; 39 | } 40 | } 41 | 42 | > input.datepicker { 43 | @include am-textfield-input; 44 | @include am-textfield-input-inline; 45 | @include am-textfield-input-date; 46 | border-bottom-right-radius: 0; 47 | border-top-right-radius: 0; 48 | } 49 | 50 | > input[type="submit"] { 51 | border-bottom-left-radius: 0; 52 | border-top-left-radius: 0; 53 | margin: 0; 54 | } 55 | } 56 | 57 | .filter_string input, 58 | .filter_numeric input { 59 | @include am-textfield-input; 60 | @include am-textfield-input-inline; 61 | } 62 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/components/flash.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Flash 3 | * Notifications that appear whenever a CRUD action or error 4 | * has surfaced 5 | */ 6 | 7 | .flash { 8 | @include am-snackbar; 9 | 10 | &.flash_alert { 11 | @include am-snackbar-error; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/components/footer.scss: -------------------------------------------------------------------------------- 1 | .footer { 2 | padding: am-unit(2); 3 | text-align: center; 4 | } 5 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/components/forms.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Forms 3 | */ 4 | 5 | fieldset.inputs { 6 | margin-bottom: am-unit(2); 7 | 8 | > ol { 9 | @include am-list-blank; 10 | } 11 | 12 | > legend { 13 | @include am-subheader; 14 | border: 0; 15 | } 16 | } 17 | 18 | .input { 19 | @include am-textfield; 20 | 21 | > label, 22 | .label > label { 23 | @include am-textfield-label; 24 | } 25 | 26 | &.string input, 27 | &.stringish input, 28 | &.numeric input { 29 | @include am-textfield-input; 30 | 31 | &[disabled="disabled"] { 32 | @include am-textfield-input-disabled; 33 | } 34 | } 35 | 36 | &.email input { 37 | @include am-textfield-input-email; 38 | 39 | &[disabled="disabled"] { 40 | @include am-textfield-input-disabled; 41 | } 42 | } 43 | 44 | &.password input { 45 | @include am-textfield-input-password; 46 | 47 | &[disabled="disabled"] { 48 | @include am-textfield-input-disabled; 49 | } 50 | } 51 | 52 | &.datepicker input { 53 | @include am-textfield-input-date; 54 | 55 | &[disabled="disabled"] { 56 | @include am-textfield-input-disabled; 57 | } 58 | } 59 | 60 | &.text textarea { 61 | @include am-textfield-input; 62 | @include am-textfield-textarea; 63 | 64 | &[disabled="disabled"] { 65 | @include am-textfield-input-disabled; 66 | } 67 | } 68 | 69 | select + input { 70 | margin-top: am-unit(2); 71 | } 72 | } 73 | 74 | .field_with_errors input { 75 | @include am-textfield-input-error; 76 | } 77 | 78 | .inline-hints { 79 | @include am-textfield-hint; 80 | } 81 | 82 | .inline-errors { 83 | @include am-textfield-hint; 84 | @include am-textfield-hint-error; 85 | 86 | + .inline-hints { 87 | display: none; 88 | } 89 | } 90 | 91 | abbr[title="required"] { 92 | @include am-textfield-required; 93 | } 94 | 95 | fieldset.actions, 96 | .buttons { 97 | @include am-actions-footer; 98 | 99 | > ol { 100 | @include am-list-blank; 101 | @include am-list-inline; 102 | } 103 | 104 | .cancel a { 105 | @include am-btn-raised; 106 | } 107 | 108 | .cancel a { 109 | @include am-btn; 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/components/header.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Header 3 | * Encapsulates several elements related to navigation at 4 | * the top of the page. 5 | */ 6 | 7 | #header { 8 | @include am-toolbar; 9 | @include am-toolbar-primary; 10 | padding-right: am-unit(8); 11 | } 12 | 13 | .site_title { 14 | text-shadow: 0 1px 2px rgba(#000, 0.15); 15 | 16 | @include am-color(text-light); 17 | @include am-toolbar-title; 18 | } 19 | 20 | #tabs { 21 | flex-grow: 1; 22 | } 23 | 24 | .header-item { 25 | @include am-toolbar-list; 26 | } 27 | 28 | .header-item > li { 29 | @include am-toolbar-item; 30 | 31 | > a { 32 | @include am-toolbar-item-primary; 33 | text-shadow: 0 1px 2px rgba(black, 0.15); 34 | } 35 | 36 | &.current > a { 37 | @include am-toolbar-item-primary-active; 38 | } 39 | } 40 | 41 | .has_nested { 42 | @include am-menu; 43 | 44 | ul { 45 | @include am-menu-list; 46 | 47 | li { 48 | @include am-menu-item; 49 | } 50 | 51 | li a { 52 | @include am-menu-link; 53 | } 54 | } 55 | 56 | &:hover ul, 57 | &:focus ul { 58 | @include am-menu-list-open; 59 | 60 | li a { 61 | @include am-menu-item-open 62 | } 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/components/hidden.scss: -------------------------------------------------------------------------------- 1 | .hidden { 2 | @include am-hidden; 3 | } 4 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/components/login.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Login 3 | * This screen appears if no session is active 4 | */ 5 | 6 | #login { 7 | @include am-dialog; 8 | margin: am-unit(-4) auto 0; 9 | max-width: am-unit(50); 10 | 11 | h2 { 12 | @include am-hidden; 13 | } 14 | 15 | // This is the "forgot password" button 16 | > a { 17 | @include am-actions-footer; 18 | border-bottom-left-radius: 3px; 19 | border-bottom-right-radius: 3px; 20 | } 21 | 22 | // Annoying br included for whatever reason 23 | > br { 24 | display: none; 25 | } 26 | 27 | .inputs { 28 | margin-bottom: 0; 29 | } 30 | 31 | // Override actions, in this case the border and shadow are 32 | // not applicable 33 | .actions { 34 | background: transparent; 35 | box-shadow: none; 36 | padding-top: 0; 37 | box-shadow: none; 38 | 39 | .action, 40 | input[type='submit'] { 41 | margin: 0; 42 | width: 100%; 43 | } 44 | } 45 | } 46 | 47 | body.logged_out { 48 | @include am-fill(primary-700); 49 | background-size: cover; 50 | display: flex; 51 | flex-direction: column; 52 | justify-content: center; 53 | } 54 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/components/overlay.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Overlay 3 | * Overlays appear below modal content that takes up the entire screen. 4 | */ 5 | 6 | .ui-widget-overlay { 7 | @include am-underlay; 8 | } 9 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/components/pagination.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Pagination 3 | * Typically appears on index pages, below tables 4 | */ 5 | 6 | .paginated_collection { 7 | @include am-clearfix; 8 | clear: both; 9 | 10 | .pagination_information, 11 | .download_links, 12 | .pagination_per_page { 13 | @include am-type-caption; 14 | padding: am-unit(2); 15 | } 16 | 17 | .pagination_information, 18 | .pagination_per_page { 19 | float: left; 20 | } 21 | 22 | .pagination_information { 23 | clear: left; 24 | } 25 | 26 | .download_links { 27 | line-height: am-unit(3); 28 | float: right; 29 | text-align: right; 30 | } 31 | 32 | .pagination_per_page { 33 | border-bottom: 1px solid #efefef; 34 | padding: am-unit(1) am-unit(2); 35 | 36 | select { 37 | @include am-select-input; 38 | 39 | height: 34px; 40 | line-height: 30px; 41 | } 42 | } 43 | } 44 | 45 | 46 | .pagination { 47 | background: #fff; 48 | border-bottom: 1px solid #efefef; 49 | display: flex; 50 | justify-content: flex-end; 51 | padding: 0 am-unit(2); 52 | 53 | .page, 54 | .first, 55 | .prev, 56 | .next, 57 | .last { 58 | @include am-btn; 59 | min-width: am-unit(3); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/components/panels.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Panels 3 | * Stand-alone segments of content, in Material Design 4 | * these could be considered Cards or pieces of paper. 5 | */ 6 | 7 | .panel, 8 | .has_many_container, 9 | body.index #main_content, 10 | body.edit #main_content > form, 11 | body.new #main_content > form, 12 | body.create #main_content > form, 13 | body.update #main_content > form { 14 | @include am-paper; 15 | 16 | > h3 { 17 | @include am-subheader; 18 | } 19 | 20 | .header_action { 21 | float: right 22 | } 23 | 24 | .row th { 25 | width: 20%; 26 | padding-left: am-unit(2); 27 | } 28 | } 29 | 30 | .admin_dashboard #wrapper #main_content{ 31 | background-color: transparent; 32 | border-radius: 0; 33 | box-shadow: none; 34 | .columns{ 35 | display: flex; 36 | } 37 | } 38 | 39 | .panel { 40 | & + & { 41 | margin-top: 16px; 42 | } 43 | } 44 | 45 | .panel_well { 46 | padding: 0 am-unit(2) am-unit(2); 47 | } 48 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/components/photo_select.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * PhotoSelects 3 | */ 4 | 5 | .photo_select { 6 | display: inline-block; 7 | } 8 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/components/scopes.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Scopes 3 | * Theses appear above tables, providing the ability to filter rows 4 | */ 5 | 6 | .scopes { 7 | @include am-list-blank; 8 | @include am-list-inline; 9 | flex-grow: 1; 10 | text-align: right; 11 | } 12 | 13 | .scope { 14 | font-size: 13px; 15 | font-weight: $am-font-weight-medium; 16 | margin-left: am-unit(2); 17 | 18 | a { 19 | @include am-link(secondary-text); 20 | } 21 | 22 | &.selected { 23 | font-weight: bold; 24 | 25 | a { 26 | @include am-fill(primary); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/components/select.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Basic Selects 3 | */ 4 | 5 | .country, 6 | .select, 7 | .polymorphic_select { 8 | 9 | select:not([multiple]) { 10 | @include am-select-input; 11 | } 12 | 13 | select[disabled="disabled"] { 14 | @include am-select-input-disabled; 15 | } 16 | } 17 | 18 | select[multiple] { 19 | @include am-multiselect; 20 | 21 | option { 22 | @include am-multiselect-option; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/components/sortable.scss: -------------------------------------------------------------------------------- 1 | //// 2 | /// Sortable 3 | /// Generic styles for sortable elements. Leans on 4 | /// jQuery UI for the bulk of work 5 | /// @group sortable 6 | //// 7 | 8 | /// The icon displayed within a sortable element's drag handle 9 | $am-sortable-icon: url('data:image/svg+xml;utf8, ') !default; 10 | // The size of the draggable handle 11 | $am-sortable-handle-size: am-unit(7); 12 | 13 | .ui-sortable { 14 | 15 | .reorder-handle-col { 16 | padding: 0 0 0 am-unit(1); 17 | width: $am-sortable-handle-size; 18 | } 19 | 20 | .reorder-handle { 21 | background: transparent $am-sortable-icon 50% 50% no-repeat; 22 | color: transparent; 23 | cursor: move; 24 | display: block; 25 | height: $am-sortable-handle-size; 26 | margin: 0 auto; 27 | opacity: 0.40; 28 | transition: 0.2s all; 29 | width: $am-sortable-handle-size; 30 | 31 | &:hover { 32 | opacity: 1; 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/components/structure.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Structure 3 | * Global structural elements 4 | */ 5 | 6 | body { 7 | @include am-fill(backdrop); 8 | } 9 | 10 | #active_admin_content { 11 | padding: am-unit(3); 12 | } 13 | 14 | #sidebar { 15 | margin-left: am-unit(3); 16 | } 17 | 18 | .with_sidebar { 19 | display: flex; 20 | width: 100%; 21 | 22 | #main_content_wrapper { 23 | flex-grow: 1; 24 | } 25 | 26 | #sidebar { 27 | max-width: am-unit(40); 28 | width: 100%; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/components/tables.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Tables 3 | */ 4 | 5 | .table_tools { 6 | @include am-table-header; 7 | } 8 | 9 | .index_table, 10 | .panel_contents table { 11 | @include am-table; 12 | 13 | th { 14 | @include am-table-column-heading; 15 | 16 | a { 17 | @include am-table-sort; 18 | } 19 | 20 | &.sorted-asc a { 21 | @include am-table-sort-asc; 22 | } 23 | 24 | &.sorted-desc a { 25 | @include am-table-sort-desc; 26 | } 27 | } 28 | 29 | tr { 30 | @include am-table-row; 31 | } 32 | 33 | tbody tr { 34 | &:hover { 35 | @include am-table-row-hover; 36 | } 37 | 38 | &.selected { 39 | @include am-table-row-selected; 40 | } 41 | } 42 | 43 | td { 44 | @include am-table-cell; 45 | 46 | } 47 | 48 | .col-selectable { 49 | @include am-table-cell-selectable; 50 | 51 | // ActiveAdmin wraps checkboxes in a div. This rule prevents 52 | // that div from messing up vertical alignment 53 | .resource_selection_cell { 54 | display: inline; 55 | } 56 | } 57 | 58 | // Styles for non-js actions 59 | td.col-actions a { 60 | padding: 0 4px 61 | } 62 | 63 | .am-js & { 64 | 65 | td.col-actions { 66 | @include am-table-cell-actions; 67 | 68 | .table_actions { 69 | @include am-menu-list; 70 | @include am-menu-list-right; 71 | top: 50%; 72 | margin-top: am-unit(-2); 73 | margin-right: am-unit(2); 74 | 75 | a { 76 | @include am-menu-link; 77 | } 78 | } 79 | 80 | &:hover, 81 | &.active { 82 | .table_actions { 83 | @include am-menu-list-open; 84 | 85 | a { 86 | @include am-menu-item-open; 87 | } 88 | } 89 | } 90 | 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/components/tabs.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Tabs 3 | * Theses show up on complicated forms, such as the Exhibit edit page. 4 | */ 5 | 6 | .nav-tabs { 7 | @include am-tabs; 8 | @include am-tabs-list; 9 | 10 | > li.ui-tabs-tab { 11 | @include am-tabs-list-item; 12 | } 13 | 14 | > li.ui-tabs-tab > a { 15 | @include am-tabs-btn; 16 | } 17 | 18 | > li.ui-state-active > a { 19 | @include am-tabs-btn-active; 20 | } 21 | 22 | > li.tab_with_errors > a { 23 | @include am-tabs-btn-error; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/components/tag.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Tags 3 | * Tags show up as states within tables and other components 4 | */ 5 | 6 | .status_tag { 7 | @include am-tag; 8 | 9 | a & { 10 | @include am-tag-pressable; 11 | } 12 | 13 | &.yes { 14 | @include am-tag-success; 15 | } 16 | } 17 | 18 | .empty { 19 | color: #ccc; 20 | font-size: 0.9em; 21 | letter-spacing: 2px; 22 | text-transform: uppercase; 23 | } 24 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/components/title_bar.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Titlebar 3 | */ 4 | 5 | .title_bar { 6 | box-shadow: 0 1px 2px rgba(#000, 0.24); 7 | align-items: center; 8 | display: flex; 9 | position: relative; 10 | z-index: 1; 11 | 12 | @include am-fill(white); 13 | @include am-toolbar-title; 14 | } 15 | 16 | #titlebar_left { 17 | flex-grow: 1; 18 | } 19 | 20 | #titlebar_right .action_item a { 21 | @include am-btn; 22 | } 23 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/components/utility_nav.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Utility Nav 3 | * Displays current user and logout information 4 | */ 5 | 6 | #utility_nav { 7 | background: url('data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJMYXllcl8xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCIgd2lkdGg9IjQ4cHgiIGhlaWdodD0iNDhweCIgdmlld0JveD0iMCAwIDQ4IDQ4IiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCA0OCA0OCIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+IDxwYXRoIGZpbGw9IiNGRkZGRkYiIGQ9Ik0yNCw0QzEyLjk1LDQsNCwxMi45NSw0LDI0czguOTUsMjAsMjAsMjBzMjAtOC45NSwyMC0yMFMzNS4wNSw0LDI0LDR6IE0yNCwxMGMzLjMxMSwwLDYsMi42OSw2LDYgYzAsMy4zMi0yLjY4OSw2LTYsNmMtMy4zMSwwLTYtMi42OC02LTZDMTgsMTIuNjksMjAuNjksMTAsMjQsMTB6IE0yNCwzOC40Yy01LjAxLDAtOS40MS0yLjU2MS0xMi02LjQ0YzAuMDUtMy45Nyw4LjAxLTYuMTYsMTItNi4xNiBzMTEuOTM5LDIuMTksMTIsNi4xNkMzMy40MSwzNS44NCwyOS4wMSwzOC40LDI0LDM4LjR6Ii8+IDwvc3ZnPg==') no-repeat; 8 | background-size: am-unit(5); 9 | width: am-unit(5); 10 | height: am-unit(5); 11 | margin-top: am-unit(-2.5); 12 | position: absolute; 13 | z-index: 2; 14 | top: 50%; 15 | right: am-unit(2); 16 | 17 | // Increase the hit region 18 | &:before { 19 | content: ""; 20 | cursor: pointer; 21 | position: absolute; 22 | width: 90px; 23 | height: 50px; 24 | top: 0; 25 | right: -12px; 26 | } 27 | 28 | a { 29 | color: #333; 30 | } 31 | 32 | > li { 33 | &:first-child { 34 | margin-top: 45px; 35 | 36 | &:before { 37 | content: ""; 38 | border: 7px solid transparent; 39 | border-bottom-color: #fff; 40 | top: -14px; 41 | right: 12px; 42 | position: absolute; 43 | } 44 | } 45 | 46 | border-top: 1px solid #d9d9d9; 47 | box-shadow: 0 1px 2px rgba(#000, 0.22); 48 | width: 200px; 49 | float: right; 50 | border-bottom-left-radius: 2px; 51 | border-bottom-right-radius: 2px; 52 | background: #efefef; 53 | text-align: right; 54 | clip: rect(0, 0, 0, 0); 55 | opacity: 0; 56 | visibility: hidden; 57 | transition: 0.28s all; 58 | position: relative; 59 | 60 | a { 61 | @include am-btn; 62 | } 63 | } 64 | 65 | #current_user { 66 | background: #fff; 67 | text-align: center; 68 | } 69 | 70 | &:hover { 71 | > li { 72 | clip: initial; 73 | opacity: 1; 74 | visibility: visible; 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/generators/functions.scss: -------------------------------------------------------------------------------- 1 | @use "sass:color"; 2 | @use "sass:map"; 3 | 4 | /// Emulates letter tracking in Adobe Photoshop, which is used for 5 | /// adjusting the space between letters in text. 6 | /// 7 | /// Follows the guidance of https://scotch.io/quick-tips/converting-photoshop-letter-spacing-to-css. 8 | /// 9 | /// @param {number} $amount - An integer value, such as 100 10 | /// @return {number} The amount of letter-spacing in ems. 11 | @function am-tracking($amount) { 12 | @return calc($amount / 1000) + 0em; 13 | } 14 | 15 | 16 | /// Calculates "scalable pixel" values. This is implemented using rems. 17 | /// Within material design, scalable pixel values are those that respect 18 | /// the user's font settings. 19 | /// 20 | /// According to the [Google Material Design Specification](https://www.google.com/design/spec/layout/units-measurements.html#units-measurements-scaleable-pixels-sp-): 21 | /// > "Users who have larger text settings for accessibility will see 22 | /// > the font size matched to their text size preferences." 23 | /// 24 | /// @param {number} $value - A pixel value to be converted into rems. 25 | /// @param {number} $baseline [16] - The assumed base font size. 26 | /// @return {number} Scalable pixel value in rems. 27 | @function am-sp($value, $baseline:16) { 28 | @return calc($value / $baseline) + rem; 29 | } 30 | 31 | 32 | /// Calculates measurements along the base unit grid defined under $am-unit-base. This provides 33 | /// an easy way to align elements upon a baseline mesh grid. 34 | /// 35 | /// @param {number} $step - The scale of units 36 | /// @return {number} A pixel value representing the number of units along the mesh grid. 37 | @function am-unit($step:1) { 38 | @return $am-unit-base * $step; 39 | } 40 | 41 | 42 | /// Calculates measurements along the base type grid defined under $am-unit-base. This provides 43 | /// an easy way to align elements upon a baseline typographic mesh grid. 44 | /// 45 | /// @param {number} $step - The scale of units 46 | /// @return {number} A pixel value representing the number of units along the typographic mesh grid. 47 | @function am-type-unit($step:1) { 48 | @return $am-unit-type * $step; 49 | } 50 | 51 | 52 | /// Extracts a color out of the $am-color map. Throws an error if that key is not defined. 53 | /// 54 | /// @param {any} $key - The desired key in $am-colors. 55 | /// @return {color} A color value from $am-colors. 56 | @function am-color ($key) { 57 | @if map.has-key($am-colors, $key) { 58 | @return map.get($am-colors, $key); 59 | } 60 | 61 | @error "Unknown color value '#{$key}'"; 62 | @return null; 63 | } 64 | 65 | 66 | /// Extracts a color out of the $am-color map and lightens it using the built-in Sass function. 67 | /// 68 | /// @param {any} $key - The desired key in $am-colors. 69 | /// @param {number} $amount - The degree of lightness. 70 | /// @return {color} A lightened color value from $am-colors. 71 | @function am-lighten ($color, $amount) { 72 | @return color.adjust(am-color($color), $lightness: $amount, $space: hsl); 73 | } 74 | 75 | 76 | /// Extracts a color out of the $am-color map and darkens it using the built-in Sass function. 77 | /// 78 | /// @param {any} $key - The desired key in $am-colors. 79 | /// @param {number} $amount - The degree of darkness. 80 | /// @return {color} A darkened color value from $am-colors. 81 | @function am-darken ($color, $amount) { 82 | @return color.adjust(am-color($color), $lightness: -$amount, $space: hsl); 83 | } 84 | 85 | /// Extracts a font family out of the $am-fonts map. Throws an error if that key is not defined. 86 | /// 87 | /// @param {any} $key - The desired key in $am-colors. 88 | /// @return {font} A font family from $am-colors. 89 | @function am-font-family ($key) { 90 | @if map.has-key($am-fonts, $key) { 91 | @return map.get($am-fonts, $key); 92 | } 93 | 94 | @error "Unknown font value '#{$key}'"; 95 | @return null; 96 | } 97 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/generators/mixins.scss: -------------------------------------------------------------------------------- 1 | /// Standard logic for management of breakpoints 2 | @mixin am-min-breakpoint($breakpoint) { 3 | @media screen and (min-width: $breakpoint) { 4 | @content; 5 | } 6 | } 7 | 8 | /// Assign a given font size in rems, falling back to pixel values 9 | /// in older browsers. 10 | /// @param {number} $size - Font size in pixels 11 | @mixin am-font-size($size) { 12 | font-size: $size; 13 | font-size: am-sp($size); 14 | } 15 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/global/.sass-cache/1fcec96287fa9894a38a2c1051b448f8568d6277/foundation.scssc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkniffin/active_material/96d2ec4abc0285fa3cf1d5a1b9265361c73b2545/app/assets/stylesheets/active_material/global/.sass-cache/1fcec96287fa9894a38a2c1051b448f8568d6277/foundation.scssc -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/global/foundation.scss: -------------------------------------------------------------------------------- 1 | html { 2 | box-sizing: border-box; 3 | } 4 | 5 | *, 6 | *:before, 7 | *:after { 8 | box-sizing: inherit; 9 | } 10 | 11 | ::selection { 12 | @include am-fill(accent); 13 | @include am-color(text-light); 14 | } 15 | 16 | html, 17 | body { 18 | height: 100%; 19 | } 20 | 21 | body { 22 | @include am-type-body-1; 23 | @include am-color(text); 24 | @include am-font-family(sans); 25 | margin: 0; 26 | } 27 | 28 | img { 29 | max-width: 100%; 30 | } 31 | 32 | b, 33 | strong { 34 | @include am-type-body-2; 35 | } 36 | 37 | h1, 38 | h2, 39 | h3, 40 | h4, 41 | h5, 42 | h6 { 43 | font: inherit; 44 | margin: 0; 45 | } 46 | 47 | p { 48 | margin: am-type-unit(3) 0; 49 | } 50 | 51 | button, 52 | input { 53 | @include am-font-family(sans); 54 | } 55 | 56 | button::-moz-focus-inner { 57 | padding: 0; 58 | border: 0 59 | } 60 | 61 | a { 62 | color: inherit; 63 | text-decoration: none; 64 | transition: 0.3s color; 65 | 66 | &:link, 67 | &:visited { 68 | @include am-color(primary); 69 | 70 | &:hover { 71 | text-decoration: underline; 72 | } 73 | } 74 | 75 | &:hover, 76 | &:focus { 77 | @include am-color(accent-hover); 78 | transition: 0.1s color; 79 | } 80 | 81 | &:active { 82 | @include am-color(accent-active); 83 | transition: 0.1s color; 84 | } 85 | } 86 | 87 | blockquote { 88 | border-left: 4px solid am-color(hint); 89 | margin: am-type-unit(4) 0; 90 | padding: am-type-unit(4); 91 | } 92 | 93 | hr { 94 | border: 0; 95 | border-bottom: 1px solid am-color(divider); 96 | margin: am-unit(4) 0 97 | } 98 | 99 | fieldset { 100 | border: 0; 101 | margin: 0; 102 | padding: 0; 103 | } 104 | 105 | hr { 106 | margin: 0; 107 | } 108 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/prototypes/actions-footer.scss: -------------------------------------------------------------------------------- 1 | @mixin am-actions-footer { 2 | background: #fefefe; 3 | border-bottom-left-radius: 2px; 4 | border-bottom-right-radius: 2px; 5 | box-shadow: inset 0 1px 1px rgba(#000, 0.2); 6 | display: block; 7 | padding: am-unit(2); 8 | } 9 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/prototypes/avatar.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Avatar 3 | * A circular image 4 | */ 5 | 6 | @import '../values/colors'; 7 | 8 | $am-avatar-background: am-color(icon) !default; 9 | $am-avatar-box-shadow: 0 1px 2px rgba(#000, 0.2) !default; 10 | $am-avatar-border-radius: 50% !default; 11 | $am-avatar-block-level: block !default; 12 | 13 | @mixin am-avatar { 14 | background: $am-avatar-background; 15 | border-radius: $am-avatar-border-radius; 16 | box-shadow: $am-avatar-box-shadow; 17 | color: transparent; 18 | display: $am-avatar-block-level; 19 | } 20 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/prototypes/btn-icon.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Button Icon 3 | * A simple, reusable icon button 4 | */ 5 | 6 | @mixin am-btn-icon { 7 | border-radius: 50%; 8 | height: 40px; 9 | overflow: hidden; 10 | padding: 0; 11 | text-indent: 100%; 12 | white-space: nowrap; 13 | width: 40px; 14 | } 15 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/prototypes/button.scss: -------------------------------------------------------------------------------- 1 | $am-btn-min-width: 88px !default; 2 | $am-btn-padding: 12px 8px !default; 3 | $am-btn-border-radius: 2px !default; 4 | $am-btn-focus-color: rgba(#999, 0.2) !default; 5 | $am-btn-active-color: rgba(#999, 0.4) !default; 6 | 7 | @mixin am-btn { 8 | @include am-type-btn; 9 | @include am-color(text); 10 | background: transparent; 11 | border-radius: $am-btn-border-radius; 12 | border: 0; 13 | cursor: pointer; 14 | display: inline-block; 15 | line-height: 18px; 16 | margin: 4px; 17 | padding: $am-btn-padding; 18 | position: relative; 19 | text-align: center; 20 | text-transform: uppercase; 21 | transition: 0.25s all; 22 | user-select: none; 23 | vertical-align: middle; 24 | 25 | &:focus { 26 | outline: none; 27 | } 28 | 29 | &:hover { 30 | @include am-color(primary); 31 | text-decoration: none; 32 | } 33 | } 34 | 35 | @mixin am-btn-raised { 36 | @include am-type-smooth; 37 | @include am-fill(primary); 38 | @include am-color(white); 39 | box-shadow: 0 0 2px rgba(#000, 0.12); 40 | font-weight: $am-font-weight-semi-bold; 41 | min-width: $am-btn-min-width; 42 | 43 | &:focus, 44 | &:hover { 45 | @include am-color(text-light); 46 | background: am-lighten(primary, 10%); 47 | outline: none; 48 | } 49 | 50 | &:active { 51 | background: am-lighten(primary, 5%); 52 | box-shadow: inset 0 1px 0 rgba(#fff, 0.2); 53 | } 54 | } 55 | 56 | @mixin am-btn-disabled { 57 | opacity: 0.4; 58 | } 59 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/prototypes/datepicker.scss: -------------------------------------------------------------------------------- 1 | //// 2 | /// Datepicker 3 | /// A calendar widget 4 | /// @group datepicker 5 | //// 6 | 7 | /// The width of the datepicker. 8 | $am-datepicker-width: am-unit(35) !default; 9 | /// The shadow cast below the datepicker. 10 | $am-datepicker-shadow: (0 1px 2px rgba(#000, 0.25), 0 -1px 1px rgba(#000, 0.12)) !default; 11 | /// The border radius of the picker. 12 | $am-datepicker-border-radius: 2px !default; 13 | /// The size of an individual cell in the calendar. Square. 14 | $am-datepicker-cell-size: am-unit(4) !default; 15 | 16 | @mixin am-datepicker { 17 | background: white; 18 | border-radius: $am-datepicker-border-radius; 19 | box-shadow: $am-datepicker-shadow; 20 | display: none; 21 | padding: 0 am-unit(1.5) am-unit(1); 22 | width: $am-datepicker-width; 23 | } 24 | 25 | @mixin am-datepicker-header { 26 | line-height: $am-datepicker-cell-size; 27 | padding: am-unit(1) 0 am-unit(0.5); 28 | position: relative; 29 | text-align: center; 30 | } 31 | 32 | @mixin am-datepicker-title { 33 | @include am-font-size(14px); 34 | font-weight: $am-font-weight-semi-bold; 35 | } 36 | 37 | @mixin am-datepicker-icon { 38 | &:before { 39 | @include am-font-size(am-unit(2)); 40 | display: inline-block; 41 | height: $am-datepicker-cell-size; 42 | width: $am-datepicker-cell-size; 43 | } 44 | } 45 | 46 | @mixin am-datepicker-prev { 47 | cursor: pointer; 48 | float: left; 49 | 50 | &:before { 51 | @include am-datepicker-icon; 52 | content: "‹"; 53 | } 54 | } 55 | 56 | @mixin am-datepicker-next { 57 | cursor: pointer; 58 | float: right; 59 | 60 | &:before { 61 | @include am-datepicker-icon; 62 | content: "›"; 63 | } 64 | } 65 | 66 | @mixin am-datepicker-calendar { 67 | @include am-font-size(12px); 68 | border-collapse: collapse; 69 | text-align: center; 70 | width: 100%; 71 | } 72 | 73 | @mixin am-datepicker-calendar-heading { 74 | @include am-color(secondary-text); 75 | font-weight: $am-font-weight-medium; 76 | padding: 0 0 am-type-unit(1); 77 | } 78 | 79 | @mixin am-datepicker-calendar-day { 80 | height: $am-datepicker-cell-size; 81 | font-weight: $am-font-weight-medium; 82 | line-height: $am-datepicker-cell-size; 83 | padding: 0; 84 | width: $am-datepicker-cell-size; 85 | } 86 | 87 | @mixin am-datepicker-calendar-day-disabled { 88 | opacity: 0; 89 | } 90 | 91 | @mixin am-datepicker-calendar-day-link { 92 | @include am-link(text); 93 | border-radius: 50%; 94 | display: block; 95 | height: inherit; 96 | margin: 0 auto; 97 | width: inherit; 98 | } 99 | 100 | @mixin am-datepicker-calendar-day-link-focus { 101 | @include am-color(primary); 102 | text-decoration: none; 103 | } 104 | 105 | @mixin am-datepicker-calendar-day-link-current { 106 | @include am-fill(primary); 107 | @include am-color(white); 108 | } 109 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/prototypes/dialog.scss: -------------------------------------------------------------------------------- 1 | //// 2 | /// Dialog 3 | /// A modal that appears above all other content 4 | /// @group dialog 5 | //// 6 | 7 | // Dialog background color 8 | $am-dialog-background: #fff !default; 9 | // Dialog container border-radius 10 | $am-dialog-border-radius: 2px !default; 11 | // Dialog title padding 12 | $am-dialog-title-padding: am-unit(4) am-unit(3) am-unit(1) !default; 13 | 14 | @keyframes am-dialog-fade { 15 | from { 16 | opacity: 0; 17 | transform: translate3d(0, 10px, 0); 18 | } 19 | 20 | to { 21 | opacity: 1; 22 | transform: translate3d(0, 0, 0); 23 | } 24 | } 25 | 26 | @mixin am-dialog { 27 | animation: 0.6s am-dialog-fade; 28 | background: $am-dialog-background; 29 | border-radius: $am-dialog-border-radius; 30 | box-shadow: 0 3px 3px rgba(#000, 0.23), 0 3px 3px rgba(#000, 0.16); 31 | outline: none; 32 | z-index: $am-elevation-top; 33 | } 34 | 35 | @mixin am-dialog-title { 36 | @include am-type-subheader; 37 | display: block; 38 | padding: $am-dialog-title-padding; 39 | } 40 | 41 | @mixin am-dialog-footer { 42 | padding: am-unit(1) am-unit(1) 0; 43 | text-align: right; 44 | } 45 | 46 | @mixin am-dialog-close { 47 | @include am-btn-icon; 48 | background: url('data:image/svg+xml;utf8, ') 50% 50% no-repeat; 49 | margin: 0; 50 | padding: 0; 51 | position: absolute; 52 | right: 0; 53 | top: 0; 54 | } 55 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/prototypes/menu.scss: -------------------------------------------------------------------------------- 1 | //// 2 | /// Menu 3 | /// A dropdown menu. Used for nested navigation and selection 4 | /// @group menu 5 | //// 6 | 7 | /// Background color of the menu 8 | $am-menu-background: #fff !default; 9 | /// Border radious of the menu 10 | $am-menu-border-radius: 2px !default; 11 | /// X-axis offset of opened menu 12 | $am-menu-offset-x: 0 !default; 13 | /// Y-axis offset of opened menu 14 | $am-menu-offset-y: am-unit(4) !default; 15 | /// Padding of opened menu's container 16 | $am-menu-padding: am-unit(1) !default; 17 | /// Padding of individual menu items 18 | $am-menu-item-padding: am-type-unit(1) am-unit(2) !default; 19 | /// Transition time of menu opening 20 | $am-menu-transition: 0.2s !default; 21 | /// Transition delay when a menu opens 22 | $am-menu-transition-delay: 0.2s !default; 23 | /// Minimum allowable width of menu 24 | $am-menu-min-width: am-unit(14) !default; 25 | /// Desktop breakpoint 26 | $am-menu-breakpoint: 1300px !default; 27 | /// The size of the dropdown carot that displays next to the menu toggle 28 | $am-menu-carat-size: 5px !default; 29 | 30 | @mixin am-menu { 31 | display: inline-block; 32 | outline: 0; 33 | position: relative; 34 | text-align: left; 35 | } 36 | 37 | @mixin am-menu-carat { 38 | border: $am-menu-carat-size solid transparent; 39 | border-color: am-color(primary) transparent transparent; 40 | content: ""; 41 | height: 0; 42 | margin-top: calc($am-menu-carat-size / -2); 43 | position: absolute; 44 | right: -15px; 45 | top: 50%; 46 | width: 0; 47 | } 48 | 49 | @mixin am-menu-carat-muted { 50 | border-top-color: am-color(hint); 51 | } 52 | 53 | @mixin am-menu-list { 54 | background: $am-menu-background; 55 | border-radius: $am-menu-border-radius; 56 | box-shadow: 0 1px 1px rgba(#000, 0.24), 0 0 1.5px rgba(#000, 0.12); 57 | filter: blur(1px); 58 | left: $am-menu-offset-x; 59 | list-style: none; 60 | margin: 0; 61 | min-width: $am-menu-min-width; 62 | padding: $am-menu-padding 0; 63 | position: absolute; 64 | text-align: left; 65 | top: $am-menu-offset-y; 66 | transform-origin: 0 0; 67 | transform: translate3d(0, -4px, 0) scaleY(0); 68 | transition: $am-menu-transition all; 69 | width: auto; 70 | will-change: transform; 71 | z-index: $am-elevation-top; 72 | } 73 | 74 | @mixin am-menu-list-right { 75 | left: auto; 76 | right: $am-menu-offset-x; 77 | } 78 | 79 | @mixin am-menu-item { 80 | display: block; 81 | margin: 0; 82 | transition: $am-menu-transition all; 83 | } 84 | 85 | @mixin am-menu-link { 86 | @include am-link(secondary-text); 87 | @include am-link-no-decoration; 88 | display: block; 89 | font-size: 14px; 90 | opacity: 0; 91 | padding: $am-menu-item-padding; 92 | transition: 0.28s opacity, 0.28s color; 93 | white-space: nowrap; 94 | 95 | &:hover, 96 | &:focus { 97 | @include am-color(primary); 98 | } 99 | 100 | @include am-min-breakpoint($am-menu-breakpoint) { 101 | font-size: 13px; 102 | } 103 | } 104 | 105 | @mixin am-menu-button { 106 | position: relative; 107 | } 108 | 109 | @mixin am-menu-list-open { 110 | filter: none; 111 | transition: $am-menu-transition all; 112 | transform: translateZ(0) scale(1); 113 | } 114 | 115 | @mixin am-menu-item-open { 116 | opacity: 1; 117 | transition: $am-menu-transition opacity; 118 | } 119 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/prototypes/multiselect.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Multiselects 3 | */ 4 | 5 | @mixin am-multiselect { 6 | border: 1px solid #d3d3d3; 7 | box-shadow: inset 0 1px 2px rgba(#000, 0.1); 8 | border-radius: 2px; 9 | min-width: 250px; 10 | max-width: 100%; 11 | } 12 | 13 | @mixin am-multiselect-option { 14 | padding: 8px; 15 | border-top: 1px solid am-color(divider); 16 | 17 | &:first-child { 18 | border-top: 0; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/prototypes/select.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Select 3 | * Custom select styles, taken from textfields in material design 4 | */ 5 | 6 | @mixin am-select { 7 | border: 1px solid am-color(divider); 8 | border-radius: 2px; 9 | display: inline-block; 10 | margin-top: am-unit(1); 11 | } 12 | 13 | @mixin am-select-input { 14 | @include am-font-size(14px); 15 | background: #fafafa url('data:image/svg+xml;utf8, ') no-repeat calc(100% - 4px) 50%; 16 | border: 1px solid #d3d3d3; 17 | border-radius: 3px; 18 | box-shadow: inset 0 1px 0 rgba(#fff, 0.8); 19 | height: am-unit(5) + 2px; // line height + border for Firefox 20 | line-height: am-unit(5); 21 | -webkit-appearance: none; 22 | -moz-appearance: none; 23 | 24 | // These rules are so that opening a select will 25 | // align as closely to the open options as much as possible 26 | letter-spacing: 0.01em; 27 | padding: 0 am-unit(3) 0 10px; 28 | } 29 | 30 | @mixin am-select-input-borderless { 31 | border: 0; 32 | border-radius: 0; 33 | } 34 | 35 | @mixin am-select-input-disabled { 36 | background-color: #eeeeee; 37 | } 38 | 39 | @mixin am-select-unit { 40 | border-left: 1px solid am-color(divider); 41 | text-align: center; 42 | 43 | &:first-child { 44 | border-left: none; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/prototypes/snackbar.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Snackbars 3 | * Material design notifications 4 | * http://www.google.com/design/spec/components/snackbars-toasts.html 5 | */ 6 | 7 | $am-snackbar-background: #323232 !default; 8 | $am-snackbar-color: am-color(text-light) !default; 9 | $am-snackbar-min-width: am-unit(36) !default; 10 | $am-snackbar-max-width: am-unit(72) !default; 11 | $am-snackbar-duration: 9s !default; 12 | 13 | @keyframes am-snackbar-fade { 14 | from { 15 | opacity: 0; 16 | transform: translate3d(0, 5px, 0); 17 | } 18 | 19 | to { 20 | opacity: 1; 21 | transform: none; 22 | } 23 | } 24 | 25 | @mixin am-snackbar { 26 | animation: 0.6s am-snackbar-fade, 0.6s am-snackbar-fade reverse $am-snackbar-duration forwards; 27 | background: $am-snackbar-background; 28 | border-radius: 2px; 29 | bottom: 0; 30 | box-shadow: 0 1px 2px rgba(#000, 0.24); 31 | color: $am-snackbar-color; 32 | font-weight: 300; 33 | font-size: 14px; 34 | line-height: am-sp(20px); 35 | margin: am-unit(2); 36 | min-width: $am-snackbar-min-width; 37 | max-width: $am-snackbar-max-width; 38 | padding: am-unit(2) am-unit(3) am-unit(1.5); 39 | position: fixed; 40 | text-shadow: 0 1px 1px #000; 41 | z-index: $am-elevation-top; 42 | } 43 | 44 | @mixin am-snackbar-error { 45 | background-color: am-darken(error, 25%); 46 | text-shadow: 0 1px 1px am-darken(error, 65%); 47 | } 48 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/prototypes/subheader.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Subheader 3 | * Used for sidebar headings and other secondary content 4 | * which require title text 5 | */ 6 | 7 | @mixin am-subheader { 8 | @include am-font-size(14px); 9 | @include am-color(secondary-text); 10 | font-weight: $am-font-weight-medium; 11 | padding: am-unit(2); 12 | line-height: am-unit(2); 13 | } 14 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/prototypes/table.scss: -------------------------------------------------------------------------------- 1 | @use "sass:color"; 2 | 3 | /** 4 | * Tables 5 | */ 6 | 7 | $am-table-background: #fff !default; 8 | $am-table-border-color: am-color(divider); 9 | 10 | @mixin am-table { 11 | background: $am-table-background; 12 | width: 100%; 13 | word-break: break-word; 14 | } 15 | 16 | @mixin am-table-header { 17 | border-bottom: 1px solid $am-table-border-color; 18 | display: flex; 19 | padding: am-unit(2); 20 | } 21 | 22 | @mixin am-table-column-heading { 23 | @include am-color(secondary-text); 24 | @include am-font-size(13px); 25 | border-bottom: 1px solid $am-table-border-color; 26 | font-weight: $am-font-weight-semi-bold; 27 | height: am-unit(6); 28 | line-height: am-unit(2); 29 | padding: am-unit(1) am-unit(2); 30 | text-align: left; 31 | white-space: nowrap; 32 | } 33 | 34 | @mixin am-table-sort { 35 | position: relative; 36 | 37 | &:after { 38 | border: 5px solid transparent; 39 | margin-left: $am-unit-type; 40 | content: ""; 41 | margin-top: -1.5px; 42 | position: absolute; 43 | top: 50%; 44 | right: -15px; 45 | width: 0; 46 | height: 0; 47 | } 48 | } 49 | 50 | @mixin am-table-sort-asc { 51 | &:after { 52 | border-bottom-color: am-color(primary); 53 | margin-top: -7.5px; 54 | } 55 | } 56 | 57 | @mixin am-table-sort-desc { 58 | &:after { 59 | border-top-color: am-color(primary); 60 | } 61 | } 62 | 63 | @mixin am-table-row { 64 | height: am-unit(6); 65 | transition: 0.12s background; 66 | } 67 | 68 | @mixin am-table-row-hover { 69 | background: #eee; 70 | 71 | td, 72 | th { 73 | box-shadow: 0 -1px 0 rgba(#000, 0.05); 74 | border-bottom: 1px solid color.adjust($am-table-border-color, $lightness: -5%, $space: hsl); 75 | } 76 | } 77 | 78 | @mixin am-table-row-selected { 79 | background: #e0e0e0; 80 | 81 | td, 82 | th { 83 | box-shadow: 0 -1px 0 rgba(#000, 0.15); 84 | border-bottom: 1px solid color.adjust($am-table-border-color, $lightness: -15%, $space: hsl); 85 | } 86 | } 87 | 88 | @mixin am-table-cell { 89 | @include am-color(text); 90 | @include am-font-size(13px); 91 | border-bottom: 1px solid $am-table-border-color; 92 | font-weight: $am-font-weight-regular; 93 | padding: am-unit(1) am-unit(2); 94 | 95 | img { 96 | display: block; 97 | height: auto; 98 | max-width: 320px; 99 | width: 100%; 100 | } 101 | } 102 | 103 | @mixin am-table-cell-selectable { 104 | padding: am-unit(2) am-unit(3) am-unit(2); 105 | width: 18px + am-unit(6); 106 | 107 | [type=checkbox] { 108 | display: inline-block; 109 | height: 18px; 110 | margin: 0; 111 | vertical-align: middle; 112 | width: 18px; 113 | } 114 | } 115 | 116 | @mixin am-table-cell-actions { 117 | background: url('data:image/svg+xml;utf8, ') 25% 50% no-repeat; 118 | position: relative; 119 | width: am-unit(6); 120 | } 121 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/prototypes/tabs.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Tabs 3 | * http://www.google.com/design/spec/components/tabs.html 4 | */ 5 | 6 | $am-tabs-padding: 0 24px !default; 7 | $am-tabs-background: am-color(primary) !default; 8 | $am-tabs-border-width: 3px !default; 9 | $am-tabs-color: rgba(#fff, 0.6) !default; 10 | $am-tabs-color-focus: #fff !default; 11 | $am-tabs-btn-background: inherit !default; 12 | $am-tabs-btn-background-focus: inherit !default; 13 | $am-tabs-btn-border-color: inherit !default; 14 | $am-tabs-font: $am-font-weight-regular 14px/16px $am-font-sans !default; 15 | 16 | @keyframes am-tabs-error-throb { 17 | from { 18 | text-shadow: none; 19 | transform: translateY(1px); 20 | } 21 | 22 | to { 23 | text-shadow: 0 0 5px rgba($am-theme-error, 0.8); 24 | transform: translateY(-1px); 25 | } 26 | } 27 | 28 | @mixin am-tabs { 29 | color: $am-tabs-color; 30 | background: $am-tabs-background; 31 | box-shadow: inset 0 -1px 1px rgba(#000, 0.15); 32 | line-height: 0; 33 | margin: 0; 34 | padding: $am-tabs-padding; 35 | } 36 | 37 | @mixin am-tabs-list { 38 | list-style: none; 39 | } 40 | 41 | @mixin am-tabs-list-item { 42 | display: inline-block; 43 | border-color: $am-tabs-btn-border-color; 44 | } 45 | 46 | @mixin am-tabs-btn { 47 | background: $am-tabs-btn-background; 48 | color: $am-tabs-color; 49 | cursor: pointer; 50 | display: block; 51 | font: $am-tabs-font; 52 | letter-spacing: 0.08em; 53 | padding: am-unit(2); 54 | position: relative; 55 | text-transform: uppercase; 56 | transition: 0.2s color; 57 | -moz-appearance: none; 58 | -webkit-appearance: none; 59 | 60 | &:after { 61 | @include am-fill(secondary-text-light); 62 | bottom: 0; 63 | box-shadow: 0 -1px 1px rgba(#000, 0.1); 64 | content: ""; 65 | height: $am-tabs-border-width; 66 | left: 0; 67 | position: absolute; 68 | transform: translateY($am-tabs-border-width); 69 | transition: 0.2s background, 0.25s transform; 70 | width: 100%; 71 | } 72 | 73 | &:focus, 74 | &:hover { 75 | background: $am-tabs-btn-background-focus; 76 | outline: none; 77 | text-decoration: none; 78 | 79 | &:after { 80 | transform: none; 81 | } 82 | } 83 | 84 | &:active { 85 | border: 0; 86 | box-shadow: none; 87 | } 88 | } 89 | 90 | @mixin am-tabs-btn-active { 91 | background: $am-tabs-btn-background-focus; 92 | color: $am-tabs-color-focus; 93 | 94 | &:after { 95 | @include am-fill(accent); 96 | box-shadow: 0 -1px 1px rgba(#000, 0.1), inset 0 1px 1px rgba(#fff, 0.50); 97 | transform: none; 98 | } 99 | 100 | &:focus, 101 | &:hover { 102 | background: $am-tabs-btn-background-focus; 103 | } 104 | } 105 | 106 | @mixin am-tabs-btn-error { 107 | padding-right: am-unit(5); 108 | 109 | &:before { 110 | @include am-color(error-400); 111 | animation: 2s am-tabs-error-throb infinite alternate; 112 | content: '\026a0'; 113 | font-size: 20px; 114 | line-height: am-unit(2); 115 | margin-top: -6px; 116 | position: absolute; 117 | right: am-unit(1); 118 | top: 50%; 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/prototypes/tag.scss: -------------------------------------------------------------------------------- 1 | @mixin am-tag { 2 | @include am-fill(secondary-text); 3 | @include am-type-caption; 4 | @include am-type-smooth; 5 | border-radius: 3px; 6 | color: #fff; 7 | display: inline-block; 8 | letter-spacing: 0.1em; 9 | line-height: am-unit(2); 10 | padding: am-unit(0.5) am-unit(1); 11 | text-decoration: none; 12 | text-transform: uppercase; 13 | white-space: nowrap; 14 | } 15 | 16 | @mixin am-tag-pressable { 17 | transition: 0.2s all; 18 | 19 | &:hover, 20 | &:focus { 21 | box-shadow: 0 1px 1px rgba(#000, 0.22); 22 | text-shadow: none; 23 | } 24 | 25 | &:active { 26 | box-shadow: none; 27 | } 28 | } 29 | 30 | @mixin am-tag-success { 31 | @include am-fill(primary); 32 | } 33 | 34 | @mixin am-tag-error { 35 | @include am-fill(error); 36 | } 37 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/prototypes/textfield.scss: -------------------------------------------------------------------------------- 1 | //// 2 | /// Textfield 3 | /// Character inputs, for simple form fields 4 | /// @group textfield 5 | //// 6 | 7 | /// Textfield input typography. 8 | $am-textfield-input-type: normal am-sp(14px)/24px $am-font-sans !default; 9 | /// Textfield label typography. 10 | $am-textfield-label-type: $am-font-weight-regular am-sp(12px)/am-unit(2) $am-font-sans !default; 11 | /// Textfield margin. 12 | $am-textfield-margin: am-unit(1) 0 !default; 13 | /// Textfield padding. 14 | $am-textfield-padding: am-unit(1) am-unit(2) !default; 15 | /// Textfield error color. 16 | $am-textfield-error-color: $am-theme-error !default; 17 | /// Textfield color. 18 | $am-textfield-color: rgba(#000, 0.70) !default; 19 | /// Textfield highlight color. 20 | $am-textfield-primary: am-color(primary) !default; 21 | /// Icon for email fields. 22 | $am-textfield-email-icon: url('data:image/svg+xml;utf8, ') !default; 23 | /// Icon for password fields. 24 | $am-textfield-password-icon: url('data:image/svg+xml;utf8, ') !default; 25 | /// Icon for date fields. 26 | $am-textfield-date-icon: url('data:image/svg+xml;utf8, ') !default; 27 | 28 | 29 | @mixin am-textfield { 30 | color: $am-textfield-color; 31 | margin: $am-textfield-margin; 32 | padding: $am-textfield-padding; 33 | position: relative; 34 | } 35 | 36 | @mixin am-textfield-input { 37 | background: #fff; 38 | border-radius: 3px; 39 | border: 1px solid #d3d3d3; 40 | box-shadow: inset 1px 1px 1px rgba(#222, 0.08); 41 | display: block; 42 | font: $am-textfield-input-type; 43 | line-height: 24px; 44 | margin: 0; 45 | padding: am-unit(1); 46 | transition: 0.35s border-color, 0.35s box-shadow; 47 | width: 100%; 48 | 49 | &:focus { 50 | border-color: am-color(primary); 51 | outline: 0; 52 | transition: 0.15s border-color, 0.15s box-shadow; 53 | } 54 | } 55 | 56 | @mixin am-textfield-input-email { 57 | background: #fff $am-textfield-email-icon am-unit(1) 50% no-repeat; 58 | padding-left: am-unit(5); 59 | } 60 | 61 | @mixin am-textfield-input-password { 62 | background: #fff $am-textfield-password-icon am-unit(1) 50% no-repeat; 63 | padding-left: am-unit(5); 64 | } 65 | 66 | @mixin am-textfield-input-date { 67 | background: #fff $am-textfield-date-icon am-unit(1) 50% no-repeat; 68 | padding-left: am-unit(5); 69 | } 70 | 71 | @mixin am-textfield-textarea { 72 | border-radius: 2px; 73 | height: am-sp(7px); 74 | padding: am-unit(1); 75 | } 76 | 77 | @mixin am-textfield-input-error { 78 | border-color: $am-textfield-error-color; 79 | box-shadow: 0 1px 0 0 $am-textfield-error-color; 80 | } 81 | 82 | @mixin am-textfield-label { 83 | @include am-font-size(13px); 84 | @include am-color(secondary-text); 85 | display: block; 86 | line-height: 16px; 87 | font: $am-textfield-label-type; 88 | margin-bottom: 8px; 89 | position: relative; 90 | transition: 0.28s all; 91 | width: 100%; 92 | 93 | .has-focus & { 94 | color: $am-textfield-primary; 95 | } 96 | } 97 | 98 | @mixin am-textfield-hint { 99 | @include am-type-caption; 100 | @include am-color(secondary-text); 101 | margin: am-unit(1) 0 0; 102 | } 103 | 104 | @mixin am-textfield-hint-error { 105 | @include am-type-caption; 106 | color: $am-textfield-error-color; 107 | display: inline-block; 108 | margin: $am-unit-type 0 0; 109 | vertical-align: middle; 110 | transition: 0.3s all; 111 | 112 | &:first-letter { 113 | text-transform: uppercase; 114 | } 115 | } 116 | 117 | @mixin am-textfield-required { 118 | @include am-type-caption; 119 | border: 0; 120 | color: $am-textfield-primary; 121 | margin-left: 4px; 122 | } 123 | 124 | @mixin am-textfield-input-disabled { 125 | background-color: #eeeeee; 126 | } 127 | 128 | @mixin am-textfield-inline { 129 | align-items: center; 130 | display: flex; 131 | flex-wrap: wrap; 132 | } 133 | 134 | @mixin am-textfield-label-inline { 135 | width: 100%; 136 | } 137 | 138 | @mixin am-textfield-input-inline { 139 | flex: 1; 140 | width: auto; 141 | } 142 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/prototypes/toolbar.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Toolbar 3 | * A basic navigation element, primary used for top level navigation 4 | */ 5 | 6 | $am-toolbar-base-font-size : am-sp(14px) !default; 7 | $am-toolbar-title-font-size : am-sp(20px) !default; 8 | $am-toolbar-keyline-small : am-unit(7) !default; 9 | $am-toolbar-keyline-medium : $am-toolbar-keyline-small + 8px !default; 10 | 11 | @mixin am-toolbar { 12 | @include am-type-smooth; 13 | align-items: center; 14 | display: flex; 15 | flex-wrap: wrap; 16 | font-size: $am-toolbar-base-font-size; 17 | position: relative; 18 | } 19 | 20 | @mixin am-toolbar-primary { 21 | @include am-fill(primary); 22 | @include am-color(text-light); 23 | } 24 | 25 | @mixin am-toolbar-title { 26 | font-size: $am-toolbar-title-font-size; 27 | font-weight: $am-font-weight-medium; 28 | line-height: am-unit(2); 29 | padding: am-unit(2); 30 | width: 100%; 31 | text-align: left; 32 | 33 | @include am-min-breakpoint($am-breakpoint-medium) { 34 | width: auto; 35 | } 36 | } 37 | 38 | @mixin am-toolbar-list { 39 | margin: 0 0 0 am-unit(2); 40 | padding: 0; 41 | text-align: left; 42 | } 43 | 44 | @mixin am-toolbar-item { 45 | @include am-link-no-decoration; 46 | @include am-color(text); 47 | display: inline-block; 48 | font-weight: $am-font-weight-medium; 49 | line-height: am-unit(3); 50 | margin: 0; 51 | } 52 | 53 | @mixin am-toolbar-item-primary { 54 | @include am-link-no-decoration; 55 | @include am-color(text-light); 56 | display: block; 57 | line-height: am-unit(2); 58 | padding: am-unit(2) am-unit(1); 59 | text-align: center; 60 | 61 | &:hover, 62 | &:focus { 63 | @include am-color(accent); 64 | } 65 | } 66 | 67 | @mixin am-toolbar-item-primary-active { 68 | @include am-color(accent); 69 | font-weight: $am-font-weight-semi-bold; 70 | } 71 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/prototypes/underlay.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Underlay 3 | * Underlays appear below modal content that takes up the entire screen. 4 | */ 5 | 6 | $am-underlay-background: rgba(#000, 0.54) !default; 7 | 8 | @mixin am-underlay { 9 | background: $am-underlay-background; 10 | height: 100%; 11 | left: 0; 12 | position: fixed; 13 | top: 0; 14 | width: 100%; 15 | z-index: $am-elevation-top; 16 | } 17 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/values/breakpoints.scss: -------------------------------------------------------------------------------- 1 | $am-breakpoint-medium : 600px !default; 2 | $am-breakpoint-large : 1024px !default; 3 | $am-breakpoint-extra-large : 1279px !default; 4 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/values/colors.scss: -------------------------------------------------------------------------------- 1 | @use "sass:color"; 2 | 3 | //// 4 | /// @group colors 5 | //// 6 | 7 | /// Primary theme color. This is the main admin theme color, showing itself 8 | /// on the main header, buttons, and other elements that command attention. 9 | /// If you want to change the main theme colors, this is the value you want. 10 | $am-theme-primary: #009688 !default; 11 | 12 | /// A darker primary theme color for contrast when overlaying important items 13 | /// containers that are already treated with primary color. 14 | $am-theme-primary-700: #0D3C55 !default; 15 | 16 | /// Used for primary action button and components like switches or sliders. 17 | $am-theme-accent: #cddc39 !default; 18 | 19 | /// The color treatment of error messages. 20 | $am-theme-error: #f44336 !default; 21 | 22 | /// A lighter treatment for errors to draw contrast to the main error color. 23 | $am-theme-error-400: #FF695E !default; 24 | 25 | /// The background color of the document. 26 | $am-theme-backdrop: #eeeeee !default; 27 | 28 | /// The background color of Material Design "paper" elements such as cards. 29 | /// And other elements that overlap content. 30 | $am-theme-paper: white !default; 31 | 32 | /// The color of tooling lines used to aid the eye when breaking down content. 33 | $am-theme-divider: #efefef !default; 34 | 35 | /// The text color for hints. Displays itself in helper text under inputs and 36 | /// other guiding copy. 37 | $am-theme-hint-text: rgba(black, 0.26) !default; 38 | 39 | /// A lighter text color for less important content. 40 | $am-theme-secondary-text: rgba(black, 0.54) !default; 41 | 42 | /// A lighter text color for less important content on dark backgrounds. 43 | $am-theme-secondary-text-reverse: rgba(white, 0.54) !default; 44 | 45 | /// An even lighter text treatment for content less important than 46 | /// secondary text. 47 | $am-theme-tertiary-text: rgba(black, 0.4) !default; 48 | 49 | /// The default color of icons. 50 | $am-theme-icon: $am-theme-secondary-text !default; 51 | 52 | /// The default color for all text. 53 | $am-theme-text: rgba(black, 0.70) !default; 54 | 55 | /// The default color for all text on dark backgrounds. 56 | $am-theme-text-reverse: white !default; 57 | 58 | /// A color for focus states. 59 | /// @deprecated 60 | $am-state-focus: rgba(#999, 0.2) !default; 61 | 62 | /// A color for active states. 63 | /// @deprecated 64 | $am-state-active: rgba(#999, 0.4) !default; 65 | 66 | /// A color for disabled states. 67 | /// @deprecated 68 | $am-state-disabled: rgba(#999, 0.1) !default; 69 | 70 | /// An old variable for primary colors maintained for legacy support on other projects. 71 | /// @deprecated 72 | $theme-primary: $am-theme-primary !default; 73 | 74 | /// An old variable for divider colors maintained for legacy support on other projects. 75 | /// @deprecated 76 | $theme-divider: $am-theme-divider !default; 77 | 78 | /// An old variable for accent colors maintained for legacy support on other projects. 79 | /// @deprecated 80 | $theme-accent: $am-theme-accent !default; 81 | 82 | /// An old variable for error colors maintained for legacy support on other projects. 83 | /// @deprecated 84 | $theme-error: $am-theme-error !default; 85 | 86 | $am-colors: ( 87 | accent : $am-theme-accent, 88 | accent-active : color.adjust($am-theme-accent, $lightness: 2%, $space: hsl), 89 | accent-hover : color.adjust($am-theme-accent, $lightness: 5%, $space: hsl), 90 | backdrop : $am-theme-backdrop, 91 | black : black, 92 | divider : $am-theme-divider, 93 | error : $am-theme-error, 94 | error-400 : $am-theme-error-400, 95 | hint : $am-theme-hint-text, 96 | paper : $am-theme-paper, 97 | primary : $am-theme-primary, 98 | primary-700 : $am-theme-primary-700, 99 | secondary-text : $am-theme-secondary-text, 100 | secondary-text-light : $am-theme-secondary-text-reverse, 101 | text : $am-theme-text, 102 | text-light : $am-theme-text-reverse, 103 | white : white, 104 | tertiary-text : $am-theme-tertiary-text, 105 | icon : $am-theme-icon 106 | ); 107 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/values/elevation.scss: -------------------------------------------------------------------------------- 1 | $am-elevation-0: 0 !default; 2 | $am-elevation-1: 100 !default; 3 | $am-elevation-2: 200 !default; 4 | $am-elevation-3: 300 !default; 5 | $am-elevation-4: 400 !default; 6 | $am-elevation-5: 500 !default; 7 | $am-elevation-fixed: 600 !default; 8 | $am-elevation-top: 1000 !default; 9 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/values/fonts.scss: -------------------------------------------------------------------------------- 1 | //// 2 | /// @group fonts 3 | //// 4 | 5 | /// The default sans-serif font 6 | $am-font-sans: 'Roboto', sans-serif !default; 7 | 8 | /// The weight of bold type 9 | $am-font-weight-bold: 700; 10 | 11 | /// The weight of semi-bold type 12 | $am-font-weight-semi-bold: 500; 13 | 14 | /// The weight of medium type 15 | $am-font-weight-medium: 500; 16 | 17 | /// The weight of regular type 18 | $am-font-weight-regular: 400; 19 | 20 | $am-fonts: ( 21 | sans: $am-font-sans 22 | ); 23 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_material/values/units.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Unit 3 | * http://www.google.com/design/spec/layout/metrics-and-keylines.html#metrics-and-keylines-baseline-units 4 | */ 5 | 6 | $am-unit-base: 8px !default; 7 | $am-unit-type: 4px !default; 8 | $am-unit-icon: 4px !default; 9 | -------------------------------------------------------------------------------- /config/importmap.rb: -------------------------------------------------------------------------------- 1 | pin "active_material" 2 | pin "active_material/actions-toggle" 3 | -------------------------------------------------------------------------------- /docs/customization.md: -------------------------------------------------------------------------------- 1 | # Customizing ActiveMaterial 2 | 3 | 1. [Customizing the Color Theme](#customizing-the-color-theme) 4 | 2. [Color Variables](#color-variables) 5 | 3. [Font Variables](#font-variables) 6 | 7 | ## Customizing the Color Theme 8 | 9 | Definitions of all colors exist in 10 | [a single colors.scss file](/app/assets/stylesheets/active_material/values/colors.scss). These 11 | color variables are assigned using the `!default` Sass flag, so they can be easily overridden. 12 | 13 | For example, to customize the primary color: 14 | 15 | ```scss 16 | // The following variables override default ActiveMaterial values 17 | @use "active_material" with ( 18 | $am-theme-primary: #00689f; 19 | $am-theme-accent: #7dd2f7; 20 | ); 21 | ``` 22 | 23 | ## Color variables 24 | 25 | **$am-theme-primary:** Primary theme color. This is the main admin theme color, showing itself on the main header, buttons, and other elements that command attention. If you want to change the main theme colors, this is the value you want. 26 | 27 | **$am-theme-primary-700:** A darker primary theme color for contrast when overlaying important items containers that are already treated with primary color. 28 | 29 | **$am-theme-accent:** Used for primary action button and components like switches or sliders. 30 | 31 | **$am-theme-error**: The color treatment of error messages. 32 | 33 | **$am-theme-error-400**: A lighter treatment for errors to draw contrast to the main error color. 34 | 35 | **$am-theme-backdrop**: The background color of the document. 36 | 37 | **$am-theme-paper**: The background color of Material Design "paper" elements such as cards. And other elements that overlap content. 38 | 39 | **$am-theme-divider:** The color of tooling lines used to aid the eye when breaking down content. 40 | 41 | 42 | **$am-theme-hint-text:** The text color for hints. Displays itself in helper text under inputs and other guiding copy 43 | 44 | **$am-theme-secondary-text:** A lighter text color for less important content. 45 | 46 | **$am-theme-secondary-text-reverse:** A lighter text color for less important content on dark backgrounds. 47 | 48 | **$am-theme-tertiary-text:** An even lighter text treatment for content less important than secondary text. 49 | 50 | **$am-theme-icon:** The default color of icons. 51 | 52 | **$am-theme-text:** The default color for all text. 53 | 54 | **$am-theme-text-reverse:** The default color for all text on dark backgrounds. 55 | 56 | ## Font Variables 57 | 58 | **$am-font-sans:** The font family used by active_material 59 | 60 | By default, this gem will load the Roboto font from google APIs and use it in the SCSS. If you would like to change that behavior, you have a few options: 61 | 62 | 1. If you want to change to another font: 63 | - In your application config, set `config.active_material.font_url` to your font url 64 | - Set `$am-font-sans: 'Roboto';`, replacing `Roboto` with your font name. 65 | 2. If you want to disable font loading altogether, you can use `config.active_material.load_font = true` 66 | 67 | **$am-font-weight-bold:** The weight of bold type 68 | 69 | **$am-font-weight-semi-bold:** The weight of semi-bold type 70 | 71 | **$am-font-weight-medium:** The weight of medium type 72 | 73 | **$am-font-weight-regular:** The weight of regular type 74 | -------------------------------------------------------------------------------- /lib/active_material.rb: -------------------------------------------------------------------------------- 1 | require "active_material/version" 2 | require "active_material/font_loader" 3 | 4 | module ActiveMaterial 5 | module Rails 6 | class Engine < ::Rails::Engine 7 | config.active_material = ActiveSupport::OrderedOptions.new 8 | config.active_material.load_font = true 9 | config.active_material.font_url = "https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap" 10 | 11 | initializer "active_material" do |app| 12 | if app.config.active_material.load_font 13 | ActiveAdmin.before_load do 14 | ActiveAdmin::Views::Pages::Base.prepend ActiveMaterial::FontLoader 15 | end 16 | end 17 | end 18 | 19 | initializer "active_material.precompile" do |app| 20 | app.config.assets.paths << self.root.join("app/javascripts") 21 | app.config.assets.paths << self.root.join("app/stylesheets") 22 | app.config.assets.precompile << "active_material.js" 23 | end 24 | 25 | initializer "active_material.importmap", before: "importmap" do |app| 26 | # Skip if importmap-rails is not installed 27 | next unless app.config.respond_to?(:importmap) 28 | 29 | app.config.importmap.paths << Engine.root.join("config/importmap.rb") 30 | end 31 | end 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /lib/active_material/font_loader.rb: -------------------------------------------------------------------------------- 1 | module ActiveMaterial 2 | module FontLoader 3 | def build_active_admin_head 4 | within super do 5 | uri = URI.parse(ActiveMaterial::Rails::Engine.config.active_material.font_url) 6 | origin = extract_origin(uri) 7 | 8 | link(rel: "preconnect", href: origin) 9 | link(rel: "preconnect", href: origin, crossorigin: true) 10 | link(rel: "stylesheet", href: uri.to_s) 11 | end 12 | end 13 | 14 | private 15 | 16 | def extract_origin(uri) 17 | origin = "#{uri.scheme}://#{uri.host}" 18 | origin += ":#{uri.port}" if uri.port && !default_port?(uri) 19 | origin 20 | end 21 | 22 | def default_port?(uri) 23 | (uri.scheme == 'http' && uri.port == 80) || (uri.scheme == 'https' && uri.port == 443) 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /lib/active_material/version.rb: -------------------------------------------------------------------------------- 1 | module ActiveMaterial 2 | VERSION = "2.1.5" 3 | end 4 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "active_material", 3 | "version": "2.1.5", 4 | "description": "ActiveAdmin skin based on Google's Material Design.", 5 | "main": "app/assets/javascripts/active_material.js", 6 | "directories": { 7 | "lib": "lib" 8 | }, 9 | "scripts": { 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "git+https://github.com/dkniffin/active_material.git" 14 | }, 15 | "author": "Derek Kniffin", 16 | "license": "MIT", 17 | "bugs": { 18 | "url": "https://github.com/dkniffin/active_material/issues" 19 | }, 20 | "homepage": "https://github.com/dkniffin/active_material#readme", 21 | "dependencies": {}, 22 | "devDependencies": {} 23 | } 24 | --------------------------------------------------------------------------------