Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-docs.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid O'Regan <doregan@gitlab.com>2023-08-01 18:28:25 +0300
committerDavid O'Regan <doregan@gitlab.com>2023-08-01 18:28:25 +0300
commit25828f26c2323658b2c9fa1fd6cb5e2bc89c2df6 (patch)
treed890b22df42027f20de9ee79b5febeed9fe51a6b
parentba6860ee32c0272444e4276885b4ba243d38c09e (diff)
parent2c6d1c0de42086d1fb5b85c3e26d5476b852e3ab (diff)
Merge branch 'replace-collapsible-container' into 'main'
Retire the collapsible_container component See merge request https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/4111 Merged-by: David O'Regan <doregan@gitlab.com> Approved-by: David O'Regan <doregan@gitlab.com> Co-authored-by: Sarah German <sgerman@gitlab.com>
-rw-r--r--content/frontend/default/components/collapsible_container.vue86
-rw-r--r--content/frontend/default/components/table_of_contents.vue19
-rw-r--r--content/frontend/default/setup_table_of_contents.js1
-rw-r--r--content/frontend/shared/dom.js13
-rw-r--r--layouts/default.html2
-rw-r--r--spec/frontend/default/components/__snapshots__/table_of_contents_spec.js.snap7
-rw-r--r--spec/frontend/default/components/collapsible_container_spec.js128
-rw-r--r--spec/frontend/default/components/table_of_contents_spec.js33
8 files changed, 16 insertions, 273 deletions
diff --git a/content/frontend/default/components/collapsible_container.vue b/content/frontend/default/components/collapsible_container.vue
deleted file mode 100644
index 59653ab8..00000000
--- a/content/frontend/default/components/collapsible_container.vue
+++ /dev/null
@@ -1,86 +0,0 @@
-<script>
-import { getOuterHeight } from '../../shared/dom';
-
-export default {
- name: 'CollapsibleContainer',
- model: {
- prop: 'isCollapsed',
- event: 'change',
- },
- props: {
- isCollapsed: {
- type: Boolean,
- required: true,
- },
- collapsingClass: {
- type: String,
- required: false,
- default: 'sm-collapsing',
- },
- collapsedClass: {
- type: String,
- required: false,
- default: 'sm-collapsed',
- },
- },
- data() {
- return {
- isCollapsing: false,
- collapsingHeight: 0,
- };
- },
- computed: {
- styles() {
- if (this.isCollapsing) {
- return {
- height: `${this.collapsingHeight}px`,
- };
- }
-
- return {};
- },
- classes() {
- if (this.isCollapsing) {
- return this.collapsingClass;
- }
- if (this.isCollapsed) {
- return this.collapsedClass;
- }
-
- return '';
- },
- },
- methods: {
- collapse(shouldCollapse) {
- if (this.isCollapsing) {
- return;
- }
- // Right away let's flag that we're collapsing so we don't accept anymore updates
- this.isCollapsing = true;
-
- // Let's let our parent go ahead and treat us as collapsed.
- this.$emit('change', shouldCollapse);
-
- // Get start/stop height based on if we're collapsing or expanding
- const containerHeight = getOuterHeight(this.$el);
- const startHeight = shouldCollapse ? containerHeight : 0;
- const stopHeight = shouldCollapse ? 0 : containerHeight;
-
- // Kick off transition
- this.collapsingHeight = startHeight;
- setTimeout(() => {
- this.collapsingHeight = stopHeight;
- }, 50);
-
- setTimeout(() => {
- this.isCollapsing = false;
- }, 400);
- },
- },
-};
-</script>
-<template>
- <div :class="classes" :style="styles">
- <slot></slot>
- </div>
-</template>
diff --git a/content/frontend/default/components/table_of_contents.vue b/content/frontend/default/components/table_of_contents.vue
index 542cd50b..7ffbc570 100644
--- a/content/frontend/default/components/table_of_contents.vue
+++ b/content/frontend/default/components/table_of_contents.vue
@@ -1,25 +1,28 @@
<script>
-import { GlIcon } from '@gitlab/ui';
+import { GlIcon, GlCollapse } from '@gitlab/ui';
import { flattenItems } from '../../shared/toc/flatten_items';
-import CollapsibleContainer from './collapsible_container.vue';
import TableOfContentsList from './table_of_contents_list.vue';
export default {
name: 'TableOfContents',
components: {
- CollapsibleContainer,
- TableOfContentsList,
+ GlCollapse,
GlIcon,
+ TableOfContentsList,
},
props: {
items: {
type: Array,
required: true,
},
+ initialCollapsed: {
+ type: Boolean,
+ required: true,
+ },
},
data() {
return {
- isCollapsed: true,
+ isCollapsed: this.initialCollapsed,
};
},
computed: {
@@ -33,7 +36,7 @@ export default {
},
methods: {
toggleCollapse() {
- this.$refs.container.collapse(!this.isCollapsed);
+ this.isCollapsed = !this.isCollapsed;
},
},
};
@@ -55,9 +58,9 @@ export default {
>
</h4>
<h4 class="border-0 gl-font-base font-weight-bold toc-lg">On this page</h4>
- <collapsible-container ref="container" v-model="isCollapsed" data-testid="container">
+ <gl-collapse ref="container" :visible="!isCollapsed" data-testid="container">
<table-of-contents-list :items="allItems" class="my-0" data-testid="main-list" />
- </collapsible-container>
+ </gl-collapse>
</div>
</div>
</template>
diff --git a/content/frontend/default/setup_table_of_contents.js b/content/frontend/default/setup_table_of_contents.js
index 5f0c7d73..c0aff655 100644
--- a/content/frontend/default/setup_table_of_contents.js
+++ b/content/frontend/default/setup_table_of_contents.js
@@ -35,6 +35,7 @@ export const setupTableOfContents = () => {
return h(TableOfContents, {
props: {
items,
+ initialCollapsed: sidebarEl.classList.contains('toc-mobile'),
},
directives: [
{
diff --git a/content/frontend/shared/dom.js b/content/frontend/shared/dom.js
index f4dbe540..4e285a01 100644
--- a/content/frontend/shared/dom.js
+++ b/content/frontend/shared/dom.js
@@ -1,16 +1,3 @@
-/* global $ */
-
-/**
- * Returns outerHeight of element **even if it's hidden**
- *
- * NOTE: Uses jQuery because there is no trivial way to do this in
- * vaniall JS, and it's nice that jQuery has a reliable out-of-the-box
- * solution.
- *
- * @param {Element} el
- */
-export const getOuterHeight = (el) => $(el).outerHeight();
-
/**
* Find the first child of the given element with the given tag name
*
diff --git a/layouts/default.html b/layouts/default.html
index 2d7905ea..abc1ee99 100644
--- a/layouts/default.html
+++ b/layouts/default.html
@@ -40,7 +40,7 @@
</div>
<div class="row d-xl-none">
<div class="col">
- <div class="doc-nav"></div>
+ <div class="doc-nav toc-mobile"></div>
</div>
</div>
<main>
diff --git a/spec/frontend/default/components/__snapshots__/table_of_contents_spec.js.snap b/spec/frontend/default/components/__snapshots__/table_of_contents_spec.js.snap
index e66a4c63..3880d071 100644
--- a/spec/frontend/default/components/__snapshots__/table_of_contents_spec.js.snap
+++ b/spec/frontend/default/components/__snapshots__/table_of_contents_spec.js.snap
@@ -29,11 +29,8 @@ exports[`frontend/default/components/table_of_contents matches snapshot 1`] = `
>
On this page
</h4>
- <collapsible-container-stub
- collapsedclass="sm-collapsed"
- collapsingclass="sm-collapsing"
+ <gl-collapse-stub
data-testid="container"
- iscollapsed="true"
>
<table-of-contents-list-stub
class="my-0"
@@ -41,7 +38,7 @@ exports[`frontend/default/components/table_of_contents matches snapshot 1`] = `
items="[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]"
level="0"
/>
- </collapsible-container-stub>
+ </gl-collapse-stub>
</div>
</div>
`;
diff --git a/spec/frontend/default/components/collapsible_container_spec.js b/spec/frontend/default/components/collapsible_container_spec.js
deleted file mode 100644
index 87395647..00000000
--- a/spec/frontend/default/components/collapsible_container_spec.js
+++ /dev/null
@@ -1,128 +0,0 @@
-/**
- * @jest-environment jsdom
- */
-
-import { shallowMount } from '@vue/test-utils';
-import CollapsibleContainer from '../../../../content/frontend/default/components/collapsible_container.vue';
-import * as dom from '../../../../content/frontend/shared/dom';
-
-const TEST_COLLAPSING_CLASS = 'test-collapsing';
-const TEST_COLLAPSED_CLASS = 'test-collapsed';
-const TEST_SLOT = 'Lorem ipsum dolar sit amit';
-const TEST_OUTER_HEIGHT = 400;
-const KICKOFF_DELAY = 50;
-const FINISH_DELAY = 400;
-
-describe('frontend/default/components/collapsible_container', () => {
- let wrapper;
-
- beforeEach(() => {
- // jquery is not available in Jest yet so we need to mock this method
- jest.spyOn(dom, 'getOuterHeight').mockImplementation((x) => Number(x.dataset.testOuterHeight));
- jest.useFakeTimers();
- });
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
-
- jest.useRealTimers();
- });
-
- const createComponent = (props = {}) => {
- wrapper = shallowMount(CollapsibleContainer, {
- propsData: {
- collapsingClass: TEST_COLLAPSING_CLASS,
- collapsedClass: TEST_COLLAPSED_CLASS,
- ...props,
- },
- slots: {
- default: TEST_SLOT,
- },
- attrs: {
- 'data-test-outer-height': TEST_OUTER_HEIGHT.toString(),
- },
- });
- };
- const findStyleHeight = () => wrapper.element.style.height;
- const waitForKickoff = () => jest.advanceTimersByTime(KICKOFF_DELAY);
- const waitForTransition = () => jest.advanceTimersByTime(FINISH_DELAY - KICKOFF_DELAY);
-
- describe.each`
- isCollapsed | startHeight | endHeight | startClasses | endClasses
- ${true} | ${0} | ${TEST_OUTER_HEIGHT} | ${[TEST_COLLAPSED_CLASS]} | ${[]}
- ${false} | ${TEST_OUTER_HEIGHT} | ${0} | ${[]} | ${[TEST_COLLAPSED_CLASS]}
- `(
- 'when isCollapsed = $isCollapsed',
- ({ isCollapsed, startHeight, endHeight, startClasses, endClasses }) => {
- beforeEach(() => {
- createComponent({ isCollapsed });
-
- return wrapper.vm.$nextTick();
- });
-
- it('renders slot', () => {
- expect(wrapper.text()).toBe(TEST_SLOT);
- });
-
- it('has starting classes', () => {
- expect(wrapper.classes()).toEqual(startClasses);
- });
-
- it('has not emitted anything', () => {
- expect(wrapper.emitted()).toEqual({});
- });
-
- describe('when collapse is triggered', () => {
- beforeEach(() => {
- wrapper.vm.collapse(!isCollapsed);
-
- // set props because this is what would naturally happen with `v-model`
- wrapper.setProps({ isCollapsed: !isCollapsed });
- });
-
- it('has collapsing class', () => {
- expect(wrapper.classes()).toEqual([TEST_COLLAPSING_CLASS]);
- });
-
- it('emits change', () => {
- expect(wrapper.emitted().change).toEqual([[!isCollapsed]]);
- });
-
- it('sets starting height', () => {
- expect(findStyleHeight()).toEqual(`${startHeight}px`);
- });
-
- it('triggering collapse again does not do anything', () => {
- wrapper.vm.collapse(isCollapsed);
-
- expect(wrapper.emitted().change).toEqual([[!isCollapsed]]);
- });
-
- describe('after animation kickoff delay', () => {
- beforeEach(() => {
- waitForKickoff();
- });
-
- it('sets ending height', () => {
- expect(findStyleHeight()).toEqual(`${endHeight}px`);
- });
-
- describe('after transition', () => {
- beforeEach(() => {
- waitForTransition();
- });
-
- it('does not set height', () => {
- expect(findStyleHeight()).toBe('');
- });
-
- it('sets ending classes', () => {
- expect(wrapper.classes()).toEqual(endClasses);
- });
- });
- });
- });
- },
- );
-});
diff --git a/spec/frontend/default/components/table_of_contents_spec.js b/spec/frontend/default/components/table_of_contents_spec.js
index 851258c3..88146c13 100644
--- a/spec/frontend/default/components/table_of_contents_spec.js
+++ b/spec/frontend/default/components/table_of_contents_spec.js
@@ -4,7 +4,6 @@
import { shallowMount, mount } from '@vue/test-utils';
import TableOfContents from '../../../../content/frontend/default/components/table_of_contents.vue';
-import * as dom from '../../../../content/frontend/shared/dom';
import { flattenItems } from '../../../../content/frontend/shared/toc/flatten_items';
import { createExampleToc } from '../../shared/toc_helper';
@@ -18,15 +17,11 @@ describe('frontend/default/components/table_of_contents', () => {
wrapper = null;
});
- beforeEach(() => {
- // jquery is not available in Jest yet so we need to mock this method
- jest.spyOn(dom, 'getOuterHeight').mockReturnValue(100);
- });
-
const createComponent = (props = {}, mountFn = shallowMount) => {
wrapper = mountFn(TableOfContents, {
propsData: {
items: TEST_ITEMS,
+ initialCollapsed: true,
...props,
},
});
@@ -34,14 +29,11 @@ describe('frontend/default/components/table_of_contents', () => {
const findCollapseButton = () => wrapper.find('[data-testid="collapse"]');
const findCollapseIcon = () => findCollapseButton().find('svg');
- const findCollapsibleContainer = () => wrapper.find('[data-testid="container"]');
const findMainList = () => wrapper.find('[data-testid="main-list"]');
const findMainListItems = () => findMainList().props('items');
- const clickCollapseButton = () => findCollapseButton().trigger('click');
const expectCollapsed = (isCollapsed = true) => {
expect(findCollapseButton().attributes('aria-expanded')).toBe(isCollapsed ? undefined : 'true');
- expect(findCollapsibleContainer().props('isCollapsed')).toBe(isCollapsed);
expect(findCollapseIcon().attributes('data-testid')).toBe(
isCollapsed ? 'chevron-right-icon' : 'chevron-down-icon',
);
@@ -64,28 +56,5 @@ describe('frontend/default/components/table_of_contents', () => {
it('is initially collapsed', () => {
expectCollapsed(true);
});
-
- describe('when collapse button is pressed', () => {
- beforeEach(() => {
- clickCollapseButton();
- });
-
- it('starts expanding', () => {
- expect(findCollapsibleContainer().classes('sm-collapsing')).toBe(true);
- });
-
- it('immediately updates collapse status', () => {
- expectCollapsed(false);
- });
-
- it('when button pressed again, nothing happens because in the middle of collapsing', () => {
- clickCollapseButton();
-
- return wrapper.vm.$nextTick(() => {
- expect(findCollapsibleContainer().classes('sm-collapsing')).toBe(true);
- expectCollapsed(false);
- });
- });
- });
});
});