Add in-app help to guide users about variant rules

This commit is contained in:
Juanfran 2025-06-27 15:17:24 +02:00
parent be43365909
commit 72b1919e29
6 changed files with 233 additions and 2 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View file

@ -37,6 +37,7 @@
[app.main.ui.hooks :as h]
[app.main.ui.icons :as i]
[app.main.ui.workspace.sidebar.assets.common :as cmm]
[app.main.ui.workspace.sidebar.options.menus.variants-help-modal]
[app.util.debug :as dbg]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
@ -963,6 +964,12 @@
(mf/deps menu-open*)
#(reset! menu-open* false))
on-click-variant-title-help
(mf/use-fn
(fn []
(modal/show! {:type :variants-help-modal})
(modal/allow-click-outside!)))
update-property-name
(mf/use-fn
(mf/deps variant-id)
@ -1001,8 +1008,15 @@
[:& title-bar {:collapsable false
:title (tr "workspace.options.component")
:class (stl/css :title-spacing-component)}
[:span {:class (stl/css :copy-text)}
(tr "workspace.options.component.main")]]]
(tr "workspace.options.component.main")]
[:div {:class (stl/css :variants-help-modal-button)}
[:> icon-button* {:variant "ghost"
:aria-label (tr "workspace.options.component.variants-help-modal.title")
:on-click on-click-variant-title-help
:icon "help"}]]]]
[:div {:class (stl/css :element-content)}
[:div {:class (stl/css-case :component-wrapper true

View file

@ -32,6 +32,15 @@
cursor: pointer;
}
.title-spacing-component {
justify-content: flex-start;
gap: $s-4;
}
.variants-help-modal-button {
margin-inline-start: auto;
}
.icon-back {
@include flexCenter;
width: $s-12;
@ -163,7 +172,6 @@
display: flex;
align-items: center;
color: var(--title-foreground-color);
margin-right: $s-8;
}
.swappeable {

View file

@ -0,0 +1,101 @@
;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;;
;; Copyright (c) KALEIDOS INC
(ns app.main.ui.workspace.sidebar.options.menus.variants-help-modal
(:require-macros [app.main.style :as stl])
(:require
[app.main.data.modal :as modal]
[app.main.ui.ds.buttons.button :refer [button*]]
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
[app.main.ui.ds.foundations.assets.icon :refer [icon*] :as i]
[app.main.ui.ds.foundations.typography :as t]
[app.main.ui.ds.foundations.typography.heading :refer [heading*]]
[app.main.ui.ds.foundations.typography.text :refer [text*]]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
[rumext.v2 :as mf]))
(mf/defc variants-help-modal
{::mf/register modal/components
::mf/register-as :variants-help-modal}
[]
(let [on-close
(mf/use-fn
(fn [] (modal/hide!)))
close-dialog-outside
(mf/use-fn
(fn [event]
(when (= (dom/get-target event) (dom/get-current-target event))
(modal/hide!))))]
[:div {:class (stl/css :modal-overlay)
:on-click close-dialog-outside}
[:div {:class (stl/css :modal-dialog)}
[:> icon-button* {:on-click on-close
:class (stl/css :modal-close-btn)
:icon i/close
:variant "action"
:aria-label (tr "labels.close")}]
[:> heading* {:level 2
:typography "headline-medium"
:class (stl/css :modal-title)}
(tr "workspace.options.component.variants-help-modal.title")]
[:div {:class (stl/css :modal-content)}
[:div {:class (stl/css :help-text)}
[:> text* {:typography t/body-large}
(tr "workspace.options.component.variants-help-modal.intro")]
[:ul {:class (stl/css :rule-list)}
[:li {:class (stl/css :rule-item)}
[:div {:class (stl/css :rule-item-icon)}
[:> icon* {:icon-id i/text-mixed
:size "s"
:aria-hidden true}]]
[:div {:class (stl/css :rule-item-text)}
[:> text* {:as "span"
:typography t/body-large
:class (stl/css :rule-item-highlight)}
(tr "workspace.options.component.variants-help-modal.rule1")]]]
[:li {:class (stl/css :rule-item)}
[:div {:class (stl/css :rule-item-icon)}
[:> icon* {:icon-id i/img
:size "s"
:aria-hidden true}]]
[:> text* {:typography t/body-large
:class (stl/css :rule-item-text)}
[:span {:class (stl/css :rule-item-highlight)} (tr "workspace.options.component.variants-help-modal.rule2")]
(tr "workspace.options.component.variants-help-modal.rule2.detail")]]
[:li {:class (stl/css :rule-item)}
[:div {:class (stl/css :rule-item-icon)}
[:> icon* {:icon-id i/folder
:size "s"
:aria-hidden true}]]
[:> text* {:class (stl/css :rule-item-text)
:typography t/body-large}
[:span {:class (stl/css :rule-item-highlight)} (tr "workspace.options.component.variants-help-modal.rule3")]
(tr "workspace.options.component.variants-help-modal.rule3.detail")]]]
[:> text* {:typography t/body-large}
(tr "workspace.options.component.variants-help-modal.outro")]]
[:div {:class (stl/css :help-image)}
[:img {:src "images/help-variant-connection.png"
:alt ""}]]]
[:div {:class (stl/css :button-row)}
[:> button* {:variant "primary"
:class (stl/css :modal-accept-btn)
:on-click on-close}
(tr "ds.confirm-ok")]]]]))

View file

@ -0,0 +1,84 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Copyright (c) KALEIDOS INC
@import "refactor/common-refactor.scss";
.modal-overlay {
@extend .modal-overlay-base;
}
.modal-dialog {
@extend .modal-container-base;
max-width: $s-800;
width: 100%;
max-height: unset;
}
.modal-title {
color: var(--modal-title-foreground-color);
margin-bottom: $s-32;
}
.modal-content {
display: flex;
color: var(--color-foreground-secondary);
padding-block-end: $s-32;
}
.modal-close-btn {
@extend .modal-close-btn-base;
}
.rule-list {
margin: $s-32 0;
}
.rule-item {
display: flex;
gap: $s-16;
align-items: center;
margin-bottom: $s-16;
&:last-child {
margin-bottom: 0;
}
}
.rule-item-highlight {
color: var(--color-foreground-primary);
margin-inline-end: $s-4;
}
.rule-item-icon {
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
width: $s-32;
height: $s-32;
background: var(--color-background-quaternary);
color: var(--color-foreground-secondary);
border-radius: 90px;
}
.rule-item-text {
margin: 0;
}
.button-row {
display: flex;
justify-content: end;
padding-block-start: $s-8;
}
.help-text {
inline-size: 100%;
}
.help-image img {
inline-size: 374px;
}

View file

@ -5530,6 +5530,30 @@ msgstr "[property]=[value], [property]=[value]"
msgid "workspace.options.component.variant.malformed.structure.title"
msgstr "Try using the following structure:"
msgid "workspace.options.component.variants-help-modal.title"
msgstr "How variants stay connected"
msgid "workspace.options.component.variants-help-modal.intro"
msgstr "To keep changes when switching between variants, Penpot connects layers using these rules:"
msgid "workspace.options.component.variants-help-modal.rule1"
msgstr "Same name"
msgid "workspace.options.component.variants-help-modal.rule2"
msgstr "Same type"
msgid "workspace.options.component.variants-help-modal.rule2.detail"
msgstr "Rectangle, ellipsis, paths and boolean operations count as same type"
msgid "workspace.options.component.variants-help-modal.rule3"
msgstr "Same hierachy level"
msgid "workspace.options.component.variants-help-modal.rule3.detail"
msgstr "Goups, boards and layouts are considered equivalent"
msgid "workspace.options.component.variants-help-modal.outro"
msgstr "Changing any of these (e.g., renaming or moving a layer) breaks the connection, but reverting the change will restore it."
#: src/app/main/ui/workspace/sidebar/options/menus/constraints.cljs:163
msgid "workspace.options.constraints"
msgstr "Constraints"