Repository: penpot/penpot
File: frontend/src/app/main/ui/inspect/attributes/visibility.cljs (ClojureScript)

Code before:
   [app.common.data.macros :as dm]
   [app.main.ui.components.copy-button :refer [copy-button*]]
   [app.main.ui.components.title-bar :refer [inspect-title-bar*]]
   [app.main.ui.inspect.attributes.common :as cmm]
   [app.util.code-gen.style-css :as css]
   [rumext.v2 :as mf]))

(def properties
  [:opacity
   :blend-mode
   :visibility])

(defn has-visibility-props? [shape]
  (and
   (not (contains? #{:text :group} (:type shape)))
   (or (:opacity shape)
       (:blend-mode shape)
       (:visibility shape))))

(mf/defc visibility-block
  [{:keys [objects shape]}]
  (for [property properties]
    (when-let [value (css/get-css-value objects shape property)]
      (let [property-name (cmm/get-css-rule-humanized property)]
        [:div {:class (stl/css :visibility-row)
               :key   (dm/str "visibility-" (:id shape) "-" (d/name property))}
         [:div {:title property-name
                :class (stl/css :global/attr-label)}
          property-name]
         [:div {:class (stl/css :global/attr-value)}

          [:> copy-button* {:data (css/get-css-property objects shape property)}
           [:div {:class (stl/css :button-children)} value]]]]))))

(mf/defc visibility-panel
  [{:keys [objects shapes]}]
  (let [shapes (filter has-visibility-props? shapes)]

    (when (seq shapes)
      [:div {:class (stl/css :attributes-block)}
       [:> inspect-title-bar*
        {:title "Visibility"
         :class (stl/css :title-spacing-visibility)}

        (when (= (count shapes) 1)
          [:> copy-button* {:data (css/get-shape-properties-css objects (first shapes) properties)
                            :class (stl/css :copy-btn-title)}])]

       (for [shape shapes]
         [:& visibility-block {:shape shape
                               :objects objects

Review comment (refactor):
The `key` is an internal react way to discriminate. It should not be global, just different for each row on this `for`
So, I suggest to simplify it to `(d/name property)`

Code after:
   [app.main.ui.components.copy-button :refer [copy-button*]]
   [app.main.ui.components.title-bar :refer [inspect-title-bar*]]
   [app.main.ui.inspect.attributes.common :as cmm]
   [app.util.code-gen.style-css :as css]
   [rumext.v2 :as mf]))

(def properties
  [:opacity
   :blend-mode
   :visibility])

(defn has-visibility-props? [shape]
  (let [shape-type (:type shape)]
    (and
     (not (or (= shape-type :text) (= shape-type :group)))
     (or (:opacity shape)
         (:blend-mode shape)
         (:visibility shape)))))

(mf/defc visibility-block*
  [{:keys [objects shape]}]
  (for [property properties]
    (when-let [value (css/get-css-value objects shape property)]
      (let [property-name (cmm/get-css-rule-humanized property)]
        [:div {:class (stl/css :visibility-row)
               :key   (d/name property)}
         [:div {:title property-name
                :class (stl/css :global/attr-label)}
          property-name]
         [:div {:class (stl/css :global/attr-value)}

          [:> copy-button* {:data (css/get-css-property objects shape property)}
           [:div {:class (stl/css :button-children)} value]]]]))))

(mf/defc visibility-panel*
  [{:keys [objects shapes]}]
  (let [shapes (mf/with-memo (filter has-visibility-props? shapes))]

    (when (seq shapes)
      [:div {:class (stl/css :attributes-block)}
       [:> inspect-title-bar*
        {:title "Visibility"
         :class (stl/css :title-spacing-visibility)}

        (when (= (count shapes) 1)
          [:> copy-button* {:data (css/get-shape-properties-css objects (first shapes) properties)
                            :class (stl/css :copy-btn-title)}])]

       (for [shape shapes]
         [:> visibility-block* {:shape shape
                                :objects objects