mac-human-design 0.1.20 → 0.1.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/changelog.md CHANGED
@@ -2,6 +2,38 @@
2
2
 
3
3
  This file tracks changes between published npm versions of `mac-human-design`.
4
4
 
5
+ ## 0.1.22
6
+
7
+ ### Added
8
+
9
+ - Added a centered loading spinner overlay for `SymbolIconButton` that shares
10
+ the icon button grid cell and respects reduced-motion preferences.
11
+ - Added `aria-busy` to loading `SymbolIconButton` instances.
12
+ - Extended the macOS design verifier to protect the loading spinner's centered
13
+ geometry, animation keyframes, reduced-motion behavior, and `aria-busy`
14
+ loading state.
15
+
16
+ ### Changed
17
+
18
+ - Kept the underlying symbol visible at reduced opacity while loading so the
19
+ button remains spatially stable.
20
+ - Bumped the package to `0.1.22`.
21
+
22
+ ## 0.1.21
23
+
24
+ ### Added
25
+
26
+ - Added macOS gallery coverage for loading and disabled `SymbolIconButton`
27
+ states plus info, success, and error `StatusMessage` states.
28
+ - Extended the macOS design verifier to require those icon and status states in
29
+ gallery builds.
30
+
31
+ ### Changed
32
+
33
+ - Added compact gallery status-stack styling for grouped status message
34
+ previews.
35
+ - Bumped the package to `0.1.21`.
36
+
5
37
  ## 0.1.20
6
38
 
7
39
  ### Added
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mac-human-design",
3
- "version": "0.1.20",
3
+ "version": "0.1.22",
4
4
  "description": "Reusable macOS-oriented UI primitives and SF Symbols bridge for Tauri apps.",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
@@ -7,6 +7,7 @@ const stylesPath = path.join(repoRoot, "src", "styles", "macosBaseUi.css");
7
7
  const packageJsonPath = path.join(repoRoot, "package.json");
8
8
  const wrapperPath = path.join(repoRoot, "src", "components", "MacBaseUI.tsx");
9
9
  const symbolIconButtonPath = path.join(repoRoot, "src", "components", "SymbolIconButton.tsx");
10
+ const galleryPath = path.join(repoRoot, "src", "components", "MacBaseUIGallery.tsx");
10
11
  const symbolServicePath = path.join(repoRoot, "src", "symbols", "systemSymbolService.ts");
11
12
 
12
13
  function readText(filePath) {
@@ -46,6 +47,7 @@ const stylesSource = readText(stylesPath);
46
47
  const packageJson = JSON.parse(readText(packageJsonPath));
47
48
  const wrapperSource = readText(wrapperPath);
48
49
  const symbolIconButtonSource = readText(symbolIconButtonPath);
50
+ const gallerySource = readText(galleryPath);
49
51
  const symbolServiceSource = readText(symbolServicePath);
50
52
 
51
53
  function getCssRuleBody(selector) {
@@ -136,6 +138,10 @@ requireCssDeclarations(".hd-mac-symbol-icon-button", [
136
138
  ["fixed 30px min-height", /min-height\s*:\s*30px\s*;/],
137
139
  ]);
138
140
 
141
+ requireCssDeclarations(".hd-mac-symbol-icon-button::after", [
142
+ ["loading overlay grid placement", /grid-area\s*:\s*1\s*\/\s*1\s*;/],
143
+ ]);
144
+
139
145
  requireCssDeclarations(".hd-mac-symbol-icon", [
140
146
  ["single grid cell placement", /grid-area\s*:\s*1\s*\/\s*1\s*;/],
141
147
  ["flex centering display", /display\s*:\s*inline-flex\s*;/],
@@ -182,6 +188,7 @@ const symbolIconRequirements = [
182
188
  ["SymbolIconButton imports MacIconButton", /import\s+\{\s*MacIconButton,\s*MacTooltip\s*\}\s+from\s+["']\.\/MacBaseUI["']/],
183
189
  ["SymbolIconButton render element is MacIconButton", /render=\{\s*<MacIconButton\b/],
184
190
  ["SymbolIconButton applies hd-mac-symbol-icon-button class", /className=["']hd-mac-symbol-icon-button["']/],
191
+ ["SymbolIconButton exposes aria-busy loading state", /aria-busy=\{isLoading \|\| undefined\}/],
185
192
  ["masked symbol class path", /className=["']hd-mac-symbol-icon hd-mac-symbol-icon-mask["']/],
186
193
  ["fallback symbol class path", /className=["']hd-mac-symbol-icon hd-mac-symbol-icon-fallback["']/],
187
194
  ["mask centering", /maskPosition:\s*["']center["']/],
@@ -196,6 +203,52 @@ if (missingSymbolIconRequirements.length > 0) {
196
203
  fail("Missing SymbolIconButton alignment invariants.", missingSymbolIconRequirements);
197
204
  }
198
205
 
206
+ const missingGalleryStateCoverage = [
207
+ ["loading symbol icon button", /<SymbolIconButton[\s\S]*?\bisLoading\b/],
208
+ ["disabled symbol icon button", /<SymbolIconButton[\s\S]*?\bdisabled\b/],
209
+ ["info status message", /<StatusMessage\s+intent=["']info["']/],
210
+ ["success status message", /<StatusMessage\s+intent=["']success["']/],
211
+ ["error status message", /<StatusMessage\s+intent=["']error["']/],
212
+ ].filter(([, pattern]) => !pattern.test(gallerySource));
213
+
214
+ if (missingGalleryStateCoverage.length > 0) {
215
+ fail(
216
+ "Missing macOS gallery coverage for critical icon and status states.",
217
+ missingGalleryStateCoverage.map(([label]) => label),
218
+ );
219
+ }
220
+
221
+ const loadingIconRule = getCssRuleBody(".hd-mac-symbol-icon-button[data-loading]::after");
222
+ const missingLoadingIconDeclarations = [
223
+ ["centered loading spinner content", /content\s*:\s*""\s*;/],
224
+ ["spinner width", /width\s*:\s*15px\s*;/],
225
+ ["spinner height", /height\s*:\s*15px\s*;/],
226
+ ["spinner automatic centering margin", /margin\s*:\s*auto\s*;/],
227
+ ["spinner center transform origin", /transform-origin\s*:\s*center\s*;/],
228
+ ["spinner animation", /animation\s*:\s*mac-symbol-icon-spin\s+720ms\s+linear\s+infinite\s*;/],
229
+ ].filter(([, pattern]) => !pattern.test(loadingIconRule));
230
+
231
+ if (missingLoadingIconDeclarations.length > 0) {
232
+ fail(
233
+ "Missing centered loading affordance declarations for SymbolIconButton.",
234
+ missingLoadingIconDeclarations.map(([label]) => label),
235
+ );
236
+ }
237
+
238
+ if (!/@keyframes\s+mac-symbol-icon-spin/.test(stylesSource)) {
239
+ fail("Missing SymbolIconButton loading spinner keyframes.", ["hd-mac-symbol-icon-spin"]);
240
+ }
241
+
242
+ if (
243
+ !/@media\s*\(prefers-reduced-motion:\s*reduce\)[\s\S]*?\.hd-mac-symbol-icon-button\[data-loading\]::after[\s\S]*?animation-name\s*:\s*none\s*!important/.test(
244
+ stylesSource,
245
+ )
246
+ ) {
247
+ fail("Missing reduced-motion handling for SymbolIconButton loading spinner.", [
248
+ ".hd-mac-symbol-icon-button[data-loading]::after",
249
+ ]);
250
+ }
251
+
199
252
  const missingSymbolServiceRequirements = [
200
253
  ["transparent symbol padding trim", /trimTransparentSymbolPadding/],
201
254
  ["alpha threshold trim", /TRANSPARENT_ALPHA_THRESHOLD/],
@@ -56,6 +56,7 @@ import {
56
56
  import { MacDataTable } from "./MacDataTable";
57
57
  import { MacSegmentedControl } from "./MacSegmentedControl";
58
58
  import { MacWindowToolbar } from "./MacWindowToolbar";
59
+ import { StatusMessage } from "./StatusMessage";
59
60
  import { SymbolIconButton } from "./SymbolIconButton";
60
61
 
61
62
  const choices = [
@@ -97,6 +98,8 @@ export function MacBaseUIGallery() {
97
98
  <SymbolIconButton label="Refresh" symbolName="arrow.clockwise" fallback="↻" onClick={() => {}} />
98
99
  <SymbolIconButton label="Upload" symbolName="square.and.arrow.up" fallback="↑" onClick={() => {}} />
99
100
  <SymbolIconButton label="Fallback refresh" symbolName="arrow.clockwise" fallback="↻" onClick={() => {}} symbolEnabled={false} />
101
+ <SymbolIconButton label="Loading refresh" symbolName="arrow.clockwise" fallback="↻" onClick={() => {}} isLoading />
102
+ <SymbolIconButton label="Disabled upload" symbolName="square.and.arrow.up" fallback="↑" onClick={() => {}} disabled />
100
103
  <MacHelpButton aria-label="Help">?</MacHelpButton>
101
104
  </GallerySection>
102
105
 
@@ -366,6 +369,7 @@ export function MacBaseUIGallery() {
366
369
  <MacButton disabled>Disabled</MacButton>
367
370
  <MacPrimaryButton disabled>Disabled Primary</MacPrimaryButton>
368
371
  <MacInput disabled placeholder="Disabled text field" />
372
+ <SymbolIconButton label="Disabled refresh" symbolName="arrow.clockwise" fallback="↻" onClick={() => {}} disabled />
369
373
  <label className="hd-mac-gallery-inline-choice">
370
374
  <MacCheckbox.Root indeterminate>
371
375
  <MacCheckbox.Indicator />
@@ -378,6 +382,11 @@ export function MacBaseUIGallery() {
378
382
  </GallerySection>
379
383
 
380
384
  <GallerySection title="Feedback">
385
+ <div className="hd-mac-gallery-status-stack">
386
+ <StatusMessage intent="info" message="Connected to the selected bucket." />
387
+ <StatusMessage intent="success" message="Upload completed." />
388
+ <StatusMessage intent="error" message="Unable to fetch object metadata." />
389
+ </div>
381
390
  <MacProgress.Root value={62}>
382
391
  <MacProgress.Label>Progress</MacProgress.Label>
383
392
  <MacProgress.Track>
@@ -38,6 +38,7 @@ export function SymbolIconButton({
38
38
  render={
39
39
  <MacIconButton
40
40
  aria-label={label}
41
+ aria-busy={isLoading || undefined}
41
42
  title={label}
42
43
  disabled={disabled || isLoading}
43
44
  onClick={onClick}
@@ -76,6 +76,7 @@
76
76
  .hd-mac-avatar,
77
77
  .hd-mac-scroll-thumb,
78
78
  .hd-mac-status-message,
79
+ .hd-mac-symbol-icon-button[data-loading]::after,
79
80
  .hd-mac-window-toolbar,
80
81
  .hd-mac-data-table,
81
82
  .hd-mac-data-table-row {
@@ -84,6 +85,10 @@
84
85
  animation-iteration-count: 1 !important;
85
86
  scroll-behavior: auto !important;
86
87
  }
88
+
89
+ .hd-mac-symbol-icon-button[data-loading]::after {
90
+ animation-name: none !important;
91
+ }
87
92
  }
88
93
 
89
94
  .hd-mac,
@@ -279,6 +284,10 @@
279
284
  border-radius: 7px;
280
285
  }
281
286
 
287
+ .hd-mac-symbol-icon-button::after {
288
+ grid-area: 1 / 1;
289
+ }
290
+
282
291
  .hd-mac-symbol-icon {
283
292
  grid-area: 1 / 1;
284
293
  display: inline-flex;
@@ -955,7 +964,31 @@
955
964
  }
956
965
 
957
966
  .hd-mac-symbol-icon-button[data-loading] {
958
- opacity: 0.62;
967
+ opacity: 1;
968
+ color: var(--hd-mac-blue);
969
+ }
970
+
971
+ .hd-mac-symbol-icon-button[data-loading] .hd-mac-symbol-icon {
972
+ opacity: 0.22;
973
+ }
974
+
975
+ .hd-mac-symbol-icon-button[data-loading]::after {
976
+ content: "";
977
+ width: 15px;
978
+ height: 15px;
979
+ border: 1.5px solid color-mix(in srgb, currentColor 28%, transparent);
980
+ border-top-color: currentColor;
981
+ border-radius: 999px;
982
+ box-sizing: border-box;
983
+ margin: auto;
984
+ transform-origin: center;
985
+ animation: mac-symbol-icon-spin 720ms linear infinite;
986
+ }
987
+
988
+ @keyframes mac-symbol-icon-spin {
989
+ to {
990
+ transform: rotate(360deg);
991
+ }
959
992
  }
960
993
 
961
994
  .hd-mac-toggle[data-pressed] {
@@ -1544,6 +1577,16 @@
1544
1577
  font: 400 13px/18px var(--hd-mac-font);
1545
1578
  }
1546
1579
 
1580
+ .hd-mac-gallery-status-stack {
1581
+ display: grid;
1582
+ min-width: min(340px, 100%);
1583
+ gap: 6px;
1584
+ }
1585
+
1586
+ .hd-mac-gallery-status-stack > .hd-mac-status-message {
1587
+ margin-top: 0;
1588
+ }
1589
+
1547
1590
  .hd-mac-gallery-scroll {
1548
1591
  width: 190px;
1549
1592
  height: 48px;