Flexible markup for items with teaser images
authorAlexander Ebert <ebert@woltlab.com>
Mon, 18 Mar 2019 15:59:33 +0000 (16:59 +0100)
committerAlexander Ebert <ebert@woltlab.com>
Mon, 18 Mar 2019 15:59:33 +0000 (16:59 +0100)
com.woltlab.wcf/templates/articleListItems.tpl
wcfsetup/install/files/style/ui/contentItem.scss [new file with mode: 0644]
wcfsetup/install/lang/de.xml
wcfsetup/install/lang/en.xml

index 5067b8e89d9a27465254a663fdb94b2630042ae3..803b37661f4ad66473b80cdad01cb7bde30ac967 100644 (file)
@@ -1,64 +1,69 @@
-<ul class="articleList">
+<div class="contentItemList">
        {foreach from=$objects item='article'}
-               <li>
-                       <a href="{$article->getLink()}">
-                               {if $article->getTeaserImage() && $article->getTeaserImage()->hasThumbnail('tiny')}
-                                       <div class="box128">
-                                               <div class="articleListImage">{@$article->getTeaserImage()->getThumbnailTag('tiny')}</div>
-                               {/if}
-                                       
-                                       <div>
-                                               <div class="containerHeadline">
-                                                       <h3 class="articleListTitle">{$article->getTitle()}</h3>
-                                                       <ul class="inlineList articleListMetaData">
-                                                               {if $article->hasLabels()}
-                                                                       <li>
-                                                                               <span class="icon icon16 fa-tags"></span>
-                                                                               <ul class="labelList">
-                                                                                       {foreach from=$article->getLabels() item=label}
-                                                                                               <li><span class="label badge{if $label->getClassNames()} {$label->getClassNames()}{/if}">{lang}{$label->label}{/lang}</span></li>
-                                                                                       {/foreach}
-                                                                               </ul>
-                                                                       </li>
-                                                               {/if}
-                                                               
-                                                               <li>
-                                                                       <span class="icon icon16 fa-clock-o"></span>
-                                                                       {@$article->time|time}
-                                                               </li>
-                                                               
-                                                               {if $article->getDiscussionProvider()->getDiscussionCountPhrase()}
-                                                                       <li>
-                                                                               <span class="icon icon16 fa-comments"></span>
-                                                                               {$article->getDiscussionProvider()->getDiscussionCountPhrase()}
-                                                                       </li>
-                                                               {/if}
-                                                               
-                                                               {if MODULE_LIKE && $__wcf->getSession()->getPermission('user.like.canViewLike')}
-                                                                       {if $article->likes || $article->dislikes || $article->neutralReactions}
-                                                                               <li class="reputationCounter {if $article->cumulativeLikes > 0}positive{elseif $article->cumulativeLikes < 0}negative{else}neutral{/if}">{if $article->cumulativeLikes > 0}+{elseif $article->cumulativeLikes == 0}±{/if}{#$article->cumulativeLikes}</li>
-                                                                       {/if}
-                                                               {/if}
-                                                               
-                                                               {if ARTICLE_ENABLE_VISIT_TRACKING && $article->isNew()}<li><span class="badge label newMessageBadge">{lang}wcf.message.new{/lang}</span></li>{/if}
-
-                                                               {if $article->isDeleted}<li><span class="badge label red">{lang}wcf.message.status.deleted{/lang}</span></li>{/if}
-                                                               
-                                                               {event name='articleListMetaData'}
-                                                       </ul>
+               <article class="contentItem">
+                       <a href="{$article->getLink()}" class="contentItemLink">
+                               <div class="contentItemImage" style="background-image: url({if $article->getImage()}{$article->getImage()->getThumbnailLink('medium')}{else}https://thunderstrike/w/22/images/coverPhotos/default.jpg{/if})">
+                                       {hascontent}
+                                               <div class="contentItemBadges">
+                                                       {content}
+                                                               {if $article->isDeleted}<span class="badge label red contentItemBadge contentItemBadgeIsDeleted">{lang}wcf.message.status.deleted{/lang}</span>{/if}
+                                                               {if ARTICLE_ENABLE_VISIT_TRACKING && $article->isNew()}<span class="badge label contentItemBadge contentItemBadgeNew">{lang}wcf.message.new{/lang}</span>{/if}
+                                                       {/content}
                                                </div>
-                                               
-                                               <div class="containerContent articleListTeaser">
-                                                       {@$article->getFormattedTeaser()}
+                                       {/hascontent}
+                               </div>
+                               
+                               <div class="contentItemContent">
+                                       {if $article->hasLabels()}
+                                               <div class="contentItemLabels">
+                                                       {foreach from=$article->getLabels() item=label}
+                                                               <span class="label badge contentItemLabel{if $label->getClassNames()} {$label->getClassNames()}{/if}">{lang}{$label->label}{/lang}</span>
+                                                       {/foreach}
                                                </div>
+                                       {/if}
+                                       
+                                       <h2 class="contentItemTitle">{$article->getTitle()}</h2>
+                                       
+                                       <div class="contentItemDescription">
+                                               {@$article->getFormattedTeaser()}
+                                       </div>
+                               </div>
+                       </a>
+                       
+                       <div class="contentItemMeta">
+                               <a href="{$article->getUserProfile()->getLink()}" class="contentItemMetaImage" aria-hidden="true" tabindex="-1">
+                                       {@$article->getUserProfile()->getAvatar()->getImageTag(32)}
+                               </a>
+                               
+                               <div class="contentItemMetaContent">
+                                       <div class="contentItemMetaAuthor">
+                                               {if $article->userID}
+                                                       <a href="{$article->getUserProfile()->getLink()}">{$article->getUserProfile()->username}</a>
+                                               {else}
+                                                       {$article->username}
+                                               {/if}
                                        </div>
-                                               
-                               {if $article->getTeaserImage() && $article->getTeaserImage()->hasThumbnail('tiny')}
+                                       <div class="contentItemMetaTime">
+                                               {@$article->time|time}
                                        </div>
-                               {/if}
+                               </div>
                                
-                               {event name='articleListEntry'}
-                       </a>
-               </li>
+                               <div class="contentItemMetaIcons">
+                                       {if MODULE_LIKE && $__wcf->getSession()->getPermission('user.like.canViewLike') && ($article->likes || $article->dislikes || $article->neutralReactions)}
+                                               <div class="contentItemMetaIcon reputationCounter {if $article->cumulativeLikes > 0}positive{elseif $article->cumulativeLikes < 0}negative{else}neutral{/if}">
+                                                       <span aria-label="{lang cumulativeLikes=$article->cumulativeLikes}wcf.like.reputation.label{/lang}">
+                                                               {if $article->cumulativeLikes > 0}+{elseif $article->cumulativeLikes == 0}±{/if}{#$article->cumulativeLikes}
+                                                       </span>
+                                               </div>
+                                       {/if}
+                                       <div class="contentItemMetaIcon">
+                                               <span class="icon icon16 fa-comments"></span>
+                                               <span aria-label="{$article->getDiscussionProvider()->getDiscussionCountPhrase()}">
+                                                       {$article->getDiscussionProvider()->getDiscussionCount()}
+                                               </span>
+                                       </div>
+                               </div>
+                       </div>
+               </article>
        {/foreach}
-</ul>
+</div>
diff --git a/wcfsetup/install/files/style/ui/contentItem.scss b/wcfsetup/install/files/style/ui/contentItem.scss
new file mode 100644 (file)
index 0000000..e7c7f1b
--- /dev/null
@@ -0,0 +1,164 @@
+.contentItemList {
+       display: flex;
+       flex-wrap: wrap;
+       margin-bottom: -20px;
+       justify-content: space-between;
+}
+
+.contentItem {
+       background-color: $wcfContentBackground;
+       border-radius: 3px;
+       box-shadow: 0 0 3px rgba(0, 0, 0, .12), 0 1px 2px rgba(0, 0, 0, .24);
+       display: flex;
+       flex: 0 0 calc(50% - 10px);
+       flex-direction: column;
+       margin-bottom: 20px;
+       max-width: calc(50% - 10px); /* IE 11 */
+       overflow: hidden;
+}
+
+.contentItemLink {
+       flex: 1 auto;
+}
+
+.contentItemContent {
+       max-height: 150px;
+       overflow: hidden;
+       padding: 10px;
+       position: relative;
+       
+       &::after {
+               background-image: linear-gradient(to top, $wcfContentBackground, transparent);
+               bottom: 0;
+               content: "";
+               height: 30px;
+               left: 0;
+               pointer-events: none;
+               position: absolute;
+               right: 0;
+               /* The `top` value is important, because it prevents the last line from being affected
+                  when the content isn't too long. */
+               top: 120px;
+       }
+}
+
+.contentItemImage {
+       background-position: center;
+       background-repeat: no-repeat;
+       background-size: cover;
+       height: 150px;
+       position: relative;
+}
+
+.contentItemBadges {
+       align-items: flex-start;
+       display: flex;
+       flex-direction: column;
+       left: 10px;
+       position: absolute;
+       top: 10px;
+}
+
+.contentItemBadge {
+       border: 1px solid currentColor;
+       flex: 0 auto;
+       
+       &:not(:first-child) {
+               margin-top: 5px;
+       }
+}
+
+.contentItemLabels {
+       margin-bottom: 5px;
+}
+
+.contentItemTitle {
+       color: $wcfContentHeadlineLink;
+       
+       @include wcfFontHeadline;
+       @include wcfFontBold;
+       
+       &:hover {
+               color: $wcfContentHeadlineLinkActive;
+       }
+}
+
+.contentItemDescription {
+       color: $wcfContentText;
+       margin-top: 10px;
+}
+
+.contentItemMeta {
+       align-items: center;
+       border-top: 1px solid $wcfContentBorderInner;
+       color: $wcfContentDimmedText;
+       display: flex;
+       flex: 0 auto;
+       padding: 10px;
+       
+       .icon {
+               color: inherit;
+       }
+}
+
+.contentItemMetaImage {
+       flex: 0 auto;
+       margin-right: 10px;
+}
+
+.contentItemMetaContent {
+       flex: 1 auto;
+       font-size: 12px;
+}
+
+.contentItemMetaAuthor {
+       color: $wcfContentText;
+       
+       a,
+       a:hover {
+               color: inherit;
+       }
+}
+
+.contentItemMetaIcons {
+       display: flex;
+       flex: 0 auto;
+       margin-left: 10px;
+}
+
+.contentItemMetaIcon {
+       flex: 0 auto;
+       
+       &:not(:first-child) {
+               margin-left: 10px;
+       }
+}
+
+@include screen-lg {
+       /* There are no sidebars, use a three column layout. */
+       .content:first-child:last-child {
+               .contentItem {
+                       flex: 0 0 calc(100% / 3 - 15px);
+                       max-width: calc(100% / 3 - 15px); /* IE 11 */
+               }
+       }
+}
+
+@include screen-md {
+       /* The sidebar, if any, is not adjacent to the content, use a three column layout. */
+       .contentItem {
+               flex: 0 0 calc(100% / 3 - 15px);
+               max-width: calc(100% / 3 - 15px); /* IE 11 */
+       }
+}
+
+@include screen-xs {
+       /* There is not enough space to fit two columns. */
+       .contentItemList {
+               display: block;
+       }
+       
+       .contentItem {
+               max-width: none;
+       }
+}
index 4f42e75d0ff64cc351282cbdb38acae68b8c4610..913cbd7158611432933ce1e76c560a60d0c8dfd8 100644 (file)
@@ -3923,6 +3923,7 @@ Dateianhänge:
                <item name="wcf.like.reactionsGiven"><![CDATA[Vergebene Reaktionen]]></item>
                <item name="wcf.like.reactionReputation"><![CDATA[Reputation aus Reaktionen]]></item>
                <item name="wcf.like.reputation"><![CDATA[Reputation]]></item>
+               <item name="wcf.like.reputation.label"><![CDATA[Reputation: {if $cumulativeLikes > 0}+{elseif $cumulativeLikes == 0}±{/if}{#$cumulativeLikes}]]></item>
        </category>
        <category name="wcf.map">
                <item name="wcf.map.noLocationSuggestions"><![CDATA[Für den aktuellen Kartenausschnitt liegen keine Ortsvorschläge vor.]]></item>
index 9624f0f4702e29018a65ad7b4a6e9fcbe22ee584..6c4c3b25d26e2fbccefe96d0b1f657934e9fd416 100644 (file)
@@ -3869,6 +3869,7 @@ Attachments:
                <item name="wcf.like.reactionsGiven"><![CDATA[Reactions Given]]></item>
                <item name="wcf.like.reactionReputation"><![CDATA[Reputation from Reactions]]></item>
                <item name="wcf.like.reputation"><![CDATA[Reputation]]></item>
+               <item name="wcf.like.reputation.label"><![CDATA[Reputation: {if $cumulativeLikes > 0}+{elseif $cumulativeLikes == 0}±{/if}{#$cumulativeLikes}]]></item>
        </category>
        <category name="wcf.map">
                <item name="wcf.map.noLocationSuggestions"><![CDATA[There are no location suggestions in the current map section.]]></item>