This repository has been archived by the owner on Jun 5, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Controls (checkbox, radio, toggle) (#129)
* move stateClass to src root * impl basic checkbox using radix-ui/react-checkbox * impl basic radio group using radix-ui/react-radio-group - refactor css * impl basic toggle using radix-ui/switch * add more specs to storybook and make it spec compliant * Add bindings * version packages
- Loading branch information
Jaeho Lee
authored
Feb 21, 2023
1 parent
0ed122c
commit e1254d4
Showing
17 changed files
with
776 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
--- | ||
"@greenlabs/formula-components": patch | ||
"@greenlabs/rescript-formula-components": patch | ||
--- | ||
|
||
Controls (checkbox, radio, toggle) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
module Checkbox = { | ||
@module("@greenlabs/formula-components") @react.component | ||
external make: ( | ||
~id: string=?, | ||
~className: string=?, | ||
~props: {..}=?, | ||
~name: string=?, | ||
~onChange: ReactEvent.Form.t => unit=?, | ||
~onFocus: ReactEvent.Focus.t => unit=?, | ||
~onBlur: ReactEvent.Focus.t => unit=?, | ||
~onInput: ReactEvent.Form.t => unit=?, | ||
~onKeyDown: ReactEvent.Keyboard.t => unit=?, | ||
~onKeyUp: ReactEvent.Keyboard.t => unit=?, | ||
~asChild: bool=?, | ||
~defaultChecked: bool=?, | ||
~checked: bool=?, | ||
~onCheckedChange: bool => unit=?, | ||
~disabled: bool=?, | ||
~required: bool=?, | ||
~value: [#on]=?, // "on" | ||
~label: string=?, | ||
~autoFocus: bool=?, | ||
// TODO: data-state, data-disabled | ||
~ref: ReactDOM.Ref.t=?, | ||
) => React.element = "Checkbox" | ||
} | ||
|
||
module Toggle = { | ||
@module("@greenlabs/formula-components") @react.component | ||
external make: ( | ||
~id: string=?, | ||
~className: string=?, | ||
~props: {..}=?, | ||
~name: string=?, | ||
~onChange: ReactEvent.Form.t => unit=?, | ||
~onFocus: ReactEvent.Focus.t => unit=?, | ||
~onBlur: ReactEvent.Focus.t => unit=?, | ||
~onInput: ReactEvent.Form.t => unit=?, | ||
~onKeyDown: ReactEvent.Keyboard.t => unit=?, | ||
~onKeyUp: ReactEvent.Keyboard.t => unit=?, | ||
~asChild: bool=?, | ||
~forceMount: bool=?, | ||
~defaultChecked: bool=?, | ||
~checked: bool=?, | ||
~onCheckedChange: bool => unit=?, | ||
~disabled: bool=?, | ||
~required: bool=?, | ||
~value: [#on]=?, // "on" | ||
~label: string=?, | ||
~autoFocus: bool=?, | ||
// TODO: data-state, data-disabled | ||
~ref: ReactDOM.Ref.t=?, | ||
) => React.element = "Toggle" | ||
} | ||
|
||
module RadioGroup = { | ||
@module("@greenlabs/formula-components") @react.component | ||
external make: ( | ||
~id: string=?, | ||
~className: string=?, | ||
~props: {..}=?, | ||
~name: string=?, | ||
~onChange: ReactEvent.Form.t => unit=?, | ||
~onFocus: ReactEvent.Focus.t => unit=?, | ||
~onBlur: ReactEvent.Focus.t => unit=?, | ||
~onInput: ReactEvent.Form.t => unit=?, | ||
~onKeyDown: ReactEvent.Keyboard.t => unit=?, | ||
~onKeyUp: ReactEvent.Keyboard.t => unit=?, | ||
~asChild: bool=?, | ||
~defaultValue: string=?, | ||
~value: string=?, | ||
~onValueChange: string => unit=?, | ||
~disabled: bool=?, | ||
~required: bool=?, | ||
~orientation: [#horizontal | #vertical]=?, | ||
~dir: [#ltr | #rtl]=?, | ||
~loop: bool=?, | ||
~children: React.element, | ||
// TODO: data-state, data-disabled | ||
~ref: ReactDOM.Ref.t=?, | ||
) => React.element = "RadioGroup" | ||
} | ||
|
||
module RadioItem = { | ||
@module("@greenlabs/formula-components") @react.component | ||
external make: ( | ||
~id: string=?, | ||
~className: string=?, | ||
~props: {..}=?, | ||
~onChange: ReactEvent.Form.t => unit=?, | ||
~onFocus: ReactEvent.Focus.t => unit=?, | ||
~onBlur: ReactEvent.Focus.t => unit=?, | ||
~onInput: ReactEvent.Form.t => unit=?, | ||
~onKeyDown: ReactEvent.Keyboard.t => unit=?, | ||
~onKeyUp: ReactEvent.Keyboard.t => unit=?, | ||
~asChild: bool=?, | ||
~value: string=?, | ||
~disabled: bool=?, | ||
~required: bool=?, | ||
~label: string=?, | ||
~autoFocus: bool=?, | ||
// TODO: data-disabled | ||
~ref: ReactDOM.Ref.t=?, | ||
) => React.element = "RadioItem" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import * as React from "react" | ||
import type { Meta } from "@storybook/react" | ||
import type { ComponentStory } from "@storybook/react" | ||
|
||
import { Checkbox } from "./Checkbox" | ||
import { createDisabledArgs } from "../utils/storybook" | ||
import { ThemeScope } from "../theme" | ||
|
||
const Template: ComponentStory<typeof Checkbox> = (args) => { | ||
return ( | ||
<ThemeScope> | ||
<form style={{ margin: "20px 10px" }}> | ||
<Checkbox {...args} /> | ||
</form> | ||
<form style={{ margin: "20px 10px" }}> | ||
<Checkbox label="disabled=true" disabled /> | ||
</form> | ||
<form style={{ margin: "20px 10px" }}> | ||
<Checkbox label="disabled=true, checked" disabled defaultChecked /> | ||
</form> | ||
</ThemeScope> | ||
) | ||
} | ||
|
||
const textControl = { | ||
defaultValue: "", | ||
control: { type: "text" }, | ||
} | ||
|
||
const commonDisabled = createDisabledArgs([ | ||
"props", | ||
"className", | ||
"onChange", | ||
"onFocus", | ||
"name", | ||
"onBlur", | ||
"onKeyDown", | ||
"onKeyUp", | ||
"form", | ||
"id", | ||
"autoFocus", | ||
]) | ||
|
||
const controls = { | ||
label: textControl, | ||
} | ||
|
||
export const Overview = Template.bind({}) | ||
Overview.args = {} | ||
Overview.argTypes = { | ||
...commonDisabled, | ||
...controls, | ||
} | ||
|
||
export default { | ||
title: "Formula/Controls/Checkbox", | ||
component: Checkbox, | ||
} as Meta<typeof Checkbox> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import * as React from "react" | ||
import { Text } from "../Text/Text" | ||
import * as IconComponents from "../Icon/generated" | ||
import * as RadixUICheckbox from "@radix-ui/react-checkbox" | ||
import type { CheckboxProps as RadixUICheckboxProps } from "@radix-ui/react-checkbox" | ||
import { checkboxStyles } from "./styles.css" | ||
import { stateClass } from "./common" | ||
|
||
type RefType = React.Ref<HTMLButtonElement> | ||
|
||
interface CheckboxProps extends RadixUICheckboxProps { | ||
props?: {} | ||
label?: string | ||
} | ||
|
||
export const Checkbox = React.forwardRef<HTMLButtonElement, CheckboxProps>( | ||
( | ||
{ id, className = "", props = {}, disabled, label, ...additionalProps }, | ||
forwardedRef | ||
) => { | ||
const inputRef: RefType = React.useRef(null) | ||
|
||
React.useImperativeHandle( | ||
forwardedRef, | ||
() => inputRef.current as HTMLButtonElement | ||
) | ||
|
||
const innerId = React.useId() | ||
const usedId = id ?? innerId | ||
|
||
return ( | ||
<div | ||
className={`${className} ${stateClass({ | ||
disabled, | ||
})} ${checkboxStyles.container}`} | ||
> | ||
<RadixUICheckbox.Root | ||
ref={inputRef} | ||
className={checkboxStyles.button} | ||
id={usedId} | ||
disabled={disabled} | ||
{...additionalProps} | ||
{...props} | ||
> | ||
<span className={checkboxStyles.container}> | ||
<IconComponents.CheckLineBold | ||
className={checkboxStyles.icon} | ||
size="sm" | ||
/> | ||
</span> | ||
</RadixUICheckbox.Root> | ||
{label ? ( | ||
<Text.Body | ||
tag="label" | ||
size="md" | ||
props={{ htmlFor: usedId }} | ||
className={checkboxStyles.label} | ||
> | ||
{label} | ||
</Text.Body> | ||
) : null} | ||
</div> | ||
) | ||
} | ||
) | ||
Checkbox.displayName = "Checkbox" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
import * as React from "react" | ||
import type { Meta } from "@storybook/react" | ||
import type { ComponentStory } from "@storybook/react" | ||
|
||
import { RadioItem, RadioGroup } from "./Radio" | ||
import { createDisabledArgs } from "../utils/storybook" | ||
import { ThemeScope } from "../theme" | ||
|
||
const Template: ComponentStory<typeof RadioGroup> = (args) => { | ||
return ( | ||
<ThemeScope> | ||
<form style={{ margin: "20px 10px" }}> | ||
<label>plain radio group</label> | ||
<RadioGroup style={{ display: "flex", gap: "10px" }} {...args}> | ||
<RadioItem value="a" label="a" /> | ||
<RadioItem value="b" label="b" /> | ||
<RadioItem value="c" label="c" /> | ||
</RadioGroup> | ||
</form> | ||
<form style={{ margin: "20px 10px" }}> | ||
<label>default selected</label> | ||
<RadioGroup style={{ display: "flex", gap: "10px" }} defaultValue="a"> | ||
<RadioItem value="a" label="a" /> | ||
<RadioItem value="b" label="b" /> | ||
</RadioGroup> | ||
</form> | ||
<form style={{ margin: "20px 10px" }}> | ||
<label>disabled radio</label> | ||
<RadioGroup style={{ display: "flex", gap: "10px" }} defaultValue="a"> | ||
<RadioItem value="a" label="a" disabled /> | ||
<RadioItem value="b" label="b" disabled /> | ||
</RadioGroup> | ||
</form> | ||
</ThemeScope> | ||
) | ||
} | ||
|
||
const textControl = { | ||
defaultValue: "", | ||
control: { type: "text" }, | ||
} | ||
|
||
const commonDisabled = createDisabledArgs([ | ||
"props", | ||
"className", | ||
"onChange", | ||
"onFocus", | ||
"name", | ||
"onBlur", | ||
"onKeyDown", | ||
"onKeyUp", | ||
"form", | ||
"id", | ||
"autoFocus", | ||
]) | ||
|
||
const controls = { | ||
label: textControl, | ||
} | ||
|
||
export const Overview = Template.bind({}) | ||
Overview.args = {} | ||
Overview.argTypes = { | ||
...commonDisabled, | ||
...controls, | ||
} | ||
|
||
export default { | ||
title: "Formula/Controls/Radio", | ||
component: RadioItem, | ||
} as Meta<typeof RadioItem> |
Oops, something went wrong.