mirror of
https://github.com/penpot/penpot.git
synced 2025-01-22 14:39:45 -05:00
Merge pull request #4938 from penpot/ladybenko-7879-ds-input
🎉 Implement input* component
This commit is contained in:
commit
1c2b6f5ab5
7 changed files with 199 additions and 1 deletions
|
@ -8,6 +8,7 @@
|
|||
(:require
|
||||
[app.main.ui.ds.buttons.button :refer [button*]]
|
||||
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
|
||||
[app.main.ui.ds.forms.input :refer [input*]]
|
||||
[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.typography :refer [typography-list]]
|
||||
|
@ -22,6 +23,7 @@
|
|||
:Heading heading*
|
||||
:Icon icon*
|
||||
:IconButton icon-button*
|
||||
:Input input*
|
||||
:Loader loader*
|
||||
:RawSvg raw-svg*
|
||||
:Text text*
|
||||
|
|
|
@ -8,3 +8,5 @@
|
|||
|
||||
// TODO: create actual tokens once we have them from design
|
||||
$br-8: px2rem(8);
|
||||
|
||||
$b-1: px2rem(1);
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
background: var(--button-bg-color);
|
||||
color: var(--button-fg-color);
|
||||
border: 1px solid var(--button-border-color);
|
||||
border: $b-1 solid var(--button-border-color);
|
||||
|
||||
&:hover {
|
||||
--button-bg-color: var(--button-hover-bg-color);
|
||||
|
|
32
frontend/src/app/main/ui/ds/forms/input.cljs
Normal file
32
frontend/src/app/main/ui/ds/forms/input.cljs
Normal file
|
@ -0,0 +1,32 @@
|
|||
;; 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.forms.input
|
||||
(:require-macros
|
||||
[app.common.data.macros :as dm]
|
||||
[app.main.style :as stl])
|
||||
(:require
|
||||
[app.main.ui.ds.foundations.assets.icon :refer [icon* icon-list]]
|
||||
[app.util.dom :as dom]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(mf/defc input*
|
||||
{::mf/props :obj}
|
||||
[{:keys [icon class type ref] :rest props}]
|
||||
(assert (or (nil? icon) (contains? icon-list icon)))
|
||||
(let [ref (or ref (mf/use-ref))
|
||||
type (or type "text")
|
||||
icon-class (stl/css-case :input true
|
||||
:input-with-icon (some? icon))
|
||||
props (mf/spread-props props {:class icon-class :ref ref :type type})
|
||||
handle-icon-click (mf/use-fn (mf/deps ref)
|
||||
(fn [_]
|
||||
(let [input-node (mf/ref-val ref)]
|
||||
(dom/select-node input-node)
|
||||
(dom/focus! input-node))))]
|
||||
[:> "span" {:class (dm/str class " " (stl/css :container))}
|
||||
(when icon [:> icon* {:id icon :class (stl/css :icon) :on-click handle-icon-click}])
|
||||
[:> "input" props]]))
|
51
frontend/src/app/main/ui/ds/forms/input.mdx
Normal file
51
frontend/src/app/main/ui/ds/forms/input.mdx
Normal file
|
@ -0,0 +1,51 @@
|
|||
import { Canvas, Meta } from '@storybook/blocks';
|
||||
import * as InputStories from "./input.stories";
|
||||
|
||||
<Meta title="Forms/Input" />
|
||||
|
||||
# Input
|
||||
|
||||
The `input*` component is a wrapper to the HTML `<input>` element with custom styling
|
||||
and additional elements that adds context and, in some cases, adds extra
|
||||
functionality.
|
||||
|
||||
<Canvas of={InputStories.Default} />
|
||||
|
||||
|
||||
## Technical notes
|
||||
|
||||
### Icons
|
||||
|
||||
`input*` accepts an `icon` prop, which must contain an [icon ID](../foundations/assets/icon.mdx).
|
||||
These are available in the `app.main.ds.foundations.assets.icon` namespace.
|
||||
|
||||
```clj
|
||||
(ns app.main.ui.foo
|
||||
(:require
|
||||
[app.main.ui.ds.foundations.assets.icon :as i]))
|
||||
```
|
||||
|
||||
```clj
|
||||
[:> input* {:icon i/effects}]
|
||||
```
|
||||
|
||||
<Canvas of={InputStories.WithIcon} />
|
||||
|
||||
## Usage guidelines (design)
|
||||
|
||||
### Where to use
|
||||
|
||||
In forms where the user needs to input any short text or number.
|
||||
|
||||
### When to use
|
||||
|
||||
When the information that is needed is short and needs an element to add context
|
||||
for using it or additional functionality (like color picker).
|
||||
|
||||
### Size
|
||||
|
||||
The width of the component depends on the content and layout. They can expand to
|
||||
fill the container or the content area to which they relate (e.g. tabs) and adapt
|
||||
depending on whether there are one or two input elements with or without buttons
|
||||
next to them. Their height is always fixed, `32px`, with text area being used for
|
||||
larger text blocks.
|
64
frontend/src/app/main/ui/ds/forms/input.scss
Normal file
64
frontend/src/app/main/ui/ds/forms/input.scss
Normal file
|
@ -0,0 +1,64 @@
|
|||
@use "../_borders.scss" as *;
|
||||
@use "../_sizes.scss" as *;
|
||||
@use "../typography.scss" as *;
|
||||
|
||||
.container {
|
||||
--input-bg-color: var(--color-background-tertiary);
|
||||
--input-fg-color: var(--color-foreground-primary);
|
||||
--input-icon-color: var(--color-foreground-secondary);
|
||||
--input-outline-color: none;
|
||||
|
||||
display: inline-flex;
|
||||
column-gap: var(--sp-xs);
|
||||
align-items: center;
|
||||
position: relative;
|
||||
|
||||
background: var(--input-bg-color);
|
||||
border-radius: $br-8;
|
||||
padding: 0 var(--sp-s);
|
||||
outline-offset: #{$b-1};
|
||||
outline: $b-1 solid var(--input-outline-color);
|
||||
|
||||
&:hover {
|
||||
--input-bg-color: var(--color-background-quaternary);
|
||||
}
|
||||
|
||||
&:has(*:focus-visible) {
|
||||
--input-bg-color: var(--color-background-primary);
|
||||
--input-outline-color: var(--color-accent-primary);
|
||||
}
|
||||
|
||||
&:has(*:disabled) {
|
||||
--input-bg-color: var(--color-background-primary);
|
||||
--input-outline-color: var(--color-background-quaternary);
|
||||
}
|
||||
}
|
||||
|
||||
.input {
|
||||
margin: unset; // remove settings from global css
|
||||
padding: 0;
|
||||
appearance: none;
|
||||
margin-inline-start: var(--sp-xxs);
|
||||
height: $sz-32;
|
||||
border: none;
|
||||
background: none;
|
||||
|
||||
@include use-typography("body-small");
|
||||
color: var(--input-fg-color);
|
||||
|
||||
&:focus-visible {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
&::selection {
|
||||
background: var(--color-accent-primary-muted);
|
||||
}
|
||||
|
||||
&::placeholder {
|
||||
--input-fg-color: var(--color-foreground-secondary);
|
||||
}
|
||||
}
|
||||
|
||||
.icon {
|
||||
color: var(--color-foreground-secondary);
|
||||
}
|
47
frontend/src/app/main/ui/ds/forms/input.stories.jsx
Normal file
47
frontend/src/app/main/ui/ds/forms/input.stories.jsx
Normal file
|
@ -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
|
||||
|
||||
import * as React from "react";
|
||||
import Components from "@target/components";
|
||||
|
||||
const { Input } = Components;
|
||||
const { icons } = Components.meta;
|
||||
|
||||
export default {
|
||||
title: "Forms/Input",
|
||||
component: Components.Input,
|
||||
argTypes: {
|
||||
icon: {
|
||||
options: icons,
|
||||
control: { type: "select" },
|
||||
},
|
||||
value: {
|
||||
control: { type: "text" },
|
||||
},
|
||||
disabled: { control: "boolean" },
|
||||
},
|
||||
args: {
|
||||
disabled: false,
|
||||
value: "Lorem ipsum",
|
||||
},
|
||||
render: ({ ...args }) => <Input {...args} />,
|
||||
};
|
||||
|
||||
export const Default = {};
|
||||
|
||||
export const WithIcon = {
|
||||
args: {
|
||||
icon: "effects",
|
||||
},
|
||||
};
|
||||
|
||||
export const WithPlaceholder = {
|
||||
args: {
|
||||
icon: "effects",
|
||||
value: undefined,
|
||||
placeholder: "Mixed",
|
||||
},
|
||||
};
|
Loading…
Add table
Reference in a new issue