Slide 1

Slide 1 text

Generate React Component with TypeScript AST 2021.11.18

Slide 2

Slide 2 text

About me - Twitter/GitHub: @Quramy - ϦΫϧʔτͰWebϑϩϯτΤϯδχΞ΍ͬͯ·͢ - ࠓ೥ͷ7݄ࠒ͔ΒελσΟαϓϦͷ࢓ࣄΛ͢ΔΑ͏ ʹͳΓ·ͨ͠

Slide 3

Slide 3 text

ݸਓతͳ OSS works - storycap reg-suit: StorybookΛ༻͍ͨVisual Regression Testing πʔϧ܈ - tsuquyomi: TypeScript Language Server ͷ Vim client - ts-graphql-plugin: TypeScript Client ޲͚ͷGraphQL ։ൃ༷πʔϧ܈ - typed-css-modules: CSS Modules Λ TypeScriptͰѻ͏ͨΊͷϢʔςΟϦςΟ

Slide 4

Slide 4 text

ݸਓతͳ OSS works - storycap reg-suit: StorybookΛ༻͍ͨVisual Regression Testing πʔϧ܈ - tsuquyomi: TypeScript Language Server ͷ Vim client - ts-graphql-plugin: TypeScript Client ޲͚ͷGraphQL ։ൃ༷πʔϧ܈ - typed-css-modules: CSS Modules Λ TypeScriptͰѻ͏ͨΊͷϢʔςΟϦςΟ ஌ࣝɾڵຯ͕UTʹภ͍ͬͯΔ

Slide 5

Slide 5 text

ࠓ೔࿩͢͜ͱ - ࠓ೔΋ࠓ೔ͱͯ TypeScript ͷ࿩ - QuramyࢀըதͷελσΟαϓϦϓϩδΣΫτ: Next.js + TypeScript + GraphQL ͳ ΞϓϦέʔγϣϯ ※ Web෦෼ʹݶΔ. ผ్ωΠςΟϒApp΋͋Δ - ϓϩδΣΫτͰ࣮ࢪ͍ͯ͠Δ Figma -> React Component (TSX) ͷࣗ ಈੜ੒෦෼ʹ͍ͭͯ঺հ

Slide 6

Slide 6 text

Agenda 1. σβΠϯγεςϜͱ Iconography Token 2. Iconography React Component ͷࣗಈੜ੒

Slide 7

Slide 7 text

Agenda 1. σβΠϯγεςϜͱ Iconography Token 2. Iconography React Component ͷࣗಈੜ੒

Slide 8

Slide 8 text

σβΠϯγεςϜ - ݱࡏࢀը͍ͯ͠ΔϓϩδΣΫτͷσβΠϯγεςϜͷಛ௃ - Designer ͕ Figma Ͱ؅ཧ ※ Figma ʹରԠ͢Δ࣮૷ʹ͍ͭͯ͸ Web Devs / Native app Devs ͷ੹຿ - ίϯϙʔωϯτࢤ޲ - Atomic Design ϕʔε

Slide 9

Slide 9 text

“Extended” Atomic Design https://bradfrost.com/blog/post/extending-atomic-design/

Slide 10

Slide 10 text

Design Token ͱ͸ - ͦΕࣗ਎͸UIཁૉʹͳΓ͑ͳ͍͕ɺͦΕͳͯ͘͠σβΠϯγεςϜΛ࣮ ݱͰ͖ͳ͍ߏ੒෺ͷ͜ͱ - e.g. ৭ม਺΍λΠϙάϥϑΟͳͲ - Extended Atomic Design Ͱ͸ Atoms ΑΓ΋ͳ͓ԼҐͷଘࡏ - (༨ஊ) ߏจղੳͰ΋ʮ͜ΕҎ্෼ղෆՄೳͳจࣈྻʯͱ͍͏ҙຯͰ token ͱ͍͏ݴ༿͕Ͱͯ͘Δ

Slide 11

Slide 11 text

Design Tokenͷҙٛ - Token ͸ϓϥοτϑΥʔϜʹґଘ͠ͳ͍ ϓϩμΫτσβΠϯͷࠜݩ - TokenΛϓϥοτϑΥʔϜݻ༗ͷݴޠ (React ΍ Kotlin) ʹ຋༁ɾม׵ͯ͠ར༻͢Δ͜ͱͰɺ Ұ؏ੑͷ͋ΔσβΠϯͱͳΔ - ࣗಈੜ੒ͱ૬ੑ͕ྑ͍ UI Component for PC Web UI Component for Android Token Automatic Compilation

Slide 12

Slide 12 text

Token Kinds Web ΞϓϦέʔγϣϯʹ͓͚Δ Design Token ࣮ݱखஈ(Ұྫ) छྨ ࣮૷ܗଶ $PMPS4IBEPX(VUUFS $44$VTUPN1SPQFSUJFT PS +BWB4DSJQUDPOTUBOU $44JO+4 5ZQPHSBQIZ $44!GPOUGBDF  MJOFIFJHIUGPOUTJ[FQSPQT *DPOPHSBQIZ 47(pMFPS*OMJOF47(PS8FC'POUTFUD

Slide 13

Slide 13 text

Token Kinds Web ΞϓϦέʔγϣϯʹ͓͚Δ Design Token ࣮ݱखஈ(Ұྫ) छྨ ࣮૷ܗଶ $PMPS4IBEPX(VUUFS $44$VTUPN1SPQFSUJFT PS +BWB4DSJQUDPOTUBOU $44JO+4 5ZQPHSBQIZ $44!GPOUGBDF  MJOFIFJHIUGPOUTJ[FQSPQT *DPOPHSBQIZ 47(pMFPS*OMJOF47(PS8FC'POUTFUD

Slide 14

Slide 14 text

Iconography Token - ৭ม਺΍ϑΥϯτάϦϑͱಉ༷ʹΞΠίϯΛߏ੒͢Δύε৘ใ΋ Design Token - ϓϩδΣΫτͰ͸ɺWeb Ͱͷ Token࣮૷ܗଶͱͯ͠ Inline SVGΛબ୒ - Atoms Component͔Β࢖͍΍͍͢Α͏ʹɺIconography Tokenࣗମ΋ React Componentͱ࣮ͯ͠૷

Slide 15

Slide 15 text

Iconography Token via React - ྫ: υϩοϓμ΢ϯϦετ - ҙຯΛ࣋ͭ࠷খUI୯Ґ͸ υϩοϓμ΢ϯ ▼ ෦෼ͷ SVG ୯ମʹҙຯ͸ແ͍ Iconography Token Dropdown Component (Atoms) import { Down } from "../../tokens/Iconography/Common" export function Dropdown() { return ( <> {/* தུ */} ) }

Slide 16

Slide 16 text

Agenda 1. σβΠϯγεςϜͱ Iconography Token 2. Iconography React Component ͷࣗಈੜ੒

Slide 17

Slide 17 text

PC Web Devs workflow ϓϩδΣΫτͰͷେ·͔ͳը໘։ൃϫʔΫϑϩʔ  'JHNBͰ6*694QFD֬ೝ  3FBDU54Ͱ࣮૷  4UPSZCPPLͰ֬ೝςετ

Slide 18

Slide 18 text

No content

Slide 19

Slide 19 text

ίΠπϥΛΰχϣΰχϣͯ͠ 3FBDU$PNQPOFOUʹͨ͠Ε

Slide 20

Slide 20 text

import { css } from '@emotion/react' import { assertNever } from 'assert-never' import { gray } from '../../colors' import { IconSize } from '../../sizing' export type Props = { readonly iconType: 'Outlined' | 'Filled' readonly css?: JSX.IntrinsicAttributes['css'] readonly size: IconSize } export function Home(props: Props) { const { iconType, size } = props const cssObj = (props as any).className ?? css` fill: ${gray[500]}; ` switch (iconType) { case 'Filled': { return ( ) } case 'Outlined': { return ( ) } default: return assertNever(iconType) } } Iconography Token Component ͷத਎

Slide 21

Slide 21 text

Why inline SVG? ଞํࣜͱൺֱ͢ΔͱɺInline SVG ͕ Icon Tokenͷ࣮૷ʹ࠷΋ద͍ͯ͠Δ ํ๏ QSPTDPOT JNH 47(pMF  'JHNB͔ΒҰׅͰ47(ϑΝΠϧΛFYQPSU͢Δ͚ͩ  ৭Λมߋ͢Δͷ͕༰қͰ͸ͳ͍ %FTJHO5PLFOͱͯ͠க໋త 8FC'POUT  ७ਮʹ໘౗  ςΩετͱͯ͠ղऍ͞ΕΔͨΊɺҙਤͤ͵࠷దԽ͕ͳ͞ΕΔ ಛʹXFCLJUܥ *OMJOF47( 3FBDU$PNQPOFOU  5SFF4IBLBCMF  ͱ͸͍͑໰୊͕ແ͍Θ͚Ͱ͸ͳ͍˞ޙड़

Slide 22

Slide 22 text

Figma to TSX (खಈ) - Figma͔ΒSVGίʔυΛίϐϖ - svgo Ͱѹॖ, svg2jsx Ͱ JSXԽ - ΤσΟλʹషΓ෇͚ͨޙɺ΋Ζ΋ΖΛ੔ ͑ͯอଘ

Slide 23

Slide 23 text

Figma to TSX (ࣗಈ?) - Figma͔ΒSVGίʔυΛίϐϖ - svgo Ͱѹॖ, svg2jsx Ͱ JSXԽ - ΤσΟλʹషΓ෇͚ͨޙɺ΋Ζ΋ΖΛ੔ ͑ͯอଘ 'JHNB"1*Ͱ47(&YUSBDU ΋Ζ΋Ζʜ

Slide 24

Slide 24 text

ʮ΋Ζ΋Ζʯ͕ॏཁ ͩͬͨΓ͢Δ

Slide 25

Slide 25 text

id໰୊ - Inline SVG ʹ͓͚ΔidଐੑͷऔΓѻ͍͸ཁ஫ҙ - ਺߲લͷʮͱ͸͍͑໰୊͕ແ͍Θ͚Ͱ͸ͳ͍ʯͷ෦෼

Slide 26

Slide 26 text

ͷѻ͍͕໘౗ͳͷͱಉ͡)

Slide 27

Slide 27 text

const id = useId() return (

Slide 28

Slide 28 text

Figma to TSX (ࣗಈ) - Figma͔ΒSVGίʔυΛίϐϖ - svgo Ͱѹॖ, svg2jsx Ͱ JSXԽ - ΤσΟλʹషΓ෇͚ͨޙɺ΋Ζ΋ΖΛ੔ ͑ͯอଘ 'JHNB"1*Ͱ47(&YUSBDU JEͷ݅Ҏ֎ʹ΋ࡉʑͨ͠มߋ͕৭ʑඞཁ  QBUIཁૉͷpMMଐੑΛDVSSFOU$PMPSʹ  DMBTT/BNFଐੑΛ௥Ճ  WJFX#PYΛἧ͑Δ  FUD

Slide 29

Slide 29 text

AST Transformation ʮ΋Ζ΋ΖΛ੔͑ͯอଘʯΛݴ͍׵͑Δͱ: SVG ͷ໦ߏ଄Λ୳ࡧͭͭ͠ɺඞཁʹԠͨ͡ஔ׵ॲஔ - AST(Abstract Syntax Tree) Transformation ͦͷ΋ͷ - Babel ΍ swc ͕ߦ͍ͬͯΔ Transpile ॲཧ(.ts -> .js) ͱಉ͡ܥ౷ͷॲཧ

Slide 30

Slide 30 text

AST Transformation https://astexplorer.net

Slide 31

Slide 31 text

AST Transformation via TS - XML ͱͯ͠ͷม׵Ͱ͋Ε͹ɺDOM APIͰे෼࣮ݱՄೳ (i.e. XSLT) - ઌͷ URL referenceͳͲɺJSXࣜͱͳΔͱͦ͏͸͍͔ͳ͍ - ࣮͸ TypeScript ୯ମͰͰ͖ͯ͠·͏ - parse( string -> ts.Node) : ts.craeteSourceFile - ASTม׵(ts.Node -> ts.Node): ts.transform - unparse(ts.Node -> string): ts.createPrinter().printFile

Slide 32

Slide 32 text

AST Transformation via TS - TS Compiler APIʹΑΔ AST ม׵ίʔυ - Try with Playground! export function transform(src: ts.Node) { const factory: ts.TransformerFactory = (ctx) => { const visitor = (node: ts.Node): ts.Node | undefined => { // ͜͜ʹ node ʹର͢ΔॲཧΛॻ͍͍ͯ͘ } return (node) => ts.visitEachChild(node, visitor, ctx) } const result = ts.transform(src, [factory]) return result.transformed[0] }

Slide 33

Slide 33 text

͜͜·Ͱͷ·ͱΊ - Inline SVG Λඳը͢Δ React ComponentͰ Iconography TokenΛ࣮ݱ͠ ͍ͯΔΑ - Iconography Token Component ͸ Figma API Λ࢖ͬͯࣗಈੜ੒͍ͯ͠ ΔΑ - ͜·͝·ͨ͠ཁ͕݅৭ʑ͋Δ͚ͲɺAST ม׵Ͱؤு͍ͬͯΔΑ

Slide 34

Slide 34 text

΍ͬͯͯྑ͔ͬͨࣗಈੜ੒ - Ұൠతʹίʔυੜ੒શൠʹݴ͑Δ͜ͱͰ͕͢ - ७ਮʹ޻਺ͷ࡟ݮʹͭͳ͕Δ - Կेݸ΋React ComponentԽͨ͠ޙͰ΋मਖ਼͕༰қ - ϓϩδΣΫτΛ૸Βͤͳ͕ΒɺϝϯόʔͱʮIcon͸΍ͬͺΓ͜͏͍ ͏Propsʹͨ͠ํ͕Α͍ʯͷΑ͏ͳٞ࿦Λͯ͠΋௧Έ͕গͳ͍

Slide 35

Slide 35 text

Why AST? - ͜͜·Ͱͷ࿩ͰʮͦΕਖ਼نදݱͰे෼Ͱ͸ʯͱࢥͬͨਓ΋͍Δ͔΋͠Ε ͳ͍ - ASTૢ࡞Λ஌͍ͬͯΔͱϑϩϯτΤϯυ։ൃͷ༷ʑͳγʔϯͰ༗༻ - Project Specific ͳ ESLint rule ࡞੒, webpack custom loader (AoT Compilation), etc…

Slide 36

Slide 36 text

Thank you !