From 5a28e709b95f906e8ecd17a688b12d19e5dfde73 Mon Sep 17 00:00:00 2001 From: Arata Date: Sun, 30 Aug 2026 10:33:27 +0900 Subject: [PATCH 01/12] feat: add filename prop to CodeBlock component and update accessibility labels --- src/components/Common/CodeBlock/index.stories.tsx | 12 ++++++++++++ src/components/Common/CodeBlock/index.tsx | 9 ++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/components/Common/CodeBlock/index.stories.tsx b/src/components/Common/CodeBlock/index.stories.tsx index d366231d..3eedea2d 100644 --- a/src/components/Common/CodeBlock/index.stories.tsx +++ b/src/components/Common/CodeBlock/index.stories.tsx @@ -1,4 +1,5 @@ import type { Meta, StoryObj } from '@storybook/nextjs-vite'; +import { expect } from 'storybook/test'; import CodeBlock, { codeBlockStyles } from '.'; const sampleCode = `export function greeting(name: string) { @@ -20,6 +21,17 @@ export const Default: Story = { }, }; +export const WithFilename: Story = { + args: { + filename: 'greeting.ts', + children: {sampleCode}, + }, + play: async ({ canvas }) => { + await expect(canvas.getByText('greeting.ts')).toBeVisible(); + await expect(canvas.getByRole('region', { name: 'コードブロック: greeting.ts' })).toBeVisible(); + }, +}; + export const LongLine: Story = { args: { children: ( diff --git a/src/components/Common/CodeBlock/index.tsx b/src/components/Common/CodeBlock/index.tsx index 9a6d3d52..56d466e7 100644 --- a/src/components/Common/CodeBlock/index.tsx +++ b/src/components/Common/CodeBlock/index.tsx @@ -6,7 +6,9 @@ import styles from './index.module.css'; /* eslint-disable jsx-a11y/no-noninteractive-tabindex -- Scrollable code regions need keyboard focus. */ -type Props = ComponentPropsWithoutRef<'pre'>; +type Props = ComponentPropsWithoutRef<'pre'> & { + filename?: string; +}; export const getReactNodeText = (node: ReactNode): string => { if (typeof node === 'string' || typeof node === 'number') { @@ -24,19 +26,20 @@ export const getReactNodeText = (node: ReactNode): string => { return ''; }; -export default function CodeBlock({ children, className, ...props }: Props) { +export default function CodeBlock({ children, className, filename, ...props }: Props) { const [wrapped, setWrapped] = useState(false); const wrapClassName = wrapped ? styles.wrapped : styles.unwrapped; return (
getReactNodeText(children)} wrapped={wrapped} onWrappedChange={setWrapped} />
Date: Sun, 30 Aug 2026 10:35:05 +0900
Subject: [PATCH 02/12] fix: update story content by removing quote section and
 adjusting heading IDs

---
 src/components/Common/Markdown/index.stories.tsx | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/src/components/Common/Markdown/index.stories.tsx b/src/components/Common/Markdown/index.stories.tsx
index 4ee667ae..def9e6f1 100644
--- a/src/components/Common/Markdown/index.stories.tsx
+++ b/src/components/Common/Markdown/index.stories.tsx
@@ -5,13 +5,11 @@ const content = `## 固定ページの見出し
 
 本文には[内部リンク](/profile)と[外部リンク](https://example.com)を含められます。
 
-### リストと引用
+### リスト
 
 - ひとつ目の項目
 - ふたつ目の項目
 
-> 引用文の表示例です。
-
 ### コード
 
 ~~~ts
@@ -30,5 +28,5 @@ export default meta;
 type Story = StoryObj;
 
 export const FixedPageContent: Story = {
-  args: { content, headingIds: ['page-heading', 'list-and-quote', 'code'] },
+  args: { content, headingIds: ['page-heading', 'list', 'code'] },
 };

From 0ac7ca4317973d4cee30b56c2a1c2aee1354c7d4 Mon Sep 17 00:00:00 2001
From: Arata 
Date: Sun, 30 Aug 2026 10:43:00 +0900
Subject: [PATCH 03/12] fix: update table header styles to use accent
 background and light text color

---
 .../Layouts/Container/FixedContentContainer/index.module.css   | 3 ++-
 .../Article/Elements/Plugins/CustomHtml/index.module.css       | 3 ++-
 .../Article/Elements/Plugins/RichText/index.module.css         | 3 ++-
 src/styles/plugin.css                                          | 1 +
 4 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/src/components/Common/Layouts/Container/FixedContentContainer/index.module.css b/src/components/Common/Layouts/Container/FixedContentContainer/index.module.css
index 5b6f8db9..a166ebf8 100644
--- a/src/components/Common/Layouts/Container/FixedContentContainer/index.module.css
+++ b/src/components/Common/Layouts/Container/FixedContentContainer/index.module.css
@@ -132,7 +132,8 @@
 }
 
 .content > table th {
-  background-color: var(--color-bg-sub);
+  background-color: var(--color-accent-soft-bg);
+  color: var(--color-theme-light-text);
   text-align: left;
   padding: 1rem;
 }
diff --git a/src/components/Features/Article/Elements/Plugins/CustomHtml/index.module.css b/src/components/Features/Article/Elements/Plugins/CustomHtml/index.module.css
index e80ebace..19340246 100644
--- a/src/components/Features/Article/Elements/Plugins/CustomHtml/index.module.css
+++ b/src/components/Features/Article/Elements/Plugins/CustomHtml/index.module.css
@@ -154,7 +154,8 @@
 }
 
 .content > table th {
-  background-color: var(--color-bg-sub);
+  background-color: var(--color-accent-soft-bg);
+  color: var(--color-theme-light-text);
   text-align: left;
   padding: 1rem;
 }
diff --git a/src/components/Features/Article/Elements/Plugins/RichText/index.module.css b/src/components/Features/Article/Elements/Plugins/RichText/index.module.css
index 473c809a..e468e931 100644
--- a/src/components/Features/Article/Elements/Plugins/RichText/index.module.css
+++ b/src/components/Features/Article/Elements/Plugins/RichText/index.module.css
@@ -147,7 +147,8 @@
 }
 
 .content > table th {
-  background-color: var(--color-bg-sub);
+  background-color: var(--color-accent-soft-bg);
+  color: var(--color-theme-light-text);
   text-align: left;
   padding: 1rem;
 }
diff --git a/src/styles/plugin.css b/src/styles/plugin.css
index e75be01f..9dd5b45e 100644
--- a/src/styles/plugin.css
+++ b/src/styles/plugin.css
@@ -36,6 +36,7 @@ table {
 table tr th {
   border: 1px solid var(--color-theme-border);
   background-color: var(--color-accent-soft-bg) !important;
+  color: var(--color-theme-light-text);
   word-wrap: break-word;
   overflow-wrap: break-word;
   white-space: normal;

From 73c258519a9cc104d2fdf6f074f76857955b8b85 Mon Sep 17 00:00:00 2001
From: Arata 
Date: Sun, 30 Aug 2026 11:02:10 +0900
Subject: [PATCH 04/12] fix: update article content to include additional
 highlighted text styles

---
 .../Article/Elements/Plugins/RichText/index.stories.tsx         | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/components/Features/Article/Elements/Plugins/RichText/index.stories.tsx b/src/components/Features/Article/Elements/Plugins/RichText/index.stories.tsx
index f0ec8ddd..9eb40784 100644
--- a/src/components/Features/Article/Elements/Plugins/RichText/index.stories.tsx
+++ b/src/components/Features/Article/Elements/Plugins/RichText/index.stories.tsx
@@ -24,7 +24,7 @@ const tableHtml = `
 `;
 
 const articleHtml = `
-  

本文には強調リンクが含まれます。

+

本文には強調青マーカー赤マーカー黄マーカーinlineCode()リンクが含まれます。

見出し2

段落の余白と行間を確認するための文章です。

見出し3

From 6f7d82533b429c8adfd33530f618fdeaf6091d40 Mon Sep 17 00:00:00 2001 From: Arata Date: Sun, 30 Aug 2026 11:06:11 +0900 Subject: [PATCH 05/12] fix: update underline_code styles for consistency with theme variables --- src/styles/plugin.css | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/styles/plugin.css b/src/styles/plugin.css index 9dd5b45e..857c91e0 100644 --- a/src/styles/plugin.css +++ b/src/styles/plugin.css @@ -12,19 +12,13 @@ } .underline_code { - background-color: #f7f7fc; + background-color: var(--color-bg-sub); border: 1px solid var(--color-theme-border); - border-radius: 3px; - color: #2b2c30; + border-radius: var(--radius-small); + color: var(--color-theme-light-text); margin: 0 2px; padding: 2px 4px; - font-family: - Menlo, - Monaco, - Consolas, - Liberation Mono, - Courier New, - monospace; + font-family: var(--font-family-content-code); } /* テーブル */ From 855bf423552c405a94a93235b81e8fda78c38fc8 Mon Sep 17 00:00:00 2001 From: Arata Date: Sun, 30 Aug 2026 11:08:28 +0900 Subject: [PATCH 06/12] fix: update table header background color for consistency across components --- .../Layouts/Container/FixedContentContainer/index.module.css | 2 +- .../Article/Elements/Plugins/CustomHtml/index.module.css | 2 +- .../Features/Article/Elements/Plugins/RichText/index.module.css | 2 +- src/styles/plugin.css | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/Common/Layouts/Container/FixedContentContainer/index.module.css b/src/components/Common/Layouts/Container/FixedContentContainer/index.module.css index a166ebf8..78051167 100644 --- a/src/components/Common/Layouts/Container/FixedContentContainer/index.module.css +++ b/src/components/Common/Layouts/Container/FixedContentContainer/index.module.css @@ -132,7 +132,7 @@ } .content > table th { - background-color: var(--color-accent-soft-bg); + background-color: var(--color-bg-sub); color: var(--color-theme-light-text); text-align: left; padding: 1rem; diff --git a/src/components/Features/Article/Elements/Plugins/CustomHtml/index.module.css b/src/components/Features/Article/Elements/Plugins/CustomHtml/index.module.css index 19340246..c0fa6fb6 100644 --- a/src/components/Features/Article/Elements/Plugins/CustomHtml/index.module.css +++ b/src/components/Features/Article/Elements/Plugins/CustomHtml/index.module.css @@ -154,7 +154,7 @@ } .content > table th { - background-color: var(--color-accent-soft-bg); + background-color: var(--color-bg-sub); color: var(--color-theme-light-text); text-align: left; padding: 1rem; diff --git a/src/components/Features/Article/Elements/Plugins/RichText/index.module.css b/src/components/Features/Article/Elements/Plugins/RichText/index.module.css index e468e931..ef91c1c3 100644 --- a/src/components/Features/Article/Elements/Plugins/RichText/index.module.css +++ b/src/components/Features/Article/Elements/Plugins/RichText/index.module.css @@ -147,7 +147,7 @@ } .content > table th { - background-color: var(--color-accent-soft-bg); + background-color: var(--color-bg-sub); color: var(--color-theme-light-text); text-align: left; padding: 1rem; diff --git a/src/styles/plugin.css b/src/styles/plugin.css index 857c91e0..e6509bda 100644 --- a/src/styles/plugin.css +++ b/src/styles/plugin.css @@ -29,7 +29,7 @@ table { table tr th { border: 1px solid var(--color-theme-border); - background-color: var(--color-accent-soft-bg) !important; + background-color: var(--color-bg-sub) !important; color: var(--color-theme-light-text); word-wrap: break-word; overflow-wrap: break-word; From b4a88fa866f36297f41b14abcae25dded5eef2e6 Mon Sep 17 00:00:00 2001 From: Arata Date: Sun, 30 Aug 2026 11:21:20 +0900 Subject: [PATCH 07/12] fix: update underline styles to use rgba colors for better consistency --- src/styles/plugin.css | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/styles/plugin.css b/src/styles/plugin.css index e6509bda..28e09424 100644 --- a/src/styles/plugin.css +++ b/src/styles/plugin.css @@ -1,14 +1,14 @@ /* マーカー */ .underline_blue { - background: linear-gradient(transparent 70%, skyblue 70%); + background: linear-gradient(transparent 70%, rgb(135 206 235 / 35%) 70%); } .underline_red { - background: linear-gradient(transparent 70%, pink 70%); + background: linear-gradient(transparent 70%, rgb(255 192 203 / 35%) 70%); } .underline_yellow { - background: linear-gradient(transparent 70%, yellow 70%); + background: linear-gradient(transparent 70%, rgb(255 255 0 / 35%) 70%); } .underline_code { From 0f1569e470edf1f0d71aace6836a01f7ff753da1 Mon Sep 17 00:00:00 2001 From: Arata Date: Sun, 30 Aug 2026 11:48:40 +0900 Subject: [PATCH 08/12] fix: update viewport settings to use iphone13promax for consistency across stories fix: adjust SpeechBubble image dimensions and styles for better layout --- .storybook/preview.tsx | 4 ++++ src/components/Common/BreadCrumb/index.stories.tsx | 2 +- src/components/Common/Layouts/Header/index.stories.tsx | 2 +- src/components/Common/TableOfContent/index.stories.tsx | 2 +- .../Article/Elements/Plugins/ImageSlider/index.stories.tsx | 4 +++- .../Article/Elements/Plugins/SpeechBubble/index.stories.tsx | 2 +- .../Features/Article/Elements/Plugins/SpeechBubble/index.tsx | 1 + .../Article/Elements/Plugins/__tests__/Plugins.test.tsx | 2 ++ src/styles/plugin.css | 5 +++++ 9 files changed, 19 insertions(+), 5 deletions(-) diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx index e8b51bf6..1eceba15 100644 --- a/.storybook/preview.tsx +++ b/.storybook/preview.tsx @@ -2,6 +2,7 @@ import type { Decorator, Preview } from '@storybook/nextjs-vite'; import { useEffect, useRef, type ReactNode } from 'react'; import { ThemeProvider, useTheme } from 'next-themes'; import { useGlobals } from 'storybook/preview-api'; +import { INITIAL_VIEWPORTS } from 'storybook/viewport'; import 'slick-carousel/slick/slick.css'; import 'slick-carousel/slick/slick-theme.css'; import '@/styles/globals.css'; @@ -87,6 +88,9 @@ const preview: Preview = { }, parameters: { layout: 'fullscreen', + viewport: { + options: INITIAL_VIEWPORTS, + }, nextjs: { appDirectory: true, navigation: { diff --git a/src/components/Common/BreadCrumb/index.stories.tsx b/src/components/Common/BreadCrumb/index.stories.tsx index 7a5f6eae..4f51cc17 100644 --- a/src/components/Common/BreadCrumb/index.stories.tsx +++ b/src/components/Common/BreadCrumb/index.stories.tsx @@ -31,5 +31,5 @@ export const LongTitle: Story = { }, }, }, - globals: { viewport: { value: 'mobile1', isRotated: false } }, + globals: { viewport: { value: 'iphone13promax', isRotated: false } }, }; diff --git a/src/components/Common/Layouts/Header/index.stories.tsx b/src/components/Common/Layouts/Header/index.stories.tsx index 965f2537..c8c5529f 100644 --- a/src/components/Common/Layouts/Header/index.stories.tsx +++ b/src/components/Common/Layouts/Header/index.stories.tsx @@ -29,7 +29,7 @@ export const Desktop: Story = { }; export const Mobile: Story = { - globals: { viewport: { value: 'mobile1', isRotated: false } }, + globals: { viewport: { value: 'iphone13promax', isRotated: false } }, play: async ({ canvas }) => { await expect(canvas.getByRole('button', { name: 'メニューを開く' })).toBeVisible(); }, diff --git a/src/components/Common/TableOfContent/index.stories.tsx b/src/components/Common/TableOfContent/index.stories.tsx index 26f10703..24db3fb6 100644 --- a/src/components/Common/TableOfContent/index.stories.tsx +++ b/src/components/Common/TableOfContent/index.stories.tsx @@ -30,5 +30,5 @@ export const DeepHierarchy: Story = { { id: 'verification', title: '動作確認で確認しておきたい長い見出し', level: 2 }, ], }, - globals: { viewport: { value: 'mobile1', isRotated: false } }, + globals: { viewport: { value: 'iphone13promax', isRotated: false } }, }; diff --git a/src/components/Features/Article/Elements/Plugins/ImageSlider/index.stories.tsx b/src/components/Features/Article/Elements/Plugins/ImageSlider/index.stories.tsx index f984a5ae..cb7a3d3d 100644 --- a/src/components/Features/Article/Elements/Plugins/ImageSlider/index.stories.tsx +++ b/src/components/Features/Article/Elements/Plugins/ImageSlider/index.stories.tsx @@ -26,7 +26,9 @@ type Story = StoryObj; export const MultipleImages: Story = {}; export const SingleImage: Story = { args: { block: { image_slider: [images[0]] } } }; -export const Mobile: Story = { globals: { viewport: { value: 'mobile1', isRotated: false } } }; +export const Mobile: Story = { + globals: { viewport: { value: 'iphone13promax', isRotated: false } }, +}; export const NextImageInteraction: Story = { play: async ({ canvasElement }) => { const canvas = within(canvasElement); diff --git a/src/components/Features/Article/Elements/Plugins/SpeechBubble/index.stories.tsx b/src/components/Features/Article/Elements/Plugins/SpeechBubble/index.stories.tsx index f2e662d6..a4a4c14c 100644 --- a/src/components/Features/Article/Elements/Plugins/SpeechBubble/index.stories.tsx +++ b/src/components/Features/Article/Elements/Plugins/SpeechBubble/index.stories.tsx @@ -25,5 +25,5 @@ export const LongText: Story = { '文章が長い場合でも、画像と吹き出しの位置関係を保ちながら自然に折り返されることを確認します。スマートフォンの画面幅でも内容がはみ出さないことが重要です。', }, }, - globals: { viewport: { value: 'mobile1', isRotated: false } }, + globals: { viewport: { value: 'iphone13promax', isRotated: false } }, }; diff --git a/src/components/Features/Article/Elements/Plugins/SpeechBubble/index.tsx b/src/components/Features/Article/Elements/Plugins/SpeechBubble/index.tsx index ff34ddff..871bbf35 100644 --- a/src/components/Features/Article/Elements/Plugins/SpeechBubble/index.tsx +++ b/src/components/Features/Article/Elements/Plugins/SpeechBubble/index.tsx @@ -15,6 +15,7 @@ export default function SpeechBubble({ block }: Props) { { const image = container.querySelector('img'); expect(image).toHaveAttribute('alt', ''); expect(image).toHaveAttribute('src', expect.stringContaining('w=150')); + expect(image).toHaveAttribute('src', expect.stringContaining('h=150')); + expect(image).toHaveAttribute('src', expect.stringContaining('fit=crop')); }); it('renders each tab box variant from its corresponding html field', () => { diff --git a/src/styles/plugin.css b/src/styles/plugin.css index 28e09424..1e3f1eeb 100644 --- a/src/styles/plugin.css +++ b/src/styles/plugin.css @@ -59,6 +59,10 @@ table tr td { } .bubble-image { + display: block; + width: 75px; + height: 75px; + object-fit: cover; border-radius: 50%; margin: 0 10px; } @@ -105,6 +109,7 @@ table tr td { .bubble-image-wrapper { display: flex; align-items: center; + flex-shrink: 0; } .bubble-image-wrapper.left { From b6efd96cebd377e931bfa725325fd5be8b86d1f2 Mon Sep 17 00:00:00 2001 From: Arata Date: Sun, 30 Aug 2026 11:55:41 +0900 Subject: [PATCH 09/12] fix: update list styles for tab boxes and add CommonList story for better presentation --- .../Elements/Plugins/TabBox/index.module.css | 24 ++++++++++++------- .../Elements/Plugins/TabBox/index.stories.tsx | 10 ++++++++ .../Article/Elements/Plugins/TabBox/index.tsx | 2 +- 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/src/components/Features/Article/Elements/Plugins/TabBox/index.module.css b/src/components/Features/Article/Elements/Plugins/TabBox/index.module.css index 466031cf..f39b3b7e 100644 --- a/src/components/Features/Article/Elements/Plugins/TabBox/index.module.css +++ b/src/components/Features/Article/Elements/Plugins/TabBox/index.module.css @@ -9,7 +9,8 @@ .tab_merit_box ul { list-style: disc; - margin-left: 50px; + margin-left: 0; + padding-left: 1.25rem; } .tab_merit_box_icon { @@ -28,7 +29,8 @@ .tab_demerit_box ul { list-style: disc; - margin-left: 50px; + margin-left: 0; + padding-left: 1.25rem; } .tab_demerit_box_icon { @@ -47,7 +49,8 @@ .tab_point_box ul { list-style: disc; - margin-left: 50px; + margin-left: 0; + padding-left: 1.25rem; } .tab_point_box_icon { @@ -66,7 +69,8 @@ .tab_common_box ul { list-style: disc; - margin-left: 50px; + margin-left: 0; + padding-left: 1.25rem; } .tab_common_box_icon { @@ -86,7 +90,8 @@ .tab_merit_box ul { list-style: disc; - margin-left: 25px; + margin-left: 0; + padding-left: 1.25rem; } .tab_merit_box_icon { @@ -105,7 +110,8 @@ .tab_demerit_box ul { list-style: disc; - margin-left: 25px; + margin-left: 0; + padding-left: 1.25rem; } .tab_demerit_box_icon { @@ -124,7 +130,8 @@ .tab_point_box ul { list-style: disc; - margin-left: 25px; + margin-left: 0; + padding-left: 1.25rem; } .tab_point_box_icon { @@ -143,7 +150,8 @@ .tab_common_box ul { list-style: disc; - margin-left: 25px; + margin-left: 0; + padding-left: 1.25rem; } .tab_common_box_icon { diff --git a/src/components/Features/Article/Elements/Plugins/TabBox/index.stories.tsx b/src/components/Features/Article/Elements/Plugins/TabBox/index.stories.tsx index bbe14644..200d01c9 100644 --- a/src/components/Features/Article/Elements/Plugins/TabBox/index.stories.tsx +++ b/src/components/Features/Article/Elements/Plugins/TabBox/index.stories.tsx @@ -20,3 +20,13 @@ export const Merit: Story = { args: { merit: true } }; export const Demerit: Story = { args: { demerit: true } }; export const Point: Story = { args: { point: true } }; export const Common: Story = { args: { common: true } }; +export const CommonList: Story = { + args: { + block: { + ...block, + box_common: + '
  • 対象となる利用環境を確認する
  • 必要な設定を済ませる
  • 表示と動作を確認する
', + }, + common: true, + }, +}; diff --git a/src/components/Features/Article/Elements/Plugins/TabBox/index.tsx b/src/components/Features/Article/Elements/Plugins/TabBox/index.tsx index cd49ce94..10b15269 100644 --- a/src/components/Features/Article/Elements/Plugins/TabBox/index.tsx +++ b/src/components/Features/Article/Elements/Plugins/TabBox/index.tsx @@ -36,7 +36,7 @@ export default function TabBox({ return ( <>
{merit && ( <> From ad29a670e9bab5418b3135a67d6bdecfbc6f2065 Mon Sep 17 00:00:00 2001 From: Arata Date: Sun, 30 Aug 2026 12:41:21 +0900 Subject: [PATCH 10/12] fix: remove play function from Default story in ThemeSwitch component --- .../Common/Layouts/ThemeSwitch/index.stories.tsx | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/src/components/Common/Layouts/ThemeSwitch/index.stories.tsx b/src/components/Common/Layouts/ThemeSwitch/index.stories.tsx index 2a790d24..dbbc64b6 100644 --- a/src/components/Common/Layouts/ThemeSwitch/index.stories.tsx +++ b/src/components/Common/Layouts/ThemeSwitch/index.stories.tsx @@ -1,5 +1,4 @@ import type { Meta, StoryObj } from '@storybook/nextjs-vite'; -import { expect, userEvent } from 'storybook/test'; import ThemeSwitch from '.'; const meta = { @@ -11,16 +10,4 @@ const meta = { export default meta; type Story = StoryObj; -export const Default: Story = { - play: async ({ canvas }) => { - const switchToDarkButton = await canvas.findByRole('button', { - name: 'ダークテーマに切り替え', - }); - - await userEvent.click(switchToDarkButton); - - await expect( - canvas.getByRole('button', { name: 'ライトテーマに切り替え' }), - ).toBeInTheDocument(); - }, -}; +export const Default: Story = {}; From 58388413a03e3a3f79d4516294fed291abfb5f08 Mon Sep 17 00:00:00 2001 From: Arata Date: Sun, 30 Aug 2026 12:44:23 +0900 Subject: [PATCH 11/12] fix: add decorators to Sidebar story for improved layout presentation --- .../Common/TableOfContent/index.stories.tsx | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/components/Common/TableOfContent/index.stories.tsx b/src/components/Common/TableOfContent/index.stories.tsx index 24db3fb6..6caca455 100644 --- a/src/components/Common/TableOfContent/index.stories.tsx +++ b/src/components/Common/TableOfContent/index.stories.tsx @@ -19,7 +19,16 @@ type Story = StoryObj; export const Default: Story = { args: { headings } }; -export const Sidebar: Story = { args: { headings, sidebar: true } }; +export const Sidebar: Story = { + args: { headings, sidebar: true }, + decorators: [ + (Story) => ( +
+ +
+ ), + ], +}; export const DeepHierarchy: Story = { args: { From 03c7dc0bcece7a69cba3c40542cfe48c772acd57 Mon Sep 17 00:00:00 2001 From: Arata1202 Date: Sun, 30 Aug 2026 13:10:57 +0900 Subject: [PATCH 12/12] fix: show focus indicator for embedded frames --- .../Plugins/CustomHtml/index.module.css | 5 ++++ .../Elements/Plugins/CustomHtml/index.tsx | 25 +++++++++++++++++++ .../Plugins/__tests__/Plugins.test.tsx | 15 +++++++++++ vitest.config.mts | 2 +- 4 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src/components/Features/Article/Elements/Plugins/CustomHtml/index.module.css b/src/components/Features/Article/Elements/Plugins/CustomHtml/index.module.css index c0fa6fb6..715b6895 100644 --- a/src/components/Features/Article/Elements/Plugins/CustomHtml/index.module.css +++ b/src/components/Features/Article/Elements/Plugins/CustomHtml/index.module.css @@ -123,6 +123,11 @@ outline-offset: var(--focus-ring-offset); } +.content iframe[data-focus-visible='true'] { + outline: var(--focus-ring-width) solid var(--color-focus-ring) !important; + outline-offset: var(--focus-ring-offset); +} + .content > figure { margin: 2rem 0; } diff --git a/src/components/Features/Article/Elements/Plugins/CustomHtml/index.tsx b/src/components/Features/Article/Elements/Plugins/CustomHtml/index.tsx index 24befaaf..43af2495 100644 --- a/src/components/Features/Article/Elements/Plugins/CustomHtml/index.tsx +++ b/src/components/Features/Article/Elements/Plugins/CustomHtml/index.tsx @@ -43,6 +43,27 @@ function CustomHtml({ html, sponsorUrl }: Props) { const cleanupMoshimoEasyLinkFallback = setupMoshimoEasyLinkFallback(content); + let iframeFocusFrame: number | undefined; + const clearIframeFocus = () => { + content.querySelectorAll('iframe[data-focus-visible]').forEach((iframe) => { + iframe.removeAttribute('data-focus-visible'); + }); + }; + const syncIframeFocus = () => { + window.cancelAnimationFrame(iframeFocusFrame ?? 0); + iframeFocusFrame = window.requestAnimationFrame(() => { + clearIframeFocus(); + const activeElement = document.activeElement; + + if (activeElement instanceof HTMLIFrameElement && content.contains(activeElement)) { + activeElement.dataset.focusVisible = 'true'; + } + }); + }; + + window.addEventListener('blur', syncIframeFocus); + window.addEventListener('focus', clearIframeFocus); + const observer = new MutationObserver(() => { syncCustomHtmlEnhancements(); }); @@ -61,6 +82,10 @@ function CustomHtml({ html, sponsorUrl }: Props) { return () => { cleanupMoshimoEasyLinkFallback(); + window.cancelAnimationFrame(iframeFocusFrame ?? 0); + window.removeEventListener('blur', syncIframeFocus); + window.removeEventListener('focus', clearIframeFocus); + clearIframeFocus(); observer.disconnect(); window.clearTimeout(timer); }; diff --git a/src/components/Features/Article/Elements/Plugins/__tests__/Plugins.test.tsx b/src/components/Features/Article/Elements/Plugins/__tests__/Plugins.test.tsx index 6275379b..d4802a89 100644 --- a/src/components/Features/Article/Elements/Plugins/__tests__/Plugins.test.tsx +++ b/src/components/Features/Article/Elements/Plugins/__tests__/Plugins.test.tsx @@ -141,6 +141,21 @@ describe('Article plugins', () => { ).toHaveAttribute('aria-pressed', 'false'); }); + it('marks a focused custom html iframe for a visible focus indicator', async () => { + renderCustomHtml(''); + + const iframe = screen.getByTitle('Embedded content'); + iframe.focus(); + fireEvent.blur(window); + + await waitFor(() => { + expect(iframe).toHaveAttribute('data-focus-visible', 'true'); + }); + + fireEvent.focus(window); + expect(iframe).not.toHaveAttribute('data-focus-visible'); + }); + it('renders rich text and injects article ad units before h2 sections', () => { render( { }, }, optimizeDeps: { - include: ['react-slick'], + include: ['react-slick', 'storybook/viewport'], }, test: { projects: [