mirror of
https://github.com/penpot/penpot.git
synced 2025-05-25 18:16:10 +02:00
✨ Add composition and slots documentation to storybook
This commit is contained in:
parent
556a68a78f
commit
066b252522
6 changed files with 118 additions and 12 deletions
|
@ -12,6 +12,9 @@
|
|||
[app.main.ui.ds.controls.combobox :refer [combobox*]]
|
||||
[app.main.ui.ds.controls.input :refer [input*]]
|
||||
[app.main.ui.ds.controls.select :refer [select*]]
|
||||
[app.main.ui.ds.controls.utilities.hint-message :refer [hint-message*]]
|
||||
[app.main.ui.ds.controls.utilities.input-field :refer [input-field*]]
|
||||
[app.main.ui.ds.controls.utilities.label :refer [label*]]
|
||||
[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]]
|
||||
|
@ -49,6 +52,9 @@
|
|||
:Icon icon*
|
||||
:IconButton icon-button*
|
||||
:Input input*
|
||||
:Label label*
|
||||
:InputField input-field*
|
||||
:HintMessage hint-message*
|
||||
:InputWithMeta input-with-meta*
|
||||
:EmptyPlaceholder empty-placeholder*
|
||||
:Loader loader*
|
||||
|
|
|
@ -26,6 +26,31 @@ These are available in the `app.main.ds.foundations.assets.icon` namespace.
|
|||
[:> input* {:icon i/effects}]
|
||||
```
|
||||
|
||||
## Destructuring the component
|
||||
|
||||
The `input*` component is composed of `label*`, `input-field*`, and `hint-message*` components. If you only need some of these components or require them to be broken down, you can build them as a group of components.
|
||||
|
||||
```clj
|
||||
[:> label* {:for id :is-optional true} label]
|
||||
[:> input-field* {:id id}]
|
||||
[:> hint-message* {:id id :message message :type "warning}]
|
||||
```
|
||||
|
||||
<Canvas of={InputStories.Composable} />
|
||||
|
||||
#### `input-field*` slots
|
||||
|
||||
The `input-field*` offers two slots where developers can include external components as properties.
|
||||
|
||||
- **slot-start**: adds a component to the beginning of the input
|
||||
- **slot-end**: adds a component to the end of the input
|
||||
|
||||
```clj
|
||||
[:> input-field* {:id id :slot-start component-one :slot-end component-two}]
|
||||
```
|
||||
|
||||
<Canvas of={InputStories.Slots} />
|
||||
|
||||
## Usage guidelines (design)
|
||||
|
||||
### Where to use
|
||||
|
|
|
@ -8,6 +8,10 @@ import * as React from "react";
|
|||
import Components from "@target/components";
|
||||
|
||||
const { Input } = Components;
|
||||
const { Label } = Components;
|
||||
const { InputField } = Components;
|
||||
const { HintMessage } = Components;
|
||||
const { IconButton } = Components;
|
||||
const { icons } = Components.meta;
|
||||
|
||||
export default {
|
||||
|
@ -85,3 +89,77 @@ export const Seamless = {
|
|||
variant: "seamless",
|
||||
},
|
||||
};
|
||||
|
||||
export const Composable = {
|
||||
argTypes: {
|
||||
label: { control: "text" },
|
||||
labelArgs: { control: "object" },
|
||||
inputArgs: { control: "object" },
|
||||
hintArgs: { control: "object" },
|
||||
},
|
||||
args: {
|
||||
label: "Label",
|
||||
labelArgs: {
|
||||
htmlFor: "input",
|
||||
isOptional: false,
|
||||
},
|
||||
inputArgs: {
|
||||
id: "input",
|
||||
variant: "comfortable",
|
||||
type: "text",
|
||||
placeholder: "Placeholder",
|
||||
},
|
||||
hintArgs: {
|
||||
id: "input",
|
||||
message: "This is a hint text to help user.",
|
||||
type: "hint",
|
||||
},
|
||||
},
|
||||
render: ({ ...args }) => {
|
||||
return (
|
||||
<>
|
||||
<Label {...args.labelArgs}>{args.label}</Label>
|
||||
<InputField {...args.inputArgs} />
|
||||
<HintMessage {...args.hintArgs} />
|
||||
</>
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
export const Slots = {
|
||||
argTypes: {
|
||||
label: { control: "text" },
|
||||
labelArgs: { control: "object" },
|
||||
inputArgs: { control: "object" },
|
||||
hintArgs: { control: "object" },
|
||||
},
|
||||
args: {
|
||||
inputArgs: {
|
||||
id: "input",
|
||||
variant: "comfortable",
|
||||
type: "text",
|
||||
placeholder: "Placeholder",
|
||||
slotStart: (
|
||||
<IconButton
|
||||
icon="search"
|
||||
variant="ghost"
|
||||
aria-label="Slot Start component"
|
||||
/>
|
||||
),
|
||||
slotEnd: (
|
||||
<IconButton
|
||||
icon="status-tick"
|
||||
variant="ghost"
|
||||
aria-label="Slot End component"
|
||||
/>
|
||||
),
|
||||
},
|
||||
},
|
||||
render: ({ ...args }) => {
|
||||
return (
|
||||
<>
|
||||
<InputField {...args.inputArgs} />
|
||||
</>
|
||||
);
|
||||
},
|
||||
};
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
--input-bg-color: var(--color-background-tertiary);
|
||||
--input-fg-color: var(--color-foreground-primary);
|
||||
--input-icon-color: var(--color-foreground-secondary);
|
||||
--input-text-indent: 0;
|
||||
--input-outline-color: none;
|
||||
--input-height: #{$sz-32};
|
||||
--input-margin: unset;
|
||||
|
@ -81,7 +80,6 @@
|
|||
border: none;
|
||||
background: none;
|
||||
inline-size: 100%;
|
||||
text-indent: var(--input-text-indent, 0);
|
||||
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
|
|
|
@ -32,11 +32,10 @@
|
|||
(let [id (mf/use-id)
|
||||
input-ref (mf/use-ref)
|
||||
swatch
|
||||
(when color
|
||||
(mf/html [:> input-token-color-bullet*
|
||||
{:color color
|
||||
:class (stl/css :slot-start)
|
||||
:on-click display-colorpicker}]))
|
||||
:on-click display-colorpicker}])
|
||||
|
||||
props (mf/spread-props props {:id id
|
||||
:type "text"
|
||||
|
|
|
@ -238,7 +238,7 @@
|
|||
(let [create? (not (instance? ctob/Token token))
|
||||
token (or token {:type token-type})
|
||||
token-properties (dwta/get-token-properties token)
|
||||
color? (cft/color-token? token)
|
||||
is-color-token (cft/color-token? token)
|
||||
selected-set-tokens (mf/deref refs/workspace-selected-token-set-tokens)
|
||||
|
||||
active-theme-tokens (cond-> (mf/deref refs/workspace-active-theme-sets-tokens)
|
||||
|
@ -321,7 +321,7 @@
|
|||
(valid-name? @token-name-ref))
|
||||
|
||||
;; Value
|
||||
color* (mf/use-state (when color? (:value token)))
|
||||
color* (mf/use-state (when is-color-token (:value token)))
|
||||
color (deref color*)
|
||||
color-ramp-open* (mf/use-state false)
|
||||
color-ramp-open? (deref color-ramp-open*)
|
||||
|
@ -345,7 +345,7 @@
|
|||
|
||||
:else
|
||||
(:resolved-value token-or-err))]
|
||||
(when color? (reset! color* (if error? nil v)))
|
||||
(when is-color-token (reset! color* (if error? nil v)))
|
||||
(reset! token-resolve-result* v))))
|
||||
|
||||
on-update-value-debounced (use-debonced-resolve-callback token-name-ref token active-theme-tokens set-resolve-value)
|
||||
|
@ -354,7 +354,7 @@
|
|||
(fn [e]
|
||||
(let [value (dom/get-target-val e)
|
||||
;; Automatically add # for hex values
|
||||
value' (if (and color? (tinycolor/hex-without-hash-prefix? value))
|
||||
value' (if (and is-color-token (tinycolor/hex-without-hash-prefix? value))
|
||||
(let [hex (dm/str "#" value)]
|
||||
(dom/set-value! (mf/ref-val value-input-ref) hex)
|
||||
hex)
|
||||
|
@ -560,7 +560,7 @@
|
|||
:label (tr "workspace.tokens.token-value")
|
||||
:default-value (mf/ref-val value-ref)
|
||||
:ref value-input-ref
|
||||
:color color
|
||||
:color (when is-color-token color)
|
||||
:on-change on-update-value
|
||||
:error (not (nil? (:errors token-resolve-result)))
|
||||
:display-colorpicker on-display-colorpicker'
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue