Skip to content
......@@ -3,49 +3,50 @@
* Visual styling for summary and details in the Settings Tray module's off canvas tray.
*/
.ui-dialog-offcanvas details,
.ui-dialog-offcanvas summary,
.ui-dialog-offcanvas .ui-dialog-content {
.ui-dialog-outside-in details,
.ui-dialog-outside-in summary,
.ui-dialog-outside-in .ui-dialog-content {
background: #474747;
color: #ddd;
}
.ui-dialog-offcanvas summary a {
.ui-dialog-outside-in summary a {
color: #ddd;
padding: 0 inherit;
padding-top: 0;
padding-bottom: 0;
}
.ui-dialog-offcanvas summary a:hover,
.ui-dialog-offcanvas summary a:focus {
.ui-dialog-outside-in summary a:hover,
.ui-dialog-outside-in summary a:focus {
color: #fff;
}
.ui-dialog-offcanvas details,
.ui-dialog-offcanvas summary,
.ui-dialog-offcanvas .details-wrapper {
.ui-dialog-outside-in details,
.ui-dialog-outside-in summary,
.ui-dialog-outside-in .details-wrapper {
border-width: 0;
/* Cancel out the padding of the parent. */
margin: 0 -20px;
padding: 0 20px;
}
.ui-dialog-offcanvas summary {
.ui-dialog-outside-in summary {
text-shadow: none;
outline: none;
padding: 10px 20px;
font-size: 14px;
transition: all .5s ease;
}
.ui-dialog-offcanvas summary:hover,
.ui-dialog-offcanvas summary:focus {
.ui-dialog-outside-in summary:hover,
.ui-dialog-outside-in summary:focus {
background-color: #222;
outline: none;
}
.ui-dialog-offcanvas details[open] {
.ui-dialog-outside-in details[open] {
background-color: #333;
padding-bottom: 10px;
}
.ui-dialog-offcanvas details[open] > summary {
.ui-dialog-outside-in details[open] > summary {
background-color: #333;
color: #eee;
}
.ui-dialog-offcanvas details[open] > summary:hover {
.ui-dialog-outside-in details[open] > summary:hover {
background-color: #222;
color: #fff;
}
......@@ -3,40 +3,40 @@
* Visual styling for forms in the Settings Tray module's off canvas tray.
*/
.ui-dialog-offcanvas label {
.ui-dialog-outside-in label {
line-height: normal;
font-size: 12px;
font-weight: normal;
color: #ddd;
}
.ui-dialog-offcanvas .description,
.ui-dialog-offcanvas .form-item .description,
.ui-dialog-offcanvas .details-description {
.ui-dialog-outside-in .description,
.ui-dialog-outside-in .form-item .description,
.ui-dialog-outside-in .details-description {
color: #ddd;
margin-top: 5px;
font-size: 12px;
font-style: normal;
}
.ui-dialog-offcanvas .details-wrapper .description {
.ui-dialog-outside-in .details-wrapper .description {
color: #bbb;
}
.ui-dialog-offcanvas .form-item {
.ui-dialog-outside-in .form-item {
margin-bottom: 10px;
margin-top: 10px;
}
/* Set size and position for all inputs. */
.ui-dialog-offcanvas .form-select,
.ui-dialog-offcanvas .form-text,
.ui-dialog-offcanvas .form-tel,
.ui-dialog-offcanvas .form-email,
.ui-dialog-offcanvas .form-url,
.ui-dialog-offcanvas .form-search,
.ui-dialog-offcanvas .form-number,
.ui-dialog-offcanvas .form-color,
.ui-dialog-offcanvas .form-file,
.ui-dialog-offcanvas .form-textarea,
.ui-dialog-offcanvas .form-date,
.ui-dialog-offcanvas .form-time {
.ui-dialog-outside-in .form-select,
.ui-dialog-outside-in .form-text,
.ui-dialog-outside-in .form-tel,
.ui-dialog-outside-in .form-email,
.ui-dialog-outside-in .form-url,
.ui-dialog-outside-in .form-search,
.ui-dialog-outside-in .form-number,
.ui-dialog-outside-in .form-color,
.ui-dialog-outside-in .form-file,
.ui-dialog-outside-in .form-textarea,
.ui-dialog-outside-in .form-date,
.ui-dialog-outside-in .form-time {
box-sizing: border-box;
max-width: 100%;
padding: 6px;
......@@ -53,58 +53,58 @@
cursor: pointer;
}
/* Reduce contrast for fields against dark backround. */
.ui-dialog-offcanvas .form-text,
.ui-dialog-offcanvas .form-tel,
.ui-dialog-offcanvas .form-email,
.ui-dialog-offcanvas .form-url,
.ui-dialog-offcanvas .form-search,
.ui-dialog-offcanvas .form-number,
.ui-dialog-offcanvas .form-color,
.ui-dialog-offcanvas .form-file,
.ui-dialog-offcanvas .form-textarea,
.ui-dialog-offcanvas .form-date,
.ui-dialog-offcanvas .form-time {
.ui-dialog-outside-in .form-text,
.ui-dialog-outside-in .form-tel,
.ui-dialog-outside-in .form-email,
.ui-dialog-outside-in .form-url,
.ui-dialog-outside-in .form-search,
.ui-dialog-outside-in .form-number,
.ui-dialog-outside-in .form-color,
.ui-dialog-outside-in .form-file,
.ui-dialog-outside-in .form-textarea,
.ui-dialog-outside-in .form-date,
.ui-dialog-outside-in .form-time {
box-shadow: inset 0 1px 2px rgba(0, 0, 0, .125);
background-color: #eee;
border-color: #333;
color: #595959;
}
.ui-dialog-offcanvas .form-text:focus,
.ui-dialog-offcanvas .form-tel:focus,
.ui-dialog-offcanvas .form-email:focus,
.ui-dialog-offcanvas .form-url:focus,
.ui-dialog-offcanvas .form-search:focus,
.ui-dialog-offcanvas .form-number:focus,
.ui-dialog-offcanvas .form-color:focus,
.ui-dialog-offcanvas .form-file:focus,
.ui-dialog-offcanvas .form-textarea:focus,
.ui-dialog-offcanvas .form-date:focus,
.ui-dialog-offcanvas .form-time:focus {
.ui-dialog-outside-in .form-text:focus,
.ui-dialog-outside-in .form-tel:focus,
.ui-dialog-outside-in .form-email:focus,
.ui-dialog-outside-in .form-url:focus,
.ui-dialog-outside-in .form-search:focus,
.ui-dialog-outside-in .form-number:focus,
.ui-dialog-outside-in .form-color:focus,
.ui-dialog-outside-in .form-file:focus,
.ui-dialog-outside-in .form-textarea:focus,
.ui-dialog-outside-in .form-date:focus,
.ui-dialog-outside-in .form-time:focus {
border-color: #40b6ff;
box-shadow: inset 0 1px 3px rgba(0, 0, 0, .125), 0 0 8px #40b6ff;
background-color: #fff;
}
.ui-dialog-offcanvas input[type="checkbox"],
.ui-dialog-offcanvas .checkbox,
.ui-dialog-offcanvas input[type="radio"],
.ui-dialog-offcanvas .radio {
.ui-dialog-outside-in input[type="checkbox"],
.ui-dialog-outside-in .checkbox,
.ui-dialog-outside-in input[type="radio"],
.ui-dialog-outside-in .radio {
position: static;
margin: 0;
}
.ui-dialog-offcanvas td .checkbox {
.ui-dialog-outside-in td .checkbox {
display: table-cell;
line-height: normal;
vertical-align: middle;
}
.ui-dialog-offcanvas .form-checkbox,
.ui-dialog-offcanvas .form-radio {
.ui-dialog-outside-in .form-checkbox,
.ui-dialog-outside-in .form-radio {
/* Add contrast for dark background. */
box-shadow: 0 0 2px 1px #000;
}
.ui-dialog-offcanvas input[type="radio"] {
.ui-dialog-outside-in input[type="radio"] {
/* Add full circular radius. */
border-radius: 50%;
}
.ui-dialog-offcanvas .form-actions {
.ui-dialog-outside-in .form-actions {
text-align: center;
}
......@@ -2,31 +2,6 @@
* @file
* Styling for Settings Tray module.
*/
/* Position the offcanvas tray container outside the right of the viewport. */
.ui-dialog-offcanvas {
box-sizing: border-box;
height: 100%;
overflow: visible;
}
/* Shift the main canvas to the right for right-to-left languages. */
[dir="rtl"] #main-canvas-wrapper.js-tray-open #main-canvas {
right: 0;
}
/* Wrap the form that's inside the offcanvas tray. */
.ui-dialog-offcanvas .ui-dialog-content {
padding: 0 20px;
/* Prevent horizontal scrollbar. */
overflow-x: hidden;
overflow-y: auto;
}
[dir="rtl"] .ui-dialog-offcanvas .ui-dialog-content {
text-align: right;
}
/*
* Position the edit toolbar tab.
* @todo Move changes into contextual module when Settings Tray is not
......@@ -47,3 +22,17 @@
pointer-events: inherit;
}
/*
* Force the tray to be 100% width at the same breakpoint the dialog system uses
* to expand dialog widths.
*/
@media all and (max-width: 48em) { /* 768px */
.ui-dialog.ui-dialog-offcanvas {
width: 100% !important;
}
/* When tray is at 100% width stop the body from scrolling */
.js-tray-open {
height: 100%;
overflow-y: hidden;
}
}
......@@ -10,18 +10,6 @@
* file: https://www.drupal.org/node/2784443.
*/
/* Transition the offcanvas tray container, with 2s delay to match main canvas speed. */
#offcanvas {
-webkit-transition: all .7s ease 2s;
-moz-transition: all .7s ease 2s;
transition: all .7s ease 2s;
}
#main-canvas-wrapper #main-canvas,
#main-canvas-wrapper.js-tray-open #main-canvas {
-webkit-transition: all .7s ease;
-moz-transition: all .7s ease;
transition: all .7s ease;
}
/* Transition the edit icon in the toolbar. */
#toolbar-bar.button.toolbar-icon.toolbar-icon.toolbar-icon-edit:before {
......@@ -31,9 +19,9 @@
}
/* Transition the editables on the page, their contextual links and their hover states. */
#main-canvas-wrapper .contextual,
#main-canvas-wrapper .js-outside-in-edit-mode .outside-in-editable,
#main-canvas-wrapper.js-tray-open .js-outside-in-edit-mode .outside-in-editable {
.dialog-offcanvas__main-canvas .contextual,
.dialog-offcanvas__main-canvas .js-outside-in-edit-mode .outside-in-editable,
.dialog-offcanvas__main-canvas.js-tray-open .js-outside-in-edit-mode .outside-in-editable {
-webkit-transition: all .7s ease;
-moz-transition: all .7s ease;
transition: all .7s ease;
......@@ -47,19 +35,6 @@
transition: all .5s ease;
}
@media (max-width: 700px) {
#offcanvas {
-webkit-transition: all .7s ease;
-moz-transition: all .7s ease;
transition: all .7s ease;
}
#main-canvas-wrapper.js-tray-open #offcanvas {
-webkit-transition: all .7s ease;
-moz-transition: all .7s ease;
transition: all .7s ease;
}
}
/* Transition the administration tray.
#toolbar-administration,
#toolbar-administration * {
......
......@@ -3,7 +3,7 @@
* Visual styling for tables in the Settings Tray module's off canvas tray.
*/
.ui-dialog-offcanvas table {
.ui-dialog-outside-in table {
border: 0;
border-collapse: collapse;
min-width: 300px;
......@@ -13,7 +13,7 @@
margin-left: -20px;
margin-bottom: -10px;
}
.ui-dialog-offcanvas tr th {
.ui-dialog-outside-in tr th {
padding: 2px 4px;
background-color: transparent;
border: 0;
......@@ -22,15 +22,14 @@
color: #bbb;
text-align: left; /* LTR */
}
[dir="rtl"] .ui-dialog-offcanvas tr th {
[dir="rtl"] .ui-dialog-outside-in tr th {
text-align: right;
}
.ui-dialog-offcanvas tr,
.ui-dialog-offcanvas tr td {
.ui-dialog-outside-in tr,
.ui-dialog-outside-in tr td {
padding: 2px 4px;
height: 35px;
vertical-align: middle;
font-size: 13px;
text-align: left; /* LTR */
border: 0px;
border-style: solid;
......@@ -40,29 +39,28 @@
background-color: transparent;
font-size: 12px;
}
[dir="rtl"] .ui-dialog-offcanvas tr th,
[dir="rtl"] .ui-dialog-offcanvas tr td {
[dir="rtl"] .ui-dialog-outside-in tr th,
[dir="rtl"] .ui-dialog-outside-in tr td {
text-align: right;
}
.ui-dialog-offcanvas td a {
.ui-dialog-outside-in td a {
display: block;
max-width: 120px;
overflow: hidden;
}
.ui-dialog.ui-dialog-offcanvas tr td:first-child,
.ui-dialog.ui-dialog-offcanvas tr th:first-child {
min-width: 120px;
.ui-dialog.ui-dialog-outside-in tr td:first-child,
.ui-dialog.ui-dialog-outside-in tr th:first-child {
padding-left: 20px; /* LTR */
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
[dir="rtl"] .ui-dialog.ui-dialog-offcanvas tr td:first-child,
[dir="rtl"] .ui-dialog.ui-dialog-offcanvas tr th:first-child {
[dir="rtl"] .ui-dialog.ui-dialog-outside-in tr td:first-child,
[dir="rtl"] .ui-dialog.ui-dialog-outside-in tr th:first-child {
padding-right: 20px;
}
.ui-dialog-offcanvas tr.odd,
.ui-dialog-offcanvas tr.even {
.ui-dialog-outside-in tr.odd,
.ui-dialog-outside-in tr.even {
background-image: none;
background-color: transparent;
}
......
......@@ -8,40 +8,40 @@
/* Because base font sizes will vary widely across themes, to maintain consistency outside-in uses only pixels. */
.ui-dialog-offcanvas body.drag {
.ui-dialog-outside-in body.drag {
cursor: move;
}
.ui-dialog-offcanvas tr.region-title {
.ui-dialog-outside-in tr.region-title {
font-weight: normal;
}
.ui-dialog-offcanvas tr.region-message {
.ui-dialog-outside-in tr.region-message {
color: #fff;
}
.ui-dialog-offcanvas tr.region-populated {
.ui-dialog-outside-in tr.region-populated {
display: none;
}
.ui-dialog-offcanvas tr.add-new .tabledrag-changed {
.ui-dialog-outside-in tr.add-new .tabledrag-changed {
display: none;
}
.ui-dialog-offcanvas .draggable a.tabledrag-handle {
.ui-dialog-outside-in .draggable a.tabledrag-handle {
background-image: none;
margin: 0;
margin-left: 0; /* LTR */
margin-right: 5px; /* LTR */
height: auto;
min-width: 20px;
padding: 0px;
padding: 0;
overflow: hidden;
float: left; /* LTR */
text-decoration: none;
cursor: move;
}
[dir="rtl"] .ui-dialog-offcanvas .draggable a.tabledrag-handle {
[dir="rtl"] .ui-dialog-outside-in .draggable a.tabledrag-handle {
float: right;
margin-right: 0;
margin-left: 5px;
}
.ui-dialog-offcanvas a.tabledrag-handle .handle {
.ui-dialog-outside-in a.tabledrag-handle .handle {
/* Use lighter drag icon against dark background. */
background-image: url(../../../misc/icons/bebebe/move.svg);
background-repeat: no-repeat;
......@@ -51,54 +51,54 @@
padding: 0;
width: auto;
}
.ui-dialog-offcanvas .draggable a.tabledrag-handle:hover .handle,
.ui-dialog-offcanvas .draggable a.tabledrag-handle:focus .handle {
.ui-dialog-outside-in .draggable a.tabledrag-handle:hover .handle,
.ui-dialog-outside-in .draggable a.tabledrag-handle:focus .handle {
background-image: url(../../../misc/icons/787878/move.svg);
text-decoration: none;
}
.ui-dialog-offcanvas .touchevents .draggable td {
.ui-dialog-outside-in .touchevents .draggable td {
padding: 0 10px;
}
.ui-dialog-offcanvas .touchevents .draggable .menu-item__link {
.ui-dialog-outside-in .touchevents .draggable .menu-item__link {
display: inline-block;
padding: 10px 0;
}
.ui-dialog-offcanvas .touchevents a.tabledrag-handle {
.ui-dialog-outside-in .touchevents a.tabledrag-handle {
height: 44px;
width: 40px;
}
.ui-dialog-offcanvas .touchevents a.tabledrag-handle .handle {
.ui-dialog-outside-in .touchevents a.tabledrag-handle .handle {
background-position: 40% 19px; /* LTR */
height: 21px;
}
[dir="rtl"] .ui-dialog-offcanvas .touch a.tabledrag-handle .handle {
[dir="rtl"] .ui-dialog-outside-in .touch a.tabledrag-handle .handle {
background-position: right 40% top 19px;
}
.ui-dialog-offcanvas .touchevents .draggable.drag a.tabledrag-handle .handle {
.ui-dialog-outside-in .touchevents .draggable.drag a.tabledrag-handle .handle {
background-position: 50% -32px;
}
.ui-dialog-offcanvas .tabledrag-toggle-weight-wrapper {
.ui-dialog-outside-in .tabledrag-toggle-weight-wrapper {
text-align: right; /* LTR */
}
[dir="rtl"] .ui-dialog-offcanvas .tabledrag-toggle-weight-wrapper {
[dir="rtl"] .ui-dialog-outside-in .tabledrag-toggle-weight-wrapper {
text-align: left;
}
.ui-dialog-offcanvas .indentation {
.ui-dialog-outside-in .indentation {
float: left; /* LTR */
height: auto;
margin: 0 3px 0 -10px; /* LTR */
padding: 0 0 0 10px; /* LTR */
width: auto;
}
[dir="rtl"] .ui-dialog-offcanvas .indentation {
[dir="rtl"] .ui-dialog-outside-in .indentation {
float: right;
margin: 0 -10px 0 3px;
padding: 0 10px 0 0;
}
.ui-dialog-offcanvas tr.drag {
.ui-dialog-outside-in tr.drag {
background-color: #555;
}
.ui-dialog-offcanvas tr.drag-previous {
.ui-dialog-outside-in tr.drag-previous {
background-color: #000;
}
......@@ -60,19 +60,19 @@
}
/* Style the editables while in edit mode. */
#main-canvas.js-outside-in-edit-mode .outside-in-editable {
.dialog-offcanvas__main-canvas.js-outside-in-edit-mode .outside-in-editable {
outline: 1px dashed rgba(0,0,0,0.5);
box-shadow: 0 0 0 1px rgba(255,255,255,0.7);
}
#main-canvas.js-outside-in-edit-mode .outside-in-editable:hover,
#main-canvas.js-outside-in-edit-mode .outside-in-editable.outside-in-active-editable {
.dialog-offcanvas__main-canvas.js-outside-in-edit-mode .outside-in-editable:hover,
.dialog-offcanvas__main-canvas.js-outside-in-edit-mode .outside-in-editable.outside-in-active-editable {
background-color: rgba(0,0,0,0.2);
}
/* Style the offcanvas container. */
.ui-dialog-offcanvas {
/* Style the dialog-offcanvas container. */
.ui-dialog-outside-in {
background: #444;
border: 0px solid transparent;
border: 0 solid transparent;
border-radius: 0;
box-shadow: 0 0 4px 2px rgba(0, 0, 0, 0.3333);
padding: 0;
......@@ -82,20 +82,20 @@
}
/* Style content in the tray. */
.ui-dialog-offcanvas p,
.ui-dialog-offcanvas h1,
.ui-dialog-offcanvas h2,
.ui-dialog-offcanvas h3,
.ui-dialog-offcanvas h4,
.ui-dialog-offcanvas h5,
.ui-dialog-offcanvas h6,
.ui-dialog-offcanvas pre,
.ui-dialog-offcanvas legend,
.ui-dialog-offcanvas cite,
.ui-dialog-offcanvas span,
.ui-dialog-offcanvas summary,
.ui-dialog-offcanvas details,
.ui-dialog-offcanvas .form-item {
.ui-dialog-outside-in p,
.ui-dialog-outside-in h1,
.ui-dialog-outside-in h2,
.ui-dialog-outside-in h3,
.ui-dialog-outside-in h4,
.ui-dialog-outside-in h5,
.ui-dialog-outside-in h6,
.ui-dialog-outside-in pre,
.ui-dialog-outside-in legend,
.ui-dialog-outside-in cite,
.ui-dialog-outside-in span,
.ui-dialog-outside-in summary,
.ui-dialog-outside-in details,
.ui-dialog-outside-in .form-item {
color: #ddd;
font-family: "Lucida Grande", 'Lucida Sans Unicode','liberation sans', sans-serif;
font-size: 14px;
......@@ -103,8 +103,8 @@
background-color: transparent;
text-shadow: none;
}
.ui-dialog-offcanvas a,
.ui-dialog-offcanvas .link {
.ui-dialog-outside-in a,
.ui-dialog-outside-in .link {
border-bottom: none;
font-family: "Lucida Grande", 'Lucida Sans Unicode','liberation sans', sans-serif;
font-size: 14px;
......@@ -113,16 +113,16 @@
text-decoration: none;
transition: color .5s ease;
}
.ui-dialog-offcanvas a:focus,
.ui-dialog-offcanvas .link:focus,
.ui-dialog-offcanvas a:hover,
.ui-dialog-offcanvas .link:hover {
.ui-dialog-outside-in a:focus,
.ui-dialog-outside-in .link:focus,
.ui-dialog-outside-in a:hover,
.ui-dialog-outside-in .link:hover {
outline: none;
color: #46a0f5;
}
/* Style the tray header. */
.ui-dialog-offcanvas .ui-dialog-titlebar {
.ui-dialog-outside-in .ui-dialog-titlebar {
padding: 20px;
background: #2d2d2d;
border: 0;
......@@ -131,11 +131,10 @@
font-weight: normal;
color: #fff;
}
.ui-dialog-offcanvas .ui-dialog-titlebar-close {
.ui-dialog-outside-in .ui-dialog-titlebar-close {
background-image: url(../../../misc/icons/bebebe/ex.svg);
background-position-x: center;
background-position: center center;
background-repeat: no-repeat;
background-position-y: center;
background-color: transparent;
border: 0;
position: absolute;
......@@ -143,14 +142,14 @@
-moz-transition: all .5s ease;
transition: background .5s ease;
}
.ui-dialog-offcanvas .ui-dialog-titlebar-close:hover {
.ui-dialog-outside-in .ui-dialog-titlebar-close:hover {
background-image: url(../../../misc/icons/ffffff/ex.svg);
}
[dir="rtl"] .ui-dialog-offcanvas .ui-dialog-titlebar-close {
[dir="rtl"] .ui-dialog-outside-in .ui-dialog-titlebar-close {
left: 20px;
right: auto;
}
.ui-dialog-offcanvas .ui-dialog-title {
.ui-dialog-outside-in .ui-dialog-title {
font-size: 16px;
margin: 0;
/* Push the text away from the icon. */
......@@ -160,12 +159,12 @@
max-width: 210px;
text-align: left; /* LTR */
}
[dir="rtl"] .ui-dialog-offcanvas .ui-dialog-title {
[dir="rtl"] .ui-dialog-outside-in .ui-dialog-title {
text-align: right;
padding-left: 0px;
padding-right: 0px;
}
.ui-dialog-offcanvas .ui-dialog-title:before {
.ui-dialog-outside-in .ui-dialog-title:before {
background: transparent url(../../../misc/icons/ffffff/pencil.svg) no-repeat scroll center center;
background-size: 100% auto;
content: '';
......@@ -176,7 +175,7 @@
top: 0;
width: 20px;
}
[dir="rtl"] .ui-dialog-offcanvas .ui-dialog-title:before {
[dir="rtl"] .ui-dialog-outside-in .ui-dialog-title:before {
left: auto;
right: 20px;
}
......@@ -191,7 +190,7 @@
color: #333;
}
/* Hide the defauld Jquery UI dialog close button. */
.ui-dialog-offcanvas .ui-icon-closethick {
.ui-dialog-outside-in .ui-icon-closethick {
visibility: hidden;
}
......@@ -203,14 +202,14 @@
* https://www.drupal.org/node/1945262.
*/
.ui-dialog-offcanvas button.link {
.ui-dialog-outside-in button.link {
background: transparent;
border: 0;
cursor: pointer;
margin: 0;
padding: 0;
}
.ui-dialog-offcanvas .button {
.ui-dialog-outside-in .button {
width: 100%;
height: auto;
margin: 1em auto;
......@@ -221,18 +220,18 @@
color: #fff;
transition: all .5s ease;
}
.ui-dialog-offcanvas .button:hover,
.ui-dialog-offcanvas .button:focus {
.ui-dialog-outside-in .button:hover,
.ui-dialog-outside-in .button:focus {
background: #888;
}
.ui-dialog-offcanvas .button--primary {
.ui-dialog-outside-in .button--primary {
background: #277abd none;
border: none;
color: #fff;
transition: all .5s ease;
}
.ui-dialog-offcanvas .button--primary:hover,
.ui-dialog-offcanvas .button--primary:focus {
.ui-dialog-outside-in .button--primary:hover,
.ui-dialog-outside-in .button--primary:focus {
background: #2b8bd8;
}
......@@ -243,17 +242,17 @@
* https://www.drupal.org/node/1945262.
*/
.ui-dialog-offcanvas .dropbutton-widget {
.ui-dialog-outside-in .dropbutton-widget {
background: #7b7b7b none;
border: 0;
border-radius: 1em;
color: #eee;
transition: background .5s ease;
}
.ui-dialog-offcanvas .dropbutton-widget:hover {
.ui-dialog-outside-in .dropbutton-widget:hover {
box-shadow: 0 2px 2px 1px rgba(0,0,0,0.5);
}
.ui-dialog-offcanvas .dropbutton-toggle button {
.ui-dialog-outside-in .dropbutton-toggle button {
background: #7b7b7b none;
border-bottom-right-radius: 1em; /* LTR */
border-top-right-radius: 1em; /* LTR */
......@@ -262,37 +261,37 @@
border-left-width: 1px; /* LTR */
transition: background .5s ease;
}
[dir="rtl"] .ui-dialog-offcanvas .dropbutton-toggle button {
[dir="rtl"] .ui-dialog-outside-in .dropbutton-toggle button {
border-radius: 0;
border-bottom-left-radius: 1em;
border-top-left-radius: 1em;
border-width: 0;
border-right-width: 1px;
}
.ui-dialog-offcanvas .dropbutton .dropbutton-action:hover,
.ui-dialog-offcanvas .dropbutton a:hover {
.ui-dialog-outside-in .dropbutton .dropbutton-action:hover,
.ui-dialog-outside-in .dropbutton a:hover {
background: #6b6b6b none;
border-bottom-left-radius: 1em; /* LTR */
border-top-left-radius: 1em; /* LTR */
}
[dir="rtl"] .ui-dialog-offcanvas .dropbutton .dropbutton-action:hover,
[dir="rtl"] .ui-dialog-offcanvas .dropbutton a:hover {
[dir="rtl"] .ui-dialog-outside-in .dropbutton .dropbutton-action:hover,
[dir="rtl"] .ui-dialog-outside-in .dropbutton a:hover {
border-radius: 0;
border-bottom-right-radius: 1em;
border-top-right-radius: 1em;
}
.ui-dialog-offcanvas .dropbutton a {
.ui-dialog-outside-in .dropbutton a {
padding: 0.1em 0.8em;
color: #eee;
font-size: 90%;
line-height: 1.8;
transition: all .5s ease;
}
.ui-dialog-offcanvas .dropbutton:hover a {
.ui-dialog-outside-in .dropbutton:hover a {
color: #fff;
}
/* Make an arrow out of borders with some fancy CSS. */
.ui-dialog-offcanvas span.dropbutton-arrow {
.ui-dialog-outside-in span.dropbutton-arrow {
border-bottom-color: transparent;
border-left-color: transparent;
border-right-color: transparent;
......@@ -309,21 +308,19 @@
overflow: hidden;
color: #fff;
}
.js .dropbutton-toggle .dropbutton-arrow:hover {
.js .ui-dialog-outside-in .dropbutton-toggle .dropbutton-arrow:hover {
background: transparent;
}
.ui-dialog-offcanvas td .dropbutton-multiple {
.ui-dialog-outside-in td .dropbutton-multiple {
padding-right: 0;
}
[dir="rtl"].ui-dialog-offcanvas td .dropbutton-multiple {
[dir="rtl"].ui-dialog-outside-in td .dropbutton-multiple {
padding-left: 0;
}
.ui-dialog-offcanvas td .dropbutton-multiple .dropbutton {
.ui-dialog-outside-in td .dropbutton-multiple .dropbutton {
border-right: 0;
border-left: 0;
}
.ui-dialog-offcanvas td .dropbutton .secondary-action {
.ui-dialog-outside-in td .dropbutton .secondary-action {
border-top-color: #000;
}
......@@ -11,6 +11,10 @@
'use strict';
// The minimum width to use body displace needs to match the width at which
// the tray will be %100 width. @see outside_in.module.css
var minDisplaceWidth = 768;
/**
* The edge of the screen that the dialog should appear on.
*
......@@ -18,7 +22,7 @@
*/
var edge = document.documentElement.dir === 'rtl' ? 'left' : 'right';
var $mainCanvasWrapper = $('#main-canvas-wrapper');
var $mainCanvasWrapper = $('[data-offcanvas-main-canvas]');
/**
* Resets the size of the dialog.
......@@ -47,7 +51,7 @@
$element
.dialog('option', adjustedOptions)
.trigger('dialogContentResize.outsidein');
.trigger('dialogContentResize.offcanvas');
}
/**
......@@ -81,6 +85,9 @@
* The event triggered.
*/
function bodyPadding(event) {
if ($('body').outerWidth() < minDisplaceWidth) {
return;
}
var $element = event.data.$element;
var $widget = $element.dialog('widget');
......@@ -100,26 +107,28 @@
$('.ui-dialog-offcanvas, .ui-dialog-offcanvas .ui-dialog-titlebar').toggleClass('ui-dialog-empty-title', !settings.title);
$element
.on('dialogresize.outsidein', eventData, debounce(bodyPadding, 100))
.on('dialogContentResize.outsidein', eventData, handleDialogResize)
.trigger('dialogresize.outsidein');
.on('dialogresize.offcanvas', eventData, debounce(bodyPadding, 100))
.on('dialogContentResize.offcanvas', eventData, handleDialogResize)
.on('dialogContentResize.offcanvas', eventData, debounce(bodyPadding, 100))
.trigger('dialogresize.offcanvas');
$element.dialog('widget').attr('data-offset-' + edge, '');
$(window)
.on('resize.outsidein scroll.outsidein', eventData, debounce(resetSize, 100))
.trigger('resize.outsidein');
.on('resize.offcanvas scroll.offcanvas', eventData, debounce(resetSize, 100))
.trigger('resize.offcanvas');
}
},
'dialog:beforecreate': function (event, dialog, $element, settings) {
if ($element.is('#drupal-offcanvas')) {
$('body').addClass('js-tray-open');
// @see http://api.jqueryui.com/position/
settings.position = {
my: 'left top',
at: edge + ' top',
of: window
};
settings.dialogClass = 'ui-dialog-offcanvas';
settings.dialogClass += ' ui-dialog-offcanvas';
// Applies initial height to dialog based on window height.
// See http://api.jqueryui.com/dialog for all dialog options.
settings.height = $(window).height();
......@@ -127,8 +136,9 @@
},
'dialog:beforeclose': function (event, dialog, $element) {
if ($element.is('#drupal-offcanvas')) {
$(document).off('.outsidein');
$(window).off('.outsidein');
$('body').removeClass('js-tray-open');
$(document).off('.offcanvas');
$(window).off('.offcanvas');
$mainCanvasWrapper.css('padding-' + edge, 0);
}
}
......
......@@ -9,7 +9,7 @@
var blockConfigureSelector = '[data-outside-in-edit]';
var toggleEditSelector = '[data-drupal-outsidein="toggle"]';
var itemsToToggleSelector = '#main-canvas, #toolbar-bar, [data-drupal-outsidein="editable"] a, [data-drupal-outsidein="editable"] button';
var itemsToToggleSelector = '[data-offcanvas-main-canvas], #toolbar-bar, [data-drupal-outsidein="editable"] a, [data-drupal-outsidein="editable"] button';
var contextualItemsSelector = '[data-contextual-id] a, [data-contextual-id] button';
var quickEditItemSelector = '[data-quickedit-entity-id]';
......@@ -42,6 +42,15 @@
});
});
$(document).on('keyup.outsidein', function (e) {
if (isInEditMode() && e.keyCode === 27) {
Drupal.announce(
Drupal.t('Exited edit mode.')
);
toggleEditMode();
}
});
/**
* Gets all items that should be toggled with class during edit mode.
*
......@@ -91,11 +100,7 @@
* Close any active toolbar tray before entering edit mode.
*/
function closeToolbarTrays() {
$('#toolbar-bar')
.find('.toolbar-tab')
.not('.contextual-toolbar-tab')
.has('.toolbar-tray.is-active')
.find('.toolbar-item').trigger('click');
$(Drupal.toolbar.models.toolbarModel.get('activeTab')).trigger('click');
}
/**
......@@ -130,7 +135,7 @@
$editables = $('[data-drupal-outsidein="editable"]').once('outsidein');
if ($editables.length) {
// Use event capture to prevent clicks on links.
document.querySelector('#main-canvas').addEventListener('click', preventClick, true);
document.querySelector('[data-offcanvas-main-canvas]').addEventListener('click', preventClick, true);
// When a click occurs try and find the outside-in edit link
// and click it.
......@@ -163,7 +168,7 @@
else {
$editables = $('[data-drupal-outsidein="editable"]').removeOnce('outsidein');
if ($editables.length) {
document.querySelector('#main-canvas').removeEventListener('click', preventClick, true);
document.querySelector('[data-offcanvas-main-canvas]').removeEventListener('click', preventClick, true);
$editables.off('.outsidein');
$(quickEditItemSelector).off('.outsidein');
}
......@@ -208,7 +213,7 @@
var search = Drupal.ajax.WRAPPER_FORMAT + '=drupal_dialog';
var replace = Drupal.ajax.WRAPPER_FORMAT + '=drupal_dialog_offcanvas';
// Loop through all Ajax links and change the format to offcanvas when
// Loop through all Ajax links and change the format to dialog-offcanvas when
// needed.
Drupal.ajax.instances
.filter(function (instance) {
......@@ -241,8 +246,9 @@
if ($element.is('#drupal-offcanvas')) {
$('body .outside-in-active-editable').removeClass('outside-in-active-editable');
var $activeElement = $('#' + settings.outsideInActiveEditableId);
if ($activeElement) {
if ($activeElement.length) {
$activeElement.addClass('outside-in-active-editable');
settings.dialogClass += ' ui-dialog-outside-in';
}
}
},
......
......@@ -12,9 +12,7 @@
*/
#}
{% if children %}
<div id="main-canvas-wrapper">
<div id="main-canvas">
{{ children }}
</div>
<div class="dialog-offcanvas__main-canvas" data-offcanvas-main-canvas >
{{ children }}
</div>
{% endif %}
......@@ -69,4 +69,38 @@ public function testOffCanvasLinks() {
}
}
/**
* Tests the body displacement behaves differently at a narrow width.
*/
public function testNarrowWidth() {
$themes = ['stark', 'bartik'];
$narrow_width_breakpoint = 768;
$offset = 20;
$height = 800;
$page = $this->getSession()->getPage();
$web_assert = $this->assertSession();
// Test the same functionality on multiple themes.
foreach ($themes as $theme) {
$this->enableTheme($theme);
// Testing at the wider width.
$this->getSession()->resizeWindow($narrow_width_breakpoint + $offset, $height);
$this->drupalGet('/offcanvas-test-links');
$this->assertFalse($page->find('css', '.dialog-offcanvas__main-canvas')->hasAttribute('style'), 'Body not padded on wide page load.');
$page->clickLink("Click Me 1!");
$this->waitForOffCanvasToOpen();
// Check that the main canvas is padded when page is not narrow width and
// tray is open.
$web_assert->elementAttributeContains('css', '.dialog-offcanvas__main-canvas', 'style', 'padding-right');
// Testing at the narrower width.
$this->getSession()->resizeWindow($narrow_width_breakpoint - $offset, $height);
$this->drupalGet('/offcanvas-test-links');
$this->assertFalse($page->find('css', '.dialog-offcanvas__main-canvas')->hasAttribute('style'), 'Body not padded on narrow page load.');
$page->clickLink("Click Me 1!");
$this->waitForOffCanvasToOpen();
$this->assertFalse($page->find('css', '.dialog-offcanvas__main-canvas')->hasAttribute('style'), 'Body not padded on narrow page with tray open.');
}
}
}
......@@ -117,8 +117,16 @@ public function testBlocks($block_id, $new_page_text, $element_selector, $label_
// suppressed.
$this->openBlockForm($element_selector);
// Exit edit mode.
$this->toggleEditingMode();
// Exit edit mode using ESC.
$web_assert->elementTextContains('css', '.contextual-toolbar-tab button', 'Editing');
$web_assert->elementAttributeContains('css', '.dialog-offcanvas__main-canvas', 'class', 'js-outside-in-edit-mode');
// Simulate press the Escape key.
$this->getSession()->executeScript('jQuery("body").trigger(jQuery.Event("keyup", { keyCode: 27 }));');
$this->waitForOffCanvasToClose();
$this->getSession()->wait(100);
$web_assert->elementTextContains('css', '#drupal-live-announce', 'Exited edit mode.');
$web_assert->elementTextNotContains('css', '.contextual-toolbar-tab button', 'Editing');
$web_assert->elementAttributeNotContains('css', '.dialog-offcanvas__main-canvas', 'class', 'js-outside-in-edit-mode');
}
/**
......
......@@ -13,7 +13,11 @@ abstract class UrlAliasBase extends DrupalSqlBase {
* {@inheritdoc}
*/
public function query() {
return $this->select('url_alias', 'ua')->fields('ua');
// The order of the migration is significant since
// \Drupal\Core\Path\AliasStorage::lookupPathAlias() orders by pid before
// returning a result. Postgres does not automatically order by primary key
// therefore we need to add a specific order by.
return $this->select('url_alias', 'ua')->fields('ua')->orderBy('pid');
}
/**
......
......@@ -37,6 +37,7 @@ entity.search_page.enable:
op: 'enable'
requirements:
_entity_access: 'search_page.update'
_csrf_token: 'TRUE'
entity.search_page.disable:
path: '/admin/config/search/pages/manage/{search_page}/disable'
......@@ -45,6 +46,7 @@ entity.search_page.disable:
op: 'disable'
requirements:
_entity_access: 'search_page.disable'
_csrf_token: 'TRUE'
entity.search_page.set_default:
path: '/admin/config/search/pages/manage/{search_page}/set-default'
......@@ -52,6 +54,7 @@ entity.search_page.set_default:
_controller: '\Drupal\search\Controller\SearchController::setAsDefault'
requirements:
_entity_access: 'search_page.update'
_csrf_token: 'TRUE'
entity.search_page.delete_form:
path: '/admin/config/search/pages/manage/{search_page}/delete'
......
......@@ -75,6 +75,16 @@ public function getFormId() {
public function buildForm(array $form, FormStateInterface $form_state) {
// Set up the form to submit using GET to the correct search page.
$entity_id = $this->searchPageRepository->getDefaultSearchPage();
$form = [];
// SearchPageRepository::getDefaultSearchPage() depends on search.settings.
// The dependency needs to be added before the conditional return, otherwise
// the block would get cached without the necessary cacheablity metadata in
// case there is no default search page and would not be invalidated if that
// changes.
$this->renderer->addCacheableDependency($form, $this->configFactory->get('search.settings'));
if (!$entity_id) {
$form['message'] = array(
'#markup' => $this->t('Search is currently disabled'),
......@@ -103,9 +113,6 @@ public function buildForm(array $form, FormStateInterface $form_state) {
'#name' => '',
);
// SearchPageRepository::getDefaultSearchPage() depends on search.settings.
$this->renderer->addCacheableDependency($form, $this->configFactory->get('search.settings'));
return $form;
}
......
......@@ -154,8 +154,7 @@ function testSearchModuleDisabling() {
// Test each plugin if it's enabled as the only search plugin.
foreach ($entities as $entity_id => $entity) {
// Set this as default.
$this->drupalGet("admin/config/search/pages/manage/$entity_id/set-default");
$this->setDefaultThroughUi($entity_id);
// Run a search from the correct search URL.
$info = $plugin_info[$entity_id];
......@@ -187,13 +186,16 @@ function testSearchModuleDisabling() {
$entity->disable()->save();
}
// Set the node search as default.
$this->setDefaultThroughUi('node_search');
// Test with all search plugins enabled. When you go to the search
// page or run search, all plugins should be shown.
foreach ($entities as $entity) {
$entity->enable()->save();
}
// Set the node search as default.
$this->drupalGet('admin/config/search/pages/manage/node_search/set-default');
\Drupal::service('router.builder')->rebuild();
$paths = array(
array('path' => 'search/node', 'options' => array('query' => array('keys' => 'pizza'))),
......@@ -316,6 +318,19 @@ public function testMultipleSearchPages() {
$this->verifySearchPageOperations($first_id, FALSE, FALSE, FALSE, FALSE);
}
/**
* Tests that the enable/disable/default routes are protected from CSRF.
*/
public function testRouteProtection() {
// Ensure that the enable and disable routes are protected.
$this->drupalGet('admin/config/search/pages/manage/node_search/enable');
$this->assertResponse(403);
$this->drupalGet('admin/config/search/pages/manage/node_search/disable');
$this->assertResponse(403);
$this->drupalGet('admin/config/search/pages/manage/node_search/set-default');
$this->assertResponse(403);
}
/**
* Checks that the search page operations match expectations.
*
......@@ -373,4 +388,17 @@ protected function assertDefaultSearch($expected, $message = '', $group = 'Other
$this->assertIdentical($search_page_repository->getDefaultSearchPage(), $expected, $message, $group);
}
/**
* Sets a search page as the default in the UI.
*
* @param string $entity_id
* The search page entity ID to enable.
*/
protected function setDefaultThroughUi($entity_id) {
$this->drupalGet('admin/config/search/pages');
preg_match('|href="([^"]+' . $entity_id . '/set-default[^"]+)"|', $this->getRawContent(), $matches);
$this->drupalGet($this->getAbsoluteUrl($matches[1]));
}
}
......@@ -240,7 +240,10 @@ abstract class TestBase {
/**
* The temporary file directory for the test environment.
*
* This is set in TestBase::prepareEnvironment().
* This is set in TestBase::prepareEnvironment(). This value has to match the
* temporary directory created in install_base_system() for test installs.
*
* @see install_base_system()
*
* @var string
*/
......
<?php
namespace Drupal\simpletest\Tests;
use Drupal\simpletest\WebTestBase;
/**
* Tests the test-specifics customisations done in the installation.
*
* @group simpletest
*/
class WebTestBaseInstallTest extends WebTestBase {
/**
* Tests the Drupal install done in \Drupal\simpletest\WebTestBase::setUp().
*/
public function testInstall() {
$htaccess_filename = $this->getTempFilesDirectory() . '/.htaccess';
$this->assertTrue(file_exists($htaccess_filename), "$htaccess_filename exists");
}
}
......@@ -496,9 +496,15 @@ protected function prepareSettings() {
$directory = DRUPAL_ROOT . '/' . $this->siteDirectory;
copy(DRUPAL_ROOT . '/sites/default/default.settings.php', $directory . '/settings.php');
// All file system paths are created by System module during installation.
// The public file system path is created during installation. Additionally,
// during tests:
// - The temporary directory is set and created by install_base_system().
// - The private file directory is created post install by
// WebTestBase::initConfig().
// @see system_requirements()
// @see TestBase::prepareEnvironment()
// @see install_base_system()
// @see\Drupal\simpletest\WebTestBase::initConfig()
$settings['settings']['file_public_path'] = (object) [
'value' => $this->publicFilesDirectory,
'required' => TRUE,
......@@ -587,15 +593,8 @@ protected function initSettings() {
protected function initConfig(ContainerInterface $container) {
$config = $container->get('config.factory');
// Manually create and configure private and temporary files directories.
// While these could be preset/enforced in settings.php like the public
// files directory above, some tests expect them to be configurable in the
// UI. If declared in settings.php, they would no longer be configurable.
// Manually create the private directory.
file_prepare_directory($this->privateFilesDirectory, FILE_CREATE_DIRECTORY);
file_prepare_directory($this->tempFilesDirectory, FILE_CREATE_DIRECTORY);
$config->getEditable('system.file')
->set('path.temporary', $this->tempFilesDirectory)
->save();
// Manually configure the test mail collector implementation to prevent
// tests from sending out emails and collect them in state instead.
......@@ -1302,7 +1301,7 @@ protected function drupalGet($path, array $options = array(), array $headers = a
}
if ($path instanceof Url) {
$path = $path->toString();
$path = $path->setAbsolute()->toString(TRUE)->getGeneratedUrl();
}
$verbose = 'GET request to: ' . $path .
......@@ -2589,7 +2588,7 @@ protected function buildUrl($path, array $options = array()) {
$url_options = $path->getOptions();
$options = $url_options + $options;
$path->setOptions($options);
return $path->setAbsolute()->toString();
return $path->setAbsolute()->toString(TRUE)->getGeneratedUrl();
}
// The URL generator service is not necessarily available yet; e.g., in
// interactive installer tests.
......
......@@ -167,7 +167,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
public function validateForm(array &$form, FormStateInterface $form_state) {
// Form submitted, but no modules selected.
if (!array_filter($form_state->getValue('uninstall'))) {
$form_state->setErrorByName('uninstall', $this->t('No modules selected.'));
$form_state->setErrorByName('', $this->t('No modules selected.'));
$form_state->setRedirect('system.modules_uninstall');
}
}
......