diff --git a/framework/core/ember/app/components/application/back-button.js b/framework/core/ember/app/components/application/back-button.js index 47c633ee9..630104130 100755 --- a/framework/core/ember/app/components/application/back-button.js +++ b/framework/core/ember/app/components/application/back-button.js @@ -5,7 +5,7 @@ import Ember from 'ember'; */ export default Ember.Component.extend({ classNames: ['back-button'], - classNameBindings: ['active'], + classNameBindings: ['active', 'className'], active: Ember.computed.or('target.paneIsShowing', 'target.paneIsPinned'), @@ -25,6 +25,10 @@ export default Ember.Component.extend({ togglePinned: function() { this.get('target').send('togglePinned'); + }, + + toggleDrawer: function() { + this.sendAction('toggleDrawer'); } } }); diff --git a/framework/core/ember/app/components/discussion/post-header/meta.js b/framework/core/ember/app/components/discussion/post-header/meta.js index c4919f4da..194b8b434 100644 --- a/framework/core/ember/app/components/discussion/post-header/meta.js +++ b/framework/core/ember/app/components/discussion/post-header/meta.js @@ -28,8 +28,8 @@ export default Ember.Component.extend({ setTimeout(function() { component.$('.permalink').select(); }, 1); }); - // Prevent clicking on the dropdown menu from closing it. - this.$('.dropdown-menu').click(function(e) { + // Prevent clicking on the input from closing it. + this.$('.permalink').click(function(e) { e.stopPropagation(); }); } diff --git a/framework/core/ember/app/components/discussion/stream-scrubber.js b/framework/core/ember/app/components/discussion/stream-scrubber.js index 48d39c657..cee8cb4b0 100644 --- a/framework/core/ember/app/components/discussion/stream-scrubber.js +++ b/framework/core/ember/app/components/discussion/stream-scrubber.js @@ -8,7 +8,7 @@ var $ = Ember.$; */ export default Ember.Component.extend({ layoutName: 'components/discussion/stream-scrubber', - classNames: ['scrubber', 'stream-scrubber'], + classNames: ['stream-scrubber', 'dropdown'], classNameBindings: ['disabled'], // The stream-content component to which this scrubber is linked. diff --git a/framework/core/ember/app/components/ui/dropdown-select.js b/framework/core/ember/app/components/ui/dropdown-select.js index 5d5781d06..b7012e92a 100644 --- a/framework/core/ember/app/components/ui/dropdown-select.js +++ b/framework/core/ember/app/components/ui/dropdown-select.js @@ -7,7 +7,7 @@ import Ember from 'ember'; export default Ember.Component.extend({ layoutName: 'components/ui/dropdown-select', classNames: ['dropdown', 'dropdown-select', 'btn-group'], - classNameBindings: ['itemCountClass', 'class'], + classNameBindings: ['itemCountClass', 'className'], buttonClass: 'btn btn-default', menuClass: '', diff --git a/framework/core/ember/app/components/ui/item-list.js b/framework/core/ember/app/components/ui/item-list.js index a7d477f2e..165ae814e 100644 --- a/framework/core/ember/app/components/ui/item-list.js +++ b/framework/core/ember/app/components/ui/item-list.js @@ -14,7 +14,10 @@ export default Ember.Component.extend({ return []; } items.forEach(function(item) { - item.reopenClass({isListItem: item.proto().tagName === 'li'}); + item.reopenClass({ + isListItem: item.proto().tagName === 'li', + listItemClass: item.proto().listItemClass + }); }); return items; }) diff --git a/framework/core/ember/app/components/ui/text-editor.js b/framework/core/ember/app/components/ui/text-editor.js index 654923cb5..e3371f268 100644 --- a/framework/core/ember/app/components/ui/text-editor.js +++ b/framework/core/ember/app/components/ui/text-editor.js @@ -22,7 +22,7 @@ export default Ember.Component.extend(HasItemLists, { }, populateControls: function(items) { - this.addActionItem(items, 'submit', this.get('submitLabel')).reopen({className: 'btn btn-primary'}); + this.addActionItem(items, 'submit', this.get('submitLabel'), 'check').reopen({className: 'btn btn-primary', listItemClass: 'primary-control'}); }, actions: { diff --git a/framework/core/ember/app/controllers/application.js b/framework/core/ember/app/controllers/application.js index e2c8cb3aa..a9e01f9c4 100644 --- a/framework/core/ember/app/controllers/application.js +++ b/framework/core/ember/app/controllers/application.js @@ -1,7 +1,6 @@ import Ember from 'ember'; export default Ember.Controller.extend({ - // The title of the forum. // TODO: Preload this value in the index.html payload from Laravel config. forumTitle: 'Flarum Demo Forum', @@ -18,6 +17,9 @@ export default Ember.Controller.extend({ actions: { search: function(query) { this.transitionToRoute('index', {queryParams: {searchQuery: query, sort: query ? 'relevance' : 'recent'}}); + }, + toggleDrawer: function() { + this.toggleProperty('drawerShowing'); } } }); diff --git a/framework/core/ember/app/routes/discussion.js b/framework/core/ember/app/routes/discussion.js index c1f7c810f..980e3366b 100644 --- a/framework/core/ember/app/routes/discussion.js +++ b/framework/core/ember/app/routes/discussion.js @@ -120,6 +120,11 @@ export default Ember.Route.extend({ .set('paned', true) .set('paneShowing', false); this.controllerFor('composer').send('minimize'); + + var application = this.controllerFor('application'); + if (!application.get('backButtonTarget')) { + application.set('backButtonTarget', this.controllerFor('index')); + } } } }); diff --git a/framework/core/ember/app/styles/app.less b/framework/core/ember/app/styles/app.less index 482053cbc..77ac169e7 100644 --- a/framework/core/ember/app/styles/app.less +++ b/framework/core/ember/app/styles/app.less @@ -18,6 +18,11 @@ // Finally, with our vendor CSS loaded, we can import Flarum-specific stuff. @import "@{flarum-base}components.less"; +@import "@{flarum-base}buttons.less"; +@import "@{flarum-base}dropdowns.less"; +@import "@{flarum-base}avatars.less"; +@import "@{flarum-base}forms.less"; +@import "@{flarum-base}hero.less"; @import "@{flarum-base}alerts.less"; @import "@{flarum-base}modals.less"; @import "@{flarum-base}layout.less"; diff --git a/framework/core/ember/app/styles/bootstrap/variables.less b/framework/core/ember/app/styles/bootstrap/variables.less index 2f14296f5..db0f51757 100644 --- a/framework/core/ember/app/styles/bootstrap/variables.less +++ b/framework/core/ember/app/styles/bootstrap/variables.less @@ -35,6 +35,15 @@ @fl-body-control-bg: @fl-body-secondary-color; @fl-body-control-color: @fl-body-muted-color; +// --------------------------------- +// DRAWER + +@fl-drawer-bg: @fl-body-primary-color; +@fl-drawer-color: #fff; +@fl-drawer-muted-color: fade(#fff, 50%); +@fl-drawer-control-bg: fade(#000, 10%); +@fl-drawer-control-color: #fff; + // --------------------------------- // HEADER @@ -50,16 +59,22 @@ @fl-body-hero-color: #fff; } .define-hdr-variables(true) { - @fl-hdr-bg: @fl-body-primary-color; - @fl-hdr-color: #fff; - @fl-hdr-muted-color: fade(#fff, 50%); - @fl-hdr-control-bg: fade(#000, 10%); - @fl-hdr-control-color: #fff; + @fl-hdr-bg: @fl-drawer-bg; + @fl-hdr-color: @fl-drawer-color; + @fl-hdr-muted-color: @fl-drawer-muted-color; + @fl-hdr-control-bg: @fl-drawer-control-bg; + @fl-hdr-control-color: @fl-drawer-control-color; @fl-body-hero-bg: @fl-body-control-bg; @fl-body-hero-color: @fl-body-control-color; } +// --------------------------------- +// LAYOUT + +@drawer-width: 270px; +@index-pane-width: 400px; + // --------------------------------- // BOOTSTRAP @@ -88,3 +103,11 @@ @zindex-alerts: @zindex-modal + 10; @link-hover-color: @link-color; + +// --------------------------------- +// MEDIA SHORTCODES + +@phone: ~"(max-width: @{screen-xs-max})"; +@tablet: ~"(min-width: @{screen-sm-min}) and (max-width: @{screen-sm-max})"; +@desktop: ~"(min-width: @{screen-md-min}) and (max-width: @{screen-md-max})"; +@desktop-hd: ~"(min-width: @{screen-lg-min})"; diff --git a/framework/core/ember/app/styles/flarum/avatars.less b/framework/core/ember/app/styles/flarum/avatars.less new file mode 100644 index 000000000..8c895ab0a --- /dev/null +++ b/framework/core/ember/app/styles/flarum/avatars.less @@ -0,0 +1,24 @@ +.avatar-size(@size) { + width: @size; + height: @size; + border-radius: @size / 2; + font-size: @size / 2; + line-height: @size; +} +.avatar { + display: inline-block; + color: @fl-body-bg; + font-weight: 300; + text-align: center; + vertical-align: top; + background-color: @fl-body-control-bg; + .avatar-size(48px); + + & img { + display: inline-block; + width: 100%; + height: 100%; + border-radius: 100%; + vertical-align: top; + } +} diff --git a/framework/core/ember/app/styles/flarum/buttons.less b/framework/core/ember/app/styles/flarum/buttons.less new file mode 100644 index 000000000..85276238c --- /dev/null +++ b/framework/core/ember/app/styles/flarum/buttons.less @@ -0,0 +1,85 @@ +.btn { + border: 0; + .box-shadow(none); + line-height: 20px; + + & .fa { + font-size: 14px; + } +} +.btn-group .btn + .btn { + margin-left: 1px; +} +.btn-icon { + padding-left: 9px; + padding-right: 9px; +} +.btn-link { + color: @fl-body-muted-color; + + &:hover, + &:focus { + text-decoration: none; + } +} +.btn-primary { + font-weight: bold; + & .icon-glyph { + display: none; + } +} +.btn-user { + & .avatar { + margin: -2px 5px -2px -5px; + .avatar-size(24px); + } +} +.btn-more { + padding: 1px 3px; + border-radius: 2px; + line-height: 1; +} + +// Redefine Bootstrap's mixin to make some general changes +.button-variant(@color; @background; @border) { + &:hover, + &:focus, + &.focus, + &:active, + &.active, + .open > .dropdown-toggle& { + background-color: darken(@background, 5%); + } + &.active { + .box-shadow(none); + } +} + +// Little round icon buttons +.btn-icon.btn-sm { + border-radius: 12px; + height: 24px; + width: 24px; + text-align: center; + padding: 3px 0; + + & .label, & .icon-caret { + display: none; + } + & .fa-ellipsis-v { + font-size: 17px; + vertical-align: middle; + } +} + +// Buttons that blend into the background +.btn-naked { + background: transparent; + &:hover { + background: @fl-body-control-bg; + } +} + +.btn-rounded { + border-radius: 18px; +} diff --git a/framework/core/ember/app/styles/flarum/components.less b/framework/core/ember/app/styles/flarum/components.less deleted file mode 100644 index 117641e86..000000000 --- a/framework/core/ember/app/styles/flarum/components.less +++ /dev/null @@ -1,247 +0,0 @@ -// ------------------------------------ -// Buttons - -.btn { - border: 0; - .box-shadow(none); - line-height: 20px; - - & .fa { - font-size: 14px; - } -} -.btn-group .btn + .btn { - margin-left: 1px; -} -.btn-icon { - padding-left: 9px; - padding-right: 9px; -} -.btn-link { - color: @fl-body-muted-color; - - &:hover, - &:focus { - text-decoration: none; - } -} -.btn-primary { - font-weight: bold; - & .icon-glyph { - display: none; - } -} -.btn-user { - & .avatar { - margin: -2px 5px -2px -5px; - .avatar-size(24px); - } -} -.btn-more { - padding: 1px 3px; - border-radius: 2px; - line-height: 1; -} - -// Redefine Bootstrap's mixin to make some general changes -.button-variant(@color; @background; @border) { - &:hover, - &:focus, - &.focus, - &:active, - &.active, - .open > .dropdown-toggle& { - background-color: darken(@background, 5%); - } - &.active { - .box-shadow(none); - } -} - -// Little round icon buttons -.btn-icon.btn-sm { - border-radius: 12px; - height: 24px; - width: 24px; - text-align: center; - padding: 3px 0; - - & .label, & .icon-caret { - display: none; - } - & .fa-ellipsis-v { - font-size: 17px; - vertical-align: middle; - } -} - -// Buttons that blend into the background -.btn-naked { - background: transparent; - &:hover { - background: @fl-body-control-bg; - } -} - -.btn-rounded { - border-radius: 18px; -} - -// ------------------------------------ -// Form Controls - -.form-group { - margin-bottom: 12px; -} -.form-control { - .box-shadow(none); - &:focus, - &.focus { - background-color: #fff; - color: @fl-body-color; - .box-shadow(none); - } -} - -// Search inputs -// @todo Extract some of this into header-specific definitions -.search-input { - margin-right: 10px; - &:before { - .fa(); - content: @fa-var-search; - float: left; - margin-right: -36px; - width: 36px; - font-size: 14px; - text-align: center; - color: @fl-body-muted-color; - position: relative; - padding: @padding-base-vertical - 1 0; - line-height: @line-height-base; - pointer-events: none; - } -} -.search-input .form-control { - float: left; - width: 225px; - padding-left: 36px; - padding-right: 36px; - .transition(~"all 0.4s"); - - &:focus { - width: 400px; - } -} -.search-input .clear { - float: left; - margin-left: -36px; - vertical-align: top; - opacity: 0; - .rotate(-180deg); - .transition(~"transform 0.2s, opacity 0.2s"); -} -.search-input.clearable .clear { - opacity: 1; - .rotate(0deg); -} - -// Select inputs -.select-input { - display: inline-block; - vertical-align: middle; -} -.select-input select { - display: inline-block; - width: auto; - -webkit-appearance: none; - padding-right: @padding-base-horizontal + 16; - cursor: pointer; -} -.select-input .fa { - margin-left: -@padding-base-horizontal - 16; - pointer-events: none; - color: @fl-body-muted-color; -} - -// ------------------------------------ -// Dropdown Menus - -.dropdown-menu { - border: 0; - padding: 8px 0; - margin-top: 7px; - .box-shadow(0 2px 6px @fl-shadow-color); - background: @fl-body-bg; - - & > li > a { - padding: 8px 15px; - color: @fl-body-color; - &:hover, &:focus { - color: @fl-body-color; - background-color: @fl-body-control-bg; - } - & .fa { - margin-right: 5px; - font-size: 14px; - } - } - & .divider { - margin: 10px 0; - background-color: @fl-body-control-bg; - } -} -.dropdown-split.item-count-1 { - & .btn { - border-radius: @border-radius-base !important; - } - & .dropdown-toggle { - display: none; - } -} - -// ------------------------------------ -// Tooltips - -.tooltip-inner { - padding: 5px 10px; -} - -// ------------------------------------ -// Loading Indicators - -.loading-indicator { - position: relative; - color: @fl-body-primary-color; -} -.loading-indicator-block { - height: 100px; -} - -// ------------------------------------ -// Avatars - -.avatar-size(@size) { - width: @size; - height: @size; - border-radius: @size / 2; - font-size: @size / 2; - line-height: @size; -} -.avatar { - display: inline-block; - color: @fl-body-bg; - font-weight: 300; - text-align: center; - vertical-align: top; - background-color: @fl-body-control-bg; - .avatar-size(48px); - - & img { - display: inline-block; - width: 100%; - height: 100%; - border-radius: 100%; - vertical-align: top; - } -} diff --git a/framework/core/ember/app/styles/flarum/composer.less b/framework/core/ember/app/styles/flarum/composer.less index 1be6a19a9..16f6c22b2 100644 --- a/framework/core/ember/app/styles/flarum/composer.less +++ b/framework/core/ember/app/styles/flarum/composer.less @@ -1,104 +1,24 @@ // ------------------------------------ // Composer -.composer-container { - position: fixed; - bottom: 0; - left: 0; - right: 0; - z-index: @zindex-composer; - pointer-events: none; - .transition(left 0.2s); - - .with-pane & { - left: @index-pane-width; - } -} .composer { pointer-events: auto; - margin-left: -20px; - margin-right: 180px; .box-shadow(0 2px 6px @fl-shadow-color); - border-radius: @border-radius-base @border-radius-base 0 0; - background: fade(@fl-body-bg, 95%); - transform: translateZ(0); // Fix for Chrome bug where a transparent white background is actually gray - position: relative; - height: 300px; - .transition(~"background 0.2s"); - - .index-index & { - margin-left: 205px; - margin-right: -20px; - } - &.active, &.fullscreen { - background: @fl-body-bg; - } - &.minimized { - height: 50px; - cursor: pointer; - } - &.fullscreen { - position: fixed; - left: 0; - top: 0; - bottom: 0; - right: 0; - margin: 0; - height: auto; - } -} -.composer-content { - padding: 20px 20px 15px; - - .minimized & { - padding: 10px 20px; - } - .fullscreen & { - max-width: 900px; - margin: 0 auto; - padding: 30px; - } -} -.composer-handle { - height: 20px; - margin-bottom: -20px; - position: relative; - - .minimized &, .fullscreen & { - display: none; - } } .composer-controls { - position: absolute; - right: 10px; - top: 10px; - list-style-type: none; + list-style: none; + padding: 0; + margin: 0; +} +.composer-header { + list-style: none; padding: 0; margin: 0; - & li { - display: inline-block; - } - .minimized & { - top: 7px; - } -} -.fa-minus.minimize { - vertical-align: -5px; -} -.composer-avatar { - float: left; - .avatar-size(64px); - - .minimized & { - display: none; - } -} -.composer-body { - margin-left: 90px; - & h3 { - margin: 5px 0 10px; + margin: 0 0 10px; + line-height: 1.5em; + &, & input { color: @fl-body-muted-color; font-size: 16px; @@ -111,16 +31,183 @@ height: auto; } } +} +.composer-loading { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(255, 255, 255, 0.9); + opacity: 0; + pointer-events: none; + border-radius: @border-radius-base @border-radius-base 0 0; + .transition(opacity 0.2s); - .minimized & { - margin-left: 0; + &.active { + opacity: 1; + pointer-events: auto; } } -.composer-editor { - .minimized & { - visibility: hidden; + +// On phones, show the composer as a fixed overlay that covers the whole +// screen. The controls are hidden (except for the 'x', which is the back- +// control), and the avatar hidden. +@media @phone { + .composer-open { + overflow: hidden; + } + .composer { + position: fixed; + bottom: 0; + left: 0; + right: 0; + z-index: @zindex-composer; + background: @fl-body-bg; + height: 100vh !important; + padding-top: 56px; + + &:before { + content: " "; + .toolbar(); + opacity: 0; + .transition(opacity 0.5s); + + .visible& { + opacity: 1; + } + } + } + .composer-content { + padding: 15px; + } + .composer-controls { + & li:not(.back-control) { + display: none; + } + } + .composer-avatar { + display: none; + } + .composer-body { + & h3 input { + width: 100% !important; + } } } + +// On larger screens, show the composer as a window at the bottom of the +// content area. We hide a lot of the content when the composer is minimized. +@media @tablet, @desktop, @desktop-hd { + .composer-container { + position: fixed; + bottom: 0; + left: 0; + right: 0; + z-index: @zindex-composer; + pointer-events: none; + .transition(left 0.2s); + + .with-pane & { + left: @index-pane-width; + } + } + .composer { + margin-left: -20px; + margin-right: 180px; + border-radius: @border-radius-base @border-radius-base 0 0; + background: fade(@fl-body-bg, 95%); + transform: translateZ(0); // Fix for Chrome bug where a transparent white background is actually gray + position: relative; + height: 300px; + .transition(~"background 0.2s"); + + .index-index & { + margin-left: 205px; + margin-right: -20px; + } + &.active, &.fullscreen { + background: @fl-body-bg; + } + &.minimized { + height: 50px; + cursor: pointer; + } + &.fullscreen { + position: fixed; + left: 0; + top: 0; + bottom: 0; + right: 0; + margin: 0; + height: auto; + } + } + .composer-content { + padding: 20px 20px 15px; + + .minimized & { + padding: 10px 20px; + } + .fullscreen & { + max-width: 900px; + margin: 0 auto; + padding: 30px; + } + } + .composer-handle { + height: 20px; + margin-bottom: -20px; + position: relative; + + .minimized &, .fullscreen & { + display: none; + } + } + .composer-controls { + position: absolute; + right: 10px; + top: 10px; + + & li { + display: inline-block; + } + .minimized & { + top: 7px; + } + } + .fa-minus.minimize { + vertical-align: -5px; + } + .composer-avatar { + float: left; + .avatar-size(64px); + + .minimized & { + display: none; + } + } + .composer-body { + margin-left: 90px; + + .minimized & { + margin-left: 0; + } + } + .composer-header h3 { + margin-top: 5px; + } + .composer-editor { + .minimized & { + visibility: hidden; + } + } +} + + +// ------------------------------------ +// Text Editor + .text-editor { & textarea { border-radius: 0; @@ -145,20 +232,10 @@ } } -.composer-loading { - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - background: rgba(255, 255, 255, 0.9); - opacity: 0; - pointer-events: none; - border-radius: @border-radius-base @border-radius-base 0 0; - .transition(opacity 0.2s); - - &.active { - opacity: 1; - pointer-events: auto; +// On phones, since one of the text editor controls will probably be the +// primary-control, we shouldn't hide it completely when it's "disabled". +@media @phone { + .text-editor-controls { + opacity: 0.5; } } diff --git a/framework/core/ember/app/styles/flarum/discussion.less b/framework/core/ember/app/styles/flarum/discussion.less index a75e93d48..e45717f5f 100644 --- a/framework/core/ember/app/styles/flarum/discussion.less +++ b/framework/core/ember/app/styles/flarum/discussion.less @@ -2,30 +2,38 @@ // Sidebar .discussion-nav { - float: right; - - &, & > ul { - width: 150px; - } & > ul { - position: fixed; - margin: 30px 0 0; padding: 0; - list-style-type: none; + margin: 0; + list-style: none; + } +} - & > li { - margin-bottom: 10px; +@media @tablet, @desktop, @desktop-hd { + .discussion-nav { + float: right; + + &, & > ul { + width: 150px; } - } - & .btn-group, & .btn { - width: 100%; - } - & .btn-group:not(.item-count-1) { - & .btn { - width: 77%; + & > ul { + position: fixed; + margin-top: 30px; + + & > li { + margin-bottom: 10px; + } } - & .dropdown-toggle { - width: 22%; + & .btn-group, & .btn { + width: 100%; + } + & .btn-group:not(.item-count-1) { + & .btn { + width: 77%; + } + & .dropdown-toggle { + width: 22%; + } } } } @@ -35,7 +43,7 @@ .discussion-posts { margin-top: 40px; - margin-right: 200px; + & .item { margin-bottom: 40px; } @@ -56,6 +64,7 @@ &:hover, &.loading, &.active { padding: 50px 0; + &.up:before, &.down:after { opacity: 1; } @@ -91,30 +100,39 @@ } } +@media @phone { + .gap { + margin-left: -15px; + margin-right: -15px; + border-left: 0; + border-right: 0; + } +} + +@media @tablet @desktop @desktop-hd { + .discussion-posts { + margin-right: 200px; + } +} + // ------------------------------------ // Posts .post { - padding-left: 90px; padding-bottom: 1px; transition: 0.2s box-shadow; & .contextual-controls { float: right; - margin: -2px 0 0 10px; - visibility: hidden; - } - &:hover .contextual-controls, & .contextual-controls.open { - visibility: visible; + margin-left: 10px; } } .item.highlight .post { border: 8px solid rgba(255, 255, 0, 0.2); border-radius: 8px; - padding: 15px 15px 1px 105px; - margin: -23px -23px -8px -23px; + padding: 15px; + margin: -23px; } - .post-header { margin-bottom: 10px; color: @fl-body-muted-color; @@ -123,39 +141,29 @@ list-style-type: none; padding: 0; margin: 0; + + &, & a { + color: @fl-body-muted-color; + } & > li { display: inline; margin-right: 10px; } - &, & a { - color: @fl-body-muted-color; - } } & .post-user { margin: 0; display: inline; font-weight: bold; font-size: 15px; + &, & a { color: @fl-body-heading-color; } } - & .avatar { - margin-left: -90px; - float: left; - .avatar-size(64px); - } } .post-body { font-size: 14px; - line-height: 1.6; -} -.post-icon { - float: left; - margin-left: -90px; - width: 64px; - text-align: right; - font-size: 22px; + line-height: 1.6em; } .post.is-hidden { & .post-user, & .post-header > ul, & .post-header > ul a:not(.btn) { @@ -193,6 +201,9 @@ } } +.post-icon { + float: left; +} .post-activity { &, & a { color: @fl-body-muted-color; @@ -249,84 +260,146 @@ } } +@media @phone { + .post-header { + & .avatar { + .avatar-size(32px); + vertical-align: middle; + margin-right: 5px; + } + } + .post-activity { + padding-left: 30px; + } + .post-icon { + font-size: 18px; + margin-left: -30px; + margin-top: 2px; + } +} + +@media @tablet @desktop @desktop-hd { + .post { + padding-left: 90px; + + & .contextual-controls { + visibility: hidden; + } + &:hover .contextual-controls, & .contextual-controls.open { + visibility: visible; + } + } + .item.highlight .post { + padding-left: 90px + 15px; + } + .post-header { + & .avatar { + margin-left: -90px; + float: left; + .avatar-size(64px); + } + } + .post-icon { + text-align: right; + margin-left: -90px; + width: 64px; + font-size: 22px; + } +} + // ------------------------------------ // Scrubber -@media (min-width: @screen-md-min) { - .stream-scrubber { - margin: 30px 0 0 0; - } - .scrubber { - & a { - margin-left: -5px; - color: @fl-body-muted-color; - & .fa { - font-size: 14px; - margin-right: 2px; - } - &:hover, &:focus { - text-decoration: none; - color: @link-hover-color; - } +.scrubber { + & a { + margin-left: -5px; + color: @fl-body-muted-color; + & .fa { + font-size: 14px; + margin-right: 2px; } - } - .scrubber-scrollbar { - margin: 8px 0 8px 3px; - height: 300px; - min-height: 50px; // JavaScript sets a max-height - position: relative; - } - .scrubber-before, .scrubber-after { - border-left: 1px solid @fl-body-secondary-color; - } - .scrubber-slider { - position: relative; - width: 100%; - padding: 5px 0; - } - .scrubber-handle { - height: 100%; - width: 5px; - background: @fl-body-primary-color; - border-radius: 4px; - float: left; - margin-left: -2px; - transition: background 0.2s; - .disabled & { - background: @fl-body-secondary-color; + &:hover, &:focus { + text-decoration: none; + color: @link-hover-color; } } - .scrubber-info { - height: (2em * @line-height-base); - margin-top: (-1em * @line-height-base); - position: absolute; - top: 50%; - width: 100%; - left: 15px; - & strong { - display: block; - } - & .description { - color: @fl-body-muted-color; - } - } - .scrubber-highlights { - position: absolute; - left: 0; - right: 0; - top: 0; - bottom: 0; - list-style-type: none; - pointer-events: none; - } - .scrubber-highlights li { - position: absolute; - right: -6px; - background: #fc0; - height: 8px; - width: 13px; - border-radius: 4px; - box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.15), inset 0 0 0 1px rgba(255, 255, 255, 0.5); - opacity: 0.99; - } +} +.scrubber-scrollbar { + margin: 8px 0 8px 3px; + height: 300px; + min-height: 50px; // JavaScript sets a max-height + position: relative; +} +.scrubber-before, .scrubber-after { + border-left: 1px solid @fl-body-secondary-color; +} +.scrubber-slider { + position: relative; + width: 100%; + padding: 5px 0; +} +.scrubber-handle { + height: 100%; + width: 5px; + background: @fl-body-primary-color; + border-radius: 4px; + float: left; + margin-left: -2px; + transition: background 0.2s; + .disabled & { + background: @fl-body-secondary-color; + } +} +.scrubber-info { + height: (2em * @line-height-base); + margin-top: (-1em * @line-height-base); + position: absolute; + top: 50%; + width: 100%; + left: 15px; + & strong { + display: block; + } + & .description { + color: @fl-body-muted-color; + } +} +.scrubber-highlights { + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; + list-style-type: none; + pointer-events: none; +} +.scrubber-highlights li { + position: absolute; + right: -6px; + background: #fc0; + height: 8px; + width: 13px; + border-radius: 4px; + box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.15), inset 0 0 0 1px rgba(255, 255, 255, 0.5); + opacity: 0.99; +} + +@media @phone { + .stream-scrubber { + & .dropdown-toggle { + font-size: 14px; + } + & .dropdown-menu { + padding: 30px; + font-size: 14px; + } + } +} + +@media @tablet, @desktop, @desktop-hd { + .stream-scrubber { + margin: 30px 0 0 0; + + .expand-dropdown(); + } } diff --git a/framework/core/ember/app/styles/flarum/dropdowns.less b/framework/core/ember/app/styles/flarum/dropdowns.less new file mode 100644 index 000000000..4b198f589 --- /dev/null +++ b/framework/core/ember/app/styles/flarum/dropdowns.less @@ -0,0 +1,112 @@ +.dropdown-menu { + border: 0; + padding: 8px 0; + margin-top: 7px; + background: @fl-body-bg; + .box-shadow(0 2px 6px @fl-shadow-color); + + & > li > a { + padding: 8px 15px; + color: @fl-body-color; + &:hover, &:focus { + color: @fl-body-color; + background-color: @fl-body-control-bg; + } + & .fa { + margin-right: 5px; + font-size: 14px; + } + } + & .divider { + margin: 10px 0; + background-color: @fl-body-control-bg; + } +} +.dropdown-split.item-count-1 { + & .btn { + border-radius: @border-radius-base !important; + } + & .dropdown-toggle { + display: none; + } +} + +// PHONES +@media (max-width: @screen-xs-max) { + .dropdown-open { + overflow: hidden; + } + .dropdown-menu { + margin: 0; + position: fixed; + left: 0 !important; + right: 0 !important; + width: auto !important; + bottom: -100vh; + top: auto; + padding: 0; + z-index: @zindex-modal; + display: block; + max-height: 100vh; + border-radius: 0; + .box-shadow(none); + .transition(bottom 0.3s); + + &:before { + content: " "; + position: absolute; + left: 0; + right: 0; + bottom: 100%; + height: 200vh; + z-index: -1; + background: fade(@fl-body-primary-color, 90%); + pointer-events: none; + opacity: 0; + .transition(opacity 0.3s); + } + & > li > a { + background: #fff; + font-size: 16px; + padding: 15px 20px; + + & .fa { + font-size: 16px; + margin-right: 10px; + } + } + & .divider { + margin: 0; + } + + .open & { + bottom: 0; + + &:before { + opacity: 1; + pointer-events: auto; + } + } + } +} + +// ------------------------------------ +// Mixins + +.expand-dropdown() { + & .dropdown-toggle { + display: none; + } + & .dropdown-menu { + display: block; + border: 0; + width: auto; + margin: 0; + padding: 0; + min-width: 0; + float: none; + position: static; + background: none; + .box-shadow(none); + } +} diff --git a/framework/core/ember/app/styles/flarum/forms.less b/framework/core/ember/app/styles/flarum/forms.less new file mode 100644 index 000000000..3e218e322 --- /dev/null +++ b/framework/core/ember/app/styles/flarum/forms.less @@ -0,0 +1,71 @@ +.form-group { + margin-bottom: 12px; +} +.form-control { + .box-shadow(none); + &:focus, + &.focus { + background-color: #fff; + color: @fl-body-color; + .box-shadow(none); + } +} + +// Search inputs +// @todo Extract some of this into header-specific definitions +.search-input { + overflow: hidden; + + &:before { + .fa(); + content: @fa-var-search; + float: left; + margin-right: -36px; + width: 36px; + font-size: 14px; + text-align: center; + color: @fl-body-muted-color; + position: relative; + padding: @padding-base-vertical - 1 0; + line-height: @line-height-base; + pointer-events: none; + } + & .form-control { + float: left; + width: 225px; + padding-left: 36px; + padding-right: 36px; + .transition(~"all 0.4s"); + } + & .clear { + float: left; + margin-left: -36px; + vertical-align: top; + opacity: 0; + width: 36px !important; + .rotate(-180deg); + .transition(~"transform 0.2s, opacity 0.2s"); + } + &.clearable .clear { + opacity: 1; + .rotate(0deg); + } +} + +// Select inputs +.select-input { + display: inline-block; + vertical-align: middle; +} +.select-input select { + display: inline-block; + width: auto; + -webkit-appearance: none; + padding-right: @padding-base-horizontal + 16; + cursor: pointer; +} +.select-input .fa { + margin-left: -@padding-base-horizontal - 16; + pointer-events: none; + color: @fl-body-muted-color; +} diff --git a/framework/core/ember/app/styles/flarum/hero.less b/framework/core/ember/app/styles/flarum/hero.less new file mode 100644 index 000000000..6627e7c32 --- /dev/null +++ b/framework/core/ember/app/styles/flarum/hero.less @@ -0,0 +1,42 @@ +.hero { + background: @fl-body-hero-bg; + text-align: center; + padding: 20px 0; + + &, & a, & .close { + color: @fl-body-hero-color; + } + & a, & .close { + opacity: 0.5; + } + & .close { + float: right; + margin-top: -10px; + } + & h2 { + margin: 0; + font-size: 16px; + font-weight: normal; + line-height: 1.5em; + } + & p { + margin: 5px 0 0; + } +} +@media @phone { + .hero { + & .close { + margin-right: -10px; + } + } +} +@media @tablet, @desktop, @desktop-hd { + .hero { + padding: 30px 0; + font-size: 14px; + + & h2 { + font-size: 22px; + } + } +} diff --git a/framework/core/ember/app/styles/flarum/index.less b/framework/core/ember/app/styles/flarum/index.less index 1ec9cc49e..0b1269fc3 100644 --- a/framework/core/ember/app/styles/flarum/index.less +++ b/framework/core/ember/app/styles/flarum/index.less @@ -1,64 +1,66 @@ // ------------------------------------ // Sidebar -.index-nav { - float: left; +.index-nav > ul { + margin: 0; + padding: 0; + list-style: none; +} - &, & > ul { - width: 175px; - } - & > ul { - margin: 30px 0 0; - padding: 0; - list-style-type: none; +// On phones, the index sidebar will pretty much take care of itself. The +// navigation list is a .dropdown-select and will be shown as the title- +// control; the new discussion button is the primary-control. On anything +// larger than a phone, however, we need to affix the sidebar and expand the +// .dropdown-select into a plain list. +@media @tablet, @desktop, @desktop-hd { + .index-nav { + float: left; - &.affix { - top: 56px; + &, & > ul { + width: 175px; } - & > li { - margin-bottom: 10px; - } - } - & .new-discussion { - display: block; - margin-bottom: 20px; - } + & > ul { + margin-top: 30px; - // Expand the dropdown-select component into a normal nav list - // @todo Extract this into a mixin as we'll need to do it elsewhere. - & .dropdown-select { - display: block; - - & .dropdown-toggle { - display: none; - } - & .dropdown-menu { - display: block; - border: 0; - width: auto; - margin: 0; - padding: 0; - min-width: 0; - float: none; - position: static; - background: none; - .box-shadow(none); - & > li > a { - padding: 8px 0; - color: @fl-body-muted-color; - & .fa { - margin-right: 8px; - font-size: 15px; - } - &:hover { - background: none; - color: @link-hover-color; - } + &.affix { + top: 56px; } - & > li.active > a { - background: none; - color: @fl-body-primary-color; - font-weight: bold; + & > li { + margin-bottom: 10px; + } + } + & .new-discussion { + display: block; + margin-bottom: 20px; + } + + // Expand the dropdown-select component into a normal nav list + // @todo Extract this into a mixin as we'll probably need to do it elsewhere. + & .dropdown-select { + display: block; + + .expand-dropdown(); + + & .dropdown-menu { + & > li > a { + padding: 8px 0; + color: @fl-body-muted-color; + + &:hover { + background: none; + color: @link-hover-color; + } + + & .fa { + margin-right: 8px; + font-size: 15px; + } + } + & > li.active > a { + background: none; + color: @fl-body-primary-color; + font-weight: bold; + } } } } @@ -67,18 +69,12 @@ // ------------------------------------ // Results -.index-results { - margin-top: 30px; - margin-left: 225px; - & .loading-indicator { - height: 46px; - } -} .index-toolbar { margin-bottom: 15px; } .index-toolbar-view { display: inline-block; + & .control-show { margin-right: 10px; } @@ -86,78 +82,98 @@ .index-toolbar-action { float: right; } +.index-results .loading-indicator { + height: 46px; +} + +@media @phone { + .index-results { + margin-top: 15px; + } +} + +@media @tablet, @desktop, @desktop-hd { + .index-results { + margin-top: 30px; + margin-left: 225px; + } +} // ------------------------------------ // Discussions Pane -@index-pane-width: 400px; - -.index-area { - left: -@index-pane-width; - width: 100%; - - &.paned { - position: fixed; - z-index: @zindex-pane; - overflow: auto; - top: 56px; - bottom: 0; - width: @index-pane-width; - background: @fl-body-bg; - padding-bottom: 200px; - .box-shadow(2px 2px 6px -2px @fl-shadow-color); - .transition(left 0.2s); - - &.showing, .with-pane & { - left: 0; - } - .with-pane & { - z-index: @zindex-composer - 1; - .transition(none); - } - & .container { - width: auto; - margin: 0; - padding: 0 !important; - } - & .index-results { - margin: 0; - } - & .hero, & .index-nav, & .index-toolbar { - display: none; - } - & .discussions-list > li { - margin: 0; - padding-left: 65px + 15px; - padding-right: 65px + 15px; - &.active { - background: @fl-body-control-bg; - } - } - & .discussion-summary { - & .title { - font-size: 14px; - } - & .count strong { - font-size: 18px; - } - } - } +.index-area.paned { + display: none; } -// When the pane is pinned, move the other page content inwards -.global-main, .global-footer { - .with-pane & { - margin-left: @index-pane-width; - & .container { - max-width: 100%; - padding: 0 30px; - } - } -} -.global-header .container { - .with-pane & { +@media @tablet, @desktop, @desktop-hd { + .index-area { + left: -@index-pane-width; width: 100%; + + &.paned { + position: fixed; + z-index: @zindex-pane; + overflow: auto; + top: 56px; + bottom: 0; + width: @index-pane-width; + background: @fl-body-bg; + padding-bottom: 200px; + .box-shadow(2px 2px 6px -2px @fl-shadow-color); + .transition(left 0.2s); + + &.showing, .with-pane & { + left: 0; + } + .with-pane & { + z-index: @zindex-composer - 1; + .transition(none); + } + & .container { + width: auto; + margin: 0; + padding: 0 !important; + } + & .index-results { + margin: 0; + } + & .hero, & .index-nav, & .index-toolbar { + display: none; + } + & .discussions-list > li { + margin: 0; + padding-left: 65px + 15px; + padding-right: 65px + 15px; + &.active { + background: @fl-body-control-bg; + } + } + & .discussion-summary { + & .title { + font-size: 14px; + } + & .count strong { + font-size: 18px; + } + } + } + } + + // When the pane is pinned, move the other page content inwards + .global-main, .global-footer { + .with-pane & { + margin-left: @index-pane-width; + & .container { + max-width: 100%; + padding: 0 30px; + } + } + } + .global-header .container { + .with-pane & { + width: 100%; + } } } @@ -169,24 +185,38 @@ padding: 0; list-style-type: none; position: relative; +} + +@media @phone { + .discussions-list > li { + padding-right: 45px; - & > li { - margin-right: -25px; - padding-right: 65px + 25px; & .contextual-controls { - position: absolute; - right: 0; - top: 18px; - visibility: hidden; - } - &:hover .contextual-controls, & .contextual-controls.open { - visibility: visible; + display: none; } } } + +@media @tablet, @desktop, @desktop-hd { + .discussions-list { + & > li { + margin-right: -25px; + padding-right: 65px + 25px; + + & .contextual-controls { + position: absolute; + right: 0; + top: 18px; + visibility: hidden; + } + &:hover .contextual-controls, & .contextual-controls.open { + visibility: visible; + } + } + } +} + .discussion-summary { - padding-left: 65px; - padding-right: 65px; position: relative; &, & a { @@ -195,25 +225,21 @@ } & .author { float: left; - margin-left: -65px; margin-top: 18px; } & .main { display: inline-block; width: 100%; padding: 20px 0; - margin-right: -65px; - - &.active { - text-decoration: none; - } - &:hover .title { - text-decoration: underline; - } + } + &.active { + text-decoration: none; + } + &:hover .title { + text-decoration: underline; } & .title { margin: 0 0 5px; - font-size: 15px; line-height: 1.3; } &.unread .title { @@ -229,33 +255,94 @@ display: inline-block; } } + & .username { + font-weight: bold; + } & .count { float: right; margin-top: 18px; - margin-right: -65px; - width: 60px; - text-align: center; - text-transform: uppercase; - color: @fl-body-muted-color; - font-size: 11px; text-decoration: none; - & strong { - font-size: 20px; - display: block; - font-weight: 300; - } .unread& { cursor: pointer; } - .unread&, .unread& strong { - color: @fl-body-heading-color; - font-weight: bold; - } } } - .load-more { text-align: center; margin-top: 10px; } + +@media @phone { + .discussion-summary { + padding-left: 45px; + padding-right: 45px; + + & .author { + margin-left: -45px; + } + & .avatar { + .avatar-size(32px); + } + & .main { + margin-right: -45px; + } + & .title { + font-size: 14px; + } + & .count { + margin-right: -45px; + background: @fl-body-control-bg; + color: @fl-body-control-color; + border-radius: @border-radius-base; + font-size: 12px; + padding: 1px 6px; + + .unread& { + background: @fl-body-primary-color; + color: #fff; + font-weight: bold; + } + + & .label { + display: none; + } + } + } +} + +@media @tablet, @desktop, @desktop-hd { + .discussion-summary { + padding-left: 65px; + padding-right: 65px; + + & .author { + margin-left: -65px; + } + & .main { + margin-right: -65px; + } + & .title { + font-size: 15px; + } + & .count { + margin-right: -65px; + width: 60px; + text-align: center; + text-transform: uppercase; + color: @fl-body-muted-color; + font-size: 20px; + font-weight: 300; + + & .label { + font-size: 11px; + display: block; + font-weight: normal; + } + .unread& { + color: @fl-body-heading-color; + font-weight: bold; + } + } + } +} diff --git a/framework/core/ember/app/styles/flarum/layout.less b/framework/core/ember/app/styles/flarum/layout.less index 617cbe0ea..72d1e0df1 100644 --- a/framework/core/ember/app/styles/flarum/layout.less +++ b/framework/core/ember/app/styles/flarum/layout.less @@ -1,194 +1,426 @@ body { background: @fl-body-bg; color: @fl-body-color; - padding-top: 56px; } .container-narrow { max-width: 500px; margin: 0 auto; } +.global-page { + overflow: hidden; +} // ------------------------------------ -// Header +// Page Toolbar -.global-header { +.toolbar() { background: fade(@fl-hdr-bg, 98%); transform: translateZ(0); // Fix for Chrome bug where a transparent white background is actually gray - padding: 10px; height: 56px; position: fixed; top: 0; left: 0; right: 0; z-index: @zindex-navbar-fixed; - .clearfix(); - .transition(box-shadow 0.2s); + border-bottom: 1px solid @fl-body-control-bg; + .transition(~"box-shadow 0.2s, left 0.2s"); +} + +// Fix a solid white box to the top of the viewport. This toolbar's contents +// will differ depending on the device: on phones it will be content +// controls, whereas on desktops it will be the header. We will overlay +// these things on top of it later. +.global-page:before { + content: " "; + .toolbar(); .scrolled & { + border-bottom: 0; .box-shadow(0 2px 6px @fl-shadow-color); } - & when (@fl-colored-hdr = true) { - &, & .btn-link { - color: @fl-hdr-control-color; + // PHONES: Push the toolbar to the right when the drawer is open. + @media @phone { + .drawer-open & { + left: @drawer-width; } - & .form-control { - background: @fl-hdr-control-bg; - border: 0; - color: @fl-hdr-control-color; - .placeholder(@fl-hdr-control-color); + } +} - &:focus { - background: fadein(@fl-hdr-control-bg, 5%); +// PHONES: Somewhere on the page there will be a .back-button, a .primary- +// control, and a .title-control. We will position these on the left, right, +// and center of the header respectively. +@media @phone { + .primary-control, .title-control, .back-control { + position: fixed; + z-index: @zindex-navbar-fixed + 1; + top: 10px; + margin: 0; + + & .btn { + float: none; + background: transparent !important; + .box-shadow(~"none !important"); + + &:active { + opacity: 0.5; } } - & .search-input:before { - color: @fl-hdr-control-color; - } - & .btn-default, & .btn-default:hover { - background: @fl-hdr-control-bg; - color: @fl-hdr-control-color; - } - & .btn-default.active, .open > .dropdown-toggle.btn-default { - background: fadein(@fl-hdr-control-bg, 5%); - } - & .btn-naked { - background: transparent; - } } -} -.header-controls { - margin: 0; - padding: 0; - list-style-type: none; - &, & > li { - display: inline-block; - vertical-align: top; - } -} -.header-primary { - float: left; - & h1 { - display: inline-block; - vertical-align: top; - } -} -.header-title { - font-size: 18px; - font-weight: normal; - margin: 0; - line-height: 36px; - &, & a { - color: @fl-hdr-color; - } -} -.header-secondary { - float: right; -} + .primary-control { + width: auto; + right: 10px; + .transition(right 0.2s); -// Back button -// @todo Lots of !importants in here, could we be more specific? -.back-button { - float: left; - margin-right: 25px; + .drawer-open .global-page & { + right: -@drawer-width; + } - & .back { - z-index: 3 !important; // z-index of an active .btn-group .btn is 2 - border-radius: @border-radius-base !important; - .transition(border-radius 0.2s); - } - & .pin { - opacity: 0; - margin-left: -36px !important; - .transition(~"opacity 0.2s, margin-left 0.2s"); - - &:not(.active) .fa { - .rotate(45deg); + & .dropdown-split { + & .btn, & .icon-caret { + display: none; + } + & .dropdown-toggle { + display: block; + } } } - &.active { - & .back { - border-radius: @border-radius-base 0 0 @border-radius-base !important; + .primary-control, .back-control { + & .btn { + color: @fl-hdr-control-color !important; + padding-left: 5px; + padding-right: 5px; + + & .icon-glyph { + display: block; + font-size: 18px; + } + & .label { + display: none; + } } + } + .title-control { + width: 200px; + left: 50%; + margin-left: -100px; + text-align: center; + .transition(margin-left 0.2s); + + .drawer-open .global-page & { + margin-left: -100px + @drawer-width; + } + + &, & .btn { + color: @fl-hdr-color; + font-size: 16px; + } + } + .back-control { + left: 10px; + .transition(left 0.2s); + + .drawer-open .global-page & { + left: @drawer-width + 10px; + } + & .pin { - opacity: 1; - margin-left: 1px !important; + display: none; } } } // ------------------------------------ -// Main +// Drawer -.global-main, .paned { - border-top: 1px solid @fl-body-control-bg; -} - -// Hero -.hero { - background: @fl-body-hero-bg; - margin-top: -1px; - text-align: center; - padding: 30px 0; - font-size: 14px; - - &, & a { - color: @fl-body-hero-color; +// This is a mixin which styles components (buttons, inputs, etc.) for use in +// the drawer. We define it as a mixin because it is also pulled in when +// styling a "colored header". +.drawer-components() { + .header-title { + &, & a { + color: @fl-drawer-color; + } } - & a { - opacity: 0.5; + &, & a, & .btn-link { + color: @fl-drawer-control-color; + } + & .form-control { + background: @fl-drawer-control-bg; + border: 0; + color: @fl-drawer-control-color; + .placeholder(@fl-drawer-control-color); + + &:focus { + background: fadein(@fl-drawer-control-bg, 5%); + } + } + & .search-input:before { + color: @fl-drawer-control-color; + } + & .btn-default, & .btn-default:hover { + background: @fl-drawer-control-bg; + color: @fl-drawer-control-color; + } + & .btn-default.active, .open > .dropdown-toggle.btn-default { + background: fadein(@fl-drawer-control-bg, 5%); + } + & .btn-naked { + background: transparent; } } -.hero .close { - float: right; - margin-top: -10px; - color: #fff; - opacity: 0.5; + +// PHONES: On phones, the drawer is displayed in its semantic sense: as a +// drawer on the left side of the screen. On other devices, the drawer has no +// specific appearance. +@media @phone { + .drawer-open { + overflow: hidden; + } + .global-drawer { + background: @fl-drawer-bg; + color: @fl-drawer-color; + width: @drawer-width; + position: fixed; + left: 0; + top: 0; + bottom: 0; + + .drawer-components(); + } } -.hero h2 { + +// ------------------------------------ +// Header + +.header-controls { margin: 0; - font-size: 22px; - font-weight: normal; + padding: 0; + list-style: none; } -.hero p { - margin: 10px 0 0; + +// On phones, the header is displayed inside of the drawer. We lay its +// contents out vertically. +@media @phone { + .global-header .container { + padding: 0; + } + .header-title { + border-bottom: 1px solid @fl-drawer-control-bg; + font-size: 16px; + font-weight: normal; + margin: 0; + line-height: 56px; + white-space: nowrap; + text-align: center; + } + .header-controls { + & > li { + padding: 10px 10px 0; + } + & .form-control, & .btn-group, & .btn { + width: 100%; + text-align: left; + } + } +} + +// On other devices, we stick the header up the top of the page, overlaying +// the page toolbar that we styled earlier. We lay its contents out +// horizontally. +@media @tablet, @desktop, @desktop-hd { + .global-header { + padding: 10px; + height: 56px; + position: fixed; + top: 0; + left: 0; + right: 0; + z-index: @zindex-navbar-fixed; + .clearfix(); + + & when (@fl-colored-hdr = true) { + .drawer-components(); + } + } + .header-controls { + &, & > li { + display: inline-block; + vertical-align: top; + } + } + .header-primary { + float: left; + } + .header-title { + display: inline-block; + vertical-align: top; + font-size: 18px; + font-weight: normal; + margin: 0; + line-height: 36px; + + &, & a { + color: @fl-hdr-color; + } + } + .header-secondary { + float: right; + + & .search-input { + margin-right: 10px; + + &:focus { + width: 400px; + } + } + } + .back-control { + float: left; + margin-right: 25px; + + & .back { + z-index: 3 !important; // z-index of an active .btn-group .btn is 2 + border-radius: @border-radius-base !important; + .transition(border-radius 0.2s); + } + & .pin { + opacity: 0; + margin-left: -36px !important; + .transition(~"opacity 0.2s, margin-left 0.2s"); + + &:not(.active) .fa { + .rotate(45deg); + } + } + &.active { + & .back { + border-radius: @border-radius-base 0 0 @border-radius-base !important; + } + & .pin { + opacity: 1; + margin-left: 1px !important; + } + } + } +} + +// ------------------------------------ +// Content Area + +.global-content { + padding-top: 56px; +} + +// On phones, the content area overlays the drawer, so we must give it a +// background and min-height so it cannot be seen through. When the drawer is +// meant to be open, we slide the content to the right to reveal the drawer. +@media @phone { + .global-content { + background: @fl-body-bg; + position: relative; + width: 100%; + min-height: 100vh; + padding-bottom: 15px; + .transition(margin-left 0.2s); + .box-shadow(0 0 6px @fl-shadow-color); + + .drawer-open & { + margin-left: @drawer-width; + } + } } // ------------------------------------ // Footer -.global-footer { - margin: 100px 0 20px; - color: @fl-body-muted-more-color; - .clearfix(); -} .footer-primary, .footer-secondary { margin: 0; padding: 0; - list-style-type: none; + list-style: none; & > li { display: inline-block; vertical-align: middle; } - & a { - color: @fl-body-muted-more-color; - &:hover, - &:focus { - text-decoration: none; - color: @link-hover-color; +} + +// On phones, the footer is displayed at the bottom of the drawer. The +// footer's primary controls don't display, but the secondary ones do. +// @todo Maybe we should reverse the naming of primary/secondary then? +@media @phone { + .global-footer { + position: fixed; + left: 15px; + bottom: 15px; + width: @drawer-width; + margin: 0; + z-index: 1; + + & .container { + padding: 0; + } + } + .footer-primary { + display: none; + } + .footer-secondary { + float: none; + + & > li { + margin-right: 15px; } } } -.footer-primary { - display: inline-block; - & > li { - margin-right: 15px; + +// On other devices, we put the footer at the bottom of the page by absolutely +// positioning it, relative to the page which we pad out at the bottom. We +// show the primary controls on the left, and the secondary controls on the +// right. +@media @tablet, @desktop, @desktop-hd { + .global-page { + padding-bottom: 150px; + position: relative; + } + .global-footer { + position: absolute; + bottom: 20px; + left: 0; + right: 0; + + &, & a { + color: @fl-body-muted-more-color; + } + & a { + &:hover, + &:focus { + text-decoration: none; + color: @link-hover-color; + } + } + } + .footer-primary { + display: inline-block; + + & > li { + margin-right: 15px; + } + } + .footer-secondary { + float: right; + + & > li { + margin-left: 15px; + } } } -.footer-secondary { - float: right; - & > li { - margin-left: 15px; + +// ------------------------------------ +// Miscellaneous + +// On phones, we disregard "affixed" elements and make them static. +@media @phone { + .affix { + position: static; } } diff --git a/framework/core/ember/app/styles/flarum/modals.less b/framework/core/ember/app/styles/flarum/modals.less index 1ff03b97d..9a6851be5 100644 --- a/framework/core/ember/app/styles/flarum/modals.less +++ b/framework/core/ember/app/styles/flarum/modals.less @@ -7,34 +7,6 @@ opacity: 0.9; } } -.modal-dialog { - margin: 120px auto; - - & .close { - position: absolute; - right: 5px; - top: 5px; - } -} -.modal-content { - border: 0; - border-radius: @border-radius-base; - .box-shadow(0 7px 15px @fl-shadow-color); -} -.modal-sm { - width: 375px; -} - -.modal-header { - text-align: center; - border: 0; - padding: 25px; - - & h3 { - font-size: 22px; - margin: 0; - } -} .modal-body { background-color: @fl-body-secondary-color; padding: 25px; @@ -49,7 +21,6 @@ text-align: center; color: @fl-body-muted-color; } - .modal-loading { position: absolute; top: 0; @@ -67,7 +38,6 @@ pointer-events: auto; } } - .form-centered { text-align: center; @@ -77,3 +47,83 @@ text-align: center; } } + + +@media @phone { + .modal.fade { + opacity: 1; + } + .modal-backdrop.in { + opacity: 0; + } + .modal-dialog { + position: fixed; + left: 0; + right: 0; + bottom: 0; + top: 0; + } + .modal-dialog { + margin: 0; + + .modal.fade & { + .transition(top 0.3s); + top: 100%; + .translate(0, 0); + } + .modal.in & { + top: 0; + } + + &:before { + content: " "; + .toolbar(); + } + } + .modal-content { + border-radius: 0; + border: 0; + min-height: 100vh; + padding-top: 56px; + .box-shadow(none); + } + .modal-header { + padding: 0; + border: 0; + min-height: 0; + + & h3 { + line-height: 36px; + } + } +} + +@media @tablet, @desktop, @desktop-hd { + .modal-dialog { + margin: 120px auto; + + & .close { + position: absolute; + right: 5px; + top: 5px; + } + } + .modal-content { + border: 0; + border-radius: @border-radius-base; + .box-shadow(0 7px 15px @fl-shadow-color); + } + .modal-sm { + width: 375px; + } + .modal-header { + text-align: center; + border: 0; + padding: 25px; + + & h3 { + font-size: 22px; + margin: 0; + } + } +} diff --git a/framework/core/ember/app/styles/flarum/signup.less b/framework/core/ember/app/styles/flarum/signup.less index 86355bb77..5af51278b 100644 --- a/framework/core/ember/app/styles/flarum/signup.less +++ b/framework/core/ember/app/styles/flarum/signup.less @@ -21,3 +21,9 @@ color: #fff; } } + +@media @phone { + .signup-welcome { + padding-top: 56px + 60px; + } +} diff --git a/framework/core/ember/app/templates/application.hbs b/framework/core/ember/app/templates/application.hbs index eb534f2bf..aacd68c31 100644 --- a/framework/core/ember/app/templates/application.hbs +++ b/framework/core/ember/app/templates/application.hbs @@ -1,34 +1,40 @@ -