@hig/modal
Advanced tools
Comparing version
@@ -0,8 +1,168 @@ | ||
import { keyframes, css } from 'emotion'; | ||
import React, { Component } from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import IconButton from '@hig/icon-button'; | ||
import { XCloseGray24 } from '@hig/icons'; | ||
import cx from 'classnames'; | ||
import Typography from '@hig/typography'; | ||
import { Close16 } from '@hig/icons'; | ||
import { generateId } from '@hig/utils'; | ||
import ThemeContext from '@hig/theme-context'; | ||
var types = Object.freeze({ | ||
STANDARD: "standard", | ||
ALTERNATE: "alternate" | ||
}); | ||
var AVAILABLE_TYPES = Object.freeze(Object.values(types)); | ||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; | ||
var _templateObject = _taggedTemplateLiteral(["\n 0% { top: 131px; }\n 30% { top: 125px; }\n"], ["\n 0% { top: 131px; }\n 30% { top: 125px; }\n"]); | ||
function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); } | ||
var MODAL_BODY_LAYER = 1001; | ||
var MODAL_HEADER_LAYER = 1002; | ||
var MODAL_SHADOW_MASK_LAYER = 1003; | ||
var MODAL_LAYER = 10001; | ||
var WindowClosing = keyframes(_templateObject); | ||
function stylesheet(props, themeData) { | ||
var open = props.open, | ||
type = props.type; | ||
var headerFontSize = themeData["density.fontSizes.large"]; | ||
var headerLinHeight = 1.66666; | ||
return { | ||
modal: { | ||
wrapper: { | ||
color: themeData["modal.textColor"], | ||
opacity: open ? 1.0 : 0, | ||
pointerEvents: open ? "visible" : "none", | ||
transition: "all ease 0.2s", | ||
transitionDelay: open ? "0s" : "0.2s" | ||
}, | ||
overlay: { | ||
backgroundColor: themeData["modal.overlay.color"], | ||
bottom: 0, | ||
left: 0, | ||
position: "fixed", | ||
right: 0, | ||
top: 0, | ||
zIndex: MODAL_LAYER | ||
}, | ||
window: { | ||
background: themeData["modal.window.backgroundColor"], | ||
borderRadius: themeData["modal.window.borderRadius"], | ||
boxShadow: "0 0 8px 0 " + themeData["modal.window.shadowColor"], | ||
display: "flex", | ||
flexDirection: "column", | ||
left: "50%", | ||
height: themeData["modal.window.height"], | ||
width: themeData["modal.window.width"], | ||
opacity: open ? 1.0 : 0, | ||
outline: "none", | ||
position: "fixed", | ||
top: "128px", | ||
transform: "translateX(-50%)", | ||
zIndex: MODAL_BODY_LAYER, | ||
animation: open ? "none" : WindowClosing + " 0.4s", | ||
transition: "all ease 0.2s", | ||
transitionDelay: "0.2s" | ||
}, | ||
header: _extends({ | ||
fontSize: headerFontSize, | ||
lineHeight: headerLinHeight, | ||
display: "flex", | ||
flexDirection: "column", | ||
justifyContent: "center", | ||
borderBottom: "1px solid " + themeData["modal.header.borderColor"], | ||
minHeight: themeData["modal.header.height"], | ||
zIndex: MODAL_HEADER_LAYER | ||
}, type === types.ALTERNATE && { | ||
backgroundColor: themeData["modal.header.backgroundColor"] | ||
}), | ||
headerContent: { | ||
margin: "0 " + themeData["modal.horizontalPadding"], | ||
display: "flex", | ||
justifyContent: "space-between", | ||
".hig__icon-button.hig__icon-button--primary": _extends({ | ||
background: "transparent", | ||
border: "none", | ||
cursor: "pointer", | ||
padding: 0, | ||
height: "calc(" + headerFontSize + " * " + headerLinHeight + ")", | ||
minWidth: "16px", | ||
"svg *": { | ||
fill: themeData["modal.textColor"] | ||
}, | ||
"&:hover, &:focus": { | ||
borderColor: "transparent", | ||
backgroundColor: "transparent", | ||
"svg *": { | ||
fill: themeData["modal.textColor"] | ||
} | ||
}, | ||
"&:focus": { | ||
outline: "none" | ||
} | ||
}, type === types.ALTERNATE && { | ||
backgroundColor: themeData["modal.header.backgroundColor"] | ||
}) | ||
}, | ||
body: { | ||
display: "flex", | ||
flex: "1 1 auto", | ||
flexDirection: "column", | ||
overflow: "hidden", | ||
position: "relative", | ||
minHeight: themeData["modal.body.height"], | ||
"&::before": { | ||
backgroundColor: themeData["modal.window.backgroundColor"], | ||
content: "''", | ||
display: "block", | ||
height: "16px", | ||
position: "relative", | ||
margin: "0 " + themeData["modal.horizontalPadding"], | ||
zIndex: MODAL_SHADOW_MASK_LAYER | ||
}, | ||
"&::after": { | ||
backgroundColor: themeData["modal.window.backgroundColor"], | ||
content: "''", | ||
display: "block", | ||
height: "16px", | ||
position: "relative", | ||
margin: "0 " + themeData["modal.horizontalPadding"], | ||
zIndex: MODAL_SHADOW_MASK_LAYER | ||
} | ||
}, | ||
bodyContent: { | ||
border: "none", | ||
flex: "1 1 auto", | ||
overflowX: "auto", | ||
overflowY: "auto", | ||
padding: "0 " + themeData["modal.horizontalPadding"] | ||
} | ||
} | ||
}; | ||
} | ||
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | ||
@@ -28,6 +188,11 @@ | ||
value: function renderChildren() { | ||
var _props = this.props, | ||
children = _props.children, | ||
id = _props.id, | ||
styles = _props.styles; | ||
return React.createElement( | ||
"header", | ||
{ className: "hig__modal-V1__header", id: this.props.id }, | ||
this.props.children | ||
{ className: css(styles), id: id }, | ||
children | ||
); | ||
@@ -38,8 +203,9 @@ } | ||
value: function render() { | ||
var _props = this.props, | ||
children = _props.children, | ||
closeButtonAriaLabel = _props.closeButtonAriaLabel, | ||
id = _props.id, | ||
onCloseClick = _props.onCloseClick, | ||
title = _props.title; | ||
var _props2 = this.props, | ||
children = _props2.children, | ||
closeButtonAriaLabel = _props2.closeButtonAriaLabel, | ||
id = _props2.id, | ||
onCloseClick = _props2.onCloseClick, | ||
title = _props2.title, | ||
styles = _props2.styles; | ||
@@ -49,13 +215,22 @@ | ||
"header", | ||
{ className: "hig__modal-V1__header", id: id }, | ||
React.createElement(IconButton, { | ||
"aria-label": closeButtonAriaLabel, | ||
icon: React.createElement(XCloseGray24, null), | ||
onClick: onCloseClick, | ||
title: "Close" | ||
}), | ||
{ className: css(styles.header), id: id }, | ||
React.createElement( | ||
"span", | ||
{ className: "hig__modal-V1__header-title" }, | ||
title | ||
"div", | ||
{ className: css(styles.headerContent) }, | ||
React.createElement( | ||
Typography, | ||
{ | ||
style: { | ||
fontSize: styles.header.fontSize, | ||
lineHeight: styles.header.lineHeight | ||
} | ||
}, | ||
title | ||
), | ||
React.createElement(IconButton, { | ||
"aria-label": closeButtonAriaLabel, | ||
icon: React.createElement(Close16, null), | ||
onClick: onCloseClick, | ||
title: "Close" | ||
}) | ||
) | ||
@@ -88,2 +263,6 @@ ); | ||
/** | ||
* Styles for the modal header | ||
*/ | ||
styles: PropTypes.objectOf(PropTypes.any), | ||
/** | ||
* Title of the modal | ||
@@ -132,2 +311,12 @@ */ | ||
}, | ||
"styles": { | ||
"type": { | ||
"name": "objectOf", | ||
"value": { | ||
"name": "any" | ||
} | ||
}, | ||
"required": false, | ||
"description": "Styles for the modal header" | ||
}, | ||
"title": { | ||
@@ -143,15 +332,4 @@ "type": { | ||
var types = Object.freeze({ | ||
STANDARD: "standard", | ||
ALTERNATE: "alternate" | ||
}); | ||
var AVAILABLE_TYPES = Object.freeze(Object.values(types)); | ||
var _ModalPresenter$modif; | ||
var _createClass$1 = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | ||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } | ||
function _classCallCheck$1(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
@@ -177,5 +355,3 @@ | ||
return _ret = (_temp = (_this = _possibleConstructorReturn$1(this, (_ref = ModalPresenter.__proto__ || Object.getPrototypeOf(ModalPresenter)).call.apply(_ref, [this].concat(args))), _this), _this.setScrolling = function (element) { | ||
_this.hasScrolling = element.scrollHeight > element.clientHeight; | ||
}, _this.titleId = generateId("modal-title"), _temp), _possibleConstructorReturn$1(_this, _ret); | ||
return _ret = (_temp = (_this = _possibleConstructorReturn$1(this, (_ref = ModalPresenter.__proto__ || Object.getPrototypeOf(ModalPresenter)).call.apply(_ref, [this].concat(args))), _this), _this.titleId = generateId("modal-title"), _temp), _possibleConstructorReturn$1(_this, _ret); | ||
} | ||
@@ -186,2 +362,4 @@ | ||
value: function render() { | ||
var _this2 = this; | ||
var _props = this.props, | ||
@@ -195,17 +373,11 @@ children = _props.children, | ||
open = _props.open, | ||
customizeStyles = _props.stylesheet, | ||
title = _props.title, | ||
type = _props.type; | ||
var windowClasses = cx("hig__modal-V1__window", ModalPresenter.modifiersByType[type]); | ||
var wrapperClasses = cx(["hig__modal-V1", { | ||
"hig__modal-V1--open": open | ||
}]); | ||
/* | ||
* The "no-noninteractive-element-interactions" rule is disabled for this block. | ||
* This is due to the modal being is a special case where its containers are to be considered | ||
* as non-interactive, static content by screen-readers, but must also respond to `click` events. | ||
* Additionally, even though they respond to `click` events, they're not focusable. | ||
* as non-interactive, static content by screen-readers, but must also respond to `click` | ||
* events. Additionally, even though they respond to `click` events, they're not focusable. | ||
*/ | ||
@@ -217,42 +389,57 @@ /* | ||
*/ | ||
return React.createElement( | ||
"div", | ||
{ className: wrapperClasses }, | ||
React.createElement( | ||
"div", | ||
{ | ||
"aria-labelledby": this.titleId, | ||
className: "hig__modal-V1__overlay", | ||
onClick: onOverlayClick, | ||
role: "dialog", | ||
tabIndex: "-1" | ||
}, | ||
React.createElement( | ||
"article", | ||
{ | ||
className: windowClasses, | ||
onClick: onWindowClick, | ||
role: "document" | ||
}, | ||
ThemeContext.Consumer, | ||
null, | ||
function (_ref2) { | ||
var resolvedRoles = _ref2.resolvedRoles, | ||
metadata = _ref2.metadata; | ||
var styles = stylesheet({ open: open, type: type }, resolvedRoles); | ||
var cssStyles = customizeStyles ? customizeStyles(styles, _this2.props, resolvedRoles, metadata.colorSchemeId) : styles; | ||
return React.createElement( | ||
"div", | ||
{ className: css(cssStyles.modal.wrapper) }, | ||
React.createElement( | ||
ModalHeaderPresenter, | ||
"div", | ||
{ | ||
id: this.titleId, | ||
closeButtonAriaLabel: closeButtonAriaLabel, | ||
onCloseClick: onCloseClick, | ||
title: title | ||
"aria-labelledby": _this2.titleId, | ||
className: css(cssStyles.modal.overlay), | ||
onClick: onOverlayClick, | ||
role: "dialog", | ||
tabIndex: "-1" | ||
}, | ||
headerChildren | ||
), | ||
React.createElement( | ||
"section", | ||
{ className: "hig__modal-V1__body" }, | ||
React.createElement( | ||
"div", | ||
{ className: "hig__modal-V1__slot" }, | ||
children | ||
"article", | ||
{ | ||
className: css(cssStyles.modal.window), | ||
onClick: onWindowClick, | ||
role: "document" | ||
}, | ||
React.createElement( | ||
ModalHeaderPresenter, | ||
{ | ||
id: _this2.titleId, | ||
closeButtonAriaLabel: closeButtonAriaLabel, | ||
onCloseClick: onCloseClick, | ||
styles: styles.modal, | ||
title: title | ||
}, | ||
headerChildren | ||
), | ||
React.createElement( | ||
"section", | ||
{ className: css(cssStyles.modal.body) }, | ||
React.createElement( | ||
"div", | ||
{ className: css(cssStyles.modal.bodyContent) }, | ||
children | ||
) | ||
) | ||
) | ||
) | ||
) | ||
) | ||
); | ||
} | ||
); | ||
@@ -270,3 +457,2 @@ /* | ||
ModalPresenter.modifiersByType = (_ModalPresenter$modif = {}, _defineProperty(_ModalPresenter$modif, types.STANDARD, "hig__modal-V1__window--standard"), _defineProperty(_ModalPresenter$modif, types.ALTERNATE, "hig__modal-V1__window--alternate"), _ModalPresenter$modif); | ||
ModalPresenter.propTypes = { | ||
@@ -303,2 +489,6 @@ /** | ||
/** | ||
* Enables modification of Modal Styles | ||
*/ | ||
stylesheet: PropTypes.func, | ||
/** | ||
* Title of the modal | ||
@@ -368,2 +558,9 @@ */ | ||
}, | ||
"stylesheet": { | ||
"type": { | ||
"name": "func" | ||
}, | ||
"required": false, | ||
"description": "Enables modification of Modal Styles" | ||
}, | ||
"title": { | ||
@@ -529,2 +726,3 @@ "type": { | ||
open = _props.open, | ||
stylesheet = _props.stylesheet, | ||
title = _props.title, | ||
@@ -554,2 +752,3 @@ type = _props.type; | ||
open: open, | ||
stylesheet: stylesheet, | ||
title: title, | ||
@@ -595,2 +794,6 @@ type: type | ||
/** | ||
* Enables modification of Modal Styles | ||
*/ | ||
stylesheet: PropTypes.func, | ||
/** | ||
* Title of the modal | ||
@@ -650,2 +853,9 @@ */ | ||
}, | ||
"stylesheet": { | ||
"type": { | ||
"name": "func" | ||
}, | ||
"required": false, | ||
"description": "Enables modification of Modal Styles" | ||
}, | ||
"title": { | ||
@@ -652,0 +862,0 @@ "type": { |
@@ -7,2 +7,3 @@ 'use strict'; | ||
var emotion = require('emotion'); | ||
var React = require('react'); | ||
@@ -12,6 +13,165 @@ var React__default = _interopDefault(React); | ||
var IconButton = _interopDefault(require('@hig/icon-button')); | ||
var Typography = _interopDefault(require('@hig/typography')); | ||
var icons = require('@hig/icons'); | ||
var cx = _interopDefault(require('classnames')); | ||
var utils = require('@hig/utils'); | ||
var ThemeContext = _interopDefault(require('@hig/theme-context')); | ||
var types = Object.freeze({ | ||
STANDARD: "standard", | ||
ALTERNATE: "alternate" | ||
}); | ||
var AVAILABLE_TYPES = Object.freeze(Object.values(types)); | ||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; | ||
var _templateObject = _taggedTemplateLiteral(["\n 0% { top: 131px; }\n 30% { top: 125px; }\n"], ["\n 0% { top: 131px; }\n 30% { top: 125px; }\n"]); | ||
function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); } | ||
var MODAL_BODY_LAYER = 1001; | ||
var MODAL_HEADER_LAYER = 1002; | ||
var MODAL_SHADOW_MASK_LAYER = 1003; | ||
var MODAL_LAYER = 10001; | ||
var WindowClosing = emotion.keyframes(_templateObject); | ||
function stylesheet(props, themeData) { | ||
var open = props.open, | ||
type = props.type; | ||
var headerFontSize = themeData["density.fontSizes.large"]; | ||
var headerLinHeight = 1.66666; | ||
return { | ||
modal: { | ||
wrapper: { | ||
color: themeData["modal.textColor"], | ||
opacity: open ? 1.0 : 0, | ||
pointerEvents: open ? "visible" : "none", | ||
transition: "all ease 0.2s", | ||
transitionDelay: open ? "0s" : "0.2s" | ||
}, | ||
overlay: { | ||
backgroundColor: themeData["modal.overlay.color"], | ||
bottom: 0, | ||
left: 0, | ||
position: "fixed", | ||
right: 0, | ||
top: 0, | ||
zIndex: MODAL_LAYER | ||
}, | ||
window: { | ||
background: themeData["modal.window.backgroundColor"], | ||
borderRadius: themeData["modal.window.borderRadius"], | ||
boxShadow: "0 0 8px 0 " + themeData["modal.window.shadowColor"], | ||
display: "flex", | ||
flexDirection: "column", | ||
left: "50%", | ||
height: themeData["modal.window.height"], | ||
width: themeData["modal.window.width"], | ||
opacity: open ? 1.0 : 0, | ||
outline: "none", | ||
position: "fixed", | ||
top: "128px", | ||
transform: "translateX(-50%)", | ||
zIndex: MODAL_BODY_LAYER, | ||
animation: open ? "none" : WindowClosing + " 0.4s", | ||
transition: "all ease 0.2s", | ||
transitionDelay: "0.2s" | ||
}, | ||
header: _extends({ | ||
fontSize: headerFontSize, | ||
lineHeight: headerLinHeight, | ||
display: "flex", | ||
flexDirection: "column", | ||
justifyContent: "center", | ||
borderBottom: "1px solid " + themeData["modal.header.borderColor"], | ||
minHeight: themeData["modal.header.height"], | ||
zIndex: MODAL_HEADER_LAYER | ||
}, type === types.ALTERNATE && { | ||
backgroundColor: themeData["modal.header.backgroundColor"] | ||
}), | ||
headerContent: { | ||
margin: "0 " + themeData["modal.horizontalPadding"], | ||
display: "flex", | ||
justifyContent: "space-between", | ||
".hig__icon-button.hig__icon-button--primary": _extends({ | ||
background: "transparent", | ||
border: "none", | ||
cursor: "pointer", | ||
padding: 0, | ||
height: "calc(" + headerFontSize + " * " + headerLinHeight + ")", | ||
minWidth: "16px", | ||
"svg *": { | ||
fill: themeData["modal.textColor"] | ||
}, | ||
"&:hover, &:focus": { | ||
borderColor: "transparent", | ||
backgroundColor: "transparent", | ||
"svg *": { | ||
fill: themeData["modal.textColor"] | ||
} | ||
}, | ||
"&:focus": { | ||
outline: "none" | ||
} | ||
}, type === types.ALTERNATE && { | ||
backgroundColor: themeData["modal.header.backgroundColor"] | ||
}) | ||
}, | ||
body: { | ||
display: "flex", | ||
flex: "1 1 auto", | ||
flexDirection: "column", | ||
overflow: "hidden", | ||
position: "relative", | ||
minHeight: themeData["modal.body.height"], | ||
"&::before": { | ||
backgroundColor: themeData["modal.window.backgroundColor"], | ||
content: "''", | ||
display: "block", | ||
height: "16px", | ||
position: "relative", | ||
margin: "0 " + themeData["modal.horizontalPadding"], | ||
zIndex: MODAL_SHADOW_MASK_LAYER | ||
}, | ||
"&::after": { | ||
backgroundColor: themeData["modal.window.backgroundColor"], | ||
content: "''", | ||
display: "block", | ||
height: "16px", | ||
position: "relative", | ||
margin: "0 " + themeData["modal.horizontalPadding"], | ||
zIndex: MODAL_SHADOW_MASK_LAYER | ||
} | ||
}, | ||
bodyContent: { | ||
border: "none", | ||
flex: "1 1 auto", | ||
overflowX: "auto", | ||
overflowY: "auto", | ||
padding: "0 " + themeData["modal.horizontalPadding"] | ||
} | ||
} | ||
}; | ||
} | ||
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | ||
@@ -37,6 +197,11 @@ | ||
value: function renderChildren() { | ||
var _props = this.props, | ||
children = _props.children, | ||
id = _props.id, | ||
styles = _props.styles; | ||
return React__default.createElement( | ||
"header", | ||
{ className: "hig__modal-V1__header", id: this.props.id }, | ||
this.props.children | ||
{ className: emotion.css(styles), id: id }, | ||
children | ||
); | ||
@@ -47,8 +212,9 @@ } | ||
value: function render() { | ||
var _props = this.props, | ||
children = _props.children, | ||
closeButtonAriaLabel = _props.closeButtonAriaLabel, | ||
id = _props.id, | ||
onCloseClick = _props.onCloseClick, | ||
title = _props.title; | ||
var _props2 = this.props, | ||
children = _props2.children, | ||
closeButtonAriaLabel = _props2.closeButtonAriaLabel, | ||
id = _props2.id, | ||
onCloseClick = _props2.onCloseClick, | ||
title = _props2.title, | ||
styles = _props2.styles; | ||
@@ -58,13 +224,22 @@ | ||
"header", | ||
{ className: "hig__modal-V1__header", id: id }, | ||
React__default.createElement(IconButton, { | ||
"aria-label": closeButtonAriaLabel, | ||
icon: React__default.createElement(icons.XCloseGray24, null), | ||
onClick: onCloseClick, | ||
title: "Close" | ||
}), | ||
{ className: emotion.css(styles.header), id: id }, | ||
React__default.createElement( | ||
"span", | ||
{ className: "hig__modal-V1__header-title" }, | ||
title | ||
"div", | ||
{ className: emotion.css(styles.headerContent) }, | ||
React__default.createElement( | ||
Typography, | ||
{ | ||
style: { | ||
fontSize: styles.header.fontSize, | ||
lineHeight: styles.header.lineHeight | ||
} | ||
}, | ||
title | ||
), | ||
React__default.createElement(IconButton, { | ||
"aria-label": closeButtonAriaLabel, | ||
icon: React__default.createElement(icons.Close16, null), | ||
onClick: onCloseClick, | ||
title: "Close" | ||
}) | ||
) | ||
@@ -97,2 +272,6 @@ ); | ||
/** | ||
* Styles for the modal header | ||
*/ | ||
styles: PropTypes.objectOf(PropTypes.any), | ||
/** | ||
* Title of the modal | ||
@@ -141,2 +320,12 @@ */ | ||
}, | ||
"styles": { | ||
"type": { | ||
"name": "objectOf", | ||
"value": { | ||
"name": "any" | ||
} | ||
}, | ||
"required": false, | ||
"description": "Styles for the modal header" | ||
}, | ||
"title": { | ||
@@ -152,15 +341,4 @@ "type": { | ||
var types = Object.freeze({ | ||
STANDARD: "standard", | ||
ALTERNATE: "alternate" | ||
}); | ||
var AVAILABLE_TYPES = Object.freeze(Object.values(types)); | ||
var _ModalPresenter$modif; | ||
var _createClass$1 = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | ||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } | ||
function _classCallCheck$1(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
@@ -186,5 +364,3 @@ | ||
return _ret = (_temp = (_this = _possibleConstructorReturn$1(this, (_ref = ModalPresenter.__proto__ || Object.getPrototypeOf(ModalPresenter)).call.apply(_ref, [this].concat(args))), _this), _this.setScrolling = function (element) { | ||
_this.hasScrolling = element.scrollHeight > element.clientHeight; | ||
}, _this.titleId = utils.generateId("modal-title"), _temp), _possibleConstructorReturn$1(_this, _ret); | ||
return _ret = (_temp = (_this = _possibleConstructorReturn$1(this, (_ref = ModalPresenter.__proto__ || Object.getPrototypeOf(ModalPresenter)).call.apply(_ref, [this].concat(args))), _this), _this.titleId = utils.generateId("modal-title"), _temp), _possibleConstructorReturn$1(_this, _ret); | ||
} | ||
@@ -195,2 +371,4 @@ | ||
value: function render() { | ||
var _this2 = this; | ||
var _props = this.props, | ||
@@ -204,17 +382,11 @@ children = _props.children, | ||
open = _props.open, | ||
customizeStyles = _props.stylesheet, | ||
title = _props.title, | ||
type = _props.type; | ||
var windowClasses = cx("hig__modal-V1__window", ModalPresenter.modifiersByType[type]); | ||
var wrapperClasses = cx(["hig__modal-V1", { | ||
"hig__modal-V1--open": open | ||
}]); | ||
/* | ||
* The "no-noninteractive-element-interactions" rule is disabled for this block. | ||
* This is due to the modal being is a special case where its containers are to be considered | ||
* as non-interactive, static content by screen-readers, but must also respond to `click` events. | ||
* Additionally, even though they respond to `click` events, they're not focusable. | ||
* as non-interactive, static content by screen-readers, but must also respond to `click` | ||
* events. Additionally, even though they respond to `click` events, they're not focusable. | ||
*/ | ||
@@ -226,42 +398,57 @@ /* | ||
*/ | ||
return React__default.createElement( | ||
"div", | ||
{ className: wrapperClasses }, | ||
React__default.createElement( | ||
"div", | ||
{ | ||
"aria-labelledby": this.titleId, | ||
className: "hig__modal-V1__overlay", | ||
onClick: onOverlayClick, | ||
role: "dialog", | ||
tabIndex: "-1" | ||
}, | ||
React__default.createElement( | ||
"article", | ||
{ | ||
className: windowClasses, | ||
onClick: onWindowClick, | ||
role: "document" | ||
}, | ||
ThemeContext.Consumer, | ||
null, | ||
function (_ref2) { | ||
var resolvedRoles = _ref2.resolvedRoles, | ||
metadata = _ref2.metadata; | ||
var styles = stylesheet({ open: open, type: type }, resolvedRoles); | ||
var cssStyles = customizeStyles ? customizeStyles(styles, _this2.props, resolvedRoles, metadata.colorSchemeId) : styles; | ||
return React__default.createElement( | ||
"div", | ||
{ className: emotion.css(cssStyles.modal.wrapper) }, | ||
React__default.createElement( | ||
ModalHeaderPresenter, | ||
"div", | ||
{ | ||
id: this.titleId, | ||
closeButtonAriaLabel: closeButtonAriaLabel, | ||
onCloseClick: onCloseClick, | ||
title: title | ||
"aria-labelledby": _this2.titleId, | ||
className: emotion.css(cssStyles.modal.overlay), | ||
onClick: onOverlayClick, | ||
role: "dialog", | ||
tabIndex: "-1" | ||
}, | ||
headerChildren | ||
), | ||
React__default.createElement( | ||
"section", | ||
{ className: "hig__modal-V1__body" }, | ||
React__default.createElement( | ||
"div", | ||
{ className: "hig__modal-V1__slot" }, | ||
children | ||
"article", | ||
{ | ||
className: emotion.css(cssStyles.modal.window), | ||
onClick: onWindowClick, | ||
role: "document" | ||
}, | ||
React__default.createElement( | ||
ModalHeaderPresenter, | ||
{ | ||
id: _this2.titleId, | ||
closeButtonAriaLabel: closeButtonAriaLabel, | ||
onCloseClick: onCloseClick, | ||
styles: styles.modal, | ||
title: title | ||
}, | ||
headerChildren | ||
), | ||
React__default.createElement( | ||
"section", | ||
{ className: emotion.css(cssStyles.modal.body) }, | ||
React__default.createElement( | ||
"div", | ||
{ className: emotion.css(cssStyles.modal.bodyContent) }, | ||
children | ||
) | ||
) | ||
) | ||
) | ||
) | ||
) | ||
); | ||
} | ||
); | ||
@@ -279,3 +466,2 @@ /* | ||
ModalPresenter.modifiersByType = (_ModalPresenter$modif = {}, _defineProperty(_ModalPresenter$modif, types.STANDARD, "hig__modal-V1__window--standard"), _defineProperty(_ModalPresenter$modif, types.ALTERNATE, "hig__modal-V1__window--alternate"), _ModalPresenter$modif); | ||
ModalPresenter.propTypes = { | ||
@@ -312,2 +498,6 @@ /** | ||
/** | ||
* Enables modification of Modal Styles | ||
*/ | ||
stylesheet: PropTypes.func, | ||
/** | ||
* Title of the modal | ||
@@ -377,2 +567,9 @@ */ | ||
}, | ||
"stylesheet": { | ||
"type": { | ||
"name": "func" | ||
}, | ||
"required": false, | ||
"description": "Enables modification of Modal Styles" | ||
}, | ||
"title": { | ||
@@ -538,2 +735,3 @@ "type": { | ||
open = _props.open, | ||
stylesheet = _props.stylesheet, | ||
title = _props.title, | ||
@@ -563,2 +761,3 @@ type = _props.type; | ||
open: open, | ||
stylesheet: stylesheet, | ||
title: title, | ||
@@ -604,2 +803,6 @@ type: type | ||
/** | ||
* Enables modification of Modal Styles | ||
*/ | ||
stylesheet: PropTypes.func, | ||
/** | ||
* Title of the modal | ||
@@ -659,2 +862,9 @@ */ | ||
}, | ||
"stylesheet": { | ||
"type": { | ||
"name": "func" | ||
}, | ||
"required": false, | ||
"description": "Enables modification of Modal Styles" | ||
}, | ||
"title": { | ||
@@ -661,0 +871,0 @@ "type": { |
@@ -0,1 +1,18 @@ | ||
# [@hig/modal-v2.0.0](https://github.com/Autodesk/hig/compare/@hig/modal@1.0.2...@hig/modal@2.0.0) (2019-02-26) | ||
### Features | ||
* add stylesheet prop for Modal customization ([7034cea](https://github.com/Autodesk/hig/commit/7034cea)) | ||
* themable Modal ([0c71121](https://github.com/Autodesk/hig/commit/0c71121)) | ||
* use emotion and stylesheet function in Modal ([057d56f](https://github.com/Autodesk/hig/commit/057d56f)) | ||
### BREAKING CHANGES | ||
* A new look for Modal with theming options and a new `stylesheet` prop | ||
for customizing styles. | ||
* DOM classNames like hig__modal-V1* replaced with | ||
emotion-generated class names | ||
# [@hig/modal-v1.0.2](https://github.com/Autodesk/hig/compare/@hig/modal@1.0.1...@hig/modal@1.0.2) (2019-01-23) | ||
@@ -2,0 +19,0 @@ |
{ | ||
"name": "@hig/modal", | ||
"version": "1.0.2", | ||
"version": "2.0.0", | ||
"description": "HIG Modal", | ||
@@ -22,6 +22,9 @@ "author": "Autodesk Inc.", | ||
"@hig/icon-button": "^1.0.1", | ||
"@hig/icons": "^1.0.0", | ||
"@hig/icons": "^2.0.2", | ||
"@hig/fonts": "^1.0.1", | ||
"@hig/utils": "^0.3.0", | ||
"classnames": "^2.2.5", | ||
"prop-types": "^15.6.1", | ||
"@hig/theme-context": "^2.1.0", | ||
"@hig/typography": "^1.0.2", | ||
"emotion": "^10.0.0", | ||
"prop-types": "^15.7.1", | ||
"react-lifecycles-compat": "^3.0.4" | ||
@@ -38,3 +41,3 @@ }, | ||
"@hig/semantic-release-config": "^0.1.0", | ||
"@hig/styles": "^0.3.0" | ||
"lodash.merge": "^4.4.0" | ||
}, | ||
@@ -41,0 +44,0 @@ "scripts": { |
@@ -26,15 +26,44 @@ # Modal | ||
<Modal | ||
title="Are you sure?" | ||
title="Remove your item?" | ||
open | ||
buttons={[{ title: "Cancel", type: "secondary" }, { title: "Ok" }]} | ||
body="This is the text body of my modal" | ||
style="alternate" | ||
> | ||
<h1> | ||
<u>This is my HTML title</u> | ||
</h1> | ||
<p> | ||
<i>This is my HTML content.</i> | ||
</p> | ||
<Typography>This action is irreversible.</Typography> | ||
<Button title="Cancel" type="outline" /> | ||
<Button title="Remove" type="outline" /> | ||
</Modal> | ||
``` | ||
## Styling | ||
You will likely want to provide your own styles for the Modal body content, including positioning for Typography and Button elements. Modal has a `stylesheet` prop that accepts a function wherein you can modify Modal's styles. For instance | ||
```js | ||
import Modal from "@hig/modal"; | ||
import Typography from "@hig/typography"; | ||
import Button from "@hig/button"; | ||
import merge from "lodash.merge"; | ||
function YourComponent() { | ||
// ... | ||
const modalStyles = styles => | ||
merge(styles, { | ||
modal: { | ||
bodyContent: { | ||
display: "flex", | ||
flexDirection: "column", | ||
justifyContent: "space-between" | ||
} | ||
} | ||
}) | ||
return ( | ||
<Modal open title="Your title" stylesheet={modalStyles}> | ||
<Typography>Modal content</Typography> | ||
<div style={{ alignSelf: "flex-end" }}> | ||
<Button title="Ok" type="outline" /> | ||
</div> | ||
</Modal> | ||
) | ||
} | ||
``` |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
69
72.5%73699
-14.68%10
42.86%1762
-6.57%+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
- Removed
- Removed
Updated
Updated