From 88fae69098706c697236910cc51d00ddc7c9da02 Mon Sep 17 00:00:00 2001
From: Yeshwanth munagapati
Date: Wed, 29 Oct 2025 22:08:13 +0530
Subject: [PATCH 1/9] Content Library Catalog - Frequently asked questions page
changes
---
.../channelList/views/Channel/CatalogFAQ.vue | 432 +++++++++---------
.../Channel/__tests__/catalogFAQ.spec.js | 58 +++
.../frontend/shared/views/StudioAccordion.vue | 112 +++++
.../shared/views/StudioAccordionItem.vue | 35 ++
4 files changed, 422 insertions(+), 215 deletions(-)
create mode 100644 contentcuration/contentcuration/frontend/channelList/views/Channel/__tests__/catalogFAQ.spec.js
create mode 100644 contentcuration/contentcuration/frontend/shared/views/StudioAccordion.vue
create mode 100644 contentcuration/contentcuration/frontend/shared/views/StudioAccordionItem.vue
diff --git a/contentcuration/contentcuration/frontend/channelList/views/Channel/CatalogFAQ.vue b/contentcuration/contentcuration/frontend/channelList/views/Channel/CatalogFAQ.vue
index 9b0ea0097a..d3c924f37b 100644
--- a/contentcuration/contentcuration/frontend/channelList/views/Channel/CatalogFAQ.vue
+++ b/contentcuration/contentcuration/frontend/channelList/views/Channel/CatalogFAQ.vue
@@ -1,355 +1,350 @@
-
-
+
+
{{ $tr('aboutHeader') }}
-
-
+
+
{{ $tr('descriptionP1') }}
-
-
+
{{ $tr('descriptionP2') }}
-
+
{{ $tr('descriptionP3') }}
-
-
+
{{ $tr('aboutLibraryHeader') }}
-
-
+
+
+
+
-
-
-
- {{ $tr('selectionQuestion') }}
-
+
+
+ {{$tr('selectionQuestion')}}
-
-
+
+
+
{{ $tr('selectionAnswerP1') }}
{{ $tr('selectionAnswerP2') }}
-
-
-
+
+
+
+
-
-
-
- {{ $tr('maintenanceQuestion') }}
-
+
+
+ {{$tr('maintenanceQuestion')}}
-
-
+
+
+
{{ $tr('maintenanceAnswerP1') }}
{{ $tr('maintenanceAnswerP2') }}
-
-
-
-
+
+
+
-
-
-
- {{ $tr('endoresementQuestion') }}
-
+
+
+ {{ $tr('endoresementQuestion') }}
-
-
+
+
+
{{ $tr('endorsementAnswer') }}
-
-
-
+
+
+
-
-
-
- {{ $tr('ownershipQuestion') }}
-
+
+
+ {{ $tr('ownershipQuestion') }}
-
-
+
+
+
{{ $tr('ownershipAnswer') }}
-
-
-
+
+
+
-
-
-
- {{ $tr('newContentQuestion') }}
-
+
+
+ {{ $tr('newContentQuestion') }}
-
-
+
+
+
{{ $tr('newContentAnswer') }}
-
-
-
+
+
+
-
-
-
- {{ $tr('customContentQuestion') }}
-
+
+
+ {{ $tr('customContentQuestion') }}
-
-
+
+
+
{{ $tr('customContentAnswer') }}
-
-
-
-
+
+
+
+
+
-
-
+
{{ $tr('usingResourcesHeader') }}
-
-
+
+
+
-
-
-
- {{ $tr('usingContentQuestion') }}
-
+
+
+ {{ $tr('usingContentQuestion') }}
-
-
+
+
+
{{ $tr('usingContentAnswer') }}
-
-
-
-
+
+
+
-
-
-
- {{ $tr('channelQuestion') }}
-
+
+
+ {{ $tr('channelQuestion') }}
-
-
+
+
+
{{ $tr('channelAnswer') }}
-
-
-
+
+
+
-
-
-
- {{ $tr('sampleContentQuestion') }}
-
+
+
+ {{ $tr('sampleContentQuestion') }}
-
-
+
+
+
{{ $tr('sampleContentAnswer') }}
- {{ $tr('sampleContentAnswerItem1') }}
- {{ $tr('sampleContentAnswerItem2') }}
-
{{ $tr('sampleContentAnswerItem3') }}
-
-
-
-
+
+
+
-
-
-
- {{ $tr('partialChannelQuestion') }}
-
+
+
+ {{ $tr('partialChannelQuestion') }}
-
-
+
+
+
{{ $tr('partialChannelAnswer') }}
-
-
-
+
+
+
-
-
-
- {{ $tr('coachContentQuestion') }}
-
+
+
+ {{ $tr('coachContentQuestion') }}
-
-
+
+
+
{{ $tr('coachContentAnswer') }}
-
-
-
+
+
+
-
-
-
- {{ $tr('issueQuestion') }}
-
+
+
+ {{ $tr('issueQuestion') }}
-
-
+
+
+
{{ $tr('issueAnswer') }}
-
-
-
-
+
+
+
-
-
+
+
+
{{ $tr('aboutKolibriHeader') }}
-
-
+
+
+
-
-
-
- {{ $tr('KolibriQuestion') }}
-
+
+
+ {{ $tr('KolibriQuestion') }}
-
-
+
+
+
{{ $tr('KolibriAnswer') }}
- {{ $tr('KolibriAnswerItem1') }}
- {{ $tr('KolibriAnswerItem2') }}
- {{ $tr('KolibriAnswerItem3') }}
-
-
-
+
+
+
-
-
-
- {{ $tr('usingKolibriQuestion') }}
-
+
+
+ {{ $tr('usingKolibriQuestion') }}
-
-
+
+
+
{{ $tr('usingKolibriAnswerP1') }}
-
{{ $tr('usingKolibriItem1') }}
-
-
{{ $tr('usingKolibriItem2') }}
-
-
{{ $tr('usingKolibriItem3') }}
-
{{ $tr('usingKolibriAnswerP2') }}
-
-
-
-
+
+
+
-
-
-
- {{ $tr('makerQuestion') }}
-
+
+
+ {{ $tr('makerQuestion') }}
-
-
+
+
+
{{ $tr('makerAnswerP1') }}
{{ $tr('makerAnswerP2') }}
-
-
-
-
-
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/contentcuration/contentcuration/frontend/shared/views/StudioAccordionItem.vue b/contentcuration/contentcuration/frontend/shared/views/StudioAccordionItem.vue
new file mode 100644
index 0000000000..ea8c277603
--- /dev/null
+++ b/contentcuration/contentcuration/frontend/shared/views/StudioAccordionItem.vue
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
From bd0315ac7027dcb8c16c4e53c09927d3804c4c03 Mon Sep 17 00:00:00 2001
From: Yeshwanth munagapati
Date: Wed, 29 Oct 2025 22:16:53 +0530
Subject: [PATCH 2/9] lint fixes
---
.../channelList/views/Channel/CatalogFAQ.vue | 32 ++++++++-----------
.../Channel/__tests__/catalogFAQ.spec.js | 2 +-
.../frontend/shared/views/StudioAccordion.vue | 26 +++++++--------
.../shared/views/StudioAccordionItem.vue | 5 +--
4 files changed, 27 insertions(+), 38 deletions(-)
diff --git a/contentcuration/contentcuration/frontend/channelList/views/Channel/CatalogFAQ.vue b/contentcuration/contentcuration/frontend/channelList/views/Channel/CatalogFAQ.vue
index d3c924f37b..0815b6b6aa 100644
--- a/contentcuration/contentcuration/frontend/channelList/views/Channel/CatalogFAQ.vue
+++ b/contentcuration/contentcuration/frontend/channelList/views/Channel/CatalogFAQ.vue
@@ -26,11 +26,10 @@
-
- {{$tr('selectionQuestion')}}
+ {{ $tr('selectionQuestion') }}
@@ -39,13 +38,12 @@
{{ $tr('selectionAnswerP2') }}
-
- {{$tr('maintenanceQuestion')}}
+ {{ $tr('maintenanceQuestion') }}
@@ -114,14 +112,12 @@
-
{{ $tr('usingResourcesHeader') }}
-
@@ -220,14 +216,12 @@
-
{{ $tr('aboutKolibriHeader') }}
-
@@ -307,7 +301,6 @@
-
@@ -324,12 +317,11 @@
name: 'CatalogFAQ',
components: {
StudioAccordionItem,
- StudioAccordion
+ StudioAccordion,
},
mixins: [routerMixin],
setup() {
- const { windowIsSmall } =
- useKResponsiveWindow();
+ const { windowIsSmall } = useKResponsiveWindow();
return {
windowIsSmall,
};
@@ -467,10 +459,11 @@
padding: 0 24px;
}
- .main-title, .sub-title {
- font-weight: 700;
- font-size: 20px;
+ .main-title,
+ .sub-title {
margin-bottom: 8px;
+ font-size: 20px;
+ font-weight: 700;
}
.sub-title {
@@ -479,14 +472,15 @@
}
.desc {
- font-size: 16px;
padding: 0 4px;
+ font-size: 16px;
}
.faq-accordion {
- box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2),
- 0 1px 1px 0 rgba(0, 0, 0, 0.14),
- 0 1px 3px 0 rgba(0, 0, 0, 0.12);
+ box-shadow:
+ 0 2px 1px -1px rgba(0, 0, 0, 0.2),
+ 0 1px 1px 0 rgba(0, 0, 0, 0.14),
+ 0 1px 3px 0 rgba(0, 0, 0, 0.12);
}
diff --git a/contentcuration/contentcuration/frontend/channelList/views/Channel/__tests__/catalogFAQ.spec.js b/contentcuration/contentcuration/frontend/channelList/views/Channel/__tests__/catalogFAQ.spec.js
index df5850b3d8..908b2166b1 100644
--- a/contentcuration/contentcuration/frontend/channelList/views/Channel/__tests__/catalogFAQ.spec.js
+++ b/contentcuration/contentcuration/frontend/channelList/views/Channel/__tests__/catalogFAQ.spec.js
@@ -42,7 +42,7 @@ describe('CatalogFAQ test cases', () => {
it('supports Enter key to toggle accordion', async () => {
renderComponent();
- const firstAccordion= document.getElementById('studio-accordion');
+ const firstAccordion = document.getElementById('studio-accordion');
expect(firstAccordion).toBeInTheDocument();
await fireEvent.keyDown(firstAccordion, { key: 'Enter', code: 'Enter' });
diff --git a/contentcuration/contentcuration/frontend/shared/views/StudioAccordion.vue b/contentcuration/contentcuration/frontend/shared/views/StudioAccordion.vue
index 1ef220e6e5..de437de2d2 100644
--- a/contentcuration/contentcuration/frontend/shared/views/StudioAccordion.vue
+++ b/contentcuration/contentcuration/frontend/shared/views/StudioAccordion.vue
@@ -19,11 +19,9 @@
:layout12="{ span: 12 }"
@click="openAccordion()"
>
-
@@ -64,16 +61,16 @@
props: {
lastItem: {
type: Boolean,
- default: false
+ default: false,
},
id: {
type: String,
- default: 'studio-accordion'
- }
+ default: 'studio-accordion',
+ },
},
data() {
return {
- showAccordionItem: false
+ showAccordionItem: false,
};
},
methods: {
@@ -101,7 +98,8 @@
text-wrap: stable;
}
- .fade-enter-active, .fade-leave-active {
+ .fade-enter-active,
+ .fade-leave-active {
transition: opacity 0.3s cubic-bezier(0.25, 0.8, 0.5, 1);
}
@@ -109,4 +107,4 @@
font-size: 24px;
}
-
\ No newline at end of file
+
diff --git a/contentcuration/contentcuration/frontend/shared/views/StudioAccordionItem.vue b/contentcuration/contentcuration/frontend/shared/views/StudioAccordionItem.vue
index ea8c277603..76d2eaf7c4 100644
--- a/contentcuration/contentcuration/frontend/shared/views/StudioAccordionItem.vue
+++ b/contentcuration/contentcuration/frontend/shared/views/StudioAccordionItem.vue
@@ -6,10 +6,7 @@
}"
>
-
-
+
From e00a18841e3e692ab2f7b652dc0d210e215c1260 Mon Sep 17 00:00:00 2001
From: Yeshwanth munagapati
Date: Mon, 3 Nov 2025 22:00:42 +0530
Subject: [PATCH 3/9] updated view docs redirection
---
.../frontend/channelList/views/Channel/CatalogFAQ.vue | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/contentcuration/contentcuration/frontend/channelList/views/Channel/CatalogFAQ.vue b/contentcuration/contentcuration/frontend/channelList/views/Channel/CatalogFAQ.vue
index 0815b6b6aa..a417436354 100644
--- a/contentcuration/contentcuration/frontend/channelList/views/Channel/CatalogFAQ.vue
+++ b/contentcuration/contentcuration/frontend/channelList/views/Channel/CatalogFAQ.vue
@@ -280,7 +280,7 @@
From 32a19be5c3d8ec7f22bcaac01924fd4b88b0ed98 Mon Sep 17 00:00:00 2001
From: Yeshwanth munagapati
Date: Tue, 25 Nov 2025 12:45:33 +0530
Subject: [PATCH 4/9] accessibility changes
---
.../Channel/__tests__/catalogFAQ.spec.js | 16 ++-------
.../frontend/shared/views/StudioAccordion.vue | 33 +++++++++----------
2 files changed, 18 insertions(+), 31 deletions(-)
diff --git a/contentcuration/contentcuration/frontend/channelList/views/Channel/__tests__/catalogFAQ.spec.js b/contentcuration/contentcuration/frontend/channelList/views/Channel/__tests__/catalogFAQ.spec.js
index 908b2166b1..2b0805d56e 100644
--- a/contentcuration/contentcuration/frontend/channelList/views/Channel/__tests__/catalogFAQ.spec.js
+++ b/contentcuration/contentcuration/frontend/channelList/views/Channel/__tests__/catalogFAQ.spec.js
@@ -9,18 +9,6 @@ const router = new VueRouter({
const renderComponent = (props = {}) => {
return render(CatalogFAQ, {
props,
- // mocks: {
- // $tr: key => key, // Mock translation function
- // $themeTokens: {
- // surface: '#ffffff',
- // },
- // $themePalette: {
- // grey: {
- // v_400: '#9e9e9e',
- // v_200: '#eeeeee',
- // },
- // },
- // },
routes: router,
});
};
@@ -40,12 +28,12 @@ describe('CatalogFAQ test cases', () => {
expect(accordions.length).toBe(15);
});
- it('supports Enter key to toggle accordion', async () => {
+ it('expands accordion to show content when user clicks button', async () => {
renderComponent();
const firstAccordion = document.getElementById('studio-accordion');
expect(firstAccordion).toBeInTheDocument();
- await fireEvent.keyDown(firstAccordion, { key: 'Enter', code: 'Enter' });
+ await fireEvent.click(firstAccordion);
const accordionContent = document.querySelector('.item-content');
expect(accordionContent).toBeInTheDocument();
diff --git a/contentcuration/contentcuration/frontend/shared/views/StudioAccordion.vue b/contentcuration/contentcuration/frontend/shared/views/StudioAccordion.vue
index de437de2d2..710a3b0f13 100644
--- a/contentcuration/contentcuration/frontend/shared/views/StudioAccordion.vue
+++ b/contentcuration/contentcuration/frontend/shared/views/StudioAccordion.vue
@@ -1,13 +1,7 @@
-
+
-
+
+
@@ -42,7 +40,6 @@
-
@@ -27,7 +27,7 @@
-
+
{{ $tr('selectionQuestion') }}
@@ -41,7 +41,7 @@
-
+
{{ $tr('maintenanceQuestion') }}
@@ -62,7 +62,7 @@
-
+
{{ $tr('endoresementQuestion') }}
@@ -75,7 +75,7 @@
-
+
{{ $tr('ownershipQuestion') }}
@@ -88,7 +88,7 @@
-
+
{{ $tr('newContentQuestion') }}
@@ -101,7 +101,10 @@
-
+
{{ $tr('customContentQuestion') }}
@@ -120,7 +123,7 @@
-
+
{{ $tr('usingContentQuestion') }}
@@ -140,7 +143,7 @@
-
+
{{ $tr('channelQuestion') }}
@@ -153,7 +156,7 @@
-
+
{{ $tr('sampleContentQuestion') }}
@@ -178,7 +181,7 @@
-
+
{{ $tr('partialChannelQuestion') }}
@@ -191,7 +194,7 @@
-
+
{{ $tr('coachContentQuestion') }}
@@ -205,7 +208,10 @@
-
+
{{ $tr('issueQuestion') }}
@@ -223,7 +229,7 @@
-
+
{{ $tr('KolibriQuestion') }}
@@ -241,7 +247,7 @@
-
+
{{ $tr('usingKolibriQuestion') }}
@@ -288,7 +294,10 @@
-
+
{{ $tr('makerQuestion') }}
@@ -331,9 +340,12 @@
},
methods: {
openChannelAccordion() {
- const channelAccordion = document.getElementById('channel');
- if (channelAccordion.ariaExpanded === 'false') {
- channelAccordion.click();
+ const channelAccordion = document.getElementById('channel-question');
+ if (channelAccordion) {
+ const button = document.getElementById('channel-question');
+ if (button && button.getAttribute('aria-expanded') === 'false') {
+ button.click();
+ }
}
},
},
diff --git a/contentcuration/contentcuration/frontend/channelList/views/Channel/__tests__/catalogFAQ.spec.js b/contentcuration/contentcuration/frontend/channelList/views/Channel/__tests__/catalogFAQ.spec.js
index 2b0805d56e..2c0f0db7af 100644
--- a/contentcuration/contentcuration/frontend/channelList/views/Channel/__tests__/catalogFAQ.spec.js
+++ b/contentcuration/contentcuration/frontend/channelList/views/Channel/__tests__/catalogFAQ.spec.js
@@ -30,7 +30,7 @@ describe('CatalogFAQ test cases', () => {
it('expands accordion to show content when user clicks button', async () => {
renderComponent();
- const firstAccordion = document.getElementById('studio-accordion');
+ const firstAccordion = document.getElementById('selection-question');
expect(firstAccordion).toBeInTheDocument();
await fireEvent.click(firstAccordion);
diff --git a/contentcuration/contentcuration/frontend/shared/views/StudioAccordion.vue b/contentcuration/contentcuration/frontend/shared/views/StudioAccordion.vue
index 710a3b0f13..263cafbdda 100644
--- a/contentcuration/contentcuration/frontend/shared/views/StudioAccordion.vue
+++ b/contentcuration/contentcuration/frontend/shared/views/StudioAccordion.vue
@@ -12,31 +12,37 @@
:layout8="{ span: 8 }"
:layout12="{ span: 12 }"
>
-
-
+
+
+
+
-
+
@@ -70,6 +76,22 @@
showAccordionItem: false,
};
},
+ computed: {
+ appearanceOverrides() {
+ return {
+ width: '100%',
+ display: 'flex',
+ alignItems: 'center',
+ justifyContent: 'space-between',
+ padding: '10px 24px',
+ textAlign: 'left',
+ cursor: 'pointer',
+ textTransform: 'none',
+ textWrap: 'stable',
+ lineHeight: '18px',
+ };
+ },
+ },
methods: {
openAccordion() {
this.showAccordionItem = !this.showAccordionItem;
@@ -83,12 +105,9 @@
diff --git a/contentcuration/contentcuration/frontend/channelList/views/Channel/__tests__/catalogFAQ.spec.js b/contentcuration/contentcuration/frontend/channelList/views/Channel/__tests__/catalogFAQ.spec.js
index 2c0f0db7af..1c50ca0220 100644
--- a/contentcuration/contentcuration/frontend/channelList/views/Channel/__tests__/catalogFAQ.spec.js
+++ b/contentcuration/contentcuration/frontend/channelList/views/Channel/__tests__/catalogFAQ.spec.js
@@ -1,4 +1,5 @@
-import { render, fireEvent } from '@testing-library/vue';
+import { render, screen } from '@testing-library/vue';
+import userEvent from '@testing-library/user-event';
import VueRouter from 'vue-router';
import CatalogFAQ from '../CatalogFAQ.vue';
@@ -16,31 +17,54 @@ const renderComponent = (props = {}) => {
describe('CatalogFAQ test cases', () => {
it('renders the FAQ component', () => {
renderComponent();
- const subTitle = document.querySelectorAll('.sub-title');
- const mainTitle = document.querySelectorAll('.main-title');
- expect(mainTitle.length).toBe(1);
- expect(subTitle.length).toBe(3);
+ const mainTitle = screen.getByText('Welcome to the Kolibri Content Library Catalog!');
+ const subTitle = screen.getByText('About the Kolibri Content Library');
+ expect(mainTitle).toBeInTheDocument();
+ expect(subTitle).toBeInTheDocument();
});
- it('renders all FAQ items using StudioAccordion', () => {
+ it('renders all FAQ items using StudioAccordion', async () => {
renderComponent();
- const accordions = document.querySelectorAll('.studio-accordion');
- expect(accordions.length).toBe(15);
+ const accordionTitles = [
+ 'How does Learning Equality determine what goes into this library?',
+ 'How is this library created and maintained?',
+ 'Have these sources been vetted or endorsed as classroom-safe and ready?',
+ 'Does Learning Equality own these resources?',
+ 'Does Learning Equality add new materials?',
+ 'How can I add my own materials or recommend materials from other creators for this library?',
+ "I found something I'm interested in and would like to start using it. What should I do?",
+ 'What is a channel?',
+ 'How do I review the contents of the channels themselves?',
+ 'I want to use some of the resources in this channel, but not all of it. What should I do?',
+ "What are 'resources for coaches'?",
+ 'I found a bug, broken link, or some mislabeled information within a resource. What should I do?',
+ 'What is Kolibri?',
+ 'How can I use Kolibri?',
+ 'Who are the makers of Kolibri?',
+ ];
+ expect(accordionTitles.length).toBe(15);
+ accordionTitles.forEach(title => {
+ expect(screen.getByRole('button', { name: title })).toBeInTheDocument();
+ });
});
- it('expands accordion to show content when user clicks button', async () => {
+ it('toggles the channel accordion when clicking the channel link button', async () => {
+ const user = userEvent.setup();
+
renderComponent();
- const firstAccordion = document.getElementById('selection-question');
- expect(firstAccordion).toBeInTheDocument();
+ const channelLinkButton = screen.getByRole('link', { name: /What is a channel\?/i });
+ const accordion = screen.getByRole('button', { name: 'What is a channel?' });
+ const descriptionText = /A channel is Kolibri’s unit of organization for digital content./;
- await fireEvent.click(firstAccordion);
+ // Accordion content should not be visible initially
+ expect(accordion).toBeInTheDocument();
+ expect(screen.queryByText(descriptionText)).not.toBeInTheDocument();
- const accordionContent = document.querySelector('.item-content');
- expect(accordionContent).toBeInTheDocument();
+ // Click link button to expand accordion
+ await user.click(channelLinkButton);
- const expandedTrue = document.querySelectorAll('[aria-expanded="true"]');
- const expandedFalse = document.querySelectorAll('[aria-expanded="false"]');
- expect(expandedTrue.length).toBe(1);
- expect(expandedFalse.length).toBe(14);
+ // Accordion content should be visible
+ expect(accordion).toBeInTheDocument();
+ expect(screen.getByText(descriptionText)).toBeInTheDocument();
});
});
diff --git a/contentcuration/contentcuration/frontend/shared/views/StudioAccordion.vue b/contentcuration/contentcuration/frontend/shared/views/StudioAccordion.vue
index dfefc1cd69..fa81f5d5ce 100644
--- a/contentcuration/contentcuration/frontend/shared/views/StudioAccordion.vue
+++ b/contentcuration/contentcuration/frontend/shared/views/StudioAccordion.vue
@@ -1,6 +1,6 @@
-
+
-
@@ -41,14 +38,18 @@
:id="`${id}-content`"
role="region"
:aria-labelledby="id"
+ class="accordion-body"
+ :style="{
+ backgroundColor: $themeTokens.surface,
+ }"
>
-
+
@@ -67,27 +68,22 @@
},
id: {
type: String,
- default: 'studio-accordion',
+ default: 'accordion',
},
},
+ expose: ['openAccordion'],
data() {
return {
showAccordionItem: false,
};
},
computed: {
- appearanceOverrides() {
+ coreOutlineFocus() {
return {
- width: '100%',
- display: 'flex',
- alignItems: 'center',
- justifyContent: 'space-between',
- padding: '10px 24px',
- textAlign: 'left',
- cursor: 'pointer',
- textTransform: 'none',
- textWrap: 'stable',
- lineHeight: '18px',
+ ':focus': {
+ ...this.$coreOutline,
+ outlineOffset: '-2px',
+ },
};
},
},
@@ -103,20 +99,30 @@
diff --git a/contentcuration/contentcuration/frontend/shared/views/__tests__/studioAccordion.spec.js b/contentcuration/contentcuration/frontend/shared/views/__tests__/studioAccordion.spec.js
new file mode 100644
index 0000000000..d6fc63dc52
--- /dev/null
+++ b/contentcuration/contentcuration/frontend/shared/views/__tests__/studioAccordion.spec.js
@@ -0,0 +1,73 @@
+import { render } from '@testing-library/vue';
+import userEvent from '@testing-library/user-event';
+import VueRouter from 'vue-router';
+import StudioAccordion from '../StudioAccordion.vue';
+
+const router = new VueRouter({
+ routes: [{ name: 'ACCORDION', path: '/accordion' }],
+});
+
+const renderAccordion = (props = {}) => {
+ return render(StudioAccordion, {
+ props: {
+ id: 'test-accordion',
+ ...props,
+ },
+ routes: router,
+ slots: {
+ title: 'Accordion Title',
+ body: 'Accordion content goes here',
+ },
+ });
+};
+
+describe('StudioAccordion', () => {
+ it('renders with title and collapsed content by default', () => {
+ const { getByText, queryByText } = renderAccordion();
+
+ expect(getByText('Accordion Title')).toBeInTheDocument();
+ expect(queryByText('Accordion content goes here')).not.toBeInTheDocument();
+ });
+
+ it('establishes correct ARIA relationship between button and content', () => {
+ const { getByRole } = renderAccordion({ id: 'my-accordion' });
+ const button = getByRole('button', { name: /Accordion Title/i });
+
+ expect(button).toHaveAttribute('id', 'my-accordion');
+ expect(button).toHaveAttribute('aria-controls', 'my-accordion-content');
+ expect(button).toHaveAttribute('aria-expanded', 'false');
+ });
+
+ it('toggles accordion content when button is clicked', async () => {
+ const user = userEvent.setup();
+ const { getByRole, getByText, queryByText } = renderAccordion();
+
+ const button = getByRole('button', { name: /Accordion Title/i });
+
+ // Initially collapsed
+ expect(queryByText('Accordion content goes here')).not.toBeInTheDocument();
+ expect(button).toHaveAttribute('aria-expanded', 'false');
+
+ // Click to expand
+ await user.click(button);
+ expect(getByText('Accordion content goes here')).toBeInTheDocument();
+ expect(button).toHaveAttribute('aria-expanded', 'true');
+
+ // Click to collapse
+ await user.click(button);
+ expect(queryByText('Accordion content goes here')).not.toBeInTheDocument();
+ expect(button).toHaveAttribute('aria-expanded', 'false');
+ });
+
+ it('renders content region with correct ARIA attributes when expanded', async () => {
+ const user = userEvent.setup();
+ const { getByRole } = renderAccordion({ id: 'my-accordion' });
+
+ const button = getByRole('button', { name: /Accordion Title/i });
+ await user.click(button);
+
+ const region = getByRole('region');
+ expect(region).toHaveAttribute('id', 'my-accordion-content');
+ expect(region).toHaveAttribute('aria-labelledby', 'my-accordion');
+ });
+});
From 60b7dfb6a68983591b9fa06b28eea231a453a387 Mon Sep 17 00:00:00 2001
From: Michaela Robosova
Date: Mon, 9 Feb 2026 16:10:10 +0100
Subject: [PATCH 9/9] Remove visuallyhidden style definition
This is newly provided by KDS so not needed in Studio.
---
.../frontend/channelList/views/Channel/CatalogFAQ.vue | 11 -----------
1 file changed, 11 deletions(-)
diff --git a/contentcuration/contentcuration/frontend/channelList/views/Channel/CatalogFAQ.vue b/contentcuration/contentcuration/frontend/channelList/views/Channel/CatalogFAQ.vue
index bcea83be46..08001daacc 100644
--- a/contentcuration/contentcuration/frontend/channelList/views/Channel/CatalogFAQ.vue
+++ b/contentcuration/contentcuration/frontend/channelList/views/Channel/CatalogFAQ.vue
@@ -455,15 +455,4 @@
@extend %dropshadow-1dp;
}
- .visuallyhidden {
- position: absolute;
- width: 1px;
- height: 1px;
- padding: 0;
- margin: -1px;
- overflow: hidden;
- clip: rect(0 0 0 0);
- border: 0;
- }
-