diff --git a/frontend/src/app/main/ui/ds.cljs b/frontend/src/app/main/ui/ds.cljs index 063f2bf874..1da41f26c4 100644 --- a/frontend/src/app/main/ui/ds.cljs +++ b/frontend/src/app/main/ui/ds.cljs @@ -11,6 +11,7 @@ [app.main.ui.ds.buttons.icon-button :refer [icon-button*]] [app.main.ui.ds.controls.combobox :refer [combobox*]] [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.foundations.assets.icon :refer [icon* icon-list]] [app.main.ui.ds.foundations.assets.raw-svg :refer [raw-svg* raw-svg-list]] @@ -44,6 +45,7 @@ :Icon icon* :IconButton icon-button* :Input input* + :InputWithValues input-with-values* :EmptyPlaceholder empty-placeholder* :Loader loader* :RawSvg raw-svg* diff --git a/frontend/src/app/main/ui/ds/controls/input.scss b/frontend/src/app/main/ui/ds/controls/input.scss index d823942e5e..0eeb49359b 100644 --- a/frontend/src/app/main/ui/ds/controls/input.scss +++ b/frontend/src/app/main/ui/ds/controls/input.scss @@ -65,7 +65,6 @@ margin: var(--input-margin, unset); // remove settings from global css padding: 0; appearance: none; - margin-inline-start: var(--sp-xxs); height: var(--input-height, #{$sz-32}); border: none; background: none; @@ -93,6 +92,10 @@ } } +.input-with-icon { + margin-inline-start: var(--sp-xxs); +} + .icon { color: var(--color-foreground-secondary); } diff --git a/frontend/src/app/main/ui/ds/controls/input_with_values.cljs b/frontend/src/app/main/ui/ds/controls/input_with_values.cljs new file mode 100644 index 0000000000..56c97a32ae --- /dev/null +++ b/frontend/src/app/main/ui/ds/controls/input_with_values.cljs @@ -0,0 +1,69 @@ +;; 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.ds.controls.input-with-values + (:require-macros + [app.main.style :as stl]) + (:require + [app.main.ui.ds.controls.input :refer [input*]] + [app.util.dom :as dom] + [app.util.keyboard :as kbd] + [rumext.v2 :as mf])) + +(def ^:private schema:input-with-values + [:map + [:name :string] + [:values :string] + [:on-blur {:optional true} fn?]]) + + +(mf/defc input-with-values* + {::mf/props :obj + ::mf/schema schema:input-with-values} + [{:keys [name values on-blur]}] + (let [editing* (mf/use-state false) + editing? (deref editing*) + input-ref (mf/use-ref) + input (mf/ref-val input-ref) + title (str name ": " values) + on-edit + (mf/use-fn + (fn [event] + (dom/stop-propagation event) + (reset! editing* true) + (dom/focus! input))) + on-stop-edit + (mf/use-fn + (mf/deps on-blur) + (fn [event] + (let [new-name (dom/get-target-val event)] + (dom/stop-propagation event) + (reset! editing* false) + (when on-blur + (on-blur new-name))))) + + handle-key-down + (mf/use-fn + (fn [event] + (let [enter? (kbd/enter? event) + esc? (kbd/esc? event) + node (dom/get-target event)] + (when ^boolean enter? (dom/blur! node)) + (when ^boolean esc? (dom/blur! node)))))] + + (if editing? + [:div {:class (stl/css :input-with-values-edit-container)} + [:> input* + {:ref input-ref + :class (stl/css :input-with-values-editing) + :default-value name + :auto-focus true + :on-blur on-stop-edit + :on-key-down handle-key-down}]] + [:div {:class (stl/css :input-with-values-container :input-with-values-grid) + :title title :on-click on-edit} + [:span {:class (stl/css :input-with-values-name)} name] + [:span {:class (stl/css :input-with-values-values)} values]]))) diff --git a/frontend/src/app/main/ui/ds/controls/input_with_values.mdx b/frontend/src/app/main/ui/ds/controls/input_with_values.mdx new file mode 100644 index 0000000000..7374e3827a --- /dev/null +++ b/frontend/src/app/main/ui/ds/controls/input_with_values.mdx @@ -0,0 +1,37 @@ +import { Canvas, Meta } from '@storybook/blocks'; +import * as InputWithValuesStories from "./input_with_values.stories"; + + + +# InputWithValues + +The `input-with-values*` acts as an input with an addition of a series of values that are only indicators. + + + + +## Technical notes + +* You need to pass the mandatory string properties `name` and `values` +* You can pass a function property `on-blur` that will be called with the new value when the component lost focus (including when the user press 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 need to be editable, and an extra set of values that aren't editables and are only 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 that is editable is the name (the values are hidden) +* If the user press enter or esc, the component goes back to "display" mode diff --git a/frontend/src/app/main/ui/ds/controls/input_with_values.scss b/frontend/src/app/main/ui/ds/controls/input_with_values.scss new file mode 100644 index 0000000000..131a4a6944 --- /dev/null +++ b/frontend/src/app/main/ui/ds/controls/input_with_values.scss @@ -0,0 +1,47 @@ +// 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 + +@use "../_borders.scss" as *; +@use "../spacing.scss" as *; +@use "../_sizes.scss" as *; +@use "../typography.scss" as t; + +.input-with-values-container { + @include t.use-typography("body-small"); + border-radius: $br-8; + background-color: var(--assets-item-background-color); + padding: var(--sp-s); + width: 99%; + display: grid; + grid-template-columns: auto 1fr; + gap: var(--sp-s); + overflow: hidden; + white-space: nowrap; + height: $sz-32; +} + +.input-with-values-edit-container { + width: 99%; + border-radius: $br-8; + height: $sz-32; +} + +.input-with-values-name, +.input-with-values-values { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.input-with-values-name { + color: var(--color-foreground-primary); + min-width: 0; +} + +.input-with-values-values { + color: var(--color-foreground-secondary); + min-width: 0; +} diff --git a/frontend/src/app/main/ui/ds/controls/input_with_values.stories.jsx b/frontend/src/app/main/ui/ds/controls/input_with_values.stories.jsx new file mode 100644 index 0000000000..a90b1618a6 --- /dev/null +++ b/frontend/src/app/main/ui/ds/controls/input_with_values.stories.jsx @@ -0,0 +1,30 @@ +// 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 * as React from "react"; +import Components from "@target/components"; + +const { InputWithValues } = Components; + +export default { + title: "Controls/InputWithValues", + component: Components.InputWithValues, + argTypes: { + name: { + control: { type: "text" }, + }, + values: { + control: { type: "text" }, + }, + }, + args: { + name: "Property 1", + values: "Value1, Value2", + }, + render: ({ ...args }) => , +}; + +export const Default = {};