Repository navigation
docs: add contributor docs, agent rules, templates and CI - #6
KomalSrinivasan wants to merge 7 commits into
Conversation
Same API as the web component. Shared logic comes from the @drift-ui/key-value-editor-utils lib item, primitives and theme variables from React Native Reusables. Pasted .env text is detected in onChangeText since React Native has no paste event; the key field is multiline so newlines survive the paste. Adds jest-expo with React Native Testing Library. Refs drift-ui/ui#132
Same Prettier settings as drift-ui/ui (no semicolons, double quotes, Tailwind class sorting) and ESLint through expo lint. ESLint is pinned to 9 because eslint-plugin-react does not load on 10. Adds lint, format and format:check scripts.
Mirrors drift-ui/ui: contributor guide with the steps to port a component, the agent workflow in AGENTS.md with a work-on-issue skill, bug and component request templates, a pull request template with iOS, Android and dark mode checks, and CI running format, typecheck, lint, test and registry build.
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
There was a problem hiding this comment.
11 issues found across 35 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name=".github/pull_request_template.md">
<violation number="1" location=".github/pull_request_template.md:15">
P2: This checklist omits `bun run format:check` and `bun run registry:build`, both required by CI, so PRs can satisfy the listed checks and still fail CI. Add both commands here.</violation>
</file>
<file name="CONTRIBUTING.md">
<violation number="1" location="CONTRIBUTING.md:27">
P2: This setup lists Expo Go on a phone but only explains the simulator/emulator shortcuts, leaving phone contributors without the launch step. Tell them to scan the QR code in Expo Go.</violation>
</file>
<file name="registry/default/ui/icon.tsx">
<violation number="1" location="registry/default/ui/icon.tsx:18">
P2: The interop leaves `text-*` colors in `style` instead of mapping them to Lucide’s `color` prop, so icon strokes do not reliably follow utility classes or the button text context. Add `color: "color"` to `nativeStyleToProp`.</violation>
</file>
<file name="README.md">
<violation number="1" location="README.md:50">
P3: This directory description incorrectly includes the locally maintained `utils.ts` helper. Clarify that `utils.ts` is local so contributors know this file can be edited here.</violation>
</file>
<file name="AGENTS.md">
<violation number="1" location="AGENTS.md:55">
P3: This asks agents to read a lib file even when the web component has none, although CONTRIBUTING makes that file optional. Change this to “its lib file, if present” so components without shared logic do not send agents searching for nonexistent source.</violation>
</file>
<file name="registry/default/lib/key-value-editor-utils.ts">
<violation number="1" location="registry/default/lib/key-value-editor-utils.ts:35">
P2: `readQuoted` removes the backslash before every character, so quoted values containing unsupported escapes lose data. Consume the backslash only for the documented `\"` and `\\` escapes.</violation>
</file>
<file name="registry/default/hooks/use-controllable-state.ts">
<violation number="1" location="registry/default/hooks/use-controllable-state.ts:14">
P2: When `T` is a function, React invokes `defaultValue` as a lazy initializer and later invokes function-valued state updates as updater functions, rather than storing those functions. Wrap function values when initializing and updating React state.</violation>
<violation number="2" location="registry/default/hooks/use-controllable-state.ts:22">
P2: The updater runs against the render-captured `currentValue`, so two functional updates in one batched event both emit the same next value and uncontrolled state loses an increment. Resolve each updater against the latest pending value so queued updates compose.</violation>
</file>
<file name="registry/default/ui/key-value-editor.tsx">
<violation number="1" location="registry/default/ui/key-value-editor.tsx:89">
P2: Replacing a row with a `.env` block that starts with the same key drops that entry: stripping `row.key` turns `HOST=1` into `=1`, which the parser discards. Parse the complete text before treating the existing key as an insertion prefix.</violation>
<violation number="2" location="registry/default/ui/key-value-editor.tsx:94">
P2: Pasting before existing rows focuses the final pre-existing row because `next.at(-1)` selects the overall tail. Track and focus the last row inserted by the paste instead.</violation>
</file>
<file name="tailwind.config.js">
<violation number="1" location="tailwind.config.js:11">
P2: The preview cannot reach this dark palette: `app.json` forces `userInterfaceStyle: "light"` and no code sets a dark scheme. Enable automatic appearance and wire NativeWind's class-mode scheme.</violation>
</file>
Tip: cubic can generate docs of your entire codebase and keep them up to date. Try it here.
View guided diff | Turn on auto-fix | Re-trigger cubic
|
|
||
| ## Checklist | ||
|
|
||
| - [ ] `bun run typecheck`, `bun run lint` and `bun run test` pass |
There was a problem hiding this comment.
P2: This checklist omits bun run format:check and bun run registry:build, both required by CI, so PRs can satisfy the listed checks and still fail CI. Add both commands here.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At .github/pull_request_template.md, line 15:
<comment>This checklist omits `bun run format:check` and `bun run registry:build`, both required by CI, so PRs can satisfy the listed checks and still fail CI. Add both commands here.</comment>
<file context>
@@ -0,0 +1,20 @@
+
+## Checklist
+
+- [ ] `bun run typecheck`, `bun run lint` and `bun run test` pass
+- [ ] Tests cover what a user does: typing, pressing, submitting
+- [ ] New components are added to `registry.json` and the README table, each at its alphabetical position
</file context>
| - [ ] `bun run typecheck`, `bun run lint` and `bun run test` pass | |
| - [ ] `bun run format:check`, `bun run typecheck`, `bun run lint`, `bun run test` and `bun run registry:build` pass |
| bun start | ||
| ``` | ||
|
|
||
| Press `i` for iOS or `a` for Android. `App.tsx` is the preview screen. |
There was a problem hiding this comment.
P2: This setup lists Expo Go on a phone but only explains the simulator/emulator shortcuts, leaving phone contributors without the launch step. Tell them to scan the QR code in Expo Go.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At CONTRIBUTING.md, line 27:
<comment>This setup lists Expo Go on a phone but only explains the simulator/emulator shortcuts, leaving phone contributors without the launch step. Tell them to scan the QR code in Expo Go.</comment>
<file context>
@@ -0,0 +1,101 @@
+bun start
+```
+
+Press `i` for iOS or `a` for Android. `App.tsx` is the preview screen.
+
+## Porting a component
</file context>
| Press `i` for iOS or `a` for Android. `App.tsx` is the preview screen. | |
| For a simulator or emulator, press `i` for iOS or `a` for Android; for Expo Go, scan the QR code with the app. `App.tsx` is the preview screen. |
| cssInterop(IconImpl, { | ||
| className: { | ||
| target: "style", | ||
| nativeStyleToProp: { |
There was a problem hiding this comment.
P2: The interop leaves text-* colors in style instead of mapping them to Lucide’s color prop, so icon strokes do not reliably follow utility classes or the button text context. Add color: "color" to nativeStyleToProp.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At registry/default/ui/icon.tsx, line 18:
<comment>The interop leaves `text-*` colors in `style` instead of mapping them to Lucide’s `color` prop, so icon strokes do not reliably follow utility classes or the button text context. Add `color: "color"` to `nativeStyleToProp`.</comment>
<file context>
@@ -0,0 +1,62 @@
+cssInterop(IconImpl, {
+ className: {
+ target: "style",
+ nativeStyleToProp: {
+ height: "size",
+ width: "size",
</file context>
| if (quote === '"' && character === "\\" && index + 1 < text.length) { | ||
| value += text[++index] | ||
| continue | ||
| } |
There was a problem hiding this comment.
P2: readQuoted removes the backslash before every character, so quoted values containing unsupported escapes lose data. Consume the backslash only for the documented \" and \\ escapes.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At registry/default/lib/key-value-editor-utils.ts, line 35:
<comment>`readQuoted` removes the backslash before every character, so quoted values containing unsupported escapes lose data. Consume the backslash only for the documented `\"` and `\\` escapes.</comment>
<file context>
@@ -0,0 +1,79 @@
+ for (let index = 1; index < text.length; index++) {
+ const character = text[index]
+ if (character === quote) return value
+ if (quote === '"' && character === "\\" && index + 1 < text.length) {
+ value += text[++index]
+ continue
</file context>
| if (quote === '"' && character === "\\" && index + 1 < text.length) { | |
| value += text[++index] | |
| continue | |
| } | |
| if ( | |
| quote === '"' && | |
| character === "\\" && | |
| (text[index + 1] === quote || text[index + 1] === "\\") | |
| ) { |
| defaultValue: T | ||
| onChange?: (value: T) => void | ||
| }) { | ||
| const [uncontrolledValue, setUncontrolledValue] = React.useState(defaultValue) |
There was a problem hiding this comment.
P2: When T is a function, React invokes defaultValue as a lazy initializer and later invokes function-valued state updates as updater functions, rather than storing those functions. Wrap function values when initializing and updating React state.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At registry/default/hooks/use-controllable-state.ts, line 14:
<comment>When `T` is a function, React invokes `defaultValue` as a lazy initializer and later invokes function-valued state updates as updater functions, rather than storing those functions. Wrap function values when initializing and updating React state.</comment>
<file context>
@@ -0,0 +1,32 @@
+ defaultValue: T
+ onChange?: (value: T) => void
+}) {
+ const [uncontrolledValue, setUncontrolledValue] = React.useState(defaultValue)
+ const isControlled = value !== undefined
+ const currentValue = isControlled ? value : uncontrolledValue
</file context>
| function changeKey(index: number, text: string) { | ||
| const row = rows[index] | ||
| if (text.length - row.key.length > 1) { | ||
| const pasted = text.startsWith(row.key) |
There was a problem hiding this comment.
P2: Replacing a row with a .env block that starts with the same key drops that entry: stripping row.key turns HOST=1 into =1, which the parser discards. Parse the complete text before treating the existing key as an insertion prefix.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At registry/default/ui/key-value-editor.tsx, line 89:
<comment>Replacing a row with a `.env` block that starts with the same key drops that entry: stripping `row.key` turns `HOST=1` into `=1`, which the parser discards. Parse the complete text before treating the existing key as an insertion prefix.</comment>
<file context>
@@ -0,0 +1,195 @@
+ function changeKey(index: number, text: string) {
+ const row = rows[index]
+ if (text.length - row.key.length > 1) {
+ const pasted = text.startsWith(row.key)
+ ? text.slice(row.key.length)
+ : text
</file context>
|
|
||
| /** @type {import('tailwindcss').Config} */ | ||
| module.exports = { | ||
| darkMode: "class", |
There was a problem hiding this comment.
P2: The preview cannot reach this dark palette: app.json forces userInterfaceStyle: "light" and no code sets a dark scheme. Enable automatic appearance and wire NativeWind's class-mode scheme.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At tailwind.config.js, line 11:
<comment>The preview cannot reach this dark palette: `app.json` forces `userInterfaceStyle: "light"` and no code sets a dark scheme. Enable automatic appearance and wire NativeWind's class-mode scheme.</comment>
<file context>
@@ -1,7 +1,39 @@
+
/** @type {import('tailwindcss').Config} */
module.exports = {
+ darkMode: "class",
content: ["./App.tsx", "./registry/**/*.{ts,tsx}"],
presets: [require("nativewind/preset")],
</file context>
| ```text | ||
| registry.json item manifest read by `shadcn build` | ||
| registry/default/ui/*.tsx component source, plus React Native Reusables primitives | ||
| registry/default/lib/*.ts installed from @drift-ui, never edited here |
There was a problem hiding this comment.
P3: This directory description incorrectly includes the locally maintained utils.ts helper. Clarify that utils.ts is local so contributors know this file can be edited here.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At README.md, line 50:
<comment>This directory description incorrectly includes the locally maintained `utils.ts` helper. Clarify that `utils.ts` is local so contributors know this file can be edited here.</comment>
<file context>
@@ -1,33 +1,63 @@
+```text
+registry.json item manifest read by `shadcn build`
+registry/default/ui/*.tsx component source, plus React Native Reusables primitives
+registry/default/lib/*.ts installed from @drift-ui, never edited here
+registry/default/hooks/*.ts installed from @drift-ui, never edited here
+App.tsx preview screen
</file context>
| registry/default/lib/*.ts installed from @drift-ui, never edited here | |
| registry/default/lib/*.ts shared logic from @drift-ui; utils.ts is local |
| gh issue view <n> --comments | ||
| ``` | ||
|
|
||
| Read the web component in drift-ui/ui too: its source, its lib file and its tests. If the issue is ambiguous, ask in the conversation before writing code. Do not guess an API. |
There was a problem hiding this comment.
P3: This asks agents to read a lib file even when the web component has none, although CONTRIBUTING makes that file optional. Change this to “its lib file, if present” so components without shared logic do not send agents searching for nonexistent source.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At AGENTS.md, line 55:
<comment>This asks agents to read a lib file even when the web component has none, although CONTRIBUTING makes that file optional. Change this to “its lib file, if present” so components without shared logic do not send agents searching for nonexistent source.</comment>
<file context>
@@ -1,41 +1,126 @@
+gh issue view <n> --comments
+```
+
+Read the web component in drift-ui/ui too: its source, its lib file and its tests. If the issue is ambiguous, ask in the conversation before writing code. Do not guess an API.
+
+### 3. Claim it and branch
</file context>
| Read the web component in drift-ui/ui too: its source, its lib file and its tests. If the issue is ambiguous, ask in the conversation before writing code. Do not guess an API. | |
| Read the web component in drift-ui/ui too: its source, its lib file if present, and its tests. If the issue is ambiguous, ask in the conversation before writing code. Do not guess an API. |
…tive-foreground A multiline paste over a selected key could shrink the text, so the length check missed it. A newline now counts as a paste too, and a paste that replaced the selected key drops the old key. The theme gains --destructive-foreground, which tailwind.config.js already maps.
# Conflicts: # registry/default/ui/key-value-editor.tsx
localhostd3veloper
left a comment
There was a problem hiding this comment.
CI passes, and format, typecheck, lint, tests and the registry build pass locally.
One change: line 9 of AGENTS.md lists me as lead maintainer and leaves out syedfahadjunaid. We list the two of us as equals, the way the ui AGENTS.md does: Maintainers: [@localhostd3veloper](https://github.com/localhostd3veloper) and [@syedfahadjunaid](https://github.com/syedfahadjunaid). Keep the sentence about you running the pilot.
Gives this repo the same contributor docs, rules and tooling as drift-ui/ui.
Stacked on #2. CI runs the Jest suite that #2 adds, so merge #2 first. After that, this diff only has the two commits below.
What's in it
native.drift-ui.dev, and the README says to build the registry locally until that site exists.registry:libitem there first, as #146 does for key-value-editor.work-on-issueskill.expo lintand is pinned to 9, becauseeslint-plugin-reactfails to load on ESLint 10.Formatting the repo rewrote the React Native Reusables files to our style (double quotes, no semicolons). drift-ui/ui does the same with its shadcn files.
Renovate is left out because #1 already adds it.
Checklist
bun run format:check,bun run typecheck,bun run lint,bun run testandbun run registry:buildpassSummary by cubic
Sets up this repo's contributor docs, agent rules, GitHub templates, CI and formatting tooling to match drift-ui/ui, and ports
key-value-editoras the first registry component.Docs and templates
work-on-issueskill cover setup, the porting checklist and the issue-to-pull-request workflow.Tooling and first component
eslint-plugin-reactfails to load on 10.key-value-editorkeeps the web component's API and shared logic, and detects pasted .env text inonChangeTextsince React Native has no paste event; a newline or a paste that replaces a selected key counts as a paste.Written for commit a11f313. Summary will update on new commits.