Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/JMBeresford/r3f-form
An *accessible* webGL form component library for use with React Three Fiber
https://github.com/JMBeresford/r3f-form
Last synced: about 2 months ago
JSON representation
An *accessible* webGL form component library for use with React Three Fiber
- Host: GitHub
- URL: https://github.com/JMBeresford/r3f-form
- Owner: JMBeresford
- Created: 2022-12-29T22:34:49.000Z (about 2 years ago)
- Default Branch: main
- Last Pushed: 2024-06-01T18:06:58.000Z (7 months ago)
- Last Synced: 2024-11-07T18:04:58.036Z (2 months ago)
- Language: TypeScript
- Homepage: https://jmberesford.github.io/r3f-form/
- Size: 2.1 MB
- Stars: 30
- Watchers: 3
- Forks: 1
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
- awesome-webxr-development - r3f-form - badge] - A webGL form component for use with React Three Fiber. Ultimately, the goal is to have fully functioning HTML `<form>`s -- with all viable input types -- rendered in webGL (2D GUI / Form)
README
# r3f-form
### [View examples](https://jmberesford.github.io/r3f-form/?path=/story/form--default-submit-button)
> ## WARNING: UNDER HEAVY DEVELOPMENT
>
> Each release will aim to be a fully functional and usable release,
> but breaking API changes WILL be likely for the forseeable future.## A webGL form component for use with React Three Fiber
![image](https://user-images.githubusercontent.com/1373954/210024281-c735f61a-1a69-45e5-a5d3-147ed57a6c30.png)
This package aims to create a fully-functional and **accessible** ``
components that can be used within the [@react-three/fiber](https://github.com/pmndrs/react-three-fiber)
ecosystem. Ultimately, the goal is to have fully functioning HTML ``s -- with all viable input types -- rendered in webGL.Current implementation binds webGL elements to the existing state and event systems of respective
hidden HTML DOM elements. There is a heavy reliance on
[troika-three-text](https://github.com/protectwise/troika/tree/main/packages/troika-three-text)
for text-rendering and selection/caret logic.> Note that `r3f-form` will only work within a React-Three-Fiber Canvas element.
> You **must** be using
>
> - [@react-three/fiber](https://github.com/pmndrs/react-three-fiber)
> - [@react-three/drei](https://github.com/pmndrs/drei)
> - [troika-three-text](https://github.com/protectwise/troika/tree/main/packages/troika-three-text)
>
> as dependencies in your project to use `r3f-form`.### Install
```sh
npm install r3f-form
# or
yarn add r3f-form
# or
pnpm install r3f-form
```# How to use
## Forms
In order to create a form, just wrap any relevant elements in a ``:
```tsx
import { Form, Input, Label, Submit } from "r3f-form";export function MyForm() {
return (
);
}
```> Note that each element in the form will require a `name` prop in order to be picked up in submission, just like in a normal DOM form element
The relevant inputs will be bound to respective DOM elements under the hood, and be rendered into the 3D scene like so:
![image](https://user-images.githubusercontent.com/1373954/217718779-816da536-00af-4375-85dd-de707e79aa8d.png)
You can define submission behavior just like with any old HTML ``:
```tsx
// redirect to a login script
;// or handle it with a callback
const handleSubmit = (e: FormEvent) => {
e.preventDefault();const data = new FormData(e.target);
for (let [name, value] of data.entries()) {
console.log(`${name}: ${value}`);
}
};;
```## Inputs
An editable text-box bound to an DOM `` and represented in the webGL canvas.
```ts
type Props = {
type?: "text" | "password";/** width of the container */
width?: number;
backgroundColor?: Color;
selectionColor?: Color;
backgroundOpacity?: number;/** [left/right , top/bottom] in THREE units, respectively
*
* note that height is implicitly defined by the capHeight of the rendered
* text. The cap height is dependant on both the `textProps.font` being used and the
* `textProps.fontSize` value
*/
padding?: Vector2;
cursorWidth?: number;/** 3D transformations */
position: Vector3;
rotation: Euler;
scale: Vector3;// And ALL props available to DOM s
};
```Create a basic input field like so:
```tsx
import { Input, Label } from "r3f-form";export function MyInput() {
return (
<>
>
);
}
```![image](https://user-images.githubusercontent.com/1373954/217718847-acb169ed-95ff-4def-a126-491c648346b9.png)
You can access the value of the input via the `onChange` callback prop:
> The callback is passed the `ChangeEvent` object from the underlying HTML ``s
> change event on every change.
>
> Read more about this event [here](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event)```tsx
import { Input, Label } from "r3f-form";export function MyInput() {
const [username, setUsername] = React.useState("");
// username will always contain the current valuefunction handleChange(e) {
setUsername(ev.target.value);
}return (
<>
>
);
}
```You can also create password inputs:
```tsx
import { Input, Label } from "r3f-form";export function MyPassword() {
return (
<>
>
);
}
```![image](https://user-images.githubusercontent.com/1373954/217718412-48158e10-53b2-4e79-86c9-54bc5495521a.png)
Add custom padding to the text container:
```tsx
import { Input, Label } from "r3f-form";/*
* padding: [horizontal padding, vertical padding] in THREE units
*/export function MyInput() {
return (
<>
>
);
}
```![image](https://user-images.githubusercontent.com/1373954/217718475-1c696ff1-3b1d-4559-9d02-9535bd59cdff.png)
---
## Textarea
```ts
type Props = {
/** width of the container */
width?: number;backgroundColor?: Color;
backgroundOpacity?: number;
selectionColor?: Color;/** [left/right , top/bottom] in THREE units, respectively
*
* note that height is implicitly defined by the capHeight of the rendered
* text. The cap height is dependant on both the `textProps.font` being used
* and the `textProps.fontSize` value
*/
padding?: Vector2;
cursorWidth?: number;/** 3D transformations */
position: Vector3;
rotation: Euler;
scale: Vector3;// And ALL props available to DOM s
};
```Similar to the `` component, you can also create a `` like so:
```tsx
import { Textarea, Label } from "r3f-form";export function App() {
return (
<>
>
);
}
```![image](https://user-images.githubusercontent.com/1373954/217718566-a718eab7-1e73-4559-96aa-8e14824f0031.png)
---
## Text
In order to configure the underlying `troika-three-text` instance
that is responsible for rendering the actual text, you can use the
`` component.There is a respective `` or `` component for both ``s and
``s.For all configuration options, check out the [troika docs](https://github.com/protectwise/troika/tree/main/packages/troika-three-text).
> Note that **not all** of troika's props are exposed on these ``
> componentsChange color and background opacity:
```tsx
import { Input, Label, InputText } from "r3f-form";export function App() {
return (
<>
>
);
}
```![image](https://user-images.githubusercontent.com/1373954/217718611-c2e4848e-8267-4926-9243-7bb61bced61d.png)
```tsx
import { Input, Textarea, Label, InputText, TextareaText } from "r3f-form";export function App() {
return (
<>
>
);
}
```---
## Submit
Equivalent to a DOM ``, exposed as
an independent component. By default it renders a button
using the following props:```ts
type Props = {
value?: string;
fontSize?: number;
width?: number;
height?: number;
color?: Color;
backgroundColor?: Color;/** 3D transformations */
position: Vector3;
rotation: Euler;
scale: Vector3;// And ALL props available to DOM s
};
```Add a simple submit button to your forms like so:
```tsx
```
![image](https://user-images.githubusercontent.com/1373954/217718665-c64f6653-f85f-4310-a1c7-f2cf43154f2e.png)
While this provides a somewhat-customizable default button, the main purpose of this component
is to provide a simple interface to use 3D elements to submit your forms. Any children passed in
will submit the form on click. For example:```tsx
. . .
```
![image](https://user-images.githubusercontent.com/1373954/217718713-a0a6671f-3f1e-4817-9ee9-e205bcc22610.png)
Clicking on the big red button would submit the ``