@farming-labs/svelte-theme 0.0.51 → 0.0.53

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/svelte-theme",
3
- "version": "0.0.51",
3
+ "version": "0.0.53",
4
4
  "description": "Svelte UI components for @farming-labs/docs — layout, sidebar, TOC, search, and theme toggle",
5
5
  "keywords": [
6
6
  "docs",
@@ -82,8 +82,8 @@
82
82
  "dependencies": {
83
83
  "gray-matter": "^4.0.3",
84
84
  "sugar-high": "^0.9.5",
85
- "@farming-labs/docs": "0.0.51",
86
- "@farming-labs/svelte": "0.0.51"
85
+ "@farming-labs/docs": "0.0.53",
86
+ "@farming-labs/svelte": "0.0.53"
87
87
  },
88
88
  "peerDependencies": {
89
89
  "svelte": ">=5.0.0"
@@ -12,6 +12,7 @@
12
12
  let openDropdownMenu = $state(false);
13
13
  let copyLabel = $state("Copy page");
14
14
  let copied = $state(false);
15
+ let selectedFeedback = $state(null);
15
16
 
16
17
  let titleSuffix = $derived(
17
18
  config?.metadata?.titleTemplate
@@ -121,6 +122,26 @@
121
122
  );
122
123
  let showActionsAbove = $derived(pageActionsPosition === "above-title" && showPageActions);
123
124
  let showActionsBelow = $derived(pageActionsPosition === "below-title" && showPageActions);
125
+ let feedbackConfig = $derived.by(() => {
126
+ const defaults = {
127
+ enabled: false,
128
+ question: "How is this guide?",
129
+ positiveLabel: "Good",
130
+ negativeLabel: "Bad",
131
+ onFeedback: undefined,
132
+ };
133
+
134
+ const feedback = config?.feedback;
135
+ if (feedback === undefined || feedback === false) return defaults;
136
+ if (feedback === true) return { ...defaults, enabled: true };
137
+ return {
138
+ enabled: feedback.enabled !== false,
139
+ question: feedback.question ?? defaults.question,
140
+ positiveLabel: feedback.positiveLabel ?? defaults.positiveLabel,
141
+ negativeLabel: feedback.negativeLabel ?? defaults.negativeLabel,
142
+ onFeedback: typeof feedback.onFeedback === "function" ? feedback.onFeedback : undefined,
143
+ };
144
+ });
124
145
 
125
146
  function handleCopyPage() {
126
147
  let text = "";
@@ -170,6 +191,44 @@
170
191
  closeDropdown();
171
192
  }
172
193
 
194
+ function handleFeedback(value) {
195
+ selectedFeedback = value;
196
+
197
+ const pathname =
198
+ typeof window !== "undefined"
199
+ ? window.location.pathname.replace(/\/$/, "") || "/"
200
+ : data.slug
201
+ ? `/${data.entry ?? config?.entry ?? "docs"}/${data.slug}`
202
+ : `/${data.entry ?? config?.entry ?? "docs"}`;
203
+
204
+ const payload = {
205
+ value,
206
+ title: data.title,
207
+ description: data.description,
208
+ url: typeof window !== "undefined" ? window.location.href : pathname,
209
+ pathname,
210
+ path: pathname,
211
+ entry: data.entry ?? config?.entry ?? "docs",
212
+ slug: data.slug ?? "",
213
+ locale: data.locale,
214
+ };
215
+
216
+ try {
217
+ feedbackConfig.onFeedback?.(payload);
218
+ } catch {}
219
+
220
+ try {
221
+ const docsWindow = typeof window !== "undefined" ? window : undefined;
222
+ if (docsWindow && typeof docsWindow.__fdOnFeedback__ === "function") {
223
+ docsWindow.__fdOnFeedback__(payload);
224
+ }
225
+ } catch {}
226
+
227
+ if (typeof window !== "undefined") {
228
+ window.dispatchEvent(new CustomEvent("fd:feedback", { detail: payload }));
229
+ }
230
+ }
231
+
173
232
  function handleClickOutside(e) {
174
233
  const target = e.target;
175
234
  if (openDropdownMenu && !target?.closest?.(".fd-page-action-dropdown")) {
@@ -344,6 +403,52 @@
344
403
  {/if}
345
404
 
346
405
  {@html htmlWithoutFirstH1}
406
+
407
+ {#if feedbackConfig.enabled}
408
+ <section class="fd-feedback" aria-label="Page feedback">
409
+ <div class="fd-feedback-content">
410
+ <p class="fd-feedback-question">{feedbackConfig.question}</p>
411
+ <div class="fd-feedback-actions" role="group" aria-label={feedbackConfig.question}>
412
+ <button
413
+ type="button"
414
+ class="fd-page-action-btn"
415
+ aria-pressed={selectedFeedback === "positive"}
416
+ data-selected={selectedFeedback === "positive" ? "true" : undefined}
417
+ onclick={() => handleFeedback("positive")}
418
+ >
419
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" aria-hidden="true">
420
+ <path
421
+ d="M7 21H5a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2h2m0 11V10m0 11h9.28a2 2 0 0 0 1.97-1.66l1.2-7A2 2 0 0 0 17.48 10H13V6.5a2.5 2.5 0 0 0-2.5-2.5L7 10"
422
+ stroke="currentColor"
423
+ stroke-width="2"
424
+ stroke-linecap="round"
425
+ stroke-linejoin="round"
426
+ />
427
+ </svg>
428
+ <span>{feedbackConfig.positiveLabel}</span>
429
+ </button>
430
+ <button
431
+ type="button"
432
+ class="fd-page-action-btn"
433
+ aria-pressed={selectedFeedback === "negative"}
434
+ data-selected={selectedFeedback === "negative" ? "true" : undefined}
435
+ onclick={() => handleFeedback("negative")}
436
+ >
437
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" aria-hidden="true">
438
+ <path
439
+ d="M17 3h2a2 2 0 0 1 2 2v7a2 2 0 0 1-2 2h-2M17 3v11m0-11H7.72a2 2 0 0 0-1.97 1.66l-1.2 7A2 2 0 0 0 6.52 14H11v3.5a2.5 2.5 0 0 0 2.5 2.5L17 14"
440
+ stroke="currentColor"
441
+ stroke-width="2"
442
+ stroke-linecap="round"
443
+ stroke-linejoin="round"
444
+ />
445
+ </svg>
446
+ <span>{feedbackConfig.negativeLabel}</span>
447
+ </button>
448
+ </div>
449
+ </div>
450
+ </section>
451
+ {/if}
347
452
  </div>
348
453
  {/snippet}
349
454
  </DocsPage>
package/styles/docs.css CHANGED
@@ -644,10 +644,19 @@ samp {
644
644
  color: var(--color-fd-foreground);
645
645
  }
646
646
 
647
+ .fd-page-action-btn[data-selected="true"] {
648
+ color: var(--color-fd-accent-foreground);
649
+ background: var(--color-fd-accent);
650
+ }
651
+
647
652
  .fd-page-action-btn svg {
648
653
  flex-shrink: 0;
649
654
  }
650
655
 
656
+ .fd-page-action-btn[data-selected="true"] svg {
657
+ color: currentColor;
658
+ }
659
+
651
660
  .fd-page-action-dropdown {
652
661
  position: relative;
653
662
  }
@@ -715,6 +724,35 @@ samp {
715
724
  margin-bottom: 1rem;
716
725
  }
717
726
 
727
+ .fd-feedback {
728
+ margin-top: 2rem;
729
+ padding-top: 1.25rem;
730
+ border-top: 1px solid var(--color-fd-border);
731
+ }
732
+
733
+ .fd-feedback-content {
734
+ display: flex;
735
+ align-items: center;
736
+ justify-content: space-between;
737
+ gap: 1rem;
738
+ flex-wrap: wrap;
739
+ }
740
+
741
+ .fd-feedback-question {
742
+ margin: 0;
743
+ font-size: 0.9375rem;
744
+ font-weight: 600;
745
+ line-height: 1.5;
746
+ color: var(--color-fd-foreground);
747
+ }
748
+
749
+ .fd-feedback-actions {
750
+ display: inline-flex;
751
+ align-items: center;
752
+ gap: 0.5rem;
753
+ flex-wrap: wrap;
754
+ }
755
+
718
756
  /* ─── Breadcrumb ─────────────────────────────────────────────────────── */
719
757
 
720
758
  .fd-breadcrumb {