Commit 793fc121 authored by Matthias Stegmann's avatar Matthias Stegmann Committed by Benni Mack
Browse files

[FEATURE] Introduce Bootstrap v5 for TYPO3 Backend

This changes removes the frontend framework
Bootstrap 3, and adds Bootstrap 5 beta 1 (we
expect Bootstrap 5 final by the time we release TYPO3 v11 LTS).

Bootstrap v3 is not supported by the Bootstrap
team any longer, so an update is critical for TYPO3 Core.

Bootstrap v5 adds a few accessibility improvements
as well as flexbox for rendering
containers and grids throughout TYPO3 Backend.

All JS components are not bound to jQuery anymore,
and have been reworked.

A lot of HTML/CSS changes happened, which we
slowly migrate (and not in a huge change)
to TYPO3's templates, in order to keep
this change managable.

A legacy CSS/SCSS file is added to
keep some backwards-compatibility classes
to ease the migration for extension developers
who have built their own backend modules.

Key features of Bootstrap 5:
* "rem" instead of "px" is used by default
* CSS variables are introduced
* Improved bootstrap focus outline styling (buttons / inputs / links)
* Simplified grid functionality
* use new button color mixin to increase contrast:
  Primary, Success and Warning Button color is now dark instead of white

EXT:styleguide was used as a basis for
upgrading to keep compatibility as much
as possible, but more changes will be coming
in the next few minor releases.

Resolves: #92616
Releases: master
Change-Id: Iec989f39649b5460b055ec879199faf38e424f2b
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/66247

Tested-by: default avatarTYPO3com <noreply@typo3.com>
Tested-by: Benjamin Franzke's avatarBenjamin Franzke <bfr@qbus.de>
Tested-by: Oliver Hader's avatarOliver Hader <oliver.hader@typo3.org>
Tested-by: Oliver Bartsch's avatarOliver Bartsch <bo@cedev.de>
Tested-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
Reviewed-by: Benjamin Franzke's avatarBenjamin Franzke <bfr@qbus.de>
Reviewed-by: Oliver Hader's avatarOliver Hader <oliver.hader@typo3.org>
Reviewed-by: Oliver Bartsch's avatarOliver Bartsch <bo@cedev.de>
Reviewed-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
parent 07bfbc84
......@@ -89,7 +89,7 @@ module.exports = function (grunt) {
outputStyle: 'expanded',
precision: 8,
includePaths: [
'node_modules/bootstrap-sass/assets/stylesheets',
'node_modules/bootstrap/scss',
'node_modules/font-awesome/scss',
'node_modules/tagsort'
]
......
//
// bootstrap v3 -> v5-beta-1 update
//
// known open todos:
//
// "scaffold-toolbar" (top right)
// - "Application Information" dropdown -> re-add colors
//
// forms module
// - missing progress bar styling (create new form layer) + cancel btn position
// - Step 2 "create new form layer" not working (JS loading spinner)
//
// Info module
// - "Pagetree overview": wrong table thead background color
// - "Page TSConfig" select + "Sort alphabetically" checkbox styling
//
// Backend Users module
// - table missing bottom footer divider line
//
// Reports module
// - Status report -> missing table 50-50 layout
// - adjust green saturation?
//
// DB Check module
// - Full search -> Advanced query -> fix form layouts
//// Mixins
@mixin panel-variant($border, $heading-text-color, $heading-bg-color, $heading-border) {
border-color: $border;
& > .panel-heading {
color: $gray-700;
background-color: $heading-bg-color;
border-color: $heading-border;
+ .panel-collapse > .panel-body {
border-top-color: $border;
}
.badge {
color: $heading-bg-color;
background-color: $heading-text-color;
}
}
& > .panel-footer {
+ .panel-collapse > .panel-body {
border-bottom-color: $border;
}
}
}
@mixin label-variant($color) {
background-color: $color;
&[href] {
&:hover,
&:focus {
background-color: darken($color, 10%);
}
}
}
@mixin rotate($degrees) {
-webkit-transform: rotate($degrees);
-ms-transform: rotate($degrees); // IE9 only
-o-transform: rotate($degrees);
transform: rotate($degrees);
}
// Form control sizing
//
// Relative text size, padding, and border-radii changes for form controls. For
// horizontal sizing, wrap controls in the predefined grid classes. `<select>`
// element gets special love because it's special, and that's a fact!
// [converter] $parent hack
@mixin input-size($parent, $input-height, $padding-vertical, $padding-horizontal, $font-size, $line-height, $border-radius) {
#{$parent} {
height: $input-height;
padding: $padding-vertical $padding-horizontal;
font-size: $font-size;
line-height: $line-height;
border-radius: $border-radius;
}
select#{$parent} {
height: $input-height;
line-height: $input-height;
}
textarea#{$parent},
select[multiple]#{$parent} {
height: auto;
}
}
// Form validation states
//
// Used in forms.less to generate the form validation CSS for warnings, errors,
// and successes.
@mixin form-control-validation($text-color: #555, $border-color: #ccc, $background-color: #f5f5f5) {
// Color the label and help text
.help-block,
.control-label,
.form-check-input,
.radio,
.checkbox,
.radio-inline,
.checkbox-inline,
&.form-check-label,
&.radio label,
&.checkbox label,
&.radio-inline label,
&.checkbox-inline label {
color: $text-color;
}
// Set the border and box shadow on specific inputs to match
.form-control {
border-color: $border-color;
@include box-shadow(inset 0 1px 1px rgba(0, 0, 0, 0.075)); // Redeclare so transitions work
&:focus {
border-color: darken($border-color, 10%);
$shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px lighten($border-color, 20%);
@include box-shadow($shadow);
}
}
// Set validation states also for addons
.input-group-addon {
color: $text-color;
background-color: $background-color;
border-color: $border-color;
}
// Optional feedback icon
.form-control-feedback {
color: $text-color;
}
}
//// Variables
$line-height-computed: floor(($font-size-base * $line-height-base)) !default; // ~20px
$grid-float-breakpoint: $screen-sm-min !default;
$input-height-base: ($line-height-computed + ($padding-base-vertical * 2) + 2) !default;
$popover-title-bg: darken($popover-bg, 3%) !default;
// Typography
$font-size-h1: $h1-font-size;
$font-size-h2: $h2-font-size;
$font-size-h3: $h3-font-size;
$font-size-h4: $h4-font-size;
// Components
$border-radius-base: $border-radius;
$border-radius-large: $border-radius-lg;
$border-radius-small: $border-radius-sm;
//== Labels
//
//##
////** Default label background color
$label-default-bg: $gray-300 !default;
////** Primary label background color
$label-primary-bg: $primary !default;
////** Success label background color
$label-success-bg: $success !default;
////** Info label background color
$label-info-bg: $info !default;
////** Warning label background color
$label-warning-bg: $warning !default;
////** Danger label background color
$label-danger-bg: $danger !default;
// Colors
// Contextual variations (linked labels get darker on :hover)
.label-default {
@include label-variant($label-default-bg);
}
.label-primary {
@include label-variant($label-primary-bg);
}
.label-success {
@include label-variant($label-success-bg);
}
.label-info {
@include label-variant($label-info-bg);
}
.label-warning {
@include label-variant($label-warning-bg);
}
.label-danger {
@include label-variant($label-danger-bg);
}
.hidden,
.hide {
display: none !important;
}
.form-group {
margin-bottom: 0.5rem;
}
.caret {
display: inline-block;
width: 0;
height: 0;
margin-left: 0.125rem;
vertical-align: middle;
border-top: 0.25rem dashed $gray-700;
border-right: 0.25rem solid transparent;
border-left: 0.25rem solid transparent;
}
.text-right {
text-align: right;
}
.input-lg {
height: 2.5rem;
}
// todo add "form-label" class to each <label>
label {
@extend .form-label !optional;
}
// todo replace '.input-group-addon' with '.input-group-text'
.input-group-addon {
@extend .input-group-text !optional;
}
// scss-docs-start table-variant
// provide bootstrap v3 fallback for <tr class="{themeColor}"> markup
// bootstrap v5 uses new class syntax -> .table-{themeColor}
@mixin table-variant($state, $background) {
.#{$state} {
/* stylelint-disable custom-property-empty-line-before */
// todo: check why 'grunt formatsass' task is adding new empty lines
$color: color-contrast(opaque($body-bg, $background));
$hover-bg: mix($color, $background, percentage($table-hover-bg-factor));
$striped-bg: mix($color, $background, percentage($table-striped-bg-factor));
$active-bg: mix($color, $background, percentage($table-active-bg-factor));
--bs-table-bg: #{$background};
--bs-table-striped-bg: #{$striped-bg};
--bs-table-striped-color: #{color-contrast($striped-bg)};
--bs-table-active-bg: #{$active-bg};
--bs-table-active-color: #{color-contrast($active-bg)};
--bs-table-hover-bg: #{$hover-bg};
--bs-table-hover-color: #{color-contrast($hover-bg)};
color: $color;
border-color: mix($color, $background, percentage($table-border-factor));
/* stylelint-enable custom-property-empty-line-before */
}
}
@each $color, $value in $table-variants {
@include table-variant($color, $value);
}
// scss-docs-end table-variant
// badge fallback
// todo use ".badge .rounded-pill .bg-{themeColor}" instead of only .badge
// todo only used in debug console?
[class="badge"] {
background-color: $gray-600;
border-radius: $rounded-pill;
}
// nav fallback
// todo add ".nav-item" and ".nav-link" classes to markup
.nav.nav-tabs {
> li:not(.nav-item) {
@extend .nav-item !optional;
> a:not(.nav-link) {
@extend .nav-link !optional;
}
}
}
// panel fallback
// see bootstrap v4 migration https://getbootstrap.com/docs/4.5/migration/#panels
// todo replace ".panel" classes with ".card"
.panel {
@extend .card !optional;
&-group {
@extend .card-group !optional;
}
&-heading {
color: $gray-700;
padding: 0.625rem 1rem;
}
&-title {
@extend .card-title !optional;
}
&-title {
@extend .card-title !optional;
}
&-body {
@extend .card-body !optional;
}
&-footer {
@extend .card-footer !optional;
}
}
// .label (badges) fallback
// todo replace ".label" classes with ".badge"
.label {
@extend .badge !optional;
&-success {
background-color: $success;
}
}
.page-header {
padding: 0.625rem 1rem;
margin: 2rem 0 1rem;
border-bottom: 1px solid $gray-700;
}
code {
margin: 0.25rem 0.5rem;
}
.help-block {
display: block;
margin-top: 0.5rem;
margin-bottom: 1rem;
color: $gray-700;
}
.btn-toolbar {
> .btn,
> .btn-group,
> .input-group {
margin-left: 0.4rem;
float: left;
}
}
.btn-toolbar {
> .btn:first-child,
> .btn-group:first-child,
> .input-group:first-child {
margin-left: 0;
}
}
.input-group-btn {
position: relative;
font-size: 0;
white-space: nowrap;
}
.form-inline .form-group {
display: inline-block;
}
.form-irre-object.panel {
flex: 1 0 100%;
width: 100%;
}
......@@ -4,98 +4,72 @@
//
//
// Bootstrap variables
// Bootstrap
// @todo: Only import the necessary parts
//
@import "bootstrap/variables";
//
// Bootstrap mixins
//
@import "bootstrap/mixins/hide-text";
@import "bootstrap/mixins/opacity";
@import "bootstrap/mixins/image";
@import "bootstrap/mixins/labels";
@import "bootstrap/mixins/reset-filter";
@import "bootstrap/mixins/resize";
@import "bootstrap/mixins/responsive-visibility";
@import "bootstrap/mixins/size";
@import "bootstrap/mixins/tab-focus";
@import "bootstrap/mixins/reset-text";
@import "bootstrap/mixins/text-emphasis";
@import "bootstrap/mixins/text-overflow";
@import "bootstrap/mixins/vendor-prefixes";
@import "bootstrap/mixins/alerts";
@import "bootstrap/mixins/buttons";
@import "bootstrap/mixins/panels";
@import "bootstrap/mixins/pagination";
@import "bootstrap/mixins/list-group";
@import "bootstrap/mixins/nav-divider";
@import "bootstrap/mixins/forms";
@import "bootstrap/mixins/progress-bar";
@import "bootstrap/mixins/table-row";
@import "bootstrap/mixins/background-variant";
@import "bootstrap/mixins/border-radius";
@import "bootstrap/mixins/gradients";
@import "bootstrap/mixins/center-block";
@import "bootstrap/mixins/nav-vertical-align";
@import "bootstrap/mixins/grid-framework";
@import "bootstrap/mixins/grid";
/*!
* Bootstrap v5.0.0-beta1 (https://getbootstrap.com/)
* Copyright 2011-2020 The Bootstrap Authors
* Copyright 2011-2020 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
//
// Custom mixins
//
@import "mixins/clearfix";
// scss-docs-start import-stack
// Configuration
@import "functions";
@import "variables";
@import "mixins";
@import "utilities";
//
// Reset and dependencies
//
@import "bootstrap/normalize";
// Layout & components
@import "root";
@import "reboot";
@import "type";
@import "images";
@import "containers";
@import "grid";
@import "tables";
@import "forms";
@import "buttons";
@import "transitions";
@import "dropdown";
@import "button-group";
@import "nav";
@import "navbar";
@import "card";
@import "breadcrumb";
@import "pagination";
@import "badge";
@import "alert";
@import "progress";
@import "list-group";
@import "close";
@import "toasts";
@import "modal";
@import "tooltip";
@import "popover";
@import "carousel";
@import "spinners";
//
// Fonts
//
@import "webfont/sourcesanspro";
@import "font-awesome";
// Helpers
@import "helpers";
//
// Bootstrap Core CSS
//
@import "bootstrap/scaffolding";
@import "bootstrap/type";
@import "bootstrap/code";
@import "bootstrap/grid";
@import "bootstrap/tables";
@import "bootstrap/forms";
@import "bootstrap/buttons";
// extend bootstrap 5 utilities
@import "utilities/utilities";
//
// Bootstrap Components
//
@import "bootstrap/component-animations";
@import "bootstrap/dropdowns";
@import "bootstrap/button-groups";
@import "bootstrap/input-groups";
@import "bootstrap/navs";
@import "bootstrap/pagination";
@import "bootstrap/labels";
@import "bootstrap/badges";
@import "bootstrap/thumbnails";
@import "bootstrap/alerts";
@import "bootstrap/progress-bars";
@import "bootstrap/media";
@import "bootstrap/list-group";
@import "bootstrap/panels";
@import "bootstrap/responsive-embed";
@import "bootstrap/wells";
@import "bootstrap/close";
// Utilities
@import "utilities/api";
// scss-docs-end import-stack
// bootstrap v3 legacy
@import "legacy";
//
// Bootstrap Components w/ JavaScript
// Fonts
//
@import "bootstrap/modals";
@import "bootstrap/popovers";
@import "bootstrap/tooltip";
@import "bootstrap/carousel";
@import "webfont/sourcesanspro";
@import "font-awesome";
//
// Scaffold
......@@ -108,7 +82,9 @@
//
// Custom Components
//
@import "component/alert";
@import "component/autocomplete";
@import "component/buttons";
@import "component/dropdown";
@import "component/avatar";
@import "component/callout";
......@@ -118,9 +94,3 @@
@import "component/panel";
@import "component/checkbox";
@import "component/simpletable";
//
// Bootstrap Utility classes
//
@import "bootstrap/utilities";
@import "bootstrap/responsive-utilities";
......@@ -6,9 +6,11 @@
//
// Load Variables
//
@import "bootstrap/variables";
@import "bootstrap/mixins/vendor-prefixes";
@import "functions";
@import "_variables";
@import "variables/main";
@import "cropper/mixins";
@import "legacy";
//
// Variables
......@@ -18,10 +20,10 @@ $adminPanel-zindex-backdrop: 99991;
$adminPanel-zindex-bar: 99992;
$adminPanel-zindex-popup: 99994;
$adminPanel-prefix: '#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel';
$adminPanel-bg: $gray-darker;
$adminPanel-color: $gray-lighter;
$adminPanel-bg: $gray-900;
$adminPanel-color: $gray-100;
$adminPanel-success: #629755;
$adminPanel-danger: $brand-danger;
$adminPanel-danger: $danger;
// Message
$adminPanel-message-bg: #fff;
......@@ -1105,13 +1107,13 @@ body.typo3-adminPanel-noscroll {
}
.typo3-adminPanel-sql-header {
color: $gray;
border-bottom: 1px solid $gray-light;
color: $gray-600;
border-bottom: 1px solid $gray-300;
}
.typo3-adminPanel-sql-queries-header {
color: $gray;
border-bottom: 1px solid $gray-light;
color: $gray-600;
border-bottom: 1px solid $gray-300;
}
.typo3-adminPanel-sql-query-ellipsis {
......@@ -1121,10 +1123,10 @@ body.t