diff --git a/src/components/pin-networked-object-button.js b/src/components/pin-networked-object-button.js
index 51f72ac1120cfa26af62d997225996a94bb0c33f..59883f8a769b64f9b4ae270f38523c2df30167ac 100644
--- a/src/components/pin-networked-object-button.js
+++ b/src/components/pin-networked-object-button.js
@@ -1,13 +1,33 @@
 AFRAME.registerComponent("pin-networked-object-button", {
+  schema: {
+    labelSelector: { type: "string" }
+  },
+
   init() {
     this.scene = document.querySelector("a-scene");
+    this.labelEl = this.el.parentNode.querySelector(this.data.labelSelector);
+
+    NAF.utils.getNetworkedEntity(this.el).then(networkedEl => (this.targetEl = networkedEl));
 
     this.onClick = () => {
-      this.targetEl.setAttribute("pinnable", { pinned: true });
-      this.scene.emit("object_pinned", { el: this.targetEl });
-    };
+      let pinned = false;
 
-    NAF.utils.getNetworkedEntity(this.el).then(networkedEl => (this.targetEl = networkedEl));
+      if (this.targetEl.components.pinnable) {
+        pinned = this.targetEl.components.pinnable.data.pinned;
+      }
+
+      if (!pinned) {
+        this.el.parentNode.setAttribute("clickable", "");
+        this.targetEl.setAttribute("pinnable", { pinned: true });
+        this.labelEl.setAttribute("text", { value: "pinned" });
+        this.scene.emit("object_pinned", { el: this.targetEl });
+      } else {
+        this.el.parentNode.removeAttribute("clickable");
+        this.targetEl.setAttribute("pinnable", { pinned: false });
+        this.labelEl.setAttribute("text", { value: "unpinned" });
+        this.scene.emit("object_unpinned", { el: this.targetEl });
+      }
+    };
   },
 
   play() {
diff --git a/src/components/pinnable.js b/src/components/pinnable.js
index f0f2e11f2c790c81804aa0385a3cfe8f72ecd057..14c7734039ba74fdc4333e19e0940c9aa6e2ddd4 100644
--- a/src/components/pinnable.js
+++ b/src/components/pinnable.js
@@ -6,10 +6,25 @@ AFRAME.registerComponent("pinnable", {
   init() {},
 
   update() {
-    this.el.setAttribute("grabbable", { maxGrabbers: this.data.pinned ? 0 : 1 });
-
     if (this.data.pinned) {
+      if (this.el.components.grabbable) {
+        this.prevMaxGrabbers = this.el.components.grabbable.data.maxGrabbers;
+      }
+
+      if (this.el.components.body) {
+        this.prevBodyType = this.el.components.body.data.type;
+      }
+
       this.el.setAttribute("body", { type: "static" });
+      this.el.setAttribute("grabbable", { maxGrabbers: 0 });
+    } else {
+      if (typeof this.prevMaxGrabbers !== "undefined") {
+        this.el.setAttribute("grabbable", { maxGrabbers: this.prevMaxGrabbers });
+      }
+
+      if (typeof this.prevBodyType !== "undefined") {
+        this.el.setAttribute("body", { type: this.prevBodyType });
+      }
     }
   }
 });
diff --git a/src/components/sticky-object.js b/src/components/sticky-object.js
index dbf57ed56353304d8409c42f776d76a53bcbe294..64d229b61ef844ce5b3d3bf8359bfeddfd958331 100644
--- a/src/components/sticky-object.js
+++ b/src/components/sticky-object.js
@@ -60,7 +60,7 @@ AFRAME.registerComponent("sticky-object", {
   },
 
   _onGrab() {
-    if (!this.el.grabbable || this.el.grabbable.data.maxGrabbers === 0) return;
+    if (!this.el.components.grabbable || this.el.components.grabbable.data.maxGrabbers === 0) return;
 
     this.setLocked(false);
     this.el.body.collisionResponse = false;
diff --git a/src/components/super-networked-interactable.js b/src/components/super-networked-interactable.js
index f2d1b398d387f60704488a69f58f1fb2bb9ced5d..5e2e3757784a926bad22e608d6ca8325d05be085 100644
--- a/src/components/super-networked-interactable.js
+++ b/src/components/super-networked-interactable.js
@@ -51,7 +51,7 @@ AFRAME.registerComponent("super-networked-interactable", {
   },
 
   _onGrabStart: function(e) {
-    if (!this.el.grabbable || this.el.grabbable.data.maxGrabbers === 0) return;
+    if (!this.el.components.grabbable || this.el.components.grabbable.data.maxGrabbers === 0) return;
 
     this.hand = e.detail.hand;
     this.hand.emit("haptic_pulse", { intensity: "high" });
diff --git a/src/hub.html b/src/hub.html
index c54135cdd930d0529e0e49f3c56f822a94a1e13d..d2d57473cdb438717ef6083432f7e898d37ffa1d 100644
--- a/src/hub.html
+++ b/src/hub.html
@@ -153,8 +153,8 @@
                     pinnable
                 >
                     <a-entity class="action-buttons" visible-while-frozen>
-                        <a-entity mixin="rounded-text-button" pin-networked-object-button position="0 0.125 0.01"> </a-entity>
-                        <a-entity text=" value:pin; width:1.75; align:center;" text-raycast-hack position="0 0.125 0.02"></a-entity>
+                        <a-entity mixin="rounded-text-button" pin-networked-object-button="labelSelector:.pin-button-label" position="0 0.125 0.01"> </a-entity>
+                        <a-entity class="pin-button-label" text=" value:unpinned; width:1.75; align:center;" text-raycast-hack position="0 0.125 0.02"></a-entity>
                         <a-entity mixin="rounded-text-button" remove-networked-object-button position="0 -0.125 0.01"> </a-entity>
                         <a-entity text=" value:remove; width:1.75; align:center;" text-raycast-hack position="0 -0.125 0.02"></a-entity>
                     </a-entity>