Skip to content

Commit ef5fa2b

Browse files
jho406claude
andcommitted
Add wrappers for shadcn/ui, React Aria, React Spectrum, PrimeReact, MUI, and Chakra UI
Adds six new candy_wrapper implementations that bridge Rails form_props with popular React UI libraries, bringing the total to eight wrappers. Updates README with component status table and install instructions for each library. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent bfb8416 commit ef5fa2b

196 files changed

Lines changed: 14436 additions & 246 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎README.md‎

Lines changed: 80 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -13,31 +13,31 @@ and name are likely to change drastically before a major version release.
1313
Each component are meant to be copied from this repo to your own project and customized to your liking. There are no
1414
CLI tools to help. just copy and paste from github.
1515

16-
| `form_props` helper | Component | [Vanilla] | [Mantine] | ? |
17-
| :-------------------------------------- | :--------------------- | :----------------- | :------------------- | :------------------- |
18-
| `f.text_field` | Checkbox | :heavy_check_mark: | :heavy_check_mark: | :white_large_square: |
19-
| `f.collection_check_boxes` | CollectionCheckboxes | :heavy_check_mark: | :heavy_check_mark: | :white_large_square: |
20-
| `f.collection_radio_buttons` | CollectionRadioButtons | :heavy_check_mark: | :heavy_check_mark: | :white_large_square: |
21-
| `f.color_field` | ColorField | :heavy_check_mark: | :heavy_check_mark: | :white_large_square: |
22-
| `f.date_field` | DateField | :heavy_check_mark: | :heavy_check_mark: | :white_large_square: |
23-
| `f.datetime_local_field` | DateTimeLocalField | :heavy_check_mark: | :heavy_check_mark: | :white_large_square: |
24-
| `f.email_field` | EmailField | :heavy_check_mark: | :heavy_check_mark: | :white_large_square: |
25-
| `f.month_field` | MonthField | :heavy_check_mark: | :heavy_check_mark: | :white_large_square: |
26-
| `f.number_field` | NumberField | :heavy_check_mark: | :heavy_check_mark: | :white_large_square: |
27-
| `f.password_field` | PasswordField | :heavy_check_mark: | :heavy_check_mark: | :white_large_square: |
28-
| `f.range_field` | RangeField | :heavy_check_mark: | :white_large_square: | :white_large_square: |
29-
| `f.search_field` | SearchField | :heavy_check_mark: | :heavy_check_mark: | :white_large_square: |
30-
| `f.select` (`multiple: true` supported) | Select | :heavy_check_mark: | :heavy_check_mark: | :white_large_square: |
31-
| `f.tel_field` | TelField | :heavy_check_mark: | :heavy_check_mark: | :white_large_square: |
32-
| `f.file_field` | FileField | :heavy_check_mark: | :heavy_check_mark: | :white_large_square: |
33-
| `f.text_field` | TextField | :heavy_check_mark: | :heavy_check_mark: | :white_large_square: |
34-
| `f.time_field` | TimeField | :heavy_check_mark: | :heavy_check_mark: | :white_large_square: |
35-
| `f.url_field` | UrlField | :heavy_check_mark: | :heavy_check_mark: | :white_large_square: |
36-
| `f.text_area` | TextArea | :heavy_check_mark: | :heavy_check_mark: | :white_large_square: |
37-
| `f.grouped_collection_select` | Select | :heavy_check_mark: | :heavy_check_mark: | :white_large_square: |
38-
| `f.weekday_select` | Select | :heavy_check_mark: | :heavy_check_mark: | :white_large_square: |
39-
| `f.time_zone_select` | Select | :heavy_check_mark: | :heavy_check_mark: | :white_large_square: |
40-
| `f.submit` | SubmitButton | :heavy_check_mark: | :heavy_check_mark: | :white_large_square: |
16+
| `form_props` helper | Component | [Vanilla] | [Mantine] | [shadcn/ui] | [React Aria] | [React Spectrum] | [PrimeReact] | [MUI] | [Chakra UI] |
17+
| :-------------------------------------- | :--------------------- | :----------------- | :----------------- | :----------------- | :----------------- | :----------------- | :----------------- | :----------------- | :----------------- |
18+
| `f.check_box` | Checkbox | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
19+
| `f.collection_check_boxes` | CollectionCheckboxes | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
20+
| `f.collection_radio_buttons` | CollectionRadioButtons | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
21+
| `f.color_field` | ColorField | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
22+
| `f.date_field` | DateField | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
23+
| `f.datetime_local_field` | DateTimeLocalField | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
24+
| `f.email_field` | EmailField | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
25+
| `f.month_field` | MonthField | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
26+
| `f.number_field` | NumberField | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
27+
| `f.password_field` | PasswordField | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
28+
| `f.range_field` | RangeField | :heavy_check_mark: | :white_large_square: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
29+
| `f.search_field` | SearchField | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
30+
| `f.select` (`multiple: true` supported) | Select | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
31+
| `f.tel_field` | TelField | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
32+
| `f.file_field` | FileField | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
33+
| `f.text_field` | TextField | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
34+
| `f.time_field` | TimeField | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
35+
| `f.url_field` | UrlField | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
36+
| `f.text_area` | TextArea | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
37+
| `f.grouped_collection_select` | Select | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
38+
| `f.weekday_select` | Select | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
39+
| `f.time_zone_select` | Select | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
40+
| `f.submit` | SubmitButton | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
4141

4242
## Installation
4343

@@ -140,17 +140,70 @@ wrappers of your own, you can start here and use other UI wrappers as reference.
140140

141141
## Mantine
142142

143-
To use the Mantine wrappers, add the following libraries to your libraries before copying
143+
To use the Mantine wrappers, add the following libraries before copying:
144144

145145
```
146-
yarn add dayjs
147146
yarn add @mantine/core
148147
yarn add @mantine/dates
149148
```
150149

150+
## shadcn/ui
151+
152+
Copy the shadcn wrapper and the shadcn components it depends on (Input, Select, Checkbox, RadioGroup, Textarea, Slider, Button, Label) into your project.
153+
154+
## React Aria
155+
156+
To use the React Aria wrappers, add the following libraries before copying:
157+
158+
```
159+
yarn add react-aria-components
160+
yarn add @internationalized/date
161+
```
162+
163+
## React Spectrum
164+
165+
To use the React Spectrum wrappers, add the following libraries before copying:
166+
167+
```
168+
yarn add @adobe/react-spectrum
169+
yarn add @internationalized/date
170+
```
171+
172+
## PrimeReact
173+
174+
To use the PrimeReact wrappers, add the following library before copying:
175+
176+
```
177+
yarn add primereact
178+
```
179+
180+
## MUI
181+
182+
To use the MUI wrappers, add the following library before copying:
183+
184+
```
185+
yarn add @mui/material @emotion/react @emotion/styled
186+
```
187+
188+
## Chakra UI
189+
190+
To use the Chakra UI wrappers, add the following library before copying:
191+
192+
```
193+
yarn add @chakra-ui/react
194+
```
195+
151196
## Contributors
152197

153198
Thank you, [contributors]!
154199

155200
[contributors]: https://github.com/thoughtbot/candy_wrapper/graphs/contributors
156201
[form_props]: https://github.com/thoughtbot/form_props
202+
[Vanilla]: wrappers/ts/vanilla
203+
[Mantine]: wrappers/ts/mantine/v9
204+
[shadcn/ui]: wrappers/ts/shadcn/v4
205+
[React Aria]: wrappers/ts/react-aria/v1
206+
[React Spectrum]: wrappers/ts/react-spectrum/v3
207+
[PrimeReact]: wrappers/ts/primereact/v10
208+
[MUI]: wrappers/ts/mui/v9
209+
[Chakra UI]: wrappers/ts/chakra/v3

‎package.json‎

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,23 @@
22
"name": "@thoughtbot/candy_wrapper",
33
"version": "0.0.4",
44
"description": "Use rails forms with popular react UI libraries",
5+
"workspaces": [
6+
"wrappers/ts/vanilla",
7+
"wrappers/ts/mantine/v9",
8+
"wrappers/ts/shadcn/v4",
9+
"wrappers/ts/react-aria/v1",
10+
"wrappers/ts/react-spectrum/v3",
11+
"wrappers/ts/primereact/v10",
12+
"wrappers/ts/mui/v9",
13+
"wrappers/ts/chakra/v3"
14+
],
515
"scripts": {
616
"build": "tsup",
7-
"build:wrappers": "tsc --project ./wrappers/tsconfig.json && rm -r wrappers/js/* && mv -v temp/wrappers/ts/* wrappers/js",
17+
"build:wrappers": "npm run build --workspaces --if-present",
818
"dev": "tsup --watch",
919
"clean": "rm -rf dist",
1020
"lint": "run-p lint:eslint lint:types lint:prettier",
21+
"typecheck:wrappers": "npm run typecheck --workspaces --if-present",
1122
"lint:eslint": "eslint --max-warnings=0 --ext js,jsx,ts,tsx",
1223
"lint:prettier": "prettier --check '**/*' --ignore-unknown",
1324
"lint:types": "tsc",
@@ -41,29 +52,25 @@
4152
},
4253
"homepage": "https://github.com/thoughtbot/candy_wrapper#readme",
4354
"devDependencies": {
44-
"@mantine/core": "^7.15.3",
45-
"@mantine/dates": "^7.15.3",
46-
"@nextui-org/react": "^2.4.8",
4755
"@react-aria/test-utils": "^1.0.0-alpha.2",
4856
"@testing-library/dom": "^10.4.0",
4957
"@testing-library/jest-dom": "^6.5.0",
58+
"@testing-library/react": "^16.1.0",
5059
"@testing-library/user-event": "^14.5.2",
51-
"@types/react": "^18.3.12",
60+
"@types/react": "^19.0.0",
5261
"@typescript-eslint/eslint-plugin": "^7.15.0",
5362
"@typescript-eslint/parser": "^7.15.0",
5463
"@vitejs/plugin-react": "^4.3.1",
5564
"@vitest/coverage-v8": "^2.0.2",
56-
"dayjs": "^1.11.13",
5765
"eslint": "^8.57.0",
5866
"eslint-plugin-react": "^7.34.3",
5967
"eslint-plugin-vitest-globals": "^1.5.0",
60-
"framer-motion": "^11.11.11",
6168
"happy-dom": "^15.7.4",
6269
"npm-run-all": "^4.1.5",
6370
"prettier": "^2.3.1",
6471
"prettier-eslint": "^16.3.0",
65-
"react": "^18.3.1",
66-
"react-dom": "^18.3.1",
72+
"react": "^19.0.0",
73+
"react-dom": "^19.0.0",
6774
"tsup": "^8.1.0",
6875
"typedoc": "^0.26.5",
6976
"typedoc-plugin-markdown": "^4.2.3",

‎vitest.config.ts‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,18 @@ export default defineConfig({
1010
restoreMocks: true,
1111
globals: true,
1212
setupFiles: ['./setup.js'],
13+
server: {
14+
deps: {
15+
inline: [/@adobe\/react-spectrum/, /@react-spectrum/, /@spectrum-icons/],
16+
},
17+
},
1318
},
1419
resolve: {
1520
alias: {
1621
'@thoughtbot/candy_wrapper': path.resolve(__dirname, './src/index'),
22+
'@/components/ui': path.resolve(__dirname, './wrappers/ts/shadcn/v4/components/ui'),
23+
'@/registry/bases/radix/lib': path.resolve(__dirname, './wrappers/ts/shadcn/v4/registry/bases/radix/lib'),
24+
'@/app/(create)/components': path.resolve(__dirname, './wrappers/ts/shadcn/v4/app/(create)/components'),
1725
},
1826
},
1927
})

0 commit comments

Comments
 (0)