@xingwangzhe/stalux 1.43.0 → 1.44.0

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.
Files changed (87) hide show
  1. package/README.md +6 -2
  2. package/package.json +4 -2
  3. package/public/background/pattern-1.min.webp +0 -0
  4. package/public/background/pattern-10.min.webp +0 -0
  5. package/public/background/pattern-11.min.webp +0 -0
  6. package/public/background/pattern-12.min.webp +0 -0
  7. package/public/background/pattern-13.min.webp +0 -0
  8. package/public/background/pattern-14.min.webp +0 -0
  9. package/public/background/pattern-15.min.webp +0 -0
  10. package/public/background/pattern-16.min.webp +0 -0
  11. package/public/background/pattern-17.min.webp +0 -0
  12. package/public/background/pattern-18.min.webp +0 -0
  13. package/public/background/pattern-19.min.webp +0 -0
  14. package/public/background/pattern-2.min.webp +0 -0
  15. package/public/background/pattern-20.min.webp +0 -0
  16. package/public/background/pattern-21.min.webp +0 -0
  17. package/public/background/pattern-22.min.webp +0 -0
  18. package/public/background/pattern-23.min.webp +0 -0
  19. package/public/background/pattern-24.min.webp +0 -0
  20. package/public/background/pattern-25.min.webp +0 -0
  21. package/public/background/pattern-26.min.webp +0 -0
  22. package/public/background/pattern-27.min.webp +0 -0
  23. package/public/background/pattern-28.min.webp +0 -0
  24. package/public/background/pattern-29.min.webp +0 -0
  25. package/public/background/pattern-3.min.webp +0 -0
  26. package/public/background/pattern-30.min.webp +0 -0
  27. package/public/background/pattern-31.min.webp +0 -0
  28. package/public/background/pattern-32.min.webp +0 -0
  29. package/public/background/pattern-33.min.webp +0 -0
  30. package/public/background/pattern-34.min.webp +0 -0
  31. package/public/background/pattern-35.min.webp +0 -0
  32. package/public/background/pattern-36.min.webp +0 -0
  33. package/public/background/pattern-37.min.webp +0 -0
  34. package/public/background/pattern-38.min.webp +0 -0
  35. package/public/background/pattern-39.min.webp +0 -0
  36. package/public/background/pattern-4.min.webp +0 -0
  37. package/public/background/pattern-40.min.webp +0 -0
  38. package/public/background/pattern-41.min.webp +0 -0
  39. package/public/background/pattern-42.min.webp +0 -0
  40. package/public/background/pattern-5.min.webp +0 -0
  41. package/public/background/pattern-6.min.webp +0 -0
  42. package/public/background/pattern-7.min.webp +0 -0
  43. package/public/background/pattern-8.min.webp +0 -0
  44. package/public/background/pattern-9.min.webp +0 -0
  45. package/src/components/stalux/archives/toArchive.astro +1 -1
  46. package/src/components/stalux/categories/categoriesCard.astro +1 -1
  47. package/src/components/stalux/common/author.astro +1 -1
  48. package/src/components/stalux/footer/FooterBadges.astro +5 -1
  49. package/src/components/stalux/layout/PageHeading.astro +2 -2
  50. package/src/components/stalux/layout/footer.astro +5 -1
  51. package/src/components/stalux/links/linkCard.astro +7 -1
  52. package/src/components/stalux/links/socialMedia.astro +1 -0
  53. package/src/components/stalux/posts/ArticleSummary.astro +6 -1
  54. package/src/components/stalux/posts/WalineComment.astro +1 -0
  55. package/src/components/stalux/posts/postCC.astro +1 -1
  56. package/src/components/stalux/posts/postCard.astro +4 -1
  57. package/src/components/stalux/posts/postContent.astro +1 -1
  58. package/src/components/stalux/posts/postLeft.astro +1 -1
  59. package/src/components/stalux/posts/postNavigation.astro +5 -1
  60. package/src/components/stalux/posts/postRight.astro +2 -2
  61. package/src/components/stalux/tags/tagHeader.astro +1 -1
  62. package/src/components/stalux/tags/tagsCloud.astro +3 -1
  63. package/src/components/stalux/words/wordCard.astro +5 -1
  64. package/src/internal/public-assets.ts +3 -3
  65. package/src/internal/style-names.generated.ts +20 -22
  66. package/src/layouts/Stalux.astro +3 -1
  67. package/src/pages/404.astro +2 -1
  68. package/src/pages/index.astro +5 -1
  69. package/src/scripts/background.ts +54 -113
  70. package/src/scripts/module-motion.ts +70 -0
  71. package/src/scripts/random-posts.ts +82 -47
  72. package/src/scripts/route-motion.ts +48 -24
  73. package/src/scripts/route-out.ts +40 -0
  74. package/src/scripts/smooth-scroll.ts +52 -0
  75. package/src/scripts/swup-router.ts +25 -9
  76. package/src/scripts/tags-cloud.ts +8 -3
  77. package/src/styles/base.css +2 -2
  78. package/src/styles/generated-article.css +1 -1
  79. package/src/styles/generated-links.css +1 -1
  80. package/src/styles/generated-waline.css +1 -1
  81. package/src/styles/generated-words.css +1 -1
  82. package/src/styles/generated.css +1 -1
  83. package/src/styles/integrations.css +1 -17
  84. package/src/styles/module-motion.css +174 -0
  85. package/src/styles/motion.css +2 -21
  86. package/src/utils/route-motion-policy.ts +5 -1
  87. package/src/utils/toc-scrollspy.ts +21 -14
@@ -0,0 +1,174 @@
1
+ /* Module cues share a short, non-spring response. No hidden pre-animation state. */
2
+ :root {
3
+ --stalux-motion-fast: 140ms;
4
+ --stalux-motion-ease: cubic-bezier(0.2, 0.7, 0.2, 1);
5
+ }
6
+ [data-stalux-control] {
7
+ transition:
8
+ color var(--stalux-motion-fast) ease,
9
+ background-color var(--stalux-motion-fast) ease,
10
+ border-color var(--stalux-motion-fast) ease,
11
+ transform var(--stalux-motion-fast) var(--stalux-motion-ease);
12
+ }
13
+ [data-stalux-control]:focus-visible,
14
+ [data-stalux-control]:has(:focus-visible) {
15
+ outline: 2px solid var(--stalux-accent-color);
16
+ outline-offset: 4px;
17
+ }
18
+ [data-stalux-control="button"] {
19
+ display: inline-flex;
20
+ align-items: center;
21
+ justify-content: center;
22
+ min-height: 44px;
23
+ }
24
+ [data-stalux-control="avatar"] img {
25
+ transition: transform 180ms var(--stalux-motion-ease);
26
+ }
27
+ [data-stalux-control="social"] {
28
+ transition:
29
+ color 140ms ease,
30
+ transform 140ms var(--stalux-motion-ease);
31
+ }
32
+ [data-stalux-control="link-card"] img {
33
+ animation: none;
34
+ transition:
35
+ transform 180ms var(--stalux-motion-ease),
36
+ border-color 140ms ease;
37
+ }
38
+ [data-stalux-module="footer"] a,
39
+ [data-stalux-back-to-top] {
40
+ transition:
41
+ color 140ms ease,
42
+ background-color 140ms ease,
43
+ opacity 140ms ease;
44
+ }
45
+ [data-stalux-module="badge-group"][open] > div {
46
+ animation: stalux-module-fade 140ms ease-out;
47
+ }
48
+ pagefind-modal#search dialog[open] {
49
+ animation: stalux-module-arrive 160ms var(--stalux-motion-ease) !important;
50
+ }
51
+ pagefind-modal dialog::backdrop {
52
+ background: rgb(0 0 0 / 0.65) !important;
53
+ animation: stalux-module-backdrop 140ms ease-out !important;
54
+ }
55
+ @keyframes stalux-module-arrive {
56
+ from {
57
+ opacity: 0.88;
58
+ transform: translateY(4px);
59
+ }
60
+ to {
61
+ opacity: 1;
62
+ transform: translateY(0);
63
+ }
64
+ }
65
+ @keyframes stalux-module-fade {
66
+ from {
67
+ opacity: 0.88;
68
+ }
69
+ to {
70
+ opacity: 1;
71
+ }
72
+ }
73
+ @keyframes stalux-module-backdrop {
74
+ from {
75
+ opacity: 0;
76
+ }
77
+ to {
78
+ opacity: 1;
79
+ }
80
+ }
81
+ @media (hover: hover) and (pointer: fine) {
82
+ [data-stalux-control="button"]:hover,
83
+ [data-stalux-control="social"]:hover,
84
+ [data-stalux-control="tag-card"]:hover {
85
+ transform: translateY(-2px);
86
+ }
87
+ [data-stalux-control="avatar"]:hover img,
88
+ [data-stalux-control="link-card"]:hover img {
89
+ animation: none;
90
+ transform: rotate(3deg);
91
+ }
92
+ }
93
+ [data-stalux-control]:active {
94
+ transform: translateY(0);
95
+ }
96
+ @media (prefers-reduced-motion: reduce) {
97
+ [data-stalux-control],
98
+ [data-stalux-control] *,
99
+ [data-stalux-module],
100
+ [data-stalux-module] *,
101
+ [data-ref="stalux-nav-list"],
102
+ [data-ref="stalux-nav-overlay"],
103
+ pagefind-modal#search dialog[open],
104
+ pagefind-modal#search dialog::backdrop {
105
+ animation: none !important;
106
+ transition: none !important;
107
+ scroll-behavior: auto !important;
108
+ }
109
+ [data-stalux-control]:is(:hover, :active),
110
+ [data-stalux-control]:hover img {
111
+ transform: none !important;
112
+ }
113
+ [data-stalux-tag-cards] {
114
+ display: block;
115
+ }
116
+ [data-stalux-tag-canvas] {
117
+ display: none;
118
+ }
119
+ }
120
+ @media print {
121
+ [data-stalux-module],
122
+ [data-stalux-control],
123
+ pagefind-modal dialog {
124
+ animation: none !important;
125
+ transform: none !important;
126
+ }
127
+ }
128
+
129
+ /* A location marker fades over the surface without repainting text shadows. */
130
+ [data-stalux-module="word"]::after {
131
+ content: "";
132
+ position: absolute;
133
+ inset: 0;
134
+ border-radius: inherit;
135
+ background: var(--accent-20p);
136
+ opacity: 0;
137
+ pointer-events: none;
138
+ }
139
+ [data-stalux-module="word"]:is(:target, [data-glow])::after {
140
+ animation: stalux-module-locate 1200ms ease-out;
141
+ }
142
+ @keyframes stalux-module-locate {
143
+ from {
144
+ opacity: 0.4;
145
+ }
146
+ to {
147
+ opacity: 0;
148
+ }
149
+ }
150
+ @media (prefers-reduced-motion: reduce) {
151
+ [data-stalux-module="word"]::after {
152
+ animation: none !important;
153
+ }
154
+ }
155
+
156
+ @media (max-width: 640px) and (prefers-reduced-motion: no-preference) {
157
+ pagefind-modal#search dialog[open] {
158
+ animation: stalux-module-fade 120ms ease-out !important;
159
+ }
160
+ }
161
+ [data-stalux-weather][data-weather-state="ready"] [data-weather-output] {
162
+ animation: stalux-module-fade 140ms ease-out;
163
+ }
164
+ @media (prefers-reduced-motion: reduce) {
165
+ [data-stalux-weather] [data-weather-output] {
166
+ animation: none !important;
167
+ }
168
+ }
169
+
170
+ @media print {
171
+ [data-stalux-module="word"]::after {
172
+ animation: none !important;
173
+ }
174
+ }
@@ -7,8 +7,8 @@
7
7
  }
8
8
  }
9
9
 
10
- /* Swup's JS plugin animates one visible heading through route-motion.ts.
11
- There is no full-page snapshot, waiting body, stagger or native VT layer. */
10
+ /* Swup animates one bounded introductory region through route-motion.ts.
11
+ Long documents stay visible; the shell is never part of an outgoing layer. */
12
12
  [data-stalux-home-content] {
13
13
  display: flex;
14
14
  flex-direction: column;
@@ -195,22 +195,3 @@
195
195
  }
196
196
  }
197
197
  }
198
-
199
- @layer components {
200
- @keyframes stalux-word-word-glow {
201
- 0% {
202
- box-shadow:
203
- 0 0 30px var(--accent-50p),
204
- 0 0 80px var(--accent-30p),
205
- var(--shadow-lg);
206
- transform: scale(1.02);
207
- }
208
- 100% {
209
- box-shadow:
210
- 0 0 20px var(--accent-40p),
211
- 0 0 60px var(--accent-20p),
212
- var(--shadow-lg);
213
- transform: scale(1);
214
- }
215
- }
216
- }
@@ -55,7 +55,11 @@ export function getRouteMotionPreset(context: MotionContext): RouteMotionPreset
55
55
  }
56
56
  if (target === "article") return "enter";
57
57
  if (target === "about" || target === "links" || target === "words") return "panel";
58
- if (target === "tags-detail" || target === "categories-detail") return "taxonomy";
58
+ if (target === "tags-detail" || target === "categories-detail") {
59
+ if (source === target) return "taxonomy";
60
+ if (source === "tags-detail" || source === "categories-detail") return "glide";
61
+ return "enter";
62
+ }
59
63
  if (
60
64
  (source === "article" &&
61
65
  (target === "archive" || target === "tags-index" || target === "categories-index")) ||
@@ -55,7 +55,26 @@ export function initTocScrollSpy(activeClass: string): (() => void) | undefined
55
55
  activeLink = link;
56
56
  if (link && !sidebarHovered) {
57
57
  link.classList.add(activeClass);
58
- link.scrollIntoView({ block: "nearest", behavior: "smooth" });
58
+ // Scroll only the TOC pane. scrollIntoView also scrolls the page,
59
+ // fighting anchor navigation and the reader's wheel/touch input.
60
+ const scrollPane = sidebar?.closest<HTMLElement>("[data-stalux-scroll-pane]");
61
+ if (scrollPane) {
62
+ const item = link.getBoundingClientRect();
63
+ const pane = scrollPane.getBoundingClientRect();
64
+ const delta =
65
+ item.top < pane.top
66
+ ? item.top - pane.top
67
+ : item.bottom > pane.bottom
68
+ ? item.bottom - pane.bottom
69
+ : 0;
70
+ if (delta)
71
+ scrollPane.scrollTo({
72
+ top: scrollPane.scrollTop + delta,
73
+ behavior: window.matchMedia("(prefers-reduced-motion: reduce)").matches
74
+ ? "instant"
75
+ : "smooth",
76
+ });
77
+ }
59
78
  } else if (link) {
60
79
  // 用户正在操作侧边栏时只高亮,不自动滚动
61
80
  link.classList.add(activeClass);
@@ -107,19 +126,7 @@ export function initTocScrollSpy(activeClass: string): (() => void) | undefined
107
126
 
108
127
  for (const h of headings) observer.observe(h);
109
128
 
110
- // 拦截 TOC 锚点点击,替换为平滑滚动
111
- for (const link of tocLinks) {
112
- link.addEventListener(
113
- "click",
114
- (event) => {
115
- event.preventDefault();
116
- const id = link.getAttribute("href")?.replace("#", "");
117
- const target = id ? document.getElementById(id) : null;
118
- target?.scrollIntoView({ behavior: "smooth", block: "start" });
119
- },
120
- { signal: controller.signal },
121
- );
122
- }
129
+ // Swup owns anchor scrolling, history and interruption for TOC links too.
123
130
 
124
131
  return () => {
125
132
  controller.abort();