diff --git a/src/Umbraco.Web.UI.Client/gulp/tasks/watchTask.js b/src/Umbraco.Web.UI.Client/gulp/tasks/watchTask.js index 4c59fd916216..24a6e6554022 100644 --- a/src/Umbraco.Web.UI.Client/gulp/tasks/watchTask.js +++ b/src/Umbraco.Web.UI.Client/gulp/tasks/watchTask.js @@ -20,7 +20,7 @@ function watchTask(cb) { //Setup a watcher for all groups of JS files _.forEach(config.sources.js, function (group) { if(group.watch !== false) { - watch(group.files, { ignoreInitial: true, interval: watchInterval }, function JS_Group_Compile() { return processJs(group.files, group.out); }); + watch(group.files, { ignoreInitial: true, interval: watchInterval }, function JS_Group_Compile() { return processJs(group.files, group.out);}); } }); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/property/umbproperty.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/property/umbproperty.directive.js index 302378b8c08d..06b9e51fba92 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/property/umbproperty.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/property/umbproperty.directive.js @@ -16,6 +16,9 @@ angular.module("umbraco.directives") replace: true, templateUrl: 'views/components/property/umb-property.html', link: function (scope) { + + scope.propertyEditorAPI = {}; + userService.getCurrentUser().then(function (u) { var isAdmin = u.userGroups.indexOf('admin') !== -1; scope.propertyAlias = (Umbraco.Sys.ServerVariables.isDebuggingEnabled === true || isAdmin) ? scope.property.alias : null; @@ -32,6 +35,19 @@ angular.module("umbraco.directives") self.setPropertyError = function (errorMsg) { $scope.property.propertyErrorMessage = errorMsg; }; + + var unsubscribe = $scope.$on("ExposePropertyEditorAPI", function(event, api) { + + //avoid eventual parent properties to capture this. + event.stopPropagation(); + + $scope.propertyEditorAPI = api; + }); + + $scope.$on("$destroy", function () { + unsubscribe(); + }); + } }; }); diff --git a/src/Umbraco.Web.UI.Client/src/common/services/clipboard.service.js b/src/Umbraco.Web.UI.Client/src/common/services/clipboard.service.js index 647133f0b76b..c3a1ba643219 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/clipboard.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/clipboard.service.js @@ -1,203 +1,264 @@ -/** - * @ngdoc service - * @name umbraco.services.clipboardService - * - * @requires notificationsService - * @requires eventsService - * - * @description - * Service to handle clipboard in general across the application. Responsible for handling the data both storing and retrive. - * The service has a set way for defining a data-set by a entryType and alias, which later will be used to retrive the posible entries for a paste scenario. - * - */ -function clipboardService(notificationsService, eventsService, localStorageService) { - - - var STORAGE_KEY = "umbClipboardService"; - - var retriveStorage = function() { - if (localStorageService.isSupported === false) { - return null; - } - var dataJSON; - var dataString = localStorageService.get(STORAGE_KEY); - if (dataString != null) { - dataJSON = JSON.parse(dataString); - } - - if(dataJSON == null) { - dataJSON = new Object(); - } - - if(dataJSON.entries === undefined) { - dataJSON.entries = []; - } - - return dataJSON; - } - - var saveStorage = function(storage) { - var storageString = JSON.stringify(storage); - - try { - var storageJSON = JSON.parse(storageString); - localStorageService.set(STORAGE_KEY, storageString); - - eventsService.emit("clipboardService.storageUpdate"); - - return true; - } catch(e) { - return false; - } - - return false; - } - - - var service = {}; - - /** - * @ngdoc method - * @name umbraco.services.clipboardService#copy - * @methodOf umbraco.services.clipboardService - * - * @param {string} type A string defining the type of data to storing, example: 'elementType', 'contentNode' - * @param {string} alias A string defining the alias of the data to store, example: 'product' - * @param {object} data A object containing the properties to be saved. - * - * @description - * Saves a single JS-object with a type and alias to the clipboard. - */ - service.copy = function(type, alias, data) { - - var storage = retriveStorage(); - - var shallowCloneData = Object.assign({}, data);// Notice only a shallow copy, since we dont need to deep copy. (that will happen when storing the data) - delete shallowCloneData.key; - delete shallowCloneData.$$hashKey; - - var key = data.key || data.$$hashKey || console.error("missing unique key for this content"); - - // remove previous copies of this entry: - storage.entries = storage.entries.filter( - (entry) => { - return entry.unique !== key; - } - ); - - var entry = {unique:key, type:type, alias:alias, data:shallowCloneData}; - storage.entries.push(entry); - - if (saveStorage(storage) === true) { - notificationsService.success("Clipboard", "Copied to clipboard."); - } else { - notificationsService.success("Clipboard", "Couldnt copy this data to clipboard."); - } - - }; - - - /** - * @ngdoc method - * @name umbraco.services.supportsCopy#supported - * @methodOf umbraco.services.clipboardService - * - * @description - * Determins wether the current browser is able to performe its actions. - */ - service.isSupported = function() { - return localStorageService.isSupported; - }; - - /** - * @ngdoc method - * @name umbraco.services.supportsCopy#hasEntriesOfType - * @methodOf umbraco.services.clipboardService - * - * @param {string} type A string defining the type of data test for. - * @param {string} aliases A array of strings providing the alias of the data you want to test for. - * - * @description - * Determines whether the current clipboard has entries that match a given type and one of the aliases. - */ - service.hasEntriesOfType = function(type, aliases) { - - if(service.retriveEntriesOfType(type, aliases).length > 0) { - return true; - } - - return false; - }; - - /** - * @ngdoc method - * @name umbraco.services.supportsCopy#retriveEntriesOfType - * @methodOf umbraco.services.clipboardService - * - * @param {string} type A string defining the type of data to recive. - * @param {string} aliases A array of strings providing the alias of the data you want to recive. - * - * @description - * Returns an array of entries matching the given type and one of the provided aliases. - */ - service.retriveEntriesOfType = function(type, aliases) { - - var storage = retriveStorage(); - - // Find entries that are fulfilling the criteria for this nodeType and nodeTypesAliases. - var filteretEntries = storage.entries.filter( - (entry) => { - return (entry.type === type && aliases.filter(alias => alias === entry.alias).length > 0); - } - ); - - return filteretEntries; - }; - - /** - * @ngdoc method - * @name umbraco.services.supportsCopy#retriveEntriesOfType - * @methodOf umbraco.services.clipboardService - * - * @param {string} type A string defining the type of data to recive. - * @param {string} aliases A array of strings providing the alias of the data you want to recive. - * - * @description - * Returns an array of data of entries matching the given type and one of the provided aliases. - */ - service.retriveDataOfType = function(type, aliases) { - return service.retriveEntriesOfType(type, aliases).map((x) => x.data); - }; - - /** - * @ngdoc method - * @name umbraco.services.supportsCopy#retriveEntriesOfType - * @methodOf umbraco.services.clipboardService - * - * @param {string} type A string defining the type of data to remove. - * @param {string} aliases A array of strings providing the alias of the data you want to remove. - * - * @description - * Removes entries matching the given type and one of the provided aliases. - */ - service.clearEntriesOfType = function(type, aliases) { - - var storage = retriveStorage(); - - // Find entries that are NOT fulfilling the criteria for this nodeType and nodeTypesAliases. - var filteretEntries = storage.entries.filter( - (entry) => { - return !(entry.type === type && aliases.filter(alias => alias === entry.alias).length > 0); - } - ); - - storage.entries = filteretEntries; - - saveStorage(storage); - }; - - - - return service; -} -angular.module("umbraco.services").factory("clipboardService", clipboardService); +/** + * @ngdoc service + * @name umbraco.services.clipboardService + * + * @requires notificationsService + * @requires eventsService + * + * @description + * Service to handle clipboard in general across the application. Responsible for handling the data both storing and retrive. + * The service has a set way for defining a data-set by a entryType and alias, which later will be used to retrive the posible entries for a paste scenario. + * + */ +function clipboardService(notificationsService, eventsService, localStorageService, iconHelper) { + + + var STORAGE_KEY = "umbClipboardService"; + + var retriveStorage = function() { + if (localStorageService.isSupported === false) { + return null; + } + var dataJSON; + var dataString = localStorageService.get(STORAGE_KEY); + if (dataString != null) { + dataJSON = JSON.parse(dataString); + } + + if(dataJSON == null) { + dataJSON = new Object(); + } + + if(dataJSON.entries === undefined) { + dataJSON.entries = []; + } + + return dataJSON; + } + + var saveStorage = function(storage) { + var storageString = JSON.stringify(storage); + + try { + var storageJSON = JSON.parse(storageString); + localStorageService.set(STORAGE_KEY, storageString); + + eventsService.emit("clipboardService.storageUpdate"); + + return true; + } catch(e) { + return false; + } + + return false; + } + + var prepareEntryForStorage = function(entryData) { + + var shallowCloneData = Object.assign({}, entryData);// Notice only a shallow copy, since we dont need to deep copy. (that will happen when storing the data) + delete shallowCloneData.key; + delete shallowCloneData.$$hashKey; + + return shallowCloneData; + } + + var isEntryCompatible = function(entry, type, allowedAliases) { + return entry.type === type + && + ( + (entry.alias && allowedAliases.filter(allowedAlias => allowedAlias === entry.alias).length > 0) + || + (entry.aliases && entry.aliases.filter(entryAlias => allowedAliases.filter(allowedAlias => allowedAlias === entryAlias).length > 0).length === entry.aliases.length) + ); + } + + + var service = {}; + + /** + * @ngdoc method + * @name umbraco.services.clipboardService#copy + * @methodOf umbraco.services.clipboardService + * + * @param {string} type A string defining the type of data to storing, example: 'elementType', 'contentNode' + * @param {string} alias A string defining the alias of the data to store, example: 'product' + * @param {object} entry A object containing the properties to be saved, this could be the object of a ElementType, ContentNode, ... + * @param {string} displayLabel (optional) A string swetting the label to display when showing paste entries. + * + * @description + * Saves a single JS-object with a type and alias to the clipboard. + */ + service.copy = function(type, alias, data, displayLabel) { + + var storage = retriveStorage(); + + var uniqueKey = data.key || data.$$hashKey || console.error("missing unique key for this content"); + + // remove previous copies of this entry: + storage.entries = storage.entries.filter( + (entry) => { + return entry.unique !== uniqueKey; + } + ); + + var entry = {unique:uniqueKey, type:type, alias:alias, data:prepareEntryForStorage(data), label:displayLabel || data.name, icon:iconHelper.convertFromLegacyIcon(data.icon)}; + storage.entries.push(entry); + + if (saveStorage(storage) === true) { + notificationsService.success("Clipboard", "Copied to clipboard."); + } else { + notificationsService.error("Clipboard", "Couldnt copy this data to clipboard."); + } + + }; + + + /** + * @ngdoc method + * @name umbraco.services.clipboardService#copyArray + * @methodOf umbraco.services.clipboardService + * + * @param {string} type A string defining the type of data to storing, example: 'elementTypeArray', 'contentNodeArray' + * @param {string} aliases An array of strings defining the alias of the data to store, example: ['banana', 'apple'] + * @param {object} datas An array of objects containing the properties to be saved, example: [ElementType, ElementType, ...] + * @param {string} displayLabel A string setting the label to display when showing paste entries. + * @param {string} displayIcon A string setting the icon to display when showing paste entries. + * @param {string} uniqueKey A string prodiving an identifier for this entry, existing entries with this key will be removed to ensure that you only have the latest copy of this data. + * + * @description + * Saves a single JS-object with a type and alias to the clipboard. + */ + service.copyArray = function(type, aliases, datas, displayLabel, displayIcon, uniqueKey) { + + var storage = retriveStorage(); + + // Clean up each entry + var copiedDatas = datas.map(data => prepareEntryForStorage(data)); + + // remove previous copies of this entry: + storage.entries = storage.entries.filter( + (entry) => { + return entry.unique !== uniqueKey; + } + ); + + var entry = {unique:uniqueKey, type:type, aliases:aliases, data:copiedDatas, label:displayLabel, icon:displayIcon}; + + storage.entries.push(entry); + + if (saveStorage(storage) === true) { + notificationsService.success("Clipboard", "Copied to clipboard."); + } else { + notificationsService.error("Clipboard", "Couldnt copy this data to clipboard."); + } + + }; + + + /** + * @ngdoc method + * @name umbraco.services.supportsCopy#supported + * @methodOf umbraco.services.clipboardService + * + * @description + * Determins wether the current browser is able to performe its actions. + */ + service.isSupported = function() { + return localStorageService.isSupported; + }; + + /** + * @ngdoc method + * @name umbraco.services.supportsCopy#hasEntriesOfType + * @methodOf umbraco.services.clipboardService + * + * @param {string} type A string defining the type of data test for. + * @param {string} aliases A array of strings providing the alias of the data you want to test for. + * + * @description + * Determines whether the current clipboard has entries that match a given type and one of the aliases. + */ + service.hasEntriesOfType = function(type, aliases) { + + if(service.retriveEntriesOfType(type, aliases).length > 0) { + return true; + } + + return false; + }; + + /** + * @ngdoc method + * @name umbraco.services.supportsCopy#retriveEntriesOfType + * @methodOf umbraco.services.clipboardService + * + * @param {string} type A string defining the type of data to recive. + * @param {string} aliases A array of strings providing the alias of the data you want to recive. + * + * @description + * Returns an array of entries matching the given type and one of the provided aliases. + */ + service.retriveEntriesOfType = function(type, allowedAliases) { + + var storage = retriveStorage(); + + // Find entries that are fulfilling the criteria for this nodeType and nodeTypesAliases. + var filteretEntries = storage.entries.filter( + (entry) => { + return isEntryCompatible(entry, type, allowedAliases); + } + ); + + return filteretEntries; + }; + + /** + * @ngdoc method + * @name umbraco.services.supportsCopy#retriveEntriesOfType + * @methodOf umbraco.services.clipboardService + * + * @param {string} type A string defining the type of data to recive. + * @param {string} aliases A array of strings providing the alias of the data you want to recive. + * + * @description + * Returns an array of data of entries matching the given type and one of the provided aliases. + */ + service.retriveDataOfType = function(type, aliases) { + return service.retriveEntriesOfType(type, aliases).map((x) => x.data); + }; + + /** + * @ngdoc method + * @name umbraco.services.supportsCopy#retriveEntriesOfType + * @methodOf umbraco.services.clipboardService + * + * @param {string} type A string defining the type of data to remove. + * @param {string} aliases A array of strings providing the alias of the data you want to remove. + * + * @description + * Removes entries matching the given type and one of the provided aliases. + */ + service.clearEntriesOfType = function(type, allowedAliases) { + + var storage = retriveStorage(); + + // Find entries that are NOT fulfilling the criteria for this nodeType and nodeTypesAliases. + var filteretEntries = storage.entries.filter( + (entry) => { + return !isEntryCompatible(entry, type, allowedAliases); + } + ); + + storage.entries = filteretEntries; + + saveStorage(storage); + }; + + + + return service; +} + + +angular.module("umbraco.services").factory("clipboardService", clipboardService); + diff --git a/src/Umbraco.Web.UI.Client/src/common/services/propertyeditor.service.js b/src/Umbraco.Web.UI.Client/src/common/services/propertyeditor.service.js new file mode 100644 index 000000000000..0b24e78567fe --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/services/propertyeditor.service.js @@ -0,0 +1,29 @@ +(function() { + 'use strict'; + + function propertyEditorService() { + /** + * @ngdoc function + * @name umbraco.services.propertyEditorService#expose + * @methodOf umbraco.services.propertyEditorService + * @function + * + * @param {object} scope An object containing API for the PropertyEditor + */ + function exposeAPI(scope, api) { + if (!scope) { + throw "scope cannot be null"; + } + if (!api) { + throw "api cannot be null"; + } + scope.$emit("ExposePropertyEditorAPI", api); + } + + return { + exposeAPI: exposeAPI + }; + } + + angular.module('umbraco.services').factory('propertyEditorService', propertyEditorService); +})(); diff --git a/src/Umbraco.Web.UI.Client/src/less/belle.less b/src/Umbraco.Web.UI.Client/src/less/belle.less index ea889211d4a3..391fafb3faf3 100644 --- a/src/Umbraco.Web.UI.Client/src/less/belle.less +++ b/src/Umbraco.Web.UI.Client/src/less/belle.less @@ -130,6 +130,7 @@ @import "components/umb-media-grid.less"; @import "components/umb-folder-grid.less"; @import "components/umb-content-grid.less"; +@import "components/umb-contextmenu.less"; @import "components/umb-layout-selector.less"; @import "components/tooltip/umb-tooltip.less"; @import "components/tooltip/umb-tooltip-list.less"; @@ -138,6 +139,7 @@ @import "components/umb-grid.less"; @import "components/umb-empty-state.less"; @import "components/umb-property-editor.less"; +@import "components/umb-property-actions.less"; @import "components/umb-color-swatches.less"; @import "components/check-circle.less"; @import "components/umb-file-icon.less"; @@ -188,6 +190,8 @@ @import "components/users/umb-user-preview.less"; @import "components/users/umb-user-picker-list.less"; +@import "components/contextdialogs/umb-dialog-datatype-delete.less"; + // Utilities @import "utilities/layout/_display.less"; diff --git a/src/Umbraco.Web.UI.Client/src/less/components/contextdialogs/umb-dialog-datatype-delete.less b/src/Umbraco.Web.UI.Client/src/less/components/contextdialogs/umb-dialog-datatype-delete.less new file mode 100644 index 000000000000..0e0b8f22bd52 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/less/components/contextdialogs/umb-dialog-datatype-delete.less @@ -0,0 +1,33 @@ +.umb-dialog-datatype-delete { + + + .umb-dialog-datatype-delete__table-head-column-name { + width: 140px; + } + + .umb-table-body__icon { + margin-right: 5px; + vertical-align: top; + display: inline-block; + } + + .table tbody td { + vertical-align: top; + } + .table tbody td > span { + margin: 5px 0; + vertical-align: middle; + } + .table tbody p { + line-height: 12px; + margin: 5px 0; + vertical-align: middle; + } + + .table tbody .icon { + vertical-align: top; + margin-right: 5px; + display: inline-block; + } + +} diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-contextmenu.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-contextmenu.less new file mode 100644 index 000000000000..8512e2020d42 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-contextmenu.less @@ -0,0 +1,75 @@ +.umb-contextmenu { + margin: 0; + list-style: none; + user-select: none; + + overflow: hidden; + border-radius: 3px; + border: 1px solid @dropdownBorder; + .box-shadow(0 5px 20px rgba(0,0,0,.3)); + border-bottom: 1px solid rgba(0,0,0,.2); + + .sep { + display: block; + border-top: 1px solid @gray-9; + + &:first-child { + border-top: none; + } + } + +} + +.umb-contextmenu-item { + + .icon { + font-size: 18px; + vertical-align: middle; + } + + .menu-label { + display: inline-block; + vertical-align: middle; + margin-left: 5px; + } + + button { + + position: relative; + + display: block; + font-weight: normal; + line-height: @baseLineHeight; + white-space: nowrap; + + background-color: @ui-option; + border: 0; + padding: 7px 12px; + color: @ui-option-type; + width: 100%; + + font-size: 14px; + text-align: left; + + &:hover { + text-decoration: none; + color: @ui-option-type-hover; + background-color: @ui-option-hover; + } + } + + &.-opens-dialog { + .menu-label:after { + // adds an ellipsis (...) after the menu label for actions that open a dialog + content: '\2026'; + } + } + button:disabled { + cursor: not-allowed; + color: @ui-option-disabled-type; + &:hover { + color: @ui-option-disabled-type-hover; + background-color: @ui-option; + } + } +} diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-nested-content.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-nested-content.less index 56b4e19122d4..455a14739563 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-nested-content.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-nested-content.less @@ -1,5 +1,4 @@ .umb-nested-content { - text-align: center; position: relative; } @@ -170,6 +169,7 @@ .umb-nested-content__add-content { display: flex; + width: 100%; align-items: center; justify-content: center; border: 1px dashed @ui-action-discreet-border; diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-property-actions.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-property-actions.less new file mode 100644 index 000000000000..3ce284870ebf --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-property-actions.less @@ -0,0 +1,96 @@ +.umb-property-actions { + display: inline; +} + +.umb-property-actions__toggle, +.umb-property-actions__menu-open-toggle { + position: relative; + display: flex; + flex: 0 0 auto; + padding: 6px 6px; + text-align: center; + cursor: pointer; + border-radius: 3px; + + background-color: @ui-action-hover; + + i { + height: 3px !important; + width: 3px !important; + border-radius: 3px; + background: @ui-action-type; + display: inline-block; + margin: 0 2px 0 0; + + &:last-child { + margin: 0; + } + } + &:hover { + i { + background: @ui-action-type-hover; + } + } +} +.umb-property-actions__menu-open-toggle { + position: absolute; + z-index:1; + outline: none;// this is not acceccible by keyboard, since we use the .umb-property-actions__toggle for that. + + top: -15px; + border-radius: 3px 3px 0 0; + + border-top-left-radius: 3px; + border-top-right-radius: 3px; + + border: 1px solid @dropdownBorder; + + border-bottom: 1px solid @gray-9; + + .box-shadow(0 5px 20px rgba(0,0,0,.3)); + + background-color: white; + +} + +.umb-property .umb-property-actions { + float: left; +} +.umb-property .umb-property-actions__toggle { + margin-top: 2px; + opacity: 0; + transition: opacity 120ms; +} +.umb-property:hover .umb-property-actions__toggle, +.umb-property .umb-property-actions__toggle:focus { + opacity: 1; +} +// Revert-style-hack that ensures that we only show property-actions on properties that are directly begin hovered. +.umb-property:hover .umb-property:not(:hover) .umb-property-actions__toggle { + opacity: 0; +} + +.umb-property-actions__menu { + + position: absolute; + z-index: 1000; + + display: block; + + float: left; + min-width: 160px; + list-style: none; + + .umb-contextmenu { + + border-top-left-radius: 0; + margin-top:1px; + + } + + .umb-contextmenu-item > button { + + z-index:2;// need to stay on top of menu-toggle-open shadow. + + } +} diff --git a/src/Umbraco.Web.UI.Client/src/less/main.less b/src/Umbraco.Web.UI.Client/src/less/main.less index 920fcdb1eb4c..86a1acbeae27 100644 --- a/src/Umbraco.Web.UI.Client/src/less/main.less +++ b/src/Umbraco.Web.UI.Client/src/less/main.less @@ -116,24 +116,42 @@ h5.-black { margin: 20px; } .umb-control-group { - border-bottom: 1px solid @gray-11; - padding-bottom: 20px; + position: relative; + &::after { + content: ''; + display:block; + margin-top: 20px; + width: 100%; + height: 1px; + background-color: @gray-11; + } } .umb-control-group.-no-border { - border: none; + &::after { + margin-top: 0px; + height: 0; + background-color: transparent; + } } .umb-property:last-of-type .umb-control-group { - border: none; - margin-bottom: 0 !important; - padding-bottom: 0; + &::after { + margin-top: 0px; + height: 0; + background-color: transparent; + } + margin-bottom: 0 !important; } /* BLOCK MODE */ .block-form .umb-control-group { - border-bottom: none; - padding-bottom: 0; + margin-top: 0px; + &::after { + margin-top: 0px; + height: 0; + background-color: transparent; + } } .block-form .umb-control-group label .help-block, @@ -163,7 +181,36 @@ h5.-black { } .umb-control-group .umb-el-wrap { - padding: 0 + padding: 0; +} +.form-horizontal .umb-control-group .control-header { + float: left; + width: 160px; + padding-top: 5px; + text-align: left; + + .control-label { + float: left; + width: auto; + padding-top: 0; + text-align: left; + } + + .control-description { + display: block; + clear: both; + max-width:480px;// avoiding description becoming too wide when its placed on top of property. + margin-bottom: 10px; + } +} +@media (max-width: 767px) { + + .form-horizontal .umb-control-group .control-header { + float: none; + width: 100%; + } + + } /* LABELS*/ diff --git a/src/Umbraco.Web.UI.Client/src/less/variables.less b/src/Umbraco.Web.UI.Client/src/less/variables.less index 166640829b7c..e8f6d4ee58e8 100644 --- a/src/Umbraco.Web.UI.Client/src/less/variables.less +++ b/src/Umbraco.Web.UI.Client/src/less/variables.less @@ -132,6 +132,7 @@ @ui-option-type: @blueExtraDark; @ui-option-type-hover: @blueMid; +@ui-option: white; @ui-option-hover: @sand-7; @ui-option-disabled-type: @gray-6; diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/compositions/compositions.html b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/compositions/compositions.html index 071d093ab49c..4096192081c8 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/compositions/compositions.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/compositions/compositions.html @@ -60,7 +60,7 @@
-
+