diff --git a/src/components/hanzi-data/lut.ts b/src/components/hanzi-data/lut.ts
index 84f648c94aac967d953a2da6d834669bc08ac407..73465f004924daca86d6e1d87c9f74bf7f56b6f1 100644
--- a/src/components/hanzi-data/lut.ts
+++ b/src/components/hanzi-data/lut.ts
@@ -8,6 +8,45 @@ interface RadicalMeanings {
 }
 
 const radicalMeanings: Lut<RadicalMeanings> = {}
+const strokeTypeNumbers: Lut<string> = {
+  一: '①',
+  '㇑': '②',
+  丨: '②',
+  '㇓': '③',
+  丿: '③',
+  '㇔': '④',
+  丶: '④',
+  '㇏': '④',
+  '㇀': '①',
+  乛: '⑤',
+  '𠃍': '⑤',
+  '㇆': '⑤',
+  '𠃌': '⑤',
+  '㇇': '⑤',
+  亅: '②',
+  '𠄌': '⑤',
+  乚: '⑤',
+  '㇉': '⑤',
+  '𡿨': '⑤',
+  '㇂': '⑤',
+  '㇊': '⑤',
+  '㇍': '⑤',
+  '㇅': '⑤',
+  '⺄': '⑤',
+  '㇈': '⑤',
+  '㇌': '⑤',
+  '㇋': '⑤',
+  '𠄎': '⑤',
+  '㇎': '⑤',
+  '𠃊': '⑤',
+  '㇄': '⑤',
+  ㄣ: '⑤',
+  '𠃑': '⑤',
+  ㄥ: '⑤',
+  '𠃋': '⑤',
+  '㇁': '⑤',
+  '㇃': '⑤'
+}
 const strokeTypeNames: Lut<string> = {
   一: '横',
   '㇑': '竖',
@@ -48,7 +87,9 @@ const strokeTypeNames: Lut<string> = {
   '㇃': '卧钩'
 }
 
-export type PropId = keyof RadicalMeanings | 'strokeTypeNames'
+export type PropId = keyof RadicalMeanings |
+'strokeTypeNames' |
+'strokeTypeNumbers'
 
 export function lookup (
   item: HanziData,
@@ -60,6 +101,8 @@ export function lookup (
     }
   } else if (propId === 'strokeTypeNames') {
     return item.strokeTypes.map(t => strokeTypeNames[t])
+  } else if (propId === 'strokeTypeNumbers') {
+    return item.strokeTypes.map(t => strokeTypeNumbers[t])
   }
   return undefined
 }
diff --git a/src/components/write/strokes.ts b/src/components/write/strokes.ts
index 40864f60682c3fd0cbc7fa01d017d6689de3d7bc..b24bc665532a4a45d8ab01851253a5f4f2303fc1 100644
--- a/src/components/write/strokes.ts
+++ b/src/components/write/strokes.ts
@@ -59,21 +59,33 @@ export async function createStrokes (
   })
   if (data !== undefined) {
     const strokeNames = lookup(data, 'strokeTypeNames')
+    const strokeNumbers = lookup(data, 'strokeTypeNumbers')
     const { strokes, strokeTypes } = data
-    for (let idx = 0; idx < strokes.length; ++idx) {
-      const svg = strokeRangeSvg(strokes, idx + 1)
-      const strokeLabel = document.createElement('div')
-      if (Array.isArray(strokeNames) && strokes.length === strokeNames.length) {
-        strokeLabel.innerHTML =
-            `${strokeNames[idx]}<br>${strokeTypes[idx]}<br>${idx + 1}`
-      } else {
-        strokeLabel.textContent = `${idx + 1}`
+    if (
+      Array.isArray(strokeNames) &&
+        Array.isArray(strokeNumbers) &&
+        strokeNames.length === strokeNumbers.length) {
+      for (let idx = 0; idx < strokes.length; ++idx) {
+        const svg = strokeRangeSvg(strokes, idx + 1)
+        const strokeLabel = document.createElement('div')
+        if (strokes.length === strokeNames.length) {
+          strokeLabel.innerHTML =
+              `${
+                strokeNames[idx]
+              }<br>${
+                strokeTypes[idx]
+              } ${
+                strokeNumbers[idx]
+              }<br>${idx + 1}.`
+        } else {
+          strokeLabel.textContent = `${idx + 1}`
+        }
+        const strokeInfo = document.createElement('div')
+        strokeInfo.classList.add('stroke')
+        strokeInfo.appendChild(svg)
+        strokeInfo.appendChild(strokeLabel)
+        container.appendChild(strokeInfo)
       }
-      const strokeInfo = document.createElement('div')
-      strokeInfo.classList.add('stroke')
-      strokeInfo.appendChild(svg)
-      strokeInfo.appendChild(strokeLabel)
-      container.appendChild(strokeInfo)
     }
   }
 
diff --git a/test/templates/lut.test.ts b/test/templates/lut.test.ts
index 8fc75c4e7983c9dc6b77aeb48b5038d8f220cef2..60db184c07631b9456c25f0e7104e25ccb6ed6ef 100644
--- a/test/templates/lut.test.ts
+++ b/test/templates/lut.test.ts
@@ -1,18 +1,41 @@
 import { getHanziData } from '../../src/components/hanzi-data'
 import { lookup } from '../../src/components/hanzi-data/lut'
 
-describe('radical names', () => {
+describe('table properties', () => {
   const testCases = [
-    [ '草', 'radicalMeaningDe', 'Gras'],
-    [ '母', 'radicalMeaningDe', 'Mutter' ]
+    { hanzi: '草', prop: 'radicalMeaningDe', expected: 'Gras' },
+    { hanzi: '母', prop: 'radicalMeaningDe', expected: 'Mutter' },
+    {
+      hanzi: '木',
+      prop: 'strokeTypeNumbers',
+      expected: [ '①', '②', '③', '④' ]
+    },
+    {
+      hanzi: '道',
+      prop: 'strokeTypeNumbers',
+      expected: [
+        '④',
+        '③',
+        '①',
+        '③',
+        '②',
+        '⑤',
+        '①',
+        '①',
+        '①',
+        '④',
+        '⑤',
+        '④'
+      ]
+    }
   ]
-  for (const [ hanzi, prop, expectedValue ] of testCases) {
+  for (const { hanzi, prop, expected } of testCases) {
     test(`${prop} of ${hanzi}`, async () => {
       const actual = lookup(
         await getHanziData({ char: hanzi }),
         prop
       )
-      expect(actual).toBe(expectedValue)
+      expect(actual).toEqual(expected)
     })
   }
-})
\ No newline at end of file
+})