From 215f2f59e95d7a191aeb6afc8003fa141fd969c8 Mon Sep 17 00:00:00 2001 From: Geoffrey Roberts Date: Wed, 15 May 2019 06:02:47 -0700 Subject: [PATCH 1/3] Avatar (User Icon) Image Fixes/Enhancements * Add an `xxlarge` size option for `` component * Add logic to scale up Avatar Placeholder (User Icon) image depending on the size parameter passed to the `` component * Add additional avatar image samples with various sizes to the Image documentation page * Resolve ESLINT warnings in `Icon.react.js`, `Image.react.js` and `ElementsImage.react.js` documentation page --- docs/src/js/components/ElementsImage.react.js | 43 ++++++++++--------- src/Elements/Icon.react.js | 17 ++++---- src/Elements/Image.react.js | 35 ++++++++------- src/scss/components/Elements/Icon.scss | 1 + 4 files changed, 53 insertions(+), 43 deletions(-) diff --git a/docs/src/js/components/ElementsImage.react.js b/docs/src/js/components/ElementsImage.react.js index 1bdd731f7..1d73f0b94 100644 --- a/docs/src/js/components/ElementsImage.react.js +++ b/docs/src/js/components/ElementsImage.react.js @@ -2,15 +2,11 @@ import 'images/marty-mcfly.jpg'; -import PropTypes from 'prop-types'; -import React from 'react'; import { Card, Header, Image, TitleBar } from 'react-cm-ui'; - -// Docs UI Components -import Block from 'components/UI/Block.react'; -import Highlighter from 'components/UI/Highlighter.react'; -import Main from 'components/UI/Main.react'; -import TableProps from 'components/UI/TableProps.react'; +import Highlighter from 'components/UI/Highlighter.react.js'; +import Main from 'components/UI/Main.react.js'; +import React from 'react'; +import TableProps from 'components/UI/TableProps.react.js'; const imageSample = `import React from 'react'; import { Image } from 'react-cm-ui'; @@ -56,7 +52,11 @@ export default class SizeSample extends React.Component {




- +

+

+

+

+
); } @@ -70,13 +70,13 @@ export default class ElementsImage extends React.Component { type: 'enum', default: 'img', description: 'An element type to render as.', - allowedTypes: 'div, img' + allowedTypes: 'div, img', }, { name: 'avatar', type: 'bool', default: '', description: 'An Image can be shown as a circular avatar.', - allowedTypes: '' + allowedTypes: '', }, { name: 'className', type: 'string', @@ -88,20 +88,20 @@ export default class ElementsImage extends React.Component { type: 'number', default: '', description: 'Size of Image.', - allowedTypes: '' + allowedTypes: '', }, { name: 'src', type: 'string', default: '', description: 'Path to image file.', - allowedTypes: '' + allowedTypes: '', }, { name: 'style', type: 'object', default: '', description: 'Supply any inline styles to the Image or Image\'s container.', - allowedTypes: '' - } + allowedTypes: '', + }, ]; const martyMcFlyImageSrc = window.location.host.indexOf('localhost') > -1 ? @@ -119,7 +119,7 @@ export default class ElementsImage extends React.Component { {/* Image */} -
+
Image An image. @@ -133,7 +133,7 @@ export default class ElementsImage extends React.Component { {/* Avatar */} -
+
Avatar An image can be an avatar. @@ -151,7 +151,7 @@ export default class ElementsImage extends React.Component { {/* Size */} -
+
Size Passing a size (number) will contrain the image by its width. @@ -160,7 +160,11 @@ export default class ElementsImage extends React.Component {



- +

+

+

+

+ {sizeSample} @@ -168,5 +172,4 @@ export default class ElementsImage extends React.Component { ); } - } diff --git a/src/Elements/Icon.react.js b/src/Elements/Icon.react.js index 367b86b8b..d08f5e830 100644 --- a/src/Elements/Icon.react.js +++ b/src/Elements/Icon.react.js @@ -34,8 +34,9 @@ class Icon extends React.Component { 'icon-size-small': size === 'small', 'icon-size-xlarge': size === 'xlarge', 'icon-size-xsmall': size === 'xsmall', + 'icon-size-xxlarge': size === 'xxlarge', 'icon-size-xxsmall': size === 'xxsmall', - 'icon-spin': spin || type === 'spinner' + 'icon-spin': spin || type === 'spinner', }); const containerStyle = _.merge(style, { height: _.isNumber(size) ? `${size / 16}rem` : null, @@ -675,7 +676,7 @@ class Icon extends React.Component { {title || type} - + {renderGradientColor} @@ -698,7 +699,7 @@ class Icon extends React.Component { {title || type} - + {renderGradientColor} @@ -721,7 +722,7 @@ class Icon extends React.Component { {title || type} - + {renderGradientColor} @@ -767,7 +768,7 @@ class Icon extends React.Component { {title || type} - + {renderGradientColor} @@ -1028,7 +1029,7 @@ class Icon extends React.Component { {title || type} - + {renderGradientColor} @@ -3645,12 +3646,12 @@ Icon.propTypes = { rotate: PropTypes.number, size: PropTypes.oneOfType([ PropTypes.oneOf(Utils.sizeEnums()), - PropTypes.number + PropTypes.number, ]), spin: PropTypes.bool, style: PropTypes.object, title: PropTypes.string, - type: PropTypes.string.isRequired + type: PropTypes.string.isRequired, }; export default Icon; diff --git a/src/Elements/Image.react.js b/src/Elements/Image.react.js index 6a30fdd6e..f0a8fafcf 100644 --- a/src/Elements/Image.react.js +++ b/src/Elements/Image.react.js @@ -1,12 +1,9 @@ 'use strict'; -import _ from 'lodash'; +import React, { Component } from 'react'; import ClassNames from 'classnames'; +import Icon from '../Elements/Icon.react.js'; import PropTypes from 'prop-types'; -import React, { Component } from 'react'; - -import Icon from '../Elements/Icon.react'; - import Utils from '../utils/Utils.js'; class Image extends Component { @@ -21,13 +18,13 @@ class Image extends Component { const ElementType = Utils.getElementType(newAs, this.props); const containerClasses = ClassNames('ui', 'image', className, { - 'image-avatar': avatar + 'image-avatar': avatar, }); if (ElementType === 'img') { newStyle = Object.assign({}, style, { backgroundImage: src ? `url(${src})` : null, - width: size + width: size, }); return ( @@ -39,21 +36,29 @@ class Image extends Component { ); } + let newInitials, avatarSize = 'xsmall'; + if (avatar) { newStyle = Object.assign({}, style, { boxShadow: src ? 'none' : null, backgroundImage: src ? `url(${src})` : null, fontSize: !size || size < 44 ? '.75rem' : '1.125rem', height: size, - width: size + width: size, }); - } - let newInitials; + if (name) { + newInitials = name.match(/\b\w/g) || []; + newInitials = ((newInitials.shift() || '') + (newInitials.pop() || '')).toUpperCase(); + } - if (name) { - newInitials = name.match(/\b\w/g) || []; - newInitials = ((newInitials.shift() || '') + (newInitials.pop() || '')).toUpperCase(); + if (size >= 88) { + avatarSize = 'xxlarge'; + } else if (size >= 66) { + avatarSize = 'large'; + } else if (size >= 44) { + avatarSize = 'small'; + } } return ( @@ -65,7 +70,7 @@ class Image extends Component { {avatar && !src ? name ? newInitials : - ( ) : + ( ) : null} ); @@ -81,7 +86,7 @@ Image.propTypes = { name: PropTypes.string, size: PropTypes.number, src: PropTypes.string, - style: PropTypes.object + style: PropTypes.object, }; export default Image; diff --git a/src/scss/components/Elements/Icon.scss b/src/scss/components/Elements/Icon.scss index 9719b2e04..a3321c8a9 100644 --- a/src/scss/components/Elements/Icon.scss +++ b/src/scss/components/Elements/Icon.scss @@ -36,6 +36,7 @@ &-compact { margin: 0; } &.icon-disable { color: $color-text-disable; cursor: default; } &-size- { + &xxlarge, &xxlarge svg { height: rem(32px); width: rem(32px); } &xlarge, &xlarge svg { height: rem(24px); width: rem(24px); } &large, &large svg { height: rem(20px); width: rem(20px); } &medium, &medium svg { height: rem(18px); width: rem(18px); } From 8b8b6dd415e59d7b237c149f86ecd430421eea5b Mon Sep 17 00:00:00 2001 From: Geoffrey Roberts Date: Wed, 15 May 2019 08:18:32 -0700 Subject: [PATCH 2/3] Accordion update/enhancement * Add ability to have an `onClick` handler for items of a "basic" accordion and where item doesn't use `` and `` but only passes in a `title` prop. * Tested the basic accordion onClick functionality on the documentation page * Fix all ESLINT issues in `Accordion.react.js` and `ModulesAccordion.react.js` --- .../js/components/ModulesAccordion.react.js | 66 +++++++++++-------- src/Modules/Accordion.react.js | 54 +++++++-------- 2 files changed, 66 insertions(+), 54 deletions(-) diff --git a/docs/src/js/components/ModulesAccordion.react.js b/docs/src/js/components/ModulesAccordion.react.js index 4d0834b35..4d655a542 100644 --- a/docs/src/js/components/ModulesAccordion.react.js +++ b/docs/src/js/components/ModulesAccordion.react.js @@ -1,16 +1,13 @@ 'use strict'; -import PropTypes from 'prop-types'; +import { Accordion, Card, Header, SubNavigation, TitleBar } from 'react-cm-ui'; +import Block from 'components/UI/Block.react.js'; +import Highlighter from 'components/UI/Highlighter.react.js'; +import Main from 'components/UI/Main.react.js'; import React from 'react'; import ReactDOM from 'react-dom'; import ScrollBar from 'react-custom-scrollbars'; -import { Accordion, Card, Header, SubNavigation, TitleBar } from 'react-cm-ui'; - -// Docs UI Components -import Block from 'components/UI/Block.react'; -import Highlighter from 'components/UI/Highlighter.react'; -import Main from 'components/UI/Main.react'; import TableProps from 'components/UI/TableProps.react'; const accordionSample = `import React from 'react'; @@ -392,8 +389,7 @@ export default class CustomSummarySample extends React.Component { ); } -}` - +}`; export default class CollectionsAccordion extends React.Component { constructor(props) { @@ -402,10 +398,11 @@ export default class CollectionsAccordion extends React.Component { this.state = { scrollBarNode: null, subNavIndex: 0, - controlledExampleSelectedIndex: 0 // first item expanded by default + controlledExampleSelectedIndex: 0, // first item expanded by default }; this._onClickAccordionItem = this._onClickAccordionItem.bind(this); + this._onClickBasicAccordionItem = this._onClickBasicAccordionItem.bind(this); } render() { @@ -416,38 +413,38 @@ export default class CollectionsAccordion extends React.Component { type: 'bool', default: '', description: 'Simplify an Accordion to a basic pared down style.', - allowedTypes: '' + allowedTypes: '', }, { name: 'className', type: 'string', default: '', description: 'Additional classes.', - allowedTypes: '' + allowedTypes: '', }, { name: 'exclusive', type: 'bool', default: 'true', description: 'Only allow one Accordion Item to open at a time.', - allowedTypes: '' + allowedTypes: '', }, { name: 'inverse', type: 'bool', default: '', description: 'Format to appear on dark backgrounds.', - allowedTypes: '' + allowedTypes: '', }, { name: 'selected', type: 'array || number', default: '', description: 'Change the default selected Accordion Item.', - allowedTypes: '' + allowedTypes: '', }, { name: 'style', type: 'object', default: '', description: 'Supply any inline styles to the Accordion\'s container. Mainly used for padding and margins.', - allowedTypes: '' - } + allowedTypes: '', + }, ]; const itemProps = [ @@ -456,26 +453,26 @@ export default class CollectionsAccordion extends React.Component { type: 'string', default: '', description: 'Additional classes.', - allowedTypes: '' + allowedTypes: '', }, { name: 'style', type: 'object', default: '', description: 'Supply any inline styles to the Accordion\'s Item container. Mainly used for padding and margins.', - allowedTypes: '' + allowedTypes: '', }, { name: 'subAccordion', type: 'bool', default: '', description: 'Required boolean for Accordion\'s nested inside of Accordion Item container.', - allowedTypes: '' + allowedTypes: '', }, { name: 'summary', type: 'bool', default: 'true', description: 'Use custom content within an Accordion\'s Item.', - allowedTypes: '' - } + allowedTypes: '', + }, ]; let examplesJSX; @@ -603,7 +600,7 @@ export default class CollectionsAccordion extends React.Component {
Accordion - A baisc Accordion can be inverted to appear on darker backgrounds better. + A basic Accordion can be inverted to appear on darker backgrounds better.
@@ -642,11 +639,17 @@ export default class CollectionsAccordion extends React.Component {
- + this._onClickBasicAccordionItem('Option One')} + title="Option One" + >

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut commodo pretium odio, quis tristique sem suscipit eget. Morbi sit amet nibh quis lorem sodales suscipit. Nam a convallis sem. Pellentesque convallis tellus ex, nec finibus lacus placerat eget. Sed nec placerat nisl. Nam facilisis dolor non ante sollicitudin sollicitudin. Aliquam magna sem, ullamcorper eget ipsum tincidunt, lobortis semper magna. Mauris cursus urna nec tellus convallis mollis ut eget sem.

- + this._onClickBasicAccordionItem('Option Two')} + title="Option Two" + >

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut commodo pretium odio, quis tristique sem suscipit eget. Morbi sit amet nibh quis lorem sodales suscipit. Nam a convallis sem. Pellentesque convallis tellus ex, nec finibus lacus placerat eget. Sed nec placerat nisl. Nam facilisis dolor non ante sollicitudin sollicitudin. Aliquam magna sem, ullamcorper eget ipsum tincidunt, lobortis semper magna. Mauris cursus urna nec tellus convallis mollis ut eget sem.



@@ -752,7 +755,12 @@ export default class CollectionsAccordion extends React.Component {

- { this.scrollBarNode = scrollBarNode }}> + { + this.scrollBarNode = scrollBarNode; + }} + >

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut commodo pretium odio, quis tristique sem suscipit eget. Morbi sit amet nibh quis lorem sodales suscipit. Nam a convallis sem. Pellentesque convallis tellus ex, nec finibus lacus placerat eget. Sed nec placerat nisl. Nam facilisis dolor non ante sollicitudin sollicitudin. Aliquam magna sem, ullamcorper eget ipsum tincidunt, lobortis semper magna. Mauris cursus urna nec tellus convallis mollis ut eget sem.

@@ -814,7 +822,7 @@ export default class CollectionsAccordion extends React.Component {
selected prop - by passing an onClick handler function to each item’s summary.` + by passing an onClick handler function to each item’s summary.`, }} /> @@ -883,6 +891,10 @@ export default class CollectionsAccordion extends React.Component { this.setState({ controlledExampleSelectedIndex: newSelectedIndex }); } + _onClickBasicAccordionItem(foo) { + console.log(`${foo} item was clicked!`); // eslint-disable-line no-console + } + _onSubNavClick(index) { this.setState({ subNavIndex: index }); } diff --git a/src/Modules/Accordion.react.js b/src/Modules/Accordion.react.js index e049ddc2d..ecffddf01 100644 --- a/src/Modules/Accordion.react.js +++ b/src/Modules/Accordion.react.js @@ -1,15 +1,13 @@ 'use strict'; +import React, { Component } from 'react'; import _ from 'lodash'; import ClassNames from 'classnames'; +import DOMUtils from '../utils/DOMUtils.js'; +import Icon from '../Elements/Icon.react.js'; import PropTypes from 'prop-types'; -import React, { Component } from 'react'; import ReactDOM from 'react-dom'; -import Icon from '../Elements/Icon.react'; - -import DOMUtils from '../utils/DOMUtils.js'; - class AccordionItem extends Component { constructor(props) { super(props); @@ -32,7 +30,7 @@ class AccordionItem extends Component { const containerClasses = ClassNames('accordion-item', className, { 'accordion-item-is-active': isSelected, 'accordion-item-sub-accordion': subAccordion, - 'accordion-item-no-summary': summary === false + 'accordion-item-no-summary': summary === false, }); return ( @@ -48,8 +46,8 @@ class AccordionItem extends Component { 'animation': 'animationend', 'OAnimation': 'oAnimationEnd', 'MozAnimation': 'animationend', - 'WebkitAnimation': 'webkitAnimationEnd' - } + 'WebkitAnimation': 'webkitAnimationEnd', + }; for (a in animations) { if (el.style[a] !== undefined) { @@ -96,12 +94,12 @@ AccordionItem.propTypes = { isSelected: PropTypes.bool, scrollContainer: PropTypes.oneOfType([ PropTypes.object, - PropTypes.string + PropTypes.string, ]), scrollContainerMarginHeight: PropTypes.number, style: PropTypes.object, subAccordion: PropTypes.bool, - summary: PropTypes.bool + summary: PropTypes.bool, }; class AccordionSummary extends Component { @@ -125,18 +123,17 @@ class AccordionSummary extends Component { } AccordionSummary.propTypes = { - onClick: PropTypes.func + onClick: PropTypes.func, }; class AccordionCheckbox extends Component { - render() { return (
{this.props.children} @@ -147,11 +144,10 @@ class AccordionCheckbox extends Component { AccordionCheckbox.propTypes = { className: PropTypes.string, - style: PropTypes.object + style: PropTypes.object, }; class AccordionContent extends Component { - render() { return (
@@ -162,11 +158,10 @@ class AccordionContent extends Component { } AccordionContent.propTypes = { - style: PropTypes.object + style: PropTypes.object, }; class Accordion extends Component { - constructor(props) { super(props); @@ -215,11 +210,11 @@ class Accordion extends Component { const containerClasses = ClassNames('ui', 'accordion', className, { 'accordion-basic': basic, 'accordion-inverse': inverse, - 'accordion-inclusive': exclusive === false + 'accordion-inclusive': exclusive === false, }); - const convertChildren = _.isArray(children) ? children : [ children ]; - let items = _.map(convertChildren, (child, index) => { - const { children, className, style, subTitle, subAccordion, summary, title } = child.props; + const convertedChildren = _.isArray(children) ? children : [ children ]; + let items = _.map(convertedChildren, (child, index) => { + const { children, onClick, style, subTitle, subAccordion, summary, title } = child.props; const isSelected = exclusive === false ? _.includes(selected, index) : selected === index; if (title) { @@ -235,10 +230,16 @@ class Accordion extends Component { >
{title}{subTitle ? {subTitle} : null} - +
@@ -319,7 +320,6 @@ class Accordion extends Component { this.setState({ selected: newSelected }); } - } Accordion.Content = AccordionContent; @@ -335,14 +335,14 @@ Accordion.propTypes = { inverse: PropTypes.bool, scrollContainer: PropTypes.oneOfType([ PropTypes.object, - PropTypes.string + PropTypes.string, ]), scrollContainerMarginHeight: PropTypes.number, selected: PropTypes.oneOfType([ PropTypes.array, - PropTypes.number + PropTypes.number, ]), - style: PropTypes.object + style: PropTypes.object, }; export default Accordion; From 65a7033928e444384fc3afbfc6a3586b4236dfac Mon Sep 17 00:00:00 2001 From: Geoffrey Roberts Date: Wed, 15 May 2019 12:59:06 -0700 Subject: [PATCH 3/3] Add `xxlarge` to `size` enumeration and fix ESLINT issues in `Utils.js` --- src/utils/Utils.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/utils/Utils.js b/src/utils/Utils.js index 657a1e1ed..aceceda5b 100644 --- a/src/utils/Utils.js +++ b/src/utils/Utils.js @@ -24,7 +24,7 @@ class Utils { 'subject', 'success', 'transparent', - 'warning' + 'warning', ]; } @@ -37,7 +37,7 @@ class Utils { } static getIncreasingUniqueKey() { - var now = (new Date().getTime()).toString(); + const now = (new Date().getTime()).toString(); return now.substring(now.length - 6, now.length) + _.uniqueId(); } @@ -54,7 +54,7 @@ class Utils { 9: 'nine', 10: 'ten', 11: 'eleven', - 12: 'twelve' + 12: 'twelve', }; return numberToWordMap[num]; @@ -63,19 +63,20 @@ class Utils { static sizeEnums() { // Sorry, breaking the alphabetical order here in favor of Large to Small. Deal with it! return [ + 'xxlarge', 'xlarge', 'large', 'medium', 'small', 'xsmall', - 'xxsmall' + 'xxsmall', ]; } static themeEnums() { return [ 'dark', - 'light' + 'light', ]; } }