From ff6e9c0b7b42a94eec874cb00dfe379fec258e89 Mon Sep 17 00:00:00 2001 From: Cheng-Hsuan Tsai Date: Tue, 18 Nov 2025 09:52:12 +0000 Subject: [PATCH] docs: add aria accordion examples (cherry picked from commit c639f84347cfe7104697debc05de1dddd8057b9a) --- .../src/disabled-focusable/app/app.css | 9 -- .../src/disabled-focusable/app/app.html | 1 - .../src/disabled-focusable/app/app.ts | 8 -- .../basic/app/app.component.css | 94 +++++++++++++++++++ .../basic/app/app.component.html | 61 ++++++++++++ .../basic/app/app.component.ts | 15 +++ .../material/app/app.component.css | 75 +++++++++++++++ .../material/app/app.component.html | 64 +++++++++++++ .../material/app/app.component.ts | 15 +++ .../retro/app/app.component.css | 83 ++++++++++++++++ .../retro/app/app.component.html | 49 ++++++++++ .../retro/app/app.component.ts | 15 +++ .../accordion/src/multi-expansion/app/app.css | 9 -- .../src/multi-expansion/app/app.html | 1 - .../accordion/src/multi-expansion/app/app.ts | 8 -- .../basic/app/app.component.css | 94 +++++++++++++++++++ .../basic/app/app.component.html | 61 ++++++++++++ .../basic/app/app.component.ts | 15 +++ .../material/app/app.component.css | 75 +++++++++++++++ .../material/app/app.component.html | 64 +++++++++++++ .../material/app/app.component.ts | 15 +++ .../retro/app/app.component.css | 83 ++++++++++++++++ .../retro/app/app.component.html | 49 ++++++++++ .../retro/app/app.component.ts | 15 +++ .../src/single-expansion/app/app.css | 9 -- .../src/single-expansion/app/app.html | 1 - .../accordion/src/single-expansion/app/app.ts | 8 -- .../basic/app/app.component.css | 94 +++++++++++++++++++ .../basic/app/app.component.html | 61 ++++++++++++ .../basic/app/app.component.ts | 15 +++ .../material/app/app.component.css | 75 +++++++++++++++ .../material/app/app.component.html | 64 +++++++++++++ .../material/app/app.component.ts | 15 +++ .../retro/app/app.component.css | 83 ++++++++++++++++ .../retro/app/app.component.html | 49 ++++++++++ .../retro/app/app.component.ts | 15 +++ adev/src/content/guide/aria/accordion.md | 89 ++++++++++++++---- 37 files changed, 1486 insertions(+), 70 deletions(-) delete mode 100644 adev/src/content/examples/aria/accordion/src/disabled-focusable/app/app.css delete mode 100644 adev/src/content/examples/aria/accordion/src/disabled-focusable/app/app.html delete mode 100644 adev/src/content/examples/aria/accordion/src/disabled-focusable/app/app.ts create mode 100644 adev/src/content/examples/aria/accordion/src/disabled-focusable/basic/app/app.component.css create mode 100644 adev/src/content/examples/aria/accordion/src/disabled-focusable/basic/app/app.component.html create mode 100644 adev/src/content/examples/aria/accordion/src/disabled-focusable/basic/app/app.component.ts create mode 100644 adev/src/content/examples/aria/accordion/src/disabled-focusable/material/app/app.component.css create mode 100644 adev/src/content/examples/aria/accordion/src/disabled-focusable/material/app/app.component.html create mode 100644 adev/src/content/examples/aria/accordion/src/disabled-focusable/material/app/app.component.ts create mode 100644 adev/src/content/examples/aria/accordion/src/disabled-focusable/retro/app/app.component.css create mode 100644 adev/src/content/examples/aria/accordion/src/disabled-focusable/retro/app/app.component.html create mode 100644 adev/src/content/examples/aria/accordion/src/disabled-focusable/retro/app/app.component.ts delete mode 100644 adev/src/content/examples/aria/accordion/src/multi-expansion/app/app.css delete mode 100644 adev/src/content/examples/aria/accordion/src/multi-expansion/app/app.html delete mode 100644 adev/src/content/examples/aria/accordion/src/multi-expansion/app/app.ts create mode 100644 adev/src/content/examples/aria/accordion/src/multi-expansion/basic/app/app.component.css create mode 100644 adev/src/content/examples/aria/accordion/src/multi-expansion/basic/app/app.component.html create mode 100644 adev/src/content/examples/aria/accordion/src/multi-expansion/basic/app/app.component.ts create mode 100644 adev/src/content/examples/aria/accordion/src/multi-expansion/material/app/app.component.css create mode 100644 adev/src/content/examples/aria/accordion/src/multi-expansion/material/app/app.component.html create mode 100644 adev/src/content/examples/aria/accordion/src/multi-expansion/material/app/app.component.ts create mode 100644 adev/src/content/examples/aria/accordion/src/multi-expansion/retro/app/app.component.css create mode 100644 adev/src/content/examples/aria/accordion/src/multi-expansion/retro/app/app.component.html create mode 100644 adev/src/content/examples/aria/accordion/src/multi-expansion/retro/app/app.component.ts delete mode 100644 adev/src/content/examples/aria/accordion/src/single-expansion/app/app.css delete mode 100644 adev/src/content/examples/aria/accordion/src/single-expansion/app/app.html delete mode 100644 adev/src/content/examples/aria/accordion/src/single-expansion/app/app.ts create mode 100644 adev/src/content/examples/aria/accordion/src/single-expansion/basic/app/app.component.css create mode 100644 adev/src/content/examples/aria/accordion/src/single-expansion/basic/app/app.component.html create mode 100644 adev/src/content/examples/aria/accordion/src/single-expansion/basic/app/app.component.ts create mode 100644 adev/src/content/examples/aria/accordion/src/single-expansion/material/app/app.component.css create mode 100644 adev/src/content/examples/aria/accordion/src/single-expansion/material/app/app.component.html create mode 100644 adev/src/content/examples/aria/accordion/src/single-expansion/material/app/app.component.ts create mode 100644 adev/src/content/examples/aria/accordion/src/single-expansion/retro/app/app.component.css create mode 100644 adev/src/content/examples/aria/accordion/src/single-expansion/retro/app/app.component.html create mode 100644 adev/src/content/examples/aria/accordion/src/single-expansion/retro/app/app.component.ts diff --git a/adev/src/content/examples/aria/accordion/src/disabled-focusable/app/app.css b/adev/src/content/examples/aria/accordion/src/disabled-focusable/app/app.css deleted file mode 100644 index bc6e9c409ad..00000000000 --- a/adev/src/content/examples/aria/accordion/src/disabled-focusable/app/app.css +++ /dev/null @@ -1,9 +0,0 @@ -h1 { - background: #1e1e1e; - color: #e0e0e0; - padding: 2rem; - margin: 0; - font-family: system-ui, -apple-system, sans-serif; - font-size: 2rem; - text-align: center; -} diff --git a/adev/src/content/examples/aria/accordion/src/disabled-focusable/app/app.html b/adev/src/content/examples/aria/accordion/src/disabled-focusable/app/app.html deleted file mode 100644 index d39d7de603b..00000000000 --- a/adev/src/content/examples/aria/accordion/src/disabled-focusable/app/app.html +++ /dev/null @@ -1 +0,0 @@ -

PLACEHOLDER

diff --git a/adev/src/content/examples/aria/accordion/src/disabled-focusable/app/app.ts b/adev/src/content/examples/aria/accordion/src/disabled-focusable/app/app.ts deleted file mode 100644 index 183576f2c24..00000000000 --- a/adev/src/content/examples/aria/accordion/src/disabled-focusable/app/app.ts +++ /dev/null @@ -1,8 +0,0 @@ -import {Component} from '@angular/core'; - -@Component({ - selector: 'app-root', - templateUrl: './app.html', - styleUrl: './app.css', -}) -export class App {} diff --git a/adev/src/content/examples/aria/accordion/src/disabled-focusable/basic/app/app.component.css b/adev/src/content/examples/aria/accordion/src/disabled-focusable/basic/app/app.component.css new file mode 100644 index 00000000000..087565cb38b --- /dev/null +++ b/adev/src/content/examples/aria/accordion/src/disabled-focusable/basic/app/app.component.css @@ -0,0 +1,94 @@ +@import url('https://fonts.googleapis.com/icon?family=Material+Symbols+Outlined'); + +:host { + display: flex; + justify-content: center; + font-family: var(--inter-font); +} + +[ngAccordionGroup] { + width: 500px; +} + +h3 { + font-size: 1rem; + margin: 0; + color: var(--secondary-contrast); + box-sizing: border-box; + position: relative; +} + +h3:focus-within::before, +h3:hover::before { + content: ''; + position: absolute; + height: 100%; + width: 2px; + background-color: var(--vivid-pink); + top: 0; + left: 0; +} + +h3:not(:first-of-type) { + border-block-start: 1px solid var(--senary-contrast); +} + +p { + margin: 0; + padding: 0 1.5rem 1.5rem 1.5rem; + color: var(--tertiary-contrast); + font-size: 0.875rem; +} + +[ngAccordionTrigger] { + display: flex; + align-items: center; + justify-content: space-between; + outline: none; + cursor: pointer; + padding: 1.5rem; +} + +[ngAccordionTrigger][aria-expanded='true'] { + background-image: var(--pink-to-purple-horizontal-gradient); + background-clip: text; + color: transparent; +} + +[ngAccordionTrigger][aria-disabled='true'] { + opacity: 0.5; + cursor: default; +} + +.expand-icon { + position: relative; + width: 1rem; + height: 1rem; + flex-shrink: 0; + margin-left: 1rem; +} + +.expand-icon::before, +.expand-icon::after { + content: ''; + position: absolute; + width: 100%; + height: 2px; + top: 50%; + background-color: var(--quaternary-contrast); + transition: .3s ease-out; +} + +.expand-icon::after { + transform: rotate(90deg); +} + +.expand-icon__expanded::before { + transform: translateY(-50%) rotate(-90deg); + opacity: 0; +} + +.expand-icon__expanded::after { + transform: translateY(-50%) rotate(0); + background-color: var(--electric-violet); +} diff --git a/adev/src/content/examples/aria/accordion/src/disabled-focusable/basic/app/app.component.html b/adev/src/content/examples/aria/accordion/src/disabled-focusable/basic/app/app.component.html new file mode 100644 index 00000000000..e8fc4e31614 --- /dev/null +++ b/adev/src/content/examples/aria/accordion/src/disabled-focusable/basic/app/app.component.html @@ -0,0 +1,61 @@ +
+

+ + Which attribute tells assistive tech whether the panel is open or closed? + + +

+
+ +

+ Use aria-expanded on the button element. Set it to "true" when the content + panel is visible and "false" when the content is hidden. This is a crucial state indicator + for screen reader users. +

+
+
+ +

+ + How do you link the button to the content it controls? + + +

+
+ +

+ Use the aria-controls attribute on the button, and set its value to match the + id of the related content panel. This establishes a programmatic relationship, allowing + assistive technologies to jump directly to the relevant content. +

+
+
+ +

+ + What role should the heading element containing the accordion button have? + + +

+
+ +

+ The element containing the button should typically have role="heading" with an + appropriate aria-level to define the structure. This ensures the accordion + section is recognized as a section header, making the page structure navigable for users. +

+
+
+
diff --git a/adev/src/content/examples/aria/accordion/src/disabled-focusable/basic/app/app.component.ts b/adev/src/content/examples/aria/accordion/src/disabled-focusable/basic/app/app.component.ts new file mode 100644 index 00000000000..27d79c434b5 --- /dev/null +++ b/adev/src/content/examples/aria/accordion/src/disabled-focusable/basic/app/app.component.ts @@ -0,0 +1,15 @@ +import {Component} from '@angular/core'; +import { + AccordionGroup, + AccordionTrigger, + AccordionPanel, + AccordionContent, +} from '@angular/aria/accordion'; + +@Component({ + selector: 'app-root', + templateUrl: 'app.component.html', + styleUrl: 'app.component.css', + imports: [AccordionGroup, AccordionTrigger, AccordionPanel, AccordionContent], +}) +export class App {} diff --git a/adev/src/content/examples/aria/accordion/src/disabled-focusable/material/app/app.component.css b/adev/src/content/examples/aria/accordion/src/disabled-focusable/material/app/app.component.css new file mode 100644 index 00000000000..bd691050aa8 --- /dev/null +++ b/adev/src/content/examples/aria/accordion/src/disabled-focusable/material/app/app.component.css @@ -0,0 +1,75 @@ +@import url('https://fonts.googleapis.com/icon?family=Material+Symbols+Outlined'); + +:host { + display: flex; + justify-content: center; + font-family: var(--inter-font); +} + +[ngAccordionGroup] { + width: 500px; +} + +h3 { + font-size: 1rem; + margin: 0; + color: var(--secondary-contrast); + box-sizing: border-box; + border-block-start: 1px solid var(--quinary-contrast); + border-inline: 1px solid var(--quinary-contrast); +} + +h3:focus-within, +h3:hover { + background-color: var(--septenary-contrast); +} + +h3:first-of-type { + border-radius: 1rem 1rem 0 0; +} + +h3:last-of-type { + border-block-end: 1px solid var(--quinary-contrast); + border-radius: 0 0 1rem 1rem; +} + +h3:last-of-type:has([aria-expanded='true']) { + border-block-end: 0; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; +} + +p { + margin: 0; + padding: 0 1.5rem 1.5rem 1.5rem; + color: var(--tertiary-contrast); + font-size: 0.875rem; + border-inline: 1px solid var(--quinary-contrast); + border-radius: 0 0 1rem 1rem; + border-block-end: 1px solid var(--quinary-contrast); + margin-block-end: 1rem; +} + +[ngAccordionTrigger] { + display: flex; + align-items: center; + justify-content: space-between; + outline: none; + cursor: pointer; + padding: 1.5rem; +} + +[ngAccordionTrigger][aria-disabled='true'] { + opacity: 0.5; + cursor: default; +} + +.expand-icon { + font-size: 1.5rem; + color: var(--quaternary-contrast); + transition: transform .3s ease-out; +} + +.expand-icon__expanded { + transform: rotate(180deg); +} diff --git a/adev/src/content/examples/aria/accordion/src/disabled-focusable/material/app/app.component.html b/adev/src/content/examples/aria/accordion/src/disabled-focusable/material/app/app.component.html new file mode 100644 index 00000000000..5e1e81557b8 --- /dev/null +++ b/adev/src/content/examples/aria/accordion/src/disabled-focusable/material/app/app.component.html @@ -0,0 +1,64 @@ +
+

+ + Which attribute tells assistive tech whether the panel is open or closed? + + +

+
+ +

+ Use aria-expanded on the button element. Set it to "true" when the content + panel is visible and "false" when the content is hidden. This is a crucial state indicator + for screen reader users. +

+
+
+ +

+ + How do you link the button to the content it controls? + + +

+
+ +

+ Use the aria-controls attribute on the button, and set its value to match the + id of the related content panel. This establishes a programmatic relationship, allowing + assistive technologies to jump directly to the relevant content. +

+
+
+ +

+ + What role should the heading element containing the accordion button have? + + +

+
+ +

+ The element containing the button should typically have role="heading" with an + appropriate aria-level to define the structure. This ensures the accordion + section is recognized as a section header, making the page structure navigable for users. +

+
+
+
diff --git a/adev/src/content/examples/aria/accordion/src/disabled-focusable/material/app/app.component.ts b/adev/src/content/examples/aria/accordion/src/disabled-focusable/material/app/app.component.ts new file mode 100644 index 00000000000..27d79c434b5 --- /dev/null +++ b/adev/src/content/examples/aria/accordion/src/disabled-focusable/material/app/app.component.ts @@ -0,0 +1,15 @@ +import {Component} from '@angular/core'; +import { + AccordionGroup, + AccordionTrigger, + AccordionPanel, + AccordionContent, +} from '@angular/aria/accordion'; + +@Component({ + selector: 'app-root', + templateUrl: 'app.component.html', + styleUrl: 'app.component.css', + imports: [AccordionGroup, AccordionTrigger, AccordionPanel, AccordionContent], +}) +export class App {} diff --git a/adev/src/content/examples/aria/accordion/src/disabled-focusable/retro/app/app.component.css b/adev/src/content/examples/aria/accordion/src/disabled-focusable/retro/app/app.component.css new file mode 100644 index 00000000000..ab6ba7e6937 --- /dev/null +++ b/adev/src/content/examples/aria/accordion/src/disabled-focusable/retro/app/app.component.css @@ -0,0 +1,83 @@ +@import url('https://fonts.googleapis.com/icon?family=Material+Symbols+Outlined'); +@import url('https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap'); + +:host { + display: flex; + justify-content: center; + font-family: 'Press Start 2P'; + + --retro-button-color: color-mix(in srgb, var(--symbolic-yellow) 90%, var(--gray-1000)); + --retro-button-text-color: color-mix(in srgb, var(--symbolic-yellow) 10%, white); + --retro-shadow-light: color-mix(in srgb, var(--retro-button-color) 90%, #fff); + --retro-shadow-dark: color-mix(in srgb, var(--retro-button-color) 90%, #000); + --retro-elevated-shadow: + inset 4px 4px 0px 0px var(--retro-shadow-light), + inset -4px -4px 0px 0px var(--retro-shadow-dark), 4px 0px 0px 0px var(--gray-700), + 0px 4px 0px 0px var(--gray-700), -4px 0px 0px 0px var(--gray-700), + 0px -4px 0px 0px var(--gray-700); + --retro-flat-shadow: + 4px 0px 0px 0px var(--gray-700), 0px 4px 0px 0px var(--gray-700), + -4px 0px 0px 0px var(--gray-700), 0px -4px 0px 0px var(--gray-700); + --retro-clickable-shadow: + inset 4px 4px 0px 0px var(--retro-shadow-light), + inset -4px -4px 0px 0px var(--retro-shadow-dark), 4px 0px 0px 0px var(--gray-700), + 0px 4px 0px 0px var(--gray-700), -4px 0px 0px 0px var(--gray-700), + 0px -4px 0px 0px var(--gray-700), 8px 8px 0px 0px var(--gray-700); + --retro-pressed-shadow: + inset 4px 4px 0px 0px var(--retro-shadow-dark), + inset -4px -4px 0px 0px var(--retro-shadow-light), 4px 0px 0px 0px var(--gray-700), + 0px 4px 0px 0px var(--gray-700), -4px 0px 0px 0px var(--gray-700), + 0px -4px 0px 0px var(--gray-700), 0px 0px 0px 0px var(--gray-700); +} + +[ngAccordionGroup] { + width: 500px; +} + +h3 { + font-size: 1rem; + margin: 0; + color: var(--retro-button-text-color); + background-color: var(--retro-button-color); + box-shadow: var(--retro-clickable-shadow); + transition: + transform 0.1s, + box-shadow 0.1s; +} + +h3:focus-within, +h3:hover { + box-shadow: var(--retro-pressed-shadow); + transform: translate(1px, 1px); + outline-offset: 6px; + outline: 4px dashed color-mix(in srgb, var(--hot-pink) 60%, transparent); +} + +h3:has([aria-disabled='true']) { + opacity: 0.5; + cursor: default; +} + +.treasure-box { + margin: 0; + padding: 1rem; + display: flex; + justify-content: center; + align-items: center; + height: 5rem; + background-color: var(--septenary-contrast); + box-shadow: var(--retro-flat-shadow); +} + +[ngAccordionTrigger] { + display: flex; + align-items: center; + justify-content: space-between; + outline: none; + cursor: pointer; + padding: 1.5rem; +} + +[ngAccordionPanel] { + padding: 1rem; +} diff --git a/adev/src/content/examples/aria/accordion/src/disabled-focusable/retro/app/app.component.html b/adev/src/content/examples/aria/accordion/src/disabled-focusable/retro/app/app.component.html new file mode 100644 index 00000000000..a7094e3148e --- /dev/null +++ b/adev/src/content/examples/aria/accordion/src/disabled-focusable/retro/app/app.component.html @@ -0,0 +1,49 @@ +
+

+ + Unlock Treasure Box + + +

+
+ +
👻
+
+
+ +

+ + Unlock Treasure Box + + +

+
+ +
💎💎💎
+
+
+ +

+ + Unlock Treasure Box + + +

+
+ +
🐸 ribbit...ribbit...
+
+
+
diff --git a/adev/src/content/examples/aria/accordion/src/disabled-focusable/retro/app/app.component.ts b/adev/src/content/examples/aria/accordion/src/disabled-focusable/retro/app/app.component.ts new file mode 100644 index 00000000000..27d79c434b5 --- /dev/null +++ b/adev/src/content/examples/aria/accordion/src/disabled-focusable/retro/app/app.component.ts @@ -0,0 +1,15 @@ +import {Component} from '@angular/core'; +import { + AccordionGroup, + AccordionTrigger, + AccordionPanel, + AccordionContent, +} from '@angular/aria/accordion'; + +@Component({ + selector: 'app-root', + templateUrl: 'app.component.html', + styleUrl: 'app.component.css', + imports: [AccordionGroup, AccordionTrigger, AccordionPanel, AccordionContent], +}) +export class App {} diff --git a/adev/src/content/examples/aria/accordion/src/multi-expansion/app/app.css b/adev/src/content/examples/aria/accordion/src/multi-expansion/app/app.css deleted file mode 100644 index bc6e9c409ad..00000000000 --- a/adev/src/content/examples/aria/accordion/src/multi-expansion/app/app.css +++ /dev/null @@ -1,9 +0,0 @@ -h1 { - background: #1e1e1e; - color: #e0e0e0; - padding: 2rem; - margin: 0; - font-family: system-ui, -apple-system, sans-serif; - font-size: 2rem; - text-align: center; -} diff --git a/adev/src/content/examples/aria/accordion/src/multi-expansion/app/app.html b/adev/src/content/examples/aria/accordion/src/multi-expansion/app/app.html deleted file mode 100644 index d39d7de603b..00000000000 --- a/adev/src/content/examples/aria/accordion/src/multi-expansion/app/app.html +++ /dev/null @@ -1 +0,0 @@ -

PLACEHOLDER

diff --git a/adev/src/content/examples/aria/accordion/src/multi-expansion/app/app.ts b/adev/src/content/examples/aria/accordion/src/multi-expansion/app/app.ts deleted file mode 100644 index 183576f2c24..00000000000 --- a/adev/src/content/examples/aria/accordion/src/multi-expansion/app/app.ts +++ /dev/null @@ -1,8 +0,0 @@ -import {Component} from '@angular/core'; - -@Component({ - selector: 'app-root', - templateUrl: './app.html', - styleUrl: './app.css', -}) -export class App {} diff --git a/adev/src/content/examples/aria/accordion/src/multi-expansion/basic/app/app.component.css b/adev/src/content/examples/aria/accordion/src/multi-expansion/basic/app/app.component.css new file mode 100644 index 00000000000..087565cb38b --- /dev/null +++ b/adev/src/content/examples/aria/accordion/src/multi-expansion/basic/app/app.component.css @@ -0,0 +1,94 @@ +@import url('https://fonts.googleapis.com/icon?family=Material+Symbols+Outlined'); + +:host { + display: flex; + justify-content: center; + font-family: var(--inter-font); +} + +[ngAccordionGroup] { + width: 500px; +} + +h3 { + font-size: 1rem; + margin: 0; + color: var(--secondary-contrast); + box-sizing: border-box; + position: relative; +} + +h3:focus-within::before, +h3:hover::before { + content: ''; + position: absolute; + height: 100%; + width: 2px; + background-color: var(--vivid-pink); + top: 0; + left: 0; +} + +h3:not(:first-of-type) { + border-block-start: 1px solid var(--senary-contrast); +} + +p { + margin: 0; + padding: 0 1.5rem 1.5rem 1.5rem; + color: var(--tertiary-contrast); + font-size: 0.875rem; +} + +[ngAccordionTrigger] { + display: flex; + align-items: center; + justify-content: space-between; + outline: none; + cursor: pointer; + padding: 1.5rem; +} + +[ngAccordionTrigger][aria-expanded='true'] { + background-image: var(--pink-to-purple-horizontal-gradient); + background-clip: text; + color: transparent; +} + +[ngAccordionTrigger][aria-disabled='true'] { + opacity: 0.5; + cursor: default; +} + +.expand-icon { + position: relative; + width: 1rem; + height: 1rem; + flex-shrink: 0; + margin-left: 1rem; +} + +.expand-icon::before, +.expand-icon::after { + content: ''; + position: absolute; + width: 100%; + height: 2px; + top: 50%; + background-color: var(--quaternary-contrast); + transition: .3s ease-out; +} + +.expand-icon::after { + transform: rotate(90deg); +} + +.expand-icon__expanded::before { + transform: translateY(-50%) rotate(-90deg); + opacity: 0; +} + +.expand-icon__expanded::after { + transform: translateY(-50%) rotate(0); + background-color: var(--electric-violet); +} diff --git a/adev/src/content/examples/aria/accordion/src/multi-expansion/basic/app/app.component.html b/adev/src/content/examples/aria/accordion/src/multi-expansion/basic/app/app.component.html new file mode 100644 index 00000000000..c9cfc0d1e62 --- /dev/null +++ b/adev/src/content/examples/aria/accordion/src/multi-expansion/basic/app/app.component.html @@ -0,0 +1,61 @@ +
+

+ + Which attribute tells assistive tech whether the panel is open or closed? + + +

+
+ +

+ Use aria-expanded on the button element. Set it to "true" when the content + panel is visible and "false" when the content is hidden. This is a crucial state indicator + for screen reader users. +

+
+
+ +

+ + How do you link the button to the content it controls? + + +

+
+ +

+ Use the aria-controls attribute on the button, and set its value to match the + id of the related content panel. This establishes a programmatic relationship, allowing + assistive technologies to jump directly to the relevant content. +

+
+
+ +

+ + What role should the heading element containing the accordion button have? + + +

+
+ +

+ The element containing the button should typically have role="heading" with an + appropriate aria-level to define the structure. This ensures the accordion + section is recognized as a section header, making the page structure navigable for users. +

+
+
+
diff --git a/adev/src/content/examples/aria/accordion/src/multi-expansion/basic/app/app.component.ts b/adev/src/content/examples/aria/accordion/src/multi-expansion/basic/app/app.component.ts new file mode 100644 index 00000000000..27d79c434b5 --- /dev/null +++ b/adev/src/content/examples/aria/accordion/src/multi-expansion/basic/app/app.component.ts @@ -0,0 +1,15 @@ +import {Component} from '@angular/core'; +import { + AccordionGroup, + AccordionTrigger, + AccordionPanel, + AccordionContent, +} from '@angular/aria/accordion'; + +@Component({ + selector: 'app-root', + templateUrl: 'app.component.html', + styleUrl: 'app.component.css', + imports: [AccordionGroup, AccordionTrigger, AccordionPanel, AccordionContent], +}) +export class App {} diff --git a/adev/src/content/examples/aria/accordion/src/multi-expansion/material/app/app.component.css b/adev/src/content/examples/aria/accordion/src/multi-expansion/material/app/app.component.css new file mode 100644 index 00000000000..bd691050aa8 --- /dev/null +++ b/adev/src/content/examples/aria/accordion/src/multi-expansion/material/app/app.component.css @@ -0,0 +1,75 @@ +@import url('https://fonts.googleapis.com/icon?family=Material+Symbols+Outlined'); + +:host { + display: flex; + justify-content: center; + font-family: var(--inter-font); +} + +[ngAccordionGroup] { + width: 500px; +} + +h3 { + font-size: 1rem; + margin: 0; + color: var(--secondary-contrast); + box-sizing: border-box; + border-block-start: 1px solid var(--quinary-contrast); + border-inline: 1px solid var(--quinary-contrast); +} + +h3:focus-within, +h3:hover { + background-color: var(--septenary-contrast); +} + +h3:first-of-type { + border-radius: 1rem 1rem 0 0; +} + +h3:last-of-type { + border-block-end: 1px solid var(--quinary-contrast); + border-radius: 0 0 1rem 1rem; +} + +h3:last-of-type:has([aria-expanded='true']) { + border-block-end: 0; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; +} + +p { + margin: 0; + padding: 0 1.5rem 1.5rem 1.5rem; + color: var(--tertiary-contrast); + font-size: 0.875rem; + border-inline: 1px solid var(--quinary-contrast); + border-radius: 0 0 1rem 1rem; + border-block-end: 1px solid var(--quinary-contrast); + margin-block-end: 1rem; +} + +[ngAccordionTrigger] { + display: flex; + align-items: center; + justify-content: space-between; + outline: none; + cursor: pointer; + padding: 1.5rem; +} + +[ngAccordionTrigger][aria-disabled='true'] { + opacity: 0.5; + cursor: default; +} + +.expand-icon { + font-size: 1.5rem; + color: var(--quaternary-contrast); + transition: transform .3s ease-out; +} + +.expand-icon__expanded { + transform: rotate(180deg); +} diff --git a/adev/src/content/examples/aria/accordion/src/multi-expansion/material/app/app.component.html b/adev/src/content/examples/aria/accordion/src/multi-expansion/material/app/app.component.html new file mode 100644 index 00000000000..fbd7ef1833d --- /dev/null +++ b/adev/src/content/examples/aria/accordion/src/multi-expansion/material/app/app.component.html @@ -0,0 +1,64 @@ +
+

+ + Which attribute tells assistive tech whether the panel is open or closed? + + +

+
+ +

+ Use aria-expanded on the button element. Set it to "true" when the content + panel is visible and "false" when the content is hidden. This is a crucial state indicator + for screen reader users. +

+
+
+ +

+ + How do you link the button to the content it controls? + + +

+
+ +

+ Use the aria-controls attribute on the button, and set its value to match the + id of the related content panel. This establishes a programmatic relationship, allowing + assistive technologies to jump directly to the relevant content. +

+
+
+ +

+ + What role should the heading element containing the accordion button have? + + +

+
+ +

+ The element containing the button should typically have role="heading" with an + appropriate aria-level to define the structure. This ensures the accordion + section is recognized as a section header, making the page structure navigable for users. +

+
+
+
diff --git a/adev/src/content/examples/aria/accordion/src/multi-expansion/material/app/app.component.ts b/adev/src/content/examples/aria/accordion/src/multi-expansion/material/app/app.component.ts new file mode 100644 index 00000000000..27d79c434b5 --- /dev/null +++ b/adev/src/content/examples/aria/accordion/src/multi-expansion/material/app/app.component.ts @@ -0,0 +1,15 @@ +import {Component} from '@angular/core'; +import { + AccordionGroup, + AccordionTrigger, + AccordionPanel, + AccordionContent, +} from '@angular/aria/accordion'; + +@Component({ + selector: 'app-root', + templateUrl: 'app.component.html', + styleUrl: 'app.component.css', + imports: [AccordionGroup, AccordionTrigger, AccordionPanel, AccordionContent], +}) +export class App {} diff --git a/adev/src/content/examples/aria/accordion/src/multi-expansion/retro/app/app.component.css b/adev/src/content/examples/aria/accordion/src/multi-expansion/retro/app/app.component.css new file mode 100644 index 00000000000..ab6ba7e6937 --- /dev/null +++ b/adev/src/content/examples/aria/accordion/src/multi-expansion/retro/app/app.component.css @@ -0,0 +1,83 @@ +@import url('https://fonts.googleapis.com/icon?family=Material+Symbols+Outlined'); +@import url('https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap'); + +:host { + display: flex; + justify-content: center; + font-family: 'Press Start 2P'; + + --retro-button-color: color-mix(in srgb, var(--symbolic-yellow) 90%, var(--gray-1000)); + --retro-button-text-color: color-mix(in srgb, var(--symbolic-yellow) 10%, white); + --retro-shadow-light: color-mix(in srgb, var(--retro-button-color) 90%, #fff); + --retro-shadow-dark: color-mix(in srgb, var(--retro-button-color) 90%, #000); + --retro-elevated-shadow: + inset 4px 4px 0px 0px var(--retro-shadow-light), + inset -4px -4px 0px 0px var(--retro-shadow-dark), 4px 0px 0px 0px var(--gray-700), + 0px 4px 0px 0px var(--gray-700), -4px 0px 0px 0px var(--gray-700), + 0px -4px 0px 0px var(--gray-700); + --retro-flat-shadow: + 4px 0px 0px 0px var(--gray-700), 0px 4px 0px 0px var(--gray-700), + -4px 0px 0px 0px var(--gray-700), 0px -4px 0px 0px var(--gray-700); + --retro-clickable-shadow: + inset 4px 4px 0px 0px var(--retro-shadow-light), + inset -4px -4px 0px 0px var(--retro-shadow-dark), 4px 0px 0px 0px var(--gray-700), + 0px 4px 0px 0px var(--gray-700), -4px 0px 0px 0px var(--gray-700), + 0px -4px 0px 0px var(--gray-700), 8px 8px 0px 0px var(--gray-700); + --retro-pressed-shadow: + inset 4px 4px 0px 0px var(--retro-shadow-dark), + inset -4px -4px 0px 0px var(--retro-shadow-light), 4px 0px 0px 0px var(--gray-700), + 0px 4px 0px 0px var(--gray-700), -4px 0px 0px 0px var(--gray-700), + 0px -4px 0px 0px var(--gray-700), 0px 0px 0px 0px var(--gray-700); +} + +[ngAccordionGroup] { + width: 500px; +} + +h3 { + font-size: 1rem; + margin: 0; + color: var(--retro-button-text-color); + background-color: var(--retro-button-color); + box-shadow: var(--retro-clickable-shadow); + transition: + transform 0.1s, + box-shadow 0.1s; +} + +h3:focus-within, +h3:hover { + box-shadow: var(--retro-pressed-shadow); + transform: translate(1px, 1px); + outline-offset: 6px; + outline: 4px dashed color-mix(in srgb, var(--hot-pink) 60%, transparent); +} + +h3:has([aria-disabled='true']) { + opacity: 0.5; + cursor: default; +} + +.treasure-box { + margin: 0; + padding: 1rem; + display: flex; + justify-content: center; + align-items: center; + height: 5rem; + background-color: var(--septenary-contrast); + box-shadow: var(--retro-flat-shadow); +} + +[ngAccordionTrigger] { + display: flex; + align-items: center; + justify-content: space-between; + outline: none; + cursor: pointer; + padding: 1.5rem; +} + +[ngAccordionPanel] { + padding: 1rem; +} diff --git a/adev/src/content/examples/aria/accordion/src/multi-expansion/retro/app/app.component.html b/adev/src/content/examples/aria/accordion/src/multi-expansion/retro/app/app.component.html new file mode 100644 index 00000000000..cef61fc04ae --- /dev/null +++ b/adev/src/content/examples/aria/accordion/src/multi-expansion/retro/app/app.component.html @@ -0,0 +1,49 @@ +
+

+ + Unlock Treasure Box + + +

+
+ +
👻
+
+
+ +

+ + Unlock Treasure Box + + +

+
+ +
💎💎💎
+
+
+ +

+ + Unlock Treasure Box + + +

+
+ +
🐸 ribbit...ribbit...
+
+
+
diff --git a/adev/src/content/examples/aria/accordion/src/multi-expansion/retro/app/app.component.ts b/adev/src/content/examples/aria/accordion/src/multi-expansion/retro/app/app.component.ts new file mode 100644 index 00000000000..27d79c434b5 --- /dev/null +++ b/adev/src/content/examples/aria/accordion/src/multi-expansion/retro/app/app.component.ts @@ -0,0 +1,15 @@ +import {Component} from '@angular/core'; +import { + AccordionGroup, + AccordionTrigger, + AccordionPanel, + AccordionContent, +} from '@angular/aria/accordion'; + +@Component({ + selector: 'app-root', + templateUrl: 'app.component.html', + styleUrl: 'app.component.css', + imports: [AccordionGroup, AccordionTrigger, AccordionPanel, AccordionContent], +}) +export class App {} diff --git a/adev/src/content/examples/aria/accordion/src/single-expansion/app/app.css b/adev/src/content/examples/aria/accordion/src/single-expansion/app/app.css deleted file mode 100644 index bc6e9c409ad..00000000000 --- a/adev/src/content/examples/aria/accordion/src/single-expansion/app/app.css +++ /dev/null @@ -1,9 +0,0 @@ -h1 { - background: #1e1e1e; - color: #e0e0e0; - padding: 2rem; - margin: 0; - font-family: system-ui, -apple-system, sans-serif; - font-size: 2rem; - text-align: center; -} diff --git a/adev/src/content/examples/aria/accordion/src/single-expansion/app/app.html b/adev/src/content/examples/aria/accordion/src/single-expansion/app/app.html deleted file mode 100644 index d39d7de603b..00000000000 --- a/adev/src/content/examples/aria/accordion/src/single-expansion/app/app.html +++ /dev/null @@ -1 +0,0 @@ -

PLACEHOLDER

diff --git a/adev/src/content/examples/aria/accordion/src/single-expansion/app/app.ts b/adev/src/content/examples/aria/accordion/src/single-expansion/app/app.ts deleted file mode 100644 index 183576f2c24..00000000000 --- a/adev/src/content/examples/aria/accordion/src/single-expansion/app/app.ts +++ /dev/null @@ -1,8 +0,0 @@ -import {Component} from '@angular/core'; - -@Component({ - selector: 'app-root', - templateUrl: './app.html', - styleUrl: './app.css', -}) -export class App {} diff --git a/adev/src/content/examples/aria/accordion/src/single-expansion/basic/app/app.component.css b/adev/src/content/examples/aria/accordion/src/single-expansion/basic/app/app.component.css new file mode 100644 index 00000000000..087565cb38b --- /dev/null +++ b/adev/src/content/examples/aria/accordion/src/single-expansion/basic/app/app.component.css @@ -0,0 +1,94 @@ +@import url('https://fonts.googleapis.com/icon?family=Material+Symbols+Outlined'); + +:host { + display: flex; + justify-content: center; + font-family: var(--inter-font); +} + +[ngAccordionGroup] { + width: 500px; +} + +h3 { + font-size: 1rem; + margin: 0; + color: var(--secondary-contrast); + box-sizing: border-box; + position: relative; +} + +h3:focus-within::before, +h3:hover::before { + content: ''; + position: absolute; + height: 100%; + width: 2px; + background-color: var(--vivid-pink); + top: 0; + left: 0; +} + +h3:not(:first-of-type) { + border-block-start: 1px solid var(--senary-contrast); +} + +p { + margin: 0; + padding: 0 1.5rem 1.5rem 1.5rem; + color: var(--tertiary-contrast); + font-size: 0.875rem; +} + +[ngAccordionTrigger] { + display: flex; + align-items: center; + justify-content: space-between; + outline: none; + cursor: pointer; + padding: 1.5rem; +} + +[ngAccordionTrigger][aria-expanded='true'] { + background-image: var(--pink-to-purple-horizontal-gradient); + background-clip: text; + color: transparent; +} + +[ngAccordionTrigger][aria-disabled='true'] { + opacity: 0.5; + cursor: default; +} + +.expand-icon { + position: relative; + width: 1rem; + height: 1rem; + flex-shrink: 0; + margin-left: 1rem; +} + +.expand-icon::before, +.expand-icon::after { + content: ''; + position: absolute; + width: 100%; + height: 2px; + top: 50%; + background-color: var(--quaternary-contrast); + transition: .3s ease-out; +} + +.expand-icon::after { + transform: rotate(90deg); +} + +.expand-icon__expanded::before { + transform: translateY(-50%) rotate(-90deg); + opacity: 0; +} + +.expand-icon__expanded::after { + transform: translateY(-50%) rotate(0); + background-color: var(--electric-violet); +} diff --git a/adev/src/content/examples/aria/accordion/src/single-expansion/basic/app/app.component.html b/adev/src/content/examples/aria/accordion/src/single-expansion/basic/app/app.component.html new file mode 100644 index 00000000000..011e67e1b56 --- /dev/null +++ b/adev/src/content/examples/aria/accordion/src/single-expansion/basic/app/app.component.html @@ -0,0 +1,61 @@ +
+

+ + Which attribute tells assistive tech whether the panel is open or closed? + + +

+
+ +

+ Use aria-expanded on the button element. Set it to "true" when the content + panel is visible and "false" when the content is hidden. This is a crucial state indicator + for screen reader users. +

+
+
+ +

+ + How do you link the button to the content it controls? + + +

+
+ +

+ Use the aria-controls attribute on the button, and set its value to match the + id of the related content panel. This establishes a programmatic relationship, allowing + assistive technologies to jump directly to the relevant content. +

+
+
+ +

+ + What role should the heading element containing the accordion button have? + + +

+
+ +

+ The element containing the button should typically have role="heading" with an + appropriate aria-level to define the structure. This ensures the accordion + section is recognized as a section header, making the page structure navigable for users. +

+
+
+
diff --git a/adev/src/content/examples/aria/accordion/src/single-expansion/basic/app/app.component.ts b/adev/src/content/examples/aria/accordion/src/single-expansion/basic/app/app.component.ts new file mode 100644 index 00000000000..27d79c434b5 --- /dev/null +++ b/adev/src/content/examples/aria/accordion/src/single-expansion/basic/app/app.component.ts @@ -0,0 +1,15 @@ +import {Component} from '@angular/core'; +import { + AccordionGroup, + AccordionTrigger, + AccordionPanel, + AccordionContent, +} from '@angular/aria/accordion'; + +@Component({ + selector: 'app-root', + templateUrl: 'app.component.html', + styleUrl: 'app.component.css', + imports: [AccordionGroup, AccordionTrigger, AccordionPanel, AccordionContent], +}) +export class App {} diff --git a/adev/src/content/examples/aria/accordion/src/single-expansion/material/app/app.component.css b/adev/src/content/examples/aria/accordion/src/single-expansion/material/app/app.component.css new file mode 100644 index 00000000000..bd691050aa8 --- /dev/null +++ b/adev/src/content/examples/aria/accordion/src/single-expansion/material/app/app.component.css @@ -0,0 +1,75 @@ +@import url('https://fonts.googleapis.com/icon?family=Material+Symbols+Outlined'); + +:host { + display: flex; + justify-content: center; + font-family: var(--inter-font); +} + +[ngAccordionGroup] { + width: 500px; +} + +h3 { + font-size: 1rem; + margin: 0; + color: var(--secondary-contrast); + box-sizing: border-box; + border-block-start: 1px solid var(--quinary-contrast); + border-inline: 1px solid var(--quinary-contrast); +} + +h3:focus-within, +h3:hover { + background-color: var(--septenary-contrast); +} + +h3:first-of-type { + border-radius: 1rem 1rem 0 0; +} + +h3:last-of-type { + border-block-end: 1px solid var(--quinary-contrast); + border-radius: 0 0 1rem 1rem; +} + +h3:last-of-type:has([aria-expanded='true']) { + border-block-end: 0; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; +} + +p { + margin: 0; + padding: 0 1.5rem 1.5rem 1.5rem; + color: var(--tertiary-contrast); + font-size: 0.875rem; + border-inline: 1px solid var(--quinary-contrast); + border-radius: 0 0 1rem 1rem; + border-block-end: 1px solid var(--quinary-contrast); + margin-block-end: 1rem; +} + +[ngAccordionTrigger] { + display: flex; + align-items: center; + justify-content: space-between; + outline: none; + cursor: pointer; + padding: 1.5rem; +} + +[ngAccordionTrigger][aria-disabled='true'] { + opacity: 0.5; + cursor: default; +} + +.expand-icon { + font-size: 1.5rem; + color: var(--quaternary-contrast); + transition: transform .3s ease-out; +} + +.expand-icon__expanded { + transform: rotate(180deg); +} diff --git a/adev/src/content/examples/aria/accordion/src/single-expansion/material/app/app.component.html b/adev/src/content/examples/aria/accordion/src/single-expansion/material/app/app.component.html new file mode 100644 index 00000000000..2e7f70acfeb --- /dev/null +++ b/adev/src/content/examples/aria/accordion/src/single-expansion/material/app/app.component.html @@ -0,0 +1,64 @@ +
+

+ + Which attribute tells assistive tech whether the panel is open or closed? + + +

+
+ +

+ Use aria-expanded on the button element. Set it to "true" when the content + panel is visible and "false" when the content is hidden. This is a crucial state indicator + for screen reader users. +

+
+
+ +

+ + How do you link the button to the content it controls? + + +

+
+ +

+ Use the aria-controls attribute on the button, and set its value to match the + id of the related content panel. This establishes a programmatic relationship, allowing + assistive technologies to jump directly to the relevant content. +

+
+
+ +

+ + What role should the heading element containing the accordion button have? + + +

+
+ +

+ The element containing the button should typically have role="heading" with an + appropriate aria-level to define the structure. This ensures the accordion + section is recognized as a section header, making the page structure navigable for users. +

+
+
+
diff --git a/adev/src/content/examples/aria/accordion/src/single-expansion/material/app/app.component.ts b/adev/src/content/examples/aria/accordion/src/single-expansion/material/app/app.component.ts new file mode 100644 index 00000000000..27d79c434b5 --- /dev/null +++ b/adev/src/content/examples/aria/accordion/src/single-expansion/material/app/app.component.ts @@ -0,0 +1,15 @@ +import {Component} from '@angular/core'; +import { + AccordionGroup, + AccordionTrigger, + AccordionPanel, + AccordionContent, +} from '@angular/aria/accordion'; + +@Component({ + selector: 'app-root', + templateUrl: 'app.component.html', + styleUrl: 'app.component.css', + imports: [AccordionGroup, AccordionTrigger, AccordionPanel, AccordionContent], +}) +export class App {} diff --git a/adev/src/content/examples/aria/accordion/src/single-expansion/retro/app/app.component.css b/adev/src/content/examples/aria/accordion/src/single-expansion/retro/app/app.component.css new file mode 100644 index 00000000000..ab6ba7e6937 --- /dev/null +++ b/adev/src/content/examples/aria/accordion/src/single-expansion/retro/app/app.component.css @@ -0,0 +1,83 @@ +@import url('https://fonts.googleapis.com/icon?family=Material+Symbols+Outlined'); +@import url('https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap'); + +:host { + display: flex; + justify-content: center; + font-family: 'Press Start 2P'; + + --retro-button-color: color-mix(in srgb, var(--symbolic-yellow) 90%, var(--gray-1000)); + --retro-button-text-color: color-mix(in srgb, var(--symbolic-yellow) 10%, white); + --retro-shadow-light: color-mix(in srgb, var(--retro-button-color) 90%, #fff); + --retro-shadow-dark: color-mix(in srgb, var(--retro-button-color) 90%, #000); + --retro-elevated-shadow: + inset 4px 4px 0px 0px var(--retro-shadow-light), + inset -4px -4px 0px 0px var(--retro-shadow-dark), 4px 0px 0px 0px var(--gray-700), + 0px 4px 0px 0px var(--gray-700), -4px 0px 0px 0px var(--gray-700), + 0px -4px 0px 0px var(--gray-700); + --retro-flat-shadow: + 4px 0px 0px 0px var(--gray-700), 0px 4px 0px 0px var(--gray-700), + -4px 0px 0px 0px var(--gray-700), 0px -4px 0px 0px var(--gray-700); + --retro-clickable-shadow: + inset 4px 4px 0px 0px var(--retro-shadow-light), + inset -4px -4px 0px 0px var(--retro-shadow-dark), 4px 0px 0px 0px var(--gray-700), + 0px 4px 0px 0px var(--gray-700), -4px 0px 0px 0px var(--gray-700), + 0px -4px 0px 0px var(--gray-700), 8px 8px 0px 0px var(--gray-700); + --retro-pressed-shadow: + inset 4px 4px 0px 0px var(--retro-shadow-dark), + inset -4px -4px 0px 0px var(--retro-shadow-light), 4px 0px 0px 0px var(--gray-700), + 0px 4px 0px 0px var(--gray-700), -4px 0px 0px 0px var(--gray-700), + 0px -4px 0px 0px var(--gray-700), 0px 0px 0px 0px var(--gray-700); +} + +[ngAccordionGroup] { + width: 500px; +} + +h3 { + font-size: 1rem; + margin: 0; + color: var(--retro-button-text-color); + background-color: var(--retro-button-color); + box-shadow: var(--retro-clickable-shadow); + transition: + transform 0.1s, + box-shadow 0.1s; +} + +h3:focus-within, +h3:hover { + box-shadow: var(--retro-pressed-shadow); + transform: translate(1px, 1px); + outline-offset: 6px; + outline: 4px dashed color-mix(in srgb, var(--hot-pink) 60%, transparent); +} + +h3:has([aria-disabled='true']) { + opacity: 0.5; + cursor: default; +} + +.treasure-box { + margin: 0; + padding: 1rem; + display: flex; + justify-content: center; + align-items: center; + height: 5rem; + background-color: var(--septenary-contrast); + box-shadow: var(--retro-flat-shadow); +} + +[ngAccordionTrigger] { + display: flex; + align-items: center; + justify-content: space-between; + outline: none; + cursor: pointer; + padding: 1.5rem; +} + +[ngAccordionPanel] { + padding: 1rem; +} diff --git a/adev/src/content/examples/aria/accordion/src/single-expansion/retro/app/app.component.html b/adev/src/content/examples/aria/accordion/src/single-expansion/retro/app/app.component.html new file mode 100644 index 00000000000..b7c43a4fb4f --- /dev/null +++ b/adev/src/content/examples/aria/accordion/src/single-expansion/retro/app/app.component.html @@ -0,0 +1,49 @@ +
+

+ + Unlock Treasure Box + + +

+
+ +
👻
+
+
+ +

+ + Unlock Treasure Box + + +

+
+ +
💎💎💎
+
+
+ +

+ + Unlock Treasure Box + + +

+
+ +
🐸 ribbit...ribbit...
+
+
+
diff --git a/adev/src/content/examples/aria/accordion/src/single-expansion/retro/app/app.component.ts b/adev/src/content/examples/aria/accordion/src/single-expansion/retro/app/app.component.ts new file mode 100644 index 00000000000..27d79c434b5 --- /dev/null +++ b/adev/src/content/examples/aria/accordion/src/single-expansion/retro/app/app.component.ts @@ -0,0 +1,15 @@ +import {Component} from '@angular/core'; +import { + AccordionGroup, + AccordionTrigger, + AccordionPanel, + AccordionContent, +} from '@angular/aria/accordion'; + +@Component({ + selector: 'app-root', + templateUrl: 'app.component.html', + styleUrl: 'app.component.css', + imports: [AccordionGroup, AccordionTrigger, AccordionPanel, AccordionContent], +}) +export class App {} diff --git a/adev/src/content/guide/aria/accordion.md b/adev/src/content/guide/aria/accordion.md index 42dd071fdc5..721343421d2 100644 --- a/adev/src/content/guide/aria/accordion.md +++ b/adev/src/content/guide/aria/accordion.md @@ -5,10 +5,10 @@ An accordion organizes related content into expandable and collapsible sections, reducing page scrolling and helping users focus on relevant information. Each section has a trigger button and a content panel. Clicking a trigger toggles the visibility of its associated panel. - - - - + + + + @@ -50,10 +50,29 @@ Accordions work well for organizing content into logical groups where users typi Set `[multiExpandable]="false"` to allow only one panel to be open at a time. Opening a new panel automatically closes any previously open panel. - - - - + + + + + + + + + + + + + + + + + + + + + + + This mode works well for FAQs or situations where you want users to focus on one answer at a time. @@ -61,10 +80,29 @@ This mode works well for FAQs or situations where you want users to focus on one Set `[multiExpandable]="true"` to allow multiple panels to be open simultaneously. Users can expand as many panels as needed without closing others. - - - - + + + + + + + + + + + + + + + + + + + + + + + This mode is useful for form sections or when users need to compare content across multiple panels. @@ -74,10 +112,29 @@ NOTE: The `multiExpandable` input defaults to `true`. Set it to `false` explicit Disable specific triggers using the `disabled` input. Control how disabled items behave during keyboard navigation using the `softDisabled` input on the accordion group. - - - - + + + + + + + + + + + + + + + + + + + + + + + When `[softDisabled]="true"` (the default), disabled items can receive focus but cannot be activated. When `[softDisabled]="false"`, disabled items are skipped entirely during keyboard navigation.