roadmap.scss 10.3 KB
Newer Older
1
$header-item-height: 60px;
Kushal Pandya's avatar
Kushal Pandya committed
2
$item-height: 50px;
3
$details-cell-width: 320px;
4
$timeline-cell-height: 32px;
Kushal Pandya's avatar
Kushal Pandya committed
5
$timeline-cell-width: 180px;
6
$border-style: 1px solid $border-gray-normal;
Lukas Eipert's avatar
Lukas Eipert committed
7 8
$roadmap-gradient-dark-gray: rgba(0, 0, 0, 0.15);
$roadmap-gradient-gray: rgba(255, 255, 255, 0.001);
9 10 11
$scroll-top-gradient: linear-gradient(to bottom, $roadmap-gradient-dark-gray 0%, $roadmap-gradient-gray 100%);
$scroll-bottom-gradient: linear-gradient(to bottom, $roadmap-gradient-gray 0%, $roadmap-gradient-dark-gray 100%);
$column-right-gradient: linear-gradient(to right, $roadmap-gradient-dark-gray 0%, $roadmap-gradient-gray 100%);
Lukas Eipert's avatar
Lukas Eipert committed
12

13 14 15 16 17 18
@keyframes colorTransitionDetailsCell {
  from {
    background-color: $blue-100;
  }

  to {
19
    background-color: $white;
20 21 22
  }
}

23 24 25 26 27
@mixin roadmap-scroll-mixin {
  height: $grid-size;
  width: $details-cell-width;
  pointer-events: none;
}
28

29 30 31 32 33 34 35 36 37 38
html.group-epics-roadmap-html {
  height: 100%;
  // We need to reset this just for Roadmap page
  overflow-y: initial;
}

.with-performance-bar {
  .group-epics-roadmap-body {
    $header-size: $performance-bar-height + $header-height;
    height: calc(100% - #{$header-size});
39 40 41
  }
}

42 43 44 45 46
.group-epics-roadmap-body {
  height: calc(100% - #{$header-height});

  .page-with-contextual-sidebar {
    height: 100%;
47 48
  }

49 50 51 52 53
  .group-epics-roadmap {
    // This size is total of breadcrumb height and computed height of
    // filters container (70px)
    $header-size: $breadcrumb-min-height + 70px;
    height: calc(100% - #{$header-size});
54 55
  }

56 57 58 59
  .group-epics-roadmap-wrapper,
  .group-epics-roadmap .content {
    height: 100%;
  }
Lukas Eipert's avatar
Lukas Eipert committed
60
}
Kushal Pandya's avatar
Kushal Pandya committed
61

62 63 64 65 66 67 68
.epics-details-filters {
  .btn-group {
    .dropdown-toggle {
      border-top-right-radius: 0;
      border-bottom-right-radius: 0;
    }

69
    .btn-sort-direction {
70 71 72
      border-left: 0;

      &:hover {
73
        border-color: $gray-darkest;
74 75
      }
    }
76 77 78 79

    @include media-breakpoint-down(xs) {
      display: flex;

80 81 82 83 84 85 86 87 88 89
      .dropdown-menu-sort {
        // This is a hack to fix dropdown alignment in small screens
        // where Bootstrap applies inline `transform: translate3d(...)`
        // and since our dropdown button has sort direction button
        // present, alignment needs to compensate for that space
        // without which it appears shifted towards left.
        //
        // One more approach is to override `transform` using `!important`
        // but that too involves using magic number
        margin-left: 27px;
90 91
      }
    }
92 93 94
  }
}

95 96 97 98 99 100 101 102
.epics-roadmap-filters {
  .epics-details-filters {
    .btn-roadmap-preset {
      padding: 7px $gl-btn-padding;
    }
  }
}

Kushal Pandya's avatar
Kushal Pandya committed
103 104 105 106 107 108 109 110
.group-epics-roadmap-wrapper {
  padding-bottom: 0;
}

.breadcrumbs.group-epics-roadmap {
  border-bottom: $border-style;

  .breadcrumbs-container {
Lukas Eipert's avatar
Lukas Eipert committed
111
    border-bottom: 0;
Kushal Pandya's avatar
Kushal Pandya committed
112 113 114
  }
}

115
.roadmap-container {
Kushal Pandya's avatar
Kushal Pandya committed
116
  overflow: hidden;
117
  height: 100%;
118 119 120 121

  &.overflow-reset {
    overflow: initial;
  }
122
}
Kushal Pandya's avatar
Kushal Pandya committed
123

124
.roadmap-shell {
Kushal Pandya's avatar
Kushal Pandya committed
125
  position: relative;
126 127
  height: 100%;
  width: 100%;
128
  overflow-x: auto;
Kushal Pandya's avatar
Kushal Pandya committed
129

Kushal Pandya's avatar
Kushal Pandya committed
130 131 132 133 134 135 136 137 138 139 140 141 142 143
  .skeleton-loader {
    position: absolute;
    top: $header-item-height;
    width: $details-cell-width;
    height: 100%;
    padding-top: $gl-padding-top;
    padding-left: $gl-padding;
    z-index: 4;

    &::after {
      height: 100%;
    }
  }

144 145
  &.prevent-vertical-scroll {
    overflow-y: hidden;
Kushal Pandya's avatar
Kushal Pandya committed
146 147 148
  }
}

Lukas Eipert's avatar
Lukas Eipert committed
149
.roadmap-timeline-section .timeline-header-blank::after,
Kushal Pandya's avatar
Kushal Pandya committed
150
.epics-list-section .epic-details-cell::after,
Florie Guibert's avatar
Florie Guibert committed
151
.milestones-list-section .milestones-list-title::after,
Kushal Pandya's avatar
Kushal Pandya committed
152
.skeleton-loader::after {
153
  content: '';
154 155 156 157 158 159 160
  position: absolute;
  top: 0;
  right: -$grid-size;
  width: $grid-size;
  pointer-events: none;
  background: $column-right-gradient;
}
Kushal Pandya's avatar
Kushal Pandya committed
161 162

.roadmap-timeline-section {
163 164 165
  position: sticky;
  position: -webkit-sticky;
  top: 0;
166
  z-index: 20;
Kushal Pandya's avatar
Kushal Pandya committed
167 168 169

  .timeline-header-blank,
  .timeline-header-item {
170 171
    float: left;
    height: $header-item-height;
Kushal Pandya's avatar
Kushal Pandya committed
172
    border-bottom: $border-style;
173
    background-color: $white;
174 175 176 177 178 179 180 181 182 183
  }

  .timeline-header-blank {
    position: sticky;
    position: -webkit-sticky;
    top: 0;
    left: 0;
    width: $details-cell-width;
    z-index: 2;

Lukas Eipert's avatar
Lukas Eipert committed
184
    &::after {
185 186
      height: $header-item-height;
    }
Kushal Pandya's avatar
Kushal Pandya committed
187 188 189
  }

  .timeline-header-item {
190 191
    width: $timeline-cell-width;

Kushal Pandya's avatar
Kushal Pandya committed
192
    &:last-of-type .item-label {
Lukas Eipert's avatar
Lukas Eipert committed
193 194 195 196 197
      border-right: 0;
    }

    .item-label,
    .item-sublabel .sublabel-value {
198
      color: $gray-600;
Lukas Eipert's avatar
Lukas Eipert committed
199 200 201
      font-weight: 400;

      &.label-dark {
202
        color: $gray-900;
Lukas Eipert's avatar
Lukas Eipert committed
203 204 205 206 207
      }

      &.label-bold {
        font-weight: 600;
      }
Kushal Pandya's avatar
Kushal Pandya committed
208 209 210 211 212 213 214 215 216 217 218 219 220
    }

    .item-label {
      padding: $gl-padding-8 $gl-padding;
      border-right: $border-style;
      border-bottom: $border-style;
    }

    .item-sublabel {
      position: relative;
      display: flex;

      .sublabel-value {
221
        flex-grow: 1;
222
        flex-basis: 0;
Kushal Pandya's avatar
Kushal Pandya committed
223
        text-align: center;
224
        font-size: $code-font-size;
225
        line-height: 1.5;
Kushal Pandya's avatar
Kushal Pandya committed
226 227
        padding: 2px 0;
      }
228
    }
Kushal Pandya's avatar
Kushal Pandya committed
229

230 231 232 233 234 235
    .current-day-indicator-header {
      bottom: 0;
      height: $gl-vert-padding;
      width: $gl-vert-padding;
      background-color: $red-500;
      border-radius: 50%;
236
      transform: translateX(-3px);
Kushal Pandya's avatar
Kushal Pandya committed
237 238
    }
  }
Lukas Eipert's avatar
Lukas Eipert committed
239 240 241

  &.scroll-top-shadow .timeline-header-blank::before {
    @include roadmap-scroll-mixin;
242
    content: '';
Lukas Eipert's avatar
Lukas Eipert committed
243 244 245
    position: absolute;
    left: 0;
    bottom: -$grid-size;
246
    border-top: 1px solid $white;
Lukas Eipert's avatar
Lukas Eipert committed
247 248
    background: $scroll-top-gradient;
  }
Kushal Pandya's avatar
Kushal Pandya committed
249 250 251
}

.epics-list-section {
252
  height: calc(100% - 60px);
253
}
254

255 256 257 258
.epics-list-item {
  &:hover {
    .epic-details-cell,
    .epic-timeline-cell {
259
      background-color: $gray-50;
260
    }
261
  }
262

263 264
  &.epics-list-item-empty {
    height: 100%;
265

266
    &:hover {
Kushal Pandya's avatar
Kushal Pandya committed
267 268
      .epic-details-cell,
      .epic-timeline-cell {
269
        background-color: $white;
270 271 272
      }
    }

Kushal Pandya's avatar
Kushal Pandya committed
273
    .epic-details-cell,
274
    .epic-details-cell::after,
Kushal Pandya's avatar
Kushal Pandya committed
275
    .epic-timeline-cell {
276
      height: 100%;
Kushal Pandya's avatar
Kushal Pandya committed
277
    }
278
  }
Kushal Pandya's avatar
Kushal Pandya committed
279

280
  &.newly-added-epic {
Kushal Pandya's avatar
Kushal Pandya committed
281
    .epic-details-cell {
282 283 284 285
      animation: colorTransitionDetailsCell 3s;
    }
  }
}
Kushal Pandya's avatar
Kushal Pandya committed
286

287 288 289 290 291 292
.epic-details-cell,
.epic-timeline-cell {
  float: left;
  height: $item-height;
  border-bottom: $border-style;
}
293

294 295 296 297
.epic-details-cell {
  position: sticky;
  position: -webkit-sticky;
  left: 0;
298
  line-height: 1.3;
299 300
  width: $details-cell-width;
  font-size: $code-font-size;
301
  background-color: $white;
302
  z-index: 10;
303

304 305 306
  &::after {
    height: $item-height;
  }
307
}
Kushal Pandya's avatar
Kushal Pandya committed
308

309 310 311 312
.epic-title,
.epic-group-timeframe {
  @include text-truncate;
}
313

314 315 316 317 318 319 320 321 322 323
.epic-timeline-cell {
  position: relative;
  width: $timeline-cell-width;
  background-color: transparent;
  border-right: $border-style;

  &:last-child {
    border-right: 0;
  }
}
Kushal Pandya's avatar
Kushal Pandya committed
324

325 326 327 328 329 330 331 332 333 334 335 336 337 338
.epic-bar-wrapper {
  position: relative;
}

.epic-bar {
  position: absolute;
  top: 5px;
  height: 40px;
  background-color: $blue-600;
  will-change: width, left;
  z-index: 5;

  &:hover {
    background-color: $blue-700;
Kushal Pandya's avatar
Kushal Pandya committed
339
  }
340
}
341

342 343 344 345
.epic-bar-inner {
  position: sticky;
  position: -webkit-sticky;
  left: $details-cell-width;
346
  color: $white;
347 348
}

349 350 351 352
.epic-bar-title {
  line-height: 1.2;
}

353 354 355 356
.epic-bar-progress {
  background-color: $blue-300;

  .progress-bar {
357
    background-color: $white;
Lukas Eipert's avatar
Lukas Eipert committed
358
  }
359
}
360

361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391
.epic-bar-child-epic {
  background-color: $white;
  border: 1px solid $blue-600;

  &:hover {
    background-color: $white;
    border: 1px solid $blue-700;
    text-decoration: none;

    .epic-bar-progress .progress-bar {
      background-color: $blue-700;
    }
  }

  .epic-bar-inner {
    color: $blue-600;

    &:hover {
      color: $blue-700;
    }
  }

  .epic-bar-progress {
    background-color: $blue-200;

    .progress-bar {
      background-color: $blue-600;
    }
  }
}

392 393 394 395 396 397 398 399
.epic-scroll-bottom-shadow {
  @include roadmap-scroll-mixin;
  position: fixed;
  bottom: 0;
  background: $scroll-bottom-gradient;
  z-index: 2;
}

Florie Guibert's avatar
Florie Guibert committed
400 401 402 403 404 405 406 407 408 409 410 411 412 413
.epic-timeline-cell,
.milestone-timeline-cell {
  .current-day-indicator {
    top: -1px;
    width: 2px;
    height: calc(100% + 1px);
    background-color: $red-500;
    pointer-events: none;
  }
}

.milestones-list-section {
  .milestones-list-items {
    .milestone-timeline-cell {
414
      height: $timeline-cell-height;
Florie Guibert's avatar
Florie Guibert committed
415 416 417 418
      width: $timeline-cell-width;
    }

    .timeline-bar-wrapper {
419
      height: $timeline-cell-height;
Florie Guibert's avatar
Florie Guibert committed
420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533
      color: $gray-700;
    }

    .milestone-start-and-end {
      display: none;
      border-left: 2px dotted $gray-900;
      border-right: 2px dotted $gray-900;
      opacity: 0.5;
      top: 1px;
    }

    .milestone-item-details {
      z-index: 1;

      &:hover .milestone-start-and-end {
        display: block;
      }
    }

    .milestone-item-title {
      left: $details-cell-width + $grid-size;
      height: 30px;
      z-index: 2;
    }

    a.milestone-url {
      color: inherit;
      max-width: 100%;

      &:hover {
        color: $gray-900;
        cursor: pointer;

        .timeline-bar {
          background-color: $gray-900;

          &::before {
            background-color: $gray-900;
          }

          &::after {
            border-color: $gray-900;
          }
        }
      }
    }

    .milestone-small,
    .milestone-minimum {
      .milestone-item-title {
        width: 100%;
        text-indent: -9999px;

        &::after {
          position: absolute;
          left: 0;
        }
      }
    }

    .milestone-small {
      .milestone-item-title::after {
        content: '...';
        text-indent: 0;
      }
    }

    .milestone-minimum {
      // We need important here to overwrite inline width which depends on dates
      width: 8px !important;

      .milestone-item-title::after {
        content: '.';
        text-indent: 5px;
      }

      .timeline-bar {
        height: 0;

        &::before {
          display: none;
        }
      }

      .milestone-start-and-end {
        border-left: 0;
      }
    }

    .timeline-bar {
      width: 100%;
      background-color: $gray-700;
      height: 2px;
      z-index: 1;
      bottom: 4px;

      &::before,
      &::after {
        content: '';
        position: absolute;
        top: -3px;
        height: 8px;
      }

      &::before {
        width: 2px;
        background-color: $gray-700;
      }

      &::after {
        right: -3px;
        width: 8px;
        border: 2px solid $gray-700;
        border-radius: 4px;
534
        background-color: $white;
Florie Guibert's avatar
Florie Guibert committed
535 536 537 538 539 540 541 542 543
      }
    }
  }

  .milestones-list-title {
    height: 100%;
    left: 0;
    width: $details-cell-width;
    font-size: $code-font-size;
544
    background-color: $white;
Florie Guibert's avatar
Florie Guibert committed
545 546 547 548 549 550 551
    z-index: 2;

    &::after {
      height: 100%;
    }
  }
}
552 553 554 555 556 557 558 559 560 561 562

.milestone-item-type {
  .gl-icon {
    padding-right: $gl-spacing-scale-1;
  }
}

.milestone-item-date {
  color: $gray-700;
  padding-top: $gl-spacing-scale-1;
}