@farming-labs/astro-theme 0.0.48 → 0.0.51

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@farming-labs/astro-theme",
3
- "version": "0.0.48",
3
+ "version": "0.0.51",
4
4
  "description": "Astro UI components for @farming-labs/docs — layout, sidebar, TOC, search, and theme toggle",
5
5
  "keywords": [
6
6
  "astro",
@@ -79,8 +79,8 @@
79
79
  },
80
80
  "dependencies": {
81
81
  "sugar-high": "^0.9.5",
82
- "@farming-labs/astro": "0.0.48",
83
- "@farming-labs/docs": "0.0.48"
82
+ "@farming-labs/astro": "0.0.51",
83
+ "@farming-labs/docs": "0.0.51"
84
84
  },
85
85
  "peerDependencies": {
86
86
  "astro": ">=4.0.0"
@@ -127,6 +127,104 @@ const localizedParentUrl = withLang(parentUrl);
127
127
  </div>
128
128
 
129
129
  <script>
130
+ let hoverLinkGlobalsBound = false;
131
+
132
+ function setHoverLinkOpen(root, open) {
133
+ if (!(root instanceof HTMLElement)) return;
134
+ const trigger = root.querySelector('.fd-hover-link-trigger');
135
+ const popover = root.querySelector('.fd-hover-link-popover');
136
+ if (!(trigger instanceof HTMLElement) || !(popover instanceof HTMLElement)) return;
137
+
138
+ root.classList.toggle('fd-hover-link-open', open);
139
+ trigger.setAttribute('aria-expanded', String(open));
140
+ popover.setAttribute('aria-hidden', String(!open));
141
+ }
142
+
143
+ function closeOpenHoverLinks(event) {
144
+ document.querySelectorAll('[data-hover-link].fd-hover-link-open').forEach((root) => {
145
+ if (!(root instanceof HTMLElement)) return;
146
+ if (event.target instanceof Node && root.contains(event.target)) return;
147
+ setHoverLinkOpen(root, false);
148
+ });
149
+ }
150
+
151
+ function bindHoverLinks() {
152
+ document.querySelectorAll('[data-hover-link]').forEach((root) => {
153
+ if (!(root instanceof HTMLElement)) return;
154
+ if (root.dataset.fdHoverLinkBound === 'true') return;
155
+ root.dataset.fdHoverLinkBound = 'true';
156
+
157
+ const trigger = root.querySelector('.fd-hover-link-trigger');
158
+ const popover = root.querySelector('.fd-hover-link-popover');
159
+ if (!(trigger instanceof HTMLElement) || !(popover instanceof HTMLElement)) return;
160
+
161
+ let closeTimer = 0;
162
+ const containsTarget = (target) => target instanceof Node && root.contains(target);
163
+ const clearCloseTimer = () => {
164
+ if (closeTimer !== 0) {
165
+ window.clearTimeout(closeTimer);
166
+ closeTimer = 0;
167
+ }
168
+ };
169
+
170
+ const openPopover = () => {
171
+ clearCloseTimer();
172
+ setHoverLinkOpen(root, true);
173
+ };
174
+ const closePopover = () => {
175
+ clearCloseTimer();
176
+ setHoverLinkOpen(root, false);
177
+ };
178
+ const closePopoverSoon = () => {
179
+ clearCloseTimer();
180
+ closeTimer = window.setTimeout(closePopover, 90);
181
+ };
182
+
183
+ trigger.addEventListener('pointerenter', openPopover);
184
+ trigger.addEventListener('pointerleave', (event) => {
185
+ if (containsTarget(event.relatedTarget)) return;
186
+ closePopoverSoon();
187
+ });
188
+ trigger.addEventListener('focus', (event) => {
189
+ if (!(event.currentTarget instanceof HTMLElement)) return;
190
+ if (typeof event.currentTarget.matches === 'function' && !event.currentTarget.matches(':focus-visible')) {
191
+ return;
192
+ }
193
+ openPopover();
194
+ });
195
+ trigger.addEventListener('blur', (event) => {
196
+ if (containsTarget(event.relatedTarget)) return;
197
+ closePopoverSoon();
198
+ });
199
+ trigger.addEventListener('click', (event) => {
200
+ event.preventDefault();
201
+ openPopover();
202
+ });
203
+
204
+ popover.addEventListener('pointerenter', openPopover);
205
+ popover.addEventListener('pointerleave', (event) => {
206
+ if (containsTarget(event.relatedTarget)) return;
207
+ closePopoverSoon();
208
+ });
209
+ popover.addEventListener('focusin', openPopover);
210
+ popover.addEventListener('focusout', (event) => {
211
+ if (containsTarget(event.relatedTarget)) return;
212
+ closePopoverSoon();
213
+ });
214
+
215
+ root.addEventListener('keydown', (event) => {
216
+ if (event.key !== 'Escape') return;
217
+ closePopover();
218
+ });
219
+ });
220
+
221
+ if (hoverLinkGlobalsBound) return;
222
+ hoverLinkGlobalsBound = true;
223
+
224
+ document.addEventListener('pointerdown', closeOpenHoverLinks);
225
+ document.addEventListener('focusin', closeOpenHoverLinks);
226
+ }
227
+
130
228
  function getItemOffset(depth) {
131
229
  if (depth <= 2) return 14;
132
230
  if (depth === 3) return 26;
@@ -457,6 +555,8 @@ const localizedParentUrl = withLang(parentUrl);
457
555
  });
458
556
  });
459
557
  });
558
+
559
+ bindHoverLinks();
460
560
  }
461
561
 
462
562
  function runTocWhenIdle() {
@@ -30,6 +30,7 @@ const ColorfulUIDefaults = {
30
30
  components: {
31
31
  Callout: { variant: "soft", icon: true },
32
32
  CodeBlock: { showCopyButton: true },
33
+ HoverLink: { linkLabel: "Open page", showIndicator: false },
33
34
  Tabs: { style: "default" },
34
35
  },
35
36
  };
@@ -30,6 +30,7 @@ const DarksharpUIDefaults = {
30
30
  components: {
31
31
  Callout: { variant: "soft", icon: true },
32
32
  CodeBlock: { showCopyButton: true },
33
+ HoverLink: { linkLabel: "Open page", showIndicator: false },
33
34
  Tabs: { style: "default" },
34
35
  },
35
36
  };
@@ -30,6 +30,7 @@ const DefaultUIDefaults = {
30
30
  components: {
31
31
  Callout: { variant: "soft", icon: true },
32
32
  CodeBlock: { showCopyButton: true },
33
+ HoverLink: { linkLabel: "Open page", showIndicator: false },
33
34
  Tabs: { style: "default" },
34
35
  },
35
36
  };
@@ -30,6 +30,7 @@ const GreenTreeUIDefaults = {
30
30
  components: {
31
31
  Callout: { variant: "soft", icon: true },
32
32
  CodeBlock: { showCopyButton: true },
33
+ HoverLink: { linkLabel: "Open page", showIndicator: false },
33
34
  Tabs: { style: "default" },
34
35
  },
35
36
  };
@@ -27,7 +27,9 @@ const PixelBorderUIDefaults = {
27
27
  toc: { enabled: true, depth: 3 },
28
28
  header: { height: 56, sticky: true },
29
29
  },
30
- components: {},
30
+ components: {
31
+ HoverLink: { linkLabel: "Open page", showIndicator: false },
32
+ },
31
33
  };
32
34
 
33
35
  export const pixelBorder = createTheme({
package/styles/docs.css CHANGED
@@ -918,6 +918,206 @@ samp {
918
918
  opacity: 0.8;
919
919
  }
920
920
 
921
+ .fd-hover-link {
922
+ position: relative;
923
+ display: inline-block;
924
+ vertical-align: baseline;
925
+ max-width: 100%;
926
+ }
927
+
928
+ .fd-hover-link-trigger {
929
+ display: inline !important;
930
+ border: none;
931
+ background: transparent;
932
+ padding: 0;
933
+ margin: 0;
934
+ color: var(--color-fd-foreground);
935
+ cursor: pointer;
936
+ text-decoration: underline;
937
+ text-decoration-style: dashed;
938
+ text-decoration-thickness: 0.08em;
939
+ text-underline-offset: 0.22em;
940
+ text-decoration-color: color-mix(in srgb, var(--color-fd-foreground) 46%, transparent);
941
+ font: inherit;
942
+ line-height: inherit;
943
+ vertical-align: baseline;
944
+ appearance: none;
945
+ transition: text-decoration-color 180ms ease, opacity 180ms ease;
946
+ }
947
+
948
+ .fd-hover-link-trigger:hover,
949
+ .fd-hover-link-trigger:focus-visible,
950
+ .fd-hover-link-open > .fd-hover-link-trigger {
951
+ text-decoration-color: color-mix(in srgb, var(--color-fd-foreground) 68%, transparent);
952
+ }
953
+
954
+ .fd-hover-link-trigger:focus-visible {
955
+ outline: none;
956
+ }
957
+
958
+ .fd-hover-link-popover {
959
+ --fd-hover-link-rest-x: -50%;
960
+ --fd-hover-link-rest-y: 8px;
961
+ --fd-hover-link-open-x: -50%;
962
+ --fd-hover-link-open-y: 0;
963
+ position: absolute;
964
+ top: calc(100% + var(--fd-hover-link-side-offset, 12px));
965
+ left: 50%;
966
+ z-index: 40;
967
+ width: min(22rem, calc(100vw - 2rem));
968
+ max-width: min(22rem, calc(100vw - 2rem));
969
+ opacity: 0;
970
+ visibility: hidden;
971
+ pointer-events: none;
972
+ transform: translate3d(var(--fd-hover-link-rest-x), var(--fd-hover-link-rest-y), 0);
973
+ transition: opacity 180ms ease, transform 180ms ease, visibility 180ms linear;
974
+ }
975
+
976
+ .fd-hover-link[data-align="start"] > .fd-hover-link-popover {
977
+ left: 0;
978
+ --fd-hover-link-rest-x: 0;
979
+ --fd-hover-link-open-x: 0;
980
+ }
981
+
982
+ .fd-hover-link[data-align="end"] > .fd-hover-link-popover {
983
+ left: auto;
984
+ right: 0;
985
+ --fd-hover-link-rest-x: 0;
986
+ --fd-hover-link-open-x: 0;
987
+ }
988
+
989
+ .fd-hover-link[data-side="top"] > .fd-hover-link-popover {
990
+ top: auto;
991
+ bottom: calc(100% + var(--fd-hover-link-side-offset, 12px));
992
+ --fd-hover-link-rest-y: -8px;
993
+ --fd-hover-link-open-y: 0;
994
+ }
995
+
996
+ .fd-hover-link[data-side="right"] > .fd-hover-link-popover {
997
+ top: 50%;
998
+ left: calc(100% + var(--fd-hover-link-side-offset, 12px));
999
+ right: auto;
1000
+ --fd-hover-link-rest-x: 8px;
1001
+ --fd-hover-link-rest-y: -50%;
1002
+ --fd-hover-link-open-x: 0;
1003
+ --fd-hover-link-open-y: -50%;
1004
+ }
1005
+
1006
+ .fd-hover-link[data-side="right"][data-align="start"] > .fd-hover-link-popover {
1007
+ top: 0;
1008
+ --fd-hover-link-rest-y: 0;
1009
+ --fd-hover-link-open-y: 0;
1010
+ }
1011
+
1012
+ .fd-hover-link[data-side="right"][data-align="end"] > .fd-hover-link-popover {
1013
+ top: auto;
1014
+ bottom: 0;
1015
+ --fd-hover-link-rest-y: 0;
1016
+ --fd-hover-link-open-y: 0;
1017
+ }
1018
+
1019
+ .fd-hover-link[data-side="left"] > .fd-hover-link-popover {
1020
+ top: 50%;
1021
+ left: auto;
1022
+ right: calc(100% + var(--fd-hover-link-side-offset, 12px));
1023
+ --fd-hover-link-rest-x: -8px;
1024
+ --fd-hover-link-rest-y: -50%;
1025
+ --fd-hover-link-open-x: 0;
1026
+ --fd-hover-link-open-y: -50%;
1027
+ }
1028
+
1029
+ .fd-hover-link[data-side="left"][data-align="start"] > .fd-hover-link-popover {
1030
+ top: 0;
1031
+ --fd-hover-link-rest-y: 0;
1032
+ --fd-hover-link-open-y: 0;
1033
+ }
1034
+
1035
+ .fd-hover-link[data-side="left"][data-align="end"] > .fd-hover-link-popover {
1036
+ top: auto;
1037
+ bottom: 0;
1038
+ --fd-hover-link-rest-y: 0;
1039
+ --fd-hover-link-open-y: 0;
1040
+ }
1041
+
1042
+ .fd-hover-link-open > .fd-hover-link-popover {
1043
+ opacity: 1;
1044
+ visibility: visible;
1045
+ pointer-events: auto;
1046
+ transform: translate3d(var(--fd-hover-link-open-x), var(--fd-hover-link-open-y), 0);
1047
+ }
1048
+
1049
+ .fd-hover-link-card {
1050
+ display: flex;
1051
+ flex-direction: column;
1052
+ gap: 0.75rem;
1053
+ width: 100%;
1054
+ border-radius: calc(var(--radius, 0.75rem) + 2px);
1055
+ border: 1px solid color-mix(in srgb, var(--color-fd-border) 88%, transparent);
1056
+ background: var(--color-fd-popover, var(--color-fd-background));
1057
+ color: var(--color-fd-popover-foreground, var(--color-fd-foreground));
1058
+ padding: 0.95rem 1rem;
1059
+ box-shadow: 0 20px 45px color-mix(in srgb, var(--color-fd-background) 78%, transparent);
1060
+ backdrop-filter: blur(14px);
1061
+ }
1062
+
1063
+ .fd-hover-link-body {
1064
+ display: flex;
1065
+ flex-direction: column;
1066
+ gap: 0.35rem;
1067
+ }
1068
+
1069
+ .fd-hover-link-preview-label {
1070
+ font-size: 0.68rem;
1071
+ text-transform: uppercase;
1072
+ letter-spacing: 0.1em;
1073
+ font-family: var(--fd-font-mono, var(--font-geist-mono, ui-monospace, monospace));
1074
+ color: color-mix(in srgb, var(--color-fd-popover-foreground, var(--color-fd-foreground)) 55%, transparent);
1075
+ }
1076
+
1077
+ .fd-hover-link-title,
1078
+ .fd-hover-link-cta {
1079
+ text-decoration: none !important;
1080
+ }
1081
+
1082
+ .fd-hover-link-title {
1083
+ color: var(--color-fd-popover-foreground, var(--color-fd-foreground));
1084
+ font-size: 1rem;
1085
+ font-weight: 600 !important;
1086
+ line-height: 1.3;
1087
+ }
1088
+
1089
+ .fd-hover-link-title:hover,
1090
+ .fd-hover-link-cta:hover {
1091
+ opacity: 1;
1092
+ }
1093
+
1094
+ .fd-hover-link-description {
1095
+ font-size: 0.92rem;
1096
+ line-height: 1.6;
1097
+ color: color-mix(in srgb, var(--color-fd-popover-foreground, var(--color-fd-foreground)) 74%, transparent);
1098
+ }
1099
+
1100
+ .fd-hover-link-footer {
1101
+ display: flex;
1102
+ align-items: center;
1103
+ justify-content: space-between;
1104
+ gap: 0.75rem;
1105
+ padding-top: 0.25rem;
1106
+ border-top: 1px solid color-mix(in srgb, var(--color-fd-border) 72%, transparent);
1107
+ }
1108
+
1109
+ .fd-hover-link-cta {
1110
+ display: inline-flex !important;
1111
+ align-items: center;
1112
+ gap: 0.4rem;
1113
+ color: var(--color-fd-primary);
1114
+ font-size: 0.8rem;
1115
+ font-weight: 600 !important;
1116
+ text-transform: uppercase;
1117
+ letter-spacing: 0.08em;
1118
+ font-family: var(--fd-font-mono, var(--font-geist-mono, ui-monospace, monospace));
1119
+ }
1120
+
921
1121
  .fd-page-body h1 {
922
1122
  font-size: var(--fd-h1-size, 2.25rem);
923
1123
  font-weight: var(--fd-h1-weight, 700);