mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-11-24 06:35:49 +03:00
Implement popovers
This commit is contained in:
parent
133aff0626
commit
3a13563f0b
@ -258,52 +258,52 @@
|
||||
|
||||
%dropdown-triangle-top {
|
||||
&:before {
|
||||
@include triangle(($dropdown_triangle * 2), #fff, up);
|
||||
@include triangle($dropdown_triangle, #fff, up);
|
||||
top: -$dropdown_triangle;
|
||||
}
|
||||
&:after {
|
||||
@include triangle(($dropdown_triangle * 2) + 2, darken($lightgrey, 15%), up);
|
||||
top: -($dropdown_triangle + 1);
|
||||
@include triangle($dropdown_triangle + 2, darken($lightgrey, 15%), up);
|
||||
top: -($dropdown_triangle + 2);
|
||||
}
|
||||
}
|
||||
%dropdown-triangle-bottom {
|
||||
&:before {
|
||||
@include triangle(($dropdown_triangle * 2), #fff, down);
|
||||
@include triangle($dropdown_triangle, #fff, down);
|
||||
bottom: -$dropdown_triangle;
|
||||
}
|
||||
&:after {
|
||||
@include triangle(($dropdown_triangle * 2) + 2, darken($lightgrey, 15%), down);
|
||||
bottom: -($dropdown_triangle + 1);
|
||||
@include triangle($dropdown_triangle + 2, darken($lightgrey, 15%), down);
|
||||
bottom: -($dropdown_triangle + 2);
|
||||
}
|
||||
}
|
||||
%dropdown-triangle-center {
|
||||
&:before {
|
||||
left: 50%;
|
||||
margin-left: (-$dropdown_triangle);
|
||||
margin-left: -($dropdown_triangle / 2);
|
||||
}
|
||||
&:after {
|
||||
left: 50%;
|
||||
margin-left: -($dropdown_triangle + 1);
|
||||
margin-left: -($dropdown_triangle / 2 + 2);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Make the values here use the $dropdown_triangle var
|
||||
%dropdown-triangle-left {
|
||||
&:before {
|
||||
left: ($dropdown_triangle + 2);
|
||||
left: ($dropdown_triangle / 2 + 2);
|
||||
}
|
||||
&:after {
|
||||
left: ($dropdown_triangle + 1);
|
||||
left: ($dropdown_triangle / 2);
|
||||
}
|
||||
}
|
||||
%dropdown-triangle-right {
|
||||
&:before {
|
||||
left: auto;
|
||||
right: ($dropdown_triangle + 2);
|
||||
right: ($dropdown_triangle / 2 + 2);
|
||||
}
|
||||
&:after {
|
||||
left: auto;
|
||||
right: ($dropdown_triangle + 1);
|
||||
right: ($dropdown_triangle / 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
265
ghost/admin/assets/sass/components/popovers.scss
Normal file
265
ghost/admin/assets/sass/components/popovers.scss
Normal file
@ -0,0 +1,265 @@
|
||||
//
|
||||
// Popovers
|
||||
// --------------------------------------------------
|
||||
|
||||
.popover-item {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
padding: 11px 26px 13px 16px;
|
||||
background: $darkgrey;
|
||||
min-width: 300px;
|
||||
max-width: 400px;
|
||||
border-radius: 6px;
|
||||
font-size: 1.2rem;
|
||||
color: $midgrey;
|
||||
}
|
||||
.popover-title {
|
||||
font-size: 1.4rem;
|
||||
font-weight: 300;
|
||||
color: #fff;
|
||||
}
|
||||
.popover-desc {
|
||||
margin-top: -4px;
|
||||
}
|
||||
.popover-body {
|
||||
margin-top: 11px;
|
||||
line-height: 1.7;
|
||||
b {
|
||||
color: #fff;
|
||||
}
|
||||
> *:last-child {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Popover triangles
|
||||
// --------------------------------------------------
|
||||
|
||||
// Placeholders
|
||||
%popover-triangle {
|
||||
&:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
display: block;
|
||||
} // :before
|
||||
}
|
||||
|
||||
// The triangle itself
|
||||
%popover-triangle-vertical-top {
|
||||
&:before {
|
||||
@include triangle($popover_triangle, $darkgrey, up, shallow);
|
||||
top: -(floor($popover_triangle * $popover_triangle_shallow_multiplier));
|
||||
}
|
||||
}
|
||||
%popover-triangle-vertical-bottom {
|
||||
&:before {
|
||||
@include triangle($popover_triangle, $darkgrey, down, shallow);
|
||||
bottom: -(floor($popover_triangle * $popover_triangle_shallow_multiplier));
|
||||
}
|
||||
}
|
||||
%popover-triangle-horizontal-left {
|
||||
&:before {
|
||||
@include triangle($popover_triangle, $darkgrey, left, shallow);
|
||||
left: -(floor($popover_triangle * $popover_triangle_shallow_multiplier));
|
||||
}
|
||||
}
|
||||
%popover-triangle-horizontal-right {
|
||||
&:before {
|
||||
@include triangle($popover_triangle, $darkgrey, right, shallow);
|
||||
right: -(floor($popover_triangle * $popover_triangle_shallow_multiplier));
|
||||
}
|
||||
}
|
||||
|
||||
// Triangle positions
|
||||
%popover-triangle-vertical-center {
|
||||
&:before {
|
||||
left: 50%;
|
||||
margin-left: -($popover_triangle / 2);
|
||||
}
|
||||
}
|
||||
%popover-triangle-vertical-left {
|
||||
&:before {
|
||||
left: $popover_triangle;
|
||||
}
|
||||
}
|
||||
%popover-triangle-vertical-right {
|
||||
&:before {
|
||||
left: auto;
|
||||
right: $popover_triangle;
|
||||
}
|
||||
}
|
||||
%popover-triangle-horizontal-center {
|
||||
&:before {
|
||||
top: 50%;
|
||||
margin-top: -$popover_triangle;
|
||||
}
|
||||
}
|
||||
%popover-triangle-horizontal-top {
|
||||
&:before {
|
||||
top: $popover_triangle;
|
||||
}
|
||||
}
|
||||
%popover-triangle-horizontal-bottom {
|
||||
&:before {
|
||||
top: auto;
|
||||
bottom: $popover_triangle;
|
||||
}
|
||||
}
|
||||
|
||||
// Usable classes
|
||||
.popover-triangle-top {
|
||||
transform-origin: top center;
|
||||
@extend %popover-triangle;
|
||||
@extend %popover-triangle-vertical-top;
|
||||
@extend %popover-triangle-vertical-center;
|
||||
}
|
||||
.popover-triangle-top-left {
|
||||
transform-origin: top left;
|
||||
@extend %popover-triangle;
|
||||
@extend %popover-triangle-vertical-top;
|
||||
@extend %popover-triangle-vertical-left;
|
||||
}
|
||||
.popover-triangle-top-right {
|
||||
transform-origin: top right;
|
||||
@extend %popover-triangle;
|
||||
@extend %popover-triangle-vertical-top;
|
||||
@extend %popover-triangle-vertical-right;
|
||||
}
|
||||
.popover-triangle-bottom {
|
||||
transform-origin: bottom center;
|
||||
@extend %popover-triangle;
|
||||
@extend %popover-triangle-vertical-bottom;
|
||||
@extend %popover-triangle-vertical-center;
|
||||
}
|
||||
.popover-triangle-bottom-left {
|
||||
transform-origin: bottom left;
|
||||
@extend %popover-triangle;
|
||||
@extend %popover-triangle-vertical-bottom;
|
||||
@extend %popover-triangle-vertical-left;
|
||||
}
|
||||
.popover-triangle-bottom-right {
|
||||
transform-origin: bottom right;
|
||||
@extend %popover-triangle;
|
||||
@extend %popover-triangle-vertical-bottom;
|
||||
@extend %popover-triangle-vertical-right;
|
||||
}
|
||||
.popover-triangle-left {
|
||||
transform-origin: left center;
|
||||
@extend %popover-triangle;
|
||||
@extend %popover-triangle-horizontal-left;
|
||||
@extend %popover-triangle-horizontal-center;
|
||||
}
|
||||
.popover-triangle-left-top {
|
||||
transform-origin: left top;
|
||||
@extend %popover-triangle;
|
||||
@extend %popover-triangle-horizontal-left;
|
||||
@extend %popover-triangle-horizontal-top;
|
||||
}
|
||||
.popover-triangle-left-bottom {
|
||||
transform-origin: left bottom;
|
||||
@extend %popover-triangle;
|
||||
@extend %popover-triangle-horizontal-left;
|
||||
@extend %popover-triangle-horizontal-bottom;
|
||||
}
|
||||
.popover-triangle-right {
|
||||
transform-origin: right center;
|
||||
@extend %popover-triangle;
|
||||
@extend %popover-triangle-horizontal-right;
|
||||
@extend %popover-triangle-horizontal-center;
|
||||
}
|
||||
.popover-triangle-right-top {
|
||||
transform-origin: right top;
|
||||
@extend %popover-triangle;
|
||||
@extend %popover-triangle-horizontal-right;
|
||||
@extend %popover-triangle-horizontal-top;
|
||||
}
|
||||
.popover-triangle-right-bottom {
|
||||
transform-origin: right bottom;
|
||||
@extend %popover-triangle;
|
||||
@extend %popover-triangle-horizontal-right;
|
||||
@extend %popover-triangle-horizontal-bottom;
|
||||
}
|
||||
|
||||
// Show/hide popover
|
||||
// Position relative to the position of the triangle
|
||||
// So... `popover-triangle-left-top` opens on the right of the button
|
||||
// because the triangle is on the top left, poitning to the top right of the button
|
||||
//
|
||||
// |------| |-----------------|
|
||||
// |Button| < Popover content |
|
||||
// |------| | Lorem ipsum dol |
|
||||
// |-----------------|
|
||||
.popover {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
|
||||
.popover-item {
|
||||
position: absolute;
|
||||
z-index: 20;
|
||||
|
||||
&.open {
|
||||
display: block;
|
||||
}
|
||||
&.closed {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.popover-item.popover-triangle-bottom {
|
||||
bottom: calc(100% + 16px);
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
.popover-item.popover-triangle-bottom-left {
|
||||
bottom: calc(100% + 16px);
|
||||
left: 0;
|
||||
}
|
||||
.popover-item.popover-triangle-bottom-right {
|
||||
bottom: calc(100% + 16px);
|
||||
right: 0;
|
||||
}
|
||||
.popover-item.popover-triangle-top {
|
||||
top: calc(100% + 16px);
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
.popover-item.popover-triangle-top-left {
|
||||
top: calc(100% + 16px);
|
||||
left: 0;
|
||||
}
|
||||
.popover-item.popover-triangle-top-right {
|
||||
top: calc(100% + 16px);
|
||||
right: 0;
|
||||
}
|
||||
.popover-item.popover-triangle-left {
|
||||
left: calc(100% + 16px);
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
.popover-item.popover-triangle-left-top {
|
||||
left: calc(100% + 16px);
|
||||
top: 50%;
|
||||
transform: translateY(-($popover_triangle * 2));
|
||||
}
|
||||
.popover-item.popover-triangle-left-bottom {
|
||||
left: calc(100% + 16px);
|
||||
top: 50%;
|
||||
transform: translateY(calc(-100% + #{($popover_triangle * 2)}));
|
||||
}
|
||||
.popover-item.popover-triangle-right {
|
||||
right: calc(100% + 16px);
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
.popover-item.popover-triangle-right-top {
|
||||
right: calc(100% + 16px);
|
||||
top: 50%;
|
||||
transform: translateY(-($popover_triangle * 2));
|
||||
}
|
||||
.popover-item.popover-triangle-right-bottom {
|
||||
right: calc(100% + 16px);
|
||||
top: 50%;
|
||||
transform: translateY(calc(-100% + #{($popover_triangle * 2)}));
|
||||
}
|
||||
}//.popover
|
@ -103,31 +103,35 @@
|
||||
|
||||
//==== Simple SCSS mixin to create CSS triangles
|
||||
//==== Example: @include css-triangle (10px, #fff, "up");
|
||||
@mixin triangle ($size: 20px, $color: #000, $direction: "down") {
|
||||
$size: $size / 2;
|
||||
@mixin triangle ($size: 20px, $color: #000, $direction: "down", $type: "normal") {
|
||||
$verticalSize: $size;
|
||||
width: 0;
|
||||
height: 0;
|
||||
|
||||
@if $type == "shallow" {
|
||||
$verticalSize: floor($size * $popover_triangle_shallow_multiplier);
|
||||
}
|
||||
|
||||
@if $direction == "down" {
|
||||
border-left: $size solid #{setTriangleColor($direction, "left", $color)};
|
||||
border-right: $size solid #{setTriangleColor($direction, "right", $color)};
|
||||
border-top: $size solid #{setTriangleColor($direction, "top", $color)};
|
||||
border-top: $verticalSize solid #{setTriangleColor($direction, "top", $color)};
|
||||
}
|
||||
|
||||
@if $direction == "up" {
|
||||
border-left: $size solid #{setTriangleColor($direction, "left", $color)};
|
||||
border-right: $size solid #{setTriangleColor($direction, "right", $color)};
|
||||
border-bottom: $size solid #{setTriangleColor($direction, "bottom", $color)};
|
||||
border-bottom: $verticalSize solid #{setTriangleColor($direction, "bottom", $color)};
|
||||
}
|
||||
|
||||
@if $direction == "left" {
|
||||
border-right: $size solid #{setTriangleColor($direction, "right", $color)};
|
||||
border-right: $verticalSize solid #{setTriangleColor($direction, "right", $color)};
|
||||
border-top: $size solid #{setTriangleColor($direction, "top", $color)};
|
||||
border-bottom: $size solid #{setTriangleColor($direction, "bottom", $color)};
|
||||
}
|
||||
|
||||
@if $direction == "right" {
|
||||
border-left: $size solid #{setTriangleColor($direction, "left", $color)};
|
||||
border-left: $verticalSize solid #{setTriangleColor($direction, "left", $color)};
|
||||
border-bottom: $size solid #{setTriangleColor($direction, "bottom", $color)};
|
||||
border-top: $size solid #{setTriangleColor($direction, "top", $color)};
|
||||
}
|
||||
|
@ -45,6 +45,8 @@ $at2x: 2 device-pixel-ratio;
|
||||
|
||||
$dropdown_triangle: 8px;
|
||||
|
||||
$popover_triangle: 14px;
|
||||
$popover_triangle_shallow_multiplier: 0.8;
|
||||
|
||||
|
||||
|
||||
|
@ -43,6 +43,7 @@
|
||||
@import "components/dropdowns";
|
||||
@import "components/pagination";
|
||||
@import "components/badges";
|
||||
@import "components/popovers";
|
||||
|
||||
|
||||
//
|
||||
|
@ -42,7 +42,7 @@ var GhostDropdown = Ember.Component.extend(DropdownMixin, {
|
||||
name = this.get('name'),
|
||||
button = this.get('button'),
|
||||
targetDropdownName = options.target;
|
||||
|
||||
|
||||
if (name === targetDropdownName && (!isOpen || isClosing)) {
|
||||
if (!button) {
|
||||
button = options.button;
|
||||
|
15
ghost/admin/components/gh-popover-button.js
Normal file
15
ghost/admin/components/gh-popover-button.js
Normal file
@ -0,0 +1,15 @@
|
||||
import DropdownButton from 'ghost/components/gh-dropdown-button';
|
||||
|
||||
var PopoverButton = DropdownButton.extend({
|
||||
click: Ember.K, // We don't want clicks on popovers, but dropdowns have them. So `K`ill them here.
|
||||
mouseEnter: function (event) {
|
||||
this._super(event);
|
||||
this.get('dropdown').toggleDropdown(this.get('popoverName'), this);
|
||||
},
|
||||
mouseLeave: function (event) {
|
||||
this._super(event);
|
||||
this.get('dropdown').toggleDropdown(this.get('popoverName'), this);
|
||||
}
|
||||
});
|
||||
|
||||
export default PopoverButton;
|
7
ghost/admin/components/gh-popover.js
Normal file
7
ghost/admin/components/gh-popover.js
Normal file
@ -0,0 +1,7 @@
|
||||
import GhostDropdown from 'ghost/components/gh-dropdown';
|
||||
|
||||
var GhostPopover = GhostDropdown.extend({
|
||||
classNames: 'ghost-popover'
|
||||
});
|
||||
|
||||
export default GhostPopover;
|
75
ghost/admin/docs/popovers.html
Normal file
75
ghost/admin/docs/popovers.html
Normal file
@ -0,0 +1,75 @@
|
||||
---
|
||||
layout: default
|
||||
title: Popovers · Ghost UI
|
||||
---
|
||||
|
||||
<header class="page-header">
|
||||
<a class="menu-button" href="#"><span class="sr-only">Menu</span></a>
|
||||
<h2>Popovers</h2>
|
||||
</header>
|
||||
|
||||
<section class="page-content" style="padding: 5%; text-align: center;">
|
||||
|
||||
<h1>Popovers</h1>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="popover-item popover-triangle-bottom">
|
||||
<div class="popover-title">URL Structure Formatting</div>
|
||||
<div class="popover-desc">You can use dynamic variables in this field.</div>
|
||||
<div class="popover-body">
|
||||
<p>
|
||||
<b>%t</b> - The title of your post (or page)<br>
|
||||
<b>%c</b> - The tag which your post is categorised in<br>
|
||||
<b>%y</b> - The year your post was published<br>
|
||||
<b>%m</b> - The month your post was published<br>
|
||||
<b>%d</b> - The day your post was published
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
{% assign popover_classes = "popover-triangle-top|popover-triangle-top-left|popover-triangle-top-right|popover-triangle-bottom|popover-triangle-bottom-left|popover-triangle-bottom-right|popover-triangle-right|popover-triangle-right-top|popover-triangle-right-bottom|popover-triangle-left|popover-triangle-left-top|popover-triangle-left-bottom" | split: "|" %}
|
||||
{% for item in popover_classes %}
|
||||
<div class="popover">
|
||||
<span class="label label-default hover-me">{{item}}</span>
|
||||
<div class="popover-item closed {{item}}">
|
||||
<div class="popover-title">URL Structure Formatting</div>
|
||||
<div class="popover-desc">You can use dynamic variables in this field.</div>
|
||||
<div class="popover-body">
|
||||
<p>
|
||||
<b>%t</b> - The title of your post (or page)<br>
|
||||
<b>%c</b> - The tag which your post is categorised in<br>
|
||||
<b>%y</b> - The year your post was published<br>
|
||||
<b>%m</b> - The month your post was published<br>
|
||||
<b>%d</b> - The day your post was published
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br><br>
|
||||
{% endfor %}
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
|
||||
</section>
|
||||
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
|
||||
<script>
|
||||
$(function(){
|
||||
$(".hover-me").hover(function(){
|
||||
$(this).next(".popover-item").addClass("open fade-in").removeClass("closed fade-out");
|
||||
}, function(){
|
||||
$(this).next(".popover-item").removeClass("fade-in").addClass("fade-out");
|
||||
$(this).next(".popover-item").on('animationend webkitAnimationEnd oanimationend MSAnimationEnd', function (event) {
|
||||
if (event.originalEvent.animationName === 'fade-out') {
|
||||
$(this).removeClass("open fade-out").addClass("closed");
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
@ -1,17 +1,4 @@
|
||||
import BodyEventListener from 'ghost/mixins/body-event-listener';
|
||||
|
||||
var DropdownService = Ember.Object.extend(Ember.Evented, BodyEventListener, {
|
||||
bodyClick: function (event) {
|
||||
/*jshint unused:false */
|
||||
this.closeDropdowns();
|
||||
},
|
||||
closeDropdowns: function () {
|
||||
this.trigger('close');
|
||||
},
|
||||
toggleDropdown: function (dropdownName, dropdownButton) {
|
||||
this.trigger('toggle', {target: dropdownName, button: dropdownButton});
|
||||
}
|
||||
});
|
||||
import DropdownService from 'ghost/utils/dropdown-service';
|
||||
|
||||
var dropdownInitializer = {
|
||||
name: 'dropdown',
|
||||
@ -19,12 +6,18 @@ var dropdownInitializer = {
|
||||
initialize: function (container, application) {
|
||||
application.register('dropdown:service', DropdownService);
|
||||
|
||||
// Inject dropdowns
|
||||
application.inject('component:gh-dropdown', 'dropdown', 'dropdown:service');
|
||||
application.inject('component:gh-dropdown-button', 'dropdown', 'dropdown:service');
|
||||
application.inject('controller:modals.delete-post', 'dropdown', 'dropdown:service');
|
||||
application.inject('controller:modals.transfer-owner', 'dropdown', 'dropdown:service');
|
||||
application.inject('route:application', 'dropdown', 'dropdown:service');
|
||||
|
||||
// Inject popovers
|
||||
application.inject('component:gh-popover', 'dropdown', 'dropdown:service');
|
||||
application.inject('component:gh-popover-button', 'dropdown', 'dropdown:service');
|
||||
application.inject('route:application', 'dropdown', 'dropdown:service');
|
||||
}
|
||||
};
|
||||
|
||||
export default dropdownInitializer;
|
||||
export default dropdownInitializer;
|
@ -6,7 +6,7 @@
|
||||
<div class="page-content">
|
||||
|
||||
<div class="settings-content">
|
||||
|
||||
|
||||
<header class="settings-view-header">
|
||||
<h2 class="page-title">Ugly Debug Tools</h2>
|
||||
<div class="js-settings-header-inner settings-header-inner">
|
||||
@ -15,6 +15,7 @@
|
||||
</header>
|
||||
|
||||
<section class="content settings-debug">
|
||||
|
||||
<form id="settings-export">
|
||||
<fieldset>
|
||||
<div class="form-group">
|
||||
|
17
ghost/admin/utils/dropdown-service.js
Normal file
17
ghost/admin/utils/dropdown-service.js
Normal file
@ -0,0 +1,17 @@
|
||||
// This is used by the dropdown initializer (and subsequently popovers) to manage closing & toggeling
|
||||
import BodyEventListener from 'ghost/mixins/body-event-listener';
|
||||
|
||||
var DropdownService = Ember.Object.extend(Ember.Evented, BodyEventListener, {
|
||||
bodyClick: function (event) {
|
||||
/*jshint unused:false */
|
||||
this.closeDropdowns();
|
||||
},
|
||||
closeDropdowns: function () {
|
||||
this.trigger('close');
|
||||
},
|
||||
toggleDropdown: function (dropdownName, dropdownButton) {
|
||||
this.trigger('toggle', {target: dropdownName, button: dropdownButton});
|
||||
}
|
||||
});
|
||||
|
||||
export default DropdownService;
|
Loading…
Reference in New Issue
Block a user