Blog

April 20, 2025

Using custom components in markdown

Selene YuSelene Yu

Magic Portfolio will replace some default HTML elements to Once UI components to integrate better in the design and add additional functionality. Furthermore, many common Once UI components are already imported and available for use.

Feedback

The feedback component is used to display critical information to visitors.

Feedback element

Longer description of the feedback message.
<Feedback
    icon
    variant="success"
    title="Feedback element"
    description="Longer description of the feedback message."
/>

Table

Tables are used to display data in a structured format.

NameTypeDescription
titlestringThe title of the document
summarystringA brief summary of the document content
updatedAtstringThe date when the document was last updated
navLabelstringThe label used in navigation menus
<Table 
    data={{
      headers: [
        { content: "Name", key: "name", sortable: true },
        { content: "Type", key: "type", sortable: true },
        { content: "Description", key: "description" }
      ],
      rows: [
        ["title", "string", "The title of the document"],
        ["summary", "string", "A brief summary of the document content"],
        ["updatedAt", "string", "The date when the document was last updated"],
        ["navLabel", "string", "The label used in navigation menus"]
      ]
    }}
/>

Code

Use the CodeBlock component to display code snippets with code highlighting, preview, and copy to clipboard functionality. Use the InlineCode component for inline code snippets.

CodeBlock

The code block component works based on Once UI's CodeBlock. You can access it with the complete syntax for full customization, or by using the standard markdown syntax (triple backticks) with pre-configured props.

Tsx
// Full component syntax
<CodeBlock
    codes={[
      {
        code: "console.log('Hello, World!');",
        language: "javascript",
        label: "Example"
      }
    ]}
/>

// Short syntax example
```tsx
function greeting(name) {
    return `Hello, ${name}!`;
}

console.log(greeting('World'));
```

InlineCode

The InlineCode is another Once UI component that you can access either through the complete syntax or the short syntax (backticks). Usually the standard markdown syntax is recommended, since it doesn't have that much configuration options.

const x = 10;
// Full component syntax
<InlineCode>
    const x = 10;
</InlineCode>

// Short syntax example
`const x = 10;`

Accordion

Accordions are used to toggle between hiding and showing content.

Section 1
This is the content for section 1. You can include any components here.
Section 2
This is the content for section 2. Accordions are great for FAQs and other expandable content.
Section 3
This is the content for section 3. They help save space by hiding content until needed.
<AccordionGroup 
    items={[
      {
        title: "Section 1",
        content: <Text>This is the content for section 1.</Text>
      },
      {
        title: "Section 2",
        content: <Text>This is the content for section 2.</Text>
      },
      {
        title: "Section 3",
        content: <Text>This is the content for section 3.</Text>
      }
    ]}
/>

Button

Buttons are used to trigger actions or navigate to other pages.

<Row gap="8">
  <Button variant="primary" label="Primary" />
  <Button variant="secondary" label="Secondary" />
  <Button variant="tertiary" label="Tertiary" />
</Row>

Card

Cards are used to group related content and actions.

<Card
    href=" "
    maxWidth={20}
    radius="l-4"
    direction="column"
    padding="4"
  >
    <Media src="/images/projects/project-01/cover-01.jpg" aspectRatio="16/9" radius="l" sizes="400px" />
    <Column fillWidth padding="12" gap="8" horizontal="start">
      <Text variant="heading-strong-m" onBackground="neutral-strong" align="left">
        Card Title
      </Text>
      <Text variant="body-default-s" onBackground="neutral-weak" align="left">
        This is a description of the card. It can contain multiple lines of text.
      </Text>
    </Column>
</Card>

Icon

Icons are used to visually represent actions, objects, or concepts. For instructions on importing new icons, head over to the Once UI documentation.

rocketclosecheckinfowarningchevronDownsearch
<Icon name="rocket" size="m" />
<Icon name="close" size="m" />
<Icon name="check" onBackground="success-medium" size="m" />
<Icon name="info" onBackground="info-medium" size="m" />
<Icon name="warning" onBackground="warning-medium" size="m" />
<Icon name="chevronDown" size="m" />
<Icon name="search" size="m" />

Layout

Layout components help structure content on the page.

Flex

The Flex component is accessible as Column and Row and can handle a wide range of layout options and style properties.

Row Item
Row Item
Row Item
Row Item
Row Item
Row Item
Row Item
Row Item
<Row
    fillWidth
    s={{direction: "column"}}
    gap="16"
  >
    <Column fillWidth border="neutral-alpha-medium" padding="16" radius="m">
      <Row padding="8">Row Item</Row>
      <Row padding="8">Row Item</Row>
    </Column>
    <Column fillWidth border="neutral-alpha-medium" padding="16" radius="m">
      <Row padding="8">Row Item</Row>
      <Row padding="8">Row Item</Row>
    </Column>
    <Column fillWidth border="neutral-alpha-medium" padding="16" radius="m">
      <Row padding="8">Row Item</Row>
      <Row padding="8">Row Item</Row>
    </Column>
    <Column fillWidth border="neutral-alpha-medium" padding="16" radius="m">
      <Row padding="8">Row Item</Row>
      <Row padding="8">Row Item</Row>
    </Column>
</Row>

Grid

Use the grid to construct responsive grid layouts. It can be styled similarly to the Flex element.

Grid Item
Grid Item
Grid Item
Grid Item
Grid Item
Grid Item
<Grid
    fillWidth
    columns="3"
    s={{columns: 2}}
    gap="16"
  >
    <Column border="neutral-alpha-medium" padding="16" radius="m">
      <Text>Grid Item</Text>
    </Column>
    <Column border="neutral-alpha-medium" padding="16" radius="m">
      <Text>Grid Item</Text>
    </Column>
    <Column border="neutral-alpha-medium" padding="16" radius="m">
      <Text>Grid Item</Text>
    </Column>
    <Column border="neutral-alpha-medium" padding="16" radius="m">
      <Text>Grid Item</Text>
    </Column>
    <Column border="neutral-alpha-medium" padding="16" radius="m">
      <Text>Grid Item</Text>
    </Column>
    <Column border="neutral-alpha-medium" padding="16" radius="m">
      <Text>Grid Item</Text>
    </Column>
</Grid>

Media

Media provides an optimized way to display images. Access it with the Media component for full customization or use the markdown syntax.

Example image
<Media
    src="/images/projects/project-01/cover-01.jpg"
    sizes="640px"
    alt="Example image"
    aspectRatio="16/9"
    radius="l"
/>

You can also use it to embed YouTube videos.

Example video
<Media
    src="https://www.youtube.com/watch?v=TQT_FSdxbC8"
    alt="Example video"
    aspectRatio="16/9"
    radius="l"
/>

SmartLink provides an enhanced way to link to internal and external resources. You can access it with the SmartLink component for full customization or with the standard markdown syntax.

<SmartLink href=" " suffixIcon="chevronRight">Link with icon</SmartLink>

Custom components

Since Magic Portfolio is based on Once UI, you can use all the components provided by Once UI in the .mdx files, but you need to import them first in the src/product/mdx.tsx file and pass it to the components object.

Tsx
const components = {
    // Add new components
    p: createParagraph as any,
    h1: createHeading("h1") as any,
    ...
    Media,
    SmartLink,
};
Share this post: