Communitygithub.com

karero/website-hero-carousel

網頁英雄輪播:輪流展示的照片,以及確保它們誠實運作的測試。

website-hero-carousel 是什麼?

這個技能提供一個網站首頁的英雄輪播元件,讓多張照片每隔幾秒自動切換,並附有導航圓點。它的設計重點在於解決常見的實作陷阱:確保頁面不會因照片切換而跳動、導航圓點在任何背景色下都可見、支援無 JavaScript 環境、以及符合無障礙規範(WCAG 2.2.2)。此技能不僅提供 Astro 元件、JavaScript、樣式與多語言文字,更關鍵的是附帶一套完整的 Playwright 端對端測試,涵蓋間隔時間、暫停按鈕、鍵盤焦點、減少動畫偏好、隱藏分頁、圖片載入延遲或失敗、無 JavaScript 情境、高度穩定性、無障礙樹與強制色彩模式等測試項目。此技能適用於 Astro 專案,開發者只需複製四個檔案並在頁面中導入元件即可使用。

相容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/karero/croftweaver/tree/HEAD/skills/website-hero-carousel

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

網站英雄輪播:輪流展示的照片,以及確保它們誠實運作的測試

放在頁面頂部的照片區,兩張或更多照片每隔幾秒輪流顯示,每張照片都有一個圓點。看起來簡單,但實際上並不簡單:一張照片上的說明文字會讓頁面在每次切換時跳動;白色圓點在淺色照片上會消失;手機需要比滑鼠更大的觸控目標;而且動態內容本身就有無障礙規範。這個技能提供了元件,更重要的是,提供了能捕獲所有這些問題的測試。

為何這樣設計(用你自己的話告訴業主)

  • 頁面永不跳動。 所有照片共用一個位置,裁切為同一形狀,因此第一張照片和最後一張照片的高度相同。照片上沒有說明文字或版權標示:它們正是導致原始網站頁面跳動的原因。版權資訊應該放在網站的圖片版權頁。
  • 圓點在任何照片上都能辨識。 它們位於一個小小的深色藥丸形狀上,無論在淺色天空還是深色牆壁上都能顯示。測試會透過像素測量淺色和深色照片上的對比度。
  • 沒有 JavaScript 也能運作。 照片會上下排列,且不顯示任何按鈕。
  • 行為有禮貌。 當滑鼠懸停、分頁隱藏、鍵盤焦點進入時會停止輪播,並且對要求減少動畫效果的訪客,從一開始就停止輪播。
  • 不儲存也不發送任何資料。 沒有 Cookie、沒有儲存空間、沒有對其他網站的請求。

以及誠實的弱點,讓業主先從你口中聽到:

  • 旋轉的照片不一定總是更好的設計。 一張強而有力的靜態照片更平靜、載入更快,也不會惹惱任何人。請明確告知;由業主決定。
  • 每多一張照片,都會增加訪客在手機上的下載時間。 三張照片各四種尺寸還可以;十張就不行了。請限制在少數幾張。
  • 「圓點」暫停模式是用可見的控制項換取更乾淨的照片(參見下方的「暫停」章節)。

0. 這是正確的工具嗎?(安裝前先詢問)

  1. 業主確定要旋轉嗎? 一張照片完全不需要這些。清楚詢問一次。
  2. 有幾張照片?它們的形狀相同嗎? 兩到五張。任何形狀都可以(每張照片都會被裁切成輪播的形狀),但主體在邊緣的照片可能會在裁切中遺失:請以輪播的形狀(預設為 16 / 9)和手機的形狀檢查每張照片。
  3. 照片有連結到任何地方嗎? 任何幻燈片都可以連結到一個頁面(例如一個專案);混合有連結和無連結的幻燈片是可以的(CI 頁面就是這樣做的)。
  4. 要使用哪種暫停模式? 向業主閱讀下方的「暫停」章節,讓他們選擇。預設值:按鈕。

1. 它為網站添加了什麼

檔案來自此技能的 templates/它是什麼
src/components/HeroCarousel.astroHeroCarousel.astro標記、圓點、樣式
src/components/hero-carousel-text.tshero-carousel-text.ts它說的文字,英文和德文
public/js/hero-carousel.jshero-carousel.js指令碼:將幻燈片放置在一個位置、輪播、處理控制項
tests/hero-carousel.spec.tshero-carousel.spec.ts訪客所見的輪播(下方列表)

安裝所有四個檔案。範本中不包含任何圖片檔案:照片是網站自己的,作為 props 傳入。

一句話說明運作方式。 伺服器發送所有幻燈片,一張疊在另一張下方,並且控制項是隱藏的。指令碼(網站自己的檔案,位於 public/js/ 而不是內嵌指令碼,這樣嚴格的 script-src 'self' 才能讓它執行)隨後將所有幻燈片放置在一個網格儲存格中,顯示控制項,並標記當前顯示的幻燈片。哪張幻燈片正在顯示由一個 data 屬性決定;CSS 負責其餘部分,包括一秒鐘的淡入效果。幻燈片僅在其圖片完全載入後才顯示,因此載入延遲或失敗的照片永遠不會留下空白位置。

規格測試的內容(以訪客視角,在已建置的頁面上):標記和每個圓點的名稱;以凍結時鐘測試毫秒級的間隔;暫停按鈕或圓點停止輪播,以及標籤和即時區域;鍵盤焦點(停止輪播、保持停止、繼續);指標懸停以及離開後重新開始倒數計時;減少動畫效果;隱藏的分頁;延遲載入和載入失敗的第二張圖片;沒有 JavaScript 的頁面;在 1280、768 和 390 px 寬度下沒有高度跳動;未顯示的幻燈片無法透過鍵盤或無障礙樹訪問;照片的連結有效,且圓點永遠不會打開它;32 像素的目標(觸控螢幕上為 44 像素);圓點在藥丸形狀上,覆蓋每張照片,從渲染的像素讀取;強制色彩模式;兩種主題下的 axe 無障礙檢測;沒有儲存或發送任何資料;指令碼是一個檔案,不是內嵌的;淡入效果在動畫中途的影格上執行並穩定下來,並且在減少動畫效果下不會執行。

2. 安裝(在分支上,作為合併請求:AGENTS.md §2)

  1. 將這四個檔案複製到 §1 中指定的位置(先執行 mkdir -p public/js)。
  2. 將輪播放在頁面上,位於該頁面的 <Base> 元件內,靠近頂部:
    ---
    import HeroCarousel from '../components/HeroCarousel.astro';
    import first from '../assets/hero-1.jpg';
    import second from '../assets/hero-2.jpg';
    ---
    <HeroCarousel label="我們作品的相片" slides={[
      { image: first,  alt: '第一張照片顯示的內容', label: '簡短名稱', href: '/projects/one' },
      { image: second, alt: '第二張照片顯示的內容', label: '另一個名稱' },
    ]} />
    
    • label:輪播是什麼,給螢幕報讀軟體使用。必填。
    • 每個幻燈片:image(導入的照片)、alt(描述照片內容的句子,至少 10 個字元:少於此長度建置會失敗)、label(圓點的簡短名稱)、href(可選)。
    • pause:"button"(預設)或 "dots"。swap:"instant"(預設)或 "fade"。intervalMs:預設 6000,不得低於 2000。ratio:預設 "16 / 9"。lang:頁面自己的語言。 照片:JPEG 或 PNG,寬度約 2,400 px,保持在頁面所需的數量(建置會為每張照片製作四種尺寸,AVIF 格式,WebP 作為備用)。第一張照片優先載入(高優先級);其他照片以低優先級載入並保留其位置。
  3. 語言。 內建英文和德文,元件會使用頁面自己的語言(Base.astro 將其作為 Astro.locals.lang 傳遞)。其他語言:請先參閱下方的「新增語言」。
  4. 在 tests/hero-carousel.spec.ts 中,將 PAGE(包含輪播的頁面)、PAUSE 和 SWAP 設定為頁面傳遞的值(元件的預設值是 button 和 instant;測試需要明確寫出)。如果其中一個是空的,測試會失敗。僅在頁面傳遞 lang 時才設定 LANG。 對比度測試的照片: 測試會讀取輪播的真實照片,因此它使用的是業主自己的照片。如果所有照片都是暗色系,則「白色圓點在藥丸形狀上」的測試無法失敗;若要查看它失敗,請手動加入一張淺色照片進行檢查(§3 中的突變檢查會執行此操作)。
  5. npm run check && npm test。

暫停(在業主選擇之前,向他們閱讀此內容)

自動啟動、持續超過五秒且與其他內容相鄰的動態內容,屬於 WCAG 2.2.2,A 級,該規範要求「使用者能夠暫停、停止或隱藏它的機制」(請閱讀 https://www.w3.org/WAI/WCAG22/Understanding/pause-stop-hide.html)。同一頁面將 暫停 定義為「由使用者請求停止,並且在使用者請求之前不會恢復」,並且沒有說明該機制必須是可見的。它沒有討論幻燈片指示器。

  • pause="button"(預設)。 在圓點旁邊有一個暫停按鈕(停止時顯示繼續按鈕)。可見、有命名、是沒有人會爭論的解讀,也是訪客會找到的方式。它的代價:照片上的一個小文字。
  • pause="dots"。 沒有按鈕。選擇一個圓點會顯示該張照片並停止輪播,直到訪客重新載入頁面;鍵盤焦點進入輪播也會停止它,並且在減少動畫效果模式下,輪播一開始就是停止的。這很可能符合 2.2.2 意義上的機制,但沒有任何東西告訴訪客圓點可以停止輪播,而且也沒有辦法恢復輪播。第一個使用此模式的網站選擇它是為了更乾淨的照片,並且充分了解這一點。

此技能不做出任何合規性結論:是否接受「圓點」模式由網站自己的稽核員決定。如果業主選擇它,請在網站的文件中寫下一行,並附上日期。

新增語言

當網站使用新語言時,或者當網站後續增加語言時。

  1. 首先閱讀網站的語調指南(CONTENT_GUIDE.md;在德文中要注意正式/非正式用語)。這些文字只有幾個單詞:在語言允許的情況下,使用非特定人稱。
  2. 在 src/components/hero-carousel-text.ts 中,複製 TEXT 物件的 en 條目,放在語言的兩位字母代碼(例如 fr,而不是 fr-CA)下,並翻譯每個值;如果缺少任何值,npm run check 會失敗。
  3. 頁面及其測試,如 §2 步驟 3 和 4 所述。

3. 親自試用一次(業主),以及此技能背後的檢查

在執行 npm run build && npm run preview 之後,或者在合併請求的預覽網址上,業主可以:

  1. 等待:照片會自動切換,當前顯示的幻燈片對應的圓點會亮起。
  2. 將滑鼠移到輪播上:輪播會暫停。移開滑鼠:輪播會在一個完整的間隔時間後繼續。
  3. 在手機上:點擊圓點(會顯示該圓點對應的照片);沒有橫向滾動;圓點易於點擊。
  4. 在按鈕模式下:按下暫停,看到它顯示繼續,再次按下。

此技能建置時使用的檢查,以便評估對範本的變更:測試套件為每一項都包含一個測試,當其保護的功能被移除時,每個測試都會失敗。當範本變更時,請手動執行一次(CI 任務會將它們安裝在一個全新的網站中,並以其使用的所有三種設定組合執行測試套件):

從 HeroCarousel.astro 中移除此項目此測試會失敗
網格規則(display: grid, grid-area)"幻燈片共用一個位置..."
照片上的 aspect-ratio同一個測試(4:3 的照片會更高)
藥丸形狀的 background"在每張照片上渲染..."(白色在淺色照片上大約是 1:1)
當前顯示圓點上的 border-width: 5px強制色彩模式測試
transition 規則淡入效果測試("動畫中途的影格")
未顯示幻燈片上的 pointer-events: none"照片連結到其頁面..."(淡出的幻燈片會攔截點擊)
指令碼在未顯示幻燈片上設定的 inert 和 aria-hidden(hero-carousel.js)Tab 鍵和無障礙樹測試(正在淡出的幻燈片的連結在淡出期間仍然可達且可讀)
指令碼的 recover()(當前顯示的照片載入失敗時,由第一張已存在的其他照片取代,無論是現在還是將來載入完成)"第一張圖片載入失敗..."

4. 隱私頁面,以及移除方式

輪播不儲存也不發送任何資訊:無需在隱私頁面添加任何內容。

要移除它:刪除這四個檔案,從頁面中刪除 <HeroCarousel> 區塊以及 import HeroCarousel 這行程式碼(以及僅由它使用的圖片導入);放回一張照片。沒有其他東西會參照它,除了由 PAGES 驅動的、僅看到該頁面的測試套件。

5. 此技能不包含的內容(以免有人假設)

上一張/下一張箭頭、滑動手勢、照片上的說明文字、照片上的版權標示、影片幻燈片、頁面上超過一個輪播(其 id 是固定的)、後續照片的延遲載入。每一項都可以在之後添加;但第一個版本都不需要。

Individual skills in this repo

This repo contains 2 individual skills — each has its own dedicated page.

相關技能