From 89420caebffb87c52cc82a8f7cc42a6104f30c87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barth=C3=A9l=C3=A9my=20Ledoux?= Date: Thu, 13 Feb 2020 08:01:03 -0600 Subject: [PATCH] Fix: Open all sections when searching (#1537) When searching with the option tocmode: 'collapse' the sections do not open automatically (because they keep their state). The found section or page is therefore not visible nor clickable. --- .../ComponentsList/ComponentsList.spec.tsx | 37 +++++++++++++++++++ .../ComponentsList/ComponentsListRenderer.tsx | 3 +- .../TableOfContents/TableOfContents.spec.tsx | 5 +++ .../TableOfContents/TableOfContents.tsx | 4 +- .../TableOfContents.spec.tsx.snap | 20 ++++++++++ src/typings/RsgSection.d.ts | 1 + 6 files changed, 67 insertions(+), 3 deletions(-) diff --git a/src/client/rsg-components/ComponentsList/ComponentsList.spec.tsx b/src/client/rsg-components/ComponentsList/ComponentsList.spec.tsx index fda98c55e..3844718b0 100644 --- a/src/client/rsg-components/ComponentsList/ComponentsList.spec.tsx +++ b/src/client/rsg-components/ComponentsList/ComponentsList.spec.tsx @@ -229,3 +229,40 @@ it('should show content of initialOpen items even if they are not active', () => Array.from(getAllByTestId('content')).map(node => (node as HTMLDivElement).innerHTML) ).toEqual(['Content for Button', 'Content for Input']); }); + +it('should show content of forcedOpen items even if they are initially collapsed', () => { + const components = [ + { + visibleName: 'Button', + name: 'Button', + slug: 'button', + content:
Content for Button
, + initialOpen: true, + }, + { + visibleName: 'Input', + name: 'Input', + slug: 'input', + content:
Content for Input
, + initialOpen: true, + forcedOpen: true, + }, + ]; + + const { getAllByTestId, getByText } = render( + + + + ); + + getByText('Input').click(); + + expect( + Array.from(getAllByTestId('content')).map(node => (node as HTMLDivElement).innerHTML) + ).toEqual(['Content for Button', 'Content for Input']); +}); diff --git a/src/client/rsg-components/ComponentsList/ComponentsListRenderer.tsx b/src/client/rsg-components/ComponentsList/ComponentsListRenderer.tsx index e4f29a0e1..4b7b135a8 100644 --- a/src/client/rsg-components/ComponentsList/ComponentsListRenderer.tsx +++ b/src/client/rsg-components/ComponentsList/ComponentsListRenderer.tsx @@ -63,6 +63,7 @@ const ComponentsListSectionRenderer: React.FunctionComponent { const { config: { tocMode }, @@ -85,7 +86,7 @@ const ComponentsListSectionRenderer: React.FunctionComponent {visibleName} - {open ? content : null} + {open || forcedOpen ? content : null} ); }; diff --git a/src/client/rsg-components/TableOfContents/TableOfContents.spec.tsx b/src/client/rsg-components/TableOfContents/TableOfContents.spec.tsx index a521f0768..2fbf79fb1 100644 --- a/src/client/rsg-components/TableOfContents/TableOfContents.spec.tsx +++ b/src/client/rsg-components/TableOfContents/TableOfContents.spec.tsx @@ -153,6 +153,7 @@ it('should render content of subsections of a section that has no components', ( Object { "components": Array [], "content": undefined, + "forcedOpen": false, "heading": false, "initialOpen": true, "sections": Array [], @@ -162,6 +163,7 @@ it('should render content of subsections of a section that has no components', ( Object { "components": Array [], "content": undefined, + "forcedOpen": false, "heading": false, "initialOpen": true, "sections": Array [], @@ -180,6 +182,7 @@ it('should render components of a single top section as root', () => { Object { "components": Array [], "content": undefined, + "forcedOpen": false, "heading": false, "initialOpen": true, "name": "Button", @@ -191,6 +194,7 @@ it('should render components of a single top section as root', () => { Object { "components": Array [], "content": undefined, + "forcedOpen": false, "heading": false, "initialOpen": true, "name": "Input", @@ -202,6 +206,7 @@ it('should render components of a single top section as root', () => { Object { "components": Array [], "content": undefined, + "forcedOpen": false, "heading": false, "initialOpen": true, "name": "Textarea", diff --git a/src/client/rsg-components/TableOfContents/TableOfContents.tsx b/src/client/rsg-components/TableOfContents/TableOfContents.tsx index 5c593235e..3d80ce416 100644 --- a/src/client/rsg-components/TableOfContents/TableOfContents.tsx +++ b/src/client/rsg-components/TableOfContents/TableOfContents.tsx @@ -76,8 +76,8 @@ export default class TableOfContents extends Component { content, selected, shouldOpenInNewTab: !!section.href, - initialOpen: - !!this.state.searchTerm.length || this.props.tocMode !== 'collapse' || containsSelected, + initialOpen: this.props.tocMode !== 'collapse' || containsSelected, + forcedOpen: !!this.state.searchTerm.length, }; }); return { diff --git a/src/client/rsg-components/TableOfContents/__snapshots__/TableOfContents.spec.tsx.snap b/src/client/rsg-components/TableOfContents/__snapshots__/TableOfContents.spec.tsx.snap index 1f67af506..8997a3541 100644 --- a/src/client/rsg-components/TableOfContents/__snapshots__/TableOfContents.spec.tsx.snap +++ b/src/client/rsg-components/TableOfContents/__snapshots__/TableOfContents.spec.tsx.snap @@ -32,6 +32,7 @@ exports[`should filter list when search field contains a query 1`] = ` Object { "components": Array [], "content": undefined, + "forcedOpen": false, "heading": false, "initialOpen": true, "name": "Button", @@ -43,6 +44,7 @@ exports[`should filter list when search field contains a query 1`] = ` Object { "components": Array [], "content": undefined, + "forcedOpen": false, "heading": false, "initialOpen": true, "name": "Input", @@ -54,6 +56,7 @@ exports[`should filter list when search field contains a query 1`] = ` Object { "components": Array [], "content": undefined, + "forcedOpen": false, "heading": false, "initialOpen": true, "name": "Textarea", @@ -82,6 +85,7 @@ exports[`should filter list when search field contains a query 2`] = ` Object { "components": Array [], "content": undefined, + "forcedOpen": true, "heading": false, "initialOpen": true, "name": "Button", @@ -110,6 +114,7 @@ exports[`should filter section names 1`] = ` Object { "components": Array [], "content": undefined, + "forcedOpen": false, "heading": false, "initialOpen": true, "name": "Introduction", @@ -135,6 +140,7 @@ exports[`should filter section names 1`] = ` Array [ Object { "content": undefined, + "forcedOpen": false, "heading": false, "initialOpen": true, "name": "Button", @@ -147,6 +153,7 @@ exports[`should filter section names 1`] = ` useHashId={true} useRouterLinks={false} />, + "forcedOpen": false, "heading": true, "initialOpen": true, "name": "Buttons", @@ -176,6 +183,7 @@ exports[`should filter section names 1`] = ` Array [ Object { "content": undefined, + "forcedOpen": false, "heading": false, "initialOpen": true, "name": "Input", @@ -185,6 +193,7 @@ exports[`should filter section names 1`] = ` }, Object { "content": undefined, + "forcedOpen": false, "heading": false, "initialOpen": true, "name": "Textarea", @@ -197,6 +206,7 @@ exports[`should filter section names 1`] = ` useHashId={true} useRouterLinks={false} />, + "forcedOpen": false, "heading": true, "initialOpen": true, "name": "Forms", @@ -225,6 +235,7 @@ exports[`should filter section names 2`] = ` Object { "components": Array [], "content": undefined, + "forcedOpen": true, "heading": false, "initialOpen": true, "name": "Forms", @@ -253,6 +264,7 @@ exports[`should render a renderer 1`] = ` Object { "components": Array [], "content": undefined, + "forcedOpen": false, "heading": false, "initialOpen": true, "name": "Button", @@ -264,6 +276,7 @@ exports[`should render a renderer 1`] = ` Object { "components": Array [], "content": undefined, + "forcedOpen": false, "heading": false, "initialOpen": true, "name": "Input", @@ -275,6 +288,7 @@ exports[`should render a renderer 1`] = ` Object { "components": Array [], "content": undefined, + "forcedOpen": false, "heading": false, "initialOpen": true, "name": "Textarea", @@ -303,6 +317,7 @@ exports[`should render renderer with sections with nested components 1`] = ` Object { "components": Array [], "content": undefined, + "forcedOpen": false, "heading": false, "initialOpen": true, "name": "Introduction", @@ -328,6 +343,7 @@ exports[`should render renderer with sections with nested components 1`] = ` Array [ Object { "content": undefined, + "forcedOpen": false, "heading": false, "initialOpen": true, "name": "Button", @@ -340,6 +356,7 @@ exports[`should render renderer with sections with nested components 1`] = ` useHashId={true} useRouterLinks={false} />, + "forcedOpen": false, "heading": true, "initialOpen": true, "name": "Buttons", @@ -369,6 +386,7 @@ exports[`should render renderer with sections with nested components 1`] = ` Array [ Object { "content": undefined, + "forcedOpen": false, "heading": false, "initialOpen": true, "name": "Input", @@ -378,6 +396,7 @@ exports[`should render renderer with sections with nested components 1`] = ` }, Object { "content": undefined, + "forcedOpen": false, "heading": false, "initialOpen": true, "name": "Textarea", @@ -390,6 +409,7 @@ exports[`should render renderer with sections with nested components 1`] = ` useHashId={true} useRouterLinks={false} />, + "forcedOpen": false, "heading": true, "initialOpen": true, "name": "Forms", diff --git a/src/typings/RsgSection.d.ts b/src/typings/RsgSection.d.ts index 67dcc54ba..33f272ad4 100644 --- a/src/typings/RsgSection.d.ts +++ b/src/typings/RsgSection.d.ts @@ -37,6 +37,7 @@ declare namespace Rsg { shouldOpenInNewTab?: boolean; selected?: boolean; initialOpen?: boolean; + forcedOpen?: boolean; content?: React.ReactNode; components?: TOCItem[]; sections?: TOCItem[];