Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to use svg paths from @mdi/js #60

Open
crystalfp opened this issue Oct 5, 2023 · 2 comments
Open

How to use svg paths from @mdi/js #60

crystalfp opened this issue Oct 5, 2023 · 2 comments

Comments

@crystalfp
Copy link

Thanks for the component!
I'm using the function call to build the menu on right button click.

<div @contextmenu="openContextMenu($event, item)">{{ item.title }}</div>

With the menu builder:

const openContextMenu = (event: MouseEvent, item: DocumentReferenceWithTitle): void => {
    event.preventDefault();

    const menuItems: {label: string; onClick: () => void}[] = [
        {
          label: "Show text",
          onClick: showDocumentText
        },
        {
          label: "Remove",
          onClick: removeDocument
        },
    ];

    ContextMenu.showContextMenu({
        x: event.x,
        y: event.y,
        items: menuItems
    });
};

This works perfectly for text only menu, but I don't know how to use one of the icons from the @mdi/js packages to decorate the entry.
From a previous attempt with a custom solution I created the SVG string with:

 const svgIcon = (mdi: string): string => {
	  return `<svg viewBox="0 0 24 24" width="24" height="24" stroke="currentColor"
stroke-width="0.2" style="margin-right: 7px; position:  relative; top: 0" fill="currentColor"
stroke-linecap="round" stroke-linejoin="round"><path d="${mdi}"></path></svg>`;
};

Using it, for example:

import {mdiTrashCanOutline} from "@mdi/js";
const svg = svgIcon(mdiTrashCanOutline);

How could use this string instead of the symbol mechanism that I'm not been able to make it work.
Thanks!
mario

@crystalfp
Copy link
Author

crystalfp commented Oct 6, 2023

Here wat I have done, if anyone interested, but I continue hoping for a better solution.

  1. In the template of the main component of the application add (you should also silence eslint that does not like a template inside a template):
<template id="svg-template">
  <svg stroke="currentColor" stroke-width="0.2" style="display: none"
  fill="currentColor" stroke-linecap="round" stroke-linejoin="round">
    <defs />
  </svg>
</template>
  1. In the component using the context menu add:
let defs: SVGDefsElement | null;
onMounted(() => {

    defs = null;
    const body = document.querySelector("body");
    if(!body) return;

    const template = document.querySelector<HTMLTemplateElement>("#svg-template");
    if(!template) return;
    defs = template.querySelector<SVGDefsElement>("defs");
});
  1. Last, in the routine that builds the menu, add (here I have a menu with two entries):
import {mdiTextBoxOutline, mdiTrashCanOutline} from "@mdi/js";

    const html = `<symbol viewBox="0 0 24 24" id="text-box"><path d="${mdiTextBoxOutline}"></path></symbol>
                  <symbol viewBox="0 0 24 24" id="trash-can"><path d="${mdiTrashCanOutline}"></path></symbol>`;
    if(defs) defs.innerHTML = html.replaceAll(/ {2,}/g, " ");
...
    const menuItems: {label: string; svgIcon: string; svgProps: Record<string, string>; onClick?: () => void}[] = [
        {
            label: "Show text",
            svgIcon: "#text-box",
            svgProps: {fill: fillColor},
            onClick: showDocumentText
        },
...

Hope it helps
mario

@crystalfp
Copy link
Author

Simplified and made more elegant. I created a component that define the needed SVG symbols

<script setup lang="ts">
const props = defineProps<{

    /** SVG path and id for icons to be called in the context menu */
    icons: {path: string; id: string}[];
}>();
</script>

<template>
<svg stroke="currentColor" stroke-width="0.2"
     fill="currentColor" stroke-linecap="round" stroke-linejoin="round">
  <defs>
    <symbol v-for="co of props.icons" :id="co.id" :key="co.id" viewBox="0 0 24 24">
      <path :d="co.path" />
    </symbol>
  </defs>
</svg>
</template>

Hope it helps.
mario

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant