diff --git a/components/ComponentLinks.tsx b/components/ComponentLinks.tsx new file mode 100644 index 0000000..355516b --- /dev/null +++ b/components/ComponentLinks.tsx @@ -0,0 +1,67 @@ +import { SiGithub, SiStorybook } from "react-icons/si"; +import { Link } from "@renderlesskit/react"; +import { Button, ButtonGroup } from "@renderlesskit/react-tailwind"; + +type ComponentLinkProps = { + github: string; + story: string; + theme: string; +}; + +const ComponentLinks: React.FC = ({ + github, + story, + theme, +}) => { + const githubBase = + "https://github.com/timelessco/renderlesskit-react-tailwind/tree/main/src/"; + const themeBase = + "https://github.com/timelessco/renderlesskit-react-tailwind/tree/main/src/theme/defaultTheme/"; + const storybookBase = + "https://renderlesskit-react-tailwind.vercel.app/?path=/story/"; + + return ( + + {github && ( + + )} + + {theme && ( + + )} + + {story && ( + + )} + + ); +}; + +export default ComponentLinks; diff --git a/components/PropsTable.tsx b/components/PropsTable.tsx new file mode 100644 index 0000000..5efbc06 --- /dev/null +++ b/components/PropsTable.tsx @@ -0,0 +1,154 @@ +import React from "react"; +import { + Popover as ReakitPopover, + PopoverArrow, + PopoverDisclosure, + usePopoverState, +} from "reakit/Popover"; +import { + Box, + Button, + InfoCircleIcon, + useTheme, +} from "@renderlesskit/react-tailwind"; +import { get } from "lodash"; + +import { RegionTable } from "./RegionTable"; + +type PropDef = { + name: string; + themeKey?: string; + required?: boolean; + default?: string | boolean; + type: string; + typeSimple: string; + description?: string; +}; + +type PopoverTypes = { + children: React.ReactNode; + content: React.ReactNode; + label?: string; +}; +const Popover: React.FC = ({ children, content, label }) => { + const popover = usePopoverState({ placement: "top" }); + return ( + <> + + {children} + + + + {content} + + + ); +}; + +type PropsTableProps = { + data: PropDef[]; + "aria-label"?: string; + "aria-labelledby"?: string; +}; + +const PropsTable: React.FC = ({ + data, + "aria-label": ariaLabel, + "aria-labelledby": ariaLabelledBy, +}) => { + const theme = useTheme(); + const hasAriaLabel = !!(ariaLabel || ariaLabelledBy); + + const tdStyles = "border-0 border-b-0 border-gray-500"; + const thStyles = `px-2 py-2 text-gray-800 ${tdStyles}`; + const typeStyles = "bg-blue-100 text-blue-800 px-2 py-1"; + + return ( + + + + +

Prop

+
+ +

Type

+
+ +

Default

+
+ + + + {data.map( + ( + { + name, + themeKey, + type, + typeSimple, + required, + default: defaultValue, + description, + }, + i, + ) => ( + + + + {name} + {required ? "*" : null} + + {description && ( + + + + )} + + + + {themeKey ? "union" : Boolean(typeSimple) ? typeSimple : type} + + {!!(typeSimple || themeKey) && ( + + {themeKey + ? Object.keys(get(theme, themeKey)).join(" | ") + : type} + + } + > + + + )} + + + {!!defaultValue ? ( + {defaultValue} + ) : ( + "-" + )} + + + ), + )} + +
+ ); +}; + +export default PropsTable; diff --git a/components/RegionTable.tsx b/components/RegionTable.tsx new file mode 100644 index 0000000..29441c4 --- /dev/null +++ b/components/RegionTable.tsx @@ -0,0 +1,21 @@ +import React from "react"; +import { Box, BoxProps } from "@renderlesskit/react-tailwind"; + +export function RegionTable({ + "aria-label": ariaLabel, + "aria-labelledby": ariaLabelledBy, + ...props +}: BoxProps) { + return ( + + + + ); +} diff --git a/next.config.js b/next.config.js new file mode 100644 index 0000000..52e5ad5 --- /dev/null +++ b/next.config.js @@ -0,0 +1,8 @@ +const withNextra = require("nextra")({ + theme: "nextra-theme-docs", + themeConfig: "./theme.config.js", + unstable_stork: false, + unstable_staticImage: true, +}); + +module.exports = withNextra({}); diff --git a/package.json b/package.json index e403548..4cb7004 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "next-react-app", + "name": "renderlesskit-tailwind-docs", "version": "1.0.0", "private": true, "description": "Personal Next React App", @@ -23,7 +23,7 @@ "scripts": { "postinstall": "husky install", "dev": "next dev", - "build": "next build", + "build": "STORK_PATH=$(pwd)/bin/stork.bin next build", "start": "next start", "test": "jest --watch --watchAll=false", "test:ci": "jest --ci", @@ -63,9 +63,13 @@ ] }, "dependencies": { + "@renderlesskit/react-tailwind": "0.0.1-alpha.33", "next": "12.0.7", + "nextra": "2.0.0-beta.5", + "nextra-theme-docs": "2.0.0-beta.5", "react": "17.0.2", - "react-dom": "17.0.2" + "react-dom": "17.0.2", + "lodash": "4.17.21" }, "devDependencies": { "@babel/core": "7.16.5", @@ -78,6 +82,7 @@ "@testing-library/react": "12.1.2", "@testing-library/user-event": "13.5.0", "@types/jest": "27.0.3", + "@types/lodash": "4.14.178", "@types/node": "17.0.5", "@types/react": "17.0.38", "@types/react-dom": "17.0.11", @@ -95,6 +100,7 @@ "lint-staged": "12.1.4", "postcss": "8.4.5", "prettier": "2.5.1", + "react-icons": "4.3.1", "release-it": "14.11.8", "sort-package-json": "1.53.1", "tailwindcss": "3.0.8", diff --git a/pages/_app.tsx b/pages/_app.tsx index fd476ee..9e9ae98 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -1,7 +1,13 @@ +import { RenderlesskitProvider } from "@renderlesskit/react-tailwind"; import type { AppProps } from "next/app"; import "@/styles/global.css"; +import "nextra-theme-docs/style.css"; export default function MyApp({ Component, pageProps }: AppProps) { - return ; + return ( + + + + ); } diff --git a/pages/_document.tsx b/pages/_document.tsx new file mode 100644 index 0000000..2f156a8 --- /dev/null +++ b/pages/_document.tsx @@ -0,0 +1,19 @@ +import Document, { Head, Html, Main, NextScript } from "next/document"; + +class MyDocument extends Document { + render() { + return ( + + + + + +
+ + + + ); + } +} + +export default MyDocument; diff --git a/pages/docs/components/feedback/circular-progress.mdx b/pages/docs/components/feedback/circular-progress.mdx new file mode 100644 index 0000000..3a002fc --- /dev/null +++ b/pages/docs/components/feedback/circular-progress.mdx @@ -0,0 +1,132 @@ +import PropsTable from "@/components/PropsTable"; +import ComponentLinks from "@/components/ComponentLinks"; + +# CircularProgress + +The CircularProgress component is used to indicate the progress for determinate +and indeterminate processes. + + + +## Imports + +```js +import { + CircularProgress, + CircularProgressBar, + CircularProgressWrapper, +} from "@renderlesskit/react-tailwind"; +``` + +- **CircularProgress** - main progress component +- **CircularProgressBar** - progress bar component +- **CircularProgressWrapper** - progress track component + +## Usage + +```jsx live + +``` + +## Min max values + +```jsx live + +``` + +## Indeterminate progress + +By setting the value prop to null, progress' state becomes indeterminate + +```jsx live + +``` + +## CircularProgress sizes + +CircularProgress comes with 3 sizes `sm` `md` & `lg` + +```jsx live +
+ + + +
+``` + +## Customizing CircularProgress + +To customize the appearance of the CircularProgress component we can simply pass +down children components (CircularProgressWrapper, CircularProgressBar) for more +control. + +```jsx live noInline +const CustomProgress = () => { + const [value, setValue] = React.useState(10); + + return ( + <> + + + + + + +
+ + + + + + ); +}; + +export default CustomProgress; +``` + +## API Reference + + + +### CircularProgressBar + + diff --git a/pages/docs/components/feedback/meta.json b/pages/docs/components/feedback/meta.json new file mode 100644 index 0000000..81fcfbf --- /dev/null +++ b/pages/docs/components/feedback/meta.json @@ -0,0 +1,5 @@ +{ + "progress": "Progress", + "circular-progress": "CircularProgress", + "spinner": "Spinner" +} diff --git a/pages/docs/components/feedback/progress.mdx b/pages/docs/components/feedback/progress.mdx new file mode 100644 index 0000000..eeedadb --- /dev/null +++ b/pages/docs/components/feedback/progress.mdx @@ -0,0 +1,107 @@ +import PropsTable from "@/components/PropsTable"; +import ComponentLinks from "@/components/ComponentLinks"; + +# Progress + +Progress is used to display the progress status for a task that takes a long +time or consists of several steps. + + + +## Imports + +```js +import { + Progress, + ProgressBar, + ProgressTrack, +} from "@renderlesskit/react-tailwind"; +``` + +- **Progress** - main progress component +- **ProgressBar** - progress bar component +- **ProgressTrack** - progress track component + +## Usage + +```jsx live + +``` + +## Min max values + +```jsx live + +``` + +## Indeterminate progress + +By setting the value prop to null, progress' state becomes indeterminate + +```jsx live + +``` + +## Progress sizes + +Progress comes with 4 sizes `sm` `md` `lg` & `xl` + +```jsx live +
+ + + + +
+``` + +## Customizing Progress + +To customize the appearance of the Progress component we can simply pass down +children components (ProgressTrack, ProgressBar) for more control. + +```jsx live noInline +const CustomProgress = () => { + const [value, setValue] = React.useState(10); + + return ( + <> + + + + + + + + + + + + ); +}; + +export default CustomProgress; +``` + +## API Reference + + diff --git a/pages/docs/components/feedback/spinner.mdx b/pages/docs/components/feedback/spinner.mdx new file mode 100644 index 0000000..facba08 --- /dev/null +++ b/pages/docs/components/feedback/spinner.mdx @@ -0,0 +1,65 @@ +import PropsTable from "@/components/PropsTable"; +import ComponentLinks from "@/components/ComponentLinks"; + +# Spinner + +Spinners provide a visual cue that an action is either processing, awaiting a +course of change or a result. + + + +## Imports + +```js +import { Spinner } from "@renderlesskit/react-tailwind"; +``` + +## Usage + +```jsx live + +``` + +## Spinner sizes + +Spinner comes with 5 sizes `xs` `sm` `md` `lg` & `xl` + +```jsx live +
+ + + + + +
+``` + +## Show stroke + +To show the subtle stroke around the spinner we can use the `stroke` which +accepts `visible` or `transparent` values + +```jsx live + +``` + +## API Reference + + diff --git a/pages/docs/components/forms/checkbox.mdx b/pages/docs/components/forms/checkbox.mdx new file mode 100644 index 0000000..737718f --- /dev/null +++ b/pages/docs/components/forms/checkbox.mdx @@ -0,0 +1,188 @@ +import Callout from "nextra-theme-docs/callout"; +import PropsTable from "@/components/PropsTable"; +import ComponentLinks from "@/components/ComponentLinks"; + +# Checkbox + +The Checkbox is used in forms when a user needs to select multiple values from +several options. Checkbox composes +[reakit's checkbox](https://reakit.io/docs/checkbox/) component. + + + +## Imports + +```js +import { + Checkbox, + CheckboxInput, + CheckboxLabel, + CheckboxIcon, + CheckboxText, +} from "@renderlesskit/react-tailwind"; +``` + +- **Checkbox** - main checkbox component +- **CheckboxInput** - checkbox's input component +- **CheckboxLabel** - label for checkbox + - **CheckboxIcon** - renders checkbox's icon + - **FormHelperText** - text for the checkbox label + +## Usage + +All the form elements of renderlesskit are compatible with `FormField`, thus you +can directly use any of the elements inside of FormField and it will +automatically handle all the accessibility & props. + +Basic usage. + +## Checkbox sizes + +Checkbox comes with 3 sizes `sm` `md` `lg` + +```jsx live +Label text +``` + +## Controlled Checkbox + +```jsx noInline live +const ControlledCheckbox = () => { + const [state, onStateChange] = React.useState(false); + + return ( + <> + + Checkbox + +
{`Checked: ${state}`}
+ + ); +}; + +export default ControlledCheckbox; +``` + +## Checkbox Groups + +We can keep track of multiple checkbox states and use them as a group. + +```jsx noInline live +const GroupedCheckbox = () => { + const [state, onStateChange] = React.useState([]); + + return ( + <> +
Choices: {state.join(", ")}
+
+ + Apple + + + Orange + + + Mango + +
+ + ); +}; + +export default GroupedCheckbox; +``` + +## Indeterminate checkboxes + +```jsx noInline live +const IndeterminateExample = () => { + const [checkedItems, setCheckedItems] = React.useState([false, false]); + + const allChecked = checkedItems.every(Boolean); + const isIndeterminate = checkedItems.some(Boolean) && !allChecked; + + return ( + <> + setCheckedItems([value, value])} + > + Parent Checkbox + +
+ setCheckedItems([value, checkedItems[1]])} + > + Child Checkbox 1 + + setCheckedItems([checkedItems[0], value])} + > + Child Checkbox 2 + +
+ + ); +}; + +export default IndeterminateExample; +``` + + + Checkout our storybook source code to [see more + examples](https://github.com/timelessco/renderlesskit-react-tailwind/blob/main/src/checkbox/stories/Checkbox.stories.tsx#L136) + + +## Customizing Checkboxes + +To customize the checkbox we can use render props api to access the internal +state of the checkbox & change it's appearance as we like with composing +`CheckboxInput`, `CheckboxLabel` etc etc components like so: + +```jsx noInline live +const CustomCheckbox = () => { + return ( + + {({ state }) => ( + + + + {state ? "😃" : "😢"} + + Checkbox + + )} + + ); +}; + +export default CustomCheckbox; +``` + +## Integrations + +// TBD + +## API Reference + +### Checkbox + +Checkbox composes reakit's checkbox component + + void", + }, + ]} +/> diff --git a/pages/docs/components/forms/form-field.mdx b/pages/docs/components/forms/form-field.mdx new file mode 100644 index 0000000..65db3e7 --- /dev/null +++ b/pages/docs/components/forms/form-field.mdx @@ -0,0 +1,276 @@ +import PropsTable from "@/components/PropsTable"; +import ComponentLinks from "@/components/ComponentLinks"; +import Callout from "nextra-theme-docs/callout"; +import outdent from "outdent"; + +# FormField + +FormField provides a cohesive way render form element's states such as +isInvalid, isDisabled, and isRequired. + + + +## Imports + +```js +import { + FormField, + FormLabel, + FormErrorText, + FormHelperText, + FormLabelValue, + FormRequiredText, + useFormControl, +} from "@renderlesskit/react-tailwind"; +``` + +- **FormField** - main wrapper context +- **FormLabel** - field's label +- **FormLabelValue** - renders form element's value +- **FormHelperText** - renders helper text +- **FormErrorText** - renders error text when FormField has `isInvalid` set to + true +- **FormRequiredText** - renders when FormField has `isRequired` set to true +- **useFormControl** - context hook to glue external form elements with + FormField's context. + +## Usage + +All the form elements of renderlesskit are compatible with `FormField`, thus you +can directly use any of the elements inside of FormField and it will +automatically handle all the accessibility & props. + +Basic usage. + +```jsx live + + Enter email address + + Hint text + Email is invalid + +``` + +## Required form fields + +By passing the `isRequired` prop, the Input field will have `aria-required` set +to true, and the `FormRequiredText` will be shown. + +```jsx live + + + Enter email address + Required + + + Hint text + +``` + +## Usage with Radios + +```jsx live + + Favorite Browser + + Chrome + FireFox + Safari + + Select which browser you use. + +``` + +## Usage with Switch + +```jsx live + + Enable darkmode? + + + + Switch darkmode + + +``` + +## Usage with slider + +Let's take a look at how we can use the `Slider` component with FormField: + +First thing you might notice is that we can access the internal state of the +`FormField` via render props. And we are also utilizing the `FormLabelValue` to +render the current value of the Slider. + +```jsx noInline live +const SliderExample = () => { + const [value, setValue] = React.useState(0); + + return ( + 60}> + {({ isInvalid }) => ( + <> + + Slider value + {value} + + setValue(v[0])} /> + {!isInvalid && Hint text} + Value is above 60 + + )} + + ); +}; + +export default SliderExample; +``` + +## Using custom inputs + +All the form elements of renderlesskit are compatible with `FromField` but you +might want to use your own input element or any other external input elements. +For these situations we provide two ways to bind your custom input elements to +FormField. + +### Method #1 (render props) + +Via the render props API, we expose the a variable called `inputProps` which +holds all the aria related props which can be directly spread into the input. + +```jsx live + + {({ inputProps }) => ( + <> + Custom input example + + Hint text + + )} + +``` + +### Method #2 (useFormControl hook) + +`useFormControl` provides a much cleaner way to bind a custom input to +FormField, all the renderlesskit form elements internally uses this hook too. + +```jsx noInline live +const MyInput = ({ disabled, readOnly, isInvalid, ...props }) => { + const fieldInputProps = useFormControl({ + ...props, + isDisabled: disabled, + isReadOnly: readOnly, + isInvalid: isInvalid, + }); + + return ; +}; + +export default () => ( + + Custom input with hook + + Hint text + , +); +``` + +## Integrations + +### React Hook Form + +This example shows how to integrate renderlesskit Input with react-hook-form + +[Explore on CodeSandbox](https://codesandbox.io/s/renderlesskit-react-hook-form-rw5c5?file=/src/App.js) + +### Formik + +This example shows how to integrate renderlesskit Input with Formik + +[Explore on CodeSandbox](https://codesandbox.io/s/renderlesskit-formik-k1k9w) + +## API Reference + +### FormField + +FormField composes [Box](/docs/components/primitives/box) + + }>`, + description: "if `true` Input will be invalid", + }, + +]} /> + +### useFormControl + + diff --git a/pages/docs/components/forms/input.mdx b/pages/docs/components/forms/input.mdx new file mode 100644 index 0000000..ac685c8 --- /dev/null +++ b/pages/docs/components/forms/input.mdx @@ -0,0 +1,203 @@ +import PropsTable from "@/components/PropsTable"; +import ComponentLinks from "@/components/ComponentLinks"; +import Callout from "nextra-theme-docs/callout"; + +# Input + + + +## Imports + +```js +import { + Input, + InputGroup, + InputPrefix, + InputSuffix, + InputGroupSuffix, + InputGroupPrefix, +} from "@renderlesskit/react-tailwind"; +``` + +- **Input** - main input component +- **InputGroup** - input group is a wrapper to hold InputGroupPrefix/Suffix +- **InputPrefix** - prefix of the input element +- **InputSuffix** - suffix of the input element +- **InputGroupSuffix** - prefix of the input group +- **InputGroupPrefix** - suffix of the input group + +## Input Prefix/Suffix + +You can append or prepend any element inside input. By default we don't give +spacing to the elements so you have to add spacing as needed. + +`InputPrefix` is positioned absolutely within the input. + +```jsx live + + https:// + .com + +``` + +As you can see clicking on the input's prefix/suffix will focus the input, but +that might not what you want in all scenarios if you want to render a button or +something interactive. To disable this behaviour you can use +`allowPointerEvents` + +For example if you want to add a select inside the suffix you can do so like +this: + +```jsx live + + https:// + + + + +``` + +## InputGroup + +`InputGroup` is used to add addons before or after the `Input` component. + +And by using `InputGroupPrefix` we can specify the prefix or suffix. + +The main difference between InputGroupPrefix & InputPrefix is that: + +- `InputPrefix` is positioned absolutely within the input. +- `InputGroupPrefix` is positioned adjacent to the input. + +```jsx live + + + + + +``` + +Unlike `InputPrefix` where you had to add `allowPointerEvents` to make the +`InputGroupPrefix` interactive, in InputGroupPrefix you can directly pass any +interactive components (eg: Button). + +Here's a password input example using InputGroupSuffix to attach a toggle +button. + +```jsx noInline live +const PasswordExample = () => { + const [show, setShow] = React.useState(false); + const toggle = () => setShow(!show); + + return ( + + + + + + + ); +}; + +export default PasswordExample; +``` + +Here's an example with all the components combined: + +```jsx noInline live +const InputButton = props => { + return ( + + + ); +}; + +export default Controlled; +``` + +## Customizing radio + +To customize the appearance of the `Radio` component we can simply pass down +children components (RadioLabel, RadioInput, RadioIcon) for more control. + +```jsx noInline live +const CustomRadio = props => { + return ( + + + + } /> + {props.children} + + + ); +}; + +export default () => ( + + apple + Orange + Watermelon + + Grapes + + +); +``` + +## Integrations + +// TBD + +## API Reference + +### Radio + +Radio composes reakit's radio component + + + +### RadioGroup + + void", + }, + { + name: "ariaLabel", + type: "string", + description: "Sets aria-label in radio group", + }, + ]} +/> + +### RadioIcon + + diff --git a/pages/docs/components/forms/slider.mdx b/pages/docs/components/forms/slider.mdx new file mode 100644 index 0000000..55afcca --- /dev/null +++ b/pages/docs/components/forms/slider.mdx @@ -0,0 +1,135 @@ +import Callout from "nextra-theme-docs/callout"; +import PropsTable from "@/components/PropsTable"; +import ComponentLinks from "@/components/ComponentLinks"; +import outdent from "outdent"; + +# Slider + +The Slider is used to allow users to make selections from a range of values. + + + +## Imports + +```js +import { + Slider, + SliderThumb, + SliderTrack, +} from "@renderlesskit/react-tailwind"; +``` + +- **Slider** - The wrapper that provides context and functionality for all + children. +- **SliderThumb** - The handle that's used to change the slider value.. +- **SliderTrack** - Slider track element. + +## Usage + +Basic usage. + +```jsx live + +``` + +## Slider sizes + +Slider comes with 3 sizes `sm` `md` `lg` + +## Reversed Slider + +By setting the `reversed` prop to true, the slider value is reversed. + +```jsx live + +``` + +## Thumb content + +To change the contents inside of the thumb we can pass `thumbContent` prop. + +```jsx live +} /> +``` + +`thumbIcon` also accepts a function which can be used to get the value of the +slider, it returns an array which can contain multiple values if slider has +multiple thumbs. + +```jsx live + {value[0]}} +/> +``` + +## Multi Slider & Range Slider + +If slider is provided with more than one value, it will be rendered as a range +or multi slider. + +Range slider + +```jsx live + +``` + +Multi slider + +```jsx live + +``` + +## Changing the slider orientation + +```jsx live +
+ +
+``` + +## Slider steps + +```jsx live + +``` + +## Customizing Slider + +To customize the appearance of the `Radio` component we can simply pass down +children components (SliderThumb, SliderTrack) for more control. + +Note that we can also use the render prop pattern to get internal state of the +slider. + +```jsx noInline live +const CustomSlider = props => { + return ( +
+ + {({ state, trackRef, thumbRef }) => ( + <> + + {state.isThumbDragging(0) ? "Dragging" : "Not dragging"} + + + + + + )} + +
+ ); +}; + +export default CustomSlider; +``` + +## Integrations + +### React Hook Form + +This example shows how to integrate renderlesskit Input with react-hook-form + +[Explore on CodeSandbox](https://codesandbox.io/s/renderlesskit-react-hook-form-slider-jrxc1) + +## API Reference diff --git a/pages/docs/components/forms/switch.mdx b/pages/docs/components/forms/switch.mdx new file mode 100644 index 0000000..040ee8d --- /dev/null +++ b/pages/docs/components/forms/switch.mdx @@ -0,0 +1,121 @@ +import PropsTable from "@/components/PropsTable"; +import ComponentLinks from "@/components/ComponentLinks"; +import Callout from "nextra-theme-docs/callout"; + +# Switch + + + +## Imports + +```js +import { + Switch, + SwitchLabel, + SwitchInput, +} from "@renderlesskit/react-tailwind"; +``` + +- **Switch** - main switch component +- **SwitchLabel** - label for switch +- **SwitchInput** - native input element for switch + +## Switch sizes + +Switch comes with 4 sizes `sm` `md` `lg` `xl` + +```jsx live + +``` + +## Switch with label + +If we pass a string children in switch it will automatically render it inside +the SwitchLabel. + +```jsx live +Label text +``` + +## Usage with FormField + +```jsx live + + Enable notifications? + + +``` + +## Controlled switch + +```jsx noInline live +const ControlledExample = () => { + const [state, setState] = React.useState(false); + + return ( + setState(!state)}> + {state ? "On" : "Off"} + + ); +}; + +export default ControlledExample; +``` + +## Customizing + +To customize the switch we can use render props api to access the internal state +of the checkbox & change it's appearance as we like by composing `SwitchInput`, +`SwitchLabel`. + +If you don't need to access the internal state of the switch, it's also possible +to directly pass all the jsx inside of the children without the render function. + +```jsx live + + {({ state }) => ( + + + + + {state ? "Dark Mode" : "Light Mode"} + + + )} + +``` + +## Integrations + +// TBD + +## API Reference + +### Switch + +Input takes all the native `HTMLInputElement` props plus: + + diff --git a/pages/docs/components/forms/textarea.mdx b/pages/docs/components/forms/textarea.mdx new file mode 100644 index 0000000..5a5c026 --- /dev/null +++ b/pages/docs/components/forms/textarea.mdx @@ -0,0 +1,116 @@ +import PropsTable from "@/components/PropsTable"; +import ComponentLinks from "@/components/ComponentLinks"; +import Callout from "nextra-theme-docs/callout"; + +# Textarea + +The Textarea component allows you to easily create multi-line text inputs. + + + +## Imports + +```js +import { Textarea } from "@renderlesskit/react-tailwind"; +``` + +- **Textarea** - main textarea component + +## Auto Resize + +By setting autoSize prop the textarea will increase it's size according to the +content. + +```jsx live +