mirror of
https://github.com/penpot/penpot.git
synced 2025-02-23 23:35:58 -05:00
Merge pull request #5541 from penpot/fix/juanfran-fix-combobox-design-review
🐛 design review t#9539
This commit is contained in:
commit
617a1060a9
3 changed files with 32 additions and 13 deletions
|
@ -60,18 +60,22 @@
|
||||||
[:class {:optional true} :string]
|
[:class {:optional true} :string]
|
||||||
[:disabled {:optional true} :boolean]
|
[:disabled {:optional true} :boolean]
|
||||||
[:default-selected {:optional true} :string]
|
[:default-selected {:optional true} :string]
|
||||||
[:on-change {:optional true} fn?]])
|
[:on-change {:optional true} fn?]
|
||||||
|
[:has-error {:optional true} :boolean]])
|
||||||
|
|
||||||
(mf/defc combobox*
|
(mf/defc combobox*
|
||||||
{::mf/props :obj
|
{::mf/props :obj
|
||||||
::mf/schema schema:combobox}
|
::mf/schema schema:combobox}
|
||||||
[{:keys [options class disabled default-selected on-change] :rest props}]
|
[{:keys [options class disabled has-error default-selected on-change] :rest props}]
|
||||||
(let [open* (mf/use-state false)
|
(let [open* (mf/use-state false)
|
||||||
open (deref open*)
|
open (deref open*)
|
||||||
|
|
||||||
selected* (mf/use-state default-selected)
|
selected* (mf/use-state default-selected)
|
||||||
selected (deref selected*)
|
selected (deref selected*)
|
||||||
|
|
||||||
|
filter-value* (mf/use-state "")
|
||||||
|
filter-value (deref filter-value*)
|
||||||
|
|
||||||
focused* (mf/use-state nil)
|
focused* (mf/use-state nil)
|
||||||
focused (deref focused*)
|
focused (deref focused*)
|
||||||
|
|
||||||
|
@ -80,12 +84,12 @@
|
||||||
|
|
||||||
dropdown-options
|
dropdown-options
|
||||||
(mf/use-memo
|
(mf/use-memo
|
||||||
(mf/deps options selected)
|
(mf/deps options filter-value)
|
||||||
(fn []
|
(fn []
|
||||||
(->> options
|
(->> options
|
||||||
(array/filter (fn [option]
|
(array/filter (fn [option]
|
||||||
(let [lower-option (.toLowerCase (obj/get option "id"))
|
(let [lower-option (.toLowerCase (obj/get option "id"))
|
||||||
lower-filter (.toLowerCase selected)]
|
lower-filter (.toLowerCase filter-value)]
|
||||||
(.includes lower-option lower-filter)))))))
|
(.includes lower-option lower-filter)))))))
|
||||||
|
|
||||||
on-click
|
on-click
|
||||||
|
@ -95,6 +99,7 @@
|
||||||
(dom/stop-propagation event)
|
(dom/stop-propagation event)
|
||||||
(when-not disabled
|
(when-not disabled
|
||||||
(reset! has-focus* true)
|
(reset! has-focus* true)
|
||||||
|
(when-not (deref open*) (reset! filter-value* ""))
|
||||||
(if (= "INPUT" (.-tagName (.-target event)))
|
(if (= "INPUT" (.-tagName (.-target event)))
|
||||||
(reset! open* true)
|
(reset! open* true)
|
||||||
(swap! open* not)))))
|
(swap! open* not)))))
|
||||||
|
@ -188,6 +193,7 @@
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(let [value (.-value (.-currentTarget event))]
|
(let [value (.-value (.-currentTarget event))]
|
||||||
(reset! selected* value)
|
(reset! selected* value)
|
||||||
|
(reset! filter-value* value)
|
||||||
(reset! focused* nil)
|
(reset! focused* nil)
|
||||||
(when (fn? on-change)
|
(when (fn? on-change)
|
||||||
(on-change value)))))
|
(on-change value)))))
|
||||||
|
@ -206,7 +212,9 @@
|
||||||
[:div {:ref combobox-ref
|
[:div {:ref combobox-ref
|
||||||
:class (stl/css-case
|
:class (stl/css-case
|
||||||
:combobox-wrapper true
|
:combobox-wrapper true
|
||||||
:focused has-focus)}
|
:focused has-focus
|
||||||
|
:has-error has-error
|
||||||
|
:disabled disabled)}
|
||||||
|
|
||||||
[:div {:class class
|
[:div {:class class
|
||||||
:on-click on-click
|
:on-click on-click
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
--combobox-bg-color: var(--color-background-tertiary);
|
--combobox-bg-color: var(--color-background-tertiary);
|
||||||
--combobox-outline-color: none;
|
--combobox-outline-color: none;
|
||||||
--combobox-border-color: none;
|
--combobox-border-color: none;
|
||||||
|
--combobox-error-outline-color: var(--color-accent-error);
|
||||||
|
|
||||||
@include use-typography("body-small");
|
@include use-typography("body-small");
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -22,7 +23,7 @@
|
||||||
gap: var(--sp-xxs);
|
gap: var(--sp-xxs);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
&:hover {
|
&:hover:not(.disabled) {
|
||||||
--combobox-bg-color: var(--color-background-quaternary);
|
--combobox-bg-color: var(--color-background-quaternary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,16 +42,11 @@
|
||||||
background: var(--combobox-bg-color);
|
background: var(--combobox-bg-color);
|
||||||
color: var(--combobox-fg-color);
|
color: var(--combobox-fg-color);
|
||||||
appearance: none;
|
appearance: none;
|
||||||
|
|
||||||
&:disabled {
|
|
||||||
--combobox-bg-color: var(--color-background-primary);
|
|
||||||
--combobox-border-color: var(--color-background-quaternary);
|
|
||||||
--combobox-fg-color: var(--color-foreground-secondary);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.focused {
|
.focused {
|
||||||
--combobox-outline-color: var(--color-accent-primary);
|
--combobox-outline-color: var(--color-accent-primary);
|
||||||
|
--combobox-bg-color: var(--color-background-secondary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.arrow {
|
.arrow {
|
||||||
|
@ -85,3 +81,13 @@
|
||||||
all: unset;
|
all: unset;
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.disabled {
|
||||||
|
--combobox-bg-color: var(--color-background-primary);
|
||||||
|
--combobox-border-color: var(--color-background-quaternary);
|
||||||
|
--combobox-fg-color: var(--color-foreground-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.has-error {
|
||||||
|
--combobox-outline-color: var(--combobox-error-outline-color);
|
||||||
|
}
|
||||||
|
|
|
@ -18,9 +18,11 @@ export default {
|
||||||
component: Combobox,
|
component: Combobox,
|
||||||
argTypes: {
|
argTypes: {
|
||||||
disabled: { control: "boolean" },
|
disabled: { control: "boolean" },
|
||||||
|
hasError: { control: "boolean" },
|
||||||
},
|
},
|
||||||
args: {
|
args: {
|
||||||
disabled: false,
|
disabled: false,
|
||||||
|
hasError: false,
|
||||||
options: [
|
options: [
|
||||||
{ id: "January", label: "January" },
|
{ id: "January", label: "January" },
|
||||||
{ id: "February", label: "February" },
|
{ id: "February", label: "February" },
|
||||||
|
@ -36,7 +38,6 @@ export default {
|
||||||
{ id: "December", label: "December" },
|
{ id: "December", label: "December" },
|
||||||
],
|
],
|
||||||
defaultSelected: "February",
|
defaultSelected: "February",
|
||||||
onChange: (value) => (lastValue = value),
|
|
||||||
},
|
},
|
||||||
parameters: {
|
parameters: {
|
||||||
controls: {
|
controls: {
|
||||||
|
@ -88,6 +89,10 @@ export const WithIcons = {
|
||||||
|
|
||||||
export const TestInteractions = {
|
export const TestInteractions = {
|
||||||
...WithIcons,
|
...WithIcons,
|
||||||
|
args: {
|
||||||
|
...WithIcons.args,
|
||||||
|
onChange: (value) => (lastValue = value),
|
||||||
|
},
|
||||||
play: async ({ canvasElement, step }) => {
|
play: async ({ canvasElement, step }) => {
|
||||||
const canvas = within(canvasElement);
|
const canvas = within(canvasElement);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue