.container-fluid#themesList v-cloak="" data-controller="themes-list" .row .col-md-3 = render partial: "respondent_categories/sidebar" .col-md-9.d-flex.flex-column.overflow-hidden style="height: calc(100vh - 100px);" = render_breadcrumbs([ \ { name: 'Home', path: projects_path }, \ { name: @project.title, path: project_path(@project) }, \ { name: @respondent_category.name, path: [@project, @respondent_category] }, \ { name: "Highlight Themes" } \ ]) / Top Header Area .d-flex.align-items-center.justify-content-between.mb-4 .fs-30.semi-bold = @respondent_category.name .fs-20.medium.text-muted | All Themes / Sticky List Header .list-header.d-flex.align-items-center.fs-12.fw-bold.bg-light.p-3.rounded-top.position-sticky.top-0 style="z-index: 10;" .col-primary.flex-grow-1 Name .col-actions.text-center.px-3 colspan="2" Actions / Main Draggable List Container .list-container.flex-grow-1.overflow-auto ref="scrollContainer" style="min-height: 0;" .dragArea.rounded-bottom.border-top-0 draggable v-model="highlightThemes" :animation="200" @end="onDragEnd" handle=".drag-handle" item-key="id" tag="div" class="draggable-list" :scroll="scrollElement" :scrollSensitivity="100" :scrollSpeed="20" :forceFallback="true" :delay="1" scroll-container=".list-container" template #item="{ element: theme, index }" .list-row.d-flex.align-items-center.p-3.border-bottom.fs-12 :key="theme.id" :data-theme-id="theme.id" .col-primary.flex-grow-1 .d-flex.align-items-center .drag-handle.me-2.cursor-move vue-feather type="menu" class="text-muted mt-1" size="14" div v-if="currentEditingTheme != theme.id" | {{ theme.theme }} div v-if="currentEditingTheme == theme.id" .d-flex.align-items-center .flex-grow-1.me-2 input.form-control type="text" :id="'theme_edit_' + theme.id" :value="theme.theme" @keyup.enter="editTheme(theme.id, index)" @keyup.esc="stopThemeEdit()" button.btn.btn-clear type="button" @click="stopThemeEdit()" vue-feather type="x" class="text-primary" size="18" small Press Enter to save .col-actions.text-center.px-3 .d-flex.justify-content-center div v-if="currentEditingTheme != theme.id" button.btn.btn-clear.me-2 type="button" @click="startThemeEdit(theme.id)" vue-feather type="edit" class="text-primary" size="14" div v-if="currentEditingTheme == theme.id" .rounded.px-2.py-1.me-2 style="background-color: #F44174;" @click="editTheme(theme.id, index)" vue-feather type="check" class="text-white mt-1" size="14" button.btn.btn-clear type="button" @click="deleteTheme(theme.id)" vue-feather type="trash-2" class="text-primary" size="14" / STICKY FOOTER ACTION AREA .mt-auto.bg-white.pt-3.pb-4.border-top style="box-shadow: 0 -10px 15px -10px rgba(0,0,0,0.05);" .d-flex.align-items-center.justify-content-between.flex-nowrap / Add Theme Section .add-item-wrapper.flex-grow-1.position-relative button.btn.btn-outline-primary.d-flex.align-items-center type="button" v-if="themeInputEnabled == false" @click="toggleThemeInput()" vue-feather type="plus" class="me-2" size="18" span Add New Theme .new-item-input v-if="themeInputEnabled == true" .d-flex.align-items-center .flex-grow-1.me-2 input.form-control type="text" id="themeAddInput" @keyup.enter="addNewTheme()" @keyup.esc="toggleThemeInput()" placeholder="Enter theme name" ref="newThemeInput" button.btn.btn-primary.d-flex.align-items-center.me-2 type="button" @click="addNewTheme()" vue-feather type="check" class="text-white me-1" size="14" span Save button.btn.btn-secondary.d-flex.align-items-center type="button" @click="toggleThemeInput()" vue-feather type="x" class="me-1" size="14" span Cancel / Absolutely positioned tip to completely prevent layout shift small.text-muted.position-absolute.start-0.fs-12 style="bottom: -22px;" Tip: Press Enter to save / Toasts remain below this line .toast-container.position-fixed.top-0.end-0.p-3 .toast id="themeSuccessToast" role="alert" aria-live="assertive" aria-atomic="true" .toast-header i.feather-18.text-success data-feather="check-circle" strong.ms-2.me-auto Success! button.btn-close.btn-sm data-bs-dismiss="toast" aria-label="Close" .toast-body | {{ successMessage }} .toast-container.position-fixed.top-0.end-0.p-3 .toast id="themeErrorToast" role="alert" aria-live="assertive" aria-atomic="true" .toast-header i.feather-18.text-danger data-feather="x-octagon" strong.ms-2.me-auto Error! button.btn-close.btn-sm data-bs-dismiss="toast" aria-label="Close" .toast-body | {{ errorMessage }}