From 1b556a269d4a14291d396e9e5a1500e57e200e7f Mon Sep 17 00:00:00 2001 From: MariaAga Date: Wed, 29 Apr 2026 15:33:47 +0100 Subject: [PATCH] Fixes #39276 - Add Stylelint rule to block global css overrides --- .github/workflows/js_tests.yml | 2 + .stylelintrc | 10 ---- .stylelintrc.json | 39 +++++++++++++ app/assets/stylesheets/base-pf4.scss | 4 ++ app/assets/stylesheets/base.scss | 16 ++++-- app/assets/stylesheets/navigation.scss | 4 +- .../stylesheets/patternfly_and_overrides.scss | 16 ++---- .../patternfly_colors_overrides.scss | 9 ++- .../pf3-to-pf5-migration-guide.asciidoc | 2 +- developer_docs/plugins.asciidoc | 1 + developer_docs/ui-testing-guidelines.asciidoc | 11 ++++ package-exclude.json | 1 + package.json | 7 ++- script/lint/lint_core_config.js | 1 + .../stylelint-no-bare-element-selectors.js | 47 ++++++++++++++++ script/lint/stylelint-no-root-pf-overrides.js | 54 ++++++++++++++++++ script/npm_stylelint_plugins.js | 56 +++++++++++++++++++ .../react_app/common/scss/mixins.scss | 4 +- .../react_app/common/variables.scss | 2 + .../components/BackendSystemStatus/index.scss | 1 + .../components/ChartBox/ChartBox.css | 1 + .../ColumnSelector/ColumnSelector.js | 10 ++-- .../ColumnSelector/column-selector.scss | 16 ++---- .../components/HostDetails/HostDetails.scss | 9 ++- .../components/HostDetails/Status/styles.scss | 7 +++ .../NetworkingInterfaces.scss | 5 ++ .../HostDetails/Tabs/Details/DetailsCard.scss | 1 + .../Tabs/Parameters/Parameters.scss | 1 + .../BulkActions/bulkDeleteModal.scss | 1 + .../components/HostsIndex/index.scss | 2 + .../ImpersonateIcon/ImpersonateIcon.scss | 2 +- .../TaxonomySwitcher/TaxonomyDropdown.scss | 7 ++- .../components/Toolbar/HeaderToolbar.scss | 5 +- .../react_app/components/Layout/layout.scss | 21 +++++-- .../components/LoginPage/LoginPage.scss | 2 +- .../breadcrumb-switcher.scss | 2 + .../PF4/TableIndexPage/TableIndexPage.scss | 12 ++++ .../components/Pagination/index.scss | 2 +- .../components/SearchBar/SearchBar.scss | 3 + .../SettingsTable/SettingsTable.scss | 1 + .../react_app/components/ToastsList/index.js | 8 ++- .../components/ToastsList/style.scss | 2 +- .../common/ActionButtons/ActionButtons.js | 1 + .../common/ActionButtons/ActionButtons.scss | 4 +- .../DateTimePicker/date-time-picker.scss | 1 + .../common/EmptyState/EmptyState.scss | 2 +- .../common/EmptyState/EmptyStatePattern.js | 2 +- .../components/common/Loader/Loader.css | 4 -- .../common/MessageBox/MessageBox.css | 7 +-- .../ModalProgressBar/ModalProgressBar.scss | 1 + .../personalAccessToken.scss | 3 + 51 files changed, 350 insertions(+), 82 deletions(-) delete mode 100644 .stylelintrc create mode 100644 .stylelintrc.json create mode 100644 script/lint/stylelint-no-bare-element-selectors.js create mode 100644 script/lint/stylelint-no-root-pf-overrides.js create mode 100755 script/npm_stylelint_plugins.js diff --git a/.github/workflows/js_tests.yml b/.github/workflows/js_tests.yml index 0355315ed7..e7e9346446 100644 --- a/.github/workflows/js_tests.yml +++ b/.github/workflows/js_tests.yml @@ -45,6 +45,8 @@ jobs: run: npm ci --no-audit - name: Run linter run: npm run lint + - name: Run stylelint + run: npm run stylelint - name: Run tests run: npm run test - name: Publish Coveralls diff --git a/.stylelintrc b/.stylelintrc deleted file mode 100644 index 5a9653f2ec..0000000000 --- a/.stylelintrc +++ /dev/null @@ -1,10 +0,0 @@ -{ - "extends": [ - "stylelint-config-standard", - ], - "rules": { - "at-rule-no-unknown": null, - "selector-type-no-unknown": null, - }, - "ignore": ["custom-elements"], -} diff --git a/.stylelintrc.json b/.stylelintrc.json new file mode 100644 index 0000000000..fca9c51ace --- /dev/null +++ b/.stylelintrc.json @@ -0,0 +1,39 @@ +{ + "extends": "stylelint-config-standard-scss", + "ignoreFiles": [ + "app/assets/stylesheets/unimported/**" + ], + "plugins": [ + "./script/lint/stylelint-no-root-pf-overrides.js", + "./script/lint/stylelint-no-bare-element-selectors.js" + ], + "rules": { + "no-descending-specificity": null, + "foreman/no-root-pf-overrides": true, + "foreman/no-bare-element-selectors": true, + "selector-class-pattern": null, + "selector-id-pattern": null, + "custom-property-pattern": null, + "scss/dollar-variable-pattern": null, + "at-rule-empty-line-before": null, + "custom-property-empty-line-before": null, + "scss/dollar-variable-empty-line-before": null, + "scss/double-slash-comment-empty-line-before": null, + "scss/double-slash-comment-whitespace-inside": null, + "scss/dollar-variable-colon-space-after": null, + "scss/load-partial-extension": null, + "scss/load-no-partial-leading-underscore": null, + "scss/no-global-function-names": null, + "media-feature-range-notation": null, + "alpha-value-notation": null, + "color-function-notation": null, + "color-function-alias-notation": null, + "font-family-name-quotes": null, + "property-no-vendor-prefix": null, + "shorthand-property-no-redundant-values": null, + "declaration-block-no-redundant-longhand-properties": null, + "declaration-property-value-keyword-no-deprecated": null, + "length-zero-no-unit": null, + "no-invalid-position-at-import-rule": null + } +} diff --git a/app/assets/stylesheets/base-pf4.scss b/app/assets/stylesheets/base-pf4.scss index d25d7557d1..ddb38999a4 100644 --- a/app/assets/stylesheets/base-pf4.scss +++ b/app/assets/stylesheets/base-pf4.scss @@ -1,3 +1,6 @@ +// stylelint-disable foreman/no-bare-element-selectors +// stylelint-disable foreman/no-root-pf-overrides + /* This file exists to make pf3 compatible with pf4. When migrating from pf3 to pf4, some styles might be removable. @@ -56,6 +59,7 @@ a { .pf-v5-c-alert { line-height: var(--pf-v5-global--LineHeight--md); + h4 { margin: 0; line-height: var(--pf-v5-global--LineHeight--md); diff --git a/app/assets/stylesheets/base.scss b/app/assets/stylesheets/base.scss index 70bc5cc13e..6b28196658 100644 --- a/app/assets/stylesheets/base.scss +++ b/app/assets/stylesheets/base.scss @@ -1,3 +1,6 @@ +// stylelint-disable foreman/no-bare-element-selectors +// stylelint-disable foreman/no-root-pf-overrides + html { height: 100%; width: 100%; @@ -17,12 +20,14 @@ html { var(--header-height) + var(--banner-height) ); height: calc(100% - var(--header-height) - var(--banner-height)); + .rails-table-toolbar { padding-bottom: 0; display: flex; flex-wrap: wrap; justify-content: space-between; } + &.pf-v5-c-page { display: block; grid-template-columns: unset; @@ -40,6 +45,7 @@ body { #react-app-root { height: 100%; width: 100%; + .pf-v5-c-page { // pf grid rule stops at @media (min-width: 1200px) display: grid; @@ -597,11 +603,10 @@ table { overflow-wrap: normal; padding: 4px; white-space: pre; - word-wrap: normal; } .masked-input { - font-family: 'AllBullets'; + font-family: 'AllBullets', sans-serif; } .btn-spinner { @@ -672,6 +677,7 @@ span.btn a.disabled { td.pf-v5-c-table__td { padding-top: 2px; padding-bottom: 2px; + > button { padding:0; } @@ -679,8 +685,8 @@ span.btn a.disabled { } .user-banner-present { + // banner height is line height and a small padding --banner-height: calc( - 2 * var(--pf-v5-global--spacer--xs) + - (var(--pf-v5-global--LineHeight--md) * var(--pf-v5-global--FontSize--sm)) - ); // banner height is line height and a small padding + 2 * var(--pf-v5-global--spacer--xs) + (var(--pf-v5-global--LineHeight--md) * var(--pf-v5-global--FontSize--sm)) + ); } diff --git a/app/assets/stylesheets/navigation.scss b/app/assets/stylesheets/navigation.scss index 1369ff3df3..3912fe7cad 100644 --- a/app/assets/stylesheets/navigation.scss +++ b/app/assets/stylesheets/navigation.scss @@ -4,6 +4,7 @@ .nav a { font-size: 13px; } + .active > a, .open > a { background: linear-gradient( @@ -18,8 +19,9 @@ } } -.pf-v5-c-masthead { +#foreman-page .pf-v5-c-masthead { background: var(--pf-v5-c-masthead--BackgroundColor) image-url('navbar.png'); + .user-icon { margin-right: 10px; } diff --git a/app/assets/stylesheets/patternfly_and_overrides.scss b/app/assets/stylesheets/patternfly_and_overrides.scss index 6d8f3532ec..bd01a1b966 100644 --- a/app/assets/stylesheets/patternfly_and_overrides.scss +++ b/app/assets/stylesheets/patternfly_and_overrides.scss @@ -1,3 +1,6 @@ +// stylelint-disable foreman/no-bare-element-selectors +// stylelint-disable foreman/no-root-pf-overrides + .control-label { text-align: left; padding-left: 0; @@ -149,15 +152,6 @@ a { z-index: 2000; } -@-moz-document url-prefix() { - /* Workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=688556 */ - *, - *::before, - *::after { - background-clip: padding-box; - } -} - .smart-var-left { max-height: 500px; direction: rtl; @@ -194,7 +188,7 @@ a { } .tooltip { - word-wrap: break-word; + overflow-wrap: break-word; } .has-error { @@ -350,7 +344,7 @@ span.btn-action.btn-primary a { ul, ol { margin-top: 0px; margin-bottom: 10px; - }*/ + } */ margin-bottom: 0; } diff --git a/app/assets/stylesheets/patternfly_colors_overrides.scss b/app/assets/stylesheets/patternfly_colors_overrides.scss index fff7d3c79b..514ae13d5f 100644 --- a/app/assets/stylesheets/patternfly_colors_overrides.scss +++ b/app/assets/stylesheets/patternfly_colors_overrides.scss @@ -4,16 +4,21 @@ .pf-v5-c-page__sidebar { --pf-v5-c-page__sidebar--Width: 250px; --pf-v5-c-page__sidebar--BackgroundColor: #{$nav-pf-vertical-bg-color}; + #navigation-search .pf-v5-c-text-input-group { background-color: var(--pf-v5-global--palette--white); + .pf-v5-c-text-input-group__icon{ color: var(--pf-v5-global--palette--black-500); } + .pf-v5-c-text-input-group__text-input { color: var(--pf-v5-global--palette--black-1000); + &::placeholder { color: var(--pf-v5-global--palette--black-500); } + ::placeholder { color: var(--pf-v5-global--palette--black-500); } @@ -35,10 +40,12 @@ .pf-v5-c-nav__subnav { --pf-v5-c-nav--c-divider--BackgroundColor: #{$nav-pf-vertical-active-bg-color}; } + .pf-v5-c-nav__item { --pf-v5-c-nav__item--before--BorderColor: #{$nav-pf-vertical-active-bg-color}; } + .pf-v5-c-notification-badge { - --pf-v5-c-notification-badge--m-read--m-expanded--after--BackgroundColor: var(--pf-v5-global--palette--blue-500) + --pf-v5-c-notification-badge--m-read--m-expanded--after--BackgroundColor: var(--pf-v5-global--palette--blue-500); } } diff --git a/developer_docs/pf3-to-pf5-migration-guide.asciidoc b/developer_docs/pf3-to-pf5-migration-guide.asciidoc index 4748f430ba..57595721b2 100644 --- a/developer_docs/pf3-to-pf5-migration-guide.asciidoc +++ b/developer_docs/pf3-to-pf5-migration-guide.asciidoc @@ -53,7 +53,7 @@ PF5 brings its own layout and tokens; old PF3-scoped or component CSS often beco * *Audit styles* tied to the old component (same directory, imported SCSS/CSS, or global rules keyed on old class names). Open the screen in the app and confirm whether each rule still affects the PF5 markup. * *Delete* rules that no longer match any DOM, duplicate what PF5 already provides, or only existed to patch PF3 quirks that are gone. -* *Update* rules that still apply (e.g. plugin-specific layout, integration with non-PF surfaces, or genuinely custom visuals). Prefer *specific selectors* so you do not bleed into core or other plugins. +* *Update* rules that still apply (e.g. plugin-specific layout, integration with non-PF surfaces, or genuinely custom visuals). Prefer *specific selectors* so you do not bleed into core or other plugins. Run `npm run stylelint` to lint your CSS/SCSS. * Only delete CSS if it is component specific and declared in a global file. ## 9. Prefer local React state over Redux when it fits diff --git a/developer_docs/plugins.asciidoc b/developer_docs/plugins.asciidoc index 3ed8e1f298..deb8f56ace 100644 --- a/developer_docs/plugins.asciidoc +++ b/developer_docs/plugins.asciidoc @@ -65,6 +65,7 @@ The Webpack config is shared with core, so there's no need for custom configurat Once all the above is set up, then the script `npm run install` executed from root of the core's git checkout installs dependencies for plugins too. You can run your plugin test by running `npm run test:plugins PLUGIN_NAME` from core. You can run lint on your plugin by running `npm run lint:plugins PLUGIN_NAME` from core. +You can run Stylelint (CSS/SCSS) on your plugin by running `npm run stylelint:plugins PLUGIN_NAME` from core. ### Entry points diff --git a/developer_docs/ui-testing-guidelines.asciidoc b/developer_docs/ui-testing-guidelines.asciidoc index f8555c3505..039ad7d7da 100644 --- a/developer_docs/ui-testing-guidelines.asciidoc +++ b/developer_docs/ui-testing-guidelines.asciidoc @@ -27,6 +27,17 @@ npm run lint:plugins ``` plugin name is optional, if not provided, all plugins will be linted. +=== Running Stylelint (CSS/SCSS) +To lint CSS/SCSS files: +```bash +npm run stylelint +``` +To run Stylelint for plugins: +```bash +npm run stylelint:plugins +``` +plugin name is optional, if not provided, all plugins will be checked. + == Writing tests Suggestions for simple and complex components, but developers should use their best judgement. diff --git a/package-exclude.json b/package-exclude.json index 2f7a1a1c8e..0a9c3bd744 100644 --- a/package-exclude.json +++ b/package-exclude.json @@ -16,6 +16,7 @@ "babel-plugin-dynamic-import-node", "coveralls", "cheerio", + "html-tags", "cross-env", "identity-obj-proxy", "jsx-ast-utils", diff --git a/package.json b/package.json index 6300ec0195..8573037acb 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,8 @@ "test:current": "tfm-test --watch", "test:plugins": "./script/npm_test_plugin.js", "lint:plugins": "./script/npm_lint_plugins.js", + "stylelint": "stylelint 'webpack/**/*.{scss,css}' 'app/**/*.{scss,css}'", + "stylelint:plugins": "./script/npm_stylelint_plugins.js", "publish-coverage": "tfm-publish-coverage", "postinstall": "./script/npm_install_plugins.js", "analyze": "./script/webpack-analyze" @@ -150,8 +152,9 @@ "sass": "~1.60.0", "sass-loader": "^13.3.2", "style-loader": "^1.3.0", - "stylelint": "^9.3.0", - "stylelint-config-standard": "^18.0.0", + "html-tags": "^5.1.0", + "stylelint": "^17.9.1", + "stylelint-config-standard-scss": "^17.0.0", "tabbable": "^6.2.0", "ts-loader": "^9.5.2", "typescript": "^5.8.2", diff --git a/script/lint/lint_core_config.js b/script/lint/lint_core_config.js index 84653e25b3..02045de1f9 100644 --- a/script/lint/lint_core_config.js +++ b/script/lint/lint_core_config.js @@ -161,6 +161,7 @@ module.exports = { 'sparc', 'storages', 'stringified', + 'stylelint', 'subcomponent', 'subcomponents', 'subnav', diff --git a/script/lint/stylelint-no-bare-element-selectors.js b/script/lint/stylelint-no-bare-element-selectors.js new file mode 100644 index 0000000000..755384ecd7 --- /dev/null +++ b/script/lint/stylelint-no-bare-element-selectors.js @@ -0,0 +1,47 @@ +const stylelint = require('stylelint'); +const htmlTags = require('html-tags'); + +const ruleName = 'foreman/no-bare-element-selectors'; +const messages = stylelint.utils.ruleMessages(ruleName, { + rejected: selector => + `Unexpected bare element selector "${selector}". Scope it under a custom class or ID instead.`, +}); + +const HTML_ELEMENTS = new Set(htmlTags.default || htmlTags); + +function isBareElementSelector(selector) { + const trimmed = selector.trim(); + const parts = trimmed.split(/\s*[>~+\s]\s*/); + + return parts.every(part => { + const tag = part.match(/^([a-zA-Z][a-zA-Z0-9]*)/); + if (!tag) return false; + const afterTag = part.slice(tag[1].length); + if (afterTag && !afterTag.startsWith('[')) return false; + return HTML_ELEMENTS.has(tag[1]); + }); +} + +const ruleFunction = enabled => (root, result) => { + if (!enabled) return; + + root.walkRules(ruleNode => { + if (ruleNode.parent.type !== 'root') return; + + ruleNode.selectors.forEach(selector => { + if (isBareElementSelector(selector)) { + stylelint.utils.report({ + message: messages.rejected(selector), + node: ruleNode, + result, + ruleName, + }); + } + }); + }); +}; + +ruleFunction.ruleName = ruleName; +ruleFunction.messages = messages; + +module.exports = stylelint.createPlugin(ruleName, ruleFunction); diff --git a/script/lint/stylelint-no-root-pf-overrides.js b/script/lint/stylelint-no-root-pf-overrides.js new file mode 100644 index 0000000000..96d82f4d5e --- /dev/null +++ b/script/lint/stylelint-no-root-pf-overrides.js @@ -0,0 +1,54 @@ +const stylelint = require('stylelint'); + +const ruleName = 'foreman/no-root-pf-overrides'; +const messages = stylelint.utils.ruleMessages(ruleName, { + rejected: selector => + `Unexpected top-level PatternFly selector "${selector}". Nest it under a component class or ID instead. If already scoped, reorder the selectors to place the scoped selector first.`, +}); + +const PF_PATTERN = /\.pf-/; +const htmlTags = require('html-tags'); + +const HTML_ELEMENTS = new Set(htmlTags.default || htmlTags); + +function startsUnscoped(selector) { + const trimmed = selector.trim(); + if (trimmed.startsWith('.pf-')) return true; + + const leadingIdent = trimmed.match(/^([a-zA-Z][a-zA-Z0-9]*)/); + if (!leadingIdent) return false; + const tag = leadingIdent[1]; + if (!HTML_ELEMENTS.has(tag)) return false; + + const afterTag = trimmed.slice(tag.length); + if (!afterTag || /^[\s>#~+,{]/.test(afterTag) || afterTag.startsWith('[')) { + return true; + } + if (afterTag.startsWith('.pf-')) return true; + + return false; +} + +const ruleFunction = enabled => (root, result) => { + if (!enabled) return; + + root.walkRules(ruleNode => { + if (ruleNode.parent.type !== 'root') return; + + ruleNode.selectors.forEach(selector => { + if (PF_PATTERN.test(selector) && startsUnscoped(selector)) { + stylelint.utils.report({ + message: messages.rejected(selector), + node: ruleNode, + result, + ruleName, + }); + } + }); + }); +}; + +ruleFunction.ruleName = ruleName; +ruleFunction.messages = messages; + +module.exports = stylelint.createPlugin(ruleName, ruleFunction); diff --git a/script/npm_stylelint_plugins.js b/script/npm_stylelint_plugins.js new file mode 100755 index 0000000000..e41a42d6ac --- /dev/null +++ b/script/npm_stylelint_plugins.js @@ -0,0 +1,56 @@ +#!/usr/bin/env node +/* eslint-disable no-var */ +/* eslint-disable no-console */ + +var path = require('path'); +var { spawnSync } = require('child_process'); +var { filterPluginDirectories } = require('./plugin_webpack_directories'); + +var { allPluginDirs, skippedDirsKeys, dirsKeys } = filterPluginDirectories(); +var passedArgs = process.argv.slice(2); +var foremanRoot = path.join(__dirname, '..'); +// eslint-disable-next-line spellcheck/spell-checker +var configPath = path.join(foremanRoot, '.stylelintrc.json'); +var errors = []; +var pluginPath; +var styleGlob; +var exitCode; + +if (passedArgs[0] && passedArgs[0][0] !== '-') { + dirsKeys = dirsKeys.filter(dir => dir.endsWith(passedArgs[0])); + passedArgs.shift(); +} + +dirsKeys.forEach(dirsKey => { + pluginPath = allPluginDirs[dirsKey]; + styleGlob = path.join(pluginPath, 'webpack/**/*.{scss,css}'); + + // eslint-disable-next-line spellcheck/spell-checker + console.log(`\nRunning stylelint on ${path.basename(pluginPath)}...`); + + exitCode = spawnSync( + 'npx', + ['stylelint', styleGlob, '--config', configPath, ...passedArgs], // eslint-disable-line spellcheck/spell-checker + { + cwd: foremanRoot, + stdio: 'inherit', + } + ).status; + + if (exitCode !== 0) { + errors.push(`stylelint:plugins ${path.basename(pluginPath)} failed`); // eslint-disable-line spellcheck/spell-checker + } +}); + +console.log( + '\nThe following plugin dirs were gems, and therefore skipped: ', + skippedDirsKeys +); + +if (errors.length) { + throw new Error( + ['Errors while running were printed in the output above', ...errors].join( + '\n' + ) + ); +} diff --git a/webpack/assets/javascripts/react_app/common/scss/mixins.scss b/webpack/assets/javascripts/react_app/common/scss/mixins.scss index f106521f85..aca739990c 100644 --- a/webpack/assets/javascripts/react_app/common/scss/mixins.scss +++ b/webpack/assets/javascripts/react_app/common/scss/mixins.scss @@ -1,19 +1,21 @@ // Mixins - Bootstrap overrides // ------------------- @mixin box-shadow($shadow...) { - -webkit-box-shadow: $shadow; // iOS <4.3 & Android <4.1 box-shadow: $shadow; } // Form control outline @mixin form-control-outline($color: $input-border-focus){ $color-rgba: rgba(red($color), green($color), blue($color), .6); + &:focus { border-color: $color; outline: 0 !important; + @include box-shadow(unquote("inset 0 1px 1px rgba(3, 3, 3, 0.075), 0 0 8px #{$color-rgba}")); } } + /** Third Party mixins imports here */ diff --git a/webpack/assets/javascripts/react_app/common/variables.scss b/webpack/assets/javascripts/react_app/common/variables.scss index beadb365f0..b23f15824f 100644 --- a/webpack/assets/javascripts/react_app/common/variables.scss +++ b/webpack/assets/javascripts/react_app/common/variables.scss @@ -5,11 +5,13 @@ $font-path: '~patternfly/dist/fonts/'; $img-path: '~patternfly/dist/img/'; $icon-font-path: '~patternfly/dist/fonts/'; + @import '~bootstrap-sass/assets/stylesheets/bootstrap/variables'; @import '~patternfly/dist/sass/patternfly/variables'; // patternfly v5 @import '~@patternfly/patternfly/base/patternfly-variables'; + $pf-v5-global--font-path: '~@patternfly/patternfly/assets/fonts'; $fa-font-path: '~@patternfly/patternfly/assets/fonts/webfonts'; $pf-v5-global--fonticon-path: '~@patternfly/patternfly/assets/pficon'; diff --git a/webpack/assets/javascripts/react_app/components/BackendSystemStatus/index.scss b/webpack/assets/javascripts/react_app/components/BackendSystemStatus/index.scss index 5ea837afc1..8d780a47fc 100644 --- a/webpack/assets/javascripts/react_app/components/BackendSystemStatus/index.scss +++ b/webpack/assets/javascripts/react_app/components/BackendSystemStatus/index.scss @@ -7,6 +7,7 @@ span.bss-service-info dl { content: '•'; margin: 0 0.4em; font-weight: normal; + /* This helps ensure the bullet is perfectly centered with the text */ vertical-align: middle; } diff --git a/webpack/assets/javascripts/react_app/components/ChartBox/ChartBox.css b/webpack/assets/javascripts/react_app/components/ChartBox/ChartBox.css index eee3273dbb..cd11f52cea 100644 --- a/webpack/assets/javascripts/react_app/components/ChartBox/ChartBox.css +++ b/webpack/assets/javascripts/react_app/components/ChartBox/ChartBox.css @@ -3,6 +3,7 @@ cursor: pointer; } } + .chart-box-modal .pf-v5-c-modal-box__body { text-align: center; } diff --git a/webpack/assets/javascripts/react_app/components/ColumnSelector/ColumnSelector.js b/webpack/assets/javascripts/react_app/components/ColumnSelector/ColumnSelector.js index 82bea2aa61..d39588cdb9 100644 --- a/webpack/assets/javascripts/react_app/components/ColumnSelector/ColumnSelector.js +++ b/webpack/assets/javascripts/react_app/components/ColumnSelector/ColumnSelector.js @@ -2,6 +2,8 @@ import React, { useState } from 'react'; import { PropTypes } from 'prop-types'; import { Button, + InputGroup, + InputGroupItem, Modal, ModalVariant, TreeView, @@ -149,8 +151,8 @@ const ColumnSelector = props => { }; return ( -
-
+ +
-
+ + ); }; diff --git a/webpack/assets/javascripts/react_app/components/ColumnSelector/column-selector.scss b/webpack/assets/javascripts/react_app/components/ColumnSelector/column-selector.scss index c633b29dbf..c1a570a329 100644 --- a/webpack/assets/javascripts/react_app/components/ColumnSelector/column-selector.scss +++ b/webpack/assets/javascripts/react_app/components/ColumnSelector/column-selector.scss @@ -1,17 +1,9 @@ -.pf-v5-c-input-group { +#column-selector { .columns-selector { - padding-left: 0px; - - .pf-v5-c-button__icon.pf-m-start { - padding-right: 4px; - } + padding-left: 0; } } -.pf-v5-c-tree-view { - padding-top: 0px -} - #btn-select-columns { @media (max-width: 1530px) { .columns-selector-text { @@ -20,6 +12,6 @@ } } -div [data-ouia-component-id="manage-columns-modal"].pf-v5-c-modal-box { - max-height: calc(100% - 128px); +[data-ouia-component-id="manage-columns-modal"] { + max-height: calc(100% - 128px); } diff --git a/webpack/assets/javascripts/react_app/components/HostDetails/HostDetails.scss b/webpack/assets/javascripts/react_app/components/HostDetails/HostDetails.scss index 136c58fbee..a32e0b407a 100644 --- a/webpack/assets/javascripts/react_app/components/HostDetails/HostDetails.scss +++ b/webpack/assets/javascripts/react_app/components/HostDetails/HostDetails.scss @@ -1,9 +1,6 @@ -.pf-gray-background { - background: var(--pf-v5-global--BackgroundColor--200); -} - -.pf-v5-c-page__main-section.pf-m-light.host-details-tabs-section { +.host-details-tabs-section { padding-left: 24px; + .tab-width-138 { max-width: calc( 100vw - 138px @@ -13,6 +10,7 @@ max-width: calc(100vw - 64px); } } + .tab-width-263 { max-width: calc( 100vw - 263px @@ -48,6 +46,7 @@ height: 100%; } } + .inline-edit-input-flex-item { display: contents; } diff --git a/webpack/assets/javascripts/react_app/components/HostDetails/Status/styles.scss b/webpack/assets/javascripts/react_app/components/HostDetails/Status/styles.scss index 4133cfa0cc..0867898cf1 100644 --- a/webpack/assets/javascripts/react_app/components/HostDetails/Status/styles.scss +++ b/webpack/assets/javascripts/react_app/components/HostDetails/Status/styles.scss @@ -1,15 +1,19 @@ .card-pf-aggregate-status-notifications a.aggregate-text { font-size: 16px; + &:hover { text-decoration: none; + span:last-child { text-decoration: underline; } } } + .host-status-icon-container { .disabled { color: var(--pf-v5-global--disabled-color--200); + .pf-v5-c-icon { margin-right: 4px; } @@ -17,6 +21,7 @@ .status-success { color: var(--pf-v5-global--success-color--100); + .pf-v5-c-icon { margin-right: 4px; } @@ -24,6 +29,7 @@ .status-error { color: var(--pf-v5-global--danger-color--100); + .pf-v5-c-icon { margin-right: 4px; } @@ -31,6 +37,7 @@ .status-warning { color: var(--pf-v5-global--warning-color--100); + .pf-v5-c-icon { margin-right: 4px; } diff --git a/webpack/assets/javascripts/react_app/components/HostDetails/Tabs/Details/Cards/NetworkingInterfaces/NetworkingInterfaces.scss b/webpack/assets/javascripts/react_app/components/HostDetails/Tabs/Details/Cards/NetworkingInterfaces/NetworkingInterfaces.scss index f8e33355e2..5b6cd6d494 100644 --- a/webpack/assets/javascripts/react_app/components/HostDetails/Tabs/Details/Cards/NetworkingInterfaces/NetworkingInterfaces.scss +++ b/webpack/assets/javascripts/react_app/components/HostDetails/Tabs/Details/Cards/NetworkingInterfaces/NetworkingInterfaces.scss @@ -2,20 +2,25 @@ .interface-name svg { margin-left: 5px; } + .primary-icon { margin-left: 5px; } + .provision-icon { margin-left: 5px; } + .pf-v5-l-grid__item { text-align: left; white-space: pre-wrap; } + .pf-v5-c-accordion__toggle-text { width: 100%; } } + .nic-empty-state{ padding-left: 16px; } diff --git a/webpack/assets/javascripts/react_app/components/HostDetails/Tabs/Details/DetailsCard.scss b/webpack/assets/javascripts/react_app/components/HostDetails/Tabs/Details/DetailsCard.scss index 46d435681c..0af8d1c381 100644 --- a/webpack/assets/javascripts/react_app/components/HostDetails/Tabs/Details/DetailsCard.scss +++ b/webpack/assets/javascripts/react_app/components/HostDetails/Tabs/Details/DetailsCard.scss @@ -1,6 +1,7 @@ .masonry-root { columns: 24rem; column-gap: 1rem; + .masonry-item { margin-bottom: 2rem; display: inline-block; diff --git a/webpack/assets/javascripts/react_app/components/HostDetails/Tabs/Parameters/Parameters.scss b/webpack/assets/javascripts/react_app/components/HostDetails/Tabs/Parameters/Parameters.scss index 5331842737..097aa81258 100644 --- a/webpack/assets/javascripts/react_app/components/HostDetails/Tabs/Parameters/Parameters.scss +++ b/webpack/assets/javascripts/react_app/components/HostDetails/Tabs/Parameters/Parameters.scss @@ -2,6 +2,7 @@ td { vertical-align: top; } + .parameters-row-actions { display: flex; } diff --git a/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/bulkDeleteModal.scss b/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/bulkDeleteModal.scss index 9d62669e43..2e939fea2f 100644 --- a/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/bulkDeleteModal.scss +++ b/webpack/assets/javascripts/react_app/components/HostsIndex/BulkActions/bulkDeleteModal.scss @@ -1,5 +1,6 @@ #bulk-delete-hosts-modal { min-height: 21rem; + .pf-v5-c-check label { font-size: 14px; position: relative; diff --git a/webpack/assets/javascripts/react_app/components/HostsIndex/index.scss b/webpack/assets/javascripts/react_app/components/HostsIndex/index.scss index 2cdda150b0..131ea34a7f 100644 --- a/webpack/assets/javascripts/react_app/components/HostsIndex/index.scss +++ b/webpack/assets/javascripts/react_app/components/HostsIndex/index.scss @@ -1,7 +1,9 @@ #legacy-ui-kebab ul.pf-v5-c-dropdown__menu { padding-left: 0; + li { display: unset; + a { font-size: 16px; color: var(--pf-v5-c-dropdown__menu-item--Color); diff --git a/webpack/assets/javascripts/react_app/components/Layout/components/ImpersonateIcon/ImpersonateIcon.scss b/webpack/assets/javascripts/react_app/components/Layout/components/ImpersonateIcon/ImpersonateIcon.scss index 82426447a8..d9d7661601 100644 --- a/webpack/assets/javascripts/react_app/components/Layout/components/ImpersonateIcon/ImpersonateIcon.scss +++ b/webpack/assets/javascripts/react_app/components/Layout/components/ImpersonateIcon/ImpersonateIcon.scss @@ -22,7 +22,7 @@ animation: blink normal 1s infinite ease-in-out; /* Opera and prob css3 final iteration */ } -.pf-v5-c-masthead { +#foreman-page .pf-v5-c-masthead { .nav-item-iconic .blink-image { color: $color-pf-gold-200; } diff --git a/webpack/assets/javascripts/react_app/components/Layout/components/TaxonomySwitcher/TaxonomyDropdown.scss b/webpack/assets/javascripts/react_app/components/Layout/components/TaxonomySwitcher/TaxonomyDropdown.scss index 424cdcf479..7cae26767c 100644 --- a/webpack/assets/javascripts/react_app/components/Layout/components/TaxonomySwitcher/TaxonomyDropdown.scss +++ b/webpack/assets/javascripts/react_app/components/Layout/components/TaxonomySwitcher/TaxonomyDropdown.scss @@ -1,19 +1,22 @@ @import '../../../../common/variables'; -.pf-v5-c-masthead .pf-v5-c-toolbar { +#foreman-page .pf-v5-c-masthead .pf-v5-c-toolbar { .pf-v5-c-context-selector__menu-search { border-bottom: 0; } + .current-taxonomy-v { margin-right: 2px; } + .organizations_clear, .locations_clear { border-bottom: var(--pf-v5-c-context-selector__menu-search--BorderBottomWidth) solid var(--pf-v5-c-context-selector__menu-search--BorderBottomColor); } + .pf-v5-c-context-selector__menu-footer > a{ - // to override secondry button text color being white if the button is in a menu + // to override secondary button text color being white if the button is in a menu color: $pf-v5-color-blue-400 } } diff --git a/webpack/assets/javascripts/react_app/components/Layout/components/Toolbar/HeaderToolbar.scss b/webpack/assets/javascripts/react_app/components/Layout/components/Toolbar/HeaderToolbar.scss index 886664b3fb..c35e5c7285 100644 --- a/webpack/assets/javascripts/react_app/components/Layout/components/Toolbar/HeaderToolbar.scss +++ b/webpack/assets/javascripts/react_app/components/Layout/components/Toolbar/HeaderToolbar.scss @@ -2,6 +2,7 @@ #data-toolbar { background-color: unset; + @media (max-width: $header-max-width) { justify-content: flex-end; @@ -11,13 +12,13 @@ } } -.pf-v5-c-toolbar#data-toolbar { +#data-toolbar.pf-v5-c-toolbar { // Override for unupdated plugins that use unupdated foreman CSS display: grid; justify-content: normal; } -.pf-v5-c-masthead__brand { +#foreman-page .pf-v5-c-masthead__brand { padding-right: 15px; &:hover { diff --git a/webpack/assets/javascripts/react_app/components/Layout/layout.scss b/webpack/assets/javascripts/react_app/components/Layout/layout.scss index d5ac5c7aa5..13bbe824dd 100644 --- a/webpack/assets/javascripts/react_app/components/Layout/layout.scss +++ b/webpack/assets/javascripts/react_app/components/Layout/layout.scss @@ -6,6 +6,7 @@ white-space: normal; height: 100%; } + #foreman-main-container { height: fit-content; } @@ -16,6 +17,7 @@ padding-left: 0; } } + #rails-app-content { margin-left: 0; } @@ -31,25 +33,30 @@ } } -.pf-v5-c-nav { +#foreman-nav { .nav-title-icon { word-break: break-word; overflow-wrap: break-word; white-space: normal; } + .nav-icon { pointer-events: none; padding-right: 10px; } + .nav-title { pointer-events: none; } + .pf-v5-c-nav__item .pf-v5-c-nav__item.pf-m-expandable .pf-v5-c-nav__list::before { border: 0; } + .pf-v5-c-nav__item.pf-m-expandable::before { z-index: var(--pf-v5-c-page__sidebar--ZIndex); } + .pf-v5-c-nav__item .pf-v5-c-nav__item.pf-m-expandable::before { // in small screens, the expandable items have css to add a second border border-bottom: none; @@ -62,15 +69,15 @@ .navigation-search-menu { .pf-v5-c-menu__item { padding: 5px; + .pf-v5-c-menu__item-description { word-break: break-word; } } + min-width: 0; margin: 0; - --pf-v5-c-menu__list-item--hover--BackgroundColor: var( - --pf-v5-global--BackgroundColor--200 - ); + --pf-v5-c-menu--BackgroundColor: var(--pf-v5-global--BackgroundColor--100); --pf-v5-c-menu__list-item--Color: var(--pf-v5-global--Color--100); --pf-v5-c-menu__list-item--BackgroundColor: transparent; @@ -85,20 +92,22 @@ --pf-v5-c-menu__item-description--Color: var(--pf-v5-global--Color--200); --pf-v5-c-menu__list-item--hover--Color: unset; } + #navigation-search { width:calc(#{var(--pf-v5-c-page__sidebar--Width)} - 10px); margin-left: 5px; + .pf-v5-c-button.pf-m-control { display: none; } } } -.pf-v5-c-page { +#foreman-page { --pf-v5-c-page--BackgroundColor: var(--pf-v5-global--BackgroundColor--100); } -.pf-v5-c-page .pf-v5-c-masthead { +#foreman-page .pf-v5-c-masthead { background-repeat: no-repeat; background-size: cover; diff --git a/webpack/assets/javascripts/react_app/components/LoginPage/LoginPage.scss b/webpack/assets/javascripts/react_app/components/LoginPage/LoginPage.scss index a43ff8b467..70262b94b3 100644 --- a/webpack/assets/javascripts/react_app/components/LoginPage/LoginPage.scss +++ b/webpack/assets/javascripts/react_app/components/LoginPage/LoginPage.scss @@ -13,6 +13,6 @@ $background_image: url('../LoginPage/background.svg'); } } -.pf-v5-c-login__footer p { +#login-page .pf-v5-c-login__footer p { overflow-wrap: break-word; } diff --git a/webpack/assets/javascripts/react_app/components/PF4/BreadcrumbSwitcher/breadcrumb-switcher.scss b/webpack/assets/javascripts/react_app/components/PF4/BreadcrumbSwitcher/breadcrumb-switcher.scss index a7f5cb862f..a56660336b 100644 --- a/webpack/assets/javascripts/react_app/components/PF4/BreadcrumbSwitcher/breadcrumb-switcher.scss +++ b/webpack/assets/javascripts/react_app/components/PF4/BreadcrumbSwitcher/breadcrumb-switcher.scss @@ -6,6 +6,7 @@ .pf-v5-c-menu__list-item{ visibility: unset; } + .pf-v5-c-menu__footer { padding: 0; @@ -14,6 +15,7 @@ justify-content: center; } } + .breadcrumb-switcher-spinner { margin: auto; width: fit-content; diff --git a/webpack/assets/javascripts/react_app/components/PF4/TableIndexPage/TableIndexPage.scss b/webpack/assets/javascripts/react_app/components/PF4/TableIndexPage/TableIndexPage.scss index cfc0317984..ab0d406fdc 100644 --- a/webpack/assets/javascripts/react_app/components/PF4/TableIndexPage/TableIndexPage.scss +++ b/webpack/assets/javascripts/react_app/components/PF4/TableIndexPage/TableIndexPage.scss @@ -2,44 +2,56 @@ .table-title-section { padding-bottom: 0; } + .table-toolbar-section { padding-top: 16px; padding-bottom: 16px; + .table-toolbar { padding: 0; + .pf-v5-c-toolbar__content { padding: 0; } + .toolbar-search { flex-grow: 1; display: block; } + .table-toolbar-actions { padding-left: 16px; } } + .pf-v5-c-toolbar__group { flex-grow: 1; + &.pf-m-align-right { justify-content: flex-end; } } } + .table-section { padding-top: 0; padding-left: 0; padding-right: 0; } + .pf-v5-c-toolbar__group { flex-grow: 1; + &.pf-m-align-right { justify-content: flex-end; } + &:first-child { margin-right: auto; width: min-content; } } + .pf-v5-c-table tr.pf-m-clickable { cursor: default; } diff --git a/webpack/assets/javascripts/react_app/components/Pagination/index.scss b/webpack/assets/javascripts/react_app/components/Pagination/index.scss index 826e86b78f..3df25c9367 100644 --- a/webpack/assets/javascripts/react_app/components/Pagination/index.scss +++ b/webpack/assets/javascripts/react_app/components/Pagination/index.scss @@ -1,4 +1,4 @@ -.pf-v5-c-pagination.pf-m-bottom.tfm-pagination { +.tfm-pagination.pf-v5-c-pagination.pf-m-bottom { &.no-side-padding { padding: 16px 0; } diff --git a/webpack/assets/javascripts/react_app/components/SearchBar/SearchBar.scss b/webpack/assets/javascripts/react_app/components/SearchBar/SearchBar.scss index b3738d903a..a27759ae33 100644 --- a/webpack/assets/javascripts/react_app/components/SearchBar/SearchBar.scss +++ b/webpack/assets/javascripts/react_app/components/SearchBar/SearchBar.scss @@ -2,6 +2,7 @@ .autocomplete-search { width: 100%; + &.disabled-autocomplete-search .pf-v5-c-input-group{ color: var(--pf-v5-global--disabled-color--100); background-color: var(--pf-v5-global--disabled-color--300); @@ -13,9 +14,11 @@ .foreman-search-bar { width: 100%; display: flex; + .pf-v5-c-dropdown.pf-m-align-right { width: unset; } + .pf-v5-c-dropdown { width: unset; // just in case Katello overrides it } diff --git a/webpack/assets/javascripts/react_app/components/SettingsTable/SettingsTable.scss b/webpack/assets/javascripts/react_app/components/SettingsTable/SettingsTable.scss index 21d06fdb46..0d560d9293 100644 --- a/webpack/assets/javascripts/react_app/components/SettingsTable/SettingsTable.scss +++ b/webpack/assets/javascripts/react_app/components/SettingsTable/SettingsTable.scss @@ -4,6 +4,7 @@ .pf-v5-c-table__tr .pf-v5-c-table__td .setting-value{ overflow-wrap: anywhere; } + .empty-value{ color: var(--pf-v5-global--Color--200); } diff --git a/webpack/assets/javascripts/react_app/components/ToastsList/index.js b/webpack/assets/javascripts/react_app/components/ToastsList/index.js index 42f781e645..def230c8cb 100644 --- a/webpack/assets/javascripts/react_app/components/ToastsList/index.js +++ b/webpack/assets/javascripts/react_app/components/ToastsList/index.js @@ -50,7 +50,13 @@ const ToastsList = ({ railsMessages }) => { ) ); - return toastsList.length > 0 && {toastsList}; + return ( + toastsList.length > 0 && ( + + {toastsList} + + ) + ); }; ToastsList.propTypes = { diff --git a/webpack/assets/javascripts/react_app/components/ToastsList/style.scss b/webpack/assets/javascripts/react_app/components/ToastsList/style.scss index 8a48c97774..f25a993d85 100644 --- a/webpack/assets/javascripts/react_app/components/ToastsList/style.scss +++ b/webpack/assets/javascripts/react_app/components/ToastsList/style.scss @@ -1,4 +1,4 @@ /* Make toasts visible over modal (z-index: 1050) */ -.pf-v5-c-alert-group { +.foreman-toast-group { z-index: 1100 !important; } diff --git a/webpack/assets/javascripts/react_app/components/common/ActionButtons/ActionButtons.js b/webpack/assets/javascripts/react_app/components/common/ActionButtons/ActionButtons.js index b44a22fa51..a9737e47b3 100644 --- a/webpack/assets/javascripts/react_app/components/common/ActionButtons/ActionButtons.js +++ b/webpack/assets/javascripts/react_app/components/common/ActionButtons/ActionButtons.js @@ -37,6 +37,7 @@ export const ActionButtons = ({ buttons }) => { return ( setIsOpen(nextOpen)} toggle={toggleRef => ( diff --git a/webpack/assets/javascripts/react_app/components/common/ActionButtons/ActionButtons.scss b/webpack/assets/javascripts/react_app/components/common/ActionButtons/ActionButtons.scss index 806b16d33b..82a31eac8d 100644 --- a/webpack/assets/javascripts/react_app/components/common/ActionButtons/ActionButtons.scss +++ b/webpack/assets/javascripts/react_app/components/common/ActionButtons/ActionButtons.scss @@ -1,4 +1,4 @@ -.pf-v5-c-menu-toggle.pf-m-split-button.pf-m-action { +.action-buttons-dropdown .pf-v5-c-menu-toggle { .action-buttons-menu-toggle-action, .pf-v5-c-menu-toggle__button { font-size: var(--pf-v5-global--FontSize--sm); } @@ -8,7 +8,7 @@ } } -.pf-v5-c-menu .pf-v5-c-menu__content .pf-v5-c-menu__list { +.action-buttons-dropdown .pf-v5-c-menu__list { .pf-v5-c-menu__item-main .pf-v5-c-menu__item-text { font-size: var(--pf-v5-global--FontSize--sm); } diff --git a/webpack/assets/javascripts/react_app/components/common/DateTimePicker/date-time-picker.scss b/webpack/assets/javascripts/react_app/components/common/DateTimePicker/date-time-picker.scss index e2b3e851d2..1f26edd9af 100644 --- a/webpack/assets/javascripts/react_app/components/common/DateTimePicker/date-time-picker.scss +++ b/webpack/assets/javascripts/react_app/components/common/DateTimePicker/date-time-picker.scss @@ -1,6 +1,7 @@ .date-picker-popover .pf-v5-c-popover__footer { margin-top: 0; margin-bottom: 10px; + .date-picker-input-items { display: flex; justify-content: space-evenly; diff --git a/webpack/assets/javascripts/react_app/components/common/EmptyState/EmptyState.scss b/webpack/assets/javascripts/react_app/components/common/EmptyState/EmptyState.scss index e88cf9a111..221b4e624a 100644 --- a/webpack/assets/javascripts/react_app/components/common/EmptyState/EmptyState.scss +++ b/webpack/assets/javascripts/react_app/components/common/EmptyState/EmptyState.scss @@ -1,4 +1,4 @@ -.pf-v5-c-empty-state { +.foreman-empty-state { margin-top: 100px; .empty-state-icon { diff --git a/webpack/assets/javascripts/react_app/components/common/EmptyState/EmptyStatePattern.js b/webpack/assets/javascripts/react_app/components/common/EmptyState/EmptyStatePattern.js index 1ac5ad0436..223af6b18f 100644 --- a/webpack/assets/javascripts/react_app/components/common/EmptyState/EmptyStatePattern.js +++ b/webpack/assets/javascripts/react_app/components/common/EmptyState/EmptyStatePattern.js @@ -62,7 +62,7 @@ const EmptyStatePattern = props => { }; return ( - + diff --git a/webpack/assets/javascripts/react_app/components/common/Loader/Loader.css b/webpack/assets/javascripts/react_app/components/common/Loader/Loader.css index ed7f615cae..f4b564326d 100644 --- a/webpack/assets/javascripts/react_app/components/common/Loader/Loader.css +++ b/webpack/assets/javascripts/react_app/components/common/Loader/Loader.css @@ -1,10 +1,6 @@ .loader-root { - display: -ms-flexbox; display: flex; - -ms-flex-pack: center; justify-content: center; - -ms-flex-align: center; align-items: center; - -ms-flex: 1; flex: 1; } diff --git a/webpack/assets/javascripts/react_app/components/common/MessageBox/MessageBox.css b/webpack/assets/javascripts/react_app/components/common/MessageBox/MessageBox.css index 2d6989ccad..e22d64be2b 100644 --- a/webpack/assets/javascripts/react_app/components/common/MessageBox/MessageBox.css +++ b/webpack/assets/javascripts/react_app/components/common/MessageBox/MessageBox.css @@ -1,19 +1,14 @@ .message-box-root { - -ms-flex: 1 1; flex: 1 1; - display: -ms-flexbox; display: flex; - -ms-flex-direction: column; flex-direction: column; - -ms-flex-align: center; align-items: center; - -ms-flex-pack: center; justify-content: center; } .message-box-content { - -ms-flex: 0 0 30px; + flex: 0 0 30px; flex-basis: 30px; text-align: center; } diff --git a/webpack/assets/javascripts/react_app/components/common/ModalProgressBar/ModalProgressBar.scss b/webpack/assets/javascripts/react_app/components/common/ModalProgressBar/ModalProgressBar.scss index 1937278dba..490aabacbb 100644 --- a/webpack/assets/javascripts/react_app/components/common/ModalProgressBar/ModalProgressBar.scss +++ b/webpack/assets/javascripts/react_app/components/common/ModalProgressBar/ModalProgressBar.scss @@ -1,6 +1,7 @@ #modal-progress-bar { min-height: 100px; } + // Needed to display modal within a container .modal-container { position: relative; diff --git a/webpack/assets/javascripts/react_app/components/users/PersonalAccessTokens/personalAccessToken.scss b/webpack/assets/javascripts/react_app/components/users/PersonalAccessTokens/personalAccessToken.scss index 00438ef056..8b3a2996c7 100644 --- a/webpack/assets/javascripts/react_app/components/users/PersonalAccessTokens/personalAccessToken.scss +++ b/webpack/assets/javascripts/react_app/components/users/PersonalAccessTokens/personalAccessToken.scss @@ -7,14 +7,17 @@ .token-expires-radio label { width: 100%; } + .token-expires-radio input { align-self: center; } + .token-expires-radio-title { width: 80px; display: inline-block; align-self: center; } + .token-expires-radio-wrapper { display: flex; }