mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
Restructure accordion so list items are in their own component
Accordion styles to get more BEM
This commit is contained in:
parent
a7f5ef7b95
commit
3be4e80711
@ -4,7 +4,10 @@ import SilverStripeComponent from 'lib/SilverStripeComponent';
|
||||
class Accordion extends SilverStripeComponent {
|
||||
render() {
|
||||
return (
|
||||
<div role="tablist" aria-multiselectable="true">{this.props.children}</div>
|
||||
<div className="accordion"
|
||||
role="tablist"
|
||||
aria-multiselectable="true"
|
||||
>{this.props.children}</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,53 +1,48 @@
|
||||
// Accordion styles
|
||||
.accordion-group {
|
||||
// Accordion based off Bootstrap collapse
|
||||
|
||||
.accordion__block {
|
||||
margin-top: $spacer-y * 1.25;
|
||||
}
|
||||
|
||||
&__title {
|
||||
margin-bottom: 0;
|
||||
.accordion__title {
|
||||
margin-bottom: 0;
|
||||
margin-left: -$spacer-y;
|
||||
margin-right: -$spacer-y;
|
||||
padding: $spacer-x*.75 $spacer-y;
|
||||
position: relative;
|
||||
display: block;
|
||||
font-size: $font-size-sm;
|
||||
line-height: $line-height-base;
|
||||
font-weight: 400;
|
||||
color: $body-color;
|
||||
text-transform: uppercase;
|
||||
text-decoration: none;
|
||||
border-bottom: 1px solid $border-color;
|
||||
|
||||
a {
|
||||
/* Todo: extend table header */
|
||||
font-size: $font-size-sm;
|
||||
line-height: $line-height-base;
|
||||
font-weight: 400;
|
||||
text-transform: uppercase;
|
||||
padding: $spacer-x*.75 $spacer-y;
|
||||
/* end table header */
|
||||
&::before {
|
||||
padding: $spacer-x*.75 $spacer-y;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
font-size: $font-size-lg;
|
||||
line-height: $line-height-base;
|
||||
color: lighten($body-color,30);
|
||||
text-align: center;
|
||||
content: "7";
|
||||
font-family: silverstripe;
|
||||
}
|
||||
|
||||
display: block;
|
||||
margin-left: -$spacer-y;
|
||||
margin-right: -$spacer-y;
|
||||
text-decoration: none;
|
||||
position: relative;
|
||||
border-bottom: 1px solid $border-color;
|
||||
&:hover,
|
||||
&:active,
|
||||
&:focus {
|
||||
text-decoration: none;
|
||||
|
||||
&::before {
|
||||
color: $body-color;
|
||||
|
||||
&::before {
|
||||
padding: $spacer-x*.75 $spacer-y;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
font-size: $font-size-lg;
|
||||
line-height: $line-height-base;
|
||||
color: lighten($body-color,30);
|
||||
text-align: center;
|
||||
content: "7";
|
||||
font-family: silverstripe;
|
||||
}
|
||||
|
||||
&.collapsed::before {
|
||||
content: "6";
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&:active,
|
||||
&:focus {
|
||||
text-decoration: none;
|
||||
|
||||
&::before {
|
||||
color: $body-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.accordion__title.collapsed::before {
|
||||
content: "6";
|
||||
}
|
||||
|
@ -1,8 +1,10 @@
|
||||
// TODO move list-group to its own component
|
||||
|
||||
import React from 'react';
|
||||
import SilverStripeComponent from 'lib/SilverStripeComponent';
|
||||
import 'bootstrap-collapse';
|
||||
|
||||
class AccordionGroup extends SilverStripeComponent {
|
||||
class AccordionBlock extends SilverStripeComponent {
|
||||
render() {
|
||||
const headerID = `${this.props.groupid}_Header`;
|
||||
const listID = `${this.props.groupid}_Items`;
|
||||
@ -15,12 +17,16 @@ class AccordionGroup extends SilverStripeComponent {
|
||||
'aria-labelledby': headerID,
|
||||
};
|
||||
return (
|
||||
<div className="accordion-group">
|
||||
<h6 className="accordion-group__title" role="tab" id={headerID}>
|
||||
<a data-toggle="collapse" href={href} aria-expanded="true" aria-controls={listID}>
|
||||
{this.props.title}
|
||||
</a>
|
||||
</h6>
|
||||
<div className="accordion__block">
|
||||
<a className="accordion__title"
|
||||
data-toggle="collapse"
|
||||
href={href}
|
||||
aria-expanded="true"
|
||||
aria-controls={listID}
|
||||
id={headerID}
|
||||
role="tab"
|
||||
>{this.props.title}
|
||||
</a>
|
||||
<div {...groupProps}>
|
||||
{this.props.children}
|
||||
</div>
|
||||
@ -28,4 +34,4 @@ class AccordionGroup extends SilverStripeComponent {
|
||||
);
|
||||
}
|
||||
}
|
||||
export default AccordionGroup;
|
||||
export default AccordionBlock;
|
3
admin/client/src/components/Accordion/README.md
Normal file
3
admin/client/src/components/Accordion/README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# Accordion
|
||||
|
||||
The ability to have panel(s) which can collapse and expand
|
96
admin/client/src/components/ListGroup/LIstGroup.scss
Normal file
96
admin/client/src/components/ListGroup/LIstGroup.scss
Normal file
@ -0,0 +1,96 @@
|
||||
// List-group, based on Bootstraps list-group
|
||||
// TODO split out campaign specific css from generic list-group
|
||||
|
||||
.list-group {
|
||||
margin-left: -$spacer-y;
|
||||
margin-right: -$spacer-y;
|
||||
border-bottom: 1px solid $border-color-light;
|
||||
margin-bottom: $spacer-y*.75;
|
||||
}
|
||||
|
||||
.list-group-item {
|
||||
padding-left: $spacer-y;
|
||||
padding-right: $spacer-y;
|
||||
min-height: 64px;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
|
||||
&:first-child {
|
||||
border-top: none;
|
||||
}
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
|
||||
.list-group-item--has-links {
|
||||
display: block;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
&.active {
|
||||
background-color: $brand-primary;
|
||||
color: #FFF;
|
||||
opacity: 1;
|
||||
|
||||
.list-group-item--has-links,
|
||||
.list-group-item__status {
|
||||
color: #FFF;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.list-group-item__heading {
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
margin: 2px 0 5px;
|
||||
color: $body-color;
|
||||
}
|
||||
|
||||
.list-group-item__thumbnail {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
display: block;
|
||||
background: #ccc;
|
||||
float: left;
|
||||
margin: -12px 12px 0 -$spacer-y;
|
||||
}
|
||||
|
||||
// Show linked items
|
||||
.list-group-item--has-links,
|
||||
.list-group-item--is-linked {
|
||||
color: $brand-primary;
|
||||
float: right;
|
||||
font-size: $font-size-sm;
|
||||
position: absolute;
|
||||
right: $spacer-y;
|
||||
top: 27px;
|
||||
opacity: 0;
|
||||
transition: opacity .2s ease-in-out;
|
||||
|
||||
.font-icon-link {
|
||||
font-size: 16px;
|
||||
position: relative;
|
||||
top: 3px;
|
||||
margin-right: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
.list-group-item--published {
|
||||
opacity: .6;
|
||||
transition: opacity .2s ease-in-out;
|
||||
|
||||
.list-group-item__status {
|
||||
opacity: 0;
|
||||
transition: opacity .2s ease-in-out;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
|
||||
.list-group-item__status {
|
||||
display: inline-block;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +1,9 @@
|
||||
// TODO move to its own component list-group
|
||||
|
||||
import React from 'react';
|
||||
import SilverStripeComponent from 'lib/SilverStripeComponent';
|
||||
|
||||
class AccordionItem extends SilverStripeComponent {
|
||||
class ListGroupItem extends SilverStripeComponent {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
@ -24,9 +26,9 @@ class AccordionItem extends SilverStripeComponent {
|
||||
}
|
||||
}
|
||||
|
||||
AccordionItem.propTypes = {
|
||||
ListGroupItem.propTypes = {
|
||||
handleClickArg: React.PropTypes.any,
|
||||
handleClick: React.PropTypes.func,
|
||||
};
|
||||
|
||||
export default AccordionItem;
|
||||
export default ListGroupItem;
|
0
admin/client/src/components/ListGroup/README.md
Normal file
0
admin/client/src/components/ListGroup/README.md
Normal file
@ -1,118 +1 @@
|
||||
.campaign-items {
|
||||
|
||||
.list-group {
|
||||
margin-left: -$spacer-y;
|
||||
margin-right: -$spacer-y;
|
||||
border-bottom: 1px solid $border-color-light;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.list-group-item {
|
||||
padding-left: $spacer-y;
|
||||
padding-right: $spacer-y;
|
||||
min-height: 64px;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
|
||||
&:first-child {
|
||||
border-top: none;
|
||||
}
|
||||
&:hover,
|
||||
&:focus {
|
||||
text-decoration: none;
|
||||
|
||||
.list-group-item--has-links {
|
||||
display: block;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline-width: 1px;
|
||||
outline-offset: -1px;
|
||||
outline-style: solid;
|
||||
outline-color: $brand-primary;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
&.active {
|
||||
background-color: $brand-primary;
|
||||
color: #FFF;
|
||||
opacity: 1;
|
||||
|
||||
.list-group-item--has-links,
|
||||
.list-group-item__status {
|
||||
color: #FFF;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
// Focus color clashes with selected colour
|
||||
&:focus {
|
||||
outline-color: darken($brand-primary, 10%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.list-group-item-heading {
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
margin: 2px 0 5px;
|
||||
color: $body-color;
|
||||
}
|
||||
|
||||
.list-group-item__thumbnail {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
display: block;
|
||||
background: #ccc;
|
||||
float: left;
|
||||
// See negate padding on bootstrap .list-group-item in _list-group.scss
|
||||
margin: -12px 12px 0 (0 - $spacer-y);
|
||||
}
|
||||
|
||||
.label {
|
||||
text-transform: uppercase;
|
||||
font-size: 10px;
|
||||
font-weight: 400;
|
||||
letter-spacing: .4px;
|
||||
}
|
||||
|
||||
// Show linked items
|
||||
.list-group-item--has-links,
|
||||
.list-group-item--is-linked {
|
||||
color: $brand-primary;
|
||||
float: right;
|
||||
font-size: $font-size-sm;
|
||||
position: absolute;
|
||||
right: $spacer-y;
|
||||
top: 27px;
|
||||
opacity: 0;
|
||||
transition: opacity .2s ease-in-out;
|
||||
|
||||
.font-icon-link {
|
||||
font-size: 16px;
|
||||
position: relative;
|
||||
top: 3px;
|
||||
margin-right: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
.list-group-item--published {
|
||||
opacity: .6;
|
||||
transition: opacity .2s ease-in-out;
|
||||
|
||||
.list-group-item__status {
|
||||
opacity: 0;
|
||||
transition: opacity .2s ease-in-out;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
|
||||
.list-group-item__status {
|
||||
display: inline-block;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,8 +5,8 @@ import * as recordActions from 'state/records/RecordsActions';
|
||||
import * as campaignActions from 'state/campaign/CampaignActions';
|
||||
import SilverStripeComponent from 'lib/SilverStripeComponent';
|
||||
import Accordion from 'components/Accordion/Accordion';
|
||||
import AccordionGroup from 'components/Accordion/AccordionGroup';
|
||||
import AccordionItem from 'components/Accordion/AccordionItem';
|
||||
import AccordionBlock from 'components/Accordion/AccordionBlock';
|
||||
import ListGroupItem from 'components/ListGroup/ListGroupItem';
|
||||
import Toolbar from 'components/Toolbar/Toolbar';
|
||||
import FormAction from 'components/FormAction/FormAction';
|
||||
import CampaignAdminItem from './CampaignAdminItem';
|
||||
@ -49,12 +49,13 @@ class CampaignAdminList extends SilverStripeComponent {
|
||||
const itemGroups = this.groupItemsForSet();
|
||||
|
||||
// Get items in this set
|
||||
let accordionGroups = [];
|
||||
let accordionBlocks = [];
|
||||
|
||||
Object.keys(itemGroups).forEach(className => {
|
||||
const group = itemGroups[className];
|
||||
const groupCount = group.items.length;
|
||||
|
||||
let accordionItems = [];
|
||||
let listGroupItems = [];
|
||||
let title = `${groupCount} ${groupCount === 1 ? group.singular : group.plural}`;
|
||||
let groupid = `Set_${campaignId}_Group_${className}`;
|
||||
|
||||
@ -86,18 +87,23 @@ class CampaignAdminList extends SilverStripeComponent {
|
||||
itemClassNames.push('active');
|
||||
}
|
||||
|
||||
accordionItems.push(
|
||||
<AccordionItem key={item.ID} className={itemClassNames.join(' ')} handleClick={this.handleItemSelected} handleClickArg={item.ID} >
|
||||
listGroupItems.push(
|
||||
<ListGroupItem
|
||||
key={item.ID}
|
||||
className={itemClassNames.join(' ')}
|
||||
handleClick={this.handleItemSelected}
|
||||
handleClickArg={item.ID}
|
||||
>
|
||||
<CampaignAdminItem item={item} campaign={this.props.record} />
|
||||
</AccordionItem>
|
||||
</ListGroupItem>
|
||||
);
|
||||
});
|
||||
|
||||
// Merge into group
|
||||
accordionGroups.push(
|
||||
<AccordionGroup key={groupid} groupid={groupid} title={title}>
|
||||
{accordionItems}
|
||||
</AccordionGroup>
|
||||
accordionBlocks.push(
|
||||
<AccordionBlock key={groupid} groupid={groupid} title={title}>
|
||||
{listGroupItems}
|
||||
</AccordionBlock>
|
||||
);
|
||||
});
|
||||
|
||||
@ -114,7 +120,7 @@ class CampaignAdminList extends SilverStripeComponent {
|
||||
</Toolbar>
|
||||
<div className="container-fluid campaign-items panel-scrollable--double-toolbar">
|
||||
<Accordion>
|
||||
{accordionGroups}
|
||||
{accordionBlocks}
|
||||
</Accordion>
|
||||
</div>
|
||||
<div className="toolbar--south">
|
||||
|
@ -28,6 +28,7 @@
|
||||
|
||||
// Components
|
||||
@import "../components/Accordion/Accordion";
|
||||
@import "../components/ListGroup/ListGroup";
|
||||
@import "../components/Breadcrumb/Breadcrumb";
|
||||
@import "../components/FormAction/FormAction";
|
||||
@import "../components/GridField/GridField";
|
||||
|
Loading…
Reference in New Issue
Block a user