1

I'm trying to create a spfx-react webpart for SharePoint Online like the feedback button on the walmart page (https://www.walmart.com right side).

This works in edit mode and in the workbench (local dev environment). But as soon as i press publish the css seems to get overridden or contained to the controlzone (see this question https://github.com/SharePoint/sp-dev-docs/issues/1227)

Is there any workaround to create a webpart/component with position: fixed for SharePoint Online? components/FixedButton.module.scss

  .container {
    max-width: 800px;
    margin: 0px auto;
    position: fixed;
    top: 150px;
    height: 50px;
    width: 50px;

    background-color: "[theme: themePrimary, default: #CCE3F2]";
    z-index: 100;
  }

Update 2019.07.03: additional code to better demonstrate the desired solution:

components/FixedButton.tsx

private updatePosition(): void {
    let style: BtnPositionStyle = new BtnPositionStyle();
    style.top = this.props.btnTop + "%";
    switch (this.props.btnPosition) {
      case 1:
        style.left = 15 + "px";
        style.right = "auto";
        break;
      case 2:
        style.left = "50%";
        style.right = "50%";
        break;
      case 3:
        style.left = "auto";
        style.right = 15 + "px";
        break;
      default:
        break;
    }
    this.lastPosition = this.props.btnPosition;
    this.lastStyle = style;
  }

public render(): React.ReactElement<IFixedButtonProps> {

    this.updatePosition();

    let btnStyle = {
      "borderRadius": "50%",
      backgroundColor: this.props.btnColor,
      height: this.props.btnSize + "px",
      width: this.props.btnSize + "px",
      "cursor": "pointer"
    };

    let txtStyle = {
      transform: "rotate(" + this.props.btnRotation + "deg)",
      color: this.props.txtColor,
    };

    return (
      <div className={styles.fixedButton}>

        <div className={styles.container} style={this.lastStyle} onClick={this.btnClick}>
          <div className={styles.centerContent} style={btnStyle}>
            <div>
              <h2 style={txtStyle} className={styles.alignCenter}>{this.props.btnText}</h2>
            </div>
          </div>
        </div>
      </div>
    );
  }

  private btnClick(event: React.MouseEvent<HTMLDivElement>): void {
    window.open(this.props.btnTarget, "_blank");
  }

FixedButtonWebPart.ts

protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
    return {
      pages: [
        {
          header: {
            description: strings.PropertyPaneDescription
          },
          groups: [
            {
              groupName: strings.BasicGroupName,
              groupFields: [
                PropertyPaneDropdown('btnPosition', {
                  label: "Button Position",
                  options: [
                    { key: 1, text: "Top left" },
                    { key: 2, text: "Top mid" },
                    { key: 3, text: "Top right" },
                  ]
                }),
                PropertyPaneTextField('btnText', {
                  label: "Button text",
                  maxLength: 55,
                  multiline: false,
                  value: "You're breathtaking!"
                }),
                PropertyPaneTextField('btnTarget', {
                  label: "Target (opens in new tab)",
                  multiline: false,
                  value: "https://www.google.com",
                  maxLength: 125,
                  onGetErrorMessage: this.validateLink
                }),
                PropertyPaneTextField('btnColor', {
                  label: "BackgroundColor",
                  multiline: false,
                  value: "#0075BE",
                  maxLength: 12,
                  onGetErrorMessage: this.validateColor
                }),
                PropertyPaneTextField('txtColor', {
                  label: "Textcolor",
                  multiline: false,
                  value: "#FFFFFF",
                  maxLength: 12,
                  onGetErrorMessage: this.validateColor
                }),
                PropertyPaneSlider('btnSize', {
                  label: "Button Size",
                  min: 100,
                  max: 400,
                  value: 250
                }),
                PropertyPaneSlider('btnRotation', {
                  label: "Text rotation",
                  min: -180,
                  max: 180,
                  value: 0
                }),
                PropertyPaneSlider('btnTop', {
                  label: "Top gap",
                  min: 5,
                  max: 95,
                  value: 10
                })
              ]
            }
          ]
        }
      ]
    };
  }

components/IFixedButtonProps

export interface IFixedButtonProps {
  btnPosition: number;
  btnColor: string;
  txtColor: string;
  btnText: string;
  btnTarget: string;
  btnSize: number;
  btnRotation: number;
  btnTop: number;
}

2 Answers 2

0

@Sebastian,

If you want the feedback to appear outside of a web part (and, I assume, on every page?), you should look at creating a SharePoint Framework Extension instead.

See https://docs.microsoft.com/en-us/sharepoint/dev/spfx/extensions/get-started/build-a-hello-world-extension

The good news is that you should be able to re-use most of your existing code and CSS.

Good luck!

1
  • Hi @Hugo, thanks for the answer, but I'm not planning on creating an Extension. I just want to create a button that you can add to specific pages that opens up a link in a new tab. Jun 26, 2019 at 14:20
0

Sample demo:

enter image description here

public render(): void {        
    document.body.insertAdjacentHTML('beforeend', `<a style="position:absolute;top: 150px;left:120px;height: 50px;" target="_blank" href="https://www.google.com/">Google</a>`);       
  }
1
  • This solution seems to work for static links like the one you show in your example but really messes up the flow of the rest of the page (e.g. property panes). Also your code example seems to conflict with newer versions of the spfx framework (I'm using 1.8.2 currently with rush-stack-compiler 2.9) Jul 3, 2019 at 13:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.