diff options
Diffstat (limited to 'app/assets/javascripts/vue_shared/components/settings/settings_block.vue')
-rw-r--r-- | app/assets/javascripts/vue_shared/components/settings/settings_block.vue | 84 |
1 files changed, 75 insertions, 9 deletions
diff --git a/app/assets/javascripts/vue_shared/components/settings/settings_block.vue b/app/assets/javascripts/vue_shared/components/settings/settings_block.vue index 92ae4575c52..e75fedbb1d7 100644 --- a/app/assets/javascripts/vue_shared/components/settings/settings_block.vue +++ b/app/assets/javascripts/vue_shared/components/settings/settings_block.vue @@ -1,5 +1,7 @@ <script> import { GlButton } from '@gitlab/ui'; +import { uniqueId } from 'lodash'; + import { __ } from '~/locale'; export default { @@ -15,35 +17,99 @@ export default { default: false, required: false, }, + collapsible: { + type: Boolean, + default: true, + required: false, + }, }, data() { return { - sectionExpanded: false, + // Non-collapsible sections should always be expanded. + // For collapsible sections, fall back to defaultExpanded. + sectionExpanded: !this.collapsible || this.defaultExpanded, }; }, computed: { - expanded() { - return this.defaultExpanded || this.sectionExpanded; - }, toggleText() { - return this.expanded ? __('Collapse') : __('Expand'); + const { collapseText, expandText } = this.$options.i18n; + return this.sectionExpanded ? collapseText : expandText; + }, + settingsContentId() { + return uniqueId('settings_content_'); }, + settingsLabelId() { + return uniqueId('settings_label_'); + }, + toggleButtonAriaLabel() { + const { collapseAriaLabel, expandAriaLabel } = this.$options.i18n; + return this.sectionExpanded ? collapseAriaLabel : expandAriaLabel; + }, + ariaExpanded() { + return String(this.sectionExpanded); + }, + }, + methods: { + toggleSectionExpanded() { + this.sectionExpanded = !this.sectionExpanded; + + if (this.sectionExpanded) { + this.$refs.settingsContent.focus(); + } + }, + }, + i18n: { + collapseText: __('Collapse'), + expandText: __('Expand'), + collapseAriaLabel: __('Collapse settings section'), + expandAriaLabel: __('Expand settings section'), }, }; </script> <template> - <section class="settings" :class="{ 'no-animate': !slideAnimated, expanded }"> + <section class="settings" :class="{ 'no-animate': !slideAnimated, expanded: sectionExpanded }"> <div class="settings-header"> - <h4><slot name="title"></slot></h4> - <gl-button @click="sectionExpanded = !sectionExpanded"> + <h4> + <span + v-if="collapsible" + :id="settingsLabelId" + role="button" + tabindex="0" + class="gl-cursor-pointer" + :aria-controls="settingsContentId" + :aria-expanded="ariaExpanded" + data-testid="section-title-button" + @click="toggleSectionExpanded" + @keydown.enter.space="toggleSectionExpanded" + > + <slot name="title"></slot> + </span> + <template v-else> + <slot name="title"></slot> + </template> + </h4> + <gl-button + v-if="collapsible" + :aria-controls="settingsContentId" + :aria-expanded="ariaExpanded" + :aria-label="toggleButtonAriaLabel" + @click="toggleSectionExpanded" + > {{ toggleText }} </gl-button> <p> <slot name="description"></slot> </p> </div> - <div class="settings-content"> + <div + :id="settingsContentId" + ref="settingsContent" + :aria-labelledby="settingsLabelId" + tabindex="-1" + role="region" + class="settings-content" + > <slot></slot> </div> </section> |