Adding Jump Links to Page Modules

By Mitchell Christ

Use modules to build your pages? Want to grab a link to a specific module? This schema is just for you!

How to add to your module

export default defineType({
  name: 'module-name',
  ...
  fields: [
    ...
    defineField({
      name: 'uid',
      title: 'Unique Identifier',
      type: 'uid',
      group: 'options',
    }),
  ],
})

The helper function (/lib/uid.ts)

export default function ({ uid = undefined, _key }) {
  return uid || _key
}

The frontend (React / Next.js)

import uid from '@/lib/uid'

export default function YourModuleComponent({ ...props }) {
  return (
    <section
      id={uid(props)}
      className="..."
    >
      ...
    </section>
  )
}

Schema + Input component

import { useState } from 'react'
import { defineType } from 'sanity'
import { Box, Button, Flex, Text, TextInput } from '@sanity/ui'
import { VscCheck, VscCopy } from 'react-icons/vsc'

export default defineType({
	name: 'uid',
	title: 'Unique Identifier',
	description: 'Used for anchor/jump links (HTML `id` attribute).',
	type: 'string',
	validation: (Rule) =>
		Rule.regex(/^[a-zA-Z0-9-]+$/g).error(
			'Must not contain spaces or special characters',
		),
	components: {
		input: ({ elementProps, path }) => {
			const indexOfModule = path.indexOf('modules')
			const moduleKey = (path[indexOfModule + 1] as any)?._key
			const [checked, setChecked] = useState(false)

			return (
				<Flex gap={1} align="center">
					<Text muted>#</Text>

					<Box flex={1}>
						<TextInput {...elementProps} placeholder={moduleKey} radius={2} />
					</Box>

					<Button
						title="Click to copy"
						mode="ghost"
						icon={checked ? VscCheck : VscCopy}
						disabled={checked}
						onClick={() => {
							navigator.clipboard.writeText(
								'#' + elementProps.value || moduleKey,
							)

							setChecked(true)
							setTimeout(() => setChecked(false), 1000)
						}}
					/>
				</Flex>
			)
		},
	},
})

👉 Read the original article on the SanityPress Blog

This uid schema+input component is part of SanityPress, a Next.js starter template with Tailwind CSS and pre-built schema.

You can find the source code for the uid here for easy copy and paste (no npm install necessary!)

Contributor