diff options
61 files changed, 2969 insertions, 3381 deletions
diff --git a/.gitlab/ci/frontend.gitlab-ci.yml b/.gitlab/ci/frontend.gitlab-ci.yml index 33aab8554e7..dfd595c2696 100644 --- a/.gitlab/ci/frontend.gitlab-ci.yml +++ b/.gitlab/ci/frontend.gitlab-ci.yml @@ -317,3 +317,30 @@ bundle-size-review: expire_in: 31d paths: - bundle-size-review + +.startup-css-check-base: + extends: + - .frontend-test-base + script: + - *yarn-install + - run_timed_command "yarn generate:startup_css" + - yarn check:startup_css + +startup-css-check: + extends: + - .startup-css-check-base + - .frontend:rules:default-frontend-jobs + needs: + - job: "compile-test-assets" + - job: "rspec frontend_fixture" + - job: "rspec-ee frontend_fixture" + optional: true + +startup-css-check as-if-foss: + extends: + - .startup-css-check-base + - .as-if-foss + - .frontend:rules:default-frontend-jobs-as-if-foss + needs: + - job: "compile-test-assets as-if-foss" + - job: "rspec frontend_fixture as-if-foss" diff --git a/.stylelintrc b/.stylelintrc index 13ec6ea340b..a4331811eb3 100644 --- a/.stylelintrc +++ b/.stylelintrc @@ -3,6 +3,7 @@ "ignoreFiles": [ "app/assets/stylesheets/pages/emojis.scss", "app/assets/stylesheets/startup/startup-*.scss", + "ee/app/assets/stylesheets/startup/startup-*.scss", "app/assets/stylesheets/lazy_bundles/select2.scss", "app/assets/stylesheets/highlight/themes/*.scss", "app/assets/stylesheets/lazy_bundles/cropper.css" diff --git a/app/assets/javascripts/frequent_items/components/app.vue b/app/assets/javascripts/frequent_items/components/app.vue index e103949b86a..dd405893e43 100644 --- a/app/assets/javascripts/frequent_items/components/app.vue +++ b/app/assets/javascripts/frequent_items/components/app.vue @@ -30,6 +30,11 @@ export default { type: Object, required: true, }, + searchClass: { + type: String, + required: false, + default: '', + }, }, computed: { ...mapVuexModuleState((vm) => vm.vuexModule, [ @@ -115,7 +120,11 @@ export default { <template> <div class="gl-display-flex gl-flex-direction-column gl-flex-align-items-stretch gl-h-full"> - <frequent-items-search-input :namespace="namespace" data-testid="frequent-items-search-input" /> + <frequent-items-search-input + :namespace="namespace" + :class="searchClass" + data-testid="frequent-items-search-input" + /> <gl-loading-icon v-if="isLoadingItems" :label="translations.loadingMessage" diff --git a/app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue b/app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue index c2f77cc8bc4..d6fcdeb9e13 100644 --- a/app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue +++ b/app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue @@ -58,7 +58,7 @@ export default { <li class="frequent-items-list-item-container"> <a :href="webUrl" - class="clearfix" + class="clearfix dropdown-item" @click="track('click_link', { label: `${dropdownType}_dropdown_frequent_items_list_item` })" > <div diff --git a/app/assets/javascripts/frequent_items/components/frequent_items_search_input.vue b/app/assets/javascripts/frequent_items/components/frequent_items_search_input.vue index fa14ee15cf3..4a1b7e57749 100644 --- a/app/assets/javascripts/frequent_items/components/frequent_items_search_input.vue +++ b/app/assets/javascripts/frequent_items/components/frequent_items_search_input.vue @@ -39,7 +39,7 @@ export default { </script> <template> - <div class="search-input-container d-none d-sm-block"> + <div class="search-input-container"> <gl-search-box-by-type v-model="searchQuery" :placeholder="translations.searchInputPlaceholder" diff --git a/app/assets/javascripts/frequent_items/index.js b/app/assets/javascripts/frequent_items/index.js index f1540ffac28..9de18ba092f 100644 --- a/app/assets/javascripts/frequent_items/index.js +++ b/app/assets/javascripts/frequent_items/index.js @@ -60,6 +60,7 @@ export default function initFrequentItemDropdowns() { namespace, currentUserName: this.currentUserName, currentItem: this.currentItem, + searchClass: 'gl-display-none gl-sm-display-block', }, }), ], diff --git a/app/assets/stylesheets/pages/login.scss b/app/assets/stylesheets/pages/login.scss index 9d437531e6d..b537a46a6f2 100644 --- a/app/assets/stylesheets/pages/login.scss +++ b/app/assets/stylesheets/pages/login.scss @@ -106,6 +106,10 @@ width: 100%; } } + + .omniauth-btn { + width: 100%; + } } .new-session-tabs { diff --git a/app/assets/stylesheets/pages/search.scss b/app/assets/stylesheets/pages/search.scss index 13c25eb7873..5fbb2e6443f 100644 --- a/app/assets/stylesheets/pages/search.scss +++ b/app/assets/stylesheets/pages/search.scss @@ -45,6 +45,7 @@ input[type='checkbox']:hover { margin: 0 8px; form { + display: block; margin: 0; padding: 4px; width: $search-input-width; diff --git a/app/assets/stylesheets/startup/startup-dark.scss b/app/assets/stylesheets/startup/startup-dark.scss index 9f7a8860e4d..f77f201693f 100644 --- a/app/assets/stylesheets/startup/startup-dark.scss +++ b/app/assets/stylesheets/startup/startup-dark.scss @@ -1,4 +1,23 @@ +// DO NOT EDIT! This is auto-generated from "yarn run generate:startup_css" +// Please see the feedback issue for more details and help: +// https://gitlab.com/gitlab-org/gitlab/-/issues/331812 @charset "UTF-8"; +body.gl-dark { + --gray-50: #303030; + --gray-100: #404040; + --gray-200: #525252; + --gray-950: #fff; + --green-100: #0d532a; + --green-400: #108548; + --green-700: #91d4a8; + --blue-400: #1f75cb; + --orange-400: #ab6100; + --gl-text-color: #fafafa; + --border-color: #4f4f4f; +} +:root { + --white: #333; +} *, *::before, *::after { @@ -8,68 +27,46 @@ html { font-family: sans-serif; line-height: 1.15; } - header, nav, section { +aside, +header, +nav { display: block; } body { margin: 0; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Noto Sans", Ubuntu, Cantarell, "Helvetica Neue", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, + "Noto Sans", Ubuntu, Cantarell, "Helvetica Neue", sans-serif, + "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-size: 1rem; font-weight: 400; line-height: 1.5; color: #fafafa; text-align: left; - background-color: #2e2e2e; + background-color: #1f1f1f; } -h1, h2, h3 { +h1 { margin-top: 0; margin-bottom: 0.25rem; } -p { - margin-top: 0; - margin-bottom: 1rem; -} - ul { margin-top: 0; margin-bottom: 1rem; } - ul ul { margin-bottom: 0; } - strong { font-weight: bolder; } -sub { - position: relative; - font-size: 75%; - line-height: 0; - vertical-align: baseline; -} -sub { - bottom: -.25em; -} a { color: #007bff; text-decoration: none; background-color: transparent; } -a:not([href]) { +a:not([href]):not([class]) { color: inherit; text-decoration: none; } -pre, -code { - font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace; - font-size: 1em; -} -pre { - margin-top: 0; - margin-bottom: 1rem; - overflow: auto; -} img { vertical-align: middle; border-style: none; @@ -78,18 +75,11 @@ svg { overflow: hidden; vertical-align: middle; } -table { - border-collapse: collapse; -} -th { - text-align: inherit; -} button { border-radius: 0; } input, -button, -textarea { +button { margin: 0; font-family: inherit; font-size: inherit; @@ -102,21 +92,20 @@ input { button { text-transform: none; } +[role="button"] { + cursor: pointer; +} button:not(:disabled), [type="button"]:not(:disabled), -[type="reset"]:not(:disabled) { +[type="submit"]:not(:disabled) { cursor: pointer; } button::-moz-focus-inner, [type="button"]::-moz-focus-inner, -[type="reset"]::-moz-focus-inner { +[type="submit"]::-moz-focus-inner { padding: 0; border-style: none; } -textarea { - overflow: auto; - resize: vertical; -} [type="search"] { outline-offset: -2px; } @@ -124,81 +113,24 @@ summary { display: list-item; cursor: pointer; } -template { - display: none; -} [hidden] { display: none !important; } -h1, h2, h3, -.h1, .h2, .h3 { +h1, +.h1 { margin-bottom: 0.25rem; font-weight: 600; line-height: 1.2; color: #fafafa; } -h1, .h1 { +h1, +.h1 { font-size: 2.1875rem; } -h2, .h2 { - font-size: 1.75rem; -} -h3, .h3 { - font-size: 1.53125rem; -} .list-unstyled { padding-left: 0; list-style: none; } -code { - font-size: 90%; - color: #fff; - word-wrap: break-word; -} -a > code { - color: inherit; -} -pre { - display: block; - font-size: 90%; - color: #fafafa; -} -pre code { - font-size: inherit; - color: inherit; - word-break: normal; -} -.container { - width: 100%; - padding-right: 15px; - padding-left: 15px; - margin-right: auto; - margin-left: auto; -} - -@media (min-width: 576px) { - .container { - max-width: 540px; - } -} - -@media (min-width: 768px) { - .container { - max-width: 720px; - } -} - -@media (min-width: 992px) { - .container { - max-width: 960px; - } -} - -@media (min-width: 1200px) { - .container { - max-width: 1140px; - } -} .container-fluid { width: 100%; padding-right: 15px; @@ -206,48 +138,7 @@ pre code { margin-right: auto; margin-left: auto; } - -@media (min-width: 576px) { - .container { - max-width: 540px; - } -} - -@media (min-width: 768px) { - .container { - max-width: 720px; - } -} - -@media (min-width: 992px) { - .container { - max-width: 960px; - } -} - -@media (min-width: 1200px) { - .container { - max-width: 1140px; - } -} -.row { - display: flex; - flex-wrap: wrap; - margin-right: -15px; - margin-left: -15px; -} -.table { - width: 100%; - margin-bottom: 0.5rem; - color: #fafafa; -} -.table th, -.table td { - padding: 0.75rem; - vertical-align: top; - border-top: 1px solid #4f4f4f; -} - .search form { +.form-control { display: block; width: 100%; height: 34px; @@ -256,24 +147,27 @@ pre code { font-weight: 400; line-height: 1.5; color: #fafafa; - background-color: #4f4f4f; + background-color: #333; background-clip: padding-box; - border: 1px solid #4f4f4f; + border: 1px solid #404040; border-radius: 0.25rem; } - @media (prefers-reduced-motion: reduce) { } - .search form:-moz-focusring { +.form-control:-moz-focusring { color: transparent; text-shadow: 0 0 0 #fafafa; } - .search form::placeholder { - color: #ccc; +.form-control::-ms-input-placeholder { + color: #bfbfbf; + opacity: 1; +} +.form-control::placeholder { + color: #bfbfbf; opacity: 1; } - .search form:disabled { - background-color: #2e2e2e; +.form-control:disabled { + background-color: #303030; opacity: 1; } .form-inline { @@ -281,9 +175,8 @@ pre code { flex-flow: row wrap; align-items: center; } - @media (min-width: 576px) { - .form-inline .search form, .search .form-inline form { + .form-inline .form-control { display: inline-block; width: auto; vertical-align: middle; @@ -295,7 +188,7 @@ pre code { color: #fafafa; text-align: center; vertical-align: middle; - cursor: pointer; + -moz-user-select: none; user-select: none; background-color: transparent; border: 1px solid transparent; @@ -304,26 +197,24 @@ pre code { line-height: 20px; border-radius: 0.25rem; } - @media (prefers-reduced-motion: reduce) { } -.btn.disabled, .btn:disabled { +.btn:disabled { opacity: 0.65; } -a.btn.disabled { - pointer-events: none; +.btn:not(:disabled):not(.disabled) { + cursor: pointer; } .collapse:not(.show) { display: none; } - .dropdown { position: relative; } - .dropdown-menu-toggle { +.dropdown-menu-toggle { white-space: nowrap; } - .dropdown-menu-toggle::after { +.dropdown-menu-toggle::after { display: inline-block; margin-left: 0.255em; vertical-align: 0.255em; @@ -333,7 +224,7 @@ a.btn.disabled { border-bottom: 0; border-left: 0.3em solid transparent; } - .dropdown-menu-toggle:empty::after { +.dropdown-menu-toggle:empty::after { margin-left: 0; } .dropdown-menu { @@ -355,16 +246,6 @@ a.btn.disabled { border: 1px solid rgba(255, 255, 255, 0.15); border-radius: 0.25rem; } -.dropdown-menu-right { - right: 0; - left: auto; -} - .divider { - height: 0; - margin: 4px 0; - overflow: hidden; - border-top: 1px solid #4f4f4f; -} .dropdown-menu.show { display: block; } @@ -383,7 +264,6 @@ a.btn.disabled { justify-content: space-between; padding: 0.25rem 0.5rem; } -.navbar .container, .navbar .container-fluid { display: flex; flex-wrap: wrap; @@ -414,15 +294,12 @@ a.btn.disabled { border: 1px solid transparent; border-radius: 0.25rem; } - @media (max-width: 575.98px) { - .navbar-expand-sm > .container, .navbar-expand-sm > .container-fluid { padding-right: 0; padding-left: 0; } } - @media (min-width: 576px) { .navbar-expand-sm { flex-flow: row nowrap; @@ -434,7 +311,6 @@ a.btn.disabled { .navbar-expand-sm .navbar-nav .dropdown-menu { position: absolute; } - .navbar-expand-sm > .container, .navbar-expand-sm > .container-fluid { flex-wrap: nowrap; } @@ -454,7 +330,7 @@ a.btn.disabled { word-wrap: break-word; background-color: #333; background-clip: border-box; - border: 1px solid #4f4f4f; + border: 1px solid #404040; border-radius: 0.25rem; } .badge { @@ -468,7 +344,6 @@ a.btn.disabled { vertical-align: baseline; border-radius: 0.25rem; } - @media (prefers-reduced-motion: reduce) { } .badge:empty { @@ -483,10 +358,6 @@ a.btn.disabled { padding-left: 0.6em; border-radius: 10rem; } -.media { - display: flex; - align-items: flex-start; -} .close { float: right; font-size: 1.5rem; @@ -494,55 +365,15 @@ a.btn.disabled { line-height: 1; color: #fff; text-shadow: 0 1px 0 #333; - opacity: .5; + opacity: 0.5; } button.close { padding: 0; background-color: transparent; border: 0; - appearance: none; -} -a.close.disabled { - pointer-events: none; -} -.modal-dialog { - position: relative; - width: auto; - margin: 0.5rem; - pointer-events: none; -} - -@media (min-width: 576px) { - .modal-dialog { - max-width: 500px; - margin: 1.75rem auto; - } -} -.bg-transparent { - background-color: transparent !important; -} -.border { - border: 1px solid #4f4f4f !important; -} -.border-top { - border-top: 1px solid #4f4f4f !important; -} -.border-right { - border-right: 1px solid #4f4f4f !important; -} -.border-bottom { - border-bottom: 1px solid #4f4f4f !important; } -.border-left { - border-left: 1px solid #4f4f4f !important; -} -.rounded { - border-radius: 0.25rem !important; -} -.clearfix::after { - display: block; - clear: both; - content: ""; +.rounded-circle { + border-radius: 50% !important; } .d-none { display: none !important; @@ -553,19 +384,16 @@ a.close.disabled { .d-block { display: block !important; } - @media (min-width: 576px) { .d-sm-none { display: none !important; } } - @media (min-width: 768px) { .d-md-block { display: block !important; } } - @media (min-width: 992px) { .d-lg-none { display: none !important; @@ -574,18 +402,11 @@ a.close.disabled { display: block !important; } } - @media (min-width: 1200px) { .d-xl-block { display: block !important; } } -.flex-wrap { - flex-wrap: wrap !important; -} -.float-right { - float: right !important; -} .sr-only { position: absolute; width: 1px; @@ -600,72 +421,59 @@ a.close.disabled { .m-auto { margin: auto !important; } -.text-nowrap { - white-space: nowrap !important; +.gl-button { + display: inline-flex; } -.visible { - visibility: visible !important; +.gl-button:not(.btn-link):active { + text-decoration: none; } - .search form.focus { +.gl-button.gl-button { + border-width: 0; + padding-top: 0.5rem; + padding-bottom: 0.5rem; + padding-left: 0.75rem; + padding-right: 0.75rem; + background-color: transparent; + line-height: 1rem; color: #fafafa; - background-color: #4f4f4f; - border-color: #80bdff; - outline: 0; - box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); -} -.gl-badge { - display: inline-flex; + fill: currentColor; + box-shadow: inset 0 0 0 1px #525252; + justify-content: center; align-items: center; - font-size: 0.75rem; - font-weight: 400; - line-height: 1rem; - padding-top: 0.25rem; - padding-bottom: 0.25rem; - padding-left: 0.5rem; - padding-right: 0.5rem; + font-size: 0.875rem; + border-radius: 0.25rem; +} +.gl-button.gl-button.btn-default { + background-color: #333; +} +.gl-button.gl-button.btn-default:active, +.gl-button.gl-button.btn-default.active { + box-shadow: inset 0 0 0 2px #bfbfbf, 0 0 0 1px rgba(51, 51, 51, 0.4), + 0 0 0 4px rgba(66, 143, 220, 0.48); outline: none; + background-color: #404040; } -body, .search form, +body, +.form-control, .search form { font-size: 0.875rem; } button, -html [type='button'], -[type='reset'], -[role='button'] { +html [type="button"], +[type="submit"], +[role="button"] { cursor: pointer; } h1, -.h1, -h2, -.h2, -h3, -.h3 { +.h1 { margin-top: 20px; margin-bottom: 10px; } -input[type='file'] { - line-height: 1; -} - strong { font-weight: bold; } a { - color: #418cd8; -} -code { - padding: 2px 4px; - color: #fff; - background-color: #2e2e2e; - border-radius: 4px; -} -.code > code { - background-color: inherit; - padding: unset; -} -table { - border-spacing: 0; + color: #63a6e9; } .hidden { display: none !important; @@ -674,7 +482,7 @@ table { .hide { display: none; } - .dropdown-menu-toggle::after { +.dropdown-menu-toggle::after { display: none; } .badge:not(.gl-badge) { @@ -684,13 +492,16 @@ table { font-weight: 400; display: inline-block; } -pre code { - white-space: pre-wrap; +.divider { + height: 0; + margin: 4px 0; + overflow: hidden; + border-top: 1px solid #404040; } .toggle-sidebar-button .collapse-text, .toggle-sidebar-button .icon-chevron-double-lg-left, .toggle-sidebar-button .icon-chevron-double-lg-right { - color: #bababa; + color: #999; } svg { vertical-align: baseline; @@ -701,42 +512,23 @@ html { body { text-decoration-skip: ink; } -.content-wrapper { - margin-top: 40px; - padding-bottom: 100px; -} -.container { - padding-top: 0; - z-index: 5; -} -.container .content { - margin: 0; -} - -@media (max-width: 575.98px) { - .container .content { - margin-top: 20px; - } -} - -@media (max-width: 575.98px) { - .container .container .title { - padding-left: 15px !important; - } -} .btn { border-radius: 4px; font-size: 0.875rem; font-weight: 400; padding: 6px 10px; background-color: #333; - border-color: #4f4f4f; + border-color: #404040; color: #fafafa; color: #fafafa; white-space: nowrap; } -.btn:active, .btn.active { - box-shadow: rgba(0, 0, 0, 0.16); +.btn:active { + background-color: #303030; + box-shadow: none; +} +.btn:active, +.btn.active { background-color: #444; border-color: #fafafa; color: #fafafa; @@ -745,61 +537,19 @@ body { height: 15px; width: 15px; } -.btn svg:not(:last-child), -.btn .fa:not(:last-child) { +.btn svg:not(:last-child) { margin-right: 5px; } .badge.badge-pill:not(.gl-badge) { font-weight: 400; - background-color: rgba(0, 0, 0, 0.07); - color: #dfdfdf; + background-color: rgba(255, 255, 255, 0.07); + color: #dbdbdb; vertical-align: baseline; } -.hint { - font-style: italic; - color: #707070; -} -.bold { - font-weight: 600; -} -pre.wrap { - word-break: break-word; - white-space: pre-wrap; -} -table a code { - position: relative; - top: -2px; - margin-right: 3px; -} -.loading { - margin: 20px auto; - height: 40px; - color: #dfdfdf; - font-size: 32px; - text-align: center; -} -.highlight { - text-shadow: none; -} .chart { overflow: hidden; height: 220px; } -.break-word { - word-wrap: break-word; -} -.center { - text-align: center; -} -.block { - display: block; -} -.flex { - display: flex; -} -.flex-grow { - flex-grow: 1; -} .dropdown { position: relative; } @@ -810,47 +560,41 @@ table a code { max-height: 312px; overflow-y: auto; } - @media (max-width: 575.98px) { .show.dropdown .dropdown-menu { width: 100%; } } - .show.dropdown .dropdown-menu-toggle, +.show.dropdown .dropdown-menu-toggle, .show.dropdown .dropdown-menu-toggle { border-color: #c4c4c4; } -.show.dropdown [data-toggle='dropdown'] { +.show.dropdown [data-toggle="dropdown"] { outline: 0; } .search-input-container .dropdown-menu { margin-top: 11px; } - .dropdown-menu-toggle { +.dropdown-menu-toggle { padding: 6px 8px 6px 10px; background-color: #333; color: #fafafa; font-size: 14px; text-align: left; - border: 1px solid #4f4f4f; + border: 1px solid #404040; border-radius: 0.25rem; white-space: nowrap; } - .no-outline.dropdown-menu-toggle { +.no-outline.dropdown-menu-toggle { outline: 0; } - .dropdown-menu-toggle .fa { - color: #c4c4c4; -} -.dropdown-menu-toggle { +.dropdown-menu-toggle.dropdown-menu-toggle { + justify-content: flex-start; + overflow: hidden; padding-right: 25px; position: relative; - width: 160px; text-overflow: ellipsis; - overflow: hidden; -} -.dropdown-menu-toggle .fa { - position: absolute; + width: 160px; } .dropdown-menu { display: none; @@ -866,7 +610,7 @@ table a code { font-weight: 400; padding: 8px 0; background-color: #333; - border: 1px solid #4f4f4f; + border: 1px solid #404040; border-radius: 0.25rem; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); } @@ -897,156 +641,56 @@ table a code { text-align: left; width: 100%; } +.dropdown-menu li > a:active, +.dropdown-menu li button:active { + background-color: #4f4f4f; + color: #fafafa; + outline: 0; + text-decoration: none; +} .dropdown-menu .divider { height: 1px; margin: 0.25rem 0; padding: 0; - background-color: #4f4f4f; + background-color: #404040; } .dropdown-menu .badge.badge-pill + span:not(.badge):not(.badge-pill) { margin-right: 40px; } -.dropdown-select { - width: 300px; -} - -@media (max-width: 767.98px) { - .dropdown-select { - width: 100%; - } -} -.dropdown-content { - max-height: 252px; - overflow-y: auto; -} -.dropdown-loading { - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - display: none; - z-index: 9; - background-color: rgba(51, 51, 51, 0.6); - font-size: 28px; -} -.dropdown-loading .fa { - position: absolute; - top: 50%; - left: 50%; - margin-top: -14px; - margin-left: -14px; -} - @media (max-width: 575.98px) { .navbar-gitlab li.dropdown { position: static; } + .navbar-gitlab li.dropdown.user-counter { + margin-left: 8px !important; + } + .navbar-gitlab li.dropdown.user-counter > a { + padding: 0 4px !important; + } header.navbar-gitlab .dropdown .dropdown-menu { width: 100%; min-width: 100%; } } - @media (max-width: 767.98px) { .dropdown-menu-toggle { width: 100%; } } -textarea { - resize: vertical; -} input { border-radius: 0.25rem; color: #fafafa; - background-color: #4f4f4f; + background-color: #333; } - .search form { +.form-control { border-radius: 4px; padding: 6px 10px; } - .search form::placeholder { - color: #a7a7a7; -} -body.ui-indigo .navbar-gitlab { - background-color: #292961; -} -body.ui-indigo .navbar-gitlab .navbar-collapse { - color: #d1d1f0; -} -body.ui-indigo .navbar-gitlab .container-fluid .navbar-toggler { - border-left: 1px solid #6868b9; -} -body.ui-indigo .navbar-gitlab .container-fluid .navbar-toggler svg { - fill: #d1d1f0; -} -body.ui-indigo .navbar-gitlab .navbar-sub-nav > li.active > a, -body.ui-indigo .navbar-gitlab .navbar-sub-nav > li.active > button, body.ui-indigo .navbar-gitlab .navbar-sub-nav > li.dropdown.show > a, -body.ui-indigo .navbar-gitlab .navbar-sub-nav > li.dropdown.show > button, -body.ui-indigo .navbar-gitlab .navbar-nav > li.active > a, -body.ui-indigo .navbar-gitlab .navbar-nav > li.active > button, -body.ui-indigo .navbar-gitlab .navbar-nav > li.dropdown.show > a, -body.ui-indigo .navbar-gitlab .navbar-nav > li.dropdown.show > button { - color: #292961; - background-color: #333; -} -body.ui-indigo .navbar-gitlab .navbar-sub-nav { - color: #d1d1f0; -} -body.ui-indigo .navbar-gitlab .nav > li { - color: #d1d1f0; -} -body.ui-indigo .navbar-gitlab .nav > li > a.header-user-dropdown-toggle .header-user-avatar { - border-color: #d1d1f0; +.form-control::-ms-input-placeholder { + color: #868686; } -body.ui-indigo .navbar-gitlab .nav > li.active > a, -body.ui-indigo .navbar-gitlab .nav > li.dropdown.show > a { - color: #292961; - background-color: #333; -} -body.ui-indigo .search form { - background-color: rgba(209, 209, 240, 0.2); -} -body.ui-indigo .search .search-input::placeholder { - color: rgba(209, 209, 240, 0.8); -} -body.ui-indigo .search .search-input-wrap .search-icon, -body.ui-indigo .search .search-input-wrap .clear-icon { - fill: rgba(209, 209, 240, 0.8); -} -body.ui-indigo .nav-sidebar li.active { - box-shadow: inset 4px 0 0 #4b4ba3; -} -body.ui-indigo .nav-sidebar li.active > a { - color: #393982; -} -body.ui-indigo .nav-sidebar li.active .nav-icon-container svg { - fill: #393982; -} -body.ui-indigo .sidebar-top-level-items > li.active .badge.badge-pill { - color: #393982; -} -body.gl-dark .logo-text svg { - fill: #fafafa; -} -body.gl-dark .navbar-gitlab { - background-color: #2e2e2e; - box-shadow: 0 1px 0 0 var(--gray-100); -} -body.gl-dark .navbar-gitlab .navbar-sub-nav li.active > a, -body.gl-dark .navbar-gitlab .navbar-sub-nav li.active > button, -body.gl-dark .navbar-gitlab .navbar-sub-nav li.dropdown.show > a, -body.gl-dark .navbar-gitlab .navbar-sub-nav li.dropdown.show > button, -body.gl-dark .navbar-gitlab .navbar-nav li.active > a, -body.gl-dark .navbar-gitlab .navbar-nav li.active > button, -body.gl-dark .navbar-gitlab .navbar-nav li.dropdown.show > a, -body.gl-dark .navbar-gitlab .navbar-nav li.dropdown.show > button { - color: #fafafa; - background-color: #707070; -} -body.gl-dark .navbar-gitlab .search form { - background-color: #4f4f4f; - box-shadow: inset 0 0 0 1px #4f4f4f; +.form-control::placeholder { + color: #868686; } .navbar-gitlab { padding: 0 16px; @@ -1054,7 +698,6 @@ body.gl-dark .navbar-gitlab .search form { margin-bottom: 0; min-height: 40px; border: 0; - border-bottom: 1px solid #4f4f4f; position: fixed; top: 0; left: 0; @@ -1104,9 +747,6 @@ body.gl-dark .navbar-gitlab .search form { .navbar-gitlab .header-content .title img + .logo-text { margin-left: 8px; } -.navbar-gitlab .header-content .title.wrap { - white-space: normal; -} .navbar-gitlab .header-content .title a { display: flex; align-items: center; @@ -1114,9 +754,6 @@ body.gl-dark .navbar-gitlab .search form { margin: 5px 2px 5px -8px; border-radius: 4px; } -.navbar-gitlab .header-content .dropdown.open > a { - border-bottom-color: #333; -} .navbar-gitlab .header-content .navbar-collapse > ul.nav > li:not(.d-none) { margin: 0 2px; } @@ -1125,7 +762,6 @@ body.gl-dark .navbar-gitlab .search form { border-top: 0; padding: 0; } - @media (max-width: 575.98px) { .navbar-gitlab .navbar-collapse { flex: 1 1 auto; @@ -1134,7 +770,6 @@ body.gl-dark .navbar-gitlab .search form { .navbar-gitlab .navbar-collapse .nav { flex-wrap: nowrap; } - @media (max-width: 575.98px) { .navbar-gitlab .navbar-collapse .nav > li:not(.d-none) a { margin-left: 0; @@ -1157,7 +792,10 @@ body.gl-dark .navbar-gitlab .search form { text-align: center; color: currentColor; } - +.navbar-gitlab .container-fluid .navbar-toggler.active { + color: currentColor; + background-color: transparent; +} @media (max-width: 575.98px) { .navbar-gitlab .container-fluid .navbar-nav { display: flex; @@ -1165,11 +803,14 @@ body.gl-dark .navbar-gitlab .search form { flex-direction: row; } } -.navbar-gitlab .container-fluid .navbar-nav li .badge.badge-pill { +.navbar-gitlab + .container-fluid + .navbar-nav + li + .badge.badge-pill:not(.merge-request-badge) { box-shadow: none; font-weight: 600; } - @media (max-width: 575.98px) { .navbar-gitlab .container-fluid .nav > li.header-user { padding-left: 10px; @@ -1181,7 +822,6 @@ body.gl-dark .navbar-gitlab .search form { padding: 6px 8px; height: 32px; } - @media (max-width: 575.98px) { .navbar-gitlab .container-fluid .nav > li > a { padding: 0; @@ -1190,7 +830,12 @@ body.gl-dark .navbar-gitlab .search form { .navbar-gitlab .container-fluid .nav > li > a.header-user-dropdown-toggle { margin-left: 2px; } -.navbar-gitlab .container-fluid .nav > li > a.header-user-dropdown-toggle .header-user-avatar { +.navbar-gitlab + .container-fluid + .nav + > li + > a.header-user-dropdown-toggle + .header-user-avatar { margin-right: 0; } .navbar-gitlab .container-fluid .nav > li .header-new-dropdown-toggle { @@ -1211,7 +856,9 @@ body.gl-dark .navbar-gitlab .search form { height: 32px; font-weight: 600; } +.navbar-sub-nav > li .top-nav-toggle, .navbar-sub-nav > li > button, +.navbar-nav > li .top-nav-toggle, .navbar-nav > li > button { background: transparent; border: 0; @@ -1249,31 +896,25 @@ body.gl-dark .navbar-gitlab .search form { font-weight: 400; margin-left: -6px; font-size: 11px; - color: #333; + color: var(--gray-950, #333); padding: 0 5px; line-height: 12px; border-radius: 7px; box-shadow: 0 1px 0 rgba(76, 78, 84, 0.2); } -.title-container .badge.badge-pill.green-badge, -.navbar-nav .badge.badge-pill.green-badge { - background-color: #1aaa55; -} -.title-container .badge.badge-pill.merge-requests-count, -.navbar-nav .badge.badge-pill.merge-requests-count { - background-color: #fca429; +.title-container .badge.badge-pill:not(.merge-request-badge).green-badge, +.navbar-nav .badge.badge-pill:not(.merge-request-badge).green-badge { + background-color: var(--green-400, #108548); } -.title-container .badge.badge-pill.todos-count, -.navbar-nav .badge.badge-pill.todos-count { - background-color: #1f78d1; +.title-container + .badge.badge-pill:not(.merge-request-badge).merge-requests-count, +.navbar-nav .badge.badge-pill:not(.merge-request-badge).merge-requests-count { + background-color: var(--orange-400, #ab6100); } -.title-container .canary-badge .badge, -.navbar-nav .canary-badge .badge { - font-size: 12px; - line-height: 16px; - padding: 0 0.5rem; +.title-container .badge.badge-pill:not(.merge-request-badge).todos-count, +.navbar-nav .badge.badge-pill:not(.merge-request-badge).todos-count { + background-color: var(--blue-400, #1f75cb); } - @media (max-width: 575.98px) { .navbar-gitlab .container-fluid { font-size: 18px; @@ -1300,7 +941,7 @@ body.gl-dark .navbar-gitlab .search form { } .header-user.show .dropdown-menu { margin-top: 4px; - color: #fafafa; + color: var(--gl-text-color, #fafafa); left: auto; max-height: 445px; } @@ -1313,30 +954,32 @@ body.gl-dark .navbar-gitlab .search form { border-radius: 50%; border: 1px solid #333; } -.media { - display: flex; - align-items: flex-start; +.notification-dot { + background-color: #9e5400; + height: 12px; + width: 12px; + margin-top: -15px; + pointer-events: none; + visibility: hidden; } -.card { - margin-bottom: 16px; +.top-nav-toggle .dropdown-icon { + margin-right: 0.5rem; } -.content-wrapper { - width: 100%; +.tanuki-logo .tanuki-left-ear, +.tanuki-logo .tanuki-right-ear, +.tanuki-logo .tanuki-nose { + fill: #e24329; } -.content-wrapper .container-fluid { - padding: 0 16px; +.tanuki-logo .tanuki-left-eye, +.tanuki-logo .tanuki-right-eye { + fill: #fc6d26; } - -@media (min-width: 768px) { - .page-with-contextual-sidebar { - padding-left: 50px; - } +.tanuki-logo .tanuki-left-cheek, +.tanuki-logo .tanuki-right-cheek { + fill: #fca326; } - -@media (min-width: 1200px) { - .page-with-contextual-sidebar { - padding-left: 220px; - } +.card { + margin-bottom: 16px; } .context-header { position: relative; @@ -1363,9 +1006,20 @@ body.gl-dark .navbar-gitlab .search form { overflow: hidden; text-overflow: ellipsis; } -.context-header .sidebar-context-title.text-secondary { - font-weight: normal; - font-size: 0.8em; +@media (min-width: 768px) { + .page-with-contextual-sidebar { + padding-left: 50px; + } +} +@media (min-width: 1200px) { + .page-with-contextual-sidebar { + padding-left: 220px; + } +} +@media (min-width: 768px) { + .page-with-icon-sidebar { + padding-left: 50px; + } } .nav-sidebar { position: fixed; @@ -1374,14 +1028,13 @@ body.gl-dark .navbar-gitlab .search form { top: 40px; bottom: 0; left: 0; - background-color: #2e2e2e; - box-shadow: inset -1px 0 0 #4f4f4f; + background-color: #303030; + box-shadow: inset -1px 0 0 #404040; transform: translate3d(0, 0, 0); } - @media (min-width: 576px) and (max-width: 576px) { .nav-sidebar:not(.sidebar-collapsed-desktop) { - box-shadow: inset -1px 0 0 #4f4f4f, 2px 1px 3px rgba(0, 0, 0, 0.1); + box-shadow: inset -1px 0 0 #404040, 2px 1px 3px rgba(0, 0, 0, 0.1); } } .nav-sidebar.sidebar-collapsed-desktop { @@ -1391,7 +1044,6 @@ body.gl-dark .navbar-gitlab .search form { overflow-x: hidden; } .nav-sidebar.sidebar-collapsed-desktop .badge.badge-pill:not(.fly-out-badge), -.nav-sidebar.sidebar-collapsed-desktop .sidebar-context-title, .nav-sidebar.sidebar-collapsed-desktop .nav-item-name { border: 0; clip: rect(0, 0, 0, 0); @@ -1412,9 +1064,6 @@ body.gl-dark .navbar-gitlab .search form { .nav-sidebar.sidebar-collapsed-desktop .avatar-container { margin: 0 auto; } -.nav-sidebar.sidebar-expanded-mobile { - left: 0; -} .nav-sidebar a { text-decoration: none; } @@ -1429,7 +1078,7 @@ body.gl-dark .navbar-gitlab .search form { display: flex; align-items: center; padding: 12px 16px; - color: #bababa; + color: #999; } .nav-sidebar li .nav-item-name { flex: 1; @@ -1437,7 +1086,6 @@ body.gl-dark .navbar-gitlab .search form { .nav-sidebar li.active > a { font-weight: 600; } - @media (max-width: 767.98px) { .nav-sidebar { left: -220px; @@ -1454,7 +1102,6 @@ body.gl-dark .navbar-gitlab .search form { height: 16px; width: 16px; } - @media (min-width: 768px) and (max-width: 1199px) { .nav-sidebar:not(.sidebar-expanded-mobile) { width: 50px; @@ -1462,8 +1109,8 @@ body.gl-dark .navbar-gitlab .search form { .nav-sidebar:not(.sidebar-expanded-mobile) .nav-sidebar-inner-scroll { overflow-x: hidden; } - .nav-sidebar:not(.sidebar-expanded-mobile) .badge.badge-pill:not(.fly-out-badge), - .nav-sidebar:not(.sidebar-expanded-mobile) .sidebar-context-title, + .nav-sidebar:not(.sidebar-expanded-mobile) + .badge.badge-pill:not(.fly-out-badge), .nav-sidebar:not(.sidebar-expanded-mobile) .nav-item-name { border: 0; clip: rect(0, 0, 0, 0); @@ -1491,7 +1138,21 @@ body.gl-dark .navbar-gitlab .search form { .nav-sidebar:not(.sidebar-expanded-mobile) .context-header a { padding: 10px 4px; } - .nav-sidebar:not(.sidebar-expanded-mobile) .sidebar-top-level-items > li .sidebar-sub-level-items:not(.flyout-list) { + .nav-sidebar:not(.sidebar-expanded-mobile) .sidebar-context-title { + border: 0; + clip: rect(0, 0, 0, 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + white-space: nowrap; + width: 1px; + } + .nav-sidebar:not(.sidebar-expanded-mobile) + .sidebar-top-level-items + > li + .sidebar-sub-level-items:not(.flyout-list) { display: none; } .nav-sidebar:not(.sidebar-expanded-mobile) .nav-icon-container { @@ -1501,11 +1162,17 @@ body.gl-dark .navbar-gitlab .search form { padding: 16px; width: 49px; } - .nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button .collapse-text, - .nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button .icon-chevron-double-lg-left { + .nav-sidebar:not(.sidebar-expanded-mobile) + .toggle-sidebar-button + .collapse-text, + .nav-sidebar:not(.sidebar-expanded-mobile) + .toggle-sidebar-button + .icon-chevron-double-lg-left { display: none; } - .nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button .icon-chevron-double-lg-right { + .nav-sidebar:not(.sidebar-expanded-mobile) + .toggle-sidebar-button + .icon-chevron-double-lg-right { display: block; margin: 0; } @@ -1522,10 +1189,12 @@ body.gl-dark .navbar-gitlab .search form { .sidebar-sub-level-items > li a { padding: 8px 16px 8px 40px; } +.sidebar-sub-level-items > li.active a { + background: rgba(255, 255, 255, 0.04); +} .sidebar-top-level-items { margin-bottom: 60px; } - @media (min-width: 576px) { .sidebar-top-level-items > li > a { margin-right: 1px; @@ -1533,7 +1202,7 @@ body.gl-dark .navbar-gitlab .search form { } .sidebar-top-level-items > li .badge.badge-pill { background-color: rgba(255, 255, 255, 0.08); - color: #bababa; + color: #999; } .sidebar-top-level-items > li.active { background: rgba(255, 255, 255, 0.04); @@ -1545,23 +1214,28 @@ body.gl-dark .navbar-gitlab .search form { .sidebar-top-level-items > li.active .badge.badge-pill { font-weight: 600; } -.sidebar-top-level-items > li.active .sidebar-sub-level-items:not(.is-fly-out-only) { +.sidebar-top-level-items + > li.active + .sidebar-sub-level-items:not(.is-fly-out-only) { display: block; } .toggle-sidebar-button, .close-nav-button { - width: 219px; - position: fixed; height: 48px; - bottom: 0; padding: 0 16px; - background-color: #2e2e2e; + background-color: #303030; border: 0; - border-top: 1px solid #4f4f4f; - color: #bababa; + color: #999; display: flex; align-items: center; } +.toggle-sidebar-button, +.close-nav-button { + position: fixed; + bottom: 0; + width: 219px; + border-top: 1px solid #404040; +} .toggle-sidebar-button svg, .close-nav-button svg { margin-right: 8px; @@ -1581,7 +1255,21 @@ body.gl-dark .navbar-gitlab .search form { .sidebar-collapsed-desktop .context-header a { padding: 10px 4px; } -.sidebar-collapsed-desktop .sidebar-top-level-items > li .sidebar-sub-level-items:not(.flyout-list) { +.sidebar-collapsed-desktop .sidebar-context-title { + border: 0; + clip: rect(0, 0, 0, 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + white-space: nowrap; + width: 1px; +} +.sidebar-collapsed-desktop + .sidebar-top-level-items + > li + .sidebar-sub-level-items:not(.flyout-list) { display: none; } .sidebar-collapsed-desktop .nav-icon-container { @@ -1595,7 +1283,9 @@ body.gl-dark .navbar-gitlab .search form { .sidebar-collapsed-desktop .toggle-sidebar-button .icon-chevron-double-lg-left { display: none; } -.sidebar-collapsed-desktop .toggle-sidebar-button .icon-chevron-double-lg-right { +.sidebar-collapsed-desktop + .toggle-sidebar-button + .icon-chevron-double-lg-right { display: block; margin: 0; } @@ -1611,7 +1301,6 @@ body.gl-dark .navbar-gitlab .search form { .close-nav-button { display: none; } - @media (max-width: 767.98px) { .close-nav-button { display: flex; @@ -1620,128 +1309,523 @@ body.gl-dark .navbar-gitlab .search form { display: none; } } -table.table { - margin-bottom: 16px; +body.sidebar-refactoring.gl-dark .nav-sidebar li.active { + box-shadow: none; } -table.table .dropdown-menu a { - text-decoration: none; +body.sidebar-refactoring.gl-dark .nav-sidebar li a, +body.sidebar-refactoring.gl-dark .toggle-sidebar-button .collapse-text, +body.sidebar-refactoring.gl-dark + .toggle-sidebar-button + .icon-chevron-double-lg-left, +body.sidebar-refactoring.gl-dark + .toggle-sidebar-button + .icon-chevron-double-lg-right, +body.sidebar-refactoring.gl-dark + .sidebar-top-level-items + .context-header + a + .sidebar-context-title, +body.sidebar-refactoring.gl-dark + .nav-sidebar-inner-scroll + > div.context-header + a + .sidebar-context-title { + color: #c4c4c4; } -table.table .success, -table.table .info { - color: #333; +body.sidebar-refactoring.ui-indigo .nav-sidebar li.active > a { + color: #2f2a6b; } -table.table .success a:not(.btn), -table.table .info a:not(.btn) { - text-decoration: underline; - color: #333; +body.sidebar-refactoring.ui-indigo + .nav-sidebar + li.active + .nav-icon-container + svg { + fill: #2f2a6b; +} +body.sidebar-refactoring .nav-sidebar { + box-shadow: none; +} +body.sidebar-refactoring .nav-sidebar li.active { + background-color: transparent; + box-shadow: none !important; +} +@media (min-width: 768px) { + body.sidebar-refactoring .page-with-contextual-sidebar { + padding-left: 50px; + } +} +@media (min-width: 1200px) { + body.sidebar-refactoring .page-with-contextual-sidebar { + padding-left: 220px; + } +} +@media (min-width: 768px) { + body.sidebar-refactoring .page-with-icon-sidebar { + padding-left: 50px; + } } -pre { - font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace; +body.sidebar-refactoring .nav-sidebar { + position: fixed; + z-index: 600; + width: 220px; + top: 40px; + bottom: 0; + left: 0; + background-color: #303030; + transform: translate3d(0, 0, 0); +} +@media (min-width: 576px) and (max-width: 576px) { + body.sidebar-refactoring .nav-sidebar:not(.sidebar-collapsed-desktop) { + box-shadow: inset -1px 0 0 #404040, 2px 1px 3px rgba(0, 0, 0, 0.1); + } +} +body.sidebar-refactoring .nav-sidebar.sidebar-collapsed-desktop { + width: 50px; +} +body.sidebar-refactoring + .nav-sidebar.sidebar-collapsed-desktop + .nav-sidebar-inner-scroll { + overflow-x: hidden; +} +body.sidebar-refactoring + .nav-sidebar.sidebar-collapsed-desktop + .badge.badge-pill:not(.fly-out-badge), +body.sidebar-refactoring .nav-sidebar.sidebar-collapsed-desktop .nav-item-name { + border: 0; + clip: rect(0, 0, 0, 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + white-space: nowrap; + width: 1px; +} +body.sidebar-refactoring + .nav-sidebar.sidebar-collapsed-desktop + .sidebar-top-level-items + > li + > a { + min-height: 45px; +} +body.sidebar-refactoring + .nav-sidebar.sidebar-collapsed-desktop + .fly-out-top-item { display: block; - padding: 8px 12px; - margin: 0 0 8px; - font-size: 13px; - word-break: break-all; - word-wrap: break-word; +} +body.sidebar-refactoring + .nav-sidebar.sidebar-collapsed-desktop + .avatar-container { + margin: 0 auto; +} +body.sidebar-refactoring .nav-sidebar a { + text-decoration: none; + line-height: 1rem; + color: #2f2a6b; +} +body.sidebar-refactoring .nav-sidebar li { + white-space: nowrap; +} +body.sidebar-refactoring .nav-sidebar li .nav-item-name { + flex: 1; +} +body.sidebar-refactoring .nav-sidebar li > a { + padding-left: 0.75rem; + padding-right: 0.75rem; + padding-top: 0.5rem; + padding-bottom: 0.5rem; + display: flex; + align-items: center; + border-radius: 0.25rem; + width: auto; + margin: 1px 4px; +} +body.sidebar-refactoring .nav-sidebar li.active > a { + font-weight: 600; +} +body.sidebar-refactoring .nav-sidebar li.active > a:not(.has-sub-items) { + background-color: rgba(41, 41, 97, 0.08); +} +body.sidebar-refactoring .nav-sidebar ul { + padding-left: 0; + list-style: none; +} +@media (max-width: 767.98px) { + body.sidebar-refactoring .nav-sidebar { + left: -220px; + } +} +body.sidebar-refactoring .nav-sidebar .nav-icon-container { + display: flex; + margin-right: 8px; +} +body.sidebar-refactoring .nav-sidebar .fly-out-top-item { + display: none; +} +@media (min-width: 768px) and (max-width: 1199px) { + body.sidebar-refactoring .nav-sidebar:not(.sidebar-expanded-mobile) { + width: 50px; + } + body.sidebar-refactoring + .nav-sidebar:not(.sidebar-expanded-mobile) + .nav-sidebar-inner-scroll { + overflow-x: hidden; + } + body.sidebar-refactoring + .nav-sidebar:not(.sidebar-expanded-mobile) + .badge.badge-pill:not(.fly-out-badge), + body.sidebar-refactoring + .nav-sidebar:not(.sidebar-expanded-mobile) + .nav-item-name { + border: 0; + clip: rect(0, 0, 0, 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + white-space: nowrap; + width: 1px; + } + body.sidebar-refactoring + .nav-sidebar:not(.sidebar-expanded-mobile) + .sidebar-top-level-items + > li + > a { + min-height: 45px; + } + body.sidebar-refactoring + .nav-sidebar:not(.sidebar-expanded-mobile) + .fly-out-top-item { + display: block; + } + body.sidebar-refactoring + .nav-sidebar:not(.sidebar-expanded-mobile) + .avatar-container { + margin: 0 auto; + } + body.sidebar-refactoring + .nav-sidebar:not(.sidebar-expanded-mobile) + .context-header { + height: 60px; + width: 50px; + } + body.sidebar-refactoring + .nav-sidebar:not(.sidebar-expanded-mobile) + .context-header + a { + padding: 10px 4px; + } + body.sidebar-refactoring + .nav-sidebar:not(.sidebar-expanded-mobile) + .sidebar-context-title { + border: 0; + clip: rect(0, 0, 0, 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + white-space: nowrap; + width: 1px; + } + body.sidebar-refactoring + .nav-sidebar:not(.sidebar-expanded-mobile) + .sidebar-top-level-items + > li + .sidebar-sub-level-items:not(.flyout-list) { + display: none; + } + body.sidebar-refactoring + .nav-sidebar:not(.sidebar-expanded-mobile) + .nav-icon-container { + margin-right: 0; + } + body.sidebar-refactoring + .nav-sidebar:not(.sidebar-expanded-mobile) + .toggle-sidebar-button { + padding: 16px; + width: 49px; + } + body.sidebar-refactoring + .nav-sidebar:not(.sidebar-expanded-mobile) + .toggle-sidebar-button + .collapse-text, + body.sidebar-refactoring + .nav-sidebar:not(.sidebar-expanded-mobile) + .toggle-sidebar-button + .icon-chevron-double-lg-left { + display: none; + } + body.sidebar-refactoring + .nav-sidebar:not(.sidebar-expanded-mobile) + .toggle-sidebar-button + .icon-chevron-double-lg-right { + display: block; + margin: 0; + } +} +body.sidebar-refactoring .nav-sidebar-inner-scroll { + height: 100%; + width: 100%; + overflow: auto; +} +body.sidebar-refactoring .nav-sidebar-inner-scroll > div.context-header { + margin-top: 0.25rem; +} +body.sidebar-refactoring .nav-sidebar-inner-scroll > div.context-header a { + padding-left: 0.75rem; + padding-right: 0.75rem; + padding-top: 0.5rem; + padding-bottom: 0.5rem; + display: flex; + align-items: center; + border-radius: 0.25rem; + width: auto; + margin: 1px 4px; + padding: 0.25rem; + margin-bottom: 0.25rem; +} +body.sidebar-refactoring + .nav-sidebar-inner-scroll + > div.context-header + a + .avatar-container { + font-weight: 400; + flex: none; + box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08); +} +body.sidebar-refactoring + .nav-sidebar-inner-scroll + > div.context-header + a + .avatar-container.rect-avatar { + border-style: none; +} +body.sidebar-refactoring + .nav-sidebar-inner-scroll + > div.context-header + a + .avatar-container.rect-avatar + .avatar.s32 { color: #fafafa; - background-color: #2e2e2e; - border: 1px solid #4f4f4f; - border-radius: 2px; + box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08); +} +body.sidebar-refactoring + .nav-sidebar-inner-scroll + > div.context-header + a + .sidebar-context-title { + color: #2f2a6b; +} +body.sidebar-refactoring .sidebar-top-level-items { + margin-top: 0.25rem; + margin-bottom: 60px; +} +body.sidebar-refactoring .sidebar-top-level-items .context-header a { + padding: 0.25rem; + margin-bottom: 0.25rem; +} +body.sidebar-refactoring + .sidebar-top-level-items + .context-header + a + .avatar-container { + font-weight: 400; + flex: none; + box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08); +} +body.sidebar-refactoring + .sidebar-top-level-items + .context-header + a + .avatar-container.rect-avatar { + border-style: none; +} +body.sidebar-refactoring + .sidebar-top-level-items + .context-header + a + .avatar-container.rect-avatar + .avatar.s32 { + color: #fafafa; + box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08); +} +body.sidebar-refactoring + .sidebar-top-level-items + .context-header + a + .sidebar-context-title { + color: #2f2a6b; +} +body.sidebar-refactoring .sidebar-top-level-items > li .badge.badge-pill { + border-radius: 0.5rem; + padding-top: 0.125rem; + padding-bottom: 0.125rem; + padding-left: 0.5rem; + padding-right: 0.5rem; + background-color: #064787; + color: #9dc7f1; +} +body.sidebar-refactoring + .sidebar-top-level-items + > li.active + .sidebar-sub-level-items:not(.is-fly-out-only) { + display: block; } -.monospace { - font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace; +body.sidebar-refactoring + .sidebar-top-level-items + > li.active + .badge.badge-pill { + font-weight: 400; + color: #9dc7f1; +} +body.sidebar-refactoring .sidebar-sub-level-items { + padding-bottom: 0; + display: none; +} +body.sidebar-refactoring .sidebar-sub-level-items:not(.fly-out-list) li > a { + padding-left: 2.25rem; +} +body.sidebar-refactoring .toggle-sidebar-button, +body.sidebar-refactoring .close-nav-button { + height: 48px; + padding: 0 16px; + background-color: #303030; + border: 0; + color: #999; + display: flex; + align-items: center; + background-color: #303030; + color: #2f2a6b; +} +body.sidebar-refactoring .toggle-sidebar-button .collapse-text, +body.sidebar-refactoring .toggle-sidebar-button .icon-chevron-double-lg-left, +body.sidebar-refactoring .toggle-sidebar-button .icon-chevron-double-lg-right, +body.sidebar-refactoring .close-nav-button .collapse-text, +body.sidebar-refactoring .close-nav-button .icon-chevron-double-lg-left, +body.sidebar-refactoring .close-nav-button .icon-chevron-double-lg-right { + color: inherit; } -input::-moz-placeholder, -textarea::-moz-placeholder { - color: #a7a7a7; +body.sidebar-refactoring .toggle-sidebar-button, +body.sidebar-refactoring .close-nav-button { + position: fixed; + bottom: 0; + width: 219px; + border-top: 1px solid #404040; +} +body.sidebar-refactoring .toggle-sidebar-button svg, +body.sidebar-refactoring .close-nav-button svg { + margin-right: 8px; +} +body.sidebar-refactoring .toggle-sidebar-button .icon-chevron-double-lg-right, +body.sidebar-refactoring .close-nav-button .icon-chevron-double-lg-right { + display: none; +} +body.sidebar-refactoring .collapse-text { + white-space: nowrap; + overflow: hidden; +} +body.sidebar-refactoring .sidebar-collapsed-desktop .context-header { + height: 60px; + width: 50px; +} +body.sidebar-refactoring .sidebar-collapsed-desktop .context-header a { + padding: 10px 4px; +} +body.sidebar-refactoring .sidebar-collapsed-desktop .sidebar-context-title { + border: 0; + clip: rect(0, 0, 0, 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + white-space: nowrap; + width: 1px; +} +body.sidebar-refactoring + .sidebar-collapsed-desktop + .sidebar-top-level-items + > li + .sidebar-sub-level-items:not(.flyout-list) { + display: none; +} +body.sidebar-refactoring .sidebar-collapsed-desktop .nav-icon-container { + margin-right: 0; +} +body.sidebar-refactoring .sidebar-collapsed-desktop .toggle-sidebar-button { + padding: 16px; + width: 49px; +} +body.sidebar-refactoring + .sidebar-collapsed-desktop + .toggle-sidebar-button + .collapse-text, +body.sidebar-refactoring + .sidebar-collapsed-desktop + .toggle-sidebar-button + .icon-chevron-double-lg-left { + display: none; +} +body.sidebar-refactoring + .sidebar-collapsed-desktop + .toggle-sidebar-button + .icon-chevron-double-lg-right { + display: block; + margin: 0; +} +body.sidebar-refactoring .close-nav-button { + display: none; +} +@media (max-width: 767.98px) { + body.sidebar-refactoring .close-nav-button { + display: flex; + } + body.sidebar-refactoring .toggle-sidebar-button { + display: none; + } +} +input::-moz-placeholder { + color: #868686; opacity: 1; } -input::-ms-input-placeholder, -textarea::-ms-input-placeholder { - color: #a7a7a7; +input::-ms-input-placeholder { + color: #868686; } -input:-ms-input-placeholder, -textarea:-ms-input-placeholder { - color: #a7a7a7; +input:-ms-input-placeholder { + color: #868686; } svg { fill: currentColor; } - svg.s12 { width: 12px; height: 12px; } - svg.s16 { width: 16px; height: 16px; } - svg.s18 { width: 18px; height: 18px; } - +svg.s32 { + width: 32px; + height: 32px; +} svg.s12 { vertical-align: -1px; } - svg.s16 { vertical-align: -3px; } -.sr-only { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - border: 0; -} -table.code { - width: 100%; - font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace; - border: 0; - border-collapse: separate; - margin: 0; - padding: 0; - table-layout: fixed; - border-radius: 0 0 4px 4px; -} -.frame .badge.badge-pill { - position: absolute; - background-color: #1b69b6; - color: #333; - border: #333 1px solid; - min-height: 16px; - padding: 5px 8px; - border-radius: 12px; -} -.frame .badge.badge-pill { - transform: translate(-50%, -50%); -} -.color-label { - padding: 0 0.5rem; - line-height: 16px; - border-radius: 100px; - color: #333; -} -.label-link { - display: inline-flex; - vertical-align: text-bottom; -} -.milestones { - padding: 8px; - margin-top: 8px; - border-radius: 4px; - background-color: #4f4f4f; -} .search { margin: 0 8px; } .search form { + display: block; margin: 0; padding: 4px; width: 200px; @@ -1750,7 +1834,6 @@ table.code { border: 0; border-radius: 4px; } - @media (min-width: 1200px) { .search form { width: 320px; @@ -1794,45 +1877,39 @@ table.code { max-height: 400px; overflow: auto; } - @media (min-width: 1200px) { .search .search-input-wrap .dropdown-menu { width: 320px; } } -.search .search-input-wrap .dropdown-content { - max-height: 382px; -} -.settings { - border-top: 1px solid #4f4f4f; +.search .identicon { + flex-basis: 16px; + flex-shrink: 0; + margin-right: 4px; } -.settings:first-of-type { - margin-top: 10px; - border: 0; -} -.settings + div .settings:first-of-type { - margin-top: 0; - border-top: 1px solid #4f4f4f; -} -.avatar, .avatar-container { +.avatar, +.avatar-container { float: left; margin-right: 16px; border-radius: 50%; border: 1px solid #333; } -.s16.avatar, .s16.avatar-container { +.avatar.s16, +.avatar-container.s16 { width: 16px; height: 16px; margin-right: 8px; } -.s18.avatar, .s18.avatar-container { +.avatar.s18, +.avatar-container.s18 { width: 18px; height: 18px; margin-right: 8px; } -.s40.avatar, .s40.avatar-container { - width: 40px; - height: 40px; +.avatar.s32, +.avatar-container.s32 { + width: 32px; + height: 32px; margin-right: 8px; } .avatar { @@ -1844,15 +1921,45 @@ table.code { overflow: hidden; border-color: rgba(255, 255, 255, 0.1); } -.avatar.center { - font-size: 14px; - line-height: 1.8em; - text-align: center; -} .avatar.avatar-tile { border-radius: 0; border: 0; } +.identicon { + text-align: center; + vertical-align: top; + color: #525252; + background-color: #eee; +} +.identicon.s16 { + font-size: 10px; + line-height: 16px; +} +.identicon.s32 { + font-size: 14px; + line-height: 32px; +} +.identicon.bg1 { + background-color: #ffebee; +} +.identicon.bg2 { + background-color: #f3e5f5; +} +.identicon.bg3 { + background-color: #e8eaf6; +} +.identicon.bg4 { + background-color: #e3f2fd; +} +.identicon.bg5 { + background-color: #e0f2f1; +} +.identicon.bg6 { + background-color: #fbe9e7; +} +.identicon.bg7 { + background-color: #eee; +} .avatar-container { overflow: hidden; display: flex; @@ -1871,10 +1978,6 @@ table.code { margin: 0; align-self: center; } -.avatar-container.s40 { - min-width: 40px; - min-height: 40px; -} .rect-avatar { border-radius: 2px; } @@ -1884,9 +1987,222 @@ table.code { .rect-avatar.s18 { border-radius: 2px; } -.rect-avatar.s40 { +.rect-avatar.s32, +body.sidebar-refactoring + .nav-sidebar-inner-scroll + > div.context-header + a + .avatar-container.rect-avatar + .avatar.s32, +body.sidebar-refactoring + .sidebar-top-level-items + .context-header + a + .avatar-container.rect-avatar + .avatar.s32 { border-radius: 4px; } +#content-body { + display: block; +} +body.gl-dark .navbar-gitlab { + background-color: #fafafa; +} +body.gl-dark .navbar-gitlab .navbar-collapse { + color: #fafafa; +} +body.gl-dark .navbar-gitlab .container-fluid .navbar-toggler { + border-left: 1px solid #b3b3b3; +} +body.gl-dark .navbar-gitlab .container-fluid .navbar-toggler svg { + fill: #fafafa; +} +body.gl-dark .navbar-gitlab .navbar-sub-nav > li.active > a, +body.gl-dark .navbar-gitlab .navbar-sub-nav > li.active > button, +body.gl-dark .navbar-gitlab .navbar-sub-nav > li.dropdown.show > a, +body.gl-dark .navbar-gitlab .navbar-sub-nav > li.dropdown.show > button, +body.gl-dark .navbar-gitlab .navbar-nav > li.active > a, +body.gl-dark .navbar-gitlab .navbar-nav > li.active > button, +body.gl-dark .navbar-gitlab .navbar-nav > li.dropdown.show > a, +body.gl-dark .navbar-gitlab .navbar-nav > li.dropdown.show > button { + color: #fafafa; + background-color: #333; +} +body.gl-dark .navbar-gitlab .navbar-sub-nav { + color: #fafafa; +} +body.gl-dark .navbar-gitlab .nav > li { + color: #fafafa; +} +body.gl-dark .navbar-gitlab .nav > li > a .notification-dot { + border: 2px solid #fafafa; +} +body.gl-dark + .navbar-gitlab + .nav + > li + > a.header-help-dropdown-toggle + .notification-dot { + background-color: #fafafa; +} +body.gl-dark + .navbar-gitlab + .nav + > li + > a.header-user-dropdown-toggle + .header-user-avatar { + border-color: #fafafa; +} +body.gl-dark .navbar-gitlab .nav > li.active > a, +body.gl-dark .navbar-gitlab .nav > li.dropdown.show > a { + color: #fafafa; + background-color: #333; +} +body.gl-dark .navbar-gitlab .nav > li.active > a .notification-dot, +body.gl-dark .navbar-gitlab .nav > li.dropdown.show > a .notification-dot { + border-color: #333; +} +body.gl-dark + .navbar-gitlab + .nav + > li.active + > a.header-help-dropdown-toggle + .notification-dot, +body.gl-dark + .navbar-gitlab + .nav + > li.dropdown.show + > a.header-help-dropdown-toggle + .notification-dot { + background-color: #fafafa; +} +body.gl-dark .search form { + background-color: rgba(250, 250, 250, 0.2); +} +body.gl-dark .search .search-input::-ms-input-placeholder { + color: rgba(250, 250, 250, 0.8); +} +body.gl-dark .search .search-input::placeholder { + color: rgba(250, 250, 250, 0.8); +} +body.gl-dark .search .search-input-wrap .search-icon, +body.gl-dark .search .search-input-wrap .clear-icon { + fill: rgba(250, 250, 250, 0.8); +} +body.gl-dark .nav-sidebar li.active { + box-shadow: inset 4px 0 0 #999; +} +body.gl-dark .nav-sidebar li.active > a { + color: #f0f0f0; +} +body.gl-dark .nav-sidebar li.active .nav-icon-container svg { + fill: #f0f0f0; +} +body.gl-dark .sidebar-top-level-items > li.active .badge.badge-pill { + color: #f0f0f0; +} +body.gl-dark .logo-text svg { + fill: var(--gl-text-color); +} +body.gl-dark .navbar-gitlab { + background-color: var(--gray-50); + box-shadow: 0 1px 0 0 var(--gray-100); +} +body.gl-dark .navbar-gitlab .navbar-sub-nav li.active > a, +body.gl-dark .navbar-gitlab .navbar-sub-nav li.active > button, +body.gl-dark .navbar-gitlab .navbar-sub-nav li.dropdown.show > a, +body.gl-dark .navbar-gitlab .navbar-sub-nav li.dropdown.show > button, +body.gl-dark .navbar-gitlab .navbar-nav li.active > a, +body.gl-dark .navbar-gitlab .navbar-nav li.active > button, +body.gl-dark .navbar-gitlab .navbar-nav li.dropdown.show > a, +body.gl-dark .navbar-gitlab .navbar-nav li.dropdown.show > button { + color: var(--gl-text-color); + background-color: var(--gray-200); +} +body.gl-dark .navbar-gitlab .search form { + background-color: var(--gray-100); + box-shadow: inset 0 0 0 1px var(--border-color); +} +body.gl-dark .navbar-gitlab .search form:active { + background-color: var(--gray-100); + box-shadow: inset 0 0 0 1px var(--blue-200); +} + +body.gl-dark { + --gray-10: #1f1f1f; + --gray-50: #303030; + --gray-100: #404040; + --gray-200: #525252; + --gray-300: #5e5e5e; + --gray-400: #868686; + --gray-500: #999; + --gray-600: #bfbfbf; + --gray-700: #dbdbdb; + --gray-800: #f0f0f0; + --gray-900: #fafafa; + --gray-950: #fff; + --green-50: #0a4020; + --green-100: #0d532a; + --green-200: #24663b; + --green-300: #217645; + --green-400: #108548; + --green-500: #2da160; + --green-600: #52b87a; + --green-700: #91d4a8; + --green-800: #c3e6cd; + --green-900: #ecf4ee; + --green-950: #f1fdf6; + --blue-50: #033464; + --blue-100: #064787; + --blue-200: #0b5cad; + --blue-300: #1068bf; + --blue-400: #1f75cb; + --blue-500: #428fdc; + --blue-600: #63a6e9; + --blue-700: #9dc7f1; + --blue-800: #cbe2f9; + --blue-900: #e9f3fc; + --blue-950: #f2f9ff; + --orange-50: #5c2900; + --orange-100: #703800; + --orange-200: #8f4700; + --orange-300: #9e5400; + --orange-400: #ab6100; + --orange-500: #c17d10; + --orange-600: #d99530; + --orange-700: #e9be74; + --orange-800: #f5d9a8; + --orange-900: #fdf1dd; + --orange-950: #fff4e1; + --red-50: #660e00; + --red-100: #8d1300; + --red-200: #ae1800; + --red-300: #c91c00; + --red-400: #dd2b0e; + --red-500: #ec5941; + --red-600: #f57f6c; + --red-700: #fcb5aa; + --red-800: #fdd4cd; + --red-900: #fcf1ef; + --red-950: #fff4f3; + --indigo-50: #1a1a40; + --indigo-100: #292961; + --indigo-200: #393982; + --indigo-300: #4b4ba3; + --indigo-400: #5b5bbd; + --indigo-500: #6666c4; + --indigo-600: #7c7ccc; + --indigo-700: #a6a6de; + --indigo-800: #d1d1f0; + --indigo-900: #ebebfa; + --indigo-950: #f7f7ff; + --indigo-900-alpha-008: rgba(235, 235, 250, 0.08); + --gl-text-color: #fafafa; + --border-color: #4f4f4f; + --white: #333; + --black: #fff; + --svg-status-bg: #333; +} .tab-width-8 { -moz-tab-size: 8; tab-size: 8; @@ -1902,12 +2218,16 @@ table.code { white-space: nowrap; width: 1px; } +.gl-absolute { + position: absolute; +} .gl-ml-3 { margin-left: 0.5rem; } -.content-wrapper > .alert-wrapper, -#content-body, .modal-dialog { - display: block; +.gl-mx-0\! { + margin-left: 0 !important; + margin-right: 0 !important; } -@import 'cloaking'; + +@import "startup/cloaking"; @include cloak-startup-scss(none); diff --git a/app/assets/stylesheets/startup/startup-general.scss b/app/assets/stylesheets/startup/startup-general.scss index 44da509481d..76071297ea0 100644 --- a/app/assets/stylesheets/startup/startup-general.scss +++ b/app/assets/stylesheets/startup/startup-general.scss @@ -1,3 +1,6 @@ +// DO NOT EDIT! This is auto-generated from "yarn run generate:startup_css" +// Please see the feedback issue for more details and help: +// https://gitlab.com/gitlab-org/gitlab/-/issues/331812 @charset "UTF-8"; *, *::before, @@ -8,12 +11,16 @@ html { font-family: sans-serif; line-height: 1.15; } - header, nav, section { +aside, +header, +nav { display: block; } body { margin: 0; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Noto Sans", Ubuntu, Cantarell, "Helvetica Neue", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, + "Noto Sans", Ubuntu, Cantarell, "Helvetica Neue", sans-serif, + "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-size: 1rem; font-weight: 400; line-height: 1.5; @@ -21,55 +28,29 @@ body { text-align: left; background-color: #fff; } -h1, h2, h3 { +h1 { margin-top: 0; margin-bottom: 0.25rem; } -p { - margin-top: 0; - margin-bottom: 1rem; -} - ul { margin-top: 0; margin-bottom: 1rem; } - ul ul { margin-bottom: 0; } - strong { font-weight: bolder; } -sub { - position: relative; - font-size: 75%; - line-height: 0; - vertical-align: baseline; -} -sub { - bottom: -.25em; -} a { color: #007bff; text-decoration: none; background-color: transparent; } -a:not([href]) { +a:not([href]):not([class]) { color: inherit; text-decoration: none; } -pre, -code { - font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace; - font-size: 1em; -} -pre { - margin-top: 0; - margin-bottom: 1rem; - overflow: auto; -} img { vertical-align: middle; border-style: none; @@ -78,18 +59,11 @@ svg { overflow: hidden; vertical-align: middle; } -table { - border-collapse: collapse; -} -th { - text-align: inherit; -} button { border-radius: 0; } input, -button, -textarea { +button { margin: 0; font-family: inherit; font-size: inherit; @@ -102,21 +76,20 @@ input { button { text-transform: none; } +[role="button"] { + cursor: pointer; +} button:not(:disabled), [type="button"]:not(:disabled), -[type="reset"]:not(:disabled) { +[type="submit"]:not(:disabled) { cursor: pointer; } button::-moz-focus-inner, [type="button"]::-moz-focus-inner, -[type="reset"]::-moz-focus-inner { +[type="submit"]::-moz-focus-inner { padding: 0; border-style: none; } -textarea { - overflow: auto; - resize: vertical; -} [type="search"] { outline-offset: -2px; } @@ -124,81 +97,24 @@ summary { display: list-item; cursor: pointer; } -template { - display: none; -} [hidden] { display: none !important; } -h1, h2, h3, -.h1, .h2, .h3 { +h1, +.h1 { margin-bottom: 0.25rem; font-weight: 600; line-height: 1.2; color: #303030; } -h1, .h1 { +h1, +.h1 { font-size: 2.1875rem; } -h2, .h2 { - font-size: 1.75rem; -} -h3, .h3 { - font-size: 1.53125rem; -} .list-unstyled { padding-left: 0; list-style: none; } -code { - font-size: 90%; - color: #1f1f1f; - word-wrap: break-word; -} -a > code { - color: inherit; -} -pre { - display: block; - font-size: 90%; - color: #303030; -} -pre code { - font-size: inherit; - color: inherit; - word-break: normal; -} -.container { - width: 100%; - padding-right: 15px; - padding-left: 15px; - margin-right: auto; - margin-left: auto; -} - -@media (min-width: 576px) { - .container { - max-width: 540px; - } -} - -@media (min-width: 768px) { - .container { - max-width: 720px; - } -} - -@media (min-width: 992px) { - .container { - max-width: 960px; - } -} - -@media (min-width: 1200px) { - .container { - max-width: 1140px; - } -} .container-fluid { width: 100%; padding-right: 15px; @@ -206,48 +122,7 @@ pre code { margin-right: auto; margin-left: auto; } - -@media (min-width: 576px) { - .container { - max-width: 540px; - } -} - -@media (min-width: 768px) { - .container { - max-width: 720px; - } -} - -@media (min-width: 992px) { - .container { - max-width: 960px; - } -} - -@media (min-width: 1200px) { - .container { - max-width: 1140px; - } -} -.row { - display: flex; - flex-wrap: wrap; - margin-right: -15px; - margin-left: -15px; -} -.table { - width: 100%; - margin-bottom: 0.5rem; - color: #303030; -} -.table th, -.table td { - padding: 0.75rem; - vertical-align: top; - border-top: 1px solid #dbdbdb; -} - .search form { +.form-control { display: block; width: 100%; height: 34px; @@ -261,18 +136,21 @@ pre code { border: 1px solid #dbdbdb; border-radius: 0.25rem; } - @media (prefers-reduced-motion: reduce) { } - .search form:-moz-focusring { +.form-control:-moz-focusring { color: transparent; text-shadow: 0 0 0 #303030; } - .search form::placeholder { +.form-control::-ms-input-placeholder { + color: #5e5e5e; + opacity: 1; +} +.form-control::placeholder { color: #5e5e5e; opacity: 1; } - .search form:disabled { +.form-control:disabled { background-color: #fafafa; opacity: 1; } @@ -281,9 +159,8 @@ pre code { flex-flow: row wrap; align-items: center; } - @media (min-width: 576px) { - .form-inline .search form, .search .form-inline form { + .form-inline .form-control { display: inline-block; width: auto; vertical-align: middle; @@ -295,7 +172,7 @@ pre code { color: #303030; text-align: center; vertical-align: middle; - cursor: pointer; + -moz-user-select: none; user-select: none; background-color: transparent; border: 1px solid transparent; @@ -304,26 +181,24 @@ pre code { line-height: 20px; border-radius: 0.25rem; } - @media (prefers-reduced-motion: reduce) { } -.btn.disabled, .btn:disabled { +.btn:disabled { opacity: 0.65; } -a.btn.disabled { - pointer-events: none; +.btn:not(:disabled):not(.disabled) { + cursor: pointer; } .collapse:not(.show) { display: none; } - .dropdown { position: relative; } - .dropdown-menu-toggle { +.dropdown-menu-toggle { white-space: nowrap; } - .dropdown-menu-toggle::after { +.dropdown-menu-toggle::after { display: inline-block; margin-left: 0.255em; vertical-align: 0.255em; @@ -333,7 +208,7 @@ a.btn.disabled { border-bottom: 0; border-left: 0.3em solid transparent; } - .dropdown-menu-toggle:empty::after { +.dropdown-menu-toggle:empty::after { margin-left: 0; } .dropdown-menu { @@ -355,16 +230,6 @@ a.btn.disabled { border: 1px solid rgba(0, 0, 0, 0.15); border-radius: 0.25rem; } -.dropdown-menu-right { - right: 0; - left: auto; -} - .divider { - height: 0; - margin: 4px 0; - overflow: hidden; - border-top: 1px solid #dbdbdb; -} .dropdown-menu.show { display: block; } @@ -383,7 +248,6 @@ a.btn.disabled { justify-content: space-between; padding: 0.25rem 0.5rem; } -.navbar .container, .navbar .container-fluid { display: flex; flex-wrap: wrap; @@ -414,15 +278,12 @@ a.btn.disabled { border: 1px solid transparent; border-radius: 0.25rem; } - @media (max-width: 575.98px) { - .navbar-expand-sm > .container, .navbar-expand-sm > .container-fluid { padding-right: 0; padding-left: 0; } } - @media (min-width: 576px) { .navbar-expand-sm { flex-flow: row nowrap; @@ -434,7 +295,6 @@ a.btn.disabled { .navbar-expand-sm .navbar-nav .dropdown-menu { position: absolute; } - .navbar-expand-sm > .container, .navbar-expand-sm > .container-fluid { flex-wrap: nowrap; } @@ -468,7 +328,6 @@ a.btn.disabled { vertical-align: baseline; border-radius: 0.25rem; } - @media (prefers-reduced-motion: reduce) { } .badge:empty { @@ -483,10 +342,6 @@ a.btn.disabled { padding-left: 0.6em; border-radius: 10rem; } -.media { - display: flex; - align-items: flex-start; -} .close { float: right; font-size: 1.5rem; @@ -494,55 +349,15 @@ a.btn.disabled { line-height: 1; color: #000; text-shadow: 0 1px 0 #fff; - opacity: .5; + opacity: 0.5; } button.close { padding: 0; background-color: transparent; border: 0; - appearance: none; -} -a.close.disabled { - pointer-events: none; -} -.modal-dialog { - position: relative; - width: auto; - margin: 0.5rem; - pointer-events: none; } - -@media (min-width: 576px) { - .modal-dialog { - max-width: 500px; - margin: 1.75rem auto; - } -} -.bg-transparent { - background-color: transparent !important; -} -.border { - border: 1px solid #dbdbdb !important; -} -.border-top { - border-top: 1px solid #dbdbdb !important; -} -.border-right { - border-right: 1px solid #dbdbdb !important; -} -.border-bottom { - border-bottom: 1px solid #dbdbdb !important; -} -.border-left { - border-left: 1px solid #dbdbdb !important; -} -.rounded { - border-radius: 0.25rem !important; -} -.clearfix::after { - display: block; - clear: both; - content: ""; +.rounded-circle { + border-radius: 50% !important; } .d-none { display: none !important; @@ -553,19 +368,16 @@ a.close.disabled { .d-block { display: block !important; } - @media (min-width: 576px) { .d-sm-none { display: none !important; } } - @media (min-width: 768px) { .d-md-block { display: block !important; } } - @media (min-width: 992px) { .d-lg-none { display: none !important; @@ -574,18 +386,11 @@ a.close.disabled { display: block !important; } } - @media (min-width: 1200px) { .d-xl-block { display: block !important; } } -.flex-wrap { - flex-wrap: wrap !important; -} -.float-right { - float: right !important; -} .sr-only { position: absolute; width: 1px; @@ -600,73 +405,60 @@ a.close.disabled { .m-auto { margin: auto !important; } -.text-nowrap { - white-space: nowrap !important; +.gl-button { + display: inline-flex; } -.visible { - visibility: visible !important; +.gl-button:not(.btn-link):active { + text-decoration: none; } - .search form.focus { +.gl-button.gl-button { + border-width: 0; + padding-top: 0.5rem; + padding-bottom: 0.5rem; + padding-left: 0.75rem; + padding-right: 0.75rem; + background-color: transparent; + line-height: 1rem; color: #303030; + fill: currentColor; + box-shadow: inset 0 0 0 1px #bfbfbf; + justify-content: center; + align-items: center; + font-size: 0.875rem; + border-radius: 0.25rem; +} +.gl-button.gl-button.btn-default { background-color: #fff; - border-color: #80bdff; - outline: 0; - box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); } -.gl-badge { - display: inline-flex; - align-items: center; - font-size: 0.75rem; - font-weight: 400; - line-height: 1rem; - padding-top: 0.25rem; - padding-bottom: 0.25rem; - padding-left: 0.5rem; - padding-right: 0.5rem; +.gl-button.gl-button.btn-default:active, +.gl-button.gl-button.btn-default.active { + box-shadow: inset 0 0 0 2px #5e5e5e, 0 0 0 1px rgba(255, 255, 255, 0.4), + 0 0 0 4px rgba(31, 117, 203, 0.48); outline: none; + background-color: #dbdbdb; } -body, .search form, +body, +.form-control, .search form { font-size: 0.875rem; } button, -html [type='button'], -[type='reset'], -[role='button'] { +html [type="button"], +[type="submit"], +[role="button"] { cursor: pointer; } h1, -.h1, -h2, -.h2, -h3, -.h3 { +.h1 { margin-top: 20px; margin-bottom: 10px; } -input[type='file'] { - line-height: 1; -} - strong { font-weight: bold; } a { color: #1068bf; } -code { - padding: 2px 4px; - color: #1f1f1f; - background-color: #f0f0f0; - border-radius: 4px; -} -.code > code { - background-color: inherit; - padding: unset; -} -table { - border-spacing: 0; -} .hidden { display: none !important; visibility: hidden !important; @@ -674,7 +466,7 @@ table { .hide { display: none; } - .dropdown-menu-toggle::after { +.dropdown-menu-toggle::after { display: none; } .badge:not(.gl-badge) { @@ -684,8 +476,11 @@ table { font-weight: 400; display: inline-block; } -pre code { - white-space: pre-wrap; +.divider { + height: 0; + margin: 4px 0; + overflow: hidden; + border-top: 1px solid #dbdbdb; } .toggle-sidebar-button .collapse-text, .toggle-sidebar-button .icon-chevron-double-lg-left, @@ -701,29 +496,6 @@ html { body { text-decoration-skip: ink; } -.content-wrapper { - margin-top: 40px; - padding-bottom: 100px; -} -.container { - padding-top: 0; - z-index: 5; -} -.container .content { - margin: 0; -} - -@media (max-width: 575.98px) { - .container .content { - margin-top: 20px; - } -} - -@media (max-width: 575.98px) { - .container .container .title { - padding-left: 15px !important; - } -} .btn { border-radius: 4px; font-size: 0.875rem; @@ -735,7 +507,12 @@ body { color: #303030; white-space: nowrap; } -.btn:active, .btn.active { +.btn:active { + background-color: #f0f0f0; + box-shadow: none; +} +.btn:active, +.btn.active { background-color: #eaeaea; border-color: #e3e3e3; color: #303030; @@ -744,8 +521,7 @@ body { height: 15px; width: 15px; } -.btn svg:not(:last-child), -.btn .fa:not(:last-child) { +.btn svg:not(:last-child) { margin-right: 5px; } .badge.badge-pill:not(.gl-badge) { @@ -754,51 +530,10 @@ body { color: #525252; vertical-align: baseline; } -.hint { - font-style: italic; - color: #bfbfbf; -} -.bold { - font-weight: 600; -} -pre.wrap { - word-break: break-word; - white-space: pre-wrap; -} -table a code { - position: relative; - top: -2px; - margin-right: 3px; -} -.loading { - margin: 20px auto; - height: 40px; - color: #525252; - font-size: 32px; - text-align: center; -} -.highlight { - text-shadow: none; -} .chart { overflow: hidden; height: 220px; } -.break-word { - word-wrap: break-word; -} -.center { - text-align: center; -} -.block { - display: block; -} -.flex { - display: flex; -} -.flex-grow { - flex-grow: 1; -} .dropdown { position: relative; } @@ -809,23 +544,22 @@ table a code { max-height: 312px; overflow-y: auto; } - @media (max-width: 575.98px) { .show.dropdown .dropdown-menu { width: 100%; } } - .show.dropdown .dropdown-menu-toggle, +.show.dropdown .dropdown-menu-toggle, .show.dropdown .dropdown-menu-toggle { border-color: #c4c4c4; } -.show.dropdown [data-toggle='dropdown'] { +.show.dropdown [data-toggle="dropdown"] { outline: 0; } .search-input-container .dropdown-menu { margin-top: 11px; } - .dropdown-menu-toggle { +.dropdown-menu-toggle { padding: 6px 8px 6px 10px; background-color: #fff; color: #303030; @@ -835,21 +569,16 @@ table a code { border-radius: 0.25rem; white-space: nowrap; } - .no-outline.dropdown-menu-toggle { +.no-outline.dropdown-menu-toggle { outline: 0; } - .dropdown-menu-toggle .fa { - color: #c4c4c4; -} -.dropdown-menu-toggle { +.dropdown-menu-toggle.dropdown-menu-toggle { + justify-content: flex-start; + overflow: hidden; padding-right: 25px; position: relative; - width: 160px; text-overflow: ellipsis; - overflow: hidden; -} -.dropdown-menu-toggle .fa { - position: absolute; + width: 160px; } .dropdown-menu { display: none; @@ -896,6 +625,13 @@ table a code { text-align: left; width: 100%; } +.dropdown-menu li > a:active, +.dropdown-menu li button:active { + background-color: #eee; + color: #303030; + outline: 0; + text-decoration: none; +} .dropdown-menu .divider { height: 1px; margin: 0.25rem 0; @@ -905,66 +641,39 @@ table a code { .dropdown-menu .badge.badge-pill + span:not(.badge):not(.badge-pill) { margin-right: 40px; } -.dropdown-select { - width: 300px; -} - -@media (max-width: 767.98px) { - .dropdown-select { - width: 100%; - } -} -.dropdown-content { - max-height: 252px; - overflow-y: auto; -} -.dropdown-loading { - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - display: none; - z-index: 9; - background-color: rgba(255, 255, 255, 0.6); - font-size: 28px; -} -.dropdown-loading .fa { - position: absolute; - top: 50%; - left: 50%; - margin-top: -14px; - margin-left: -14px; -} - @media (max-width: 575.98px) { .navbar-gitlab li.dropdown { position: static; } + .navbar-gitlab li.dropdown.user-counter { + margin-left: 8px !important; + } + .navbar-gitlab li.dropdown.user-counter > a { + padding: 0 4px !important; + } header.navbar-gitlab .dropdown .dropdown-menu { width: 100%; min-width: 100%; } } - @media (max-width: 767.98px) { .dropdown-menu-toggle { width: 100%; } } -textarea { - resize: vertical; -} input { border-radius: 0.25rem; color: #303030; background-color: #fff; } - .search form { +.form-control { border-radius: 4px; padding: 6px 10px; } - .search form::placeholder { +.form-control::-ms-input-placeholder { + color: #868686; +} +.form-control::placeholder { color: #868686; } .navbar-gitlab { @@ -973,7 +682,6 @@ input { margin-bottom: 0; min-height: 40px; border: 0; - border-bottom: 1px solid #dbdbdb; position: fixed; top: 0; left: 0; @@ -1023,9 +731,6 @@ input { .navbar-gitlab .header-content .title img + .logo-text { margin-left: 8px; } -.navbar-gitlab .header-content .title.wrap { - white-space: normal; -} .navbar-gitlab .header-content .title a { display: flex; align-items: center; @@ -1033,9 +738,6 @@ input { margin: 5px 2px 5px -8px; border-radius: 4px; } -.navbar-gitlab .header-content .dropdown.open > a { - border-bottom-color: #fff; -} .navbar-gitlab .header-content .navbar-collapse > ul.nav > li:not(.d-none) { margin: 0 2px; } @@ -1044,7 +746,6 @@ input { border-top: 0; padding: 0; } - @media (max-width: 575.98px) { .navbar-gitlab .navbar-collapse { flex: 1 1 auto; @@ -1053,7 +754,6 @@ input { .navbar-gitlab .navbar-collapse .nav { flex-wrap: nowrap; } - @media (max-width: 575.98px) { .navbar-gitlab .navbar-collapse .nav > li:not(.d-none) a { margin-left: 0; @@ -1076,7 +776,10 @@ input { text-align: center; color: currentColor; } - +.navbar-gitlab .container-fluid .navbar-toggler.active { + color: currentColor; + background-color: transparent; +} @media (max-width: 575.98px) { .navbar-gitlab .container-fluid .navbar-nav { display: flex; @@ -1084,11 +787,14 @@ input { flex-direction: row; } } -.navbar-gitlab .container-fluid .navbar-nav li .badge.badge-pill { +.navbar-gitlab + .container-fluid + .navbar-nav + li + .badge.badge-pill:not(.merge-request-badge) { box-shadow: none; font-weight: 600; } - @media (max-width: 575.98px) { .navbar-gitlab .container-fluid .nav > li.header-user { padding-left: 10px; @@ -1100,7 +806,6 @@ input { padding: 6px 8px; height: 32px; } - @media (max-width: 575.98px) { .navbar-gitlab .container-fluid .nav > li > a { padding: 0; @@ -1109,7 +814,12 @@ input { .navbar-gitlab .container-fluid .nav > li > a.header-user-dropdown-toggle { margin-left: 2px; } -.navbar-gitlab .container-fluid .nav > li > a.header-user-dropdown-toggle .header-user-avatar { +.navbar-gitlab + .container-fluid + .nav + > li + > a.header-user-dropdown-toggle + .header-user-avatar { margin-right: 0; } .navbar-gitlab .container-fluid .nav > li .header-new-dropdown-toggle { @@ -1130,7 +840,9 @@ input { height: 32px; font-weight: 600; } +.navbar-sub-nav > li .top-nav-toggle, .navbar-sub-nav > li > button, +.navbar-nav > li .top-nav-toggle, .navbar-nav > li > button { background: transparent; border: 0; @@ -1168,31 +880,25 @@ input { font-weight: 400; margin-left: -6px; font-size: 11px; - color: #fff; + color: var(--gray-950, #fff); padding: 0 5px; line-height: 12px; border-radius: 7px; box-shadow: 0 1px 0 rgba(76, 78, 84, 0.2); } -.title-container .badge.badge-pill.green-badge, -.navbar-nav .badge.badge-pill.green-badge { - background-color: #108548; +.title-container .badge.badge-pill:not(.merge-request-badge).green-badge, +.navbar-nav .badge.badge-pill:not(.merge-request-badge).green-badge { + background-color: var(--green-400, #2da160); } -.title-container .badge.badge-pill.merge-requests-count, -.navbar-nav .badge.badge-pill.merge-requests-count { - background-color: #de7e00; +.title-container + .badge.badge-pill:not(.merge-request-badge).merge-requests-count, +.navbar-nav .badge.badge-pill:not(.merge-request-badge).merge-requests-count { + background-color: var(--orange-400, #c17d10); } -.title-container .badge.badge-pill.todos-count, -.navbar-nav .badge.badge-pill.todos-count { - background-color: #1f75cb; +.title-container .badge.badge-pill:not(.merge-request-badge).todos-count, +.navbar-nav .badge.badge-pill:not(.merge-request-badge).todos-count { + background-color: var(--blue-400, #428fdc); } -.title-container .canary-badge .badge, -.navbar-nav .canary-badge .badge { - font-size: 12px; - line-height: 16px; - padding: 0 0.5rem; -} - @media (max-width: 575.98px) { .navbar-gitlab .container-fluid { font-size: 18px; @@ -1219,7 +925,7 @@ input { } .header-user.show .dropdown-menu { margin-top: 4px; - color: #303030; + color: var(--gl-text-color, #303030); left: auto; max-height: 445px; } @@ -1232,30 +938,32 @@ input { border-radius: 50%; border: 1px solid #f5f5f5; } -.media { - display: flex; - align-items: flex-start; +.notification-dot { + background-color: #d99530; + height: 12px; + width: 12px; + margin-top: -15px; + pointer-events: none; + visibility: hidden; } -.card { - margin-bottom: 16px; +.top-nav-toggle .dropdown-icon { + margin-right: 0.5rem; } -.content-wrapper { - width: 100%; +.tanuki-logo .tanuki-left-ear, +.tanuki-logo .tanuki-right-ear, +.tanuki-logo .tanuki-nose { + fill: #e24329; } -.content-wrapper .container-fluid { - padding: 0 16px; +.tanuki-logo .tanuki-left-eye, +.tanuki-logo .tanuki-right-eye { + fill: #fc6d26; } - -@media (min-width: 768px) { - .page-with-contextual-sidebar { - padding-left: 50px; - } +.tanuki-logo .tanuki-left-cheek, +.tanuki-logo .tanuki-right-cheek { + fill: #fca326; } - -@media (min-width: 1200px) { - .page-with-contextual-sidebar { - padding-left: 220px; - } +.card { + margin-bottom: 16px; } .context-header { position: relative; @@ -1282,9 +990,20 @@ input { overflow: hidden; text-overflow: ellipsis; } -.context-header .sidebar-context-title.text-secondary { - font-weight: normal; - font-size: 0.8em; +@media (min-width: 768px) { + .page-with-contextual-sidebar { + padding-left: 50px; + } +} +@media (min-width: 1200px) { + .page-with-contextual-sidebar { + padding-left: 220px; + } +} +@media (min-width: 768px) { + .page-with-icon-sidebar { + padding-left: 50px; + } } .nav-sidebar { position: fixed; @@ -1297,7 +1016,6 @@ input { box-shadow: inset -1px 0 0 #dbdbdb; transform: translate3d(0, 0, 0); } - @media (min-width: 576px) and (max-width: 576px) { .nav-sidebar:not(.sidebar-collapsed-desktop) { box-shadow: inset -1px 0 0 #dbdbdb, 2px 1px 3px rgba(0, 0, 0, 0.1); @@ -1310,7 +1028,6 @@ input { overflow-x: hidden; } .nav-sidebar.sidebar-collapsed-desktop .badge.badge-pill:not(.fly-out-badge), -.nav-sidebar.sidebar-collapsed-desktop .sidebar-context-title, .nav-sidebar.sidebar-collapsed-desktop .nav-item-name { border: 0; clip: rect(0, 0, 0, 0); @@ -1331,9 +1048,6 @@ input { .nav-sidebar.sidebar-collapsed-desktop .avatar-container { margin: 0 auto; } -.nav-sidebar.sidebar-expanded-mobile { - left: 0; -} .nav-sidebar a { text-decoration: none; } @@ -1356,7 +1070,6 @@ input { .nav-sidebar li.active > a { font-weight: 600; } - @media (max-width: 767.98px) { .nav-sidebar { left: -220px; @@ -1373,7 +1086,6 @@ input { height: 16px; width: 16px; } - @media (min-width: 768px) and (max-width: 1199px) { .nav-sidebar:not(.sidebar-expanded-mobile) { width: 50px; @@ -1381,8 +1093,8 @@ input { .nav-sidebar:not(.sidebar-expanded-mobile) .nav-sidebar-inner-scroll { overflow-x: hidden; } - .nav-sidebar:not(.sidebar-expanded-mobile) .badge.badge-pill:not(.fly-out-badge), - .nav-sidebar:not(.sidebar-expanded-mobile) .sidebar-context-title, + .nav-sidebar:not(.sidebar-expanded-mobile) + .badge.badge-pill:not(.fly-out-badge), .nav-sidebar:not(.sidebar-expanded-mobile) .nav-item-name { border: 0; clip: rect(0, 0, 0, 0); @@ -1410,7 +1122,21 @@ input { .nav-sidebar:not(.sidebar-expanded-mobile) .context-header a { padding: 10px 4px; } - .nav-sidebar:not(.sidebar-expanded-mobile) .sidebar-top-level-items > li .sidebar-sub-level-items:not(.flyout-list) { + .nav-sidebar:not(.sidebar-expanded-mobile) .sidebar-context-title { + border: 0; + clip: rect(0, 0, 0, 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + white-space: nowrap; + width: 1px; + } + .nav-sidebar:not(.sidebar-expanded-mobile) + .sidebar-top-level-items + > li + .sidebar-sub-level-items:not(.flyout-list) { display: none; } .nav-sidebar:not(.sidebar-expanded-mobile) .nav-icon-container { @@ -1420,11 +1146,17 @@ input { padding: 16px; width: 49px; } - .nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button .collapse-text, - .nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button .icon-chevron-double-lg-left { + .nav-sidebar:not(.sidebar-expanded-mobile) + .toggle-sidebar-button + .collapse-text, + .nav-sidebar:not(.sidebar-expanded-mobile) + .toggle-sidebar-button + .icon-chevron-double-lg-left { display: none; } - .nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button .icon-chevron-double-lg-right { + .nav-sidebar:not(.sidebar-expanded-mobile) + .toggle-sidebar-button + .icon-chevron-double-lg-right { display: block; margin: 0; } @@ -1441,10 +1173,12 @@ input { .sidebar-sub-level-items > li a { padding: 8px 16px 8px 40px; } +.sidebar-sub-level-items > li.active a { + background: rgba(0, 0, 0, 0.04); +} .sidebar-top-level-items { margin-bottom: 60px; } - @media (min-width: 576px) { .sidebar-top-level-items > li > a { margin-right: 1px; @@ -1464,23 +1198,28 @@ input { .sidebar-top-level-items > li.active .badge.badge-pill { font-weight: 600; } -.sidebar-top-level-items > li.active .sidebar-sub-level-items:not(.is-fly-out-only) { +.sidebar-top-level-items + > li.active + .sidebar-sub-level-items:not(.is-fly-out-only) { display: block; } .toggle-sidebar-button, .close-nav-button { - width: 219px; - position: fixed; height: 48px; - bottom: 0; padding: 0 16px; background-color: #fafafa; border: 0; - border-top: 1px solid #dbdbdb; color: #666; display: flex; align-items: center; } +.toggle-sidebar-button, +.close-nav-button { + position: fixed; + bottom: 0; + width: 219px; + border-top: 1px solid #dbdbdb; +} .toggle-sidebar-button svg, .close-nav-button svg { margin-right: 8px; @@ -1500,7 +1239,21 @@ input { .sidebar-collapsed-desktop .context-header a { padding: 10px 4px; } -.sidebar-collapsed-desktop .sidebar-top-level-items > li .sidebar-sub-level-items:not(.flyout-list) { +.sidebar-collapsed-desktop .sidebar-context-title { + border: 0; + clip: rect(0, 0, 0, 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + white-space: nowrap; + width: 1px; +} +.sidebar-collapsed-desktop + .sidebar-top-level-items + > li + .sidebar-sub-level-items:not(.flyout-list) { display: none; } .sidebar-collapsed-desktop .nav-icon-container { @@ -1514,7 +1267,9 @@ input { .sidebar-collapsed-desktop .toggle-sidebar-button .icon-chevron-double-lg-left { display: none; } -.sidebar-collapsed-desktop .toggle-sidebar-button .icon-chevron-double-lg-right { +.sidebar-collapsed-desktop + .toggle-sidebar-button + .icon-chevron-double-lg-right { display: block; margin: 0; } @@ -1530,7 +1285,6 @@ input { .close-nav-button { display: none; } - @media (max-width: 767.98px) { .close-nav-button { display: flex; @@ -1539,128 +1293,500 @@ input { display: none; } } -table.table { - margin-bottom: 16px; +body.sidebar-refactoring.ui-indigo .nav-sidebar li.active > a { + color: #2f2a6b; } -table.table .dropdown-menu a { - text-decoration: none; +body.sidebar-refactoring.ui-indigo + .nav-sidebar + li.active + .nav-icon-container + svg { + fill: #2f2a6b; } -table.table .success, -table.table .info { - color: #fff; +body.sidebar-refactoring .nav-sidebar { + box-shadow: none; } -table.table .success a:not(.btn), -table.table .info a:not(.btn) { - text-decoration: underline; - color: #fff; +body.sidebar-refactoring .nav-sidebar li.active { + background-color: transparent; + box-shadow: none !important; +} +@media (min-width: 768px) { + body.sidebar-refactoring .page-with-contextual-sidebar { + padding-left: 50px; + } } -pre { - font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace; +@media (min-width: 1200px) { + body.sidebar-refactoring .page-with-contextual-sidebar { + padding-left: 220px; + } +} +@media (min-width: 768px) { + body.sidebar-refactoring .page-with-icon-sidebar { + padding-left: 50px; + } +} +body.sidebar-refactoring .nav-sidebar { + position: fixed; + z-index: 600; + width: 220px; + top: 40px; + bottom: 0; + left: 0; + background-color: #f0f0f0; + transform: translate3d(0, 0, 0); +} +@media (min-width: 576px) and (max-width: 576px) { + body.sidebar-refactoring .nav-sidebar:not(.sidebar-collapsed-desktop) { + box-shadow: inset -1px 0 0 #dbdbdb, 2px 1px 3px rgba(0, 0, 0, 0.1); + } +} +body.sidebar-refactoring .nav-sidebar.sidebar-collapsed-desktop { + width: 50px; +} +body.sidebar-refactoring + .nav-sidebar.sidebar-collapsed-desktop + .nav-sidebar-inner-scroll { + overflow-x: hidden; +} +body.sidebar-refactoring + .nav-sidebar.sidebar-collapsed-desktop + .badge.badge-pill:not(.fly-out-badge), +body.sidebar-refactoring .nav-sidebar.sidebar-collapsed-desktop .nav-item-name { + border: 0; + clip: rect(0, 0, 0, 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + white-space: nowrap; + width: 1px; +} +body.sidebar-refactoring + .nav-sidebar.sidebar-collapsed-desktop + .sidebar-top-level-items + > li + > a { + min-height: 45px; +} +body.sidebar-refactoring + .nav-sidebar.sidebar-collapsed-desktop + .fly-out-top-item { display: block; - padding: 8px 12px; - margin: 0 0 8px; - font-size: 13px; - word-break: break-all; - word-wrap: break-word; +} +body.sidebar-refactoring + .nav-sidebar.sidebar-collapsed-desktop + .avatar-container { + margin: 0 auto; +} +body.sidebar-refactoring .nav-sidebar a { + text-decoration: none; + line-height: 1rem; + color: #2f2a6b; +} +body.sidebar-refactoring .nav-sidebar li { + white-space: nowrap; +} +body.sidebar-refactoring .nav-sidebar li .nav-item-name { + flex: 1; +} +body.sidebar-refactoring .nav-sidebar li > a { + padding-left: 0.75rem; + padding-right: 0.75rem; + padding-top: 0.5rem; + padding-bottom: 0.5rem; + display: flex; + align-items: center; + border-radius: 0.25rem; + width: auto; + margin: 1px 4px; +} +body.sidebar-refactoring .nav-sidebar li.active > a { + font-weight: 600; +} +body.sidebar-refactoring .nav-sidebar li.active > a:not(.has-sub-items) { + background-color: rgba(41, 41, 97, 0.08); +} +body.sidebar-refactoring .nav-sidebar ul { + padding-left: 0; + list-style: none; +} +@media (max-width: 767.98px) { + body.sidebar-refactoring .nav-sidebar { + left: -220px; + } +} +body.sidebar-refactoring .nav-sidebar .nav-icon-container { + display: flex; + margin-right: 8px; +} +body.sidebar-refactoring .nav-sidebar .fly-out-top-item { + display: none; +} +@media (min-width: 768px) and (max-width: 1199px) { + body.sidebar-refactoring .nav-sidebar:not(.sidebar-expanded-mobile) { + width: 50px; + } + body.sidebar-refactoring + .nav-sidebar:not(.sidebar-expanded-mobile) + .nav-sidebar-inner-scroll { + overflow-x: hidden; + } + body.sidebar-refactoring + .nav-sidebar:not(.sidebar-expanded-mobile) + .badge.badge-pill:not(.fly-out-badge), + body.sidebar-refactoring + .nav-sidebar:not(.sidebar-expanded-mobile) + .nav-item-name { + border: 0; + clip: rect(0, 0, 0, 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + white-space: nowrap; + width: 1px; + } + body.sidebar-refactoring + .nav-sidebar:not(.sidebar-expanded-mobile) + .sidebar-top-level-items + > li + > a { + min-height: 45px; + } + body.sidebar-refactoring + .nav-sidebar:not(.sidebar-expanded-mobile) + .fly-out-top-item { + display: block; + } + body.sidebar-refactoring + .nav-sidebar:not(.sidebar-expanded-mobile) + .avatar-container { + margin: 0 auto; + } + body.sidebar-refactoring + .nav-sidebar:not(.sidebar-expanded-mobile) + .context-header { + height: 60px; + width: 50px; + } + body.sidebar-refactoring + .nav-sidebar:not(.sidebar-expanded-mobile) + .context-header + a { + padding: 10px 4px; + } + body.sidebar-refactoring + .nav-sidebar:not(.sidebar-expanded-mobile) + .sidebar-context-title { + border: 0; + clip: rect(0, 0, 0, 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + white-space: nowrap; + width: 1px; + } + body.sidebar-refactoring + .nav-sidebar:not(.sidebar-expanded-mobile) + .sidebar-top-level-items + > li + .sidebar-sub-level-items:not(.flyout-list) { + display: none; + } + body.sidebar-refactoring + .nav-sidebar:not(.sidebar-expanded-mobile) + .nav-icon-container { + margin-right: 0; + } + body.sidebar-refactoring + .nav-sidebar:not(.sidebar-expanded-mobile) + .toggle-sidebar-button { + padding: 16px; + width: 49px; + } + body.sidebar-refactoring + .nav-sidebar:not(.sidebar-expanded-mobile) + .toggle-sidebar-button + .collapse-text, + body.sidebar-refactoring + .nav-sidebar:not(.sidebar-expanded-mobile) + .toggle-sidebar-button + .icon-chevron-double-lg-left { + display: none; + } + body.sidebar-refactoring + .nav-sidebar:not(.sidebar-expanded-mobile) + .toggle-sidebar-button + .icon-chevron-double-lg-right { + display: block; + margin: 0; + } +} +body.sidebar-refactoring .nav-sidebar-inner-scroll { + height: 100%; + width: 100%; + overflow: auto; +} +body.sidebar-refactoring .nav-sidebar-inner-scroll > div.context-header { + margin-top: 0.25rem; +} +body.sidebar-refactoring .nav-sidebar-inner-scroll > div.context-header a { + padding-left: 0.75rem; + padding-right: 0.75rem; + padding-top: 0.5rem; + padding-bottom: 0.5rem; + display: flex; + align-items: center; + border-radius: 0.25rem; + width: auto; + margin: 1px 4px; + padding: 0.25rem; + margin-bottom: 0.25rem; +} +body.sidebar-refactoring + .nav-sidebar-inner-scroll + > div.context-header + a + .avatar-container { + font-weight: 400; + flex: none; + box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.08); +} +body.sidebar-refactoring + .nav-sidebar-inner-scroll + > div.context-header + a + .avatar-container.rect-avatar { + border-style: none; +} +body.sidebar-refactoring + .nav-sidebar-inner-scroll + > div.context-header + a + .avatar-container.rect-avatar + .avatar.s32 { + color: #303030; + box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.08); +} +body.sidebar-refactoring + .nav-sidebar-inner-scroll + > div.context-header + a + .sidebar-context-title { + color: #2f2a6b; +} +body.sidebar-refactoring .sidebar-top-level-items { + margin-top: 0.25rem; + margin-bottom: 60px; +} +body.sidebar-refactoring .sidebar-top-level-items .context-header a { + padding: 0.25rem; + margin-bottom: 0.25rem; +} +body.sidebar-refactoring + .sidebar-top-level-items + .context-header + a + .avatar-container { + font-weight: 400; + flex: none; + box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.08); +} +body.sidebar-refactoring + .sidebar-top-level-items + .context-header + a + .avatar-container.rect-avatar { + border-style: none; +} +body.sidebar-refactoring + .sidebar-top-level-items + .context-header + a + .avatar-container.rect-avatar + .avatar.s32 { color: #303030; + box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.08); +} +body.sidebar-refactoring + .sidebar-top-level-items + .context-header + a + .sidebar-context-title { + color: #2f2a6b; +} +body.sidebar-refactoring .sidebar-top-level-items > li .badge.badge-pill { + border-radius: 0.5rem; + padding-top: 0.125rem; + padding-bottom: 0.125rem; + padding-left: 0.5rem; + padding-right: 0.5rem; + background-color: #cbe2f9; + color: #0b5cad; +} +body.sidebar-refactoring + .sidebar-top-level-items + > li.active + .sidebar-sub-level-items:not(.is-fly-out-only) { + display: block; +} +body.sidebar-refactoring + .sidebar-top-level-items + > li.active + .badge.badge-pill { + font-weight: 400; + color: #0b5cad; +} +body.sidebar-refactoring .sidebar-sub-level-items { + padding-bottom: 0; + display: none; +} +body.sidebar-refactoring .sidebar-sub-level-items:not(.fly-out-list) li > a { + padding-left: 2.25rem; +} +body.sidebar-refactoring .toggle-sidebar-button, +body.sidebar-refactoring .close-nav-button { + height: 48px; + padding: 0 16px; background-color: #fafafa; - border: 1px solid #dbdbdb; - border-radius: 2px; + border: 0; + color: #666; + display: flex; + align-items: center; + background-color: #f0f0f0; + color: #2f2a6b; +} +body.sidebar-refactoring .toggle-sidebar-button .collapse-text, +body.sidebar-refactoring .toggle-sidebar-button .icon-chevron-double-lg-left, +body.sidebar-refactoring .toggle-sidebar-button .icon-chevron-double-lg-right, +body.sidebar-refactoring .close-nav-button .collapse-text, +body.sidebar-refactoring .close-nav-button .icon-chevron-double-lg-left, +body.sidebar-refactoring .close-nav-button .icon-chevron-double-lg-right { + color: inherit; +} +body.sidebar-refactoring .toggle-sidebar-button, +body.sidebar-refactoring .close-nav-button { + position: fixed; + bottom: 0; + width: 219px; + border-top: 1px solid #dbdbdb; +} +body.sidebar-refactoring .toggle-sidebar-button svg, +body.sidebar-refactoring .close-nav-button svg { + margin-right: 8px; +} +body.sidebar-refactoring .toggle-sidebar-button .icon-chevron-double-lg-right, +body.sidebar-refactoring .close-nav-button .icon-chevron-double-lg-right { + display: none; +} +body.sidebar-refactoring .collapse-text { + white-space: nowrap; + overflow: hidden; +} +body.sidebar-refactoring .sidebar-collapsed-desktop .context-header { + height: 60px; + width: 50px; +} +body.sidebar-refactoring .sidebar-collapsed-desktop .context-header a { + padding: 10px 4px; } -.monospace { - font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace; +body.sidebar-refactoring .sidebar-collapsed-desktop .sidebar-context-title { + border: 0; + clip: rect(0, 0, 0, 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + white-space: nowrap; + width: 1px; +} +body.sidebar-refactoring + .sidebar-collapsed-desktop + .sidebar-top-level-items + > li + .sidebar-sub-level-items:not(.flyout-list) { + display: none; +} +body.sidebar-refactoring .sidebar-collapsed-desktop .nav-icon-container { + margin-right: 0; +} +body.sidebar-refactoring .sidebar-collapsed-desktop .toggle-sidebar-button { + padding: 16px; + width: 49px; +} +body.sidebar-refactoring + .sidebar-collapsed-desktop + .toggle-sidebar-button + .collapse-text, +body.sidebar-refactoring + .sidebar-collapsed-desktop + .toggle-sidebar-button + .icon-chevron-double-lg-left { + display: none; +} +body.sidebar-refactoring + .sidebar-collapsed-desktop + .toggle-sidebar-button + .icon-chevron-double-lg-right { + display: block; + margin: 0; +} +body.sidebar-refactoring .close-nav-button { + display: none; +} +@media (max-width: 767.98px) { + body.sidebar-refactoring .close-nav-button { + display: flex; + } + body.sidebar-refactoring .toggle-sidebar-button { + display: none; + } } -input::-moz-placeholder, -textarea::-moz-placeholder { +input::-moz-placeholder { color: #868686; opacity: 1; } -input::-ms-input-placeholder, -textarea::-ms-input-placeholder { +input::-ms-input-placeholder { color: #868686; } -input:-ms-input-placeholder, -textarea:-ms-input-placeholder { +input:-ms-input-placeholder { color: #868686; } svg { fill: currentColor; } - svg.s12 { width: 12px; height: 12px; } - svg.s16 { width: 16px; height: 16px; } - svg.s18 { width: 18px; height: 18px; } - +svg.s32 { + width: 32px; + height: 32px; +} svg.s12 { vertical-align: -1px; } - svg.s16 { vertical-align: -3px; } -.sr-only { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - border: 0; -} -table.code { - width: 100%; - font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace; - border: 0; - border-collapse: separate; - margin: 0; - padding: 0; - table-layout: fixed; - border-radius: 0 0 4px 4px; -} -.frame .badge.badge-pill { - position: absolute; - background-color: #428fdc; - color: #fff; - border: #fff 1px solid; - min-height: 16px; - padding: 5px 8px; - border-radius: 12px; -} -.frame .badge.badge-pill { - transform: translate(-50%, -50%); -} -.color-label { - padding: 0 0.5rem; - line-height: 16px; - border-radius: 100px; - color: #fff; -} -.label-link { - display: inline-flex; - vertical-align: text-bottom; -} -.milestones { - padding: 8px; - margin-top: 8px; - border-radius: 4px; - background-color: #dbdbdb; -} .search { margin: 0 8px; } .search form { + display: block; margin: 0; padding: 4px; width: 200px; @@ -1669,7 +1795,6 @@ table.code { border: 0; border-radius: 4px; } - @media (min-width: 1200px) { .search form { width: 320px; @@ -1713,45 +1838,39 @@ table.code { max-height: 400px; overflow: auto; } - @media (min-width: 1200px) { .search .search-input-wrap .dropdown-menu { width: 320px; } } -.search .search-input-wrap .dropdown-content { - max-height: 382px; -} -.settings { - border-top: 1px solid #dbdbdb; -} -.settings:first-of-type { - margin-top: 10px; - border: 0; -} -.settings + div .settings:first-of-type { - margin-top: 0; - border-top: 1px solid #dbdbdb; +.search .identicon { + flex-basis: 16px; + flex-shrink: 0; + margin-right: 4px; } -.avatar, .avatar-container { +.avatar, +.avatar-container { float: left; margin-right: 16px; border-radius: 50%; border: 1px solid #f5f5f5; } -.s16.avatar, .s16.avatar-container { +.avatar.s16, +.avatar-container.s16 { width: 16px; height: 16px; margin-right: 8px; } -.s18.avatar, .s18.avatar-container { +.avatar.s18, +.avatar-container.s18 { width: 18px; height: 18px; margin-right: 8px; } -.s40.avatar, .s40.avatar-container { - width: 40px; - height: 40px; +.avatar.s32, +.avatar-container.s32 { + width: 32px; + height: 32px; margin-right: 8px; } .avatar { @@ -1763,15 +1882,45 @@ table.code { overflow: hidden; border-color: rgba(0, 0, 0, 0.1); } -.avatar.center { - font-size: 14px; - line-height: 1.8em; - text-align: center; -} .avatar.avatar-tile { border-radius: 0; border: 0; } +.identicon { + text-align: center; + vertical-align: top; + color: #525252; + background-color: #eee; +} +.identicon.s16 { + font-size: 10px; + line-height: 16px; +} +.identicon.s32 { + font-size: 14px; + line-height: 32px; +} +.identicon.bg1 { + background-color: #ffebee; +} +.identicon.bg2 { + background-color: #f3e5f5; +} +.identicon.bg3 { + background-color: #e8eaf6; +} +.identicon.bg4 { + background-color: #e3f2fd; +} +.identicon.bg5 { + background-color: #e0f2f1; +} +.identicon.bg6 { + background-color: #fbe9e7; +} +.identicon.bg7 { + background-color: #eee; +} .avatar-container { overflow: hidden; display: flex; @@ -1790,10 +1939,6 @@ table.code { margin: 0; align-self: center; } -.avatar-container.s40 { - min-width: 40px; - min-height: 40px; -} .rect-avatar { border-radius: 2px; } @@ -1803,9 +1948,25 @@ table.code { .rect-avatar.s18 { border-radius: 2px; } -.rect-avatar.s40 { +.rect-avatar.s32, +body.sidebar-refactoring + .nav-sidebar-inner-scroll + > div.context-header + a + .avatar-container.rect-avatar + .avatar.s32, +body.sidebar-refactoring + .sidebar-top-level-items + .context-header + a + .avatar-container.rect-avatar + .avatar.s32 { border-radius: 4px; } +#content-body { + display: block; +} + .tab-width-8 { -moz-tab-size: 8; tab-size: 8; @@ -1821,12 +1982,16 @@ table.code { white-space: nowrap; width: 1px; } +.gl-absolute { + position: absolute; +} .gl-ml-3 { margin-left: 0.5rem; } -.content-wrapper > .alert-wrapper, -#content-body, .modal-dialog { - display: block; +.gl-mx-0\! { + margin-left: 0 !important; + margin-right: 0 !important; } -@import 'cloaking'; + +@import "startup/cloaking"; @include cloak-startup-scss(none); diff --git a/app/assets/stylesheets/startup/startup-signin.scss b/app/assets/stylesheets/startup/startup-signin.scss index 6b78abdb5e0..ebb4f32054f 100644 --- a/app/assets/stylesheets/startup/startup-signin.scss +++ b/app/assets/stylesheets/startup/startup-signin.scss @@ -1,3 +1,6 @@ +// DO NOT EDIT! This is auto-generated from "yarn run generate:startup_css" +// Please see the feedback issue for more details and help: +// https://gitlab.com/gitlab-org/gitlab/-/issues/331812 @charset "UTF-8"; *, *::before, @@ -8,12 +11,14 @@ html { font-family: sans-serif; line-height: 1.15; } - header, nav, section { +header { display: block; } body { margin: 0; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Noto Sans", Ubuntu, Cantarell, "Helvetica Neue", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, + "Noto Sans", Ubuntu, Cantarell, "Helvetica Neue", sans-serif, + "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-size: 1rem; font-weight: 400; line-height: 1.5; @@ -26,7 +31,8 @@ hr { height: 0; overflow: visible; } -h1, h2, h3 { +h1, +h3 { margin-top: 0; margin-bottom: 0.25rem; } @@ -39,47 +45,20 @@ address { font-style: normal; line-height: inherit; } - -ul { - margin-top: 0; - margin-bottom: 1rem; -} - -ul ul { - margin-bottom: 0; -} - -strong { - font-weight: bolder; -} -sub { - position: relative; - font-size: 75%; - line-height: 0; - vertical-align: baseline; -} -sub { - bottom: -.25em; -} a { color: #007bff; text-decoration: none; background-color: transparent; } -a:not([href]) { +a:not([href]):not([class]) { color: inherit; text-decoration: none; } -pre, code { - font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace; + font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", + "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace; font-size: 1em; } -pre { - margin-top: 0; - margin-bottom: 1rem; - overflow: auto; -} img { vertical-align: middle; border-style: none; @@ -88,89 +67,54 @@ svg { overflow: hidden; vertical-align: middle; } -table { - border-collapse: collapse; -} -th { - text-align: inherit; -} label { display: inline-block; margin-bottom: 0.5rem; } -button { - border-radius: 0; -} -input, -button, -textarea { +input { margin: 0; font-family: inherit; font-size: inherit; line-height: inherit; } -button, input { overflow: visible; } -button { - text-transform: none; -} -button:not(:disabled), -[type="button"]:not(:disabled), -[type="reset"]:not(:disabled), [type="submit"]:not(:disabled) { cursor: pointer; } -button::-moz-focus-inner, -[type="button"]::-moz-focus-inner, -[type="reset"]::-moz-focus-inner, [type="submit"]::-moz-focus-inner { padding: 0; border-style: none; } - -input[type="checkbox"] { - box-sizing: border-box; - padding: 0; -} -textarea { - overflow: auto; - resize: vertical; -} fieldset { min-width: 0; padding: 0; margin: 0; border: 0; } -[type="search"] { - outline-offset: -2px; -} summary { display: list-item; cursor: pointer; } -template { - display: none; -} [hidden] { display: none !important; } -h1, h2, h3, -.h1, .h2, .h3 { +h1, +h3, +.h1, +.h3 { margin-bottom: 0.25rem; font-weight: 600; line-height: 1.2; color: #303030; } -h1, .h1 { +h1, +.h1 { font-size: 2.1875rem; } -h2, .h2 { - font-size: 1.75rem; -} -h3, .h3 { +h3, +.h3 { font-size: 1.53125rem; } hr { @@ -179,10 +123,6 @@ hr { border: 0; border-top: 1px solid rgba(0, 0, 0, 0.1); } -.list-unstyled { - padding-left: 0; - list-style: none; -} code { font-size: 90%; color: #1f1f1f; @@ -191,16 +131,6 @@ code { a > code { color: inherit; } -pre { - display: block; - font-size: 90%; - color: #303030; -} -pre code { - font-size: inherit; - color: inherit; - word-break: normal; -} .container { width: 100%; padding-right: 15px; @@ -208,56 +138,21 @@ pre code { margin-right: auto; margin-left: auto; } - -@media (min-width: 576px) { - .container { - max-width: 540px; - } -} - -@media (min-width: 768px) { - .container { - max-width: 720px; - } -} - -@media (min-width: 992px) { - .container { - max-width: 960px; - } -} - -@media (min-width: 1200px) { - .container { - max-width: 1140px; - } -} -.container-fluid { - width: 100%; - padding-right: 15px; - padding-left: 15px; - margin-right: auto; - margin-left: auto; -} - @media (min-width: 576px) { .container { max-width: 540px; } } - @media (min-width: 768px) { .container { max-width: 720px; } } - @media (min-width: 992px) { .container { max-width: 960px; } } - @media (min-width: 1200px) { .container { max-width: 1140px; @@ -269,19 +164,26 @@ pre code { margin-right: -15px; margin-left: -15px; } - .col-sm-5, .col-sm-7, .col-sm-12 { +.col, +.col-sm-5, +.col-sm-7, +.col-sm-12 { position: relative; width: 100%; padding-right: 15px; padding-left: 15px; } +.col { + flex-basis: 0; + flex-grow: 1; + max-width: 100%; +} .order-1 { order: 1; } .order-12 { order: 12; } - @media (min-width: 576px) { .col-sm-5 { flex: 0 0 41.66667%; @@ -302,18 +204,7 @@ pre code { order: 12; } } -.table { - width: 100%; - margin-bottom: 0.5rem; - color: #303030; -} -.table th, -.table td { - padding: 0.75rem; - vertical-align: top; - border-top: 1px solid #dbdbdb; -} -.form-control, .search form { +.form-control { display: block; width: 100%; height: 34px; @@ -327,52 +218,37 @@ pre code { border: 1px solid #dbdbdb; border-radius: 0.25rem; } - @media (prefers-reduced-motion: reduce) { } -.form-control:-moz-focusring, .search form:-moz-focusring { +.form-control:-moz-focusring { color: transparent; text-shadow: 0 0 0 #303030; } -.form-control::placeholder, .search form::placeholder { +.form-control::-ms-input-placeholder { color: #5e5e5e; opacity: 1; } -.form-control:disabled, .search form:disabled { - background-color: #fafafa; +.form-control::placeholder { + color: #5e5e5e; opacity: 1; } -textarea.form-control { - height: auto; +.form-control:disabled { + background-color: #fafafa; + opacity: 1; } .form-group { margin-bottom: 1rem; } -.form-inline { +.form-row { display: flex; - flex-flow: row wrap; - align-items: center; + flex-wrap: wrap; + margin-right: -5px; + margin-left: -5px; } - -@media (min-width: 576px) { - .form-inline label { - display: flex; - align-items: center; - justify-content: center; - margin-bottom: 0; - } - .form-inline .form-group { - display: flex; - flex: 0 0 auto; - flex-flow: row wrap; - align-items: center; - margin-bottom: 0; - } - .form-inline .form-control, .form-inline .search form, .search .form-inline form { - display: inline-block; - width: auto; - vertical-align: middle; - } +.form-row > .col, +.form-row > [class*="col-"] { + padding-right: 5px; + padding-left: 5px; } .btn { display: inline-block; @@ -380,7 +256,7 @@ textarea.form-control { color: #303030; text-align: center; vertical-align: middle; - cursor: pointer; + -moz-user-select: none; user-select: none; background-color: transparent; border: 1px solid transparent; @@ -389,147 +265,16 @@ textarea.form-control { line-height: 20px; border-radius: 0.25rem; } - @media (prefers-reduced-motion: reduce) { } -.btn.disabled, .btn:disabled { +.btn:disabled { opacity: 0.65; } -a.btn.disabled, -fieldset:disabled a.btn { - pointer-events: none; -} -.btn-success { - color: #fff; - background-color: #108548; - border-color: #108548; -} -.btn-success.disabled, .btn-success:disabled { - color: #fff; - background-color: #108548; - border-color: #108548; -} -.btn-success:not(:disabled):not(.disabled):active, .btn-success:not(:disabled):not(.disabled).active, -.show > .btn-success.dropdown-menu-toggle { - color: #fff; - background-color: #0b572f; - border-color: #094c29; -} - .login-page input[type='submit'] { - display: block; - width: 100%; -} - .login-page input[type='submit'] + input[type='submit'] { - margin-top: 0.5rem; -} - .login-page input[type="submit"][type='submit'], -.login-page input[type="reset"][type='submit'], -.login-page input[type="button"][type='submit'] { - width: 100%; -} -.collapse:not(.show) { - display: none; -} - -.dropdown { - position: relative; -} - .dropdown-menu-toggle { - white-space: nowrap; -} - .dropdown-menu-toggle::after { - display: inline-block; - margin-left: 0.255em; - vertical-align: 0.255em; - content: ""; - border-top: 0.3em solid; - border-right: 0.3em solid transparent; - border-bottom: 0; - border-left: 0.3em solid transparent; -} - .dropdown-menu-toggle:empty::after { - margin-left: 0; -} -.dropdown-menu { - position: absolute; - top: 100%; - left: 0; - z-index: 1000; - display: none; - float: left; - min-width: 10rem; - padding: 0.5rem 0; - margin: 0.125rem 0 0; - font-size: 1rem; - color: #303030; - text-align: left; - list-style: none; - background-color: #fff; - background-clip: padding-box; - border: 1px solid rgba(0, 0, 0, 0.15); - border-radius: 0.25rem; -} -.dropdown-menu-right { - right: 0; - left: auto; -} - .divider { - height: 0; - margin: 4px 0; - overflow: hidden; - border-top: 1px solid #dbdbdb; -} -.dropdown-menu.show { - display: block; -} -.nav { - display: flex; - flex-wrap: wrap; - padding-left: 0; - margin-bottom: 0; - list-style: none; -} -.nav-link { - display: block; - padding: 0.5rem 1rem; +.btn:not(:disabled):not(.disabled) { + cursor: pointer; } -.nav-link.disabled { - color: #5e5e5e; +fieldset:disabled a.btn { pointer-events: none; - cursor: default; -} -.nav-tabs { - border-bottom: 1px solid #999; -} -.nav-tabs .nav-item { - margin-bottom: -1px; -} -.nav-tabs .nav-link { - border: 1px solid transparent; - border-top-left-radius: 0.25rem; - border-top-right-radius: 0.25rem; -} -.nav-tabs .nav-link.disabled { - color: #5e5e5e; - background-color: transparent; - border-color: transparent; -} -.nav-tabs .nav-link.active, -.nav-tabs .nav-item.show .nav-link { - color: #525252; - background-color: #fff; - border-color: #999 #999 #fff; -} -.nav-tabs .dropdown-menu { - margin-top: -1px; - border-top-left-radius: 0; - border-top-right-radius: 0; -} -.tab-content > .tab-pane { - display: none; -} -.tab-content > .active { - display: block; } .navbar { position: relative; @@ -539,77 +284,12 @@ fieldset:disabled a.btn { justify-content: space-between; padding: 0.25rem 0.5rem; } -.navbar .container, -.navbar .container-fluid { +.navbar .container { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; } -.navbar-nav { - display: flex; - flex-direction: column; - padding-left: 0; - margin-bottom: 0; - list-style: none; -} -.navbar-nav .nav-link { - padding-right: 0; - padding-left: 0; -} -.navbar-nav .dropdown-menu { - position: static; - float: none; -} -.navbar-collapse { - flex-basis: 100%; - flex-grow: 1; - align-items: center; -} -.navbar-toggler { - padding: 0.25rem 0.75rem; - font-size: 1.25rem; - line-height: 1; - background-color: transparent; - border: 1px solid transparent; - border-radius: 0.25rem; -} - -@media (max-width: 575.98px) { - .navbar-expand-sm > .container, - .navbar-expand-sm > .container-fluid { - padding-right: 0; - padding-left: 0; - } -} - -@media (min-width: 576px) { - .navbar-expand-sm { - flex-flow: row nowrap; - justify-content: flex-start; - } - .navbar-expand-sm .navbar-nav { - flex-direction: row; - } - .navbar-expand-sm .navbar-nav .dropdown-menu { - position: absolute; - } - .navbar-expand-sm .navbar-nav .nav-link { - padding-right: 0.5rem; - padding-left: 0.5rem; - } - .navbar-expand-sm > .container, - .navbar-expand-sm > .container-fluid { - flex-wrap: nowrap; - } - .navbar-expand-sm .navbar-collapse { - display: flex !important; - flex-basis: auto; - } - .navbar-expand-sm .navbar-toggler { - display: none; - } -} .card { position: relative; display: flex; @@ -625,132 +305,12 @@ fieldset:disabled a.btn { margin-right: 0; margin-left: 0; } -.badge { - display: inline-block; - padding: 0.25em 0.4em; - font-size: 75%; - font-weight: 600; - line-height: 1; - text-align: center; - white-space: nowrap; - vertical-align: baseline; - border-radius: 0.25rem; -} - -@media (prefers-reduced-motion: reduce) { -} -.badge:empty { - display: none; -} -.btn .badge { - position: relative; - top: -1px; -} -.badge-pill { - padding-right: 0.6em; - padding-left: 0.6em; - border-radius: 10rem; -} -.media { - display: flex; - align-items: flex-start; -} -.close { - float: right; - font-size: 1.5rem; - font-weight: 600; - line-height: 1; - color: #000; - text-shadow: 0 1px 0 #fff; - opacity: .5; -} -button.close { - padding: 0; - background-color: transparent; - border: 0; - appearance: none; -} -a.close.disabled { - pointer-events: none; -} -.modal-dialog { - position: relative; - width: auto; - margin: 0.5rem; - pointer-events: none; -} - -@media (min-width: 576px) { - .modal-dialog { - max-width: 500px; - margin: 1.75rem auto; - } -} -.bg-transparent { - background-color: transparent !important; -} -.border { - border: 1px solid #dbdbdb !important; -} -.border-top { - border-top: 1px solid #dbdbdb !important; -} -.border-right { - border-right: 1px solid #dbdbdb !important; -} -.border-bottom { - border-bottom: 1px solid #dbdbdb !important; -} -.border-left { - border-left: 1px solid #dbdbdb !important; -} -.rounded { - border-radius: 0.25rem !important; -} -.clearfix::after { - display: block; - clear: both; - content: ""; -} -.d-none { - display: none !important; -} -.d-inline-block { - display: inline-block !important; -} .d-block { display: block !important; } .d-flex { display: flex !important; } - -@media (min-width: 576px) { - .d-sm-none { - display: none !important; - } -} - -@media (min-width: 768px) { - .d-md-block { - display: block !important; - } -} - -@media (min-width: 992px) { - .d-lg-none { - display: none !important; - } - .d-lg-block { - display: block !important; - } -} - -@media (min-width: 1200px) { - .d-xl-block { - display: block !important; - } -} .flex-wrap { flex-wrap: wrap !important; } @@ -760,9 +320,6 @@ a.close.disabled { .align-items-center { align-items: center !important; } -.float-right { - float: right !important; -} .fixed-top { position: fixed; top: 0; @@ -770,16 +327,8 @@ a.close.disabled { left: 0; z-index: 1030; } -.sr-only { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - white-space: nowrap; - border: 0; +.ml-2 { + margin-left: 0.5rem !important; } .mt-3 { margin-top: 1rem !important; @@ -787,81 +336,125 @@ a.close.disabled { .mb-3 { margin-bottom: 1rem !important; } -.m-auto { - margin: auto !important; -} - @media (min-width: 576px) { .mt-sm-0 { margin-top: 0 !important; } } -.text-nowrap { - white-space: nowrap !important; -} -.text-left { - text-align: left !important; +.text-center { + text-align: center !important; } .font-weight-normal { font-weight: 400 !important; } -.visible { - visibility: visible !important; -} -.form-control.focus, .search form.focus { - color: #303030; +.gl-form-input, +.gl-form-input.form-control { background-color: #fff; - border-color: #80bdff; - outline: 0; - box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, + "Noto Sans", Ubuntu, Cantarell, "Helvetica Neue", sans-serif, + "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + font-size: 0.875rem; + line-height: 1rem; + padding-top: 0.5rem; + padding-bottom: 0.5rem; + padding-left: 0.75rem; + padding-right: 0.75rem; + height: auto; + color: #303030; + box-shadow: inset 0 0 0 1px #868686; + border-style: none; + appearance: none; + -moz-appearance: none; } -input[type="color"].form-control { - height: 34px; - padding: 0.125rem 0.25rem; +.gl-form-input:not(.form-control-plaintext):-moz-read-only, +.gl-form-input.form-control:not(.form-control-plaintext):-moz-read-only { + background-color: #fafafa; + color: #868686; + box-shadow: inset 0 0 0 1px #dbdbdb; + cursor: not-allowed; } -input[type="color"].form-control:disabled { - background-color: #666; - opacity: 0.65; +.gl-form-input:disabled, +.gl-form-input:not(.form-control-plaintext):read-only, +.gl-form-input.form-control:disabled, +.gl-form-input.form-control:not(.form-control-plaintext):read-only { + background-color: #fafafa; + color: #868686; + box-shadow: inset 0 0 0 1px #dbdbdb; + cursor: not-allowed; +} +.gl-form-input::-ms-input-placeholder, +.gl-form-input.form-control::-ms-input-placeholder { + color: #868686; +} +.gl-form-input::placeholder, +.gl-form-input.form-control::placeholder { + color: #868686; } -.gl-badge { +.gl-button { display: inline-flex; - align-items: center; - font-size: 0.75rem; - font-weight: 400; +} +.gl-button:not(.btn-link):active { + text-decoration: none; +} +.gl-button.gl-button { + border-width: 0; + padding-top: 0.5rem; + padding-bottom: 0.5rem; + padding-left: 0.75rem; + padding-right: 0.75rem; + background-color: transparent; line-height: 1rem; - padding-top: 0.25rem; - padding-bottom: 0.25rem; - padding-left: 0.5rem; - padding-right: 0.5rem; + color: #303030; + fill: currentColor; + box-shadow: inset 0 0 0 1px #bfbfbf; + justify-content: center; + align-items: center; + font-size: 0.875rem; + border-radius: 0.25rem; +} +.gl-button.gl-button .gl-button-icon { + height: 1rem; + width: 1rem; + flex-shrink: 0; + margin-right: 0.25rem; + top: auto; +} +.gl-button.gl-button.btn-default { + background-color: #fff; +} +.gl-button.gl-button.btn-default:active { + box-shadow: inset 0 0 0 2px #5e5e5e, 0 0 0 1px rgba(255, 255, 255, 0.4), + 0 0 0 4px rgba(31, 117, 203, 0.48); outline: none; + background-color: #dbdbdb; +} +.gl-button.gl-button.btn-confirm { + color: #fff; } -body, .form-control, .search form, -.search form { +.gl-button.gl-button.btn-confirm { + background-color: #1f75cb; + box-shadow: inset 0 0 0 1px #1068bf; +} +.gl-button.gl-button.btn-confirm:active { + box-shadow: inset 0 0 0 2px #033464, 0 0 0 1px rgba(255, 255, 255, 0.4), + 0 0 0 4px rgba(31, 117, 203, 0.48); + outline: none; + background-color: #0b5cad; +} +body, +.form-control { font-size: 0.875rem; } -button, -html [type='button'], -[type='reset'], -[type='submit'], -[role='button'] { +[type="submit"] { cursor: pointer; } h1, .h1, -h2, -.h2, h3, .h3 { margin-top: 20px; margin-bottom: 10px; } -input[type='file'] { - line-height: 1; -} - -strong { - font-weight: bold; -} a { color: #1068bf; } @@ -878,9 +471,6 @@ code { background-color: inherit; padding: unset; } -table { - border-spacing: 0; -} .hidden { display: none !important; visibility: hidden !important; @@ -888,10 +478,6 @@ table { .hide { display: none; } - .dropdown-menu-toggle::after { - display: none; -} -.badge:not(.gl-badge), .label { padding: 4px 5px; font-size: 12px; @@ -899,28 +485,6 @@ table { font-weight: 400; display: inline-block; } -.nav-tabs { - border-bottom: 0; -} -.nav-tabs .nav-link { - border-top: 0; - border-left: 0; - border-right: 0; -} -.nav-tabs .nav-item { - margin-bottom: 0; -} -pre code { - white-space: pre-wrap; -} -input[type="color"].form-control { - height: 34px; -} -.toggle-sidebar-button .collapse-text, -.toggle-sidebar-button .icon-chevron-double-lg-left, -.toggle-sidebar-button .icon-chevron-double-lg-right { - color: #666; -} svg { vertical-align: baseline; } @@ -933,10 +497,6 @@ body { body.navless { background-color: #fff !important; } -.content-wrapper { - margin-top: 40px; - padding-bottom: 100px; -} .container { padding-top: 0; z-index: 5; @@ -944,13 +504,11 @@ body.navless { .container .content { margin: 0; } - @media (max-width: 575.98px) { .container .content { margin-top: 20px; } } - @media (max-width: 575.98px) { .container .container .title { padding-left: 15px !important; @@ -971,259 +529,35 @@ body.navless { color: #303030; white-space: nowrap; } -.btn:active, .btn.active { - box-shadow: rgba(0, 0, 0, 0.16); +.btn:active { + background-color: #f0f0f0; + box-shadow: none; +} +.btn:active { background-color: #eaeaea; border-color: #e3e3e3; color: #303030; } -.btn.btn-success { - background-color: #108548; - border-color: #217645; - color: #fff; -} -.btn.btn-success:active, .btn.btn-success.active { - box-shadow: rgba(0, 0, 0, 0.16); - background-color: #24663b; - border-color: #0d532a; - color: #fff; -} .btn svg { height: 15px; width: 15px; } -.btn svg:not(:last-child), -.btn .fa:not(:last-child) { +.btn svg:not(:last-child) { margin-right: 5px; } - .login-page input[type='submit'] { - width: 100%; - margin: 0; - margin-bottom: 15px; -} - .login-page input.btn[type='submit'] { - padding: 6px 0; -} -.badge.badge-pill:not(.gl-badge) { - font-weight: 400; - background-color: rgba(0, 0, 0, 0.07); - color: #525252; - vertical-align: baseline; -} -.hint { - font-style: italic; - color: #bfbfbf; -} -.bold { - font-weight: 600; -} -.tab-content { - overflow: visible; -} -pre.wrap { - word-break: break-word; - white-space: pre-wrap; +.light { + color: #303030; } hr { - margin: 24px 0; + margin: 1.5rem 0; border-top: 1px solid #eee; } -table a code { - position: relative; - top: -2px; - margin-right: 3px; -} -.loading { - margin: 20px auto; - height: 40px; - color: #525252; - font-size: 32px; - text-align: center; -} -.highlight { - text-shadow: none; -} -.chart { - overflow: hidden; - height: 220px; -} .footer-links { margin-bottom: 20px; } .footer-links a { margin-right: 15px; } -.break-word { - word-wrap: break-word; -} -.append-bottom-20 { - margin-bottom: 20px; -} -.center { - text-align: center; -} -.block { - display: block; -} -.flex { - display: flex; -} -.flex-grow { - flex-grow: 1; -} -.dropdown { - position: relative; -} -.show.dropdown .dropdown-menu { - transform: translateY(0); - display: block; - min-height: 40px; - max-height: 312px; - overflow-y: auto; -} - -@media (max-width: 575.98px) { - .show.dropdown .dropdown-menu { - width: 100%; - } -} - .show.dropdown .dropdown-menu-toggle, -.show.dropdown .dropdown-menu-toggle { - border-color: #c4c4c4; -} -.show.dropdown [data-toggle='dropdown'] { - outline: 0; -} -.search-input-container .dropdown-menu { - margin-top: 11px; -} - .dropdown-menu-toggle { - padding: 6px 8px 6px 10px; - background-color: #fff; - color: #303030; - font-size: 14px; - text-align: left; - border: 1px solid #dbdbdb; - border-radius: 0.25rem; - white-space: nowrap; -} - .no-outline.dropdown-menu-toggle { - outline: 0; -} - .dropdown-menu-toggle .fa { - color: #c4c4c4; -} -.dropdown-menu-toggle { - padding-right: 25px; - position: relative; - width: 160px; - text-overflow: ellipsis; - overflow: hidden; -} -.dropdown-menu-toggle .fa { - position: absolute; -} -.dropdown-menu { - display: none; - position: absolute; - width: auto; - top: 100%; - z-index: 300; - min-width: 240px; - max-width: 500px; - margin-top: 4px; - margin-bottom: 24px; - font-size: 14px; - font-weight: 400; - padding: 8px 0; - background-color: #fff; - border: 1px solid #dbdbdb; - border-radius: 0.25rem; - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); -} -.dropdown-menu ul { - margin: 0; - padding: 0; -} -.dropdown-menu li { - display: block; - text-align: left; - list-style: none; - padding: 0 1px; -} -.dropdown-menu li > a, -.dropdown-menu li button { - background: transparent; - border: 0; - border-radius: 0; - box-shadow: none; - display: block; - font-weight: 400; - position: relative; - padding: 8px 12px; - color: #303030; - line-height: 16px; - white-space: normal; - overflow: hidden; - text-align: left; - width: 100%; -} -.dropdown-menu .divider { - height: 1px; - margin: 0.25rem 0; - padding: 0; - background-color: #dbdbdb; -} -.dropdown-menu .badge.badge-pill + span:not(.badge):not(.badge-pill) { - margin-right: 40px; -} -.dropdown-select { - width: 300px; -} - -@media (max-width: 767.98px) { - .dropdown-select { - width: 100%; - } -} -.dropdown-content { - max-height: 252px; - overflow-y: auto; -} -.dropdown-loading { - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - display: none; - z-index: 9; - background-color: rgba(255, 255, 255, 0.6); - font-size: 28px; -} -.dropdown-loading .fa { - position: absolute; - top: 50%; - left: 50%; - margin-top: -14px; - margin-left: -14px; -} - -@media (max-width: 575.98px) { - .navbar-gitlab li.dropdown { - position: static; - } - header.navbar-gitlab .dropdown .dropdown-menu { - width: 100%; - min-width: 100%; - } -} - -@media (max-width: 767.98px) { - .dropdown-menu-toggle { - width: 100%; - } -} .flash-container { margin: 0; margin-bottom: 16px; @@ -1232,8 +566,8 @@ table a code { z-index: 1; } .flash-container.sticky { - position: sticky; position: -webkit-sticky; + position: sticky; top: 48px; z-index: 251; } @@ -1243,9 +577,6 @@ table a code { .flash-container:empty { margin: 0; } -textarea { - resize: vertical; -} input { border-radius: 0.25rem; color: #303030; @@ -1257,809 +588,61 @@ label { label.label-bold { font-weight: 600; } -.form-control, .search form { +.form-control { border-radius: 4px; padding: 6px 10px; } -.form-control::placeholder, .search form::placeholder { +.form-control::-ms-input-placeholder { color: #868686; } -.gl-field-error { - color: #dd2b0e; - font-size: 0.875rem; +.form-control::placeholder { + color: #868686; } -.gl-show-field-errors .form-control:not(textarea), .gl-show-field-errors .search form:not(textarea), .search .gl-show-field-errors form:not(textarea) { +.gl-show-field-errors .form-control:not(textarea) { height: 34px; } .gl-show-field-errors .gl-field-hint { color: #303030; } - -@media (max-width: 575.98px) { - .remember-me .remember-me-checkbox { - margin-top: 0; - } -} -body.ui-indigo .navbar-gitlab { - background-color: #292961; -} -body.ui-indigo .navbar-gitlab .navbar-collapse { - color: #d1d1f0; -} -body.ui-indigo .navbar-gitlab .container-fluid .navbar-toggler { - border-left: 1px solid #6868b9; -} -body.ui-indigo .navbar-gitlab .container-fluid .navbar-toggler svg { - fill: #d1d1f0; -} -body.ui-indigo .navbar-gitlab .navbar-sub-nav > li.active > a, -body.ui-indigo .navbar-gitlab .navbar-sub-nav > li.active > button, body.ui-indigo .navbar-gitlab .navbar-sub-nav > li.dropdown.show > a, -body.ui-indigo .navbar-gitlab .navbar-sub-nav > li.dropdown.show > button, -body.ui-indigo .navbar-gitlab .navbar-nav > li.active > a, -body.ui-indigo .navbar-gitlab .navbar-nav > li.active > button, -body.ui-indigo .navbar-gitlab .navbar-nav > li.dropdown.show > a, -body.ui-indigo .navbar-gitlab .navbar-nav > li.dropdown.show > button { - color: #292961; - background-color: #fff; -} -body.ui-indigo .navbar-gitlab .navbar-sub-nav { - color: #d1d1f0; -} -body.ui-indigo .navbar-gitlab .nav > li { - color: #d1d1f0; -} -body.ui-indigo .navbar-gitlab .nav > li > a.header-user-dropdown-toggle .header-user-avatar { - border-color: #d1d1f0; -} -body.ui-indigo .navbar-gitlab .nav > li.active > a, -body.ui-indigo .navbar-gitlab .nav > li.dropdown.show > a { - color: #292961; - background-color: #fff; -} -body.ui-indigo .search form { - background-color: rgba(209, 209, 240, 0.2); -} -body.ui-indigo .search .search-input::placeholder { - color: rgba(209, 209, 240, 0.8); -} -body.ui-indigo .search .search-input-wrap .search-icon, -body.ui-indigo .search .search-input-wrap .clear-icon { - fill: rgba(209, 209, 240, 0.8); -} -body.ui-indigo .nav-sidebar li.active { - box-shadow: inset 4px 0 0 #4b4ba3; -} -body.ui-indigo .nav-sidebar li.active > a { - color: #393982; -} -body.ui-indigo .nav-sidebar li.active .nav-icon-container svg { - fill: #393982; -} -body.ui-indigo .sidebar-top-level-items > li.active .badge.badge-pill { - color: #393982; -} -body.ui-indigo .nav-links li.active a, -body.ui-indigo .nav-links li a.active { - border-bottom: 2px solid #6666c4; -} -body.ui-indigo .nav-links li.active a .badge.badge-pill, -body.ui-indigo .nav-links li a.active .badge.badge-pill { - font-weight: 600; -} -.navbar-gitlab { - padding: 0 16px; - z-index: 1000; - margin-bottom: 0; - min-height: 40px; - border: 0; - border-bottom: 1px solid #dbdbdb; - position: fixed; - top: 0; - left: 0; - right: 0; - border-radius: 0; -} -.navbar-gitlab .logo-text { - line-height: initial; -} -.navbar-gitlab .logo-text svg { - width: 55px; - height: 14px; - margin: 0; - fill: #fff; -} -.navbar-gitlab .close-icon { - display: none; -} -.navbar-gitlab .header-content { - width: 100%; - display: flex; - justify-content: space-between; - position: relative; - min-height: 40px; - padding-left: 0; -} -.navbar-gitlab .header-content .title-container { - display: flex; - align-items: stretch; - flex: 1 1 auto; - padding-top: 0; - overflow: visible; -} -.navbar-gitlab .header-content .title { - padding-right: 0; - color: currentColor; - display: flex; - position: relative; - margin: 0; - font-size: 18px; - vertical-align: top; - white-space: nowrap; -} -.navbar-gitlab .header-content .title img { - height: 28px; -} -.navbar-gitlab .header-content .title img + .logo-text { - margin-left: 8px; -} -.navbar-gitlab .header-content .title.wrap { - white-space: normal; -} -.navbar-gitlab .header-content .title a { - display: flex; - align-items: center; - padding: 2px 8px; - margin: 5px 2px 5px -8px; - border-radius: 4px; -} -.navbar-gitlab .header-content .dropdown.open > a { - border-bottom-color: #fff; -} -.navbar-gitlab .header-content .navbar-collapse > ul.nav > li:not(.d-none) { - margin: 0 2px; -} -.navbar-gitlab .navbar-collapse { - flex: 0 0 auto; - border-top: 0; - padding: 0; -} - -@media (max-width: 575.98px) { - .navbar-gitlab .navbar-collapse { - flex: 1 1 auto; - } -} -.navbar-gitlab .navbar-collapse .nav { - flex-wrap: nowrap; -} - -@media (max-width: 575.98px) { - .navbar-gitlab .navbar-collapse .nav > li:not(.d-none) a { - margin-left: 0; - } -} -.navbar-gitlab .container-fluid { - padding: 0; -} -.navbar-gitlab .container-fluid .user-counter svg { - margin-right: 3px; -} -.navbar-gitlab .container-fluid .navbar-toggler { - position: relative; - right: -10px; - border-radius: 0; - min-width: 45px; - padding: 0; - margin: 8px -7px 8px 0; - font-size: 14px; - text-align: center; - color: currentColor; -} - -@media (max-width: 575.98px) { - .navbar-gitlab .container-fluid .navbar-nav { - display: flex; - padding-right: 10px; - flex-direction: row; - } -} -.navbar-gitlab .container-fluid .navbar-nav li .badge.badge-pill { - box-shadow: none; - font-weight: 600; -} - -@media (max-width: 575.98px) { - .navbar-gitlab .container-fluid .nav > li.header-user { - padding-left: 10px; - } -} -.navbar-gitlab .container-fluid .nav > li > a { - will-change: color; - margin: 4px 0; - padding: 6px 8px; - height: 32px; -} - -@media (max-width: 575.98px) { - .navbar-gitlab .container-fluid .nav > li > a { - padding: 0; - } -} -.navbar-gitlab .container-fluid .nav > li > a.header-user-dropdown-toggle { - margin-left: 2px; -} -.navbar-gitlab .container-fluid .nav > li > a.header-user-dropdown-toggle .header-user-avatar { - margin-right: 0; -} -.navbar-gitlab .container-fluid .nav > li .header-new-dropdown-toggle { - margin-right: 0; -} -.navbar-sub-nav > li > a, -.navbar-sub-nav > li > button, -.navbar-nav > li > a, -.navbar-nav > li > button { - display: flex; - align-items: center; - justify-content: center; - padding: 6px 8px; - margin: 4px 2px; - font-size: 12px; - color: currentColor; - border-radius: 4px; - height: 32px; - font-weight: 600; -} -.navbar-sub-nav > li > button, -.navbar-nav > li > button { - background: transparent; - border: 0; -} -.navbar-sub-nav .dropdown-menu, -.navbar-nav .dropdown-menu { - position: absolute; -} -.navbar-sub-nav { - display: flex; - margin: 0 0 0 6px; -} -.caret-down, -.btn .caret-down { - top: 0; - height: 11px; - width: 11px; - margin-left: 4px; - fill: currentColor; -} -.header-user .dropdown-menu, -.header-new .dropdown-menu { - margin-top: 4px; -} -.btn-sign-in { - background-color: #ebebfa; - color: #292961; - font-weight: 600; - line-height: 18px; - margin: 4px 0 4px 2px; -} -.title-container .badge.badge-pill, -.navbar-nav .badge.badge-pill { - position: inherit; - font-weight: 400; - margin-left: -6px; - font-size: 11px; - color: #fff; - padding: 0 5px; - line-height: 12px; - border-radius: 7px; - box-shadow: 0 1px 0 rgba(76, 78, 84, 0.2); -} -.title-container .badge.badge-pill.green-badge, -.navbar-nav .badge.badge-pill.green-badge { - background-color: #108548; -} -.title-container .badge.badge-pill.merge-requests-count, -.navbar-nav .badge.badge-pill.merge-requests-count { - background-color: #de7e00; -} -.title-container .badge.badge-pill.todos-count, -.navbar-nav .badge.badge-pill.todos-count { - background-color: #1f75cb; -} -.title-container .canary-badge .badge, -.navbar-nav .canary-badge .badge { - font-size: 12px; - line-height: 16px; - padding: 0 0.5rem; -} - -@media (max-width: 575.98px) { - .navbar-gitlab .container-fluid { - font-size: 18px; - } - .navbar-gitlab .container-fluid .navbar-nav { - table-layout: fixed; - width: 100%; - margin: 0; - text-align: right; - } - .navbar-gitlab .container-fluid .navbar-collapse { - margin-left: -8px; - margin-right: -10px; - } - .navbar-gitlab .container-fluid .navbar-collapse .nav > li:not(.d-none) { - flex: 1; - } - .header-user-dropdown-toggle { - text-align: center; - } - .header-user-avatar { - float: none; - } -} -.header-user.show .dropdown-menu { - margin-top: 4px; - color: #303030; - left: auto; - max-height: 445px; -} -.header-user.show .dropdown-menu svg { - vertical-align: text-top; -} -.header-user-avatar { - float: left; - margin-right: 5px; - border-radius: 50%; - border: 1px solid #f5f5f5; -} .navbar-empty { justify-content: center; height: 40px; background: #fff; border-bottom: 1px solid #f0f0f0; } - -@media (max-width: 575.98px) { - .nav-links > li > a .badge.badge-pill { - display: none; - } -} - -@media (max-width: 575.98px) { - .nav-links > li > a { - margin-right: 3px; - } -} -.media { - display: flex; - align-items: flex-start; -} -.card { - margin-bottom: 16px; -} -.nav-links:not(.quick-links) { - display: flex; - padding: 0; - margin: 0; - list-style: none; - height: auto; - border-bottom: 1px solid #dbdbdb; -} -.content-wrapper { - width: 100%; -} -.content-wrapper .container-fluid { - padding: 0 16px; -} - -@media (min-width: 768px) { - .page-with-contextual-sidebar { - padding-left: 50px; - } -} - -@media (min-width: 1200px) { - .page-with-contextual-sidebar { - padding-left: 220px; - } -} -.context-header { - position: relative; - margin-right: 2px; - width: 220px; -} -.context-header > a, -.context-header > button { - font-weight: 600; - display: flex; - width: 100%; - align-items: center; - padding: 10px 16px 10px 10px; - color: #303030; - background-color: transparent; - border: 0; - text-align: left; -} -.context-header .avatar-container { - flex: 0 0 40px; - background-color: #fff; -} -.context-header .sidebar-context-title { - overflow: hidden; - text-overflow: ellipsis; -} -.context-header .sidebar-context-title.text-secondary { - font-weight: normal; - font-size: 0.8em; -} -.nav-sidebar { - position: fixed; - z-index: 600; - width: 220px; - top: 40px; - bottom: 0; - left: 0; - background-color: #fafafa; - box-shadow: inset -1px 0 0 #dbdbdb; - transform: translate3d(0, 0, 0); -} - -@media (min-width: 576px) and (max-width: 576px) { - .nav-sidebar:not(.sidebar-collapsed-desktop) { - box-shadow: inset -1px 0 0 #dbdbdb, 2px 1px 3px rgba(0, 0, 0, 0.1); - } -} -.nav-sidebar.sidebar-collapsed-desktop { - width: 50px; -} -.nav-sidebar.sidebar-collapsed-desktop .nav-sidebar-inner-scroll { - overflow-x: hidden; -} -.nav-sidebar.sidebar-collapsed-desktop .badge.badge-pill:not(.fly-out-badge), -.nav-sidebar.sidebar-collapsed-desktop .sidebar-context-title, -.nav-sidebar.sidebar-collapsed-desktop .nav-item-name { - border: 0; - clip: rect(0, 0, 0, 0); - height: 1px; - margin: -1px; - overflow: hidden; - padding: 0; - position: absolute; - white-space: nowrap; - width: 1px; -} -.nav-sidebar.sidebar-collapsed-desktop .sidebar-top-level-items > li > a { - min-height: 45px; -} -.nav-sidebar.sidebar-collapsed-desktop .fly-out-top-item { - display: block; -} -.nav-sidebar.sidebar-collapsed-desktop .avatar-container { - margin: 0 auto; -} -.nav-sidebar.sidebar-expanded-mobile { - left: 0; -} -.nav-sidebar a { - text-decoration: none; -} -.nav-sidebar ul { - padding-left: 0; - list-style: none; -} -.nav-sidebar li { - white-space: nowrap; -} -.nav-sidebar li a { - display: flex; - align-items: center; - padding: 12px 16px; - color: #666; -} -.nav-sidebar li .nav-item-name { - flex: 1; -} -.nav-sidebar li.active > a { - font-weight: 600; -} - -@media (max-width: 767.98px) { - .nav-sidebar { - left: -220px; - } -} -.nav-sidebar .nav-icon-container { - display: flex; - margin-right: 8px; -} -.nav-sidebar .fly-out-top-item { - display: none; -} -.nav-sidebar svg { - height: 16px; - width: 16px; -} - -@media (min-width: 768px) and (max-width: 1199px) { - .nav-sidebar:not(.sidebar-expanded-mobile) { - width: 50px; - } - .nav-sidebar:not(.sidebar-expanded-mobile) .nav-sidebar-inner-scroll { - overflow-x: hidden; - } - .nav-sidebar:not(.sidebar-expanded-mobile) .badge.badge-pill:not(.fly-out-badge), - .nav-sidebar:not(.sidebar-expanded-mobile) .sidebar-context-title, - .nav-sidebar:not(.sidebar-expanded-mobile) .nav-item-name { - border: 0; - clip: rect(0, 0, 0, 0); - height: 1px; - margin: -1px; - overflow: hidden; - padding: 0; - position: absolute; - white-space: nowrap; - width: 1px; - } - .nav-sidebar:not(.sidebar-expanded-mobile) .sidebar-top-level-items > li > a { - min-height: 45px; - } - .nav-sidebar:not(.sidebar-expanded-mobile) .fly-out-top-item { - display: block; - } - .nav-sidebar:not(.sidebar-expanded-mobile) .avatar-container { - margin: 0 auto; - } - .nav-sidebar:not(.sidebar-expanded-mobile) .context-header { - height: 60px; - width: 50px; - } - .nav-sidebar:not(.sidebar-expanded-mobile) .context-header a { - padding: 10px 4px; - } - .nav-sidebar:not(.sidebar-expanded-mobile) .sidebar-top-level-items > li .sidebar-sub-level-items:not(.flyout-list) { - display: none; - } - .nav-sidebar:not(.sidebar-expanded-mobile) .nav-icon-container { - margin-right: 0; - } - .nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button { - padding: 16px; - width: 49px; - } - .nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button .collapse-text, - .nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button .icon-chevron-double-lg-left { - display: none; - } - .nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button .icon-chevron-double-lg-right { - display: block; - margin: 0; - } -} -.nav-sidebar-inner-scroll { - height: 100%; - width: 100%; - overflow: auto; -} -.sidebar-sub-level-items { - display: none; - padding-bottom: 8px; -} -.sidebar-sub-level-items > li a { - padding: 8px 16px 8px 40px; -} -.sidebar-top-level-items { - margin-bottom: 60px; -} - -@media (min-width: 576px) { - .sidebar-top-level-items > li > a { - margin-right: 1px; - } -} -.sidebar-top-level-items > li .badge.badge-pill { - background-color: rgba(0, 0, 0, 0.08); - color: #666; -} -.sidebar-top-level-items > li.active { - background: rgba(0, 0, 0, 0.04); -} -.sidebar-top-level-items > li.active > a { - margin-left: 4px; - padding-left: 12px; -} -.sidebar-top-level-items > li.active .badge.badge-pill { - font-weight: 600; -} -.sidebar-top-level-items > li.active .sidebar-sub-level-items:not(.is-fly-out-only) { - display: block; -} -.toggle-sidebar-button, -.close-nav-button { - width: 219px; - position: fixed; - height: 48px; - bottom: 0; - padding: 0 16px; - background-color: #fafafa; - border: 0; - border-top: 1px solid #dbdbdb; - color: #666; - display: flex; - align-items: center; -} -.toggle-sidebar-button svg, -.close-nav-button svg { - margin-right: 8px; -} -.toggle-sidebar-button .icon-chevron-double-lg-right, -.close-nav-button .icon-chevron-double-lg-right { - display: none; -} -.collapse-text { - white-space: nowrap; - overflow: hidden; -} -.sidebar-collapsed-desktop .context-header { - height: 60px; - width: 50px; -} -.sidebar-collapsed-desktop .context-header a { - padding: 10px 4px; -} -.sidebar-collapsed-desktop .sidebar-top-level-items > li .sidebar-sub-level-items:not(.flyout-list) { - display: none; +.navbar-empty .tanuki-logo, +.navbar-empty .brand-header-logo { + max-height: 100%; } -.sidebar-collapsed-desktop .nav-icon-container { - margin-right: 0; +.tanuki-logo .tanuki-left-ear, +.tanuki-logo .tanuki-right-ear, +.tanuki-logo .tanuki-nose { + fill: #e24329; } -.sidebar-collapsed-desktop .toggle-sidebar-button { - padding: 16px; - width: 49px; +.tanuki-logo .tanuki-left-eye, +.tanuki-logo .tanuki-right-eye { + fill: #fc6d26; } -.sidebar-collapsed-desktop .toggle-sidebar-button .collapse-text, -.sidebar-collapsed-desktop .toggle-sidebar-button .icon-chevron-double-lg-left { - display: none; +.tanuki-logo .tanuki-left-cheek, +.tanuki-logo .tanuki-right-cheek { + fill: #fca326; } -.sidebar-collapsed-desktop .toggle-sidebar-button .icon-chevron-double-lg-right { - display: block; - margin: 0; -} -.fly-out-top-item > a { - display: flex; -} -.fly-out-top-item .fly-out-badge { - margin-left: 8px; -} -.fly-out-top-item-name { - flex: 1; -} -.close-nav-button { - display: none; -} - -@media (max-width: 767.98px) { - .close-nav-button { - display: flex; - } - .toggle-sidebar-button { - display: none; - } -} -table.table { +.card { margin-bottom: 16px; } -table.table .dropdown-menu a { - text-decoration: none; -} -table.table .success, -table.table .info { - color: #fff; -} -table.table .success a:not(.btn), -table.table .info a:not(.btn) { - text-decoration: underline; - color: #fff; -} -pre { - font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace; - display: block; - padding: 8px 12px; - margin: 0 0 8px; - font-size: 13px; - word-break: break-all; - word-wrap: break-word; - color: #303030; - background-color: #fafafa; - border: 1px solid #dbdbdb; - border-radius: 2px; -} -.monospace { - font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace; -} -input::-moz-placeholder, -textarea::-moz-placeholder { +input::-moz-placeholder { color: #868686; opacity: 1; } -input::-ms-input-placeholder, -textarea::-ms-input-placeholder { +input::-ms-input-placeholder { color: #868686; } -input:-ms-input-placeholder, -textarea:-ms-input-placeholder { +input:-ms-input-placeholder { color: #868686; } svg { fill: currentColor; } - -svg.s12 { - width: 12px; - height: 12px; -} - -svg.s16 { - width: 16px; - height: 16px; -} - -svg.s18 { - width: 18px; - height: 18px; -} - -svg.s12 { - vertical-align: -1px; -} - -svg.s16 { - vertical-align: -3px; -} -.sr-only { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - border: 0; -} -table.code { - width: 100%; - font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace; - border: 0; - border-collapse: separate; - margin: 0; - padding: 0; - table-layout: fixed; - border-radius: 0 0 4px 4px; -} -.frame .badge.badge-pill { - position: absolute; - background-color: #428fdc; - color: #fff; - border: #fff 1px solid; - min-height: 16px; - padding: 5px 8px; - border-radius: 12px; -} -.frame .badge.badge-pill { - transform: translate(-50%, -50%); -} -.color-label { - padding: 0 0.5rem; - line-height: 16px; - border-radius: 100px; - color: #fff; -} -.label-link { - display: inline-flex; - vertical-align: text-bottom; -} -.label-link .label { - vertical-align: inherit; - font-size: 12px; -} .login-page .container { max-width: 960px; } @@ -2096,6 +679,25 @@ table.code { border-radius: 0.25rem; padding: 15px; } +.login-page .login-box .login-heading h3, +.login-page .omniauth-container .login-heading h3 { + font-weight: 400; + line-height: 1.5; + margin: 0 0 10px; +} +.login-page .login-box .login-footer, +.login-page .omniauth-container .login-footer { + margin-top: 10px; +} +.login-page .login-box .login-footer p:last-child, +.login-page .omniauth-container .login-footer p:last-child { + margin-bottom: 0; +} +.login-page .login-box a.forgot, +.login-page .omniauth-container a.forgot { + float: right; + padding-top: 6px; +} .login-page .login-box .nav .active a, .login-page .omniauth-container .nav .active a { background: transparent; @@ -2132,7 +734,6 @@ table.code { background: none; margin-bottom: 16px; } - @media (max-width: 991.98px) { .login-page .omniauth-container form { width: 100%; @@ -2140,7 +741,6 @@ table.code { } .login-page .omniauth-container .omniauth-btn { width: 100%; - padding: 8px; } .login-page .new-session-tabs { display: flex; @@ -2148,6 +748,19 @@ table.code { border-top-right-radius: 4px; border-top-left-radius: 4px; } +.login-page .new-session-tabs.custom-provider-tabs { + flex-wrap: wrap; +} +.login-page .new-session-tabs.custom-provider-tabs li { + min-width: 85px; + flex-basis: auto; +} +.login-page .new-session-tabs.custom-provider-tabs li:nth-child(n + 5) { + border-top: 1px solid #dbdbdb; +} +.login-page .new-session-tabs.custom-provider-tabs a { + font-size: 16px; +} .login-page .new-session-tabs li { flex: 1; text-align: center; @@ -2170,17 +783,29 @@ table.code { .login-page .new-session-tabs li.active > a { cursor: default; } +.login-page .form-control:active, +.login-page .form-control:focus { + background-color: #fff; +} .login-page .submit-container { margin-top: 16px; } -.login-page input[type='submit'] { +.login-page input[type="submit"] { margin-bottom: 0; + display: block; + width: 100%; } .login-page .devise-errors h2 { margin-top: 0; font-size: 14px; color: #ae1800; } +@media (max-width: 575.98px) { + .login-page .col-md-5.float-right { + float: none !important; + margin-bottom: 45px; + } +} .devise-layout-html { margin: 0; padding: 0; @@ -2213,191 +838,57 @@ table.code { .devise-layout-html body .navless-container { padding: 65px 15px; } - @media (max-width: 575.98px) { .devise-layout-html body .navless-container { padding: 0 15px 65px; } } -.milestones { - padding: 8px; - margin-top: 8px; - border-radius: 4px; - background-color: #dbdbdb; -} -.search { - margin: 0 8px; -} -.search form { - margin: 0; - padding: 4px; - width: 200px; - line-height: 24px; - height: 32px; - border: 0; - border-radius: 4px; -} -@media (min-width: 1200px) { - .search form { - width: 320px; - } -} -.search .search-input { - border: 0; - font-size: 14px; - padding: 0 20px 0 0; - margin-left: 5px; - line-height: 25px; - width: 98%; - color: #fff; - background: none; -} -.search .search-input-container { - display: flex; - position: relative; -} -.search .search-input-wrap { - width: 100%; -} -.search .search-input-wrap .search-icon, -.search .search-input-wrap .clear-icon { - position: absolute; - right: 5px; - top: 4px; +.gl-border-solid { + border-style: solid; } -.search .search-input-wrap .search-icon { - -moz-user-select: none; - user-select: none; -} -.search .search-input-wrap .clear-icon { - display: none; -} -.search .search-input-wrap .dropdown { - position: static; -} -.search .search-input-wrap .dropdown-menu { - left: -5px; - max-height: 400px; - overflow: auto; -} - -@media (min-width: 1200px) { - .search .search-input-wrap .dropdown-menu { - width: 320px; - } -} -.search .search-input-wrap .dropdown-content { - max-height: 382px; -} -.settings { - border-top: 1px solid #dbdbdb; -} -.settings:first-of-type { - margin-top: 10px; - border: 0; -} -.settings + div .settings:first-of-type { - margin-top: 0; - border-top: 1px solid #dbdbdb; -} -.avatar, .avatar-container { - float: left; - margin-right: 16px; - border-radius: 50%; - border: 1px solid #f5f5f5; -} -.s16.avatar, .s16.avatar-container { - width: 16px; - height: 16px; - margin-right: 8px; -} -.s18.avatar, .s18.avatar-container { - width: 18px; - height: 18px; - margin-right: 8px; -} -.s40.avatar, .s40.avatar-container { - width: 40px; - height: 40px; - margin-right: 8px; +.gl-border-gray-100 { + border-color: #dbdbdb; } -.avatar { - transition-property: none; - width: 40px; - height: 40px; - padding: 0; - background: #fdfdfd; - overflow: hidden; - border-color: rgba(0, 0, 0, 0.1); +.gl-border-1 { + border-width: 1px; } -.avatar.center { - font-size: 14px; - line-height: 1.8em; - text-align: center; +.gl-rounded-base { + border-radius: 0.25rem; } -.avatar.avatar-tile { - border-radius: 0; - border: 0; +.gl-text-green-600 { + color: #217645; } -.avatar-container { - overflow: hidden; - display: flex; +.gl-text-red-500 { + color: #dd2b0e; } -.avatar-container a { - width: 100%; - height: 100%; +.gl-display-flex { display: flex; - text-decoration: none; -} -.avatar-container .avatar { - border-radius: 0; - border: 0; - height: auto; - width: 100%; - margin: 0; - align-self: center; -} -.avatar-container.s40 { - min-width: 40px; - min-height: 40px; -} -.rect-avatar { - border-radius: 2px; } -.rect-avatar.s16 { - border-radius: 2px; +.gl-align-items-center { + align-items: center; } -.rect-avatar.s18 { - border-radius: 2px; +.gl-p-2 { + padding: 0.25rem; } -.rect-avatar.s40 { - border-radius: 4px; +.gl-p-4 { + padding: 0.75rem; } -.tab-width-8 { - -moz-tab-size: 8; - tab-size: 8; +.gl-mt-2 { + margin-top: 0.25rem; } -.gl-sr-only { - border: 0; - clip: rect(0, 0, 0, 0); - height: 1px; - margin: -1px; - overflow: hidden; - padding: 0; - position: absolute; - white-space: nowrap; - width: 1px; +.gl-mb-2 { + margin-bottom: 0.25rem; } -.gl-mt-5 { - margin-top: 1rem; +.gl-mb-3 { + margin-bottom: 0.5rem; } -.gl-ml-3 { - margin-left: 0.5rem; +.gl-mb-5 { + margin-bottom: 1rem; } -.content-wrapper > .alert-wrapper, -#content-body, .modal-dialog { - display: block; +.gl-text-left { + text-align: left; } -@import 'cloaking'; + +@import "startup/cloaking"; @include cloak-startup-scss(none); diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index d62bb6f32bd..62af141fbc5 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -39,6 +39,11 @@ class ProjectsController < Projects::ApplicationController push_frontend_feature_flag(:refactor_blob_viewer, @project, default_enabled: :yaml) end + before_action only: [:new] do + # Run experiment before render so it will be written to the `gon` for FE + helpers.new_repo_experiment_text + end + layout :determine_layout feature_category :projects, [ diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb index 0e3dff27da9..46414b49f37 100644 --- a/app/helpers/application_settings_helper.rb +++ b/app/helpers/application_settings_helper.rb @@ -368,7 +368,9 @@ module ApplicationSettingsHelper :container_registry_cleanup_tags_service_max_list_size, :keep_latest_artifact, :whats_new_variant - ] + ].tap do |settings| + settings << :deactivate_dormant_users unless Gitlab.com? + end end def external_authorization_service_attributes diff --git a/app/helpers/invite_members_helper.rb b/app/helpers/invite_members_helper.rb index 717621d6278..8e0511e40f2 100644 --- a/app/helpers/invite_members_helper.rb +++ b/app/helpers/invite_members_helper.rb @@ -21,17 +21,6 @@ module InviteMembersHelper experiment_enabled?(:invite_members_empty_group_version_a) && Ability.allowed?(current_user, :admin_group_member, group) end - def dropdown_invite_members_link(form_model) - link_to invite_members_url(form_model), - data: { - 'track-event': 'click_link', - 'track-label': tracking_label, - 'track-property': experiment_tracking_category_and_group(:invite_members_new_dropdown) - } do - invite_member_link_content - end - end - def invite_accepted_notice(member) case member.source when Project @@ -42,23 +31,4 @@ module InviteMembersHelper { member_human_access: member.human_access, name: member.source.name } end end - - private - - def invite_members_url(form_model) - case form_model - when Project - project_project_members_path(form_model) - when Group - group_group_members_path(form_model) - end - end - - def invite_member_link_content - text = s_('InviteMember|Invite members') - - return text unless experiment_enabled?(:invite_members_new_dropdown) - - "#{text} #{emoji_icon('shaking_hands', 'aria-hidden': true, class: 'gl-font-base gl-vertical-align-baseline')}".html_safe - end end diff --git a/app/helpers/nav/new_dropdown_helper.rb b/app/helpers/nav/new_dropdown_helper.rb new file mode 100644 index 00000000000..b952aeacb13 --- /dev/null +++ b/app/helpers/nav/new_dropdown_helper.rb @@ -0,0 +1,188 @@ +# frozen_string_literal: true + +module Nav + module NewDropdownHelper + def new_dropdown_view_model(group:, project:) + return unless current_user + + menu_sections = [] + + if group&.persisted? + menu_sections.push(group_menu_section(group)) + elsif project&.persisted? + menu_sections.push(project_menu_section(project)) + end + + menu_sections.push(general_menu_section) + + { + title: _("New..."), + menu_sections: menu_sections.select { |x| x.fetch(:menu_items).any? } + } + end + + def new_repo_experiment_text + experiment(:new_repo, user: current_user) do |e| + e.use { _('New project') } + e.try { _('New project/repository') } + end.run + end + + private + + def group_menu_section(group) + menu_items = [] + + if can?(current_user, :create_projects, group) + menu_items.push( + ::Gitlab::Nav::TopNavMenuItem.build( + id: 'new_project', + title: new_repo_experiment_text, + href: new_project_path(namespace_id: group.id), + data: { track_experiment: 'new_repo', track_event: 'click_link_new_project_group', track_label: 'plus_menu_dropdown' } + ) + ) + end + + if can?(current_user, :create_subgroup, group) + menu_items.push( + ::Gitlab::Nav::TopNavMenuItem.build( + id: 'new_subgroup', + title: _('New subgroup'), + href: new_group_path(parent_id: group.id), + data: { track_event: 'click_link_new_subgroup', track_label: 'plus_menu_dropdown' } + ) + ) + end + + menu_items.push(create_epic_menu_item(group)) + + if Gitlab::Experimentation.active?(:invite_members_new_dropdown) && can?(current_user, :admin_group_member, group) + menu_items.push( + invite_members_menu_item( + href: group_group_members_path(group) + ) + ) + end + + { + title: _('This group'), + menu_items: menu_items.compact + } + end + + def project_menu_section(project) + menu_items = [] + merge_project = merge_request_source_project_for_project(project) + + if show_new_issue_link?(project) + menu_items.push( + ::Gitlab::Nav::TopNavMenuItem.build( + id: 'new_issue', + title: _('New issue'), + href: new_project_issue_path(project), + data: { track_event: 'click_link_new_issue', track_label: 'plus_menu_dropdown', qa_selector: 'new_issue_link' } + ) + ) + end + + if merge_project + menu_items.push( + ::Gitlab::Nav::TopNavMenuItem.build( + id: 'new_mr', + title: _('New merge request'), + href: project_new_merge_request_path(merge_project), + data: { track_event: 'click_link_new_mr', track_label: 'plus_menu_dropdown' } + ) + ) + end + + if can?(current_user, :create_snippet, project) + menu_items.push( + ::Gitlab::Nav::TopNavMenuItem.build( + id: 'new_snippet', + title: _('New snippet'), + href: new_project_snippet_path(project), + data: { track_event: 'click_link_new_snippet_project', track_label: 'plus_menu_dropdown' } + ) + ) + end + + if Gitlab::Experimentation.active?(:invite_members_new_dropdown) && can_import_members? + menu_items.push( + invite_members_menu_item( + href: project_project_members_path(project) + ) + ) + end + + { + title: _('This project'), + menu_items: menu_items + } + end + + def general_menu_section + menu_items = [] + + if current_user.can_create_project? + menu_items.push( + ::Gitlab::Nav::TopNavMenuItem.build( + id: 'general_new_project', + title: new_repo_experiment_text, + href: new_project_path, + data: { track_experiment: 'new_repo', track_event: 'click_link_new_project', track_label: 'plus_menu_dropdown', qa_selector: 'global_new_project_link' } + ) + ) + end + + if current_user.can_create_group? + menu_items.push( + ::Gitlab::Nav::TopNavMenuItem.build( + id: 'general_new_group', + title: _('New group'), + href: new_group_path, + data: { track_event: 'click_link_new_group', track_label: 'plus_menu_dropdown' } + ) + ) + end + + if current_user.can?(:create_snippet) + menu_items.push( + ::Gitlab::Nav::TopNavMenuItem.build( + id: 'general_new_snippet', + title: _('New snippet'), + href: new_snippet_path, + data: { track_event: 'click_link_new_snippet_parent', track_label: 'plus_menu_dropdown', qa_selector: 'global_new_snippet_link' } + ) + ) + end + + { + title: _('GitLab'), + menu_items: menu_items + } + end + + def invite_members_menu_item(href:) + ::Gitlab::Nav::TopNavMenuItem.build( + id: 'invite', + title: s_('InviteMember|Invite members'), + emoji: ('shaking_hands' if experiment_enabled?(:invite_members_new_dropdown)), + href: href, + data: { + track_event: 'click_link', + track_label: tracking_label, + track_property: experiment_tracking_category_and_group(:invite_members_new_dropdown) + } + ) + end + + # Overridden in EE + def create_epic_menu_item(group) + nil + end + end +end + +Nav::NewDropdownHelper.prepend_mod diff --git a/app/views/admin/application_settings/_account_and_limit.html.haml b/app/views/admin/application_settings/_account_and_limit.html.haml index 1e2c9f821d2..eb30efabb98 100644 --- a/app/views/admin/application_settings/_account_and_limit.html.haml +++ b/app/views/admin/application_settings/_account_and_limit.html.haml @@ -53,6 +53,14 @@ = _('Specify an e-mail address regex pattern to identify default internal users.') = link_to _('More information'), help_page_path('user/permissions', anchor: 'setting-new-users-to-external'), target: '_blank' + - unless Gitlab.com? + .form-group + = f.label :deactivate_dormant_users, _('Dormant users'), class: 'label-bold' + .form-check + = f.check_box :deactivate_dormant_users, class: 'form-check-input' + = f.label :deactivate_dormant_users, class: 'form-check-label' do + = _('Deactivate dormant users after 90 days of inactivity. Users can return to active status by signing in to their account. While inactive, a user is not counted as an active user in the instance.') + = link_to _('More information'), help_page_path('user/admin_area/moderate_users', anchor: 'automatically-deactivate-dormant-users'), target: '_blank' .form-group = f.label :personal_access_token_prefix, _('Personal Access Token prefix'), class: 'label-light' = f.text_field :personal_access_token_prefix, placeholder: _('Max 20 characters'), class: 'form-control gl-form-input' diff --git a/app/views/layouts/_head.html.haml b/app/views/layouts/_head.html.haml index b28cd47efcc..a59bc07a97b 100644 --- a/app/views/layouts/_head.html.haml +++ b/app/views/layouts/_head.html.haml @@ -36,7 +36,7 @@ = favicon_link_tag favicon, id: 'favicon', data: { original_href: favicon }, type: 'image/png' - = render 'layouts/startup_css' + = render 'layouts/startup_css', { startup_filename: local_assigns.fetch(:startup_filename, nil) } - if user_application_theme == 'gl-dark' = stylesheet_link_tag_defer "application_dark" = yield :page_specific_styles @@ -54,8 +54,6 @@ = stylesheet_link_tag 'performance_bar' if performance_bar_enabled? - -# Rendering this above Gon, to use in JS later - = render 'layouts/header/new_repo_experiment' = Gon::Base.render_data(nonce: content_security_policy_nonce) = javascript_include_tag locale_path unless I18n.locale == :en diff --git a/app/views/layouts/_startup_css.haml b/app/views/layouts/_startup_css.haml index 7d3cfe28007..67c871b95f5 100644 --- a/app/views/layouts/_startup_css.haml +++ b/app/views/layouts/_startup_css.haml @@ -1,4 +1,5 @@ -- startup_filename = current_path?("sessions#new") ? 'signin' : user_application_theme == 'gl-dark' ? 'dark' : 'general' +- startup_filename_default = user_application_theme == 'gl-dark' ? 'dark' : 'general' +- startup_filename = local_assigns.fetch(:startup_filename, nil) || startup_filename_default %style = Rails.application.assets_manifest.find_sources("themes/#{user_application_theme_css_filename}.css").first.to_s.html_safe if user_application_theme_css_filename diff --git a/app/views/layouts/devise.html.haml b/app/views/layouts/devise.html.haml index ef61a04c288..ae7c160c060 100644 --- a/app/views/layouts/devise.html.haml +++ b/app/views/layouts/devise.html.haml @@ -1,6 +1,6 @@ !!! 5 %html.devise-layout-html{ class: system_message_class } - = render "layouts/head" + = render "layouts/head", { startup_filename: 'signin' } %body.ui-indigo.login-page.application.navless{ class: "#{client_class_list}", data: { page: body_data_page, qa_selector: 'login_page' } } = header_message = render "layouts/init_client_detection_flags" diff --git a/app/views/layouts/header/_group_invite_members_new_dropdown_item.html.haml b/app/views/layouts/header/_group_invite_members_new_dropdown_item.html.haml deleted file mode 100644 index cb74c77dff8..00000000000 --- a/app/views/layouts/header/_group_invite_members_new_dropdown_item.html.haml +++ /dev/null @@ -1,3 +0,0 @@ -- return unless Gitlab::Experimentation.active?(:invite_members_new_dropdown) && can?(current_user, :admin_group_member, @group) - -%li= dropdown_invite_members_link(@group) diff --git a/app/views/layouts/header/_new_dropdown.html.haml b/app/views/layouts/header/_new_dropdown.html.haml index ca90d2e02fa..47846207978 100644 --- a/app/views/layouts/header/_new_dropdown.html.haml +++ b/app/views/layouts/header/_new_dropdown.html.haml @@ -1,47 +1,26 @@ -- new_repo_experiment_text = content_for(:new_repo_experiment) +- view_model = new_dropdown_view_model(project: @project, group: @group) +- menu_sections = view_model.fetch(:menu_sections) +- title = view_model.fetch(:title) +- show_headers = menu_sections.length > 1 + +- return if menu_sections.empty? + %li.header-new.dropdown{ data: { track_label: "new_dropdown", track_event: "click_dropdown", track_experiment: "new_repo" } } - = link_to new_project_path, class: "header-new-dropdown-toggle has-tooltip qa-new-menu-toggle", id: "js-onboarding-new-project-link", title: _("New..."), ref: 'tooltip', aria: { label: _("New...") }, data: { toggle: 'dropdown', placement: 'bottom', container: 'body', display: 'static' } do + = link_to new_project_path, class: "header-new-dropdown-toggle has-tooltip", id: "js-onboarding-new-project-link", title: title, ref: 'tooltip', aria: { label: title }, data: { toggle: 'dropdown', placement: 'bottom', container: 'body', display: 'static', qa_selector: 'new_menu_toggle' } do = sprite_icon('plus-square') = sprite_icon('chevron-down', css_class: 'caret-down') .dropdown-menu.dropdown-menu-right.dropdown-extended-height %ul - - if @group&.persisted? - - create_group_project = can?(current_user, :create_projects, @group) - - create_group_subgroup = can?(current_user, :create_subgroup, @group) - - - if create_group_project || create_group_subgroup - %li.dropdown-bold-header - = _('This group') - - if create_group_project - %li= link_to new_repo_experiment_text, new_project_path(namespace_id: @group.id), data: { track_experiment: 'new_repo', track_event: 'click_link_new_project_group', track_label: 'plus_menu_dropdown' } - - if create_group_subgroup - %li= link_to _('New subgroup'), new_group_path(parent_id: @group.id), data: { track_event: 'click_link_new_subgroup', track_label: 'plus_menu_dropdown' } - = render_if_exists 'layouts/header/create_epic_new_dropdown_item' - = render 'layouts/header/group_invite_members_new_dropdown_item' + - menu_sections.each_with_index do |section, index| + - if index > 0 %li.divider - %li.dropdown-bold-header GitLab - - - if @project&.persisted? - - create_project_issue = show_new_issue_link?(@project) - - merge_project = merge_request_source_project_for_project(@project) - - create_project_snippet = can?(current_user, :create_snippet, @project) - - - if create_project_issue || merge_project || create_project_snippet + - if show_headers %li.dropdown-bold-header - = _('This project') - - if create_project_issue - %li= link_to _('New issue'), new_project_issue_path(@project), data: { track_event: 'click_link_new_issue', track_label: 'plus_menu_dropdown' } - - if merge_project - %li= link_to _('New merge request'), project_new_merge_request_path(merge_project), data: { track_event: 'click_link_new_mr', track_label: 'plus_menu_dropdown' } - - - if create_project_snippet - %li= link_to _('New snippet'), new_project_snippet_path(@project), data: { track_event: 'click_link_new_snippet_project', track_label: 'plus_menu_dropdown' } - = render 'layouts/header/project_invite_members_new_dropdown_item' - %li.divider - %li.dropdown-bold-header GitLab - - if current_user.can_create_project? - %li= link_to new_repo_experiment_text, new_project_path, class: 'qa-global-new-project-link', data: { track_experiment: 'new_repo', track_event: 'click_link_new_project', track_label: 'plus_menu_dropdown' } - - if current_user.can_create_group? - %li= link_to _('New group'), new_group_path, data: { track_event: 'click_link_new_group', track_label: 'plus_menu_dropdown' } - - if current_user.can?(:create_snippet) - %li= link_to _('New snippet'), new_snippet_path, data: { track_event: 'click_link_new_snippet_parent', track_label: 'plus_menu_dropdown' }, class: 'qa-global-new-snippet-link' + = section.fetch(:title) + - section.fetch(:menu_items).each do |menu_item| + %li< + = link_to menu_item.fetch(:href), class: menu_item.fetch(:css_class), data: menu_item.fetch(:data) do + = menu_item.fetch(:title) + - if menu_item.fetch(:emoji) + -# We need to insert a space between the title and emoji + = " #{emoji_icon(menu_item.fetch(:emoji), 'aria-hidden': true, class: "gl-font-base gl-vertical-align-baseline")}".html_safe diff --git a/app/views/layouts/header/_new_repo_experiment.html.haml b/app/views/layouts/header/_new_repo_experiment.html.haml deleted file mode 100644 index aaa13d593cd..00000000000 --- a/app/views/layouts/header/_new_repo_experiment.html.haml +++ /dev/null @@ -1,6 +0,0 @@ -- content_for :new_repo_experiment do - - experiment(:new_repo, user: current_user) do |e| - - e.use do - = _('New project') - - e.try do - = _('New project/repository') diff --git a/app/views/layouts/header/_project_invite_members_new_dropdown_item.html.haml b/app/views/layouts/header/_project_invite_members_new_dropdown_item.html.haml deleted file mode 100644 index 2cb67e857e3..00000000000 --- a/app/views/layouts/header/_project_invite_members_new_dropdown_item.html.haml +++ /dev/null @@ -1,3 +0,0 @@ -- return unless Gitlab::Experimentation.active?(:invite_members_new_dropdown) && can_import_members? - -%li= dropdown_invite_members_link(@project) diff --git a/app/views/projects/buttons/_clone.html.haml b/app/views/projects/buttons/_clone.html.haml index ee195e69a98..74d10f11898 100644 --- a/app/views/projects/buttons/_clone.html.haml +++ b/app/views/projects/buttons/_clone.html.haml @@ -26,14 +26,19 @@ = clipboard_button(target: '#http_project_clone', title: _("Copy URL"), class: "input-group-text gl-button btn btn-icon btn-default") = render_if_exists 'projects/buttons/geo' %li.divider.mt-2 - %li.pt-2.gl-new-dropdown-item - %label.label-bold{ class: 'gl-px-4!' } - = _('Open in your IDE') + %li.pt-2.gl-new-dropdown-item + %label.label-bold{ class: 'gl-px-4!' } + = _('Open in your IDE') + - if ssh_enabled? + %a.dropdown-item.open-with-link{ href: 'vscode://vscode.git/clone?url=' + CGI.escape(project.ssh_url_to_repo) } + .gl-new-dropdown-item-text-wrapper + = _('Visual Studio Code (SSH)') + - if http_enabled? %a.dropdown-item.open-with-link{ href: 'vscode://vscode.git/clone?url=' + CGI.escape(project.http_url_to_repo) } .gl-new-dropdown-item-text-wrapper - = _('Visual Studio Code') - - if show_xcode_link?(@project) - %a.dropdown-item.open-with-link{ href: xcode_uri_to_repo(@project) } - .gl-new-dropdown-item-text-wrapper - = _("Xcode") + = _('Visual Studio Code (HTTPS)') + - if show_xcode_link?(@project) + %a.dropdown-item.open-with-link{ href: xcode_uri_to_repo(@project) } + .gl-new-dropdown-item-text-wrapper + = _("Xcode") = render_if_exists 'projects/buttons/kerberos_clone_field' diff --git a/doc/administration/job_logs.md b/doc/administration/job_logs.md index 3956146f0d7..510da68442c 100644 --- a/doc/administration/job_logs.md +++ b/doc/administration/job_logs.md @@ -10,7 +10,7 @@ type: reference > [Renamed from job traces to job logs](https://gitlab.com/gitlab-org/gitlab/-/issues/29121) in GitLab 12.5. Job logs are sent by a runner while it's processing a job. You can see -logs in job pages, pipelines, email notifications, etc. +logs in job pages, pipelines, email notifications, and so on. ## Data flow diff --git a/doc/api/settings.md b/doc/api/settings.md index ada1d0e7fc4..406688732fe 100644 --- a/doc/api/settings.md +++ b/doc/api/settings.md @@ -241,6 +241,7 @@ listed in the descriptions of the relevant settings. | `check_namespace_plan` | boolean | no | **(PREMIUM)** Enabling this makes only licensed EE features available to projects if the project namespace's plan includes the feature or if the project is public. | | `commit_email_hostname` | string | no | Custom hostname (for private commit emails). | | `container_registry_token_expire_delay` | integer | no | Container Registry token duration in minutes. | +| `deactivate_dormant_users` | boolean | no | Enable [atomatic deactivation of dormant users](../user/admin_area/moderate_users.md#automatically-deactivate-dormant-users). | | `default_artifacts_expire_in` | string | no | Set the default expiration time for each job's artifacts. | | `default_branch_protection` | integer | no | Determine if developers can push to the default branch. Can take: `0` _(not protected, both developers and maintainers can push new commits, force push, or delete the branch)_, `1` _(partially protected, developers and maintainers can push new commits, but cannot force push, or delete, the branch)_ or `2` _(fully protected, developers cannot push new commits, but maintainers can; no-one can force push or delete the branch)_ as a parameter. Default is `2`. | | `default_ci_config_path` | string | no | Default CI configuration path for new projects (`.gitlab-ci.yml` if not set). | diff --git a/doc/user/admin_area/moderate_users.md b/doc/user/admin_area/moderate_users.md index c04003dd75f..5afecc66294 100644 --- a/doc/user/admin_area/moderate_users.md +++ b/doc/user/admin_area/moderate_users.md @@ -95,6 +95,20 @@ Users can also be deactivated using the [GitLab API](../../api/users.md#deactiva NOTE: A deactivated user does not consume a [seat](../../subscriptions/self_managed/index.md#billable-users). +### Automatically deactivate dormant users + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/320875) in GitLab 14.0. + +Administrators can enable automatic deactivation of users who have not signed in, or have no activity in the last 90 days. To do this: + +1. Navigate to **Admin Area > Settings > General > Account and Limit**. +1. Under the **Dormant users** tab, check **Deactivate dormant users after 90 days of inactivity**. +1. Click **Save changes**. + +When this feature is enabled, GitLab runs a job once a day to deactivate the dormant users. + +A maximum of 100,000 users can be deactivated per day. + ### Activating a user > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/22257) in GitLab 12.4. diff --git a/doc/user/project/merge_requests/approvals/rules.md b/doc/user/project/merge_requests/approvals/rules.md index 32f0160771f..79b48ebb6d5 100644 --- a/doc/user/project/merge_requests/approvals/rules.md +++ b/doc/user/project/merge_requests/approvals/rules.md @@ -144,7 +144,7 @@ approve in these ways: [**Prevent committers approval**](settings.md#prevent-committers-from-approving-their-own-work) project setting. -### Code owners as eligible approvers +### Code owners as eligible approvers **(PREMIUM)** > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/7933) in GitLab 11.5. > - Moved to GitLab Premium in 13.9. @@ -162,7 +162,7 @@ You can also [require code owner approval](../../protected_branches.md#protected-branches-approval-by-code-owners) for protected branches. **(PREMIUM)** -## Merge request approval segregation of duties +## Merge request approval segregation of duties **(PREMIUM)** > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40491) in GitLab 13.4. > - Moved to GitLab Premium in 13.9. diff --git a/doc/user/project/repository/index.md b/doc/user/project/repository/index.md index ad54def0c2b..44ad592c07e 100644 --- a/doc/user/project/repository/index.md +++ b/doc/user/project/repository/index.md @@ -82,11 +82,11 @@ prompted to open XCode. > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/220957) in GitLab 13.10. -All projects can be cloned into Visual Studio Code. +All projects can be cloned into Visual Studio Code. To do that: 1. From the GitLab UI, go to the project's overview page. -1. Select **Clone**. -1. Select **Visual Studio Code**. +1. Click **Clone**. +1. Select **Clone with Visual Studio Code** under either HTTPS or SSH method. 1. Select a folder to clone the project into. When VS Code has successfully cloned your project, it opens the folder. @@ -100,7 +100,7 @@ You can download the source code that's stored in a repository. 1. Above the file list, select the download icon (**{download}**). 1. From the options, select the files you want to download. - + - **Source code:** Download the source code from the current branch you're viewing. Available extensions: `zip`, `tar`, `tar.gz`, and `tar.bz2`. diff --git a/doc/user/project/working_with_projects.md b/doc/user/project/working_with_projects.md index b96e990c4e8..3adcfc67117 100644 --- a/doc/user/project/working_with_projects.md +++ b/doc/user/project/working_with_projects.md @@ -84,6 +84,7 @@ Built-in templates are project templates that are: - Developed and maintained in the [`project-templates`](https://gitlab.com/gitlab-org/project-templates) and [`pages`](https://gitlab.com/pages) groups. - Released with GitLab. +- Anyone can contribute a built-in template by following [these steps](https://about.gitlab.com/community/contribute/project-templates). To use a built-in template on the **New project** page: diff --git a/lib/gitlab/nav/top_nav_menu_item.rb b/lib/gitlab/nav/top_nav_menu_item.rb index a5f835136fc..cfc9be02cbf 100644 --- a/lib/gitlab/nav/top_nav_menu_item.rb +++ b/lib/gitlab/nav/top_nav_menu_item.rb @@ -8,7 +8,7 @@ module Gitlab # this is already :/. We could also take a hash and manually check every # entry, but it's much more maintainable to do rely on native Ruby. # rubocop: disable Metrics/ParameterLists - def self.build(id:, title:, active: false, icon: '', href: '', view: '', css_class: '', data: {}) + def self.build(id:, title:, active: false, icon: '', href: '', view: '', css_class: nil, data: {}, emoji: nil) { id: id, title: title, @@ -17,7 +17,8 @@ module Gitlab href: href, view: view.to_s, css_class: css_class, - data: data + data: data, + emoji: emoji } end # rubocop: enable Metrics/ParameterLists diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 5fb394c657a..74a438a2873 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -10464,6 +10464,9 @@ msgstr "" msgid "Days to merge" msgstr "" +msgid "Deactivate dormant users after 90 days of inactivity. Users can return to active status by signing in to their account. While inactive, a user is not counted as an active user in the instance." +msgstr "" + msgid "Deactivate this user" msgstr "" @@ -11707,6 +11710,9 @@ msgstr "" msgid "Done" msgstr "" +msgid "Dormant users" +msgstr "" + msgid "Download" msgstr "" @@ -36232,7 +36238,10 @@ msgstr "" msgid "Visit settings page" msgstr "" -msgid "Visual Studio Code" +msgid "Visual Studio Code (HTTPS)" +msgstr "" + +msgid "Visual Studio Code (SSH)" msgstr "" msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:" diff --git a/package.json b/package.json index 25ff42eae2e..ef4b3dcb4ab 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,7 @@ "scripts": { "check-dependencies": "scripts/frontend/check_dependencies.sh", "block-dependencies": "node scripts/frontend/block_dependencies.js", + "check:startup_css": "scripts/frontend/startup_css/startup_css_changed.sh", "clean": "rm -rf public/assets tmp/cache/*-loader", "dev-server": "NODE_OPTIONS=\"--max-old-space-size=3584\" node scripts/frontend/webpack_dev_server.js", "file-coverage": "scripts/frontend/file_test_coverage.js", diff --git a/qa/qa/page/dashboard/snippet/index.rb b/qa/qa/page/dashboard/snippet/index.rb index 63589c376f6..d8314509b1f 100644 --- a/qa/qa/page/dashboard/snippet/index.rb +++ b/qa/qa/page/dashboard/snippet/index.rb @@ -7,6 +7,9 @@ module QA class Index < Page::Base view 'app/views/layouts/header/_new_dropdown.html.haml' do element :new_menu_toggle + end + + view 'app/helpers/nav/new_dropdown_helper.rb' do element :global_new_snippet_link end diff --git a/qa/qa/page/project/show.rb b/qa/qa/page/project/show.rb index c174d4b0c3f..6e5097c3812 100644 --- a/qa/qa/page/project/show.rb +++ b/qa/qa/page/project/show.rb @@ -24,7 +24,10 @@ module QA view 'app/views/layouts/header/_new_dropdown.html.haml' do element :new_menu_toggle - element :new_issue_link, "link_to _('New issue'), new_project_issue_path(@project)" # rubocop:disable QA/ElementWithPattern + end + + view 'app/helpers/nav/new_dropdown_helper.rb' do + element :new_issue_link end view 'app/views/projects/_last_push.html.haml' do @@ -115,7 +118,7 @@ module QA def go_to_new_issue click_element :new_menu_toggle - click_link 'New issue' + click_element(:new_issue_link) end def has_file?(name) diff --git a/scripts/frontend/startup_css/constants.js b/scripts/frontend/startup_css/constants.js index 9b9dc522a8f..a76092f8b45 100644 --- a/scripts/frontend/startup_css/constants.js +++ b/scripts/frontend/startup_css/constants.js @@ -27,7 +27,6 @@ const CSS_TO_REMOVE = [ /\.commit/, /\.md/, /\.with-performance-bar/, - /\.identicon/, ]; const APPLICATION_CSS_PREFIX = 'application'; const APPLICATION_DARK_CSS_PREFIX = 'application_dark'; @@ -36,49 +35,55 @@ const UTILITIES_DARK_CSS_PREFIX = 'application_utilities_dark'; // paths ----------------------------------------------------------------------- const ROOT = path.resolve(__dirname, '../../..'); +const ROOT_RAILS = IS_EE ? path.join(ROOT, 'ee') : ROOT; const FIXTURES_FOLDER_NAME = IS_EE ? 'fixtures-ee' : 'fixtures'; const FIXTURES_ROOT = path.join(ROOT, 'tmp/tests/frontend', FIXTURES_FOLDER_NAME); const PATH_SIGNIN_HTML = path.join(FIXTURES_ROOT, 'startup_css/sign-in.html'); const PATH_ASSETS = path.join(ROOT, 'tmp/startup_css_assets'); -const PATH_STARTUP_SCSS = path.join(ROOT, 'app/assets/stylesheets/startup'); +const PATH_STARTUP_SCSS = path.join(ROOT_RAILS, 'app/assets/stylesheets/startup'); + +// helpers --------------------------------------------------------------------- +const createMainOutput = ({ outFile, cssKeys, type }) => ({ + outFile, + htmlPaths: [ + path.join(FIXTURES_ROOT, `startup_css/project-${type}.html`), + path.join(FIXTURES_ROOT, `startup_css/project-${type}-legacy-menu.html`), + path.join(FIXTURES_ROOT, `startup_css/project-${type}-legacy-sidebar.html`), + path.join(FIXTURES_ROOT, `startup_css/project-${type}-signed-out.html`), + ], + cssKeys, + purgeOptions: { + safelist: { + standard: [ + 'page-with-icon-sidebar', + 'sidebar-collapsed-desktop', + // We want to include the root dropdown-menu style since it should be hidden by default + 'dropdown-menu', + ], + // We want to include the identicon backgrounds + greedy: [/^bg[0-9]$/], + }, + }, +}); + const OUTPUTS = [ - { + createMainOutput({ + type: 'general', outFile: 'startup-general', - htmlPaths: [ - path.join(FIXTURES_ROOT, 'startup_css/project-general.html'), - path.join(FIXTURES_ROOT, 'startup_css/project-general-legacy-menu.html'), - path.join(FIXTURES_ROOT, 'startup_css/project-general-signed-out.html'), - ], cssKeys: [APPLICATION_CSS_PREFIX, UTILITIES_CSS_PREFIX], - // We want to include the root dropdown-menu style since it should be hidden by default - purgeOptions: { - safelist: { - standard: ['dropdown-menu'], - }, - }, - }, - { + }), + createMainOutput({ + type: 'dark', outFile: 'startup-dark', - htmlPaths: [ - path.join(FIXTURES_ROOT, 'startup_css/project-dark.html'), - path.join(FIXTURES_ROOT, 'startup_css/project-dark-legacy-menu.html'), - path.join(FIXTURES_ROOT, 'startup_css/project-dark-signed-out.html'), - ], cssKeys: [APPLICATION_DARK_CSS_PREFIX, UTILITIES_DARK_CSS_PREFIX], - // We want to include the root dropdown-menu styles since it should be hidden by default - purgeOptions: { - safelist: { - standard: ['dropdown-menu'], - }, - }, - }, + }), { outFile: 'startup-signin', htmlPaths: [PATH_SIGNIN_HTML], cssKeys: [APPLICATION_CSS_PREFIX, UTILITIES_CSS_PREFIX], purgeOptions: { safelist: { - standard: ['fieldset'], + standard: ['fieldset', 'hidden'], deep: [/login-page$/], }, }, diff --git a/scripts/frontend/startup_css/startup_css_changed.sh b/scripts/frontend/startup_css/startup_css_changed.sh new file mode 100755 index 00000000000..2ae647557e4 --- /dev/null +++ b/scripts/frontend/startup_css/startup_css_changed.sh @@ -0,0 +1,40 @@ +#!/bin/sh + +echo "-----------------------------------------------------------" +echo "If you run into any issues with Startup CSS generation" +echo "please check out the feedback issue:" +echo "" +echo "https://gitlab.com/gitlab-org/gitlab/-/issues/331812" +echo "-----------------------------------------------------------" + +startup_glob="*stylesheets/startup*" + +echo "Staging changes to '${startup_glob}' so we can check for untracked files..." +git add ${startup_glob} + +if [ -n "$(git diff HEAD --name-only -- ${startup_glob})" ]; then + diff=$(git diff HEAD -- ${startup_glob}) + cat <<EOF + +Startup CSS changes detected! + +It looks like there have been recent changes which require +regenerating the Startup CSS files. + +**What should I do now?** + +IMPORTANT: Please make sure to update your MR title with `[RUN AS-IF-FOSS]` and start a new MR pipeline + +To fix this job, consider one of the following options: + + 1. Regenerating locally with "yarn run generate:startup_css". + 2. Copy and apply the following diff: + +----- start diff ----- +$diff + +----- end diff ------- +EOF + + exit 1 +fi diff --git a/scripts/frontend/startup_css/write_startup_scss.js b/scripts/frontend/startup_css/write_startup_scss.js index 3754b95cefd..245681bada3 100644 --- a/scripts/frontend/startup_css/write_startup_scss.js +++ b/scripts/frontend/startup_css/write_startup_scss.js @@ -9,7 +9,7 @@ const buildFinalContent = (raw) => { // https://gitlab.com/gitlab-org/gitlab/-/issues/331812 @charset "UTF-8"; ${raw} -@import 'cloaking'; +@import 'startup/cloaking'; @include cloak-startup-scss(none); `; diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb index 7cccac11363..c289c18126d 100644 --- a/spec/features/admin/admin_settings_spec.rb +++ b/spec/features/admin/admin_settings_spec.rb @@ -8,9 +8,11 @@ RSpec.describe 'Admin updates settings' do include UsageDataHelpers let(:admin) { create(:admin) } + let(:dot_com?) { false } context 'application setting :admin_mode is enabled', :request_store do before do + allow(Gitlab).to receive(:com?).and_return(dot_com?) stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false') sign_in(admin) gitlab_enable_admin_mode_sign_in(admin) @@ -127,6 +129,37 @@ RSpec.describe 'Admin updates settings' do expect(user_internal_regex['placeholder']).to eq 'Regex pattern' end + context 'Dormant users' do + context 'when Gitlab.com' do + let(:dot_com?) { true } + + it 'does not expose the setting' do + expect(page).to have_no_selector('#application_setting_deactivate_dormant_users') + end + end + + context 'when not Gitlab.com' do + let(:dot_com?) { false } + + it 'change Dormant users' do + expect(page).to have_unchecked_field('Deactivate dormant users after 90 days of inactivity') + expect(current_settings.deactivate_dormant_users).to be_falsey + + page.within('.as-account-limit') do + check 'application_setting_deactivate_dormant_users' + click_button 'Save changes' + end + + expect(page).to have_content "Application settings saved successfully" + + page.refresh + + expect(current_settings.deactivate_dormant_users).to be_truthy + expect(page).to have_checked_field('Deactivate dormant users after 90 days of inactivity') + end + end + end + context 'Change Sign-up restrictions' do context 'Require Admin approval for new signup setting' do it 'changes the setting', :js do diff --git a/spec/features/projects/show/user_sees_collaboration_links_spec.rb b/spec/features/projects/show/user_sees_collaboration_links_spec.rb index ffdfbb9fe81..613033373e8 100644 --- a/spec/features/projects/show/user_sees_collaboration_links_spec.rb +++ b/spec/features/projects/show/user_sees_collaboration_links_spec.rb @@ -12,6 +12,10 @@ RSpec.describe 'Projects > Show > Collaboration links', :js do sign_in(user) end + def find_new_menu_toggle + find('#js-onboarding-new-project-link') + end + context 'with developer user' do before do project.add_developer(user) @@ -22,7 +26,7 @@ RSpec.describe 'Projects > Show > Collaboration links', :js do # The navigation bar page.within('.header-new') do - find('.qa-new-menu-toggle').click + find_new_menu_toggle.click aggregate_failures 'dropdown links in the navigation bar' do expect(page).to have_link('New issue') @@ -30,7 +34,7 @@ RSpec.describe 'Projects > Show > Collaboration links', :js do expect(page).to have_link('New snippet', href: new_project_snippet_path(project)) end - find('.qa-new-menu-toggle').click + find_new_menu_toggle.click end # The dropdown above the tree @@ -56,7 +60,7 @@ RSpec.describe 'Projects > Show > Collaboration links', :js do visit project_path(project) page.within('.header-new') do - find('.qa-new-menu-toggle').click + find_new_menu_toggle.click aggregate_failures 'dropdown links' do expect(page).not_to have_link('New issue') @@ -64,7 +68,7 @@ RSpec.describe 'Projects > Show > Collaboration links', :js do expect(page).not_to have_link('New snippet', href: new_project_snippet_path(project)) end - find('.qa-new-menu-toggle').click + find_new_menu_toggle.click end expect(page).not_to have_selector('.qa-add-to-tree') diff --git a/spec/frontend/fixtures/startup_css.rb b/spec/frontend/fixtures/startup_css.rb index 134d29d3106..003f7b768dd 100644 --- a/spec/frontend/fixtures/startup_css.rb +++ b/spec/frontend/fixtures/startup_css.rb @@ -11,12 +11,13 @@ RSpec.describe 'Startup CSS fixtures', type: :controller do before(:all) do stub_feature_flags(combined_menu: true) + stub_feature_flags(sidebar_refactor: true) clean_frontend_fixtures('startup_css/') end shared_examples 'startup css project fixtures' do |type| let(:user) { create(:user, :admin) } - let(:project) { create(:project, :public, :repository, description: 'Code and stuff', avatar: fixture_file_upload('spec/fixtures/dk.png', 'image/png'), creator: user) } + let(:project) { create(:project, :public, :repository, description: 'Code and stuff', creator: user) } before do sign_in(user) @@ -42,6 +43,17 @@ RSpec.describe 'Startup CSS fixtures', type: :controller do expect(response).to be_successful end + it "startup_css/project-#{type}-legacy-sidebar.html" do + stub_feature_flags(sidebar_refactor: false) + + get :show, params: { + namespace_id: project.namespace.to_param, + id: project + } + + expect(response).to be_successful + end + it "startup_css/project-#{type}-signed-out.html" do sign_out(user) diff --git a/spec/frontend/frequent_items/components/app_spec.js b/spec/frontend/frequent_items/components/app_spec.js index 7a1026e8bfc..a94cb3e2fcc 100644 --- a/spec/frontend/frequent_items/components/app_spec.js +++ b/spec/frontend/frequent_items/components/app_spec.js @@ -21,13 +21,14 @@ const TEST_NAMESPACE = 'projects'; const TEST_VUEX_MODULE = 'frequentProjects'; const TEST_PROJECT = currentSession[TEST_NAMESPACE].project; const TEST_STORAGE_KEY = currentSession[TEST_NAMESPACE].storageKey; +const TEST_SEARCH_CLASS = 'test-search-class'; describe('Frequent Items App Component', () => { let wrapper; let mock; let store; - const createComponent = ({ currentItem = null } = {}) => { + const createComponent = (props = {}) => { const session = currentSession[TEST_NAMESPACE]; gon.api_version = session.apiVersion; @@ -36,7 +37,8 @@ describe('Frequent Items App Component', () => { propsData: { namespace: TEST_NAMESPACE, currentUserName: session.username, - currentItem: currentItem || session.project, + currentItem: session.project, + ...props, }, provide: { vuexModule: TEST_VUEX_MODULE, @@ -88,7 +90,7 @@ describe('Frequent Items App Component', () => { }); it('should render search input', () => { - expect(findSearchInput().exists()).toBe(true); + expect(findSearchInput().classes()).toEqual(['search-input-container']); }); it('should render loading animation', async () => { @@ -159,6 +161,16 @@ describe('Frequent Items App Component', () => { }); }); + describe('with searchClass', () => { + beforeEach(() => { + createComponent({ searchClass: TEST_SEARCH_CLASS }); + }); + + it('should render search input with searchClass', () => { + expect(findSearchInput().classes()).toEqual(['search-input-container', TEST_SEARCH_CLASS]); + }); + }); + describe('logging', () => { it('when created, it should create a project storage entry and adds a project', () => { createComponent(); diff --git a/spec/frontend/integrations/edit/components/active_checkbox_spec.js b/spec/frontend/integrations/edit/components/active_checkbox_spec.js index 0e56fb6454e..df7ffd19747 100644 --- a/spec/frontend/integrations/edit/components/active_checkbox_spec.js +++ b/spec/frontend/integrations/edit/components/active_checkbox_spec.js @@ -1,5 +1,6 @@ import { GlFormCheckbox } from '@gitlab/ui'; import { mount } from '@vue/test-utils'; + import ActiveCheckbox from '~/integrations/edit/components/active_checkbox.vue'; import { createStore } from '~/integrations/edit/store'; diff --git a/spec/frontend/integrations/edit/components/confirmation_modal_spec.js b/spec/frontend/integrations/edit/components/confirmation_modal_spec.js index 1c126f60c37..805d3971994 100644 --- a/spec/frontend/integrations/edit/components/confirmation_modal_spec.js +++ b/spec/frontend/integrations/edit/components/confirmation_modal_spec.js @@ -1,5 +1,6 @@ import { GlModal } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; + import ConfirmationModal from '~/integrations/edit/components/confirmation_modal.vue'; import { createStore } from '~/integrations/edit/store'; @@ -13,13 +14,10 @@ describe('ConfirmationModal', () => { }; afterEach(() => { - if (wrapper) { - wrapper.destroy(); - wrapper = null; - } + wrapper.destroy(); }); - const findGlModal = () => wrapper.find(GlModal); + const findGlModal = () => wrapper.findComponent(GlModal); describe('template', () => { beforeEach(() => { diff --git a/spec/frontend/integrations/edit/components/dynamic_field_spec.js b/spec/frontend/integrations/edit/components/dynamic_field_spec.js index 2ebb3333c0f..8784b3c2b00 100644 --- a/spec/frontend/integrations/edit/components/dynamic_field_spec.js +++ b/spec/frontend/integrations/edit/components/dynamic_field_spec.js @@ -1,5 +1,6 @@ import { GlFormGroup, GlFormCheckbox, GlFormInput, GlFormSelect, GlFormTextarea } from '@gitlab/ui'; import { mount } from '@vue/test-utils'; + import DynamicField from '~/integrations/edit/components/dynamic_field.vue'; describe('DynamicField', () => { @@ -24,17 +25,14 @@ describe('DynamicField', () => { }; afterEach(() => { - if (wrapper) { - wrapper.destroy(); - wrapper = null; - } + wrapper.destroy(); }); - const findGlFormGroup = () => wrapper.find(GlFormGroup); - const findGlFormCheckbox = () => wrapper.find(GlFormCheckbox); - const findGlFormInput = () => wrapper.find(GlFormInput); - const findGlFormSelect = () => wrapper.find(GlFormSelect); - const findGlFormTextarea = () => wrapper.find(GlFormTextarea); + const findGlFormGroup = () => wrapper.findComponent(GlFormGroup); + const findGlFormCheckbox = () => wrapper.findComponent(GlFormCheckbox); + const findGlFormInput = () => wrapper.findComponent(GlFormInput); + const findGlFormSelect = () => wrapper.findComponent(GlFormSelect); + const findGlFormTextarea = () => wrapper.findComponent(GlFormTextarea); describe('template', () => { describe.each([ diff --git a/spec/frontend/integrations/edit/components/integration_form_spec.js b/spec/frontend/integrations/edit/components/integration_form_spec.js index c015fd0b9e0..cbce26762b1 100644 --- a/spec/frontend/integrations/edit/components/integration_form_spec.js +++ b/spec/frontend/integrations/edit/components/integration_form_spec.js @@ -1,6 +1,6 @@ -import { shallowMount } from '@vue/test-utils'; import { setHTMLFixture } from 'helpers/fixtures'; -import { extendedWrapper } from 'helpers/vue_test_utils_helper'; +import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; + import { mockIntegrationProps } from 'jest/integrations/edit/mock_data'; import ActiveCheckbox from '~/integrations/edit/components/active_checkbox.vue'; import ConfirmationModal from '~/integrations/edit/components/confirmation_modal.vue'; @@ -23,42 +23,37 @@ describe('IntegrationForm', () => { initialState = {}, props = {}, } = {}) => { - wrapper = extendedWrapper( - shallowMount(IntegrationForm, { - propsData: { ...props }, - store: createStore({ - customState: { ...mockIntegrationProps, ...customStateProps }, - ...initialState, - }), - stubs: { - OverrideDropdown, - ActiveCheckbox, - ConfirmationModal, - JiraTriggerFields, - TriggerFields, - }, - provide: { - glFeatures: featureFlags, - }, + wrapper = shallowMountExtended(IntegrationForm, { + propsData: { ...props }, + store: createStore({ + customState: { ...mockIntegrationProps, ...customStateProps }, + ...initialState, }), - ); + stubs: { + OverrideDropdown, + ActiveCheckbox, + ConfirmationModal, + JiraTriggerFields, + TriggerFields, + }, + provide: { + glFeatures: featureFlags, + }, + }); }; afterEach(() => { - if (wrapper) { - wrapper.destroy(); - wrapper = null; - } + wrapper.destroy(); }); - const findOverrideDropdown = () => wrapper.find(OverrideDropdown); - const findActiveCheckbox = () => wrapper.find(ActiveCheckbox); - const findConfirmationModal = () => wrapper.find(ConfirmationModal); - const findResetConfirmationModal = () => wrapper.find(ResetConfirmationModal); - const findResetButton = () => wrapper.find('[data-testid="reset-button"]'); - const findJiraTriggerFields = () => wrapper.find(JiraTriggerFields); - const findJiraIssuesFields = () => wrapper.find(JiraIssuesFields); - const findTriggerFields = () => wrapper.find(TriggerFields); + const findOverrideDropdown = () => wrapper.findComponent(OverrideDropdown); + const findActiveCheckbox = () => wrapper.findComponent(ActiveCheckbox); + const findConfirmationModal = () => wrapper.findComponent(ConfirmationModal); + const findResetConfirmationModal = () => wrapper.findComponent(ResetConfirmationModal); + const findResetButton = () => wrapper.findByTestId('reset-button'); + const findJiraTriggerFields = () => wrapper.findComponent(JiraTriggerFields); + const findJiraIssuesFields = () => wrapper.findComponent(JiraIssuesFields); + const findTriggerFields = () => wrapper.findComponent(TriggerFields); describe('template', () => { describe('showActive is true', () => { @@ -286,7 +281,7 @@ describe('IntegrationForm', () => { </div> `); - it('renders `helpHtml`', async () => { + it('renders `helpHtml`', () => { const mockHelpHtml = document.querySelector(`[data-testid="${mockTestId}"]`); createComponent({ diff --git a/spec/frontend/integrations/edit/components/jira_issues_fields_spec.js b/spec/frontend/integrations/edit/components/jira_issues_fields_spec.js index 9cc041490d0..eb5f7e9fe40 100644 --- a/spec/frontend/integrations/edit/components/jira_issues_fields_spec.js +++ b/spec/frontend/integrations/edit/components/jira_issues_fields_spec.js @@ -1,5 +1,6 @@ import { GlFormCheckbox, GlFormInput } from '@gitlab/ui'; -import { mount } from '@vue/test-utils'; +import { mountExtended } from 'helpers/vue_test_utils_helper'; + import JiraIssuesFields from '~/integrations/edit/components/jira_issues_fields.vue'; import JiraUpgradeCta from '~/integrations/edit/components/jira_upgrade_cta.vue'; import eventHub from '~/integrations/edit/event_hub'; @@ -20,7 +21,7 @@ describe('JiraIssuesFields', () => { defaultState: isInheriting ? {} : undefined, }); - wrapper = mount(JiraIssuesFields, { + wrapper = mountExtended(JiraIssuesFields, { propsData: { ...defaultProps, ...props }, store, stubs: ['jira-issue-creation-vulnerabilities'], @@ -37,7 +38,7 @@ describe('JiraIssuesFields', () => { findEnableCheckbox().find('[type=checkbox]').attributes('disabled'); const findProjectKey = () => wrapper.findComponent(GlFormInput); const findJiraUpgradeCta = () => wrapper.findComponent(JiraUpgradeCta); - const findJiraForVulnerabilities = () => wrapper.find('[data-testid="jira-for-vulnerabilities"]'); + const findJiraForVulnerabilities = () => wrapper.findByTestId('jira-for-vulnerabilities'); const setEnableCheckbox = async (isEnabled = true) => findEnableCheckbox().vm.$emit('input', isEnabled); diff --git a/spec/frontend/integrations/edit/components/jira_trigger_fields_spec.js b/spec/frontend/integrations/edit/components/jira_trigger_fields_spec.js index 5c04add61a1..9e01371f542 100644 --- a/spec/frontend/integrations/edit/components/jira_trigger_fields_spec.js +++ b/spec/frontend/integrations/edit/components/jira_trigger_fields_spec.js @@ -1,5 +1,6 @@ import { GlFormCheckbox } from '@gitlab/ui'; -import { mount } from '@vue/test-utils'; +import { mountExtended } from 'helpers/vue_test_utils_helper'; + import JiraTriggerFields from '~/integrations/edit/components/jira_trigger_fields.vue'; describe('JiraTriggerFields', () => { @@ -12,7 +13,7 @@ describe('JiraTriggerFields', () => { }; const createComponent = (props, isInheriting = false) => { - wrapper = mount(JiraTriggerFields, { + wrapper = mountExtended(JiraTriggerFields, { propsData: { ...defaultProps, ...props }, computed: { isInheriting: () => isInheriting, @@ -21,18 +22,15 @@ describe('JiraTriggerFields', () => { }; afterEach(() => { - if (wrapper) { - wrapper.destroy(); - wrapper = null; - } + wrapper.destroy(); }); - const findCommentSettings = () => wrapper.find('[data-testid="comment-settings"]'); - const findCommentDetail = () => wrapper.find('[data-testid="comment-detail"]'); - const findCommentSettingsCheckbox = () => findCommentSettings().find(GlFormCheckbox); + const findCommentSettings = () => wrapper.findByTestId('comment-settings'); + const findCommentDetail = () => wrapper.findByTestId('comment-detail'); + const findCommentSettingsCheckbox = () => findCommentSettings().findComponent(GlFormCheckbox); const findIssueTransitionEnabled = () => wrapper.find('[data-testid="issue-transition-enabled"] input[type="checkbox"]'); - const findIssueTransitionMode = () => wrapper.find('[data-testid="issue-transition-mode"]'); + const findIssueTransitionMode = () => wrapper.findByTestId('issue-transition-mode'); const findIssueTransitionModeRadios = () => findIssueTransitionMode().findAll('input[type="radio"]'); const findIssueTransitionIdsField = () => diff --git a/spec/frontend/integrations/edit/components/jira_upgrade_cta_spec.js b/spec/frontend/integrations/edit/components/jira_upgrade_cta_spec.js index e49a1619627..e90e9a5d2ac 100644 --- a/spec/frontend/integrations/edit/components/jira_upgrade_cta_spec.js +++ b/spec/frontend/integrations/edit/components/jira_upgrade_cta_spec.js @@ -1,4 +1,5 @@ import { shallowMount } from '@vue/test-utils'; + import JiraUpgradeCta from '~/integrations/edit/components/jira_upgrade_cta.vue'; describe('JiraUpgradeCta', () => { @@ -18,13 +19,13 @@ describe('JiraUpgradeCta', () => { it('displays the correct message for premium and lower users', () => { createComponent({ showPremiumMessage: true }); - expect(wrapper.html()).toContain('This is a Premium feature'); - expect(wrapper.html()).toContain(contentMessage); + expect(wrapper.text()).toContain('This is a Premium feature'); + expect(wrapper.text()).toContain(contentMessage); }); it('displays the correct message for ultimate and lower users', () => { createComponent({ showUltimateMessage: true }); - expect(wrapper.html()).toContain('This is an Ultimate feature'); - expect(wrapper.html()).toContain(contentMessage); + expect(wrapper.text()).toContain('This is an Ultimate feature'); + expect(wrapper.text()).toContain(contentMessage); }); }); diff --git a/spec/frontend/integrations/edit/components/override_dropdown_spec.js b/spec/frontend/integrations/edit/components/override_dropdown_spec.js index 592f4514e45..eb43d940f5e 100644 --- a/spec/frontend/integrations/edit/components/override_dropdown_spec.js +++ b/spec/frontend/integrations/edit/components/override_dropdown_spec.js @@ -1,5 +1,6 @@ import { GlDropdown, GlLink } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; + import OverrideDropdown from '~/integrations/edit/components/override_dropdown.vue'; import { integrationLevels, overrideDropdownDescriptions } from '~/integrations/edit/constants'; import { createStore } from '~/integrations/edit/store'; @@ -26,14 +27,11 @@ describe('OverrideDropdown', () => { }; afterEach(() => { - if (wrapper) { - wrapper.destroy(); - wrapper = null; - } + wrapper.destroy(); }); - const findGlLink = () => wrapper.find(GlLink); - const findGlDropdown = () => wrapper.find(GlDropdown); + const findGlLink = () => wrapper.findComponent(GlLink); + const findGlDropdown = () => wrapper.findComponent(GlDropdown); describe('template', () => { describe('override prop is true', () => { diff --git a/spec/frontend/integrations/edit/components/trigger_fields_spec.js b/spec/frontend/integrations/edit/components/trigger_fields_spec.js index b9d16464e72..5f85c58da28 100644 --- a/spec/frontend/integrations/edit/components/trigger_fields_spec.js +++ b/spec/frontend/integrations/edit/components/trigger_fields_spec.js @@ -1,5 +1,6 @@ import { GlFormGroup, GlFormCheckbox, GlFormInput } from '@gitlab/ui'; -import { mount } from '@vue/test-utils'; +import { mountExtended } from 'helpers/vue_test_utils_helper'; + import TriggerFields from '~/integrations/edit/components/trigger_fields.vue'; describe('TriggerFields', () => { @@ -10,7 +11,7 @@ describe('TriggerFields', () => { }; const createComponent = (props, isInheriting = false) => { - wrapper = mount(TriggerFields, { + wrapper = mountExtended(TriggerFields, { propsData: { ...defaultProps, ...props }, computed: { isInheriting: () => isInheriting, @@ -19,21 +20,19 @@ describe('TriggerFields', () => { }; afterEach(() => { - if (wrapper) { - wrapper.destroy(); - wrapper = null; - } + wrapper.destroy(); }); + const findTriggerLabel = () => wrapper.findByTestId('trigger-fields-group').find('label'); const findAllGlFormGroups = () => wrapper.find('#trigger-fields').findAll(GlFormGroup); - const findAllGlFormCheckboxes = () => wrapper.findAll(GlFormCheckbox); - const findAllGlFormInputs = () => wrapper.findAll(GlFormInput); + const findAllGlFormCheckboxes = () => wrapper.findAllComponents(GlFormCheckbox); + const findAllGlFormInputs = () => wrapper.findAllComponents(GlFormInput); describe.each([true, false])('template, isInheriting = `%p`', (isInheriting) => { it('renders a label with text "Trigger"', () => { createComponent(); - const triggerLabel = wrapper.find('[data-testid="trigger-fields-group"]').find('label'); + const triggerLabel = findTriggerLabel(); expect(triggerLabel.exists()).toBe(true); expect(triggerLabel.text()).toBe('Trigger'); }); @@ -68,7 +67,7 @@ describe('TriggerFields', () => { }); it('renders GlFormInput with description for each event', () => { - const groups = wrapper.find('#trigger-fields').findAll(GlFormGroup); + const groups = findAllGlFormGroups(); expect(groups).toHaveLength(2); groups.wrappers.forEach((group, index) => { diff --git a/spec/frontend/integrations/index/components/integrations_list_spec.js b/spec/frontend/integrations/index/components/integrations_list_spec.js index 94fd7fc84ee..ee54a5fd359 100644 --- a/spec/frontend/integrations/index/components/integrations_list_spec.js +++ b/spec/frontend/integrations/index/components/integrations_list_spec.js @@ -1,5 +1,5 @@ -import { shallowMount } from '@vue/test-utils'; -import { extendedWrapper } from 'helpers/vue_test_utils_helper'; +import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; + import IntegrationsList from '~/integrations/index/components/integrations_list.vue'; import { mockActiveIntegrations, mockInactiveIntegrations } from '../mock_data'; @@ -10,7 +10,7 @@ describe('IntegrationsList', () => { const findInactiveIntegrationsTable = () => wrapper.findByTestId('inactive-integrations-table'); const createComponent = (propsData = {}) => { - wrapper = extendedWrapper(shallowMount(IntegrationsList, { propsData })); + wrapper = shallowMountExtended(IntegrationsList, { propsData }); }; afterEach(() => { diff --git a/spec/frontend/nav/components/top_nav_container_view_spec.js b/spec/frontend/nav/components/top_nav_container_view_spec.js index 12bee7a515e..311331ce8f5 100644 --- a/spec/frontend/nav/components/top_nav_container_view_spec.js +++ b/spec/frontend/nav/components/top_nav_container_view_spec.js @@ -16,8 +16,8 @@ const DEFAULT_PROPS = { }; const TEST_OTHER_PROPS = { namespace: 'projects', - currentUserName: '', - currentItem: {}, + currentUserName: 'test-user', + currentItem: { id: 'test' }, }; describe('~/nav/components/top_nav_container_view.vue', () => { @@ -84,7 +84,7 @@ describe('~/nav/components/top_nav_container_view.vue', () => { it('renders frequent items app', () => { expect(findFrequentItemsApp()).toEqual({ vuexModule: DEFAULT_PROPS.frequentItemsVuexModule, - props: TEST_OTHER_PROPS, + props: expect.objectContaining(TEST_OTHER_PROPS), attributes: expect.objectContaining(EXTRA_ATTRS), }); }); diff --git a/spec/helpers/application_settings_helper_spec.rb b/spec/helpers/application_settings_helper_spec.rb index c74ee3ce0ec..4c62b3e12c1 100644 --- a/spec/helpers/application_settings_helper_spec.rb +++ b/spec/helpers/application_settings_helper_spec.rb @@ -37,8 +37,24 @@ RSpec.describe ApplicationSettingsHelper do it_behaves_like 'when HTTP protocol is in use', 'https' it_behaves_like 'when HTTP protocol is in use', 'http' - context 'with tracking parameters' do - it { expect(visible_attributes).to include(*%i(snowplow_collector_hostname snowplow_cookie_domain snowplow_enabled snowplow_app_id)) } + describe '.visible_attributes' do + it 'contains tracking parameters' do + expect(helper.visible_attributes).to include(*%i(snowplow_collector_hostname snowplow_cookie_domain snowplow_enabled snowplow_app_id)) + end + + it 'contains :deactivate_dormant_users' do + expect(helper.visible_attributes).to include(:deactivate_dormant_users) + end + + context 'when GitLab.com' do + before do + allow(Gitlab).to receive(:com?).and_return(true) + end + + it 'does not contain :deactivate_dormant_users' do + expect(helper.visible_attributes).not_to include(:deactivate_dormant_users) + end + end end describe '.integration_expanded?' do diff --git a/spec/helpers/invite_members_helper_spec.rb b/spec/helpers/invite_members_helper_spec.rb index 122f2339b28..3d2adaa5b5d 100644 --- a/spec/helpers/invite_members_helper_spec.rb +++ b/spec/helpers/invite_members_helper_spec.rb @@ -114,69 +114,4 @@ RSpec.describe InviteMembersHelper do end end end - - describe '#dropdown_invite_members_link' do - shared_examples_for 'dropdown invite members link' do - let(:link_regex) do - /data-track-event="click_link".*data-track-property="_track_property_".*Invite members/ - end - - before do - allow(helper).to receive(:experiment_tracking_category_and_group) { '_track_property_' } - allow(helper).to receive(:current_user) { owner } - end - - it 'records the experiment' do - allow(helper).to receive(:experiment_enabled?) - - helper.dropdown_invite_members_link(form_model) - - expect(helper).to have_received(:experiment_tracking_category_and_group).with(:invite_members_new_dropdown) - end - - context 'with experiment enabled' do - before do - allow(helper).to receive(:experiment_enabled?).with(:invite_members_new_dropdown) { true } - end - - it 'returns link' do - link = helper.dropdown_invite_members_link(form_model) - - expect(link).to match(link_regex) - expect(link).to include(link_href) - expect(link).to include('gl-emoji') - end - end - - context 'with no experiment enabled' do - before do - allow(helper).to receive(:experiment_enabled?).with(:invite_members_new_dropdown) { false } - end - - it 'returns link' do - link = helper.dropdown_invite_members_link(form_model) - - expect(link).to match(link_regex) - expect(link).to include(link_href) - expect(link).not_to include('gl-emoji') - end - end - end - - context 'with a project' do - let_it_be(:form_model) { project } - - let(:link_href) { "href=\"#{project_project_members_path(form_model)}\"" } - - it_behaves_like 'dropdown invite members link' - end - - context 'with a group' do - let_it_be(:form_model) { create(:group) } - - let(:link_href) { "href=\"#{group_group_members_path(form_model)}\"" } - - it_behaves_like 'dropdown invite members link' - end - end end diff --git a/spec/helpers/nav/new_dropdown_helper_spec.rb b/spec/helpers/nav/new_dropdown_helper_spec.rb new file mode 100644 index 00000000000..dd860ce3180 --- /dev/null +++ b/spec/helpers/nav/new_dropdown_helper_spec.rb @@ -0,0 +1,320 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Nav::NewDropdownHelper do + describe '#new_dropdown_view_model' do + let_it_be(:user) { build_stubbed(:user) } + + let(:current_user) { user } + let(:current_project) { nil } + let(:current_group) { nil } + + let(:with_can_create_project) { false } + let(:with_can_create_group) { false } + let(:with_can_create_snippet) { false } + let(:with_new_repo_experiment) { :control } + let(:with_invite_members_experiment) { false } + let(:with_invite_members_experiment_enabled) { false } + + let(:subject) { helper.new_dropdown_view_model(project: current_project, group: current_group) } + + def expected_menu_section(title:, menu_item:) + [ + { + title: title, + menu_items: [menu_item] + } + ] + end + + before do + stub_experiments(new_repo: with_new_repo_experiment) + allow(::Gitlab::Experimentation).to receive(:active?).with(:invite_members_new_dropdown) { with_invite_members_experiment } + allow(helper).to receive(:experiment_enabled?).with(:invite_members_new_dropdown) { with_invite_members_experiment_enabled } + allow(helper).to receive(:tracking_label) { 'test_tracking_label' } + allow(helper).to receive(:experiment_tracking_category_and_group) { |x| x } + + allow(helper).to receive(:current_user) { current_user } + allow(helper).to receive(:can?) { false } + + allow(user).to receive(:can_create_project?) { with_can_create_project } + allow(user).to receive(:can_create_group?) { with_can_create_group } + allow(user).to receive(:can?).with(:create_snippet) { with_can_create_snippet } + end + + shared_examples 'new repo experiment shared example' do |title| + let(:with_new_repo_experiment) { :candidate } + + it 'has experiment project title' do + expect(subject[:menu_sections]).to match( + expected_menu_section( + title: title, + menu_item: a_hash_including(title: 'New project/repository') + ) + ) + end + end + + shared_examples 'invite member link shared example' do + it 'shows invite member link' do + expect(subject[:menu_sections]).to eq( + expected_menu_section( + title: expected_title, + menu_item: ::Gitlab::Nav::TopNavMenuItem.build( + id: 'invite', + title: 'Invite members', + href: expected_href, + data: { + track_event: 'click_link', + track_label: 'test_tracking_label', + track_property: :invite_members_new_dropdown + } + ) + ) + ) + end + + context 'with experiment enabled' do + let(:with_invite_members_experiment_enabled) { true } + + it 'shows emoji with invite member link' do + expect(subject[:menu_sections]).to match( + expected_menu_section( + title: expected_title, + menu_item: a_hash_including( + emoji: 'shaking_hands' + ) + ) + ) + end + end + end + + it 'has title' do + expect(subject[:title]).to eq('New...') + end + + context 'when current_user is nil (anonymous)' do + let(:current_user) { nil } + + it 'is nil' do + expect(subject).to be_nil + end + end + + context 'when group and project are nil' do + it 'has no menu sections' do + expect(subject[:menu_sections]).to eq([]) + end + + context 'when can create project' do + let(:with_can_create_project) { true } + + it 'has project menu item' do + expect(subject[:menu_sections]).to eq( + expected_menu_section( + title: 'GitLab', + menu_item: ::Gitlab::Nav::TopNavMenuItem.build( + id: 'general_new_project', + title: 'New project', + href: '/projects/new', + data: { track_experiment: 'new_repo', track_event: 'click_link_new_project', track_label: 'plus_menu_dropdown', qa_selector: 'global_new_project_link' } + ) + ) + ) + end + + it_behaves_like 'new repo experiment shared example', 'GitLab' + end + + context 'when can create group' do + let(:with_can_create_group) { true } + + it 'has group menu item' do + expect(subject[:menu_sections]).to eq( + expected_menu_section( + title: 'GitLab', + menu_item: ::Gitlab::Nav::TopNavMenuItem.build( + id: 'general_new_group', + title: 'New group', + href: '/groups/new', + data: { track_event: 'click_link_new_group', track_label: 'plus_menu_dropdown' } + ) + ) + ) + end + end + + context 'when can create snippet' do + let(:with_can_create_snippet) { true } + + it 'has new snippet menu item' do + expect(subject[:menu_sections]).to eq( + expected_menu_section( + title: 'GitLab', + menu_item: ::Gitlab::Nav::TopNavMenuItem.build( + id: 'general_new_snippet', + title: 'New snippet', + href: '/-/snippets/new', + data: { track_event: 'click_link_new_snippet_parent', track_label: 'plus_menu_dropdown', qa_selector: 'global_new_snippet_link' } + ) + ) + ) + end + end + end + + context 'with persisted group' do + let_it_be(:group) { build_stubbed(:group) } + + let(:current_group) { group } + let(:with_can_create_projects_in_group) { false } + let(:with_can_create_subgroup_in_group) { false } + let(:with_can_admin_in_group) { false } + + before do + allow(group).to receive(:persisted?) { true } + allow(helper).to receive(:can?).with(current_user, :create_projects, group) { with_can_create_projects_in_group } + allow(helper).to receive(:can?).with(current_user, :create_subgroup, group) { with_can_create_subgroup_in_group } + allow(helper).to receive(:can?).with(current_user, :admin_group_member, group) { with_can_admin_in_group } + end + + it 'has no menu sections' do + expect(subject[:menu_sections]).to eq([]) + end + + context 'when can create projects in group' do + let(:with_can_create_projects_in_group) { true } + + it 'has new project menu item' do + expect(subject[:menu_sections]).to eq( + expected_menu_section( + title: 'This group', + menu_item: ::Gitlab::Nav::TopNavMenuItem.build( + id: 'new_project', + title: 'New project', + href: "/projects/new?namespace_id=#{group.id}", + data: { track_experiment: 'new_repo', track_event: 'click_link_new_project_group', track_label: 'plus_menu_dropdown' } + ) + ) + ) + end + + it_behaves_like 'new repo experiment shared example', 'This group' + end + + context 'when can create subgroup' do + let(:with_can_create_subgroup_in_group) { true } + + it 'has new subgroup menu item' do + expect(subject[:menu_sections]).to eq( + expected_menu_section( + title: 'This group', + menu_item: ::Gitlab::Nav::TopNavMenuItem.build( + id: 'new_subgroup', + title: 'New subgroup', + href: "/groups/new?parent_id=#{group.id}", + data: { track_event: 'click_link_new_subgroup', track_label: 'plus_menu_dropdown' } + ) + ) + ) + end + end + + context 'when can invite members' do + let(:with_can_admin_in_group) { true } + let(:with_invite_members_experiment) { true } + let(:expected_title) { 'This group' } + let(:expected_href) { "/groups/#{group.full_path}/-/group_members" } + + it_behaves_like 'invite member link shared example' + end + end + + context 'with persisted project' do + let_it_be(:project) { build_stubbed(:project) } + let_it_be(:merge_project) { build_stubbed(:project) } + + let(:current_project) { project } + let(:with_show_new_issue_link) { false } + let(:with_merge_project) { nil } + let(:with_can_create_snippet_in_project) { false } + let(:with_can_import_members) { false } + + before do + allow(helper).to receive(:show_new_issue_link?).with(project) { with_show_new_issue_link } + allow(helper).to receive(:merge_request_source_project_for_project).with(project) { with_merge_project } + allow(helper).to receive(:can?).with(user, :create_snippet, project) { with_can_create_snippet_in_project } + allow(helper).to receive(:can_import_members?) { with_can_import_members } + end + + it 'has no menu sections' do + expect(subject[:menu_sections]).to eq([]) + end + + context 'with show_new_issue_link?' do + let(:with_show_new_issue_link) { true } + + it 'shows new issue menu item' do + expect(subject[:menu_sections]).to eq( + expected_menu_section( + title: 'This project', + menu_item: ::Gitlab::Nav::TopNavMenuItem.build( + id: 'new_issue', + title: 'New issue', + href: "/#{project.path_with_namespace}/-/issues/new", + data: { track_event: 'click_link_new_issue', track_label: 'plus_menu_dropdown', qa_selector: 'new_issue_link' } + ) + ) + ) + end + end + + context 'with merge project' do + let(:with_merge_project) { merge_project } + + it 'shows merge project' do + expect(subject[:menu_sections]).to eq( + expected_menu_section( + title: 'This project', + menu_item: ::Gitlab::Nav::TopNavMenuItem.build( + id: 'new_mr', + title: 'New merge request', + href: "/#{merge_project.path_with_namespace}/-/merge_requests/new", + data: { track_event: 'click_link_new_mr', track_label: 'plus_menu_dropdown' } + ) + ) + ) + end + end + + context 'when can create snippet' do + let(:with_can_create_snippet_in_project) { true } + + it 'shows new snippet' do + expect(subject[:menu_sections]).to eq( + expected_menu_section( + title: 'This project', + menu_item: ::Gitlab::Nav::TopNavMenuItem.build( + id: 'new_snippet', + title: 'New snippet', + href: "/#{project.path_with_namespace}/-/snippets/new", + data: { track_event: 'click_link_new_snippet_project', track_label: 'plus_menu_dropdown' } + ) + ) + ) + end + end + + context 'when invite members experiment' do + let(:with_invite_members_experiment) { true } + let(:with_can_import_members) { true } + let(:expected_title) { 'This project' } + let(:expected_href) { "/#{project.path_with_namespace}/-/project_members" } + + it_behaves_like 'invite member link shared example' + end + end + end +end diff --git a/spec/lib/gitlab/nav/top_nav_menu_item_spec.rb b/spec/lib/gitlab/nav/top_nav_menu_item_spec.rb index c96bed2284b..966b23bf51a 100644 --- a/spec/lib/gitlab/nav/top_nav_menu_item_spec.rb +++ b/spec/lib/gitlab/nav/top_nav_menu_item_spec.rb @@ -13,7 +13,8 @@ RSpec.describe ::Gitlab::Nav::TopNavMenuItem do href: 'href', view: 'view', css_class: 'css_class', - data: {} + data: {}, + emoji: 'smile' } expect(described_class.build(**item)).to eq(item) diff --git a/spec/views/layouts/header/_new_dropdown.haml_spec.rb b/spec/views/layouts/header/_new_dropdown.haml_spec.rb index bf81ab577f7..319e7b55fc3 100644 --- a/spec/views/layouts/header/_new_dropdown.haml_spec.rb +++ b/spec/views/layouts/header/_new_dropdown.haml_spec.rb @@ -52,7 +52,6 @@ RSpec.describe 'layouts/header/_new_dropdown' do end it 'has a "New project" link' do - render('layouts/header/new_repo_experiment') render expect(rendered).to have_link('New project', href: new_project_path(namespace_id: group.id)) @@ -164,7 +163,6 @@ RSpec.describe 'layouts/header/_new_dropdown' do end it 'has a "New project" link' do - render('layouts/header/new_repo_experiment') render expect(rendered).to have_link('New project', href: new_project_path) @@ -182,13 +180,13 @@ RSpec.describe 'layouts/header/_new_dropdown' do expect(rendered).to have_link('New snippet', href: new_snippet_path) end - context 'when the user is not allowed to create snippets' do + context 'when the user is not allowed to do anything' do let(:user) { create(:user, :external) } - it 'has no "New snippet" link' do - render - - expect(rendered).not_to have_link('New snippet', href: new_snippet_path) + it 'is nil' do + # We have to us `view.render` because `render` causes issues + # https://github.com/rails/rails/issues/41320 + expect(view.render("layouts/header/new_dropdown")).to be_nil end end end diff --git a/workhorse/internal/lsif_transformer/parser/code_hover.go b/workhorse/internal/lsif_transformer/parser/code_hover.go index dbdaba643d1..5651ea8e5a3 100644 --- a/workhorse/internal/lsif_transformer/parser/code_hover.go +++ b/workhorse/internal/lsif_transformer/parser/code_hover.go @@ -50,9 +50,29 @@ func (ts *truncatableString) MarshalJSON() ([]byte, error) { return json.Marshal(ts.Value) } +func newCodeHovers(contents json.RawMessage) ([]*codeHover, error) { + var rawContents []json.RawMessage + if err := json.Unmarshal(contents, &rawContents); err != nil { + rawContents = []json.RawMessage{contents} + } + + codeHovers := []*codeHover{} + for _, rawContent := range rawContents { + c, err := newCodeHover(rawContent) + if err != nil { + return nil, err + } + + codeHovers = append(codeHovers, c) + } + + return codeHovers, nil +} + func newCodeHover(content json.RawMessage) (*codeHover, error) { // Hover value can be either an object: { "value": "func main()", "language": "go" } // Or a string with documentation + // Or a markdown object: { "value": "```go\nfunc main()\n```", "kind": "markdown" } // We try to unmarshal the content into a string and if we fail, we unmarshal it into an object var c codeHover if err := json.Unmarshal(content, &c.TruncatedValue); err != nil { diff --git a/workhorse/internal/lsif_transformer/parser/code_hover_test.go b/workhorse/internal/lsif_transformer/parser/code_hover_test.go index 2030e530155..c09636b2f76 100644 --- a/workhorse/internal/lsif_transformer/parser/code_hover_test.go +++ b/workhorse/internal/lsif_transformer/parser/code_hover_test.go @@ -64,21 +64,33 @@ func TestHighlight(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - raw := []byte(fmt.Sprintf(`{"language":"%s","value":"%s"}`, tt.language, tt.value)) - c, err := newCodeHover(json.RawMessage(raw)) + raw := []byte(fmt.Sprintf(`[{"language":"%s","value":"%s"}]`, tt.language, tt.value)) + c, err := newCodeHovers(json.RawMessage(raw)) require.NoError(t, err) - require.Equal(t, tt.want, c.Tokens) + require.Len(t, c, 1) + require.Equal(t, tt.want, c[0].Tokens) }) } } func TestMarkdown(t *testing.T) { - value := `"This method reverses a string \n\n"` - c, err := newCodeHover(json.RawMessage(value)) + value := `["This method reverses a string \n\n"]` + c, err := newCodeHovers(json.RawMessage(value)) require.NoError(t, err) - require.Equal(t, "This method reverses a string \n\n", c.TruncatedValue.Value) + require.Len(t, c, 1) + require.Equal(t, "This method reverses a string \n\n", c[0].TruncatedValue.Value) +} + +func TestMarkdownContentsFormat(t *testing.T) { + value := `{"kind":"markdown","value":"some _markdown_ **text**"}` + c, err := newCodeHovers(json.RawMessage(value)) + + require.NoError(t, err) + require.Len(t, c, 1) + require.Equal(t, [][]token(nil), c[0].Tokens) + require.Equal(t, "some _markdown_ **text**", c[0].TruncatedValue.Value) } func TestTruncatedValue(t *testing.T) { diff --git a/workhorse/internal/lsif_transformer/parser/hovers.go b/workhorse/internal/lsif_transformer/parser/hovers.go index e96d7e4fca3..5889d595ade 100644 --- a/workhorse/internal/lsif_transformer/parser/hovers.go +++ b/workhorse/internal/lsif_transformer/parser/hovers.go @@ -18,7 +18,7 @@ type Hovers struct { } type RawResult struct { - Contents []json.RawMessage `json:"contents"` + Contents json.RawMessage `json:"contents"` } type RawData struct { @@ -107,14 +107,9 @@ func (h *Hovers) addData(line []byte) error { return err } - codeHovers := []*codeHover{} - for _, rawContent := range rawData.Result.Contents { - c, err := newCodeHover(rawContent) - if err != nil { - return err - } - - codeHovers = append(codeHovers, c) + codeHovers, err := newCodeHovers(rawData.Result.Contents) + if err != nil { + return err } codeHoversData, err := json.Marshal(codeHovers) |