Modeling a "scroll to div" link in Sanity.io using a custom string component and a dropdown menu.
5 replies
Last updated: Jan 13, 2023
E
How would you model a link to a section within a page? Type "scroll to div" link.
E
One solution I'm thinking of is to create a custom string component, that fetches the modules of the current document, and lists them in a dropdown. When the user selects an entry the
_keygets stored. I can then use that in the frontend to link to the section.
E
But maybe something exists?
E
I did this. Works fine! 🙂
E
Not the most beautiful, but works!
I did something similar for selecting a section in a document you’re referencing in a V2 Studio (sorry I haven’t had a change to migrate it yet):
//schema
{
name: 'referenceField',
title: 'Field within a Reference',
description:
'This field uses the @sanity/client to allow you to indicate a specific field within a selected reference',
type: 'object',
fields: [
{
name: 'page',
title: 'Page',
type: 'reference',
to: [{ type: 'page' }],
},
{
name: 'section',
title: 'Section',
type: 'string',
hidden: ({ document }) => !document.referenceField.page,
inputComponent: ClientAsyncSelect,
},
],
},import React, { useState, useEffect } from 'react';
import { Card, Stack, Select } from '@sanity/ui';
import { FormField } from '@sanity/base/components';
import PatchEvent, { set, unset } from '@sanity/form-builder/PatchEvent';
import { useId } from '@reach/auto-id';
import { studioClient } from '../../lib/utils/studioClient';
const ClientAsyncSelect = React.forwardRef((props, ref) => {
const [listItems, setListItems] = useState([]);
const {
type, // Schema information
value, // Current field value
readOnly, // Boolean if field is not editable
markers, // Markers including validation rules
presence, // Presence information for collaborative avatars
compareValue, // Value to check for "edited" functionality
onFocus, // Method to handle focus state
onBlur, // Method to handle blur state
onChange, // Method to handle patch events,
parent,
} = props;
// Creates a change handler for patching data
const handleChange = React.useCallback(
// useCallback will help with performance
event => {
const inputValue = event.currentTarget.value; // get current value
// if the value exists, set the data, if not, unset the data
onChange(PatchEvent.from(inputValue ? set(inputValue) : unset()));
},
[onChange]
);
const inputId = useId();
useEffect(() => {
const getSections = async () => {
await studioClient
.fetch(`*[_id == $id][0].sections[].title`, {
id: parent.page._ref ? parent.page._ref : '',
})
.then(setListItems);
};
getSections();
}, []);
return (
<FormField
description={type.description} // Creates description from schema
title={type.title} // Creates label from schema title
__unstable_markers={markers} // Handles all markers including validation
__unstable_presence={presence} // Handles presence avatars
compareValue={compareValue} // Handles "edited" status
inputId={inputId} // Allows the label to connect to the input field
>
<Card padding={0}>
<Stack>
<Select
id={inputId} // A unique ID for this input
fontSize={2}
padding={[3, 3, 4]}
space={[3, 3, 4]}
value={value} // Current field value
readOnly={readOnly} // If "readOnly" is defined make this field read only
onFocus={onFocus} // Handles focus events
onBlur={onBlur} // Handles blur events
ref={ref}
onChange={handleChange} // A function to call when the input value changes
>
<option value={''}>---</option>
{listItems &&
listItems.map(item => (
<option key={item} value={item}>
{item}
</option>
))}
</Select>
</Stack>
</Card>
</FormField>
);
});
export default ClientAsyncSelect;Sanity – Build the way you think, not the way your CMS thinks
Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.