diff --git a/CHANGELOG.md b/CHANGELOG.md index da049ea49e..238bc9551e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,25 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) **For example** - DP-1234: The short description text on a [service detail](http://mayflower.digital.mass.gov/?p=pages-detail-for-service-howto-location) page banner ([@organisms/by-template/page-banner](http://mayflower.digital.mass.gov/?p=organisms-page-banner)) should now render ([PR #493](https://github.com/massgov/mayflower/pull/493)) +## 9.2.0 (05/05/2019) + +### Added +- (Patternlab) [Header] DP-4562: Set focus state for search on mobile menu in mobileNav module. #473 +- (React) [HelpTip] DP-12875: Add `disabled` prop to disable HelpTip trigger text. #494 + +### Fixed +- (React) [InputSlider] DP-12732: Allows slider callback and updates form context on handler drag (Added onUpdate prop) #495 +- (React) [InputSlider] DP-12732: Allows keyboard actions and slider track click to update value (Changed handleChange from using onSlideEnd to onChange) #495 +- (React) [InputCurrency] DP-12807: Prevent InputCurrency returning NaN when default value is set to null #484 +- (React) [ErrorMessage] DP-12806: Fix error message inline styling #484 +- (React) [InputSlider] DP-12875: Disable handle button when InputSlider is disabled. #494 +- (React) [InputCurrency] DP-12890: Fix `NaN` value when defaultValue is null using up/down buttons. #498 + +### Changed +- (Patternlab) [SectionLinks] DP-9249: Topic card more links #472 +- (React) [InputCurrency] DP-12890: Pass event type to callback #498 + + ## 9.1.1 (02/19/2019) ### Fixed diff --git a/assets/scss/03-organisms/_help-tip.scss b/assets/scss/03-organisms/_help-tip.scss index 768b56a271..4a86611091 100644 --- a/assets/scss/03-organisms/_help-tip.scss +++ b/assets/scss/03-organisms/_help-tip.scss @@ -54,12 +54,20 @@ $border-width: 1px; border-bottom: 2px dotted $c-primary; background-color: $c-bay-blue-lightest; + svg { + margin-left: 5px; + width: 16px; + height: 16px; + margin-bottom: -.1em; + fill: $c-font-link; + } + &:focus { box-shadow: 0 0 3px 3px $c-focus; outline: 0; } - &.active, &:hover { + &--active, &:hover { background-color: $c-primary; color: $c-white; @@ -68,12 +76,8 @@ $border-width: 1px; } } - svg { - margin-left: 5px; - width: 16px; - height: 16px; - margin-bottom: -.1em; - fill: $c-font-link; + &--disabled { + pointer-events: none; } } diff --git a/changelogs/template.txt b/changelogs/template.md similarity index 60% rename from changelogs/template.txt rename to changelogs/template.md index 48891a63dd..d42d5b0e47 100644 --- a/changelogs/template.txt +++ b/changelogs/template.md @@ -1,7 +1,13 @@ +___EXAMPLE___ +Minor +Added +- (Patternlab) [Header] DP-4562: Set focus state for search on mobile menu in mobileNav module #473 +- (React) [HelpTip] DP-12875: Add `disabled` prop to disable HelpTip trigger text. #494 + ___DESCRIPTION___ -Change_type (see below) Change_impact (see below) -- (Project_prefix) DP-1234: Adds apples to apple trees for admin apple pickers #PR# +Change_type (see below) +- (Project_prefix) [ComponentName] DP-1234: Adds apples to apple trees for admin apple pickers #PR ___POST DEPLOY STEPS___ 1. Do this @@ -28,3 +34,8 @@ ___PROJECTS PREFIX___ - Patternlab - React - Docs + + +___COMPONENT NAME___ +Component name in `PascalCase` +e.g. Header, Form, InputSlider, InputTextTypeAhead diff --git a/docs/for-developers/changelog-instructions.md b/docs/for-developers/changelog-instructions.md index 3ee6ceee4c..2a6135f985 100644 --- a/docs/for-developers/changelog-instructions.md +++ b/docs/for-developers/changelog-instructions.md @@ -4,18 +4,20 @@ This documentation outlines a simple series of steps to keep `CHANGELOG.md` up-t ## Dev: Before You Submit a PR for a Feature Branch or Hot Fix -1. Make a copy of `changelogs/template.txt` with the ticket number as the name \(example: `DP-1234.txt`\). If there is no ticket number for the contribution, just use the branch name and your initials \(`awesome- feature-branch.txt`\). -2. Write a plain language description of the feature you're contributing. It needs to include the name, what changed, and who it impacts. -3. Write down any post deploy steps that need to be performed \(Examples: `This change will effect the local build. Make sure all developers know what steps to take after this gets in to dev`\). -4. Commit the file and open your PR. +1. Make a copy of `changelogs/template.md` with the ticket number as the name, e.g. `DP-1234.md.` If there is no ticket number for the contribution, just use the branch name and your initials, e.g. `awesome- feature-branch.md`. +2. Write a plain language description of the feature you're contributing. It needs to include the project prefix, component name, what changed, and who it impacts. +3. Write down any post deploy steps that need to be performed, e.g. +> This change will effect the local build. Make sure all developers know what steps to take after this gets in to dev. + +4. For any breaking changes, add a comment in the PR describing the necessary changes on the consumer side and link that comment in the changelog. +5. Commit the file and open your PR. ## Release Master: When you are Releasing Do this after your open your release branch: 1. In `CHANGELOG.md`, create a new section for the release with "Added", "Changed", and "Removed" sub-sections. -2. Go through each `changelogs/*.txt` file and copy the description into the appropriate sub-section of `CHANGELOG.md`. +2. Go through each `changelogs/*.md` file and copy the description into the appropriate sub-section of `CHANGELOG.md`. 3. Keep a list of post deployment steps handy for yourself. -4. After the last description is copied and you have all the post deployment steps, delete all files in `changelogs/` except for `changelogs/template.txt.` +4. After the last description is copied and you have all the post deployment steps, delete all files in `changelogs/` except for `changelogs/template.md`. 5. Commit changes to the release branch. - diff --git a/patternlab/styleguide/source/_patterns/02-molecules/section-links.twig b/patternlab/styleguide/source/_patterns/02-molecules/section-links.twig index b2e2bd7308..2fce87419c 100644 --- a/patternlab/styleguide/source/_patterns/02-molecules/section-links.twig +++ b/patternlab/styleguide/source/_patterns/02-molecules/section-links.twig @@ -27,6 +27,7 @@ "type": "", "href": sectionLinks.title.href, "text": "Learn More", + "labelContext": "about " ~ sectionLinks.title.text, "info": "learn more about " ~ sectionLinks.title.text } %} {% include "@atoms/decorative-link.twig" %} @@ -51,8 +52,15 @@ {% if sectionLinks.seeAll %}
{% endif %} diff --git a/patternlab/styleguide/source/assets/js/modules/mobileNav.js b/patternlab/styleguide/source/assets/js/modules/mobileNav.js index 93e76712b1..5d1e38e793 100644 --- a/patternlab/styleguide/source/assets/js/modules/mobileNav.js +++ b/patternlab/styleguide/source/assets/js/modules/mobileNav.js @@ -2,8 +2,8 @@ let menuButton = document.querySelector(".js-header-menu-button"); let feedbackButton = document.querySelector('.ma__fixed-feedback-button'); -if(null !== menuButton){ - menuButton.addEventListener("click", function(event) { +if (null !== menuButton) { + menuButton.addEventListener("click", function (event) { event.preventDefault(); document.querySelector("body").classList.toggle("show-menu"); @@ -15,13 +15,14 @@ if(null !== menuButton){ // ****** Main Header Search button on mobile should open the mobile menu ****** let searchForm = document.querySelector(".js-header-search-menu .js-header-search-form"); -if(null !== searchForm){ - searchForm.addEventListener("submit", function(event) { - if(window.innerWidth > 620) { +if (null !== searchForm) { + searchForm.addEventListener("submit", function (event) { + if (window.innerWidth > 620) { return; } event.preventDefault(); document.querySelector("body").classList.toggle("show-menu"); + document.querySelector('.ma__header__nav-search .ma__header-search__input').focus(); feedbackButton.classList.toggle("hide-button"); }); } diff --git a/react/backstop/data/bitmaps_reference/vrt_atoms_forms_Form_0_document_0_small_atom.png b/react/backstop/data/bitmaps_reference/vrt_atoms_forms_Form_0_document_0_small_atom.png index 3b117dda34..9ccbcaff30 100644 Binary files a/react/backstop/data/bitmaps_reference/vrt_atoms_forms_Form_0_document_0_small_atom.png and b/react/backstop/data/bitmaps_reference/vrt_atoms_forms_Form_0_document_0_small_atom.png differ diff --git a/react/src/components/atoms/forms/CompoundSlider/index.js b/react/src/components/atoms/forms/CompoundSlider/index.js index 04265e52d4..22bad0c6d5 100644 --- a/react/src/components/atoms/forms/CompoundSlider/index.js +++ b/react/src/components/atoms/forms/CompoundSlider/index.js @@ -9,7 +9,7 @@ import './style.css'; const Handle = (props) => { const { - handle: { id, value, percent }, getHandleProps, axis, min, max, step, displayValueFormat + handle: { id, value, percent }, getHandleProps, axis, min, max, step, displayValueFormat, disabled } = props; const decimalPlaces = countDecimals(step); const roundedValue = (Number.isInteger(step)) ? value : Number(Number.parseFloat(value).toFixed(decimalPlaces)); @@ -17,6 +17,7 @@ const Handle = (props) => { 'aria-valuemin': min, 'aria-valuemax': max, 'aria-valuenow': roundedValue, + disabled, role: 'slider', onClick: (e) => { e.preventDefault(); @@ -106,14 +107,22 @@ class CompoundSlider extends Component { { (context) => { const { - min, max, step, disabled, domain + min, max, step, disabled, domain, onChange, onUpdate } = this.props; const decimalPlaces = countDecimals(step); - const handleDragEnd = (values) => { + const handleChange = (values) => { const value = (Number.isInteger(step)) ? values[0] : Number(Number.parseFloat(values[0]).toFixed(decimalPlaces)); context.updateState({ value }, () => { - if (typeof this.props.onChange === 'function') { - this.props.onChange(value, this.props.id); + if (typeof onChange === 'function') { + onChange(value, this.props.id); + } + }); + }; + const handleUpdate = (values) => { + const value = (Number.isInteger(step)) ? values[0] : Number(Number.parseFloat(values[0]).toFixed(decimalPlaces)); + context.updateState({ value }, () => { + if (typeof onUpdate === 'function') { + onUpdate(value, this.props.id); } }); }; @@ -157,11 +166,14 @@ class CompoundSlider extends Component { domain, step, vertical: !(this.props.axis === 'x'), - onSlideEnd: handleDragEnd, + onChange: handleChange, values: [defaultValue], mode: handleMode, disabled }; + if (onUpdate) { + sliderProps.onUpdate = handleUpdate; + } const wrapperClasses = classNames({ 'ma__input-slider': true, 'ma__input-slider--disabled': disabled, @@ -190,6 +202,7 @@ class CompoundSlider extends Component { max={max} step={step} displayValueFormat={this.props.displayValueFormat} + disabled={disabled} /> ))} @@ -251,7 +264,9 @@ class CompoundSlider extends Component { CompoundSlider.propTypes = { /** The unique ID for the input field */ id: PropTypes.string.isRequired, - /** Custom change function */ + /** Custom update function, triggered with the values on drag (caution: high-volume updates when dragging). Only if a function is passed to onUpdate will form context get updated on drag. */ + onUpdate: PropTypes.func, + /** Custom on change function, triggered when the value of the slider has changed. This will recieve changes at the end of a slide as well as changes from clicks on rails and tracks. */ onChange: PropTypes.func, /** Default input text value */ defaultValue: PropTypes.string, diff --git a/react/src/components/atoms/forms/CompoundSlider/style.scss b/react/src/components/atoms/forms/CompoundSlider/style.scss index 6a33afc780..fc1cc6a203 100644 --- a/react/src/components/atoms/forms/CompoundSlider/style.scss +++ b/react/src/components/atoms/forms/CompoundSlider/style.scss @@ -65,9 +65,14 @@ $margin: 20px; &-handle { background-color: $c-gray-dark; cursor: not-allowed; + opacity: 1; &:hover { transform: none; } + + &-value { + color: $c-black; + } } } } diff --git a/react/src/components/atoms/forms/Form/Form.stories.js b/react/src/components/atoms/forms/Form/Form.stories.js index d8a727959f..4a01322ded 100644 --- a/react/src/components/atoms/forms/Form/Form.stories.js +++ b/react/src/components/atoms/forms/Form/Form.stories.js @@ -33,7 +33,7 @@ storiesOf('atoms/forms', module) inputSliderOptionsWithKnobs.domain = array('InputSlider.domain', [0, 1]).map((num) => Number(num)); inputSliderOptionsWithKnobs.max = number('InputSlider.max', 1); inputSliderOptionsWithKnobs.step = number('InputSlider.step', 0.01, { min: 0, max: 1, step: 0.01 }); - inputSliderOptionsWithKnobs.labelText = text('InputSlider.labelText', 'Slider (Linked to Input 3)'); + inputSliderOptionsWithKnobs.labelText = text('InputSlider.labelText', 'Slider (Linked to Input 0 and Input 1)'); const formTicks = object('InputSlider.ticks', { 0: '0%', 0.6: 'Minimum requirement', 1: '100%' }); const ticks = []; Object.keys(formTicks).forEach((tick) => ticks.push([tick, formTicks[tick]])); @@ -42,7 +42,7 @@ storiesOf('atoms/forms', module) delete InputCurrencyOptions.labelText; const inputCurrencyOptionsWithKnobs = Object.assign(...Object.entries(InputCurrencyOptions).map(([k, v]) => ( { [k]: v() }))); - inputCurrencyOptionsWithKnobs.labelText = text('InputCurrency.labelText', 'Currency Input (Set to 999 when Slider is 60)'); + inputCurrencyOptionsWithKnobs.labelText = text('InputCurrency.labelText', 'Currency Input (Set to 999 when Slider is greater than 60)'); const languages = new Map(); languages.set('Chinese', 'zh-CN'); languages.set('English', 'en-US'); @@ -55,28 +55,27 @@ storiesOf('atoms/forms', module) { (formContext) => { inputTextOptionsWithKnobs.onChange = (e, newVal, id) => { - if (formContext.hasId('test1')) { - if (formContext.getValue('test1') === 30) { - formContext.setValue({ id: 'test2', value: 25 }); - } - } // Keep test0 and test1 in sync. - if (formContext.hasId('test1') && formContext.hasId('test0')) { + if (formContext.hasId('test0') && formContext.hasId('test1') && (formContext.hasId('slider'))) { if (id === 'test0') { - formContext.setValue({ id: 'test1', value: formContext.getValue('test0') }); + const test0 = formContext.getValue('test0'); + formContext.setValue({ id: 'test1', value: 100 - test0 }); + formContext.setValue({ id: 'slider', value: test0 / 100 }); + if (test0 > 60) { + formContext.setValue({ id: 'currency-input', value: '$999.00' }); + } else { + formContext.setValue({ id: 'currency-input', value: '$0.00' }); + } } if (id === 'test1') { - formContext.setValue({ id: 'test0', value: formContext.getValue('test1') }); - } - } - if (formContext.hasId('test3')) { - if (id === 'test3') { - formContext.setValue({ id: 'slider', value: Number(formContext.getValue('test3') / 100).toFixed(2) }, () => { - // Use afterUpdate function so that slider is updated before this check. - if (formContext.getValue('slider') === 0.6) { - formContext.setValue({ id: 'currency-input', value: '$999.00' }); - } - }); + const test1 = formContext.getValue('test1'); + formContext.setValue({ id: 'test0', value: 100 - test1 }); + formContext.setValue({ id: 'slider', value: (100 - test1) / 100 }); + if ((100 - test1) > 60) { + formContext.setValue({ id: 'currency-input', value: '$999.00' }); + } else { + formContext.setValue({ id: 'currency-input', value: '$0.00' }); + } } } }; @@ -87,8 +86,9 @@ storiesOf('atoms/forms', module) ...inputTextOptionsWithKnobs, key: 'Form.InputNumber.test0', defaultValue: 0, - labelText: 'Input 0 (Linked to Input 1)', - id: 'test0' + labelText: 'Input 0 (Linked to Input 1 and Slider)', + id: 'test0', + unit: '%' } ], [ @@ -96,29 +96,10 @@ storiesOf('atoms/forms', module) { ...inputTextOptionsWithKnobs, key: 'Form.InputNumber.test1', - defaultValue: 1, - labelText: 'Input 1 (Linked to Input 0)', - id: 'test1' - } - ], - [ - 'test2', - { - ...inputTextOptionsWithKnobs, - key: 'Form.InputNumber.test2', - defaultValue: 2, - labelText: 'Input 2 (Set to 25 when Input 1 is 30)', - id: 'test2' - } - ], - [ - 'test3', - { - ...inputTextOptionsWithKnobs, - key: 'Form.InputNumber.test3', - defaultValue: 0, - labelText: 'Input 3 (Linked to Slider)', - id: 'test3' + defaultValue: 100, + labelText: 'Input 1 (Linked to Input 0 and Slider)', + id: 'test1', + unit: '%' } ] ]; @@ -126,21 +107,24 @@ storiesOf('atoms/forms', module) ids.forEach((numberProps) => { inputs.push(