{props.meta?.tocVideo && !!tocVideoPreview && (
@@ -176,6 +178,7 @@ const Layout: FC
= (props) => {
)}
+
On this page
diff --git a/apps/docs/lib/fetch/feedback.ts b/apps/docs/lib/fetch/feedback.ts
new file mode 100644
index 00000000000..2d622925619
--- /dev/null
+++ b/apps/docs/lib/fetch/feedback.ts
@@ -0,0 +1,40 @@
+import { type UseMutationOptions, useMutation } from '@tanstack/react-query'
+
+import { type ResponseError } from '~/types/fetch'
+import { post } from './fetchWrappers'
+
+type SendFeedbackVariables = {
+ message: string
+ pathname?: string
+}
+
+export async function sendFeedback({ message, pathname }: SendFeedbackVariables) {
+ const { data, error } = await post('/platform/feedback/send', {
+ body: {
+ message,
+ category: 'Feedback',
+ tags: ['docs-feedback'],
+ pathname,
+ },
+ })
+ if (error) throw Error(`Couldn't send feedback`, { cause: error })
+ return data
+}
+
+type SendFeedbackData = Awaited
>
+
+export const useSendFeedbackMutation = (
+ options: Omit<
+ UseMutationOptions,
+ 'mutationFn'
+ > = {}
+) => {
+ return useMutation({
+ ...options,
+ mutationFn: (vars) => sendFeedback(vars),
+ onError: (error, vars, ctx) => {
+ console.error(error)
+ options.onError?.(error, vars, ctx)
+ },
+ })
+}
diff --git a/apps/docs/lib/telemetry.ts b/apps/docs/lib/telemetry.ts
new file mode 100644
index 00000000000..6bb19ac6003
--- /dev/null
+++ b/apps/docs/lib/telemetry.ts
@@ -0,0 +1,41 @@
+import { usePathname } from 'next/navigation'
+
+import { useConsent } from 'ui-patterns/ConsentToast'
+
+import { unauthedAllowedPost } from './fetch/fetchWrappers'
+
+type TelemetryEvent = {
+ action: string
+ category: string
+ label: string
+}
+
+const noop = () => {}
+
+/**
+ * Sends a telemetry event to Logflare for tracking by the product team.
+ *
+ * Checks for user consent to telemetry before sending.
+ */
+const useSendTelemetryEvent = () => {
+ const { hasAcceptedConsent } = useConsent()
+ const pathname = usePathname()
+
+ if (!hasAcceptedConsent) return noop
+
+ return (event: TelemetryEvent) =>
+ unauthedAllowedPost('/platform/telemetry/event', {
+ // @ts-ignore - endpoint will accept this just fine
+ body: {
+ ...event,
+ page_title: document?.title,
+ page_location: pathname,
+ },
+ })
+ .then(({ error }) => {
+ if (error) console.error(error)
+ })
+ .catch((error) => console.error(error))
+}
+
+export { useSendTelemetryEvent }
diff --git a/apps/docs/package.json b/apps/docs/package.json
index 2d37fe12d91..0b78a1ebc9e 100644
--- a/apps/docs/package.json
+++ b/apps/docs/package.json
@@ -31,6 +31,7 @@
"@radix-ui/react-accordion": "^1.1.2",
"@supabase/auth-helpers-react": "^0.4.2",
"@supabase/supabase-js": "^2.39.3",
+ "@tailwindcss/container-queries": "^0.1.1",
"@tanstack/react-query": "^5.13.4",
"common": "*",
"common-tags": "^1.8.2",
@@ -70,7 +71,6 @@
"remark-gfm": "^3.0.1",
"shared-data": "*",
"ui": "*",
- "icons": "*",
"ui-patterns": "*",
"unist-builder": "^3.0.1",
"unist-util-filter": "^4.0.1",
diff --git a/apps/docs/styles/main.scss b/apps/docs/styles/main.scss
index 088cade3e5a..7e86e881477 100644
--- a/apps/docs/styles/main.scss
+++ b/apps/docs/styles/main.scss
@@ -69,11 +69,6 @@ article h1 {
}
}
-.table-of-contents-height {
- max-height: calc(100vh - 3.75rem - 2rem);
- top: calc(4rem + 60px); // padding height + navbar height
-}
-
.width-full {
width: 100% !important;
}
diff --git a/apps/docs/tailwind.config.js b/apps/docs/tailwind.config.js
index 9b04f141695..b4b91c5d972 100644
--- a/apps/docs/tailwind.config.js
+++ b/apps/docs/tailwind.config.js
@@ -20,5 +20,6 @@ module.exports = config({
},
})
},
+ require('@tailwindcss/container-queries'),
],
})
diff --git a/package-lock.json b/package-lock.json
index b2e9ee4d538..84119da5dca 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -473,6 +473,7 @@
"@radix-ui/react-accordion": "^1.1.2",
"@supabase/auth-helpers-react": "^0.4.2",
"@supabase/supabase-js": "^2.39.3",
+ "@tailwindcss/container-queries": "^0.1.1",
"@tanstack/react-query": "^5.13.4",
"common": "*",
"common-tags": "^1.8.2",
@@ -14615,6 +14616,14 @@
"dev": true,
"license": "Apache-2.0"
},
+ "node_modules/@tailwindcss/container-queries": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/container-queries/-/container-queries-0.1.1.tgz",
+ "integrity": "sha512-p18dswChx6WnTSaJCSGx6lTmrGzNNvm2FtXmiO6AuA1V4U5REyoqwmT6kgAsIMdjo07QdAfYXHJ4hnMtfHzWgA==",
+ "peerDependencies": {
+ "tailwindcss": ">=3.2.0"
+ }
+ },
"node_modules/@tailwindcss/forms": {
"version": "0.5.6",
"license": "MIT",
diff --git a/supabase/migrations/20240208001120_add_feedback_table.sql b/supabase/migrations/20240208001120_add_feedback_table.sql
new file mode 100644
index 00000000000..da8ad1563e0
--- /dev/null
+++ b/supabase/migrations/20240208001120_add_feedback_table.sql
@@ -0,0 +1,19 @@
+create type feedback_vote as enum (
+ 'yes',
+ 'no'
+);
+
+create table feedback (
+ id bigint primary key generated always as identity,
+ date_created date not null default current_date,
+ vote feedback_vote not null,
+ page text not null
+);
+
+alter table feedback enable row level security;
+
+create policy "Anyone can insert feedback"
+on feedback
+as permissive for insert
+to public
+with check (true);
diff --git a/supabase/migrations/20240306233728_create_feedback_view.sql b/supabase/migrations/20240306233728_create_feedback_view.sql
new file mode 100644
index 00000000000..989ff28a792
--- /dev/null
+++ b/supabase/migrations/20240306233728_create_feedback_view.sql
@@ -0,0 +1,7 @@
+create schema if not exists metrics;
+
+create view metrics.feedback_response_aggregate
+as select
+ count(*) filter (where vote = 'yes') as yes,
+ count(*) filter (where vote = 'no') as no
+from feedback;
\ No newline at end of file