Contents
Basic example
The most basic ListGroup
component is simply list ListGroupItem
components.
The components encapsulate the complexity of the underlying HTML, ensuring that all the
default CSS classes and other HTML attributes are present, leaving you with minimal markup.
Rendering OverReact Demo
.
.
.
import 'package:over_react/over_react.dart' ;
import '../../demo_components.dart' ;
ReactElement listGroupBasicDemo () = >
ListGroup ()(
ListGroupItem ()( 'Dapibus ac facilisis in' ),
ListGroupItem ()( 'Cras sit amet nibh libero' ),
ListGroupItem ()( 'Porta ac consectetur ac' ),
ListGroupItem ()( 'Vestibulum at eros' )
);
import 'package:over_react/over_react.dart' ;
import '../demo_components.dart' ;
part 'list_group.over_react.g.dart' ;
UiFactory < ListGroupProps > ListGroup = _$ListGroup ;
mixin ListGroupProps on UiProps {
/// The HTML element type for the [ListGroup], specifying its
/// DOM representation when rendered.
///
/// Default: [ListGroupElementType.DIV]
ListGroupElementType elementType ;
}
class ListGroupComponent extends UiComponent2 < ListGroupProps > {
@override
get defaultProps = > ( newProps (). . elementType = ListGroupElementType . DIV );
@override
render () {
var classes = forwardingClassNameBuilder ()
. . add ( 'list-group' );
return ( props . elementType . componentBuilderFactory ()
. . modifyProps ( addUnconsumedDomProps )
. . className = classes . toClassName ()
)( props . children );
}
}
class ListGroupElementType {
final BuilderOnlyUiFactory < DomProps > componentBuilderFactory ;
ListGroupElementType . _internal ( this . componentBuilderFactory );
/// A [Dom.ul] (HTML `<ul>` element)
static final ListGroupElementType UL = ListGroupElementType . _internal ( Dom . ul );
/// A [Dom.div] (HTML `<div>` element)
static final ListGroupElementType DIV = ListGroupElementType . _internal ( Dom . div );
}
import 'package:over_react/over_react.dart' ;
import '../demo_components.dart' ;
part 'list_group_item.over_react.g.dart' ;
UiFactory < ListGroupItemProps > ListGroupItem = _$ListGroupItem ;
mixin ListGroupItemProps on UiProps {
/// The HTML element type for the [ListGroupItem], specifying its DOM
/// representation when rendered.
///
/// Will only be used if [href] and [onClick] are both `null`.
///
/// Default: [ListGroupItemElementType.SPAN]
ListGroupItemElementType elementType ;
/// Optional header text to display within the [ListGroupItem] above
/// the value of [children].
///
/// See: <https://getbootstrap.com/docs/4.4/components/list-group/#custom-content>.
dynamic header ;
/// The size of the [header] text you desire.
///
/// Default: [ListGroupItemHeaderElementSize.H5]
ListGroupItemHeaderElementSize headerSize ;
/// Additional props to be added to the [header] element _(if specified)_.
Map headerProps ;
/// The skin / "context" for the [ListGroupItem].
///
/// See: <https://getbootstrap.com/docs/4.4/components/list-group/#contextual-classes>.
///
/// Default: [ListGroupItemSkin.DEFAULT]
ListGroupItemSkin skin ;
/// Whether the [ListGroupItem] should appear "active".
///
/// See: <https://getbootstrap.com/docs/4.4/components/list-group/#anchors-and-buttons>
///
/// Default: false
bool isActive ;
/// Whether the [ListGroupItem] is disabled.
///
/// See: <https://getbootstrap.com/docs/4.4/components/list-group/#disabled-items>
///
/// Default: false
@Accessor ( key: 'disabled' , keyNamespace: '' )
bool isDisabled ;
/// The HTML `href` attribute value for the [ListGroupItem].
///
/// If set, the item will render via [Dom.a].
///
/// _Proxies [DomProps.href]_
@Accessor ( keyNamespace: '' )
String href ;
/// The HTML `target` attribute value for the [ListGroupItem].
///
/// If set, the item will render via [Dom.a].
///
/// _Proxies [DomProps.target]_
@Accessor ( keyNamespace: '' )
String target ;
/// The HTML `type` attribute value for the [ListGroupItem] when
/// rendered via [Dom.button].
///
/// This will only be applied if [onClick] is also set.
///
/// _Proxies [DomProps.type]_
///
/// Default: [ButtonType.BUTTON]
ButtonType type ;
}
class ListGroupItemComponent extends UiComponent2 < ListGroupItemProps > {
@override
get defaultProps = > ( newProps ()
. . elementType = ListGroupItemElementType . SPAN
. . skin = ListGroupItemSkin . DEFAULT
. . isActive = false
. . isDisabled = false
. . type = ButtonType . BUTTON
. . headerSize = ListGroupItemHeaderElementSize . H5
);
@override
render () {
var children = props . children ;
if ( props . header != null ) {
children = [
renderItemHeader (),
( Dom . p ()
. . className = 'list-group-item-text'
. . key = 'item-text'
)( props . children )
];
}
BuilderOnlyUiFactory < DomProps > factory = _getItemDomNodeFactory ();
return ( factory ()
. . modifyProps ( addUnconsumedDomProps )
. . className = _getItemClasses () . toClassName ()
. . href = props . href
. . target = props . target
. . type = _isActionItem && ! _isAnchorLink ? props . type . typeName : null
. . disabled = _useDisabledAttr ? props . isDisabled : null
. aria . disabled = ! _useDisabledAttr ? props . isDisabled : null
)( children );
}
ReactElement renderItemHeader () {
if ( props . header == null ) return null ;
var headerClasses = ClassNameBuilder . fromProps ( props . headerProps )
. . add ( 'list-group-item-heading' );
return ( props . headerSize . componentBuilderFactory ()
. . addProps ( props . headerProps )
. . className = headerClasses . toClassName ()
. . key = 'item-header'
)( props . header );
}
BuilderOnlyUiFactory < DomProps > _getItemDomNodeFactory () {
BuilderOnlyUiFactory < DomProps > factory ;
if ( props . href != null ) {
factory = Dom . a ;
} else if ( props . onClick != null ) {
factory = Dom . button ;
} else {
factory = props . elementType . componentBuilderFactory ;
}
return factory ;
}
ClassNameBuilder _getItemClasses () {
return forwardingClassNameBuilder ()
. . add ( 'list-group-item' )
. . add ( 'list-group-item-action' , _isActionItem )
. . add ( 'active' , props . isActive )
. . add ( 'disabled' , props . isDisabled )
. . add ( props . skin . className );
}
bool get _useDisabledAttr = > _getItemDomNodeFactory () == Dom . button ;
bool get _isActionItem = > ( props . href ?? props . onClick ) != null ;
bool get _isAnchorLink = > props . href != null ;
}
class ListGroupItemSkin extends ClassNameConstant {
const ListGroupItemSkin . _ ( String name , String className ) : super ( name , className );
/// [className] value: null
static const ListGroupItemSkin DEFAULT =
ListGroupItemSkin . _ ( 'DEFAULT' , null );
/// [className] value: 'list-group-item-danger'
static const ListGroupItemSkin DANGER =
ListGroupItemSkin . _ ( 'DANGER' , 'list-group-item-danger' );
/// [className] value: 'list-group-item-success'
static const ListGroupItemSkin SUCCESS =
ListGroupItemSkin . _ ( 'SUCCESS' , 'list-group-item-success' );
/// [className] value: 'list-group-item-warning'
static const ListGroupItemSkin WARNING =
ListGroupItemSkin . _ ( 'WARNING' , 'list-group-item-warning' );
/// [className] value: 'list-group-item-info'
static const ListGroupItemSkin INFO =
ListGroupItemSkin . _ ( 'INFO' , 'list-group-item-info' );
}
class ListGroupItemElementType {
final BuilderOnlyUiFactory < DomProps > componentBuilderFactory ;
ListGroupItemElementType . _internal ( this . componentBuilderFactory );
/// A [Dom.li] (HTML `<li>` element)
///
/// Will only be used if [ListGroupItemProps.href] and
/// [ListGroupItemProps.onClick] are both `null`.
///
/// Only use this when the parent [ListGroup] has
/// [ListGroupProps.elementType] set to [ListGroupElementType.UL].
static final ListGroupItemElementType LI =
ListGroupItemElementType . _internal ( Dom . li );
/// A [Dom.span] (HTML `<span>` element)
///
/// Will only be used if [ListGroupItemProps.href] and
/// [ListGroupItemProps.onClick] are both `null`.
static final ListGroupItemElementType SPAN =
ListGroupItemElementType . _internal ( Dom . span );
}
class ListGroupItemHeaderElementSize {
final BuilderOnlyUiFactory < DomProps > componentBuilderFactory ;
ListGroupItemHeaderElementSize . _internal ( this . componentBuilderFactory );
/// A [Dom.h1] (HTML `<h1>` element)
static final ListGroupItemHeaderElementSize H1 =
ListGroupItemHeaderElementSize . _internal ( Dom . h1 );
/// A [Dom.h2] (HTML `<h2>` element)
static final ListGroupItemHeaderElementSize H2 =
ListGroupItemHeaderElementSize . _internal ( Dom . h2 );
/// A [Dom.h3] (HTML `<h3>` element)
static final ListGroupItemHeaderElementSize H3 =
ListGroupItemHeaderElementSize . _internal ( Dom . h3 );
/// A [Dom.h4] (HTML `<h4>` element)
static final ListGroupItemHeaderElementSize H4 =
ListGroupItemHeaderElementSize . _internal ( Dom . h4 );
/// A [Dom.h5] (HTML `<h5>` element)
static final ListGroupItemHeaderElementSize H5 =
ListGroupItemHeaderElementSize . _internal ( Dom . h5 );
/// A [Dom.h6] (HTML `<h6>` element)
static final ListGroupItemHeaderElementSize H6 =
ListGroupItemHeaderElementSize . _internal ( Dom . h6 );
}
Nest a Tag
component within any `ListGroupItem` to show unread counts, activity,
etc.
import 'package:over_react/over_react.dart' ;
import '../../demo_components.dart' ;
ReactElement listGroupTagsDemo () = >
ListGroup ()(
ListGroupItem ()(
( Tag ()
. . className = 'float-xs-right'
. . isPill = true
)( 14 ),
'Cras justo odio'
),
ListGroupItem ()(
( Tag ()
. . className = 'float-xs-right'
. . isPill = true
)( 2 ),
'Dapibus ac facilisis in'
),
ListGroupItem ()(
( Tag ()
. . className = 'float-xs-right'
. . isPill = true
)( 1 ),
'Morbi leo risus'
)
);
Set props.onClick
to render an HTML <button>
element, or props.href
to render an HTML <a>
element with hover, disabled, and active states.
Set props.isDisabled
to disable an item, and props.isActive
to make an item appear active.
import 'package:over_react/over_react.dart' ;
import '../../demo_components.dart' ;
ReactElement listGroupAnchorsAndButtonsDemo () = >
ListGroup ()(
( ListGroupItem ()
. . isActive = true
. . href = '#'
)( 'Cras justo odio' ),
( ListGroupItem ()
. . onClick = ( _ ) {}
)( 'Dapibus ac facilisis in' ),
( ListGroupItem ()
. . onClick = ( _ ) {}
)( 'Morbi leo risus' ),
( ListGroupItem ()
. . onClick = ( _ ) {}
)( 'Porta ac consectetur ac' ),
( ListGroupItem ()
. . isDisabled = true
. . onClick = ( _ ) {}
)( 'Vestibulum at eros' )
);
Contextual skins
Set props.skin
to style a ListGroupItem
using contextual colors.
Rendering OverReact Demo
.
.
.
import 'package:over_react/over_react.dart' ;
import '../../demo_components.dart' ;
ReactElement listGroupContextualSkinDemo () = >
ListGroup ()(
( ListGroupItem ()
. . onClick = ( _ ) {}
. . skin = ListGroupItemSkin . SUCCESS
)( 'Dapibus ac facilisis in' ),
( ListGroupItem ()
. . onClick = ( _ ) {}
. . skin = ListGroupItemSkin . INFO
)( 'Cras sit amet nibh libero' ),
( ListGroupItem ()
. . onClick = ( _ ) {}
. . skin = ListGroupItemSkin . WARNING
)( 'Porta ac consectetur ac' ),
( ListGroupItem ()
. . onClick = ( _ ) {}
. . skin = ListGroupItemSkin . DANGER
)( 'Vestibulum at eros' )
);
Set props.header
to render a ListGroupItem
that has a distinct header and body content
region.
Optionally, set props.headerSize
to modify the size of the header itself.
import 'package:over_react/over_react.dart' ;
import '../../demo_components.dart' ;
ReactElement listGroupHeaderDemo () = >
ListGroup ()(
( ListGroupItem ()
. . header = 'List group item heading'
. . onClick = ( _ ) {}
. . isActive = true
)(
'Donec id elit non mi porta gravida at eget metus. '
'Maecenas sed diam eget risus varius blandit.'
),
( ListGroupItem ()
. . header = 'List group item heading'
. . headerSize = ListGroupItemHeaderElementSize . H4
. . onClick = ( _ ) {}
)(
'Donec id elit non mi porta gravida at eget metus. '
'Maecenas sed diam eget risus varius blandit.'
),
( ListGroupItem ()
. . header = 'List group item heading'
. . headerSize = ListGroupItemHeaderElementSize . H3
. . onClick = ( _ ) {}
)(
'Donec id elit non mi porta gravida at eget metus. '
'Maecenas sed diam eget risus varius blandit.'
)
);