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

React button not showing icon #508

Open
StephaneAdeso opened this issue Sep 29, 2023 · 13 comments
Open

React button not showing icon #508

StephaneAdeso opened this issue Sep 29, 2023 · 13 comments
Assignees
Labels
bug Something isn't working

Comments

@StephaneAdeso
Copy link

StephaneAdeso commented Sep 29, 2023

I am developing an extension for vscode with React and using the WebUi Toolkit library for components. I want to add a "save" icon to my button.

I have followed the documentation to add my button in react and add an icon.
So the resulting code is:

import { VSCodeButton } from '@vscode/webview-ui-toolkit/react';    

<VSCodeButton >
    Save
    <span slot="start" className="codicon codicon-save"></span>
</VSCodeButton>

But the icon is not showing. How to add the icon to the button?

image

@StephaneAdeso StephaneAdeso added the bug Something isn't working label Sep 29, 2023
@hawkticehurst
Copy link
Member

hawkticehurst commented Oct 6, 2023

Hey @StephaneAdeso! Out of curiosity what does your content security policy look like in your extension? This looks like a case where the icon is being blocked from rendering.

As an example, your CSP should probably look something like this: https://github.com/microsoft/vscode-webview-ui-toolkit-samples/blob/main/frameworks/component-gallery-react/src/panels/ComponentGalleryPanel.ts#L122

In particular, the font-src CSP rule should allow the codicons.ttf (required to render Codicons) file to be rendered.

@StephaneAdeso
Copy link
Author

Thank you very much for answering. After several days without finding a solution, I finally decided to use an icon library. I must also say that you are right. I did not have any content security policy established. As soon as I have some time I'll try it. Thank you so much.

@hawkticehurst
Copy link
Member

Of course! Please let me know how it goes so I can know if this issue is resolved and I can close it :)

@StephaneAdeso
Copy link
Author

Sorry, i was unable to find a correct CSP configuration that works. All variations i tried throw errors so i removed it.

@hawkticehurst
Copy link
Member

Hmm okay, in that case, could you create/provide a link to a GitHub repo with a small reproduction of the issue so I can see if I can figure out what the problem might be?

@maninak
Copy link

maninak commented Dec 13, 2023

I'm using vue with the web components and I have the same issue.

My CSP is the following:

      <meta
        http-equiv="Content-Security-Policy"
        content="
          default-src 'none';
          object-src 'none';
          base-uri 'none';
          style-src ${allowedSource} 'unsafe-inline';
          img-src ${allowedSource} https: data:;
          script-src 'strict-dynamic' 'nonce-${nonce}' 'unsafe-inline' https:;
        "
      >

But I don't think it's a CSP issue because I get no CSP-related issues logged in the webview's dev tools' console and even if I delete the whole CSP I still have the icons not showing.

Repro steps

  1. $ git clone git@github.com:cytechmobile/radicle-vscode-extension.git
  2. $ git checkout 4ee3787d591a1612242b43b663bd7167fbee9fad (or browse source code)
  3. F5 (no need to install node modules)
  4. Ctrl + Shift + P (to open Cmd Palette) and select command "Open dat webview"

you should be seeing this

Peek.2023-12-13.06-35.mp4

The related code can be found under src/webviews/src/components/Counter.vue and looks like this

    <vscode-button appearance="icon" @click="showInfoNotifWithCount">
      <span class="codicon codicon-megaphone"></span>
    </vscode-button>

@r3m0t
Copy link

r3m0t commented Dec 13, 2023

You are missing the font-src directive, so default-src 'none' is taking precedence.

@maninak
Copy link

maninak commented Dec 13, 2023

@r3m0t if you could share a diff so that I can better understand where I'm missing it that would help a lot, thank you!

I Ctrl + F for "font-src" in the docs and don't find anything.

That's what's shown in the docs
image

@hawkticehurst
Copy link
Member

Hey @maninak! Yes, as @r3m0t said this looks like a case of not including the font-src CSP directive (thank you for chiming in @r3m0t btw 😊).

You would add the font-src CSP to the content attribute in the meta tag you wrote out above. Something like this:

<meta 
  http-equiv="Content-Security-Policy" 
  content="
    default-src 'none'; 
    script-src 'nonce-${nonce}';
    style-src ${webview.cspSource}; 
    font-src ${webview.cspSource};   // <-- here!
">

The above example is specifically pulled from our component-gallery sample extension. Feel free to look there for more context.

Also, the content security policy docs live in Webview API VS Code documentation since CSP is a topic that applies to webview extension development in general, not just in the Webview UI Toolkit.

Hope that helps, but please let me know if there are any other questions you have!

@maninak
Copy link

maninak commented Dec 14, 2023

Thank you both for the quick respons and especially @hawkticehurst for the detailed hints.

I've changed my CSP to be

      <meta
        http-equiv="Content-Security-Policy"
        content="
          default-src 'none';
          object-src 'none';
          base-uri 'none';
          style-src ${allowedSource} 'unsafe-inline';
          img-src ${allowedSource} https: data:;
          script-src 'strict-dynamic' 'nonce-${nonce}' 'unsafe-inline' https:;
          font-src ${allowedSource};
        "
      >

The above seemed to have no effect. Noteworthy is that the chromium devtools report no CSP warnings or errors! Neither did they before nor do they now after adding the font-src directive.

@r3m0t
Copy link

r3m0t commented Dec 14, 2023

What does the Network tab show after filtering for Font?

Is the codicon.css stylesheet referenced in your project?

@maninak
Copy link

maninak commented Dec 15, 2023

Hey @r3m0t, after reading your comment I didn't know to which codicon.css you were referring to. There's no mention of it on the Readme nor the Getting Started Guide.

After checking the link @hawkticehurst shared above I found that in that sample there's an explicit import for codicon.css which also imports codicon.ttf and both are local in the repo.

I copy-pasted those into my vue repo's assets/ folder. The vue repo is nested in my vscode extension which meant that the actual path is src/webviews/src/assets/codicon.css. Then I imported the css like so inside my App.vue.

<style>
@import './assets/codicon.css';
</style>

In codicon.css the font is loaded like so

 @font-face {
  font-family: "codicon";
  font-display: block;
  src: url("./codicon.ttf") format("truetype");
}

Here's is also a screencap of the filetree showing that those files coexist and colocate inside the dist dir that vite produces

See image

This has definitely moved me closer but now I'm seeing this in the console and the network tab
image
image

In my webview options I have localResourceRoots set with what seems to be a correct path to the location of the above assets:

  const webviewOptions: WebviewOptions = {
    enableScripts: true,
    localResourceRoots: [
      Uri.joinPath(getExtensionContext().extensionUri, 'dist'),
      Uri.joinPath(getExtensionContext().extensionUri, 'assets'),
      Uri.joinPath(getExtensionContext().extensionUri, 'src', 'webviews', 'dist'),
    ],
  }

It looks like it's a problem with how the ttf file's path resolves and honestly I have no clue how to fix it.

For reference, the index.css file gets loaded correctly and its path seems to be different (I guess vite patches behind the scenes)
image

Shouldn't this very important info about copying and importing those files be in the readme/guide? Better yet, why isn't this an implementation detail handled by the UI lib itself and I have to copy and import those manually? Perhaps I am doing it wrong?

Thank you so much for your assistance! 🙏

@maninak
Copy link

maninak commented Dec 15, 2023

OK, so after copying the css and ttf file under assets/ and importing it in my App.vue what was left was setting base: '' in the vue app's vite.config.ts which, for the sake of completion, now looks like this:

import { fileURLToPath, URL } from 'node:url'

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    vue(),
  ],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url)),
      'lib': fileURLToPath(new URL('../../lib', import.meta.url)),
      'utils': fileURLToPath(new URL('../utils', import.meta.url)),
    }
  },
  build: {
    rollupOptions: {
      external: ['vscode'],
      // produce predictable filenames without cache-busting SHA suffix
      output: {
        entryFileNames: `assets/[name].js`,
        chunkFileNames: `assets/[name].js`,
        assetFileNames: `assets/[name].[ext]`,
      },
    },
  },
  base: '', // <-- this fixed the problem with the resolved path to codicons.ttf :man_shrugging: 
})

Of course, this is more specific to my use case, but I'd argue that it is tangential to the scope of this issue, since I wouldn't have to deal with all of this if the UI library would make sure to import its necessary assets by itself and if the necessity for the font-src CSP directive was documented.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants