diff --git a/frontend/public/components/catalog/_catalog.scss b/frontend/public/components/catalog/_catalog.scss index a50e9bbd930..10f62367e20 100644 --- a/frontend/public/components/catalog/_catalog.scss +++ b/frontend/public/components/catalog/_catalog.scss @@ -140,19 +140,10 @@ $catalog-item-icon-size-sm: 24px; // Enable scrolling on the modal &__overlay { - .modal-body { - flex: 1 1 auto; - overflow-y: auto; - -webkit-overflow-scrolling: touch; - - .hint-block-pf { + .modal-body .hint-block-pf { margin-bottom: 10px; - } - } - .modal-content { - display: flex; - flex-direction: column; } + .properties-side-panel-pf { flex: 0 0 auto; } diff --git a/frontend/public/components/catalog/catalog-item-details.jsx b/frontend/public/components/catalog/catalog-item-details.jsx index 62905ac7133..c9b29527147 100644 --- a/frontend/public/components/catalog/catalog-item-details.jsx +++ b/frontend/public/components/catalog/catalog-item-details.jsx @@ -69,28 +69,32 @@ export class CatalogTileDetails extends React.Component { iconImg={tileImgUrl} /> -
- - {this.props.item.createLabel} - {tileProvider && } - {supportUrl && } - {creationTimestamp && } />} - -
- {tileDescription &&

{tileDescription}

} - {longDescription &&

{longDescription}

} - {sampleRepo &&

Sample repository: {sampleRepoLink}

} - {documentationUrl && -

Documentation

-

{documentationUrlLink}

-
} - {!_.isEmpty(plans) && -

Service Plans

-
    - {planItems} -
-
} - {kind === 'ImageStream' && } +
+
+
+ + {this.props.item.createLabel} + {tileProvider && } + {supportUrl && } + {creationTimestamp && } />} + +
+ {tileDescription &&

{tileDescription}

} + {longDescription &&

{longDescription}

} + {sampleRepo &&

Sample repository: {sampleRepoLink}

} + {documentationUrl && +

Documentation

+

{documentationUrlLink}

+
} + {!_.isEmpty(plans) && +

Service Plans

+
    + {planItems} +
+
} + {kind === 'ImageStream' && } +
+
diff --git a/frontend/public/components/factory/modal.tsx b/frontend/public/components/factory/modal.tsx index 20fe55c95d1..c6fd28cc034 100644 --- a/frontend/public/components/factory/modal.tsx +++ b/frontend/public/components/factory/modal.tsx @@ -35,7 +35,7 @@ export const createModalLauncher: CreateModalLauncher = (Component) => (props) = isOpen={true} contentLabel="Modal" onRequestClose={closeModal} - className="modal-dialog modal-content" + className="modal-dialog" overlayClassName="co-overlay" shouldCloseOnOverlayClick={!props.blocking}> @@ -48,7 +48,14 @@ export const createModalLauncher: CreateModalLauncher = (Component) => (props) = export const ModalTitle: React.SFC = ({children, className = 'modal-header'}) =>

{children}

; -export const ModalBody: React.SFC = ({children, className= 'modal-body'}) =>
{children}
; +export const ModalBody: React.SFC = ({children, className= 'modal-body'}) => ( +
+
+
{children}
+
+
+); + export const ModalFooter: React.SFC = ({message, errorMessage, inProgress, children}) => { return diff --git a/frontend/public/components/modals/_modals.scss b/frontend/public/components/modals/_modals.scss index 525450d292f..20be2e9dde8 100644 --- a/frontend/public/components/modals/_modals.scss +++ b/frontend/public/components/modals/_modals.scss @@ -26,42 +26,75 @@ } } +// Modal modifications to enable vertical scrolling with shadow overlays .modal-body { display: flex; + flex: 1 1 auto; flex-direction: column; + height: 100%; overflow-y: auto; - -webkit-overflow-scrolling: touch; // enable momentum scrolling in mobile Safari + padding: 0; + @include scroll-shadows-vertical; + -webkit-overflow-scrolling: touch; +} + +.modal-body-content { + height: 100%; +} + +.modal-body-inner-shadow-covers { + min-height: 100%; + padding: ($grid-gutter-width / 2) $modal-title-padding-horizontal; + @include scroll-shadows-vertical-covers; + width: 100%; + + // so that input, textarea, button, and input-group-addon don't mask the inner scroll shadows + input, textarea { + &.form-control { + background-color: transparent; + &[disabled], + &[readonly] { + background-color: rgba(234, 234, 234, 0.5); + } + } + } - @media(max-width: $screen-xs-max) { - bottom: 75px; - height: auto; - left: 11px; - position: fixed; - right: 11px; - top: 54px; - width: auto; + .input-group-addon { + background-color: rgba(227, 227, 227, 0.5); } +} +.modal-content { + display: flex; + flex-direction: column; + height: 100%; @media(min-width: $screen-sm-min) { - max-height: calc(100vh - 165px); // 165px = 30 (margin-top) + 44 (modal-header) + 15 (modal-footer margin-top) + 44 (modal-footer) + 30 (margin-bottom) + 2px (top/bottom border) - min-height: 200px; + max-height: 415px; + } + min-height: 250px; + position: relative; +} + +@media(min-width: $screen-sm-min) { + .modal-content--large { + max-height: 530px; } + .modal-content--small { + max-height: 300px; + } } +// setting a height on modal-dialog enables flex child height to shrink and become scrollable .modal-dialog { - @media(max-width: $screen-xs-max) { - height: calc(100% - 20px); + height: calc(100% - 20px); // subtract height margin-top 10px + margin-bottom 10px + outline: 0; + + @media(min-width: $screen-sm-min) { + height: calc(100% - 60px); // subtract height margin-top 30px + margin-bottom 30px } } .modal-footer { - bottom: 0; - left: 0; - padding-top: 0; - position: absolute; - right: 0; - @media(min-width: $screen-sm-min) { - position: relative; - } + margin-top: 0; } diff --git a/frontend/public/components/modals/add-secret-to-workload.tsx b/frontend/public/components/modals/add-secret-to-workload.tsx index c102cabe8a2..834dab038fe 100644 --- a/frontend/public/components/modals/add-secret-to-workload.tsx +++ b/frontend/public/components/modals/add-secret-to-workload.tsx @@ -163,7 +163,7 @@ export class AddSecretToWorkloadModal extends React.Component + return
Add Secret to Workload

diff --git a/frontend/public/components/modals/cluster-update-modal.tsx b/frontend/public/components/modals/cluster-update-modal.tsx index 738fdbd9f6c..1be36ab082a 100644 --- a/frontend/public/components/modals/cluster-update-modal.tsx +++ b/frontend/public/components/modals/cluster-update-modal.tsx @@ -41,7 +41,7 @@ class ClusterUpdateModal extends PromiseComponent { const currentVersion = getCurrentClusterVersion(cv); const dropdownItems = _.map(availableUpdates, 'version'); const dropdownTitle = _.get(availableUpdates[selectedVersion], 'version'); - return + return Update Cluster

diff --git a/frontend/public/components/modals/configure-count-modal.jsx b/frontend/public/components/modals/configure-count-modal.jsx index 9684d06eb57..edf81a52b78 100644 --- a/frontend/public/components/modals/configure-count-modal.jsx +++ b/frontend/public/components/modals/configure-count-modal.jsx @@ -55,7 +55,7 @@ class ConfigureCountModal extends PromiseComponent { } render() { - return + return {this.props.title}

{this.props.message}

diff --git a/frontend/public/components/modals/configure-ns-pull-secret-modal.jsx b/frontend/public/components/modals/configure-ns-pull-secret-modal.jsx index bd2374870a3..302ea8c8e56 100644 --- a/frontend/public/components/modals/configure-ns-pull-secret-modal.jsx +++ b/frontend/public/components/modals/configure-ns-pull-secret-modal.jsx @@ -169,7 +169,7 @@ class ConfigureNamespacePullSecret extends PromiseComponent { const existingData = parseExisitingPullSecret(pullSecret); - return + return Default Pull Secret

diff --git a/frontend/public/components/modals/configure-operator-channel-modal.jsx b/frontend/public/components/modals/configure-operator-channel-modal.jsx index 1d51a808aac..247d9a9912a 100644 --- a/frontend/public/components/modals/configure-operator-channel-modal.jsx +++ b/frontend/public/components/modals/configure-operator-channel-modal.jsx @@ -38,7 +38,7 @@ class ConfigureOperatorChannel extends PromiseComponent { 'tectonic-1.9-preproduction': 'Tectonic-1.9-preproduction', 'tectonic-1.9-production': 'Tectonic-1.9-production', }; - return + return Update Channel

diff --git a/frontend/public/components/modals/configure-operator-modal.jsx b/frontend/public/components/modals/configure-operator-modal.jsx index 3da487ef840..8f3b8cf608c 100644 --- a/frontend/public/components/modals/configure-operator-modal.jsx +++ b/frontend/public/components/modals/configure-operator-modal.jsx @@ -43,7 +43,7 @@ class ConfigureOperatorModal extends PromiseComponent { } render() { - return + return {this.props.title}
{this.props.message}
diff --git a/frontend/public/components/modals/configure-unschedulable-modal.jsx b/frontend/public/components/modals/configure-unschedulable-modal.jsx index 3b4be606ea3..3e79e23a5d4 100644 --- a/frontend/public/components/modals/configure-unschedulable-modal.jsx +++ b/frontend/public/components/modals/configure-unschedulable-modal.jsx @@ -23,7 +23,7 @@ class UnscheduleNodeModal extends PromiseComponent { } render() { - return + return Mark as Unschedulable Unschedulable nodes won't accept new pods. This is useful for scheduling maintenance or preparing to decommission a node. diff --git a/frontend/public/components/modals/configure-update-strategy-modal.jsx b/frontend/public/components/modals/configure-update-strategy-modal.jsx index 070071b55c9..301871e93ac 100644 --- a/frontend/public/components/modals/configure-update-strategy-modal.jsx +++ b/frontend/public/components/modals/configure-update-strategy-modal.jsx @@ -61,7 +61,7 @@ class ConfigureUpdateStrategyModal extends PromiseComponent { const maxUnavailable = _.get(this.deployment.spec, 'strategy.rollingUpdate.maxUnavailable', ''); const maxSurge = _.get(this.deployment.spec, 'strategy.rollingUpdate.maxSurge', ''); - return + return Edit Update Strategy
diff --git a/frontend/public/components/modals/confirm-modal.jsx b/frontend/public/components/modals/confirm-modal.jsx index 9f9fe4ce6ec..66967e56d1c 100644 --- a/frontend/public/components/modals/confirm-modal.jsx +++ b/frontend/public/components/modals/confirm-modal.jsx @@ -22,7 +22,7 @@ class ConfirmModal extends PromiseComponent { } render() { - return + return {this.props.title} {this.props.message} diff --git a/frontend/public/components/modals/create-namespace-modal.jsx b/frontend/public/components/modals/create-namespace-modal.jsx index 9d5a9a91a2f..11f9ce9d82e 100644 --- a/frontend/public/components/modals/create-namespace-modal.jsx +++ b/frontend/public/components/modals/create-namespace-modal.jsx @@ -101,7 +101,7 @@ const CreateNamespaceModal = connect(null, mapDispatchToProps)(class CreateNames [allow]: 'No restrictions (default)', [deny]: 'Deny all inbound traffic', }; - return + return Create {label}
diff --git a/frontend/public/components/modals/delete-modal.jsx b/frontend/public/components/modals/delete-modal.jsx index e4bf001f3ce..c7b0771d4c4 100644 --- a/frontend/public/components/modals/delete-modal.jsx +++ b/frontend/public/components/modals/delete-modal.jsx @@ -43,7 +43,7 @@ class DeleteModal extends PromiseComponent { render() { const {kind, resource} = this.props; - return + return Delete {kind.label}
diff --git a/frontend/public/components/modals/delete-namespace-modal.jsx b/frontend/public/components/modals/delete-namespace-modal.jsx index 09b480accaf..d42b1476568 100644 --- a/frontend/public/components/modals/delete-namespace-modal.jsx +++ b/frontend/public/components/modals/delete-namespace-modal.jsx @@ -28,7 +28,7 @@ class DeleteNamespaceModal extends PromiseComponent { } render() { - return + return Delete {this.props.kind.label}
diff --git a/frontend/public/components/modals/disable-application-modal.tsx b/frontend/public/components/modals/disable-application-modal.tsx index 817a5fad511..21f546d1b70 100644 --- a/frontend/public/components/modals/disable-application-modal.tsx +++ b/frontend/public/components/modals/disable-application-modal.tsx @@ -38,7 +38,7 @@ export class DisableApplicationModal extends PromiseComponent { render() { const {name} = this.props.subscription.spec; - return + return Remove Subscription
diff --git a/frontend/public/components/modals/error-modal.jsx b/frontend/public/components/modals/error-modal.jsx index 96fee0388c1..8e287666d4d 100644 --- a/frontend/public/components/modals/error-modal.jsx +++ b/frontend/public/components/modals/error-modal.jsx @@ -5,7 +5,7 @@ import {createModalLauncher, ModalTitle, ModalBody, ModalFooter} from '../factor export const errorModal = createModalLauncher( ({error, cancel}) => { return ( -
+
Error {error} diff --git a/frontend/public/components/modals/installplan-approval-modal.tsx b/frontend/public/components/modals/installplan-approval-modal.tsx index e9ab20ea2d2..91dbdec0134 100644 --- a/frontend/public/components/modals/installplan-approval-modal.tsx +++ b/frontend/public/components/modals/installplan-approval-modal.tsx @@ -34,7 +34,7 @@ export class InstallPlanApprovalModal extends PromiseComponent { } render() { - return + return Change Update Approval Strategy
diff --git a/frontend/public/components/modals/labels-modal.jsx b/frontend/public/components/modals/labels-modal.jsx index 98283e94de6..9c781672644 100644 --- a/frontend/public/components/modals/labels-modal.jsx +++ b/frontend/public/components/modals/labels-modal.jsx @@ -50,7 +50,7 @@ class BaseLabelsModal extends PromiseComponent { render() { const { kind, resource, description, message, labelClassName } = this.props; - return + return Edit {description || 'Labels'}
diff --git a/frontend/public/components/modals/subscription-channel-modal.tsx b/frontend/public/components/modals/subscription-channel-modal.tsx index 4f351a60ac5..7401a80aae1 100644 --- a/frontend/public/components/modals/subscription-channel-modal.tsx +++ b/frontend/public/components/modals/subscription-channel-modal.tsx @@ -28,7 +28,7 @@ export class SubscriptionChannelModal extends PromiseComponent { } render() { - return + return Change Subscription Update Channel
diff --git a/frontend/public/components/modals/tags.jsx b/frontend/public/components/modals/tags.jsx index 157c01bac9d..5438ae167ed 100644 --- a/frontend/public/components/modals/tags.jsx +++ b/frontend/public/components/modals/tags.jsx @@ -56,7 +56,7 @@ class TagsModal extends PromiseComponent { render() { const {tags} = this.state; - return + return {this.props.title} diff --git a/frontend/public/components/modals/token-info-modal.jsx b/frontend/public/components/modals/token-info-modal.jsx index 73956696ffd..50d95eccb02 100644 --- a/frontend/public/components/modals/token-info-modal.jsx +++ b/frontend/public/components/modals/token-info-modal.jsx @@ -34,7 +34,7 @@ class TokenInfoModal extends PromiseComponent { e.stopPropagation(); this.props.close(e); }; - return
+ return
Token Information
{this.state.tokenReview}
diff --git a/frontend/public/components/operator-hub/operator-hub-item-details.tsx b/frontend/public/components/operator-hub/operator-hub-item-details.tsx index e2bfc39ae75..7aed13c87d7 100644 --- a/frontend/public/components/operator-hub/operator-hub-item-details.tsx +++ b/frontend/public/components/operator-hub/operator-hub-item-details.tsx @@ -88,29 +88,33 @@ export const OperatorHubItemDetails: React.SFC = ({ /> -
- - - - - - - - - - -
- {getHintBlock()} - {longDescription - ? - : description} +
+
+
+ + + + + + + + + + +
+ {getHintBlock()} + {longDescription + ? + : description} +
+
diff --git a/frontend/public/components/operator-lifecycle-manager/descriptors/spec/resource-requirements.tsx b/frontend/public/components/operator-lifecycle-manager/descriptors/spec/resource-requirements.tsx index cac9810d97c..d897aa919f9 100644 --- a/frontend/public/components/operator-lifecycle-manager/descriptors/spec/resource-requirements.tsx +++ b/frontend/public/components/operator-lifecycle-manager/descriptors/spec/resource-requirements.tsx @@ -26,7 +26,7 @@ export class ResourceRequirementsModal extends PromiseComponent { } render() { - return this.submit(e)}> + return this.submit(e)} className="modal-content"> {this.props.title}
diff --git a/frontend/public/style.scss b/frontend/public/style.scss index 5c2bc7a259d..9047bfa8d55 100644 --- a/frontend/public/style.scss +++ b/frontend/public/style.scss @@ -18,6 +18,7 @@ // Mixins @import "style/mixin/prefix"; @import "style/mixin/break-word"; +@import "style/mixin/scroll-shadows"; /* CUSTOM STYLES */ diff --git a/frontend/public/style/_overrides.scss b/frontend/public/style/_overrides.scss index 7527080da94..e091b78f985 100644 --- a/frontend/public/style/_overrides.scss +++ b/frontend/public/style/_overrides.scss @@ -38,7 +38,12 @@ tags-input .tags { @include transition(border-color ease-in-out .15s, box-shadow ease-in-out .15s); } .modal-body tags-input .tags { - min-height: 200px; + background-color: rgba(255, 255, 255, 0.5); // enable scroll-shadows to be seen + margin-bottom: ($grid-gutter-width / 2); + min-height: 120px; + .tag-item { + background-color: rgba(235,235,235,.5); // enable scroll-shadows to be seen + } } tags-input .tags.focused, tags-input .tags:focus { @@ -218,10 +223,19 @@ tags-input .autocomplete .suggestion-item em { } } -.modal.right-side-modal-pf .modal-dialog { - margin-top: $pf-4-nav-bar-height; // since PatternFly 4's masthead is taller than PatternFly 3's - .modal-content { - height: calc(100vh - #{$pf-4-nav-bar-height}); + + +.modal.right-side-modal-pf { + top: 76px; // since PatternFly 4's masthead is taller than PatternFly 3's + + .modal-dialog { + height: 100%; // Entend panel to bottom + margin-top: 0; // parent is positioned: fixed so margin isn't needed for positioning + + .modal-content { + height: 100%; // Use % instead of vh so that scroll-shadows can be used + max-height: none; + } } } diff --git a/frontend/public/style/mixin/_scroll-shadows.scss b/frontend/public/style/mixin/_scroll-shadows.scss new file mode 100644 index 00000000000..a0e26ea891d --- /dev/null +++ b/frontend/public/style/mixin/_scroll-shadows.scss @@ -0,0 +1,15 @@ +@mixin scroll-shadows-vertical($shadow-width: 90%, $shadow-opacity: 0.25) { + background-attachment: scroll; + background-image: radial-gradient(ellipse at top, rgba(0, 0, 0, $shadow-opacity) 0%, rgba(0, 0, 0, 0) $shadow-width), radial-gradient(ellipse at bottom, rgba(0, 0, 0, $shadow-opacity) 0%, rgba(0, 0, 0, 0) $shadow-width); + background-position: 0 0, 0 100%; + background-repeat: no-repeat; + background-size: 100% 5px; +} + +@mixin scroll-shadows-vertical-covers($shadow-cover-bg-color: rgba(255,255,255,1), $shadow-cover-bg-color-transparent: rgba(255,255,255,0)) { + background-attachment: local; + background-image: linear-gradient($shadow-cover-bg-color 30%, $shadow-cover-bg-color-transparent), linear-gradient($shadow-cover-bg-color-transparent, $shadow-cover-bg-color 70%); + background-position: 0 0, 0 100%; + background-repeat: no-repeat; + background-size: 100% 12px; +}