♻️ Rename, move and refactor the input-with-values component (#6387)

* 💄 Adapt behaviour when hovering

* ♻️ Rename, refactor and move component

* 📎 PR changes
This commit is contained in:
luisδμ 2025-05-06 11:19:18 +02:00 committed by GitHub
parent 3249fb43c3
commit e62231cfed
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 85 additions and 78 deletions

View file

@ -11,7 +11,6 @@
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]] [app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
[app.main.ui.ds.controls.combobox :refer [combobox*]] [app.main.ui.ds.controls.combobox :refer [combobox*]]
[app.main.ui.ds.controls.input :refer [input*]] [app.main.ui.ds.controls.input :refer [input*]]
[app.main.ui.ds.controls.input-with-values :refer [input-with-values*]]
[app.main.ui.ds.controls.select :refer [select*]] [app.main.ui.ds.controls.select :refer [select*]]
[app.main.ui.ds.foundations.assets.icon :refer [icon* icon-list]] [app.main.ui.ds.foundations.assets.icon :refer [icon* icon-list]]
[app.main.ui.ds.foundations.assets.raw-svg :refer [raw-svg* raw-svg-list]] [app.main.ui.ds.foundations.assets.raw-svg :refer [raw-svg* raw-svg-list]]
@ -29,6 +28,7 @@
[app.main.ui.ds.product.avatar :refer [avatar*]] [app.main.ui.ds.product.avatar :refer [avatar*]]
[app.main.ui.ds.product.cta :refer [cta*]] [app.main.ui.ds.product.cta :refer [cta*]]
[app.main.ui.ds.product.empty-placeholder :refer [empty-placeholder*]] [app.main.ui.ds.product.empty-placeholder :refer [empty-placeholder*]]
[app.main.ui.ds.product.input-with-meta :refer [input-with-meta*]]
[app.main.ui.ds.product.loader :refer [loader*]] [app.main.ui.ds.product.loader :refer [loader*]]
[app.main.ui.ds.product.user-milestone :refer [user-milestone*]] [app.main.ui.ds.product.user-milestone :refer [user-milestone*]]
[app.main.ui.ds.storybook :as sb] [app.main.ui.ds.storybook :as sb]
@ -48,7 +48,7 @@
:Icon icon* :Icon icon*
:IconButton icon-button* :IconButton icon-button*
:Input input* :Input input*
:InputWithValues input-with-values* :InputWithMeta input-with-meta*
:EmptyPlaceholder empty-placeholder* :EmptyPlaceholder empty-placeholder*
:Loader loader* :Loader loader*
:RawSvg raw-svg* :RawSvg raw-svg*

View file

@ -1,35 +0,0 @@
import { Canvas, Meta } from '@storybook/blocks';
import * as InputWithValuesStories from "./input_with_values.stories";
<Meta title="Controls/InputWithValues" />
# InputWithValues
The `input-with-values*` acts as an input with an optional addition of a series of values that are only indicators, and an event which is triggered when the focus is lost.
<Canvas of={InputWithValuesStories.Default} />
## Technical notes
* You need to pass the mandatory string property `name`.
* You can pass the optional string property `values`.
* You can pass a function property `on-blur` that will be called with the blur event when the component loses focus (including when the user presses enter or esc).
```clj
[:> input-with-values*
{:name name
:values values
:on-blur on-blur}]
```
## Usage guidelines (design)
### When to use
When we have an element that can be editable, but doesn't change its appearance on hover, and adds an extra set of values that aren't editable (they're just indicators).
### Interaction / Behavior
* The component starts on "display" mode, showing the name and the values.
* Once the user clicks on it, the input goes into "active" mode and the only thing that remains and can be editable is the name (the values are hidden).
* If the user presses enter or esc, the component goes back to "display" mode.

View file

@ -4,7 +4,7 @@
;; ;;
;; Copyright (c) KALEIDOS INC ;; Copyright (c) KALEIDOS INC
(ns app.main.ui.ds.controls.input-with-values (ns app.main.ui.ds.product.input-with-meta
(:require-macros (:require-macros
[app.main.style :as stl]) [app.main.style :as stl])
(:require (:require
@ -13,23 +13,23 @@
[app.util.keyboard :as kbd] [app.util.keyboard :as kbd]
[rumext.v2 :as mf])) [rumext.v2 :as mf]))
(def ^:private schema:input-with-values (def ^:private schema:input-with-meta
[:map [:map
[:name :string] [:value :string]
[:values {:optional true} :string] [:meta {:optional true} :string]
[:on-blur {:optional true} fn?]]) [:on-blur {:optional true} fn?]])
(mf/defc input-with-values* (mf/defc input-with-meta*
{::mf/props :obj {::mf/props :obj
::mf/schema schema:input-with-values} ::mf/schema schema:input-with-meta}
[{:keys [name values on-blur] :rest props}] [{:keys [value meta on-blur] :rest props}]
(let [editing* (mf/use-state false) (let [editing* (mf/use-state false)
editing? (deref editing*) editing? (deref editing*)
input-ref (mf/use-ref) input-ref (mf/use-ref)
input (mf/ref-val input-ref) input (mf/ref-val input-ref)
title (if values (str name ": " values) name) title (if meta (str value ": " meta) value)
on-edit on-edit
(mf/use-fn (mf/use-fn
@ -63,19 +63,18 @@
(when ^boolean esc? (dom/blur! node))))) (when ^boolean esc? (dom/blur! node)))))
props (mf/spread-props props {:ref input-ref props (mf/spread-props props {:ref input-ref
:class (stl/css :input-with-values-editing) :default-value value
:default-value name
:auto-focus true :auto-focus true
:on-focus on-focus :on-focus on-focus
:on-blur on-stop-edit :on-blur on-stop-edit
:on-key-down handle-key-down})] :on-key-down handle-key-down})]
(if editing? (if editing?
[:div {:class (stl/css :input-with-values-edit-container)} [:div {:class (stl/css :input-with-meta-edit-container)}
[:> input* props]] [:> input* props]]
[:div {:class (stl/css :input-with-values-container :input-with-values-grid) [:div {:class (stl/css :input-with-meta-container)
:title title :title title
:on-click on-edit} :on-click on-edit}
[:span {:class (stl/css :input-with-values-name)} name] [:span {:class (stl/css :input-with-meta-value)} value]
(when values (when meta
[:span {:class (stl/css :input-with-values-values)} values])]))) [:span {:class (stl/css :input-with-meta-data)} meta])])))

View file

@ -0,0 +1,34 @@
import { Canvas, Meta } from '@storybook/blocks';
import * as InputWithMetaStories from "./input_with_meta.stories";
<Meta title="Product/InputWithMeta" />
# InputWithMeta
The `input-with-meta*` acts as an input with an optional addition of a meta text that is only an indicator, and an event which is triggered when the focus is lost.
<Canvas of={InputWithMetaStories.Default} />
## Technical notes
* You need to pass the mandatory string property `value`.
* You can pass the optional string property `meta`.
* You can pass a function property `on-blur` that will be called with the blur event when the component loses focus (including when the user presses enter or esc).
```clj
[:> input-with-meta* {:value value
:meta meta
:on-blur on-blur}]
```
## Usage guidelines (design)
### When to use
When we have an element that can be editable, but doesn't change its appearance on hover, and adds an extra meta text that isn't editable (it's just an indicator).
### Interaction / Behavior
* The component starts on "display" mode, showing the value and the meta text.
* Once the user clicks on it, the input goes into "active" mode and the only thing that remains and can be editable is the value (the meta text is hidden).
* If the user presses enter or esc, the component goes back to "display" mode.

View file

@ -9,10 +9,14 @@
@use "../_sizes.scss" as *; @use "../_sizes.scss" as *;
@use "../typography.scss" as t; @use "../typography.scss" as t;
.input-with-values-container { .input-with-meta-container {
--input-meta-value: var(--color-foreground-primary);
--input-meta-data: var(--color-foreground-secondary);
--input-meta-background: var(--color-background-tertiary);
@include t.use-typography("body-small"); @include t.use-typography("body-small");
border-radius: $br-8; border-radius: $br-8;
background-color: var(--assets-item-background-color); background-color: var(--input-meta-background);
padding: var(--sp-s); padding: var(--sp-s);
width: 99%; width: 99%;
display: grid; display: grid;
@ -21,27 +25,32 @@
overflow: hidden; overflow: hidden;
white-space: nowrap; white-space: nowrap;
height: $sz-32; height: $sz-32;
&:hover {
--input-meta-background: var(--color-background-quaternary);
cursor: text;
}
} }
.input-with-values-edit-container { .input-with-meta-edit-container {
width: 99%; width: 99%;
border-radius: $br-8; border-radius: $br-8;
height: $sz-32; height: $sz-32;
} }
.input-with-values-name, .input-with-meta-value,
.input-with-values-values { .input-with-meta-data {
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
} }
.input-with-values-name { .input-with-meta-value {
color: var(--color-foreground-primary); color: var(--input-meta-value);
min-width: 0; min-width: 0;
} }
.input-with-values-values { .input-with-meta-data {
color: var(--color-foreground-secondary); color: var(--input-meta-data);
min-width: 0; min-width: 0;
} }

View file

@ -7,24 +7,24 @@
import * as React from "react"; import * as React from "react";
import Components from "@target/components"; import Components from "@target/components";
const { InputWithValues } = Components; const { InputWithMeta } = Components;
export default { export default {
title: "Controls/InputWithValues", title: "Product/InputWithMeta",
component: Components.InputWithValues, component: Components.InputWithMeta,
argTypes: { argTypes: {
name: { value: {
control: { type: "text" }, control: { type: "text" },
}, },
values: { meta: {
control: { type: "text" }, control: { type: "text" },
}, },
}, },
args: { args: {
name: "Property 1", value: "Property 1",
values: "Value1, Value2", meta: "Value1, Value2",
}, },
render: ({ ...args }) => <InputWithValues {...args} />, render: ({ ...args }) => <InputWithMeta {...args} />,
}; };
export const Default = {}; export const Default = {};

View file

@ -30,7 +30,7 @@
[app.main.ui.context :as ctx] [app.main.ui.context :as ctx]
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]] [app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
[app.main.ui.ds.controls.combobox :refer [combobox*]] [app.main.ui.ds.controls.combobox :refer [combobox*]]
[app.main.ui.ds.controls.input-with-values :refer [input-with-values*]] [app.main.ui.ds.product.input-with-meta :refer [input-with-meta*]]
[app.main.ui.hooks :as h] [app.main.ui.hooks :as h]
[app.main.ui.icons :as i] [app.main.ui.icons :as i]
[app.main.ui.workspace.sidebar.assets.common :as cmm] [app.main.ui.workspace.sidebar.assets.common :as cmm]
@ -279,7 +279,7 @@
[:div {:key (str variant-id "-" pos) :class (stl/css :variant-property-container)} [:div {:key (str variant-id "-" pos) :class (stl/css :variant-property-container)}
[:* [:*
[:div {:class (stl/css :variant-property-name-wrapper)} [:div {:class (stl/css :variant-property-name-wrapper)}
[:> input-with-values* {:name (:name prop) [:> input-with-meta* {:value (:name prop)
:data-position pos :data-position pos
:on-blur update-property-name}]] :on-blur update-property-name}]]
@ -900,10 +900,10 @@
(when-not multi? (when-not multi?
[:* [:*
(for [[pos property] (map vector (range) properties)] (for [[pos property] (map vector (range) properties)]
(let [val (str/join ", " (:value property))] (let [meta (str/join ", " (:value property))]
[:div {:key (str (:id shape) pos) :class (stl/css :variant-property-row)} [:div {:key (str (:id shape) pos) :class (stl/css :variant-property-row)}
[:> input-with-values* {:name (:name property) [:> input-with-meta* {:value (:name property)
:values val :meta meta
:data-position pos :data-position pos
:on-blur update-property-name}] :on-blur update-property-name}]
[:> icon-button* {:variant "ghost" [:> icon-button* {:variant "ghost"