MDX/InstagramEmbed
Default
Multiple Embeds
Reel Post
With Class Name
instagram-embed.tsx
import type { FunctionComponent } from 'preact';
const toEmbedSrc = (url: string): string => {
try {
const urlObj = new URL(url);
const allowedHosts = ['instagram.com', 'www.instagram.com'];
if (!allowedHosts.includes(urlObj.hostname)) {
throw new Error(`Invalid Instagram host: ${urlObj.hostname}`);
}
// Extract shortcode from /p/{shortcode}/ or /reel/{shortcode}/ URLs
const match = urlObj.pathname.match(/^\/(p|reel)\/([A-Za-z0-9_-]+)/);
if (!match) {
throw new Error(`Could not extract shortcode from: ${urlObj.pathname}`);
}
const type = match[1];
const shortcode = match[2];
return `https://www.instagram.com/${type}/${shortcode}/embed/`;
} catch (error) {
throw new Error(`Invalid Instagram URL: ${url} - ${error}`, { cause: error });
}
};
interface InstagramEmbedProps {
url: string;
className?: string;
}
const InstagramEmbed: FunctionComponent<InstagramEmbedProps> = ({ url, className = '' }) => (
<div className="pb-vgap-lg">
<div className={`border border-zd-white aspect-[4/5] lg:max-w-3/4 ${className}`}>
<iframe
src={toEmbedSrc(url)}
title="Instagram embed"
allowFullScreen
loading="lazy"
referrerPolicy="strict-origin-when-cross-origin"
className={'block w-full h-full border-none'}
></iframe>
</div>
</div>
);
export { InstagramEmbed };
instagram-embed.stories.tsx
import { InstagramEmbed } from './instagram-embed';
import type { ControlsMap } from '../../sub-packages/styleguide-v2/src/data/control-types';
/**
* InstagramEmbed Component
*
* Embeds Instagram posts and reels in MDX articles.
* Features:
* - Supports post (/p/) and reel (/reel/) URL formats
* - URL validation for instagram.com
* - Lazy loading for performance
*/
export const meta = {
title: 'MDX/InstagramEmbed',
};
export const controls: ControlsMap = {
url: { type: 'text', default: 'https://www.instagram.com/p/DUlkwjdDdQS/' },
};
/**
* Default - Standard Instagram post URL
*
* Uses the standard instagram.com/p/ format
*/
export const Default = {
args: { url: 'https://www.instagram.com/p/DUlkwjdDdQS/' },
render: ({ url }: { url: string }) => <InstagramEmbed url={url} />,
};
/**
* Reel post format (/reel/)
*/
export const ReelPost = () => <InstagramEmbed url="https://www.instagram.com/reel/DUlkwjdDdQS/" />;
/**
* With custom className
*/
export const WithClassName = () => (
<InstagramEmbed
url="https://www.instagram.com/p/DUlkwjdDdQS/"
className="border-2 border-zd-link"
/>
);
/**
* Multiple embeds in sequence
*/
export const MultipleEmbeds = () => (
<div className="max-w-[800px]">
<h3 className="text-zd-white pb-vgap-sm">Instagram 投稿</h3>
<InstagramEmbed url="https://www.instagram.com/p/DUlkwjdDdQS/" />
<h3 className="text-zd-white pb-vgap-sm">Instagram リール</h3>
<InstagramEmbed url="https://www.instagram.com/reel/DUlkwjdDdQS/" />
</div>
);