Commit 575561a7 authored by Markus Sommer's avatar Markus Sommer Committed by Benjamin Kott
Browse files

[TASK] Refactor distribution list view with cards

The card component has been extended and is now more flexible to be
more usefull for different usecases, and is now used in the distribution
listing of the extension manager. We have also changed to Documentation
format of the CSS files to match KSS Knyle Style Sheets format.

Releases: master
Resolves: #82000

Change-Id: I61711dd0ee6c38e3c249d9b744a3ee6b2e24273e
Reviewed-on: https://review.typo3.org/53619

Reviewed-by: Christian Kuhn's avatarChristian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn's avatarChristian Kuhn <lolli@schwarzbu.ch>
Tested-by: default avatarTYPO3com <no-reply@typo3.com>
Reviewed-by: Benjamin Kott's avatarBenjamin Kott <benjamin.kott@outlook.com>
Tested-by: Benjamin Kott's avatarBenjamin Kott <benjamin.kott@outlook.com>
parent 8ea2cea3
//
// Card
// ====
// Cards for typo3
//
// Cards are flexible content containers that are meant to be used for organizing groups of elements.
// Each card is a collection of the container and corresponding child elements, that can be used as needed.
// Child Elements are optional but combinung those will bring the best experience.
//
// Normal Usage
// ------------
//
// <div class="card card-size-medium">
// ... Content ...
// </div>
// Styleguide component.card
//
//
// Grid Usage
// ----------
// Examples
//
// Markup:
// <div class="card-container">
// <div class="card card-size-medium">
// ... Content ...
// <div class="card-header">
// <h1 class="card-title">Simple Card</h1>
// <span class="card-subtitle">Subtitle</span>
// </div>
// <div class="card-content">
// <p class="card-text">
// Nulla at mattis lectus. Duis pulvinar sollicitudin aliquam. Praesent id convallis ante, id auctor sem. Duis vestibulum nisl sit amet feugiat blandit. Cras in neque sit amet eros iaculis dapibus sed sit amet tortor.
// </p>
// </div>
// </div>
// <div class="card card-size-medium">
// ... Content ...
// <div class="card-header">
// <div class="card-icon">
// <img src="http://via.placeholder.com/32x32" height="32" width="32">
// </div>
// <div class="card-header-body">
// <h1 class="card-title">Icon Card</h1>
// <span class="card-subtitle">Subtitle</span>
// <div class="card-longdesc">
// <p class="card-text">
// Nulla at mattis lectus. Duis pulvinar sollicitudin aliquam. Praesent id convallis ante, id auctor sem. Duis vestibulum nisl sit amet feugiat blandit. Cras in neque sit amet eros iaculis dapibus sed sit amet tortor.
// </p>
// </div>
// </div>
// </div>
// </div>
// <div class="card card-size-medium">
// ... Content ...
// <div class="card-header">
// <h1 class="card-title">Action Card</h1>
// </div>
// <div class="card-content">
// <p class="card-text">
// Etiam posuere tristique arcu, a elementum justo semper eget. Etiam malesuada consectetur risus nec hendrerit. Mauris velit arcu, efficitur at erat eget, luctus consequat felis.
// </p>
// </div>
// <div class="card-footer">
// <a class="btn btn-primary" href="#">
// Action 1
// </a>
// <a class="btn btn-default" href="#">
// Action 2
// </a>
// </div>
// </div>
// <a href="#" class="card card-size-medium">
// <div class="card-header">
// <h1 class="card-title">Linked Card</h1>
// </div>
// <div class="card-content">
// <p class="card-text">
// Etiam posuere tristique arcu, a elementum justo semper eget. Etiam malesuada consectetur risus nec hendrerit. Mauris velit arcu, efficitur at erat eget, luctus consequat felis.
// </p>
// </div>
// </a>
// <div class="card card-size-medium">
// ... Content ...
// <div class="card-image">
// <img src="http://via.placeholder.com/300x120" height="120" width="300">
// </div>
// <div class="card-header">
// <h1 class="card-title">Product Card</h1>
// <span class="card-subtitle">Subtitle</span>
// </div>
// <div class="card-content">
// <p class="card-text">
// Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse erat justo, hendrerit vitae arcu eget.
// </p>
// </div>
// <div class="card-footer">
// <a class="btn btn-default" href="#">
// Action 1
// </a>
// <a class="btn btn-link" href="#">
// Link 2
// </a>
// </div>
// </div>
// </div>
//
// Styleguide component.card.1
//
// Sizes
// -----
//
// Flexible Sizes
//
// .card-size-small - Small
// .card-size-medium - Medium
// .card-size-large - Large
//
// Markup:
// <div class="card $modifierClass">
// <div class="card-image">
// <img src="http://via.placeholder.com/300x225" height="225" width="300">
// </div>
// <div class="card-header">
// <h1 class="card-title">The official Introduction Package</h1>
// <span class="card-subtitle">introduction</span>
// </div>
// <div class="card-content">
// <p class="card-text">
// This package delivers a new website (page tree) and shows all out-of-the-box features of TYPO3, and includes a theme based on Twitter Bootstrap 3, and...
// </p>
// </div>
// <div class="card-footer">
// <a class="btn btn-default" href="#">
// Install
// </a>
// <a class="btn btn-link" href="#">
// Show Details
// </a>
// </div>
// </div>
//
// Styleguide component.card.2
//
//
// Fixed Sizes
//
// .card-size-fixed-small - Small
//
// Markup:
// <div class="card $modifierClass">
// <div class="card-image">
// <img src="http://via.placeholder.com/300x225" height="225" width="300">
// </div>
// <div class="card-header">
// <h1 class="card-title">The official Introduction Package</h1>
// <span class="card-subtitle">introduction</span>
// </div>
// <div class="card-content">
// <p class="card-text">
// This package delivers a new website (page tree) and shows all out-of-the-box features of TYPO3, and includes a theme based on Twitter Bootstrap 3, and...
// </p>
// </div>
// <div class="card-footer">
// <a class="btn btn-default" href="#">
// Install
// </a>
// <a class="btn btn-link" href="#">
// Show Details
// </a>
// </div>
// </div>
//
// card-size-small => 3 2 1
// card-size-medium => 2 2 1
// card-size-large => 1 1 1
// Styleguide component.card.3
//
//
// Collection
//
// The card container groups multiple card elements and ensures that these elements always share
// the same height for elements in a row. Each group is wrapped with `<div class="card-container">|</div>`
//
// Markup:
// <div class="card-container">
// <div class="card card-size-medium">
// <div class="card-image">
// <img src="http://via.placeholder.com/300x100" height="100" width="300">
// </div>
// <div class="card-header">
// <h1 class="card-title">Card with a lot of content</h1>
// </div>
// <div class="card-content">
// <p class="card-text">
// Curabitur semper tellus ac odio dignissim, maximus ornare eros tempor. Integer tempus vestibulum leo, elementum cursus arcu euismod non. Aenean quam nisi, laoreet vitae diam eget, posuere efficitur eros. Curabitur id arcu purus. Suspendisse ullamcorper dictum neque ut pellentesque. Integer pharetra dui eu justo rutrum accumsan. Aenean vehicula dictum purus, sit amet consequat ante malesuada vitae. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.
// </p>
// </div>
// </div>
// <div class="card card-size-medium">
// <div class="card-image">
// <img src="http://via.placeholder.com/300x100" height="100" width="300">
// </div>
// <div class="card-header">
// <h1 class="card-title">Card with little to none content</h1>
// </div>
// <div class="card-content">
// <p class="card-text">
// Lorem ipsum dolor sit amet, consectetur adipiscing elit.
// </p>
// </div>
// </div>
// </div>
//
// Styleguide component.card.4
//
//
// Header
//
//
// Variables
//
$card-spacing: 10px;
$card-padding: 1.5em;
$card-base-color: #000;
$card-border-color: lighten($card-base-color, 80);
$card-border-hover-color: lighten($card-base-color, 70);
......@@ -53,20 +219,22 @@ $card-shadow-hover-color: transparentize($card-base-color, 0.7);
// Component
//
.card {
overflow: hidden;
border-radius: 2px;
display: flex;
padding: 15px;
box-shadow: 0 2px 0 $card-shadow-color;
flex-direction: column;
box-shadow: 0 1px 1px $card-shadow-color;
border: 1px solid $card-border-color;
margin-bottom: ($card-spacing*2);
transition: all 0.2s ease-in-out;
transition-property: box-shadow, border, transform;
}
&:hover {
text-decoration: none;
border: 1px solid $card-border-hover-color;
transform: translate(0, -1px);
box-shadow: 0 3px 0 $card-shadow-hover-color;
}
a.card:hover {
text-decoration: none;
border: 1px solid $card-border-hover-color;
transform: translate(0, -1px);
box-shadow: 0 2px 1px $card-shadow-hover-color;
}
.card-container {
......@@ -110,3 +278,117 @@ $card-shadow-hover-color: transparentize($card-base-color, 0.7);
width: calc(100% - #{$card-spacing*2});
}
}
//
// Fixed sizes
//
.card-size-fixed-small {
width: calc(100% - #{$card-spacing*2});
@media (min-width: $screen-ms-min) {
width: calc(50% - #{$card-spacing*2});
}
@media (min-width: $screen-sm-min) {
width: 300px;
}
}
//
// Components
//
.card-image,
.card-header,
.card-content,
.card-footer {
padding: $card-padding $card-padding 0 $card-padding;
&:last-child {
padding-bottom: $card-padding;
}
*:first-child {
margin-top: 0;
}
*:last-child {
margin-bottom: 0;
}
}
//
// Image
//
.card-image {
position: relative;
padding-left: 0;
padding-right: 0;
&:first-child {
padding-top: 0;
.card-image-badge {
top: $card-padding / 2;
}
}
&:last-child {
padding-bottom: 0;
}
.card-image-badge {
position: absolute;
top: $card-padding;
right: $card-padding / 2;
}
img {
display: block;
height: auto;
width: 100%;
margin: 0 auto;
}
}
//
// Header
//
.card-header {
.card-icon {
float: left;
margin-right: $card-padding / 2;
}
.card-header-body {
display: block;
overflow: hidden;
}
.card-title {
font-family: inherit;
font-weight: 500;
display: block;
font-size: 1.35em;
line-height: 1.2em;
margin: 0;
}
.card-subtitle {
display: block;
margin-top: 0.5em;
font-size: 1em;
line-height: 1.2em;
opacity: 0.5;
}
.card-longdesc {
margin-top: 1em;
}
}
//
// Content
//
.card-content {
height: 100%;
}
//
// Extensionmanager
//
// Extension list
.typo3-extensionmanager-headerRowLeft {
float: left;
}
.typo3-extensionmanager-headerRowRight {
float: right;
}
.ui-toolbar {
margin-bottom: 5px;
......@@ -59,105 +49,40 @@
}
}
// Distributions list
.distribution {
border: 1px solid darken($gray-lighter, 15%);
background-color: $gray-lighter;
margin-bottom: 20px;
margin-left: 20px;
width: 300px;
float: left;
&:hover {
background-color: darken($gray-lighter, 3%);
// Distributions List
.distribution-official-badge {
position: absolute;
bottom: 0;
right: 0.75em;
transform: translate(0, 25%);
.distribution-hover {
top: 0;
opacity: 1;
}
img {
width: 50px;
display: block;
.distribution-more {
text-decoration: underline;
@media (min-width: $screen-sm-min) {
width: 64px;
}
}
.typo3-dependency-version {
position: absolute;
right: 0;
}
}
.distribution-holder {
@extend .clearfix;
margin-top: 1em;
bottom: 0;
margin-left: -20px;
}
.distribution-image {
position: relative;
width: 300px;
height: 225px;
overflow: hidden;
// Distribution Detail
.distribution-detail-previewpane {
margin-bottom: 2em;
max-width: 100%;
img {
display: block;
height: 100%;
width: 100%;
}
}
.distribution-hover {
background-color: $gray-lighter;
position: absolute;
top: 100%;
left: 0;
width: 300px;
height: 225px;
overflow: hidden;
opacity: 0;
@include transition(all 0.2s ease-in-out);
}
.distribution-hover-inner {
padding: 15px;
}
.distribution-meta {
border-top: 1px solid darken($gray-lighter, 10%);
padding: 15px;
.distribution-title {
margin: 0;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
font-size: 14px;
max-width: 100%;
height: auto;
}
.distribution-install {
margin-top: 0.5em;
@media (min-width: $screen-sm-min) {
float: left;
margin-right: 3em;
}
}
.distribution-detail {
@extend .clearfix;
min-width: 750px;
}
.distribution-detail-previewpane {
float: left;
margin-right: 30px;
}
.distribution-detail-preview {
display: block;
border: 1px solid darken($gray-lighter, 15%);
}
.distribution-detail-body {
overflow: hidden;
zoom: 1;
......@@ -177,19 +102,20 @@
margin-bottom: 2.5em;
}
.distribution-detail-actions {
list-style: none;
padding: 0;
li {
margin: 0.25em 0;
}
}
.distribution-detail-summary {
margin-top: 2.5em;
margin-bottom: 2.5em;
}
.distribution-installed {
hr {
margin: 2.5em 0;
border: 0;
border-top: 1px solid darken($gray-lighter, 15%);
}
}
// Misc
.ui-widget-header {
background: none;
......
......@@ -65,6 +65,8 @@ $line-height-base: 1.5;
$screen-xs: 480px;
$screen-xs-min: $screen-xs;
$screen-phone: $screen-xs-min;
$screen-ms: 624px;
$screen-ms-min: $screen-ms;
$screen-sm: 768px;
$screen-sm-min: $screen-sm;
$screen-tablet: $screen-sm-min;
......
This diff is collapsed.
......@@ -14,25 +14,27 @@
title="{f:if(condition: subModule.shortDescription, then: '{f:translate(key: subModule.shortDescription)}')}"
class="card card-size-medium"
>
<div class="media">
<div class="media-left">
<span class="media-object" title="{f:if(condition: subModule.label, then: '{f:translate(key: subModule.label)}')}">
<core:icon identifier="{subModule.iconIdentifier}" size="default" />
</span>
<div class="card-header">
<div class="card-icon">
<core:icon identifier="{subModule.iconIdentifier}" size="default" />
</div>
<div class="media-body">
<f:if condition="{subModule.label}">
<h3 class="h4 media-heading">
<f:if condition="{subModule.label}">
<div class="card-header-body">
<h3 class="card-title">
{f:translate(key: subModule.label)}
<f:if condition="{subModule.shortDescription}">
<br><small class="text-muted"><f:translate key="{subModule.shortDescription}" /></small><br>
</f:if>
</h3>
</f:if>
<f:if condition="{subModule.longDescription}">
{f:translate(key: subModule.longDescription) -> f:format.raw()}
</f:if>
</div>
<f:if condition="{subModule.shortDescription}">
<span class="card-subtitle">
<f:translate key="{subModule.shortDescription}" />
</span>
</f:if>
<f:if condition="{subModule.longDescription}">
<div class="card-longdesc">
{f:translate(key: subModule.longDescription) -> f:format.raw()}
</div>
</f:if>
</div>
</f:if>