$30 off During Our Annual Pro Sale. View Details »

ピクシブのデザインシステム「Charcoal」アイコンライブラリをつくる

mimo
September 29, 2023
470

 ピクシブのデザインシステム「Charcoal」アイコンライブラリをつくる

mimo

September 29, 2023
Tweet

Transcript

  1. pixiv.inc
    ピクシブのデザインシステム「Charcoal」
    アイコンライブラリを
    つくる
    @mi2_okmt

    View Slide

  2. Profile
    mimo
    フロントエンドエンジニア
    2022年 新卒入社
    CTO室デザインシステム部
    兼 クリエイター事業部 FACTORY部
    初音ミクが好き DJする趣味がある

    View Slide

  3. しゃべること
    ● Charcoalとは?
    ● charcoal-ui/iconsとは?
    ● charcoal-ui/iconsをつくる
    ● SVGのimportについて

    View Slide

  4. とは?

    View Slide

  5. とは?
    ● pixivをはじめ、様々なプロダクトが利用
    ● web / iOS / Android それぞれに対応した実装がある
    ● 2022年7月からはデザインシステム部が開発してる
    ○ DEV MEETUP(2020) のときはタスクフォースだった
    ○ 部外からもドカドカPRをくれるのでレビューしてる
    ピクシブのデザインシステム「Charcoal」

    View Slide

  6. ● 10個のパッケージを持つweb実装のモノレポ
    ● @charcoal-ui/styled, /tailwind-config, /react …などなど
    ● 今回は @charcoal-ui/icons について話します
    web実装 pixiv/charcoal
    とは?

    View Slide

  7. @charcoal-ui/icons

    View Slide

  8. @charcoal-ui/icons
    ● Web Componentsとして実装
    ○ 他フレームワークへの依存なしで利用可能
    ○ Charcoalの他パッケージへの依存もほとんどない
    ● SVGファイルを独自アイコンとして登録できる
    Charcoalのアイコンライブラリ

    View Slide

  9. @charcoal-ui/icons
    1. yarn add @charcoal-ui/icons
    2. import ‘@charcoal-ui/icons’
    3.
    簡単 3ステップ クイックスタート!

    View Slide

  10. @charcoal-ui/icons
    パッケージの構造
    Figma
    SVG stringをexportする
    JSのパッケージ
    @charcoal-ui/icon-files
    .cjs
    SVGを
    Custom Elementsにする
    @charcoal-ui/icons
    jsでimport
    @charcoal-ui
    /icons-cli

    View Slide

  11. @charcoal-ui/icons
    ● Figma APIからSVGとしてアイコンを取得
    ● fill属性を currentcolor に置き換える
    ● SVGをstringでexportするファイルをつくる
    ● /icon-files に差分があれば commit して PR をつくる
    Figmaのアイコンを取ってくる icons-cli

    View Slide

  12. @charcoal-ui/icons
    ● icons-cli によって作られる.cjsファイルのパッケージ
    ● export default '● どうしてこうなったのかはあとで話します
    SVGタグをstringで返す icon-files

    View Slide

  13. @charcoal-ui/icons
    ● icon-filesに依存 SVG文字列をCustom Elementsにする
    ● 指定されたSVGファイルをアイコンにする
    ○ icon-files にないアイコンを使いたい需要に対応
    ○ PixivIcon.extend()
    Custom Elementsをつくる icons

    View Slide

  14. どうして
    Web Components?

    View Slide

  15. どうしてWeb Components?
    ● 2021年2月としては珍しい技術選択
    ● ピクシブに求められる要件がいくつかあった
    @charcoal-ui/iconsはWeb Components

    View Slide

  16. どうしてWeb Components?
    ● プロダクトごとに異なるフレームワーク
    ○ Smarty ERB React Vue …
    ● 導入がスムーズに行えること
    ● SSRできる
    ● 検討したがボツになったものを具体的に紹介します
    ピクシブでの要件

    View Slide

  17. @charcoal-ui/icons
    ボツ案

    View Slide

  18. @charcoal-ui/icons ボツ案
    1. Reactでつくる
    2. icon font
    3. SVGR
    ボツ案一覧
    4. SVGのuseタグ
    5. Lit HTML

    View Slide

  19. @charcoal-ui/icons ボツ案
    × Reactでしか使えない
    ピクシブにはVueプロダクトもある (BOOTH pixivのSP版 …など)
    × ReactプロダクトでもReactだけを使うとは限らない
    局所的にSmartyやERBをなこともある
    1. Reactでつくる

    View Slide

  20. @charcoal-ui/icons ボツ案
    × フォントをつくるのがめんどくさい
    × font familyの上書きで変な文字が出る
    × スクリーンリーダーやa11yに弱い
    タグなどを本来と異なる用途で使うため
    2. icon font

    View Slide

  21. @charcoal-ui/icons ボツ案
    SVGR: SVGをimportするとReactコンポーネントになるもの
    × inline SVGになって、HTMLが巨大になるおそれ
    JSXからのimportでHTMLが巨大になるリスクが指摘されていた
    × React前提になる
    3. SVGRのようなアプローチ

    View Slide

  22. @charcoal-ui/icons ボツ案
    id のついているSVG要素を useタグで呼び出せる
    × どうやってアイコンファイルを配信するか不明
    SVGアイコン全部入りファイルを読み込ませる必要がありそう
    × ロード時間や維持管理が厳しそう
    4. SVGのuseタグ

    View Slide

  23. @charcoal-ui/icons ボツ案
    Web Componentsが作れる薄めなライブラリ
    ✓ いったん採用した
    × SSR対応のとき、Lit HTMLが嫌な実装だったので結局やめた
    5. Lit HTML

    View Slide

  24. @charcoal-ui/icons ボツ案
    × 内部でDOM APIをめっちゃさわる
    × SSRができない nodeでimportするとクラッシュした
    × lit-labs/ssr があったが嫌な実装だった
    globalThisにDOM APIを生やすような感じ
    ここがいい感じだったら採用していたかもしれない...
    5. Lit HTML

    View Slide

  25. そして
    Web Components へ

    View Slide

  26. そして Web Components へ
    ✓ 使うアイコンだけ読み込ませられる
    ✓ 特定のフレームワークに依存させることなく実装できる
    ✓ 無理のない実装方法である
    ion-icon も Web Componentsだった
    SVGファイルをDOMにレンダリング

    View Slide

  27. そして Web Components へ
    ● 当時「Vue 3でWeb Components対応」と言われていた
    ● SSR対応のCustom Elementsの参考に実装
    ● globalThis に頼った箇所がひとつだけ残った
    ○ HTMLElementsがSSRでundefinedになるのを回避させる部分
    SSRでも動くコードで実装

    View Slide

  28. できあがった
    @charcoal-ui/icons

    View Slide

  29. できあがった @charcoal-ui/icons
    👍 dependenciesがたった2つになった
    DOMPurifyとwarningsのみ
    👍 最新でも、レガシーでも、CSRでも、SSRでも使える
    tailwindもstyledもReactもVueもいらない!
    👍 社内プロダクトへの導入がスムーズだった
    良かったこと

    View Slide

  30. できあがった @charcoal-ui/icons
    🥳< 属人化していて更新しづらくて不幸になってました。
    ツールでサポートされたので属人性も手間もなくなり、
    工数削減だけでなく参入もしやすくなりました。
    喜びの声

    View Slide

  31. 🤔 PixivIcon.extends() を使うときはバンドラの設定が必要
    独自アイコンを使うなら各自でバンドラを設定してね!
    🤔 a11yが不十分 もし対応不可能なことがあるとマズい
    🤔 レイアウトシフトが起こりやすい
    ドキュメントにリセットCSSを載せてるだけなのでパッケージに含めたい...
    残された課題・デメリット
    できあがった @charcoal-ui/icons

    View Slide

  32. SVGのimport

    View Slide

  33. SVGのimport
    おさらい
    Figma
    SVG stringをexportする
    JSのパッケージ
    @charcoal-ui/icon-files
    .cjs
    SVGを
    Custom Elementsにする
    @charcoal-ui/icons
    jsでimport
    @charcoal-ui
    /icons-cli

    View Slide

  34. SVGのimport
    おさらい
    Figma
    SVG stringをexport
    するJSのパッケージ
    @charcoal-ui/icon-files
    .cjs
    SVGを
    Custom Elementsにする
    @charcoal-ui/icons
    jsでimport
    @charcoal-ui
    /icons-cli

    View Slide

  35. SVGのimport
    ● 最近はwebpack以外のバンドラが増えた
    ○ vite swc Parcel …
    ● /icons は webpack 環境下でしか動かなかった
    ● 社内から webpack 以外でも動いてほしいとの要望が来た
    webpackが必須だった /icons v1.x.x

    View Slide

  36. SVGのimport
    ● 「.jsではないものを相対パスで読み込む」に差が出やすい
    なぜ webpack でしか動かなかったのか
    const { default: filepath } = await import(
    `../svg/${encodeURIComponent(size)}/
    ${encodeURIComponent(name)}.svg`
    )
    ● jsに従って文字列を扱えば解決するのでは?

    View Slide

  37. SVGのimport
    ● CIでやることを追加
    ○ icons-cli で SVGを取ってきてSVGファイルをつくる
    ○ + SVGファイル → string を export する .cjs ファイル
    ○ + 保存する場所を /icon-files に変更
    ○ つくったファイルをまとめてcommit
    v2.x.x から増えた /icon-files

    View Slide

  38. SVGのimport
    ● アイコンの import する処理を分離
    ○ SVG string 用の関数を用意
    ○ 独自アイコン用に dynamic import する処理も残す
    ■ PixivIcon.extends()にバンドラ設定が必要なのはこのため
    /icons の SVG import 改修

    View Slide

  39. SVGのimport
    // v1.x.x
    const { default: filepath } = await import(
    `../svg/${encodeURIComponent(size)}/
    ${encodeURIComponent(name)}.svg`
    )
    // v2.x.x
    import charcoalIconFiles from ‘@charcoal-ui/icon-files’
    get importIconFile() {
    return charcoalIconFiles[this._name]
    }

    View Slide

  40. 今後の話

    View Slide

  41. 今後の話
    ● webpack以外でも使えることを確認すべき
    ● 依存ライブラリのバージョンアップの影響もうける
    ○ /icons だけは依存ライブラリの影響は少ない
    ○ 他パッケージは peer dependenciesが多い
    ■ /react /tailwind-config /styled …
    動作環境、依存ライブラリはどんどん変わる

    View Slide

  42. 今後の話
    ● /icons は a11y やパフォーマンスの課題を抱えている
    ● Charcoalは品質をあげるステップに入った
    ○ より安定、よりハイパフォーマンスであるべき
    ● Charcoalのぜんぶで頑張っている最中
    ● キリがないのであとでとっ捕まえて聞いてください
    デザイナーやiOSエンジニアも捕えておきます

    View Slide

  43. 宣伝
    ● Charcoalのセッションは他にもあります!
    ○ SUB STAGE: cilvia「BOOTHにおけるCharcoal実践活用術」
    現場で実際に行われているテーマのカスタムなどの話が聞けそうです
    ○ SUB STAGE: ああうえ「Charcoalをモバイルアプリで使う」
    CharcoalのiOS開発メンバーの発表です
    ● 懇親会パートでmimoはDJをします

    View Slide