Back
Back
Back
Simple Documentation Maker
Simple Documentation Maker
Page Contents
Page Contents
Page Contents
Need a simple documentation system? This component adds auto linking contents list to a one page document system.
Looking to add a bit of documentation to your project? This tool is perfect for you!
Have you ever been asked to include documentation tools to enhance your builds? If so, you might have already explored the power of the Framer CMS.
This component enables you to add page titles in a sidebar that automatically link to articles in the main page content. It’s ideal for smaller documentation libraries, where you want all your information on a single page, organized in a vertical stack.
With full customization options, this component can be easily tailored to match your brand. It’s simple to set up—just grab the remix file to see how the implementation works!
If you are not sure how to add code to Framer watch this quick video.
Framer Code Component
Simple Documentation Maker
1.0
1.0
1.0
1.0
// A custom Framer code override by Chris Kellett - Framerverse
// Get more components at www.framerverse.com
// Simple Docs Sidelinks
// Version 1.0
import React, { useState, useEffect, useRef } from "react";
import { Frame, addPropertyControls, ControlType } from "framer";
export function SidebarLink(props) {
const {
text,
link,
activeColor,
inactiveColor,
hoverColor,
font,
fontSize,
fontWeight,
} = props;
const [isActive, setIsActive] = useState(false);
const observer = useRef(null);
useEffect(() => {
// Function to update active state
const updateActiveState = () => {
const hash = window.location.hash.slice(1);
setIsActive(hash === link);
};
// Set up Intersection Observer
observer.current = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
setIsActive(true);
window.history.pushState(null, null, `#${link}`);
} else {
setIsActive(false);
}
});
},
{ threshold: 0.5 } // Trigger when 50% of the target is visible
);
// Observe the corresponding section
const targetSection = document.getElementById(link);
if (targetSection) {
observer.current.observe(targetSection);
}
// Listen for hash changes
window.addEventListener("hashchange", updateActiveState);
updateActiveState(); // Initial check
// Cleanup
return () => {
window.removeEventListener("hashchange", updateActiveState);
if (observer.current && targetSection) {
observer.current.unobserve(targetSection);
}
};
}, [link]);
return (
<div
style={{
width: "100%",
height: "auto",
textAlign: "left",
display: "flex",
overflow: "hidden", // Prevent scrollbar
}}
>
<div
background="none"
width="100%"
style={{
color: isActive ? activeColor : inactiveColor,
fontFamily: font,
fontSize: fontSize,
fontWeight: fontWeight,
textDecoration: "none",
cursor: "pointer",
textAlign: "left",
display: "flex",
alignItems: "center", // Ensure vertical centering
transition: "color 0.3s ease, transform 0.3s ease",
transform: isActive ? "translateX(8px)" : "translateX(0px)",
whiteSpace: "normal", // Allow text to wrap to the next line
}}
whileHover={{ color: hoverColor }}
onClick={() => {
const element = document.getElementById(link);
if (element) {
element.scrollIntoView({ behavior: "smooth" });
}
}}
>
{isActive && (
<span
style={{
marginRight: "8px",
transition: "opacity 0.3s ease",
opacity: isActive ? 1 : 0,
}}
>
›
</span>
)}
<span>{text}</span>
</div>
</div>
);
}
SidebarLink.defaultProps = {
text: "Link Text",
link: "page-1",
activeColor: "#27AB8A",
inactiveColor: "white",
hoverColor: "#27AB8A",
font: "Inter",
fontSize: 16,
fontWeight: 400, // Default font weight
};
addPropertyControls(SidebarLink, {
text: { type: ControlType.String, title: "Text" },
link: { type: ControlType.String, title: "Link (without #)" },
activeColor: { type: ControlType.Color, title: "Active Color" },
inactiveColor: { type: ControlType.Color, title: "Inactive Color" },
hoverColor: { type: ControlType.Color, title: "Hover Color" },
font: { type: ControlType.String, title: "Font" },
fontSize: {
type: ControlType.Number,
title: "Font Size",
min: 8,
max: 72,
step: 1,
},
fontWeight: {
type: ControlType.Number,
title: "Font Weight",
min: 100,
max: 900,
step: 100,
},
});
CLICK TO COPY
// A custom Framer code override by Chris Kellett - Framerverse
// Get more components at www.framerverse.com
// Simple Docs Sidelinks
// Version 1.0
import React, { useState, useEffect, useRef } from "react";
import { Frame, addPropertyControls, ControlType } from "framer";
export function SidebarLink(props) {
const {
text,
link,
activeColor,
inactiveColor,
hoverColor,
font,
fontSize,
fontWeight,
} = props;
const [isActive, setIsActive] = useState(false);
const observer = useRef(null);
useEffect(() => {
// Function to update active state
const updateActiveState = () => {
const hash = window.location.hash.slice(1);
setIsActive(hash === link);
};
// Set up Intersection Observer
observer.current = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
setIsActive(true);
window.history.pushState(null, null, `#${link}`);
} else {
setIsActive(false);
}
});
},
{ threshold: 0.5 } // Trigger when 50% of the target is visible
);
// Observe the corresponding section
const targetSection = document.getElementById(link);
if (targetSection) {
observer.current.observe(targetSection);
}
// Listen for hash changes
window.addEventListener("hashchange", updateActiveState);
updateActiveState(); // Initial check
// Cleanup
return () => {
window.removeEventListener("hashchange", updateActiveState);
if (observer.current && targetSection) {
observer.current.unobserve(targetSection);
}
};
}, [link]);
return (
<div
style={{
width: "100%",
height: "auto",
textAlign: "left",
display: "flex",
overflow: "hidden", // Prevent scrollbar
}}
>
<div
background="none"
width="100%"
style={{
color: isActive ? activeColor : inactiveColor,
fontFamily: font,
fontSize: fontSize,
fontWeight: fontWeight,
textDecoration: "none",
cursor: "pointer",
textAlign: "left",
display: "flex",
alignItems: "center", // Ensure vertical centering
transition: "color 0.3s ease, transform 0.3s ease",
transform: isActive ? "translateX(8px)" : "translateX(0px)",
whiteSpace: "normal", // Allow text to wrap to the next line
}}
whileHover={{ color: hoverColor }}
onClick={() => {
const element = document.getElementById(link);
if (element) {
element.scrollIntoView({ behavior: "smooth" });
}
}}
>
{isActive && (
<span
style={{
marginRight: "8px",
transition: "opacity 0.3s ease",
opacity: isActive ? 1 : 0,
}}
>
›
</span>
)}
<span>{text}</span>
</div>
</div>
);
}
SidebarLink.defaultProps = {
text: "Link Text",
link: "page-1",
activeColor: "#27AB8A",
inactiveColor: "white",
hoverColor: "#27AB8A",
font: "Inter",
fontSize: 16,
fontWeight: 400, // Default font weight
};
addPropertyControls(SidebarLink, {
text: { type: ControlType.String, title: "Text" },
link: { type: ControlType.String, title: "Link (without #)" },
activeColor: { type: ControlType.Color, title: "Active Color" },
inactiveColor: { type: ControlType.Color, title: "Inactive Color" },
hoverColor: { type: ControlType.Color, title: "Hover Color" },
font: { type: ControlType.String, title: "Font" },
fontSize: {
type: ControlType.Number,
title: "Font Size",
min: 8,
max: 72,
step: 1,
},
fontWeight: {
type: ControlType.Number,
title: "Font Weight",
min: 100,
max: 900,
step: 100,
},
});
CLICK TO COPY
// A custom Framer code override by Chris Kellett - Framerverse
// Get more components at www.framerverse.com
// Simple Docs Sidelinks
// Version 1.0
import React, { useState, useEffect, useRef } from "react";
import { Frame, addPropertyControls, ControlType } from "framer";
export function SidebarLink(props) {
const {
text,
link,
activeColor,
inactiveColor,
hoverColor,
font,
fontSize,
fontWeight,
} = props;
const [isActive, setIsActive] = useState(false);
const observer = useRef(null);
useEffect(() => {
// Function to update active state
const updateActiveState = () => {
const hash = window.location.hash.slice(1);
setIsActive(hash === link);
};
// Set up Intersection Observer
observer.current = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
setIsActive(true);
window.history.pushState(null, null, `#${link}`);
} else {
setIsActive(false);
}
});
},
{ threshold: 0.5 } // Trigger when 50% of the target is visible
);
// Observe the corresponding section
const targetSection = document.getElementById(link);
if (targetSection) {
observer.current.observe(targetSection);
}
// Listen for hash changes
window.addEventListener("hashchange", updateActiveState);
updateActiveState(); // Initial check
// Cleanup
return () => {
window.removeEventListener("hashchange", updateActiveState);
if (observer.current && targetSection) {
observer.current.unobserve(targetSection);
}
};
}, [link]);
return (
<div
style={{
width: "100%",
height: "auto",
textAlign: "left",
display: "flex",
overflow: "hidden", // Prevent scrollbar
}}
>
<div
background="none"
width="100%"
style={{
color: isActive ? activeColor : inactiveColor,
fontFamily: font,
fontSize: fontSize,
fontWeight: fontWeight,
textDecoration: "none",
cursor: "pointer",
textAlign: "left",
display: "flex",
alignItems: "center", // Ensure vertical centering
transition: "color 0.3s ease, transform 0.3s ease",
transform: isActive ? "translateX(8px)" : "translateX(0px)",
whiteSpace: "normal", // Allow text to wrap to the next line
}}
whileHover={{ color: hoverColor }}
onClick={() => {
const element = document.getElementById(link);
if (element) {
element.scrollIntoView({ behavior: "smooth" });
}
}}
>
{isActive && (
<span
style={{
marginRight: "8px",
transition: "opacity 0.3s ease",
opacity: isActive ? 1 : 0,
}}
>
›
</span>
)}
<span>{text}</span>
</div>
</div>
);
}
SidebarLink.defaultProps = {
text: "Link Text",
link: "page-1",
activeColor: "#27AB8A",
inactiveColor: "white",
hoverColor: "#27AB8A",
font: "Inter",
fontSize: 16,
fontWeight: 400, // Default font weight
};
addPropertyControls(SidebarLink, {
text: { type: ControlType.String, title: "Text" },
link: { type: ControlType.String, title: "Link (without #)" },
activeColor: { type: ControlType.Color, title: "Active Color" },
inactiveColor: { type: ControlType.Color, title: "Inactive Color" },
hoverColor: { type: ControlType.Color, title: "Hover Color" },
font: { type: ControlType.String, title: "Font" },
fontSize: {
type: ControlType.Number,
title: "Font Size",
min: 8,
max: 72,
step: 1,
},
fontWeight: {
type: ControlType.Number,
title: "Font Weight",
min: 100,
max: 900,
step: 100,
},
});
CLICK TO COPY
What is it?
Need a simple documentation system? This component adds auto linking contents list to a one page document system.
What is it?
Need a simple documentation system? This component adds auto linking contents list to a one page document system.
What is it?
Need a simple documentation system? This component adds auto linking contents list to a one page document system.
How to use.
Click in the code are below to copy the code to your clipboard. Then click the 'plus' button int the assets panel for 'Code'. Choose if its an overide or Component. Paste the code in and save.
How to use.
Click in the code are below to copy the code to your clipboard. Then click the 'plus' button int the assets panel for 'Code'. Choose if its an overide or Component. Paste the code in and save.
How to use.
Click in the code are below to copy the code to your clipboard. Then click the 'plus' button int the assets panel for 'Code'. Choose if its an overide or Component. Paste the code in and save.
Usage Licence
I'm happy for you to use this code in your projects, even templates. If you use it please keep my accreditation in the code. Please don't sell it as your own. (Hover for full licence).
Usage Licence
I'm happy for you to use this code in your projects, even templates. If you use it please keep my accreditation in the code. Please don't sell it as your own. (Hover for full licence).
Usage Licence
I'm happy for you to use this code in your projects, even templates. If you use it please keep my accreditation in the code. Please don't sell it as your own. (Hover for full licence).
Change Log
// Version 1.0
Figma to Framer
Support
If you need support first watch the help video above. If that does not help reach out to me on one of my social channels or use the contact form. As I am a team of one it may take a short while to get back to you. Please be patient, thanks.
Hope this helps. Good luck with your project.
More Framer resources.
Real Loan Calculator
Add a fully functional, responsive, configurable loan calculator to your project.
Section
Real Loan Calculator
Add a fully functional, responsive, configurable loan calculator to your project.
Section
Real Loan Calculator
Add a fully functional, responsive, configurable loan calculator to your project.
Section
Mobile Rotation Alert
If your site works better in one orientation than another why not let your users know with this little component.
Code Component
Mobile Rotation Alert
If your site works better in one orientation than another why not let your users know with this little component.
Code Component
Mobile Rotation Alert
If your site works better in one orientation than another why not let your users know with this little component.
Code Component
Starfield Generator
A niche component for creating a swirling Starfield, simple but great in the right scenario (like this site).
Code Component
Starfield Generator
A niche component for creating a swirling Starfield, simple but great in the right scenario (like this site).
Code Component
Starfield Generator
A niche component for creating a swirling Starfield, simple but great in the right scenario (like this site).
Code Component
Swipe Variant Changer
Use this component and overide combo to create a swipe toggle that switches component variants.
Code Override
Swipe Variant Changer
Use this component and overide combo to create a swipe toggle that switches component variants.
Code Override
Swipe Variant Changer
Use this component and overide combo to create a swipe toggle that switches component variants.
Code Override
Change Variants with URL Parameters
Use a URL parameter to change the variant on the page you link to.
Code Override
Change Variants with URL Parameters
Use a URL parameter to change the variant on the page you link to.
Code Override
Change Variants with URL Parameters
Use a URL parameter to change the variant on the page you link to.
Code Override
Multi-step Form Experience
Build simple form experiences that look, feel and work like a multi-step form.
Section
Multi-step Form Experience
Build simple form experiences that look, feel and work like a multi-step form.
Section
Multi-step Form Experience
Build simple form experiences that look, feel and work like a multi-step form.
Section