Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/tabbed neos works with logo #512

Draft
wants to merge 4 commits into
base: development
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ Neos.NeosIo:Content.ImageGrid:
group: content
isMonochrome:
type: boolean
defaultValue: false
ui:
reloadIfChanged: true
label: 'Monochrome'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
'Neos.NeosIo.FeatureList:FeatureList': true
'Neos.NeosIo.CaseStudies:Content.CaseList': true
'Neos.NeosIo:PostArchive': true
'Neos.NeosIo:Tabs': true
ui:
label: Stage
icon: icon-tasks
Expand Down
18 changes: 18 additions & 0 deletions DistributionPackages/Neos.NeosIo/NodeTypes/Content/Tabs.Item.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
'Neos.NeosIo:Tabs.Item':
superTypes:
'Neos.Neos:Content': true
'Neos.Neos:ContentCollection': true
'Neos.NeosIo:ContentInspectorGroupMixin': true
ui:
label: 'Tab'
icon: icon-square-o
position: 200
properties:
title:
type: string
ui:
reloadIfChanged: true
label: 'Tab Title'
showInCreationDialog: true
inspector:
group: 'default'
19 changes: 19 additions & 0 deletions DistributionPackages/Neos.NeosIo/NodeTypes/Content/Tabs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
'Neos.NeosIo:Tabs':
superTypes:
'Neos.Neos:Content': true
'Neos.Neos:ContentCollection': true
ui:
label: 'Tabs'
icon: icon-layer-group
position: 400
constraints:
nodeTypes:
'*': false
'Neos.NeosIo:Tabs.Item': true
options:
# `internezzo/childreload`
reloadIfChildChanged: true
template:
childNodes:
itemNode1:
type: 'Neos.NeosIo:Tabs.Item'
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
prototype(Neos.NeosIo:Tabs.Item) < prototype(Neos.Neos:ContentComponent) {
content = Neos.Neos:ContentCollection {
nodePath = '.'
}

renderer = afx`
<div id={'panel-' + node.identifier} class="tab-item" role="tabpanel" tabindex="0" aria-labelledby={'tab-' + node.identifier}>
{props.content}
</div>
`
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
prototype(Neos.NeosIo:Tabs) < prototype(Neos.Neos:ContentComponent) {
renderer = afx`
<div data-component="Tabs" class="tabs__wrapper">
<div class="tabs" role="tablist">
<Neos.Fusion:Loop items={q(node).children()} iteratorName="iterator" itemName="node">
<button
class={["tab", iterator.isFirst && 'active']}
role="tab"
aria-selected={iterator.isFirst ? "true" : "false"}
tabindex={iterator.isFirst ? "0" : "-1"}
id={'tab-' + node.identifier}
aria-controls={'panel-' + node.identifier}
>
<span class="tab-link__inner">
{q(node).property("title")}
</span>
</button>
</Neos.Fusion:Loop>
</div>
<div class="tabs-content__wrapper">
<Neos.Neos:ContentCollection nodePath="." attributes.class="tabs-content" />
</div>
</div>
`
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
.tabs {
position: relative;
overflow-x: auto;
overflow-y: hidden;
height: 48px;
width: 100%;
margin: 0 auto;
white-space: nowrap;

.tab {
display: inline-block;
text-align: center;
line-height: 48px;
height: 48px;
flex-shrink: 0;
padding: 0;
margin: 0;
background: none;
appearance: none;
border: none;
cursor: pointer;

&:focus,
&:focus.active {
outline: none;
}

&:hover,
&.active {
background-color: transparent;
}

.tab-link__inner {
padding: 0 24px;
height: 100%;
}

font-size: 14px;
text-overflow: ellipsis;
overflow: hidden;
transition: color .28s ease, background-color .28s ease;

&.disabled a,
&.disabled a:hover {
cursor: default;
}
}
}

.tabs {
display: flex;
justify-content: center;
padding: 0;
}

.tabs .indicator {
display: none;
}

.tabs-content__wrapper {
position: relative;
padding-top: 48px;

&::after {
bottom: -1px;
content: "";
width: 16px;
border-top: 1px solid #e7e7e8;
position: absolute;
right: 12px;
transform-origin: right top;
transform: rotateZ(135deg);
}
}

.tabs-content {
display: flex;
flex-direction: column;
gap: 20px;
padding-left: 15px;
padding-right: 15px;
padding-bottom: 15px;
}

.tab-item:not([hidden]){
display: inline-block;
width: 100%;
}

.tabs {
.tab {
@include clippedForm;

position: relative;
color: $headingsColor;

.tab-link__inner {
pointer-events: none;
display: grid;
font-weight: bold;
font-family: $brand-font-family;

&:empty::after {
content: "Tab title";
color: #ccc;
}
}

&[aria-selected="true"] {
.tab-link__inner {
background-color: brand('primary');
}

color: #fff;
}

&:focus, &:active, &:focus[aria-selected="true"] {
.tab-link__inner {
background-color: brand('primary');
}
}

&:focus,
&:active,
&[aria-selected="true"] {
&:before {
content: "";
width: 18px;
border-top: 1px solid #e7e7e8;
position: absolute;
left: -7px;
transform-origin: right top;
transform: rotateZ(-45deg);
z-index: 1;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
@import "../Scss/Main";

// TODO HACKY, as in: they dont follow the Atomic Design Structure
@import "./Content/Tabs/Tabs";
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import BaseComponent from "./BaseComponent";

/**
* Adapted code from https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/tab_role#example
*/
export default class Tabs extends BaseComponent {
constructor(el) {
super(el);

const tabwrapper = this.el;

const tabList = tabwrapper.querySelector('[role="tablist"]');
const tabs = tabwrapper.querySelectorAll('[role="tab"]');
const tabPanels = tabwrapper.querySelectorAll('[role="tabpanel"]');
tabPanels.forEach((panel, index) => index !== 0 && panel.toggleAttribute("hidden", true));

// Add a click event handler to each tab
tabs.forEach((tab) => {
tab.addEventListener("click", () => {
tabs.forEach((t) => t.setAttribute("aria-selected", t !== tab ? 'false' : 'true'));

const controls = tab.getAttribute("aria-controls");
tabPanels.forEach((panel) => panel.toggleAttribute("hidden", panel.id !== controls));
});
});

// Enable arrow navigation between tabs in the tab list

let tabFocus = 0;
tabList.addEventListener("keydown", (e) => {
// Move right
if (e.key === 'ArrowRight' || e.key === 'ArrowLeft') {
tabs[tabFocus].setAttribute("tabindex", -1);
if (e.key === 'ArrowRight') {
tabFocus++;
// If we're at the end, go to the start
if (tabFocus >= tabs.length) {
tabFocus = 0;
}
// Move left
} else if (e.key === 'ArrowLeft') {
tabFocus--;
// If we're at the start, move to the end
if (tabFocus < 0) {
tabFocus = tabs.length - 1;
}
}

tabs[tabFocus].setAttribute("tabindex", 0);
tabs[tabFocus].focus();
}
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import ScrollTo from './ScrollTo';
import ProgressiveImage from './ProgressiveImage';
import ScrollClassToggler from './ScrollClassToggler';
import SentenceSwitcher from './SentenceSwitcher';
import Tabs from './Tabs';

export {
ClassToggler,
Expand All @@ -16,5 +17,6 @@ export {
SentenceSwitcher,
ProgressiveImage,
ScrollClassToggler,
EmptyClickHandler
EmptyClickHandler,
Tabs
};
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,7 @@ $btn-horizontal-padding: 40px;

@mixin btnClippedBorder() {
.btn__content {
$clip-path: polygon(var(--btn-clip-width) 0px, 0 var(--btn-clip-height), 0 100%, calc(100% - var(--btn-clip-width)) 100%, 100% calc(100% - var(--btn-clip-height)), 100% 0);

// Autoprefixer doesn't add the required webkit prefix for some reason
-webkit-clip-path: #{$clip-path};
clip-path: #{$clip-path};
@include clippedForm;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,7 @@

}
}

.image-grid__greyscale figure {
filter: grayscale(1);
}
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,13 @@
}
}
}

@mixin clippedForm() {
$btn-clip-width: 14px;
$btn-clip-height: 10px;
$clip-path: polygon($btn-clip-width 0px, 0 $btn-clip-height, 0 100%, calc(100% - #{$btn-clip-width}) 100%, 100% calc(100% - #{$btn-clip-height}), 100% 0);

// Autoprefixer doesn't add the required webkit prefix for some reason
-webkit-clip-path: #{$clip-path};
clip-path: #{$clip-path};
}
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@

"ttree/outofbandrendering": "dev-task/newer-neos-versions as 4.0.0",
"cweagans/composer-patches": "^1.7",
"jcupitt/vips": "^1.0"
"jcupitt/vips": "^1.0",
"internezzo/childreload": "^1.0"
},
"require-dev": {
"roave/security-advisories": "dev-latest",
Expand Down
38 changes: 38 additions & 0 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.