1<script> 2import { GlButton, GlLoadingIcon, GlIcon } from '@gitlab/ui'; 3import { __ } from '~/locale'; 4 5export default { 6 components: { 7 GlButton, 8 GlLoadingIcon, 9 GlIcon, 10 }, 11 props: { 12 title: { 13 type: String, 14 required: true, 15 }, 16 isLoading: { 17 type: Boolean, 18 required: false, 19 default: false, 20 }, 21 hasError: { 22 type: Boolean, 23 required: false, 24 default: false, 25 }, 26 }, 27 data() { 28 return { 29 isCollapsed: true, 30 }; 31 }, 32 33 computed: { 34 arrowIconName() { 35 return this.isCollapsed ? 'angle-right' : 'angle-down'; 36 }, 37 ariaLabel() { 38 return this.isCollapsed ? __('Expand') : __('Collapse'); 39 }, 40 }, 41 methods: { 42 toggleCollapsed() { 43 this.isCollapsed = !this.isCollapsed; 44 }, 45 }, 46}; 47</script> 48<template> 49 <div> 50 <div class="mr-widget-extension d-flex align-items-center pl-3"> 51 <div v-if="hasError" class="ci-widget media"> 52 <div class="media-body"> 53 <span class="gl-font-sm mr-widget-margin-left gl-line-height-24 js-error-state"> 54 {{ title }} 55 </span> 56 </div> 57 </div> 58 59 <template v-else> 60 <button 61 class="btn-blank btn s32 square" 62 type="button" 63 :aria-label="ariaLabel" 64 :disabled="isLoading" 65 @click="toggleCollapsed" 66 > 67 <gl-loading-icon v-if="isLoading" size="sm" /> 68 <gl-icon v-else :name="arrowIconName" class="js-icon" /> 69 </button> 70 <template v-if="isCollapsed"> 71 <slot name="header"></slot> 72 <gl-button 73 variant="link" 74 data-testid="mr-collapsible-title" 75 :disabled="isLoading" 76 :class="{ 'border-0': isLoading }" 77 @click="toggleCollapsed" 78 > 79 {{ title }} 80 </gl-button> 81 </template> 82 <gl-button 83 v-else 84 variant="link" 85 data-testid="mr-collapsible-title" 86 :disabled="isLoading" 87 :class="{ 'border-0': isLoading }" 88 @click="toggleCollapsed" 89 >{{ __('Collapse') }}</gl-button 90 > 91 </template> 92 </div> 93 94 <div v-if="!isCollapsed" class="border-top js-slot-container"> 95 <slot></slot> 96 </div> 97 </div> 98</template> 99