mirror of
https://github.com/penpot/penpot.git
synced 2025-05-26 04:26:11 +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.combobox :refer [combobox*]]
|
||||||
[app.main.ui.ds.controls.input :refer [input*]]
|
[app.main.ui.ds.controls.input :refer [input*]]
|
||||||
[app.main.ui.ds.controls.select :refer [select*]]
|
[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.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]]
|
||||||
[app.main.ui.ds.foundations.typography :refer [typography-list]]
|
[app.main.ui.ds.foundations.typography :refer [typography-list]]
|
||||||
|
@ -49,6 +52,9 @@
|
||||||
:Icon icon*
|
:Icon icon*
|
||||||
:IconButton icon-button*
|
:IconButton icon-button*
|
||||||
:Input input*
|
:Input input*
|
||||||
|
:Label label*
|
||||||
|
:InputField input-field*
|
||||||
|
:HintMessage hint-message*
|
||||||
:InputWithMeta input-with-meta*
|
:InputWithMeta input-with-meta*
|
||||||
:EmptyPlaceholder empty-placeholder*
|
:EmptyPlaceholder empty-placeholder*
|
||||||
:Loader loader*
|
:Loader loader*
|
||||||
|
|
|
@ -26,6 +26,31 @@ These are available in the `app.main.ds.foundations.assets.icon` namespace.
|
||||||
[:> input* {:icon i/effects}]
|
[:> 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)
|
## Usage guidelines (design)
|
||||||
|
|
||||||
### Where to use
|
### Where to use
|
||||||
|
|
|
@ -8,6 +8,10 @@ import * as React from "react";
|
||||||
import Components from "@target/components";
|
import Components from "@target/components";
|
||||||
|
|
||||||
const { Input } = Components;
|
const { Input } = Components;
|
||||||
|
const { Label } = Components;
|
||||||
|
const { InputField } = Components;
|
||||||
|
const { HintMessage } = Components;
|
||||||
|
const { IconButton } = Components;
|
||||||
const { icons } = Components.meta;
|
const { icons } = Components.meta;
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -85,3 +89,77 @@ export const Seamless = {
|
||||||
variant: "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-bg-color: var(--color-background-tertiary);
|
||||||
--input-fg-color: var(--color-foreground-primary);
|
--input-fg-color: var(--color-foreground-primary);
|
||||||
--input-icon-color: var(--color-foreground-secondary);
|
--input-icon-color: var(--color-foreground-secondary);
|
||||||
--input-text-indent: 0;
|
|
||||||
--input-outline-color: none;
|
--input-outline-color: none;
|
||||||
--input-height: #{$sz-32};
|
--input-height: #{$sz-32};
|
||||||
--input-margin: unset;
|
--input-margin: unset;
|
||||||
|
@ -81,7 +80,6 @@
|
||||||
border: none;
|
border: none;
|
||||||
background: none;
|
background: none;
|
||||||
inline-size: 100%;
|
inline-size: 100%;
|
||||||
text-indent: var(--input-text-indent, 0);
|
|
||||||
|
|
||||||
font-family: inherit;
|
font-family: inherit;
|
||||||
font-size: inherit;
|
font-size: inherit;
|
||||||
|
|
|
@ -32,11 +32,10 @@
|
||||||
(let [id (mf/use-id)
|
(let [id (mf/use-id)
|
||||||
input-ref (mf/use-ref)
|
input-ref (mf/use-ref)
|
||||||
swatch
|
swatch
|
||||||
(when color
|
(mf/html [:> input-token-color-bullet*
|
||||||
(mf/html [:> input-token-color-bullet*
|
{:color color
|
||||||
{:color color
|
:class (stl/css :slot-start)
|
||||||
:class (stl/css :slot-start)
|
:on-click display-colorpicker}])
|
||||||
:on-click display-colorpicker}]))
|
|
||||||
|
|
||||||
props (mf/spread-props props {:id id
|
props (mf/spread-props props {:id id
|
||||||
:type "text"
|
:type "text"
|
||||||
|
|
|
@ -238,7 +238,7 @@
|
||||||
(let [create? (not (instance? ctob/Token token))
|
(let [create? (not (instance? ctob/Token token))
|
||||||
token (or token {:type token-type})
|
token (or token {:type token-type})
|
||||||
token-properties (dwta/get-token-properties token)
|
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)
|
selected-set-tokens (mf/deref refs/workspace-selected-token-set-tokens)
|
||||||
|
|
||||||
active-theme-tokens (cond-> (mf/deref refs/workspace-active-theme-sets-tokens)
|
active-theme-tokens (cond-> (mf/deref refs/workspace-active-theme-sets-tokens)
|
||||||
|
@ -321,7 +321,7 @@
|
||||||
(valid-name? @token-name-ref))
|
(valid-name? @token-name-ref))
|
||||||
|
|
||||||
;; Value
|
;; Value
|
||||||
color* (mf/use-state (when color? (:value token)))
|
color* (mf/use-state (when is-color-token (:value token)))
|
||||||
color (deref color*)
|
color (deref color*)
|
||||||
color-ramp-open* (mf/use-state false)
|
color-ramp-open* (mf/use-state false)
|
||||||
color-ramp-open? (deref color-ramp-open*)
|
color-ramp-open? (deref color-ramp-open*)
|
||||||
|
@ -345,7 +345,7 @@
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(:resolved-value token-or-err))]
|
(: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))))
|
(reset! token-resolve-result* v))))
|
||||||
|
|
||||||
on-update-value-debounced (use-debonced-resolve-callback token-name-ref token active-theme-tokens set-resolve-value)
|
on-update-value-debounced (use-debonced-resolve-callback token-name-ref token active-theme-tokens set-resolve-value)
|
||||||
|
@ -354,7 +354,7 @@
|
||||||
(fn [e]
|
(fn [e]
|
||||||
(let [value (dom/get-target-val e)
|
(let [value (dom/get-target-val e)
|
||||||
;; Automatically add # for hex values
|
;; 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)]
|
(let [hex (dm/str "#" value)]
|
||||||
(dom/set-value! (mf/ref-val value-input-ref) hex)
|
(dom/set-value! (mf/ref-val value-input-ref) hex)
|
||||||
hex)
|
hex)
|
||||||
|
@ -560,7 +560,7 @@
|
||||||
:label (tr "workspace.tokens.token-value")
|
:label (tr "workspace.tokens.token-value")
|
||||||
:default-value (mf/ref-val value-ref)
|
:default-value (mf/ref-val value-ref)
|
||||||
:ref value-input-ref
|
:ref value-input-ref
|
||||||
:color color
|
:color (when is-color-token color)
|
||||||
:on-change on-update-value
|
:on-change on-update-value
|
||||||
:error (not (nil? (:errors token-resolve-result)))
|
:error (not (nil? (:errors token-resolve-result)))
|
||||||
:display-colorpicker on-display-colorpicker'
|
:display-colorpicker on-display-colorpicker'
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue