O hirunewani blog

Frontend Weekly 2024-08-02

Created at

Chrome 127のfont-size-adjust、Storybook 8.2のPortable stories、TutorialKitなどを紹介する。

Chrome 127

2024年7月24日にChrome 127がリリースされた。

https://developer.chrome.com/blog/new-in-chrome-127

CSS font-size-adjust

CSSのfont-size-adjustプロパティがサポートされた。 これに伴い、font-size-adjustプロパティはBaselineに追加された。

フォントは、アスペクト比によって同じfont-sizeであっても、大きく異なる印象を与える。 ここで、アスペクト比とは、小文字の高さをフォントサイズで割った値である。

Text using 14px Verdana font appears larger than text using Times font.

Text using 14px Times font appears smaller than text using Verdana font.

font-size-adjustプロパティは、このフォントのアスペクト比を調整するために使用される。

次のように利用する。

.font-a {
  font-size: 14px;
  font-family: Verdana;
  font-size-adjust: 0.545;
}
.font-b {
  font-size: 14px;
  font-family: Times;
  font-size-adjust: 0.545;
}

Text using 14px Verdana font appears larger than text using Times font.

Text using 14px Times font appears smaller than text using Verdana font.

CSS content with alt text

contentプロパティを利用して画像を表示する際に、画像の代替テキストを指定できるようになった。

<style>
  .has-before-content::before {
    content: url("cat.jpg") / "A cute" attr(data-animal);
  }
</style>
<div class="has-before-content" data-animal="cat"></div>

Keyboard focusable scroll containers

スクロールコンテナにキーボードでフォーカスするようになる。 以前でもtabindexを0以上に設定するか、スクロールコンテナ内にフォーカス可能な子要素がある場合、スクロールコンテナにフォーカスできたが、今後はどちらでもない場合でもフォーカスされる。

start content

end content

この挙動はChrome 127以降、徐々に展開されていく。

同意書などをスクロールコンテナ内に表示するサービスでは、開発者が十分にアクセシビリティに配慮していない場合、キーボードのみによる操作が困難であった。しかし、今後は開発者が意識しなくても、スクロールコンテナにフォーカスが当たるため、アクセシビリティが向上する。

Storybook 8.2

Storybook 8.2がリリースされた。テスト機能の改善や、ポータブルストーリーの正式なサポートなどが行われた。 またStorybook 8.3では、Vitestとの統合や互換性の向上が予定されている。

https://storybook.js.org/blog/storybook-8-2/

Portable stories

ポータブルストーリーを介することで、StoryをネイティブコンポーネントとしてJestやVitest、Playwrightなどで再利用が出来るようになった。

// Button.test.js
import { test, expect } from "vitest";
import { screen } from "@testing-library/react";
import { composeStories } from "@storybook/react";
import * as stories from "./Button.stories";

const { Primary, Secondary } = composeStories(stories);

test("renders primary button with default args", async () => {
  await Primary.play();
});

VitestやJestでポータブルストーリーを利用する方法についてドキュメントが公開されている。

https://storybook.js.org/docs/api/portable-stories/portable-stories-jest?ref=storybookblog.ghost.io

https://storybook.js.org/docs/api/portable-stories/portable-stories-vitest?ref=storybookblog.ghost.io

Storybookにテストの責務を持たせたくない場合や、VitestやJestの資産を利用したい場合など、非常に便利な機能である。

New test hooks

JestやVitest、Playwright、Cypressなどとより互換性のあるテストの記述が可能になった。

今まではcanvasオブジェクトを通してのみStoryのテストが可能であったが、mountメソッドが追加され他のテストフレームワークと比較的近い記述が出来るようになった。

// example.stories.tsx
import { fn, expect } from "@storybook/test";
// ...
export const Disabled = {
  args: { disabled: true, onSelected: fn() },
  play: async ({ mount, args }) => {
    // Arrange
    const user = useEvent.setup();
    const items = await loadItems(10);
    const canvas = await mount(<ToolbarMenu items={items} />);

    // Act
    await user.click(canvas.getByRole("button"));

    // Assert
    expect(canvas.getAllByRole("button").length).toBe(items.length);
    expect(args.onSelected).not.toHaveBeenCalled();
  },
};

beforeEachafterEachなどは、Storyファイルのmetaに記述する。

// example.stories.tsx
const meta = {
  // ...
  async beforeEach() {
    MockDate.set("2024-02-14");

    // Reset the Date after each story
    return () => {
      MockDate.reset();
    };
  },
};

beforeAllafterAllは、.storybook/preview.tsに記述する。

// .storybook/preview.ts
import { Preview } from "@storybook/react";

import { init } from "../project-bootstrap";

const preview: Preview = {
  async beforeAll() {
    await init();
  },
};

export default preview;

https://storybook.js.org/docs/writing-tests/interaction-testing?ref=storybookblog.ghost.io#run-code-before-the-component-gets-rendered

個人的な感想としては、確かに名前が同じフックは生えたが、利用方法にはズレがあり、テストをCSFに変換するための学習曲線は変わらずあるように思う。

Announcing TutorialKit

TutorialKitのアナウンスが行われた。TutorialKitはJavaScriptコミュニティ向けのインタラクティブなチュートリアルを作ることが出来るWeb Containerベースのツールキットである。

https://blog.stackblitz.com/posts/announcing-tutorialkit/

商用利用ではライセンスが必要だが、オープンソースでは無償で利用できる。

次のコマンドでテンプレートを作成できる。

npm create tutorial

How to choose the best rendering strategy for your app

Next.jsにおける最適なレンダリング戦略(SSG、ISR、SSR、CSR、PPR)の選び方をVercelが解説している。

https://vercel.com/blog/how-to-choose-the-best-rendering-strategy-for-your-app

最も重要なことは、アプリケーションのユースケースに合わせて適切なレンダリング戦略を”組み合わせて”利用することである。

図や動画を交えて、それぞれのレンダリング戦略の特徴や適用例をかなり分かりやすく紹介している。

ただ長いコンテンツを読むのが面倒な場合は、現実のプロダクトでどこにどのレンダリング戦略を適用するかを書いた Real-world product rendering strategiesだけでも読んでおくと、イメージがしやすくて良いと思う。

tsconfig.json の include オプションには何を指定すべきか

TypeScriptのプロジェクトで tsconfig.json を設定する際、include オプションにはsrc/index.ts, src/**/*, **/*,srcなど、どのように指定するべきかについて解説している。

https://www.mizdra.net/entry/2024/07/27/193815

次の指定をオススメしつつ、src/index.tsのような指定はやめるように促している。

  • src/**/*またはsrcsrcディレクトリ配下をターゲットとする
  • **/*または指定なし:全てのファイルをターゲットとする

What we got wrong about HTTP imports - Deno

Denoの開発者であるRyan Dahlが、HTTP Importsについて問題を指摘した上で、それらの問題に対処するためインポートマップやJSRを導入したという話。

https://deno.com/blog/http-imports

Albert Einsteinの言葉「Everything should be made as simple as possible, but not simpler.」を引用している。

Get the screen width & height without JavaScript

CSSのみでスクリーンの幅と高さを取得する方法について解説している。

https://css-tip.com/screen-dimension/

tan(atan2(var(--_w),1px))を利用することで、vwvh単位の値をpx単位に変換している。

:root {
  --w: tan(atan2(var(--_w),1px));
  --h: tan(atan2(var(--_h),1px));
}

How to Get the Width/Height of Any Element in Only CSS

CSSのみで任意の要素の幅と高さを取得する方法について解説している。

https://frontendmasters.com/blog/how-to-get-the-width-height-of-any-element-in-only-css/

Scroll-driven Animationsを利用することで、要素の幅と高さを取得している。