Update 2/26/2020 – due to the comments I’ve posted a github project that you can check out to help. https://github.com/tom-daly/spfx-trim-ribbon

What I’m about to show you is a technique that you could use to trim the ribbon and suite bar off an Office 365 – SharePoint site. If you worked with any previous on-prem version we had the SPSecurityTrimmedControl where we could set permissions string. I first learned of this from Dr. Z’s famous post, “How To Hide Ribbon From Users Without Edit Page Privilege

In comes new modern SharePoint sites and pages where we don’t have master pages to work with. Yet the desire of some clients to remove that top bar for users with minimal permissions still remains. So what can we do? I have 2 ways that I can show you how to accomplish this. Let’s start with the easy method and I’ll save the more complex for another post.

Create an SPFx – Application Customizer 

Create the basic hello world application customer. Click the link in the header to reference the Microsoft guidance. We are focused on the top placeholder for this example but any placeholder would work just fine. If you have an application customizer then skip this section

Now that you have an application customizer with top placeholders you are ready for the good stuff.  For this we’ll use PnP JS library to check user permissions. This is consider the easier method because the PnP JS core library does all the heavy lifting. It allows you to easily make a call given a Permission level. Trust me, doing this yourself requires in depth knowledge about the High/Low security permissions, converting decimals to binary and mapping permissions to a bit on a binary string. If you are feeling adventurous you can read some more details on André Lage’s post “It is SharePoint Permission call FullMask or “NearFullMask” in CSOM?”

Add PnP-JS to your project

Follow the guidance here “Getting Started: Install & Use” with the NPM Install

Now in your application customizer .ts file you need to import PnP

import pnp from "sp-pnp-js";

inside the onInit() you must initialize the pnp.setup before you call your content placeholders. If you don’t do this then pnp won’t be ready to use inside the content placeholders.

  @override
  public onInit(): Promise<void> {
    Log.info(LOG_SOURCE, `Initialized ${strings.Title}`);

    return super.onInit().then(_ => {
      pnp.setup({
        spfxContext: this.context
      });

      this.context.placeholderProvider.changedEvent.add(
        this,
        this._renderPlaceHolders
      );
      this._renderPlaceHolders();
    });

  }

This setups up PnP so it can do it’s work. My application customizer creates a sub component called Header and here is where I do my permission checking and trimming.

 private _renderPlaceHolders(): void {
    if (!this._topPlaceholder) {
      this._topPlaceholder = this.context.placeholderProvider.tryCreateContent(
        PlaceholderName.Top
      );

      if (this._topPlaceholder) {
        if (this._topPlaceholder.domElement) {
          const element: React.ReactElement<IHeaderProps> = React.createElement(Header, {});
          ReactDom.render(element, this._topPlaceholder.domElement);
        }
      }
    }
  }

Insides Header.tsx I create a function that will trim the suite bar / ribbon. I am using pnp js to check for a particular security level and then hiding or showing. In my case below I’ve hidden the ribbon for everyone using CSS and then I unhide it here. You can use any of the PermissionKind enumeration listed here

import pnp, { PermissionKind } from "sp-pnp-js";
  public componentDidMount(): void {
    this._trimSuiteBar();
  }
 
 private _trimSuiteBar(): void {
    pnp.sp.web.usingCaching()
      .currentUserHasPermissions(PermissionKind.EditListItems)
      .then(perms => {
        var suiteBar = document.getElementById("SuiteNavPlaceHolder");
        if (!suiteBar || !perms) return; //return if no suite bar OR perms not high enough

        suiteBar.setAttribute("style", "display: block !important");
      });
  }

And there you have it. Suite Bar / Ribbon trimming on Modern Office 365 / SharePoint sites using an SPFx Application Customizer and PnP JS

** Disclaimer ** I have to tell you that this is simply for  information and demonstration purposes. Use at your own risk. It’s not recommended to trim the ribbon or suite bar as it provides functionality to users within the SharePoint site. This is obviously a hack to the product and I’m sure Microsoft would not like you to do this.

Comments
  • 0365
    Posted at 2:43 pm April 29, 2020
    0365
    Reply
    Author

    Seems like there is flickering before hiding.

    • Tom Daly
      Posted at 2:54 pm April 29, 2020
      Tom Daly
      Reply
      Author

      you have some trade offs here due to when app customizers load and caching. css vs js . Just remember all Microsoft code loads first, then it allows app customizers / webparts.

      the least amount of flicker is to hide the bar with CSS and then show it with JavaScript. the css will cache but there is always a flicker.

  • Jake
    Posted at 9:06 am February 26, 2020
    Jake
    Reply
    Author

    That would be great, thanks very much for the response Tom.

    • Tom Daly
      Posted at 6:10 am February 27, 2020
      Tom Daly
      Reply
      Author

      Just posted an update to the article w/ a link to a sample github project. let me know if you have any other questions!

      • Jake
        Posted at 11:54 am March 4, 2020
        Jake
        Reply
        Author

        Thanks so much Tom, this works great. Your help is much appreciated. 🙂

  • William
    Posted at 2:56 pm October 18, 2019
    William
    Reply
    Author

    Hello, I am new to Sharepoint and trying to apply your tutorial. I dit all the MS Sharepoint tutorials you advised (create an extension with top and bottom placeholders) but i am stuck with following errors when running ‘gulp serve’ :

    – ERROR TS2304: Cannot find name ‘IHeaderProps’
    – ERROR TS2552: Cannot find name ‘Header’. Did you mean ‘Headers’ ?

    I assume these need to be declared but how and where?

    For the React and the ReactDom I have added:
    import * as React from “react”;
    import * as ReactDom from “react-dom”;

    Do I need to understand that a file Header.tsx needs to be created ? If so, where to place this ?
    Thank you for your help.

    • William
      Posted at 12:45 pm October 23, 2019
      William
      Reply
      Author

      Hello,
      We resolved this issue, no further action needed.
      Thank you and regards,
      W.

      • Jake
        Posted at 12:30 pm February 18, 2020
        Jake
        Reply
        Author

        Hi William,

        I’m not sure whether you will see this comment but I’m in similar position to yourself, could you perhaps expand on what you had to do to resolve these errors? Any help would be greatly appreciated.

        Thanks

        • Tom Daly
          Posted at 6:46 am February 25, 2020
          Tom Daly
          Reply
          Author

          Thanks for the feedback. The header is if you had a component you were creating in the application customizer. This was a snippet from my original POC. Tomorrow I’ll post a link to a sample github project with the complete solution.

      • Jake
        Posted at 9:36 am February 20, 2020
        Jake
        Reply
        Author

        Hi William,

        I don’t know whether you will see this but I am in the same situation as yourself. I was wondering if you could perhaps elaborate on how you were able to resolve these errors?

        Thanks

  • Leave a Reply

    This site uses Akismet to reduce spam. Learn how your comment data is processed.