Skip to content

Implement global skip links#18499

Open
gcamacho079 wants to merge 10 commits into6.xfrom
a11y/bypass-blocks
Open

Implement global skip links#18499
gcamacho079 wants to merge 10 commits into6.xfrom
a11y/bypass-blocks

Conversation

@gcamacho079
Copy link
Contributor

@gcamacho079 gcamacho079 commented Mar 2, 2026

Description

Re-implements skip links with a few updates/improvements

  • The AppLayout has a single skip link by default, but IndexLayout pushes additional skip links via an additionalSkipLinks prop.
  • Changes the “Skip to left sidebar” skip link to “Skip to secondary navigation”. This feels like it’s clearer.
  • Moves the Breadcrumb navigation out of the #main container, so it can be bypassed via the “Skip to main” link.

To test

  • Non-index pages should have a single skip link (“Skip to main”)
  • Index pages should have two additional skip links (“Skip to secondary navigation”, “Skip to content”)
  • The “Skip to main” link should bypass all repeated content, so it should take users past the breadcrumbs as well
  • All navigation regions should have unique labels (“Primary”, “Secondary”, “Breadcrumb”)

Related issues

Resolves ACC-29

@gcamacho079 gcamacho079 added the accessibility 👤 features related to accessibility label Mar 2, 2026
@linear
Copy link

linear bot commented Mar 2, 2026

@gcamacho079 gcamacho079 requested a review from Copilot March 3, 2026 16:09
@gcamacho079 gcamacho079 marked this pull request as ready for review March 3, 2026 16:09
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Implements global “skip links” for improved keyboard/accessibility navigation across the CP, with index pages contributing additional skip targets and breadcrumb navigation moved outside the main landmark so it can be bypassed.

Changes:

  • Add global skip-link rendering in AppLayout, with IndexLayout injecting extra skip links for secondary nav/content.
  • Add/adjust ARIA landmark labels (Primary/Secondary/Breadcrumbs) and move breadcrumbs outside #main.
  • Update skip-link styling and add missing translations.

Reviewed changes

Copilot reviewed 21 out of 22 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
resources/translations/en/app.php Adds translation strings for “Secondary” and “Skip to secondary navigation”.
resources/js/pages/SettingsSitesIndex.vue Removes extra <nav> wrapper in interior-nav slot (avoids nested nav now that layout provides it).
resources/js/layout/IndexLayout.vue Adds secondary-nav/content skip-link targets and wraps interior nav in a labeled <nav> with focus target IDs.
resources/js/layout/AppLayout.vue Introduces global skip links, adds additionalSkipLinks prop, and moves breadcrumbs outside the main container.
resources/js/components/CpSidebar.vue Adds an aria-label (“Primary”) to the main sidebar navigation landmark.
resources/js/components/Breadcrumbs.vue Wraps breadcrumbs list in a labeled <nav> landmark (“Breadcrumbs”).
resources/build/legacy.js Bundled output updated (import symbol changes).
resources/build/assets/cp.css Bundled CSS updated to reflect skip-link styling changes.
resources/build/assets/AppLayout.css Bundled CSS updated for AppLayout scope hash changes.
resources/build/Updater.js Bundled output updated (import symbol changes).
resources/build/SettingsSitesIndex.js Bundled output updated for SettingsSitesIndex changes.
resources/build/SettingsSitesEdit.js Bundled output updated (import symbol changes).
resources/build/SettingsIndexPage.js Bundled output updated (import symbol changes).
resources/build/SettingsGeneralPage.js Bundled output updated (import symbol changes).
resources/build/Install.js Bundled output updated (import symbol changes).
resources/build/IndexLayout.js Bundled output updated for IndexLayout changes.
resources/build/DeleteSiteModal.vue_vue_type_script_setup_true_lang.js Bundled output updated (import symbol changes).
resources/build/CpQueueIndicator.js Bundled output updated (internal symbol changes).
resources/build/CalloutReadOnly.vue_vue_type_script_setup_true_lang.js Bundled output updated (import symbol changes).
resources/build/AppLayout.js Bundled output updated, but currently contains debug/placeholder content that doesn’t match source.
packages/craftcms-cp/src/styles/cp.css Updates .skip-link styling and adds .skip-link--global positioning variables.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

<div class="cp">
<div class="cp__header">
<header class="cp__header">
<a v-for="link in skipLinks" :href="link.url" class="skip-link skip-link--global">{{ link.label }}</a>
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The global skip links are rendered with v-for but without a :key, which will trigger Vue warnings and can lead to unstable DOM updates (especially if additionalSkipLinks changes). Add a stable :key (e.g. link.url or a combination of url+label).

Suggested change
<a v-for="link in skipLinks" :href="link.url" class="skip-link skip-link--global">{{ link.label }}</a>
<a
v-for="link in skipLinks"
:key="link.url || link.label"
:href="link.url"
class="skip-link skip-link--global"
>
{{ link.label }}
</a>

Copilot uses AI. Check for mistakes.
@@ -1 +1 @@
import{d as g,ab as N,l as x,o as s,q as E,s as f,w as B,a as e,c as t,m as c,t as u,_ as $,F as y,p as J,b as k,u as v,O as F,A as T,$ as R,N as p,ad as S,v as z,T as j,aj as W,a9 as O,K,z as P,ah as Q,X,r as h,B as G,ak as H,i as D}from"./cp3.js";const U={class:"system-info__icon"},Y=["src"],Z={class:"system-info__name"},ee=g({__name:"SystemInfo",setup(a){const i=N(),r=f(()=>i.system),o=f(()=>i.site),l=f(()=>o.value.url?"a":"div");return(b,d)=>(s(),x(E(l.value),{class:"system-info",href:o.value.url,target:o.value.url?"_blank":null},{default:B(()=>[e("div",U,[r.value.icon?(s(),t("img",{key:0,src:r.value.icon.url,alt:""},null,8,Y)):c("",!0)]),e("div",Z,u(r.value.name),1)]),_:1},8,["href","target"]))}}),I=$(ee,[["__scopeId","data-v-f4725d04"]]),se=["icon","href","active","indicator"],te={key:0,slot:"subnav"},ae=["active","href","indicator"],ie=["name"],ne={key:1,class:"nav-indicator",slot:"icon"},oe=[".displayedJob",".hasReservedJobs",".hasWaitingJobs"],le=g({__name:"MainNav",setup(a){const i=F(),{nav:r}=N(),o=f(()=>i.props.queue);return(l,b)=>(s(),t("craft-nav-list",null,[(s(!0),t(y,null,J(v(r),d=>(s(),t("craft-nav-item",{key:d.url,icon:d.icon,href:d.url,active:d.sel,indicator:!!d.badgeCount},[k(u(d.label)+" ",1),d.subnav?(s(),t(y,{key:0},[d.subnav?(s(),t("craft-nav-list",te,[(s(!0),t(y,null,J(d.subnav,n=>(s(),t("craft-nav-item",{key:n.url,active:n.sel,href:n.url,indicator:!!n.badgeCount},[n.icon?(s(),t("craft-icon",{key:0,name:n.icon,slot:"icon"},null,8,ie)):(s(),t("span",ne)),k(" "+u(n.label),1)],8,ae))),128))])):c("",!0)],64)):c("",!0)],8,se))),128)),e("cp-queue-indicator",{".displayedJob":o.value.displayedJob,".hasReservedJobs":o.value.hasReservedJobs,".hasWaitingJobs":o.value.hasWaitingJobs},null,40,oe)]))}}),re=$(le,[["__scopeId","data-v-2115cac3"]]),de={class:"flex justify-center py-4 px-2 text-muted"},ce={lang:"en",class:"flex items-center gap-2"},ue={class:"edition-logo"},be={"aria-hidden":"true"},_e={class:"sr-only"},ve=g({__name:"EditionInfo",setup(a){const{app:i}=N(),r=f(()=>`${i.edition.name} Edition`);return(o,l)=>(s(),t("div",de,[e("div",null,[e("span",ce,[l[0]||(l[0]=k(" Craft CMS ",-1)),e("span",ue,[e("span",be,u(v(i).edition.name),1),e("span",_e,u(r.value),1)]),k(" "+u(v(i).version),1)])])]))}}),fe=$(ve,[["__scopeId","data-v-f8b4ece7"]]),me={},he={class:"dev-mode"};function pe(a,i){return s(),t("div",he,[...i[0]||(i[0]=[e("div",{class:"inline-flex py-1 px-2 bg-slate-900 text-slate-100 font-mono text-xs rounded-lg"}," Dev Mode is enabled ",-1)])])}const ye=$(me,[["render",pe],["__scopeId","data-v-52fa7a33"]]),ge=["data-visibility","data-mode"],$e={class:"cp-sidebar__header"},ke={key:0,class:"sidebar-header"},xe={class:"cp-sidebar__body"},Ce={class:"cp-sidebar__footer"},Se=g({__name:"CpSidebar",props:{mode:{default:"floating"},visibility:{default:"hidden"}},emits:["close","dock"],setup(a,{emit:i}){const r=i,o=f(()=>a.mode==="floating");return T(()=>a.visibility,async l=>{o.value&&l==="visible"&&(await R(),document.querySelector(".cp-sidebar").querySelector('button, [href], [tabindex]:not([tabindex="-1"])')?.focus())}),(l,b)=>(s(),t("nav",{class:"cp-sidebar","data-visibility":a.visibility,"data-mode":a.mode},[a.visibility==="visible"?(s(),t(y,{key:0},[e("div",$e,[a.mode!=="docked"?(s(),t("div",ke,[p(I),b[2]||(b[2]=e("div",{class:"ml-auto"},null,-1)),e("craft-button",{size:"small",icon:"",onClick:b[0]||(b[0]=d=>r("close")),type:"button"},[...b[1]||(b[1]=[e("craft-icon",{name:"x",style:{"font-size":"0.7em"}},null,-1)])])])):c("",!0)]),e("div",xe,[p(re)]),e("div",Ce,[p(fe),p(ye)])],64)):c("",!0)],8,ge))}}),we=$(Se,[["__scopeId","data-v-22a18951"]]),Je={class:"breadcrumbs"},Ne={key:2,class:"separator"},Be=g({__name:"Breadcrumbs",props:{items:{},separator:{default:"/"}},setup(a){return(i,r)=>(s(),t("ul",Je,[(s(!0),t(y,null,J(a.items,(o,l)=>(s(),t("li",{key:l,class:S({"breadcrumb-item":!0,"breadcrumb-item--active":l===a.items.length-1})},[o.url?(s(),x(z,{key:0,href:o.url},{default:B(()=>[k(u(o.label),1)]),_:2},1032,["href"])):(s(),t(y,{key:1},[k(u(o.label),1)],64)),l<a.items.length-1?(s(),t("span",Ne,u(a.separator),1)):c("",!0)],2))),128))]))}}),De=$(Be,[["__scopeId","data-v-4d21c399"]]),Fe={key:0,id:"global-live-region",class:"sr-only",role:"status"},Te=g({__name:"LiveRegion",setup(a){const{announcement:i}=W();return(r,o)=>(s(),x(j,null,{default:B(()=>[v(i)?(s(),t("div",Fe,u(v(i)),1)):c("",!0)]),_:1}))}}),We={class:"cp"},Ie={class:"cp__header"},Me={class:"flex gap-2 p-2"},qe=["name"],Le={key:0,variant:"danger",rounded:"none"},Ve={key:1,variant:"success",rounded:"none"},Ae={class:"cp__sidebar"},Ee={class:"cp__main"},Re={key:0,class:"px-4 py-2 border-b border-b-border-subtle"},ze={class:"index-grid index-grid--header"},je={class:"index-grid__aside"},Oe={class:"text-xl"},Ke={class:"index-grid__main"},Pe={class:"cp__footer"},Qe={key:0,class:"fixed bottom-2 right-2 flex gap-2 justify-end items-center p-2"},Xe={class:"bg-blue-50 border border-blue-500 py-1 px-4 rounded"},Ge=["label"],He=["label"],Ue=g({__name:"AppLayout",props:{title:{},debug:{},fullWidth:{type:Boolean,default:!1}},setup(a){O(_=>({v51f1fb4a:V.value}));const i=F(),r=f(()=>i.props.flash?.error),o=f(()=>i.props.flash?.success),l=f(()=>i.props.crumbs??null),b=K("sidebarToggle"),{announcement:d}=W(),n=Q({sidebar:{mode:"floating",visibility:"hidden"}}),w=P("(min-width: 1024px)"),C=G(!1);T(w,_=>{_?(n.sidebar.mode="docked",n.sidebar.visibility="visible"):(n.sidebar.mode="floating",n.sidebar.visibility="hidden")},{immediate:!0});function M(){n.sidebar.visibility==="visible"?n.sidebar.visibility="hidden":n.sidebar.visibility="visible"}function q(){n.sidebar.visibility="hidden",b.value.focus()}const L=f(()=>n.sidebar.visibility==="visible"?"x":"bars"),V=f(()=>n.sidebar.mode==="docked"?n.sidebar.visibility==="visible"?"var(--global-sidebar-width)":"0":"auto");return(_,m)=>(s(),t(y,null,[p(v(X),{title:a.title},null,8,["title"]),p(Te,{debug:!0}),e("div",We,[e("div",Ie,[e("div",Me,[v(w)?c("",!0):(s(),t("craft-button",{key:0,icon:"",type:"button",appearance:"plain",onClick:M,ref_key:"sidebarToggle",ref:b},[e("craft-icon",{name:L.value},null,8,qe)],512)),v(w)?(s(),x(I,{key:1})):c("",!0),m[2]||(m[2]=e("div",{class:"ml-auto"},null,-1)),m[3]||(m[3]=e("craft-button",{icon:"",appearance:"plain"},[e("craft-icon",{name:"search"})],-1))]),r.value?(s(),t("craft-callout",Le,u(r.value),1)):c("",!0),o.value?(s(),t("craft-callout",Ve,u(o.value),1)):c("",!0)]),e("div",Ae,[p(we,{mode:n.sidebar.mode,visibility:n.sidebar.visibility,onClose:q},null,8,["mode","visibility"])]),e("div",Ee,[h(_.$slots,"main",{},()=>[e("main",null,[h(_.$slots,"breadcrumbs",{},()=>[l.value?(s(),t("div",Re,[p(De,{items:l.value},null,8,["items"])])):c("",!0)],!0),h(_.$slots,"header",{},()=>[e("div",{class:S({container:!0,"container--full":a.fullWidth})},[e("div",ze,[e("div",je,[h(_.$slots,"title",{},()=>[e("h1",Oe,u(a.title),1)],!0),h(_.$slots,"title-badge",{},void 0,!0)]),e("div",Ke,[h(_.$slots,"actions",{},void 0,!0)])])],2)],!0),e("div",{class:S({container:!0,"container--full":a.fullWidth})},[h(_.$slots,"default",{},void 0,!0)],2)])],!0)]),e("div",Pe,[e("footer",null,[e("div",{class:S({container:!0,"container--full":a.fullWidth})},[h(_.$slots,"footer",{},void 0,!0)],2)])])]),a.debug?(s(),t("div",Qe,[e("div",Xe,u(v(d)??"No announcement"),1),e("div",null,[C.value?(s(),x(H,{key:0,data:a.debug,class:"max-h-[50vh] max-w-[600px] overflow-scroll absolute transform -translate-full"},null,8,["data"])):c("",!0),C.value?(s(),t("craft-button",{key:1,icon:"",type:"button",onClick:m[0]||(m[0]=A=>C.value=!1)},[e("craft-icon",{label:v(D)("Close Debug panel"),name:"x"},null,8,Ge)])):(s(),t("craft-button",{key:2,type:"button",onClick:m[1]||(m[1]=A=>C.value=!0),icon:""},[e("craft-icon",{name:"code",label:v(D)("Show debug variables")},null,8,He)]))])])):c("",!0)],64))}}),Ze=$(Ue,[["__scopeId","data-v-63434e96"]]);export{Ze as A};
import{d as g,ab as N,l as x,o as s,q as A,s as f,w as B,a as e,c as t,m as c,t as u,_ as $,F as y,p as J,b as k,u as v,O as F,A as L,$ as R,N as h,ad as S,v as z,T as j,aj as T,a9 as O,K as H,z as K,ah as P,X as Q,r as p,B as X,ak as G,e as D}from"./cp3.js";const U={class:"system-info__icon"},Y=["src"],Z={class:"system-info__name"},ee=g({__name:"SystemInfo",setup(a){const i=N(),r=f(()=>i.system),o=f(()=>i.site),l=f(()=>o.value.url?"a":"div");return(b,d)=>(s(),x(A(l.value),{class:"system-info",href:o.value.url,target:o.value.url?"_blank":null},{default:B(()=>[e("div",U,[r.value.icon?(s(),t("img",{key:0,src:r.value.icon.url,alt:""},null,8,Y)):c("",!0)]),e("div",Z,u(r.value.name),1)]),_:1},8,["href","target"]))}}),W=$(ee,[["__scopeId","data-v-f4725d04"]]),se=["icon","href","active","indicator"],te={key:0,slot:"subnav"},ae=["active","href","indicator"],ie=["name"],ne={key:1,class:"nav-indicator",slot:"icon"},oe=[".displayedJob",".hasReservedJobs",".hasWaitingJobs"],le=g({__name:"MainNav",setup(a){const i=F(),{nav:r}=N(),o=f(()=>i.props.queue);return(l,b)=>(s(),t("craft-nav-list",null,[(s(!0),t(y,null,J(v(r),d=>(s(),t("craft-nav-item",{key:d.url,icon:d.icon,href:d.url,active:d.sel,indicator:!!d.badgeCount},[k(u(d.label)+" ",1),d.subnav?(s(),t(y,{key:0},[d.subnav?(s(),t("craft-nav-list",te,[(s(!0),t(y,null,J(d.subnav,n=>(s(),t("craft-nav-item",{key:n.url,active:n.sel,href:n.url,indicator:!!n.badgeCount},[n.icon?(s(),t("craft-icon",{key:0,name:n.icon,slot:"icon"},null,8,ie)):(s(),t("span",ne)),k(" "+u(n.label),1)],8,ae))),128))])):c("",!0)],64)):c("",!0)],8,se))),128)),e("cp-queue-indicator",{".displayedJob":o.value.displayedJob,".hasReservedJobs":o.value.hasReservedJobs,".hasWaitingJobs":o.value.hasWaitingJobs},null,40,oe)]))}}),re=$(le,[["__scopeId","data-v-2115cac3"]]),de={class:"flex justify-center py-4 px-2 text-muted"},ce={lang:"en",class:"flex items-center gap-2"},ue={class:"edition-logo"},be={"aria-hidden":"true"},_e={class:"sr-only"},ve=g({__name:"EditionInfo",setup(a){const{app:i}=N(),r=f(()=>`${i.edition.name} Edition`);return(o,l)=>(s(),t("div",de,[e("div",null,[e("span",ce,[l[0]||(l[0]=k(" Craft CMS ",-1)),e("span",ue,[e("span",be,u(v(i).edition.name),1),e("span",_e,u(r.value),1)]),k(" "+u(v(i).version),1)])])]))}}),fe=$(ve,[["__scopeId","data-v-f8b4ece7"]]),me={},pe={class:"dev-mode"};function he(a,i){return s(),t("div",pe,[...i[0]||(i[0]=[e("div",{class:"inline-flex py-1 px-2 bg-slate-900 text-slate-100 font-mono text-xs rounded-lg"}," Dev Mode is enabled ",-1)])])}const ye=$(me,[["render",he],["__scopeId","data-v-52fa7a33"]]),ge=["data-visibility","data-mode"],$e={class:"cp-sidebar__header"},ke={key:0,class:"sidebar-header"},xe={class:"cp-sidebar__body"},Ce={class:"cp-sidebar__footer"},Se=g({__name:"CpSidebar",props:{mode:{default:"floating"},visibility:{default:"hidden"}},emits:["close","dock"],setup(a,{emit:i}){const r=i,o=f(()=>a.mode==="floating");return L(()=>a.visibility,async l=>{o.value&&l==="visible"&&(await R(),document.querySelector(".cp-sidebar").querySelector('button, [href], [tabindex]:not([tabindex="-1"])')?.focus())}),(l,b)=>(s(),t("nav",{class:"cp-sidebar","data-visibility":a.visibility,"data-mode":a.mode},[a.visibility==="visible"?(s(),t(y,{key:0},[e("div",$e,[a.mode!=="docked"?(s(),t("div",ke,[h(W),b[2]||(b[2]=e("div",{class:"ml-auto"},null,-1)),e("craft-button",{size:"small",icon:"",onClick:b[0]||(b[0]=d=>r("close")),type:"button"},[...b[1]||(b[1]=[e("craft-icon",{name:"x",style:{"font-size":"0.7em"}},null,-1)])])])):c("",!0)]),e("div",xe,[h(re)]),e("div",Ce,[h(fe),h(ye)])],64)):c("",!0)],8,ge))}}),we=$(Se,[["__scopeId","data-v-22a18951"]]),Je={class:"breadcrumbs"},Ne={key:2,class:"separator"},Be=g({__name:"Breadcrumbs",props:{items:{},separator:{default:"/"}},setup(a){return(i,r)=>(s(),t("ul",Je,[(s(!0),t(y,null,J(a.items,(o,l)=>(s(),t("li",{key:l,class:S({"breadcrumb-item":!0,"breadcrumb-item--active":l===a.items.length-1})},[o.url?(s(),x(z,{key:0,href:o.url},{default:B(()=>[k(u(o.label),1)]),_:2},1032,["href"])):(s(),t(y,{key:1},[k(u(o.label),1)],64)),l<a.items.length-1?(s(),t("span",Ne,u(a.separator),1)):c("",!0)],2))),128))]))}}),De=$(Be,[["__scopeId","data-v-4d21c399"]]),Fe={key:0,id:"global-live-region",class:"sr-only",role:"status"},Le=g({__name:"LiveRegion",setup(a){const{announcement:i}=T();return(r,o)=>(s(),x(j,null,{default:B(()=>[v(i)?(s(),t("div",Fe,u(v(i)),1)):c("",!0)]),_:1}))}}),Te={class:"cp"},We={class:"cp__header"},Ie={class:"flex gap-2 p-2"},Me=["name"],qe={key:0,variant:"danger",rounded:"none"},Ee={key:1,variant:"success",rounded:"none"},Ve={class:"cp__sidebar"},Ae={class:"cp__main"},Re={key:0,class:"px-4 py-2 border-b border-b-border-subtle"},ze={class:"index-grid index-grid--header"},je={class:"index-grid__aside"},Oe={class:"text-xl"},He={class:"index-grid__main"},Ke={class:"cp__footer"},Pe={key:0,class:"fixed bottom-2 right-2 flex gap-2 justify-end items-center p-2"},Qe={class:"bg-blue-50 border border-blue-500 py-1 px-4 rounded"},Xe=["label"],Ge=["label"],Ue=g({__name:"AppLayout",props:{title:{},debug:{},fullWidth:{type:Boolean,default:!1}},setup(a){O(_=>({v1749f026:E.value})),console.log("HELLO");const i=F(),r=f(()=>i.props.flash?.error),o=f(()=>i.props.flash?.success),l=f(()=>i.props.crumbs??null),b=H("sidebarToggle"),{announcement:d}=T(),n=P({sidebar:{mode:"floating",visibility:"hidden"}}),w=K("(min-width: 1024px)"),C=X(!1);L(w,_=>{_?(n.sidebar.mode="docked",n.sidebar.visibility="visible"):(n.sidebar.mode="floating",n.sidebar.visibility="hidden")},{immediate:!0});function I(){n.sidebar.visibility==="visible"?n.sidebar.visibility="hidden":n.sidebar.visibility="visible"}function M(){n.sidebar.visibility="hidden",b.value.focus()}const q=f(()=>n.sidebar.visibility==="visible"?"x":"bars"),E=f(()=>n.sidebar.mode==="docked"?n.sidebar.visibility==="visible"?"var(--global-sidebar-width)":"0":"auto");return(_,m)=>(s(),t(y,null,[h(v(Q),{title:a.title},null,8,["title"]),h(Le,{debug:!0}),e("div",Te,[e("div",We,[m[4]||(m[4]=e("a",{href:""},"Skip to main hello",-1)),e("div",Ie,[v(w)?c("",!0):(s(),t("craft-button",{key:0,icon:"",type:"button",appearance:"plain",onClick:I,ref_key:"sidebarToggle",ref:b},[e("craft-icon",{name:q.value},null,8,Me)],512)),v(w)?(s(),x(W,{key:1})):c("",!0),m[2]||(m[2]=e("div",{class:"ml-auto"},null,-1)),m[3]||(m[3]=e("craft-button",{icon:"",appearance:"plain"},[e("craft-icon",{name:"search"})],-1))]),r.value?(s(),t("craft-callout",qe,u(r.value),1)):c("",!0),o.value?(s(),t("craft-callout",Ee,u(o.value),1)):c("",!0)]),e("div",Ve,[h(we,{mode:n.sidebar.mode,visibility:n.sidebar.visibility,onClose:M},null,8,["mode","visibility"])]),e("div",Ae,[p(_.$slots,"main",{},()=>[e("main",null,[p(_.$slots,"breadcrumbs",{},()=>[l.value?(s(),t("div",Re,[h(De,{items:l.value},null,8,["items"])])):c("",!0)],!0),p(_.$slots,"header",{},()=>[e("div",{class:S({container:!0,"container--full":a.fullWidth})},[e("div",ze,[e("div",je,[p(_.$slots,"title",{},()=>[e("h1",Oe,u(a.title),1)],!0),p(_.$slots,"title-badge",{},void 0,!0)]),e("div",He,[p(_.$slots,"actions",{},void 0,!0)])])],2)],!0),e("div",{class:S({container:!0,"container--full":a.fullWidth})},[p(_.$slots,"default",{},void 0,!0)],2)])],!0)]),e("div",Ke,[e("footer",null,[e("div",{class:S({container:!0,"container--full":a.fullWidth})},[p(_.$slots,"footer",{},void 0,!0)],2)])])]),a.debug?(s(),t("div",Pe,[e("div",Qe,u(v(d)??"No announcement"),1),e("div",null,[C.value?(s(),x(G,{key:0,data:a.debug,class:"max-h-[50vh] max-w-[600px] overflow-scroll absolute transform -translate-full"},null,8,["data"])):c("",!0),C.value?(s(),t("craft-button",{key:1,icon:"",type:"button",onClick:m[0]||(m[0]=V=>C.value=!1)},[e("craft-icon",{label:v(D)("Close Debug panel"),name:"x"},null,8,Xe)])):(s(),t("craft-button",{key:2,type:"button",onClick:m[1]||(m[1]=V=>C.value=!0),icon:""},[e("craft-icon",{name:"code",label:v(D)("Show debug variables")},null,8,Ge)]))])])):c("",!0)],64))}}),Ze=$(Ue,[["__scopeId","data-v-b783c2e3"]]);export{Ze as A};
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The built resources/build/AppLayout.js output appears to include stray debug/placeholder content (console.log("HELLO") and a Skip to main hello link with an empty href). This doesn’t match the Vue source and would ship broken skip-link behavior + console noise. Please remove the debug/placeholder code and regenerate the build artifacts from the updated sources (or stop committing generated build output if that’s the intended workflow).

Copilot uses AI. Check for mistakes.
fullWidth?: boolean;
additionalSkipLinks?: Array<{label: string; url: string;}>;
}>(),
{fullWidth: false, crumbs: () => []}
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

withDefaults() is providing a default for crumbs, but crumbs is not a defined prop in defineProps<...>() (crumbs comes from page.props). This will at minimum confuse the props contract and can cause TS macro/type errors. Remove the crumbs default (or add a crumbs prop if that was intended).

Suggested change
{fullWidth: false, crumbs: () => []}
{fullWidth: false}

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

accessibility 👤 features related to accessibility

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants