feat(sw): add step header with multi-step and split layout support

This commit is contained in:
shkim4 committed 2026-11-03 14:58:53 +09:00
1 parent 6ca92c5d55
commit adbb034cb1
28 files changed
+2477 -7

No files matched your search

@@ -0,0 +1,17 @@
<svg preserveAspectRatio="none" overflow="visible" style="display: block;" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="controls 1">
<circle id="Ellipse 499" cx="7.71924" cy="7.79834" r="2.12158" fill="#003425"/>
<circle id="Ellipse 500" cx="16.606" cy="16.5244" r="2.12158" fill="#003425"/>
<g id="Union">
<use xlink:href="#stroke0_0_190" fill="#FFC600"/>
<mask id="stroke1_0_190" maskUnits="userSpaceOnUse" x="3.08594" y="3.68262" width="18" height="17" fill="black">
<rect fill="white" x="3.08594" y="3.68262" width="18" height="17"/>
<use xlink:href="#stroke0_0_190"/>
</mask>
<path d="M16.1807 13.041C17.9137 13.041 19.3191 14.4458 19.3193 16.1787C19.3192 17.9117 17.9137 19.3174 16.1807 19.3174C14.7063 19.3172 13.4701 18.2995 13.1338 16.9287H4.08594V15.4287H13.1338C13.4701 14.058 14.7063 13.0412 16.1807 13.041ZM16.1807 14.541C15.2763 14.5412 14.5432 15.2743 14.543 16.1787C14.5431 17.0832 15.2762 17.8172 16.1807 17.8174C17.0853 17.8174 17.8192 17.0833 17.8193 16.1787C17.8191 15.2742 17.0852 14.541 16.1807 14.541ZM7.82129 4.68262C9.29579 4.68267 10.5327 5.69951 10.8691 7.07031H19.915V8.57031H10.8691C10.5327 9.94121 9.29576 10.9589 7.82129 10.959C6.08843 10.9588 4.68373 9.55319 4.68359 7.82031C4.68382 6.08751 6.08849 4.68284 7.82129 4.68262ZM7.82129 6.18262C6.91691 6.18284 6.18382 6.91594 6.18359 7.82031C6.18373 8.72476 6.91686 9.45876 7.82129 9.45898C8.71966 9.45893 9.44889 8.73487 9.45898 7.83887V7.80078C9.44843 6.90519 8.71937 6.18268 7.82129 6.18262Z" stroke-width="2" stroke="black" mask="url(#stroke1_0_190)"/>
</g>
</g>
<defs>
<path id="stroke0_0_190" d="M16.1807 13.041C17.9137 13.041 19.3191 14.4458 19.3193 16.1787C19.3192 17.9117 17.9137 19.3174 16.1807 19.3174C14.7063 19.3172 13.4701 18.2995 13.1338 16.9287H4.08594V15.4287H13.1338C13.4701 14.058 14.7063 13.0412 16.1807 13.041ZM16.1807 14.541C15.2763 14.5412 14.5432 15.2743 14.543 16.1787C14.5431 17.0832 15.2762 17.8172 16.1807 17.8174C17.0853 17.8174 17.8192 17.0833 17.8193 16.1787C17.8191 15.2742 17.0852 14.541 16.1807 14.541ZM7.82129 4.68262C9.29579 4.68267 10.5327 5.69951 10.8691 7.07031H19.915V8.57031H10.8691C10.5327 9.94121 9.29576 10.9589 7.82129 10.959C6.08843 10.9588 4.68373 9.55319 4.68359 7.82031C4.68382 6.08751 6.08849 4.68284 7.82129 4.68262ZM7.82129 6.18262C6.91691 6.18284 6.18382 6.91594 6.18359 7.82031C6.18373 8.72476 6.91686 9.45876 7.82129 9.45898C8.71966 9.45893 9.44889 8.73487 9.45898 7.83887V7.80078C9.44842 6.90519 8.71937 6.18268 7.82129 6.18262Z"/>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

@@ -0,0 +1,17 @@
<svg preserveAspectRatio="none" overflow="visible" style="display: block;" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="controls 1">
<circle id="Ellipse 499" cx="7.71924" cy="7.79834" r="2.12158" fill="#003425"/>
<circle id="Ellipse 500" cx="16.606" cy="16.5244" r="2.12158" fill="#003425"/>
<g id="Union">
<use xlink:href="#stroke0_0_190" fill="#B6D0C9"/>
<mask id="stroke1_0_190" maskUnits="userSpaceOnUse" x="3.08594" y="3.68262" width="18" height="17" fill="black">
<rect fill="white" x="3.08594" y="3.68262" width="18" height="17"/>
<use xlink:href="#stroke0_0_190"/>
</mask>
<path d="M16.1807 13.041C17.9137 13.041 19.3191 14.4458 19.3193 16.1787C19.3192 17.9117 17.9137 19.3174 16.1807 19.3174C14.7063 19.3172 13.4701 18.2995 13.1338 16.9287H4.08594V15.4287H13.1338C13.4701 14.058 14.7063 13.0412 16.1807 13.041ZM16.1807 14.541C15.2763 14.5412 14.5432 15.2743 14.543 16.1787C14.5431 17.0832 15.2762 17.8172 16.1807 17.8174C17.0853 17.8174 17.8192 17.0833 17.8193 16.1787C17.8191 15.2742 17.0852 14.541 16.1807 14.541ZM7.82129 4.68262C9.29579 4.68267 10.5327 5.69951 10.8691 7.07031H19.915V8.57031H10.8691C10.5327 9.94121 9.29576 10.9589 7.82129 10.959C6.08843 10.9588 4.68373 9.55319 4.68359 7.82031C4.68382 6.08751 6.08849 4.68284 7.82129 4.68262ZM7.82129 6.18262C6.91691 6.18284 6.18382 6.91594 6.18359 7.82031C6.18373 8.72476 6.91686 9.45876 7.82129 9.45898C8.71966 9.45893 9.44889 8.73487 9.45898 7.83887V7.80078C9.44843 6.90519 8.71937 6.18268 7.82129 6.18262Z" stroke-width="2" stroke="black" mask="url(#stroke1_0_190)"/>
</g>
</g>
<defs>
<path id="stroke0_0_190" d="M16.1807 13.041C17.9137 13.041 19.3191 14.4458 19.3193 16.1787C19.3192 17.9117 17.9137 19.3174 16.1807 19.3174C14.7063 19.3172 13.4701 18.2995 13.1338 16.9287H4.08594V15.4287H13.1338C13.4701 14.058 14.7063 13.0412 16.1807 13.041ZM16.1807 14.541C15.2763 14.5412 14.5432 15.2743 14.543 16.1787C14.5431 17.0832 15.2762 17.8172 16.1807 17.8174C17.0853 17.8174 17.8192 17.0833 17.8193 16.1787C17.8191 15.2742 17.0852 14.541 16.1807 14.541ZM7.82129 4.68262C9.29579 4.68267 10.5327 5.69951 10.8691 7.07031H19.915V8.57031H10.8691C10.5327 9.94121 9.29576 10.9589 7.82129 10.959C6.08843 10.9588 4.68373 9.55319 4.68359 7.82031C4.68382 6.08751 6.08849 4.68284 7.82129 4.68262ZM7.82129 6.18262C6.91691 6.18284 6.18382 6.91594 6.18359 7.82031C6.18373 8.72476 6.91686 9.45876 7.82129 9.45898C8.71966 9.45893 9.44889 8.73487 9.45898 7.83887V7.80078C9.44842 6.90519 8.71937 6.18268 7.82129 6.18262Z"/>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

@@ -0,0 +1,15 @@
<svg preserveAspectRatio="none" overflow="visible" style="display: block;" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="exit-arrow 1">
<g id="Vector (Stroke)">
<use xlink:href="#stroke0_0_68" fill="#FFC600"/>
<mask id="stroke1_0_68" maskUnits="userSpaceOnUse" x="3" y="3.28747" width="19" height="18" fill="black">
<rect fill="white" x="3" y="3.28747" width="19" height="18"/>
<use xlink:href="#stroke0_0_68"/>
</mask>
<path d="M4 17.8383V6.16174C4 5.65257 4.12778 5.15234 4.49632 4.7838C4.86487 4.41525 5.3651 4.28747 5.87427 4.28747H10.514V5.57779H5.87427C5.56403 5.57779 5.44971 5.65487 5.40855 5.69602C5.3674 5.73718 5.29032 5.8515 5.29032 6.16174V17.8383C5.29032 18.1485 5.3674 18.2628 5.40855 18.304C5.44971 18.3451 5.56403 18.4222 5.87427 18.4222H10.514V19.7125H5.87427C5.3651 19.7125 4.86487 19.5847 4.49632 19.2162C4.12778 18.8477 4 18.3474 4 17.8383ZM20 12L15.3998 7.39985L14.487 8.31268L17.5298 11.3548H9.22371V12.6452H17.5298L14.487 15.6873L15.3998 16.6001L20 12Z" stroke-width="2" stroke="black" mask="url(#stroke1_0_68)"/>
</g>
</g>
<defs>
<path id="stroke0_0_68" d="M4 17.8383V6.16174C4 5.65257 4.12778 5.15234 4.49632 4.7838C4.86487 4.41525 5.3651 4.28747 5.87427 4.28747H10.514V5.57779H5.87427C5.56403 5.57779 5.44971 5.65487 5.40855 5.69602C5.3674 5.73718 5.29032 5.8515 5.29032 6.16174V17.8383C5.29032 18.1485 5.3674 18.2628 5.40855 18.304C5.44971 18.3451 5.56403 18.4222 5.87427 18.4222H10.514V19.7125H5.87427C5.3651 19.7125 4.86487 19.5848 4.49632 19.2162C4.12778 18.8477 4 18.3474 4 17.8383ZM20 12L15.3998 16.6002L14.487 15.6873L17.5298 12.6452H9.22371V11.3548H17.5298L14.487 8.31268L15.3998 7.39985L20 12Z"/>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

@@ -0,0 +1,15 @@
<svg preserveAspectRatio="none" overflow="visible" style="display: block;" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="exit-arrow 1">
<g id="Vector (Stroke)">
<use xlink:href="#stroke0_0_68" fill="#B6D0C9"/>
<mask id="stroke1_0_68" maskUnits="userSpaceOnUse" x="3" y="3.28747" width="19" height="18" fill="black">
<rect fill="white" x="3" y="3.28747" width="19" height="18"/>
<use xlink:href="#stroke0_0_68"/>
</mask>
<path d="M4 17.8383V6.16174C4 5.65257 4.12778 5.15234 4.49632 4.7838C4.86487 4.41525 5.3651 4.28747 5.87427 4.28747H10.514V5.57779H5.87427C5.56403 5.57779 5.44971 5.65487 5.40855 5.69602C5.3674 5.73718 5.29032 5.8515 5.29032 6.16174V17.8383C5.29032 18.1485 5.3674 18.2628 5.40855 18.304C5.44971 18.3451 5.56403 18.4222 5.87427 18.4222H10.514V19.7125H5.87427C5.3651 19.7125 4.86487 19.5847 4.49632 19.2162C4.12778 18.8477 4 18.3474 4 17.8383ZM20 12L15.3998 7.39985L14.487 8.31268L17.5298 11.3548H9.22371V12.6452H17.5298L14.487 15.6873L15.3998 16.6001L20 12Z" stroke-width="2" stroke="black" mask="url(#stroke1_0_68)"/>
</g>
</g>
<defs>
<path id="stroke0_0_68" d="M4 17.8383V6.16174C4 5.65257 4.12778 5.15234 4.49632 4.7838C4.86487 4.41525 5.3651 4.28747 5.87427 4.28747H10.514V5.57779H5.87427C5.56403 5.57779 5.44971 5.65487 5.40855 5.69602C5.3674 5.73718 5.29032 5.8515 5.29032 6.16174V17.8383C5.29032 18.1485 5.3674 18.2628 5.40855 18.304C5.44971 18.3451 5.56403 18.4222 5.87427 18.4222H10.514V19.7125H5.87427C5.3651 19.7125 4.86487 19.5848 4.49632 19.2162C4.12778 18.8477 4 18.3474 4 17.8383ZM20 12L15.3998 16.6002L14.487 15.6873L17.5298 12.6452H9.22371V11.3548H17.5298L14.487 8.31268L15.3998 7.39985L20 12Z"/>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

@@ -0,0 +1,16 @@
<svg preserveAspectRatio="none" overflow="visible" style="display: block;" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="help 1">
<circle id="Ellipse 499" cx="11.9995" cy="12" r="7.22998" fill="#003425"/>
<g id="Union">
<use xlink:href="#stroke0_0_58" fill="#FFC600"/>
<mask id="stroke1_0_58" maskUnits="userSpaceOnUse" x="2.83984" y="2.84033" width="19" height="19" fill="black">
<rect fill="white" x="2.83984" y="2.84033" width="19" height="19"/>
<use xlink:href="#stroke0_0_58"/>
</mask>
<path d="M11.999 3.84033C16.5053 3.84033 20.159 7.4933 20.1592 11.9995C20.159 16.5057 16.5053 20.1597 11.999 20.1597C7.49289 20.1595 3.83998 16.5056 3.83984 11.9995C3.83998 7.49338 7.4929 3.84047 11.999 3.84033ZM11.999 5.46533C8.39036 5.46547 5.46498 8.39085 5.46484 11.9995C5.46498 15.6082 8.39035 18.5345 11.999 18.5347C15.6078 18.5347 18.534 15.6083 18.5342 11.9995C18.534 8.39076 15.6078 5.46533 11.999 5.46533ZM11.8047 14.938C12.0986 14.84 12.3929 14.9384 12.5889 15.1343C12.6868 15.2323 12.7852 15.4284 12.7852 15.7222C12.7851 15.918 12.6868 16.1142 12.5889 16.3101C12.3929 16.5059 12.0985 16.6033 11.8047 16.5054C11.7072 16.5051 11.707 16.4078 11.6094 16.4077C11.3156 16.2119 11.2178 16.0159 11.2178 15.7222C11.2178 15.4283 11.3156 15.2325 11.6094 15.0366C11.707 15.0365 11.7072 14.9383 11.8047 14.938ZM12.001 7.68896C12.7846 7.68896 13.2749 7.88474 13.7646 8.37451C14.2544 8.86431 14.4502 9.35481 14.4502 10.0405C14.4501 10.7261 14.0577 11.3139 13.3721 11.9995C13.1763 12.2932 13.0786 12.4892 12.8828 12.6851C12.7849 12.783 12.6868 13.0768 12.5889 13.3706C12.5889 13.6645 12.2946 13.8608 12.0986 13.8608H11.9033C11.5116 13.8608 11.2177 13.567 11.3154 13.1753C11.3154 13.0773 11.4131 12.8807 11.4131 12.7827C11.5111 12.4889 11.8051 12.097 12.001 11.8032C12.0989 11.7053 12.2946 11.4122 12.3926 11.314C12.9803 10.8242 13.1768 10.4317 13.1768 9.94189C13.1767 9.55043 13.0785 9.25689 12.8828 9.06104C12.6869 8.86512 12.2949 8.76709 12.001 8.76709C11.7071 8.76712 11.3153 8.96256 11.0215 9.25635C10.9236 9.35424 10.8254 9.54992 10.7275 9.64795C10.6296 9.94183 10.3359 10.1378 10.042 9.94189H9.94434C9.65046 9.94189 9.55243 9.55023 9.65039 9.25635C9.74835 8.96268 9.94387 8.669 10.1396 8.47314C10.6294 7.8854 11.2173 7.68897 12.001 7.68896Z" stroke-width="2" stroke="black" mask="url(#stroke1_0_58)"/>
</g>
</g>
<defs>
<path id="stroke0_0_58" d="M11.999 3.84033C16.5053 3.84033 20.159 7.4933 20.1592 11.9995C20.159 16.5057 16.5053 20.1597 11.999 20.1597C7.49289 20.1595 3.83998 16.5056 3.83984 11.9995C3.83998 7.49338 7.4929 3.84047 11.999 3.84033ZM11.999 5.46533C8.39036 5.46547 5.46498 8.39085 5.46484 11.9995C5.46498 15.6082 8.39035 18.5345 11.999 18.5347C15.6078 18.5347 18.534 15.6083 18.5342 11.9995C18.534 8.39076 15.6078 5.46533 11.999 5.46533ZM11.8047 14.938C12.0986 14.84 12.3929 14.9384 12.5889 15.1343C12.6868 15.2323 12.7852 15.4284 12.7852 15.7222C12.7851 15.918 12.6868 16.1142 12.5889 16.3101C12.3929 16.5059 12.0985 16.6033 11.8047 16.5054C11.7072 16.5051 11.707 16.4078 11.6094 16.4077C11.3156 16.2119 11.2178 16.0159 11.2178 15.7222C11.2178 15.4283 11.3156 15.2325 11.6094 15.0366C11.707 15.0365 11.7072 14.9383 11.8047 14.938ZM12.001 7.68896C12.7846 7.68896 13.2749 7.88474 13.7646 8.37451C14.2544 8.86431 14.4502 9.35481 14.4502 10.0405C14.4501 10.7261 14.0577 11.3139 13.3721 11.9995C13.1763 12.2932 13.0786 12.4892 12.8828 12.6851C12.7849 12.783 12.6868 13.0768 12.5889 13.3706C12.5889 13.6645 12.2946 13.8608 12.0986 13.8608H11.9033C11.5116 13.8608 11.2177 13.567 11.3154 13.1753C11.3154 13.0773 11.4131 12.8807 11.4131 12.7827C11.5111 12.4889 11.8051 12.097 12.001 11.8032C12.0989 11.7053 12.2946 11.4122 12.3926 11.314C12.9803 10.8242 13.1768 10.4317 13.1768 9.94189C13.1767 9.55043 13.0785 9.25689 12.8828 9.06104C12.6869 8.86512 12.2949 8.76709 12.001 8.76709C11.7071 8.76712 11.3153 8.96256 11.0215 9.25635C10.9236 9.35424 10.8254 9.54992 10.7275 9.64795C10.6296 9.94183 10.3359 10.1378 10.042 9.94189H9.94434C9.65046 9.94189 9.55243 9.55023 9.65039 9.25635C9.74835 8.96268 9.94387 8.669 10.1396 8.47314C10.6294 7.8854 11.2173 7.68897 12.001 7.68896Z"/>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 4.1 KiB

@@ -0,0 +1,16 @@
<svg preserveAspectRatio="none" overflow="visible" style="display: block;" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="help 1">
<circle id="Ellipse 499" cx="11.9995" cy="12" r="7.22998" fill="#003425"/>
<g id="Union">
<use xlink:href="#stroke0_0_58" fill="#B6D0C9"/>
<mask id="stroke1_0_58" maskUnits="userSpaceOnUse" x="2.83984" y="2.84033" width="19" height="19" fill="black">
<rect fill="white" x="2.83984" y="2.84033" width="19" height="19"/>
<use xlink:href="#stroke0_0_58"/>
</mask>
<path d="M11.999 3.84033C16.5053 3.84033 20.159 7.4933 20.1592 11.9995C20.159 16.5057 16.5053 20.1597 11.999 20.1597C7.49289 20.1595 3.83998 16.5056 3.83984 11.9995C3.83998 7.49338 7.4929 3.84047 11.999 3.84033ZM11.999 5.46533C8.39036 5.46547 5.46498 8.39085 5.46484 11.9995C5.46498 15.6082 8.39035 18.5345 11.999 18.5347C15.6078 18.5347 18.534 15.6083 18.5342 11.9995C18.534 8.39076 15.6078 5.46533 11.999 5.46533ZM11.8047 14.938C12.0986 14.84 12.3929 14.9384 12.5889 15.1343C12.6868 15.2323 12.7852 15.4284 12.7852 15.7222C12.7851 15.918 12.6868 16.1142 12.5889 16.3101C12.3929 16.5059 12.0985 16.6033 11.8047 16.5054C11.7072 16.5051 11.707 16.4078 11.6094 16.4077C11.3156 16.2119 11.2178 16.0159 11.2178 15.7222C11.2178 15.4283 11.3156 15.2325 11.6094 15.0366C11.707 15.0365 11.7072 14.9383 11.8047 14.938ZM12.001 7.68896C12.7846 7.68896 13.2749 7.88474 13.7646 8.37451C14.2544 8.86431 14.4502 9.35481 14.4502 10.0405C14.4501 10.7261 14.0577 11.3139 13.3721 11.9995C13.1763 12.2932 13.0786 12.4892 12.8828 12.6851C12.7849 12.783 12.6868 13.0768 12.5889 13.3706C12.5889 13.6645 12.2946 13.8608 12.0986 13.8608H11.9033C11.5116 13.8608 11.2177 13.567 11.3154 13.1753C11.3154 13.0773 11.4131 12.8807 11.4131 12.7827C11.5111 12.4889 11.8051 12.097 12.001 11.8032C12.0989 11.7053 12.2946 11.4122 12.3926 11.314C12.9803 10.8242 13.1768 10.4317 13.1768 9.94189C13.1767 9.55043 13.0785 9.25689 12.8828 9.06104C12.6869 8.86512 12.2949 8.76709 12.001 8.76709C11.7071 8.76712 11.3153 8.96256 11.0215 9.25635C10.9236 9.35424 10.8254 9.54992 10.7275 9.64795C10.6296 9.94183 10.3359 10.1378 10.042 9.94189H9.94434C9.65046 9.94189 9.55243 9.55023 9.65039 9.25635C9.74835 8.96268 9.94387 8.669 10.1396 8.47314C10.6294 7.8854 11.2173 7.68897 12.001 7.68896Z" stroke-width="2" stroke="black" mask="url(#stroke1_0_58)"/>
</g>
</g>
<defs>
<path id="stroke0_0_58" d="M11.999 3.84033C16.5053 3.84033 20.159 7.4933 20.1592 11.9995C20.159 16.5057 16.5053 20.1597 11.999 20.1597C7.49289 20.1595 3.83998 16.5056 3.83984 11.9995C3.83998 7.49338 7.4929 3.84047 11.999 3.84033ZM11.999 5.46533C8.39036 5.46547 5.46498 8.39085 5.46484 11.9995C5.46498 15.6082 8.39035 18.5345 11.999 18.5347C15.6078 18.5347 18.534 15.6083 18.5342 11.9995C18.534 8.39076 15.6078 5.46533 11.999 5.46533ZM11.8047 14.938C12.0986 14.84 12.3929 14.9384 12.5889 15.1343C12.6868 15.2323 12.7852 15.4284 12.7852 15.7222C12.7851 15.918 12.6868 16.1142 12.5889 16.3101C12.3929 16.5059 12.0985 16.6033 11.8047 16.5054C11.7072 16.5051 11.707 16.4078 11.6094 16.4077C11.3156 16.2119 11.2178 16.0159 11.2178 15.7222C11.2178 15.4283 11.3156 15.2325 11.6094 15.0366C11.707 15.0365 11.7072 14.9383 11.8047 14.938ZM12.001 7.68896C12.7846 7.68896 13.2749 7.88474 13.7646 8.37451C14.2544 8.86431 14.4502 9.35481 14.4502 10.0405C14.4501 10.7261 14.0577 11.3139 13.3721 11.9995C13.1763 12.2932 13.0786 12.4892 12.8828 12.6851C12.7849 12.783 12.6868 13.0768 12.5889 13.3706C12.5889 13.6645 12.2946 13.8608 12.0986 13.8608H11.9033C11.5116 13.8608 11.2177 13.567 11.3154 13.1753C11.3154 13.0773 11.4131 12.8807 11.4131 12.7827C11.5111 12.4889 11.8051 12.097 12.001 11.8032C12.0989 11.7053 12.2946 11.4122 12.3926 11.314C12.9803 10.8242 13.1768 10.4317 13.1768 9.94189C13.1767 9.55043 13.0785 9.25689 12.8828 9.06104C12.6869 8.86512 12.2949 8.76709 12.001 8.76709C11.7071 8.76712 11.3153 8.96256 11.0215 9.25635C10.9236 9.35424 10.8254 9.54992 10.7275 9.64795C10.6296 9.94183 10.3359 10.1378 10.042 9.94189H9.94434C9.65046 9.94189 9.55243 9.55023 9.65039 9.25635C9.74835 8.96268 9.94387 8.669 10.1396 8.47314C10.6294 7.8854 11.2173 7.68897 12.001 7.68896Z"/>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 4.1 KiB

@@ -0,0 +1,15 @@
<svg preserveAspectRatio="none" overflow="visible" style="display: block;" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="menu-list 1">
<g id="Union">
<use xlink:href="#stroke0_0_85" fill="#FFC600"/>
<mask id="stroke1_0_85" maskUnits="userSpaceOnUse" x="2.89844" y="4.66113" width="18" height="15" fill="black">
<rect fill="white" x="2.89844" y="4.66113" width="18" height="15"/>
<use xlink:href="#stroke0_0_85"/>
</mask>
<path d="M5.44434 16.793V18.3389H3.89844V16.793H5.44434ZM19.8018 18.3164H7.78906V16.8164H19.8018V18.3164ZM5.44434 12.7734H3.89844V11.2266H5.44434V12.7734ZM19.8018 12.75H7.78906V11.25H19.8018V12.75ZM5.44434 7.20703H3.89844V5.66113H5.44434V7.20703ZM19.8018 7.18457H7.78906V5.68457H19.8018V7.18457Z" stroke-width="2" stroke="black" mask="url(#stroke1_0_85)"/>
</g>
</g>
<defs>
<path id="stroke0_0_85" d="M5.44434 16.793V18.3389H3.89844V16.793H5.44434ZM19.8018 18.3164H7.78906V16.8164H19.8018V18.3164ZM5.44434 12.7734H3.89844V11.2266H5.44434V12.7734ZM19.8018 12.75H7.78906V11.25H19.8018V12.75ZM5.44434 7.20703H3.89844V5.66113H5.44434V7.20703ZM19.8018 7.18457H7.78906V5.68457H19.8018V7.18457Z"/>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

@@ -0,0 +1,15 @@
<svg preserveAspectRatio="none" overflow="visible" style="display: block;" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="menu-list 1">
<g id="Union">
<use xlink:href="#stroke0_0_85" fill="#B6D0C9"/>
<mask id="stroke1_0_85" maskUnits="userSpaceOnUse" x="2.89844" y="4.66113" width="18" height="15" fill="black">
<rect fill="white" x="2.89844" y="4.66113" width="18" height="15"/>
<use xlink:href="#stroke0_0_85"/>
</mask>
<path d="M5.44434 16.793V18.3389H3.89844V16.793H5.44434ZM19.8018 18.3164H7.78906V16.8164H19.8018V18.3164ZM5.44434 12.7734H3.89844V11.2266H5.44434V12.7734ZM19.8018 12.75H7.78906V11.25H19.8018V12.75ZM5.44434 7.20703H3.89844V5.66113H5.44434V7.20703ZM19.8018 7.18457H7.78906V5.68457H19.8018V7.18457Z" stroke-width="2" stroke="black" mask="url(#stroke1_0_85)"/>
</g>
</g>
<defs>
<path id="stroke0_0_85" d="M5.44434 16.793V18.3389H3.89844V16.793H5.44434ZM19.8018 18.3164H7.78906V16.8164H19.8018V18.3164ZM5.44434 12.7734H3.89844V11.2266H5.44434V12.7734ZM19.8018 12.75H7.78906V11.25H19.8018V12.75ZM5.44434 7.20703H3.89844V5.66113H5.44434V7.20703ZM19.8018 7.18457H7.78906V5.68457H19.8018V7.18457Z"/>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

@@ -0,0 +1,28 @@
<svg preserveAspectRatio="none" overflow="visible" style="display: block;" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="view-3d 1">
<g id="Rectangle 9122" filter="url(#filter0_i_0_49)">
<path d="M20 4.36646H8.37521L4.88 7.74889L4 19.2053H16.2071L20 15.7102V4.36646Z" fill="#003425"/>
</g>
<g id="Vector">
<use xlink:href="#stroke0_0_49" fill="#FFC600"/>
<mask id="stroke1_0_49" maskUnits="userSpaceOnUse" x="3" y="3" width="18" height="18" fill="black">
<rect fill="white" x="3" y="3" width="18" height="18"/>
<use xlink:href="#stroke0_0_49"/>
</mask>
<path d="M19.4359 4C19.7462 4 20 4.25249 20 4.56094V15.6203C19.9999 15.7919 19.9193 15.9438 19.7961 16.0469L16.1195 19.7914C16.0159 19.917 15.8611 20 15.6859 20H4.56406C4.25395 20 4.00014 19.7474 4 19.439V8.37968C4 8.36816 4.00242 8.35672 4.00313 8.34528C4.00457 8.3212 4.00638 8.2972 4.01094 8.27344C4.01364 8.2596 4.01816 8.24632 4.02187 8.2328C4.02781 8.21096 4.03354 8.18912 4.04218 8.168C4.0471 8.15608 4.05368 8.14504 4.05938 8.1336C4.07013 8.11184 4.08075 8.08992 4.09453 8.06952C4.10043 8.06072 4.10769 8.05296 4.11406 8.04456C4.12754 8.02688 4.14036 8.0084 4.15625 7.99216L7.84528 4.17344C7.9616 4.05178 8.12072 3.9961 8.27736 4.00313C8.28952 4.00231 8.30168 4 8.31408 4H19.4359ZM5.12816 18.8782H15.1218V8.94064H5.12816V18.8782ZM16.25 8.5992V18.0578L18.8718 15.3883V5.9328L16.25 8.5992ZM5.88752 7.81872H15.4438L18.0914 5.12734H8.4828L5.88752 7.81872Z" stroke-width="2" stroke="black" mask="url(#stroke1_0_49)"/>
</g>
</g>
<defs>
<filter id="filter0_i_0_49" x="4" y="4.36646" width="16" height="14.8389" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="1.68269"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_0_49"/>
</filter>
<path id="stroke0_0_49" d="M19.4359 4C19.7462 4 20 4.25249 20 4.56094V15.6203C19.9999 15.7919 19.9193 15.9438 19.7961 16.0469L16.1195 19.7914C16.0159 19.917 15.8611 20 15.6859 20H4.56406C4.25395 20 4.00014 19.7474 4 19.439V8.37968C4 8.36816 4.00242 8.35672 4.00313 8.34528C4.00457 8.3212 4.00638 8.2972 4.01094 8.27344C4.01364 8.2596 4.01816 8.24632 4.02187 8.2328C4.02781 8.21096 4.03354 8.18912 4.04218 8.168C4.0471 8.15608 4.05368 8.14504 4.05938 8.1336C4.07013 8.11184 4.08075 8.08992 4.09453 8.06952C4.10043 8.06072 4.10769 8.05296 4.11406 8.04456C4.12754 8.02688 4.14036 8.0084 4.15625 7.99216L7.84528 4.17344C7.9616 4.05178 8.12072 3.9961 8.27736 4.00313C8.28952 4.00231 8.30168 4 8.31408 4H19.4359ZM5.12816 18.8782H15.1218V8.94064H5.12816V18.8782ZM16.25 8.5992V18.0578L18.8718 15.3883V5.9328L16.25 8.5992ZM5.88752 7.81872H15.4438L18.0914 5.12734H8.4828L5.88752 7.81872Z"/>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

@@ -0,0 +1,28 @@
<svg preserveAspectRatio="none" overflow="visible" style="display: block;" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="view-3d 1">
<g id="Rectangle 9122" filter="url(#filter0_i_0_49)">
<path d="M20 4.36646H8.37521L4.88 7.74889L4 19.2053H16.2071L20 15.7102V4.36646Z" fill="#003425"/>
</g>
<g id="Vector">
<use xlink:href="#stroke0_0_49" fill="#B6D0C9"/>
<mask id="stroke1_0_49" maskUnits="userSpaceOnUse" x="3" y="3" width="18" height="18" fill="black">
<rect fill="white" x="3" y="3" width="18" height="18"/>
<use xlink:href="#stroke0_0_49"/>
</mask>
<path d="M19.4359 4C19.7462 4 20 4.25249 20 4.56094V15.6203C19.9999 15.7919 19.9193 15.9438 19.7961 16.0469L16.1195 19.7914C16.0159 19.917 15.8611 20 15.6859 20H4.56406C4.25395 20 4.00014 19.7474 4 19.439V8.37968C4 8.36816 4.00242 8.35672 4.00313 8.34528C4.00457 8.3212 4.00638 8.2972 4.01094 8.27344C4.01364 8.2596 4.01816 8.24632 4.02187 8.2328C4.02781 8.21096 4.03354 8.18912 4.04218 8.168C4.0471 8.15608 4.05368 8.14504 4.05938 8.1336C4.07013 8.11184 4.08075 8.08992 4.09453 8.06952C4.10043 8.06072 4.10769 8.05296 4.11406 8.04456C4.12754 8.02688 4.14036 8.0084 4.15625 7.99216L7.84528 4.17344C7.9616 4.05178 8.12072 3.9961 8.27736 4.00313C8.28952 4.00231 8.30168 4 8.31408 4H19.4359ZM5.12816 18.8782H15.1218V8.94064H5.12816V18.8782ZM16.25 8.5992V18.0578L18.8718 15.3883V5.9328L16.25 8.5992ZM5.88752 7.81872H15.4438L18.0914 5.12734H8.4828L5.88752 7.81872Z" stroke-width="2" stroke="black" mask="url(#stroke1_0_49)"/>
</g>
</g>
<defs>
<filter id="filter0_i_0_49" x="4" y="4.36646" width="16" height="14.8389" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="1.68269"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_0_49"/>
</filter>
<path id="stroke0_0_49" d="M19.4359 4C19.7462 4 20 4.25249 20 4.56094V15.6203C19.9999 15.7919 19.9193 15.9438 19.7961 16.0469L16.1195 19.7914C16.0159 19.917 15.8611 20 15.6859 20H4.56406C4.25395 20 4.00014 19.7474 4 19.439V8.37968C4 8.36816 4.00242 8.35672 4.00313 8.34528C4.00457 8.3212 4.00638 8.2972 4.01094 8.27344C4.01364 8.2596 4.01816 8.24632 4.02187 8.2328C4.02781 8.21096 4.03354 8.18912 4.04218 8.168C4.0471 8.15608 4.05368 8.14504 4.05938 8.1336C4.07013 8.11184 4.08075 8.08992 4.09453 8.06952C4.10043 8.06072 4.10769 8.05296 4.11406 8.04456C4.12754 8.02688 4.14036 8.0084 4.15625 7.99216L7.84528 4.17344C7.9616 4.05178 8.12072 3.9961 8.27736 4.00313C8.28952 4.00231 8.30168 4 8.31408 4H19.4359ZM5.12816 18.8782H15.1218V8.94064H5.12816V18.8782ZM16.25 8.5992V18.0578L18.8718 15.3883V5.9328L16.25 8.5992ZM5.88752 7.81872H15.4438L18.0914 5.12734H8.4828L5.88752 7.81872Z"/>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

+142
View File
@@ -0,0 +1,142 @@
import { useState, type CSSProperties } from "react"
import type { SWProcessGroup, SWProcessSplitType, SWProcessStep } from "@hm-design/sw"
// SW/Step Header demo data and tool icons (2026-11-03). Like a consuming program: the package ships no product
// icons, so the Strana tool pictures (HeaderStyles.xaml Header.Icon.*) live here. Fills that change with the button
// state use currentColor (the pill button color: #B6D0C9, hover / pressed #FFC600).
/** Strana Main Header process data (DesignPreviewData.cs). */
export const PROCESS_GROUPS: SWProcessGroup[] = [
{ id: "modeling", number: "01", label: "Modeling", steps: [{ id: "structure", label: "Structure" }, { id: "loads", label: "Loads" }] },
{ id: "analysis", number: "02", label: "Analysis Result", steps: [{ id: "results", label: "Results" }] },
]
/**
* StrAna-SW multi step data (Figma 873:16481 / 873:16254 / 873:17421). Groups without a Figma title keep their name for
* assistive technology only; the last two groups are not available yet (gray).
*/
export const MULTI_GROUPS: SWProcessGroup[] = [
{ id: "data", label: "데이터 구축", steps: [{ id: "data-input", label: "데이터입력" }, { id: "data-check", label: "데이터확인" }] },
{ id: "alignment", label: "선형 입력", labelHidden: true, steps: [{ id: "alignment-input", label: "선형입력" }] },
{
id: "structure", label: "구조물 상세 및 계획",
steps: [{ id: "body-plan", label: "본체계획" }, { id: "body-detail", label: "본체상세" }, { id: "wing-plan", label: "날개벽계획" }, { id: "wing-detail", label: "날개벽상세" }],
},
{ id: "condition", label: "설계 및 해석조건", labelHidden: true, disabled: true, steps: [{ id: "condition", label: "설계 및 해석조건" }] },
{
id: "analysis", label: "해석 및 성과품", labelHidden: true, disabled: true,
steps: [{ id: "analysis-model", label: "해석모델" }, { id: "design-review", label: "설계검토" }, { id: "deliverable", label: "성과품" }],
},
]
/** More groups than the Figma frame (8). */
export const MULTI_MANY_GROUPS: SWProcessGroup[] = [
...MULTI_GROUPS.slice(0, 3),
{ id: "drawing", label: "도면 작성", steps: [{ id: "drawing-create", label: "도면생성" }, { id: "drawing-edit", label: "도면편집" }] },
{ id: "quantity", label: "수량 산출", labelHidden: true, steps: [{ id: "quantity", label: "수량산출" }] },
...MULTI_GROUPS.slice(3),
{ id: "report", label: "보고서", disabled: true, steps: [{ id: "report-write", label: "보고서작성" }, { id: "report-print", label: "출력" }] },
]
/** More steps in one group (8 in 구조물 상세 및 계획). */
export const MULTI_MANY_STEPS: SWProcessGroup[] = MULTI_GROUPS.map(group => group.id !== "structure" ? group : {
...group,
steps: [
...group.steps,
{ id: "base-plan", label: "기초계획" }, { id: "base-detail", label: "기초상세" }, { id: "drain-plan", label: "배수계획" }, { id: "drain-detail", label: "배수상세" },
],
})
const OUTLINE = "#000"
export function ViewPropertyIcon() {
return (
<svg viewBox="0 0 24 24" width="24" height="24" aria-hidden="true">
<path d="M5,3.5 H19 C19.8284,3.5 20.5,4.1716 20.5,5 V19 C20.5,19.8285 19.8284,20.5 19,20.5 H5 C4.1716,20.5 3.5,19.8285 3.5,19 V5 C3.5,4.1716 4.1716,3.5 5,3.5 Z" fill="#0b3227" stroke={OUTLINE} />
<path d="M6.0469,5.5481 H17.9507 C18.2268,5.5481 18.4507,5.772 18.4507,6.0481 V17.9519 C18.4507,18.2281 18.2268,18.4519 17.9507,18.4519 H6.0469 C5.7707,18.4519 5.5469,18.2281 5.5469,17.9519 V6.0481 C5.5469,5.772 5.7707,5.5481 6.0469,5.5481 Z" fill="#003022" stroke={OUTLINE} />
<path fillRule="evenodd" fill="currentColor" d="M18.11,5.1359 C18.5265,5.1359 18.8642,5.4735 18.8642,5.8901 V18.11 C18.8642,18.5266 18.5265,18.8642 18.11,18.8642 H5.89 C5.4735,18.8642 5.1358,18.5266 5.1358,18.11 V5.8901 C5.1358,5.4735 5.4735,5.1359 5.89,5.1359 H18.11 Z M20,4.7542 C20,4.3377 19.6623,4 19.2458,4 H4.7542 C4.3377,4 4,4.3377 4,4.7542 V19.2459 C4,19.6624 4.3377,20 4.7542,20 H19.2458 C19.6623,20 20,19.6624 20,19.2459 V4.7542 Z" />
<path fill="currentColor" opacity="0.85" d="M6.7578,6.7586 H14.5249 V12.0545 H6.7578 Z M14.9258,6.7586 H17.2425 V12.0545 H14.9258 Z M12.9164,15.258 H13.9841 V17.4899 H12.9164 Z M10.1078,13.2172 H11.1755 V15.334 H10.1078 Z" />
<path fill="none" stroke={OUTLINE} strokeWidth="0.5" d="M6.7578,6.7586 H14.5249 V12.0545 H6.7578 Z M14.9258,6.7586 H17.2425 V12.0545 H14.9258 Z" />
<path fill="none" stroke={OUTLINE} strokeWidth="0.3" d="M12.9164,15.258 H13.9841 V17.4899 H12.9164 Z M10.1078,13.2172 H11.1755 V15.334 H10.1078 Z" />
<path fill="currentColor" stroke={OUTLINE} strokeWidth="0.3" opacity="0.5" d="M14.7445,15.7826 H17.1428 V16.8502 H14.7445 Z M11.8539,13.9657 H17.15 V15.0333 H11.8539 Z M6.8578,13.9657 H9.4288 V15.0333 H6.8578 Z M6.8578,15.7823 H12.1539 V16.85 H6.8578 Z" />
</svg>
)
}
/** Sub window button picture: two monitors; the back one brightens on hover (story CSS, like Strana). */
export function SubWindowIcon() {
return (
<svg viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" className="sw-process-story-sub-icon">
<g transform="translate(0 4.81)">
<path className="sw-process-story-sub-icon__back" fill="currentColor" d="M0.6836 1.4039C0.6836 1.0078 1.0047 0.6868 1.4007 0.6868H14.3084C14.7044 0.6868 15.0255 1.0078 15.0255 1.4039V10.0089C15.0255 10.4049 14.7044 10.726 14.3084 10.726H9.2888V12.4496H10.0057C10.4017 12.4496 10.7228 12.7059 10.7228 13.022C10.7228 13.3382 10.4017 13.5945 10.0057 13.5945H5.7031C5.3071 13.5945 4.986 13.3382 4.986 13.022C4.986 12.7059 5.3071 12.4496 5.7031 12.4496H6.4204V10.726H1.4007C1.0047 10.726 0.6836 10.4049 0.6836 10.0089V1.4039ZM1.8343 1.851V9.5785H7.8545H13.8715V1.851H1.8343Z" />
<path fill={OUTLINE} opacity="0.5" fillRule="evenodd" d="M0 1.40417C0 0.628669 0.628669 0 1.40417 0H14.3119C15.0874 0 15.716 0.628669 15.716 1.40417V10.0093C15.716 10.7848 15.0874 11.4135 14.3119 11.4135H9.97936V11.7629H10.0092C10.6322 11.7629 11.4133 12.1905 11.4133 13.0225C11.4133 13.8544 10.6322 14.282 10.0092 14.282H5.7066C5.08357 14.282 4.30243 13.8544 4.30243 13.0225C4.30243 12.1905 5.08357 11.7629 5.7066 11.7629H5.73682V11.4135H1.40417C0.628669 11.4135 0 10.7848 0 10.0093V1.40417ZM6.4239 12.45H5.7066C5.31056 12.45 4.98951 12.7063 4.98951 13.0225C4.98951 13.3386 5.31056 13.5949 5.7066 13.5949H10.0092C10.4052 13.5949 10.7263 13.3386 10.7263 13.0225C10.7263 12.7063 10.4052 12.45 10.0092 12.45H9.29228V10.7264H14.3119C14.7079 10.7264 15.029 10.4053 15.029 10.0093V1.40417C15.029 1.00813 14.7079 0.687077 14.3119 0.687077H1.40417C1.00813 0.687077 0.687077 1.00813 0.687077 1.40417V10.0093C0.687077 10.4053 1.00813 10.7264 1.40417 10.7264H6.4239V12.45ZM2.52486 2.53837V8.8918H13.1879V2.53837H2.52486ZM1.83778 1.85129H13.875V9.57887H1.83778V1.85129Z" />
<path fill="currentColor" d="M8.97266 1.40385C8.97266 1.00782 9.29371 0.686768 9.68975 0.686768H22.5975C22.9935 0.686768 23.3145 1.00782 23.3145 1.40385V10.0089C23.3145 10.4049 22.9935 10.726 22.5975 10.726H17.5779V12.4496H18.2948C18.6908 12.4496 19.0118 12.7059 19.0118 13.022C19.0118 13.3382 18.6908 13.5945 18.2948 13.5945H13.9922C13.5961 13.5945 13.2751 13.3382 13.2751 13.022C13.2751 12.7059 13.5961 12.4496 13.9922 12.4496H14.7095V10.726H9.68975C9.29371 10.726 8.97266 10.4049 8.97266 10.0089V1.40385ZM10.1234 1.85097V9.57847H16.1436H22.1606V1.85097H10.1234Z" />
<path fill={OUTLINE} fillRule="evenodd" d="M8.28125 1.40417C8.28125 0.628669 8.90992 0 9.68542 0H22.5931C23.3686 0 23.9973 0.628669 23.9973 1.40417V10.0093C23.9973 10.7848 23.3686 11.4135 22.5931 11.4135H18.2606V11.7629H18.2904C18.9135 11.7629 19.6946 12.1905 19.6946 13.0225C19.6946 13.8544 18.9134 14.282 18.2904 14.282H13.9879C13.3648 14.282 12.5837 13.8544 12.5837 13.0225C12.5837 12.1905 13.3648 11.7629 13.9879 11.7629H14.0181V11.4135H9.68542C8.90992 11.4135 8.28125 10.7848 8.28125 10.0093V1.40417ZM14.7052 12.45H13.9879C13.5918 12.45 13.2708 12.7063 13.2708 13.0225C13.2708 13.3386 13.5918 13.5949 13.9879 13.5949H18.2904C18.6865 13.5949 19.0075 13.3386 19.0075 13.0225C19.0075 12.7063 18.6865 12.45 18.2904 12.45H17.5735V10.7264H22.5931C22.9892 10.7264 23.3102 10.4053 23.3102 10.0093V1.40417C23.3102 1.00813 22.9892 0.687077 22.5931 0.687077H9.68542C9.28938 0.687077 8.96833 1.00813 8.96833 1.40417V10.0093C8.96833 10.4053 9.28938 10.7264 9.68542 10.7264H14.7052V12.45ZM10.8061 2.53837V8.8918H21.4692V2.53837H10.8061ZM10.119 1.85129H22.1563V9.57887H10.119V1.85129Z" />
<path fill="#0c372a" d="M10.7852 2.54395H21.476V8.97411H10.7852V2.54395Z" />
</g>
</svg>
)
}
/**
* Demo program state: every header state is the program's; actions without state (tools, minimize, close, file name,
* window move) have nothing to show and are no-ops.
*/
export function useProcessHeaderDemo(initialStep = "structure") {
const [stepId, setStepId] = useState(initialStep)
const [layerVisible, setLayerVisible] = useState(true)
const [layerOpen, setLayerOpen] = useState(false)
const [homeOpen, setHomeOpen] = useState(false)
const [viewProperty, setViewProperty] = useState(false)
const [maximized, setMaximized] = useState(true)
const [splitType, setSplitType] = useState<SWProcessSplitType>("grid")
const [splitOpen, setSplitOpen] = useState(false)
const none = () => {}
return {
stepId, layerVisible, layerOpen, homeOpen, viewProperty, maximized, splitType, splitOpen,
onSplitTypeChange: setSplitType,
onSplitOpenChange: setSplitOpen,
onStepSelect: (step: SWProcessStep) => setStepId(step.id),
onLayerVisibilityChange: setLayerVisible,
onLayerClick: () => setLayerOpen(open => !open),
onHomeClick: () => setHomeOpen(open => !open),
onViewProperty: () => setViewProperty(on => !on),
onTool: (_name: string) => none,
onMaximizeToggle: () => setMaximized(on => !on),
onMinimize: none,
onClose: none,
onDocumentClick: none,
onWindowMoveStart: none,
}
}
/**
* Strana Dark theme through token overrides on the outermost SW scope (docs/sw/sw-process-header-design-spec.md §7).
* Partial on purpose: shows the mechanism with the solid colors and the main surfaces; the rest keeps Hanmac.
*/
export const DARK_OVERRIDE = {
"--hm-sw-header-background": "#0b0d11",
"--hm-sw-header-text-color": "#f4f7fa",
"--hm-sw-header-title-color": "#f4f7fa",
"--hm-sw-header-selected-color": "#ffc833",
"--hm-sw-header-stripe-color": "rgba(63, 72, 86, 0.322)",
"--hm-sw-header-document-background": "linear-gradient(180deg, #12151a 0%, #181c23 8.69%, #1e232b 25.43%, #262c36 51.25%, #1e232b 80.03%, #1a1e25 89.76%, #12151a 100%)",
"--hm-sw-header-document-border-gradient": "linear-gradient(180deg, #3a4250 0%, #0b0d11 13.73%, #0b0d11 89.51%, #3f4856 100%)",
"--hm-sw-header-object-background": "linear-gradient(0deg, #1c2027 0%, #20252d 6%, #22272f 10%, #1a1e25 18%, #353d48 72%, #2a3039 83%, #1c2027 92%, #1e232b 100%)",
"--hm-sw-header-object-border-gradient": "linear-gradient(180deg, #313843 0%, #1e232b 13.57%, #74c4b4 37.06%, #12151a 80.5%, #2e353f 100%)",
"--hm-sw-process-base-background": "linear-gradient(180deg, #1c2027 0%, #4a5260 10.1%, #313843 18.27%, #1c2027 100%)",
"--hm-sw-process-dim": "rgba(11, 13, 17, 0.902)",
"--hm-sw-process-number-color": "#74c4b4",
"--hm-sw-process-group-color": "#c9d3de",
"--hm-sw-process-glow-halo": "rgba(116, 196, 180, 0.85)",
"--hm-sw-process-arrow-fill": "#74c4b4",
"--hm-sw-process-arrow-edge": "#1a1e25",
"--hm-sw-process-arrow-mid": "#4a5260",
"--hm-sw-process-arrow-light": "#5e8f87",
"--hm-sw-process-tab-glow": "rgba(74, 82, 96, 0.702)",
"--hm-sw-process-tab-border-gradient": "linear-gradient(180deg, #0b0d11 8.98%, #4a5260 22.9%, #262c36 100%)",
"--hm-sw-process-tab-depth": "linear-gradient(180deg, rgba(26, 30, 37, 0) 0%, rgba(26, 30, 37, 0.8) 100%)",
"--hm-sw-process-tab-sheen": "linear-gradient(180deg, rgba(116, 196, 180, 0.502) 0%, rgba(116, 196, 180, 0) 40%)",
"--hm-sw-process-tab-disabled-text": "#6d7784",
"--hm-sw-process-tool-icon-color": "#c9d3de",
} as CSSProperties
+8
View File
@@ -0,0 +1,8 @@
/* Story-owned layout for SW/Step Header. Like a consuming program it arranges public components and its own
fixture icons; it never styles hm-sw-* classes. Rows, stacks and scrollers are the shared SW story classes. */
.sw-process-story-screen { width: 100%; max-width: 1920px; background: #060606; }
.sw-process-story-canvas { height: 120px; background: var(--sw-story-canvas, #1b1b1b); }
.sw-process-story-surface { padding: 12px; border-radius: 4px; background: #060606; }
/* Strana Header.Icon.ToolSubMonitor: the back monitor is 20% and 50% while its button is hovered or pressed. */
.sw-process-story-sub-icon__back { opacity: 0.2; }
button:is(:hover, [aria-pressed="true"]) .sw-process-story-sub-icon__back { opacity: 0.5; }
+350
View File
@@ -0,0 +1,350 @@
import { useState, type ReactNode } from "react"
import type { Meta, StoryObj } from "@storybook/react-vite"
import {
SWProcessBar, SWProcessHeader, SWProcessSplitButton, SWTheme, SWToolButton, type SWProcessGroup, type SWProcessHeaderProps, type SWProcessSplitType,
} from "@hm-design/sw"
import "@hm-design/sw/styles.css"
import { StoryPage, StoryPageHeader, StorySection } from "@/components/story-page"
import {
DARK_OVERRIDE, MULTI_GROUPS, MULTI_MANY_GROUPS, MULTI_MANY_STEPS, PROCESS_GROUPS, SubWindowIcon, useProcessHeaderDemo, ViewPropertyIcon,
} from "./sw-process-header-fixture"
import "./sw-stories.css"
import "./sw-process-header-stories.css"
import placeholderLogo from "./assets/sw-header-logo-placeholder.svg"
import toolHelp from "./assets/process-header/tool-help.svg"
import toolView3d from "./assets/process-header/tool-view-3d.svg"
import toolControls from "./assets/process-header/tool-controls.svg"
import toolMenuList from "./assets/process-header/tool-menu-list.svg"
import toolExit from "./assets/process-header/tool-exit.svg"
import toolHelpHover from "./assets/process-header/tool-help-hover.svg"
import toolView3dHover from "./assets/process-header/tool-view-3d-hover.svg"
import toolControlsHover from "./assets/process-header/tool-controls-hover.svg"
import toolMenuListHover from "./assets/process-header/tool-menu-list-hover.svg"
import toolExitHover from "./assets/process-header/tool-exit-hover.svg"
// SW/Step Header (2026-11-03, shown as "Step Header"; the components keep the SWProcess* names): the Strana Main Header as an independent SW general-mode header. Public API only,
// like a consuming program. The logo is the temporary SW placeholder through `logoSrc` (replace with the real logo).
// Page layout as SW/Header and SW/Viewer: title, then sections; checks stay as verification stories (hidden).
const KICKER = "HM DESIGN SYSTEM / SW"
const LOGO = { logoSrc: placeholderLogo, logoAlt: "임시 로고" } satisfies Partial<SWProcessHeaderProps>
const meta = {
title: "SW/Step Header",
parameters: { layout: "fullscreen", controls: { disable: true } },
} satisfies Meta
export default meta
type Story = StoryObj<typeof meta>
interface SplitState { value: SWProcessSplitType; open?: boolean; defaultOpen?: boolean; onValueChange?: (value: SWProcessSplitType) => void; onOpenChange?: (open: boolean) => void }
/** The three Strana tools as host content of the pill: fixture icons (SWToolButton) and the package split tool. */
function Tools({ viewProperty = false, onViewProperty, onTool, split = { value: "grid" } }: {
viewProperty?: boolean; onViewProperty?: () => void; onTool?: (name: string) => () => void; split?: SplitState
}) {
return (
<>
<SWToolButton appearance="pill" icon={<ViewPropertyIcon />} pressed={viewProperty} onClick={onViewProperty} title="View Property">View Property</SWToolButton>
<SWProcessSplitButton {...split} />
<SWToolButton appearance="pill" icon={<SubWindowIcon />} onClick={onTool?.("subWindow")} title="Sub 창">Sub 창</SWToolButton>
</>
)
}
/** A header with fixed demo state (no program behind it). */
function StaticHeader({ step = "structure", ...props }: Partial<SWProcessHeaderProps> & { step?: string }) {
return (
<SWProcessHeader documentTitle="Example project" {...LOGO} process={{ groups: PROCESS_GROUPS, activeStepId: step }}
layer={{ label: "Layer", value: "Layer 0" }} tools={<Tools />} maximized {...props} />
)
}
function LiveHeader() {
const demo = useProcessHeaderDemo()
return (
<div className="sw-process-story-screen">
<SWProcessHeader
documentTitle="Example project" onDocumentClick={demo.onDocumentClick}
{...LOGO} onHomeClick={demo.onHomeClick} homeMenuOpen={demo.homeOpen}
process={{ groups: PROCESS_GROUPS, activeStepId: demo.stepId, onStepSelect: demo.onStepSelect }}
layer={{ label: "Layer", value: "Layer 0", visible: demo.layerVisible, open: demo.layerOpen }}
onLayerClick={demo.onLayerClick} onLayerVisibilityChange={demo.onLayerVisibilityChange}
tools={<Tools viewProperty={demo.viewProperty} onViewProperty={demo.onViewProperty} onTool={demo.onTool}
split={{ value: demo.splitType, open: demo.splitOpen, onValueChange: demo.onSplitTypeChange, onOpenChange: demo.onSplitOpenChange }} />}
onWindowMoveStart={demo.onWindowMoveStart} maximized={demo.maximized}
onMinimize={demo.onMinimize} onMaximizeToggle={demo.onMaximizeToggle} onClose={demo.onClose} />
<div className="sw-process-story-canvas" />
</div>
)
}
/**
* The five Figma tools (fixture icons from the Figma file; the package ships no product icons). Like the SW print
* button, each has a hover picture with the #B6D0C9 fill in #FFC600 (`hoverIcon`).
*/
function MultiTools({ onTool, split }: { onTool?: (name: string) => () => void; split?: SplitState }) {
const tool = (name: string, src: string, hover: string, label: string) => (
<SWToolButton appearance="pill" icon={<img src={src} alt="" />} hoverIcon={<img src={hover} alt="" />} onClick={onTool?.(name)} title={label}>{label}</SWToolButton>
)
return (
<>
{tool("help", toolHelp, toolHelpHover, "도움말")}{tool("view3d", toolView3d, toolView3dHover, "3D 보기")}
{split && <SWProcessSplitButton {...split} />}
{tool("controls", toolControls, toolControlsHover, "설정")}{tool("menu", toolMenuList, toolMenuListHover, "메뉴")}
{tool("exit", toolExit, toolExitHover, "나가기")}
</>
)
}
/** Figma multi step frame: no layer field, only minimize and close. */
function MultiHeader({ step = "data-input", groups = MULTI_GROUPS, ...props }: Partial<SWProcessHeaderProps> & { step?: string; groups?: SWProcessGroup[] }) {
return (
<SWProcessHeader appearance="multi" documentTitle="" documentEmptyLabel="프로젝트 생성 전" {...LOGO}
process={{ groups, activeStepId: step }} tools={<MultiTools />} hiddenControls={["maximize"]} {...props} />
)
}
/** A Figma multi step frame with its own program state (steps, logo, tools and window buttons respond). */
function LiveMultiHeader({ step, documentTitle = "" }: { step: string; documentTitle?: string }) {
const demo = useProcessHeaderDemo(step)
return (
<MultiHeader documentTitle={documentTitle} onDocumentClick={demo.onDocumentClick}
onHomeClick={demo.onHomeClick} homeMenuOpen={demo.homeOpen}
process={{ groups: MULTI_GROUPS, activeStepId: demo.stepId, onStepSelect: demo.onStepSelect }}
tools={<MultiTools onTool={demo.onTool} />}
onWindowMoveStart={demo.onWindowMoveStart} onMinimize={demo.onMinimize} onClose={demo.onClose} />
)
}
/** Split tool with a live layout (the selector opens on load; choosing a layout updates the icon and the checked cell). */
function useSplitDemo(initial: SWProcessSplitType): SplitState {
const [value, setValue] = useState(initial)
return { value, onValueChange: setValue, defaultOpen: true }
}
/** Row of a page: as wide as the Story column, at most `max` (like the SW/Header Logo and Responsive rows). */
function Row({ max = 1920, children }: { max?: number; children: ReactNode }) {
return <div style={{ width: "100%", maxWidth: max }}>{children}</div>
}
/** A fixed program width in a horizontal scroller (2560 / 1920 are wider than most pages). Verification only. */
function Fixed({ width, children }: { width: number; children: ReactNode }) {
return <div className="sw-story-scroller"><div style={{ width }} data-width={width}>{children}</div></div>
}
// ---------- Pages ----------
// Figma StrAna-SW multi step frames, in this order (the node ids stay as data only, never shown):
// 873:16481 no project yet, 873:16254 project open, 873:17421 a later step.
const FIGMA_FRAMES: { node: string; step: string; documentTitle?: string }[] = [
{ node: "873:16481", step: "data-input" },
{ node: "873:16254", step: "data-input", documentTitle: "Example project" },
{ node: "873:17421", step: "body-plan" },
]
// One page (2026-11-03): the Default header, then the three Multi Step frames; each header keeps its own state.
export const ProcessHeader: Story = {
name: "Step Header",
render: () => (
<StoryPage>
<StoryPageHeader title="SW Step Header" />
<StorySection title="Step Header">
<LiveHeader />
</StorySection>
<StorySection title="Multi Step">
<div className="sw-story-stack">
{FIGMA_FRAMES.map(frame => (
<Row key={frame.node}><div data-figma-node={frame.node}><LiveMultiHeader step={frame.step} documentTitle={frame.documentTitle} /></div></Row>
))}
</div>
</StorySection>
</StoryPage>
),
}
const WIDTHS = [1920, 1366, 1100]
export const Responsive: Story = {
name: "Responsive",
render: () => (
<StoryPage>
<StoryPageHeader title="SW Step Header — 화면 너비" />
<div className="sw-story-stack sw-story-responsive">
{WIDTHS.map(width => (
// The 1920 row shows only on a page with 1920px of room, like the SW Header / Viewer Responsive pages.
<div key={width} className={width === 1920 ? "sw-story-responsive-hidden" : undefined}>
<StorySection title={`${width}px`}>
<Row max={width}>
<div className="sw-story-stack" data-width={width}>
<StaticHeader />
<MultiHeader step="body-plan" documentTitle="Example project" />
</div>
</Row>
</StorySection>
</div>
))}
</div>
</StoryPage>
),
}
/** Split selector open in both appearances (Default leftTall, Multi rows), over the drawing area. */
function SplitOpenPage() {
const defaultSplit = useSplitDemo("leftTall")
const multiSplit = useSplitDemo("rows")
return (
<StoryPage>
<StoryPageHeader title="SW Step Header — 화면 분할" />
<div className="sw-story-stack">
<StorySection title="Default">
<div className="sw-process-story-screen" data-appearance="default"><StaticHeader tools={<Tools split={defaultSplit} />} /><div className="sw-process-story-canvas" /></div>
</StorySection>
<StorySection title="Multi Step">
<div className="sw-process-story-screen" data-appearance="multi"><MultiHeader documentTitle="Example project" tools={<MultiTools split={multiSplit} />} /><div className="sw-process-story-canvas" /></div>
</StorySection>
</div>
</StoryPage>
)
}
// Hidden from the sidebar (2026-11-03): the split tool works in the Step Header page; this open-state check stays.
export const SplitOpen: Story = {
name: "화면 분할",
tags: ["verification"],
render: () => <SplitOpenPage />,
}
// ---------- Verification (hidden from the sidebar; direct URLs kept for checks) ----------
/** The three Multi Step frames at the Figma 1920 width, marked with their node ids for comparisons. */
export const MultiStep: Story = {
name: "Multi Step",
tags: ["verification"],
render: () => (
<StoryPage>
<StoryPageHeader kicker={KICKER} title="Multi Step" />
<div className="sw-story-stack">
{FIGMA_FRAMES.map(frame => (
<div key={frame.node} data-figma-node={frame.node}><Fixed width={1920}><MultiHeader step={frame.step} documentTitle={frame.documentTitle ?? ""} /></Fixed></div>
))}
</div>
</StoryPage>
),
}
export const FixedWidths: Story = {
name: "Fixed Widths",
tags: ["verification"],
render: () => (
<StoryPage>
<StoryPageHeader kicker={KICKER} title="Fixed Widths" />
<div className="sw-story-stack">
{[1100, 1366, 1920, 2560].map(width => (
<StorySection key={width} title={`${width}px`}>
<div className="sw-story-stack">
<Fixed width={width}><StaticHeader /></Fixed>
<Fixed width={width}><MultiHeader step="body-plan" documentTitle="Example project" /></Fixed>
</div>
</StorySection>
))}
</div>
</StoryPage>
),
}
const DISABLED_LOADS: SWProcessGroup[] = [
{ ...PROCESS_GROUPS[0], steps: [PROCESS_GROUPS[0].steps[0], { ...PROCESS_GROUPS[0].steps[1], disabled: true }] },
PROCESS_GROUPS[1],
]
export const ProcessBar: Story = {
name: "Process Bar",
tags: ["verification"],
render: () => (
<StoryPage>
<StoryPageHeader kicker={KICKER} title="SWProcessBar" />
<SWTheme className="sw-process-story-surface">
<div className="sw-story-stack">
<div style={{ width: 1003 }}><SWProcessBar groups={PROCESS_GROUPS} activeStepId="structure" /></div>
<div style={{ width: 1003 }}><SWProcessBar groups={PROCESS_GROUPS} activeStepId="results" /></div>
<div style={{ width: 520 }}><SWProcessBar groups={PROCESS_GROUPS} activeStepId="loads" /></div>
<div style={{ width: 1003 }}><SWProcessBar groups={DISABLED_LOADS} activeStepId="structure" /></div>
<div style={{ width: 1003 }}><SWProcessBar groups={PROCESS_GROUPS} activeStepId="structure" disabled /></div>
<div style={{ width: 1278 }}><SWProcessBar appearance="multi" groups={MULTI_GROUPS} activeStepId="data-input" /></div>
<div style={{ width: 1278 }}><SWProcessBar appearance="multi" groups={MULTI_GROUPS} activeStepId="body-plan" /></div>
</div>
</SWTheme>
</StoryPage>
),
}
export const MultiStepManyGroups: Story = {
name: "Multi Step · Many Groups",
tags: ["verification"],
render: () => (
<StoryPage>
<StoryPageHeader kicker={KICKER} title="Multi Step · Many Groups" />
<div className="sw-story-stack">
<Fixed width={1920}><MultiHeader groups={MULTI_MANY_GROUPS} step="drawing-edit" documentTitle="Example project" /></Fixed>
<Fixed width={1920}><MultiHeader groups={MULTI_MANY_GROUPS} step="body-plan" documentTitle="Example project" /></Fixed>
</div>
</StoryPage>
),
}
export const MultiStepManySteps: Story = {
name: "Multi Step · Many Steps",
tags: ["verification"],
render: () => (
<StoryPage>
<StoryPageHeader kicker={KICKER} title="Multi Step · Many Steps" />
<div className="sw-story-stack">
<Fixed width={1920}><MultiHeader groups={MULTI_MANY_STEPS} step="drain-detail" documentTitle="Example project" /></Fixed>
<Fixed width={1920}><MultiHeader groups={MULTI_MANY_STEPS} step="data-check" documentTitle="Example project" /></Fixed>
</div>
</StoryPage>
),
}
// Three groups: renders, design not confirmed (trapezoids only on the first and last group). Verification only.
const THREE_GROUPS: SWProcessGroup[] = [
PROCESS_GROUPS[0],
{ id: "design", number: "02", label: "Design", steps: [{ id: "member", label: "Member" }, { id: "joint", label: "Joint", disabled: true }] },
{ ...PROCESS_GROUPS[1], number: "03" },
]
const STATES: [string, Partial<SWProcessHeaderProps>][] = [
["default", {}],
["results", { process: { groups: PROCESS_GROUPS, activeStepId: "results" } }],
["layer-open", { layer: { label: "Layer", value: "Layer 0", open: true, visible: false }, tools: <Tools viewProperty /> }],
["home-open", { homeMenuOpen: true, maximized: false }],
["disabled", { disabled: true }],
["hidden-controls", { hiddenControls: ["tools", "windowMove", "maximize"] }],
["long-names", { documentTitle: "A very long project file name for the ellipsis check.strn", layer: { label: "Layer", value: "Foundation_Pile_Cap_Layer_Long_Name" } }],
["three-groups", { process: { groups: THREE_GROUPS, activeStepId: "member" } }],
]
export const States: Story = {
name: "States",
tags: ["verification"],
render: () => (
<StoryPage>
<StoryPageHeader kicker={KICKER} title="States" />
<div className="sw-story-stack">
{STATES.map(([state, props]) => (
<div key={state} data-state={state}><Fixed width={1920}><StaticHeader {...props} /></Fixed></div>
))}
</div>
</StoryPage>
),
}
export const ThemeOverride: Story = {
name: "Theme Override",
tags: ["verification"],
render: () => (
<StoryPage>
<StoryPageHeader kicker={KICKER} title="Theme Override" />
<Fixed width={1920}><StaticHeader style={DARK_OVERRIDE} /></Fixed>
</StoryPage>
),
}