Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Spindle UIのつくりかた / Spindle UI: From Concept to ...

Ameba Spindle
August 30, 2023

Spindle UIのつくりかた / Spindle UI: From Concept to Creation

Ameba Spindle

August 30, 2023
Tweet

More Decks by Ameba Spindle

Other Decks in Design

Transcript

  1. 概要 Amebaの開発での利用実績を踏まえ、以下の点を考慮してライブラ リを提供します。 • Reactコンポーネントの提供: Amebaで最も利用されているUIライブラリの Reactで作られたミニマムなコンポーネントを提供します • スタイルが定義されたCSSの提供: UIライブラリを使用しないLPなどのプ

    ロジェクトにCSSで表現できる範囲の振る舞いを提供します • UIコンポーネントカタログ中心の開発: 作られたコンポーネントはすぐ にテストされ、表示を確認します • 管理されたファイルサイズ: 共通処理が集まるため、大きくなりがちなUIラ イブラリのファイルサイズが規定を超さないようにします
  2. デザイントークン • Surface Secondary (背景色) • Text Accent Primary (リンク色)

    • Text Low Emphasis (現在地テキスト色) • Object Low Emphasis (矢印の色) • Focus Clarity (フォーカスリングの色)
  3. プロパティ type Props { children?: React.ReactNode; variant?: 'standard' | 'emphasized';

    wrap?: 'wrap'; // 画面幅に入り切らなくなったタイミングで折り返して表示します }
  4. • 現在位置を確認できる[SHOULD] ◦ 現在位置は aria-current="page" を付与している • HTMLの要素や属性を正しい役割で使用する[MUST] ◦ パンくずリストのnav要素に

    aria-label="パンくずリス ト"、現在位置には aria-current="page" を付与してい る ◦ スクリーンリーダーでも機能落ちがなく、読み上げが過 不足なく行われている
  5. cd packages/spindle-ui yarn generate ? Please select a document. (Use

    arrow keys) ❯ component ? Please select the output destination directory. (Use arrow keys or type to search) ❯ src/ ? Please enter a component name. Breadcrumb
  6. cd packages/spindle-ui yarn generate ? Please select a document. (Use

    arrow keys) ❯ component ? Please select the output destination directory. (Use arrow keys or type to search) ❯ src/ ? Please enter a component name. Breadcrumb 🐶 Generated 7 files! ✔ src/Breadcrumb/index.ts ✔ src/Breadcrumb/Breadcrumb.tsx ✔ src/Breadcrumb/Breadcrumb.css ✔ src/Breadcrumb/Breadcrumb.stories.mdx ✔ src/Breadcrumb/Breadcrumb.test.mdx ✔ src/index.ts ✔ src/index.css
  7. /* src/Breadcrumb/Breadcrumb.tsx */ import React from 'react'; type Props =

    {}; const BLOCK_NAME = 'spui-Breadcrumb'; export const Breadcrumb: React.FC<Props> = ({}) => { return ( <div className={BLOCK_NAME}></div> ); };
  8. /* src/Breadcrumb/Breadcrumb.tsx */ import React from 'react'; type Props =

    { variant: 'standard' | 'emphasized' }; const BLOCK_NAME = 'spui-Breadcrumb'; export const Breadcrumb: React.FC<Props> = ({ variant = 'standard' }) => { return ( <nav aria-label="パンくずリスト" className={`${BLOCK_NAME} ${BLOCK_NAME}--${variant}`}} >{...}</nav> ); };
  9. /* src/Breadcrumb/Breadcrumb.tsx */ import React from 'react'; type Props =

    { variant: 'standard' | 'emphasized' }; const BLOCK_NAME = 'spui-Breadcrumb'; export const Breadcrumb: React.FC<Props> = ({ variant = 'standard' }) => { return ( <nav aria-label="パンくずリスト" className={`${BLOCK_NAME} ${BLOCK_NAME}--${variant}`}} >{...}</nav> ); };
  10. /* src/Breadcrumb/Breadcrumb.css */ .spui-Breadcrumb { overflow: auto hidden; } .spui-Breadcrumb--wrap

    { overflow: hidden; } … .spui-Breadcrumb--emphasized { background-color: var(--color-surface-secondary); } … .spui-Breadcrumb a:not([aria-current]) { color: var(--color-text-accent-primary); font-weight: bold; } .spui-Breadcrumb a[aria-current] { color: var(--color-text-low-emphasis); font-weight: normal; } デザイントークンは spindle-tokens.css で定義されています
  11. # Breadcrumb <Meta title="Breadcrumb" component={Breadcrumb} /> ## Variant ### Standard

    <Preview withSource="open"> <Story name="Standard"> <BreadcrumbList variant="standard"> <BreadcrumbItem href="#" current>Amebaとは</BreadcrumbItem> </Button> </Story> </Preview> Standard Variantはタップエリアを確保する目的でテキストに余白が指定されています。ページ内での左端 を揃えたい場合には、個別に余白を指定しBreadcrumb要素の位置を調整してください。 Storyは Docs, VRT用途 でも使います
  12. import React from 'react'; import { render, screen } from

    '@testing-library/react'; import { BreadcrumbList, BreadcrumbItem } from './Breadcrumb; describe('<Breadcrumb />', () => { test('having aria attributes', async () => { render( <BreadcrumbList> <BreadcrumbItem href="/about" current>Amebaとは</BreadcrumbItem> </BreadcrumbList> ); expect(screen.getByRole('navigation').getAttribute('aria-label')).toEqual( 'パンくずリスト', ); }); }); できるだけ 自動的に テストします