Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@TWilson023
Copy link
Collaborator

@TWilson023 TWilson023 commented Nov 7, 2025

Adds dir="auto" throughout the lander and application pages

Summary by CodeRabbit

  • New Features
    • Applied automatic text direction handling to all form fields and controls
    • Enhanced text rendering in headers, accordions, and content blocks for improved consistency across the application

@vercel
Copy link
Contributor

vercel bot commented Nov 7, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Updated (UTC)
dub Ready Ready Preview Nov 7, 2025 7:20pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 7, 2025

Walkthrough

This pull request systematically adds bidirectional text support across the application by introducing dir="auto" attributes to UI components and extending the FormControl component to accept label direction configuration, enabling automatic text direction handling for form fields and lander blocks.

Changes

Cohort / File(s) Summary
Form Control Infrastructure
apps/web/ui/partners/groups/design/application-form/fields/form-control.tsx
Extended FormControlProps to include labelDir prop and HTMLAttributes support, enabling label customization and direction control. Updated function signature to accept and apply these new props to label and inner container elements.
Application Form Fields
apps/web/ui/partners/groups/design/application-form/fields/long-text-field.tsx, apps/web/ui/partners/groups/design/application-form/fields/multiple-choice-field.tsx, apps/web/ui/partners/groups/design/application-form/fields/select-field.tsx, apps/web/ui/partners/groups/design/application-form/fields/short-text-field.tsx
Added dir="auto" to FormControl wrappers or via new labelDir prop for automatic bidirectional text handling in form fields.
Application Form Hero
apps/web/ui/partners/groups/design/application-form/application-hero-preview.tsx
Added dir="auto" to Heading component for automatic text direction support.
Lander Components
apps/web/ui/partners/lander/blocks/accordion-block.tsx, apps/web/ui/partners/lander/blocks/block-markdown.tsx, apps/web/ui/partners/lander/blocks/block-title.tsx, apps/web/ui/partners/lander/blocks/files-block.tsx, apps/web/ui/partners/lander/lander-hero.tsx
Added dir="auto" attributes to various elements (triggers, wrappers, headings, paragraphs, text spans) for automatic bidirectional text support across lander blocks.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

  • Majority of changes are trivial attribute additions with high repetition patterns across files
  • One moderately complex change (form-control.tsx) extending props structure and HTMLAttributes support, though straightforward in implementation
  • No significant logic changes or control flow modifications

Suggested reviewers

  • steven-tey

Poem

🐰 A hop through text directions true,
Auto-flowing, East to West anew,
Labels dance and fields align,
Bidirectional threads now intertwine,
Forms and landers, all a-gleam,
Global text—a multilingual dream!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding RTL (right-to-left) alignment support to program lander and application pages, which aligns with the changeset's addition of dir="auto" attributes across multiple components.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch lander-rtl

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (5)
apps/web/ui/partners/groups/design/lander/modals/accordion-block-modal.tsx (1)

51-72: Default RTL flag never makes it into the form

useProgram() resolves asynchronously, so on the first render program is undefined. useForm only consumes defaultValues during that first render, which leaves direction stuck as undefined. When the program finishes loading with rtlContentEnabledAt, new accordion blocks still default to LTR unless the author notices and manually flips the toggle. Please hydrate the form once the program arrives (and only when the user hasn’t already touched the field) so RTL defaults kick in automatically. One way is to import useEffect, surface isDirty, and call setValue with shouldDirty: false.

-import { Dispatch, SetStateAction, useId, useRef } from "react";
+import { Dispatch, SetStateAction, useEffect, useId, useRef } from "react";-    formState: { errors },
+    formState: { errors, isDirty },
   } = useForm<AccordionBlockData>({
…
-      direction: program?.rtlContentEnabledAt ? "rtl" : undefined,
+      direction: program?.rtlContentEnabledAt ? "rtl" : undefined,
     },
   });
+
+  useEffect(() => {
+    if (!defaultValues?.direction && program?.rtlContentEnabledAt && !isDirty) {
+      setValue("direction", "rtl", { shouldDirty: false });
+    }
+  }, [
+    defaultValues?.direction,
+    program?.rtlContentEnabledAt,
+    isDirty,
+    setValue,
+  ]);
apps/web/ui/partners/groups/design/lander/modals/text-block-modal.tsx (1)

43-107: Same async default bug here

The text block modal has the same sequencing issue: direction is derived from program inside defaultValues, but program is undefined on the initial render. After the SWR fetch completes, the form keeps the original undefined value, so RTL-enabled programs still default to LTR when authors create new text blocks. Please mirror the useEffect pattern (import useEffect, expose setValue and isDirty) to seed "rtl" when the toggle is available and untouched.

-import { Dispatch, SetStateAction, useId } from "react";
+import { Dispatch, SetStateAction, useEffect, useId } from "react";-  const {
-    handleSubmit,
-    register,
-    control,
-    formState: { errors },
-  } = useForm<TextBlockData>({
+  const {
+    handleSubmit,
+    register,
+    control,
+    setValue,
+    formState: { errors, isDirty },
+  } = useForm<TextBlockData>({
     defaultValues: {
       direction: program?.rtlContentEnabledAt ? "rtl" : undefined,
       ...defaultValues,
     },
   });
+
+  useEffect(() => {
+    if (!defaultValues?.direction && program?.rtlContentEnabledAt && !isDirty) {
+      setValue("direction", "rtl", { shouldDirty: false });
+    }
+  }, [
+    defaultValues?.direction,
+    program?.rtlContentEnabledAt,
+    isDirty,
+    setValue,
+  ]);
apps/web/ui/partners/groups/design/application-form/modals/short-text-field-modal.tsx (1)

86-283: Propagation gap for RTL defaults

This modal also relies on program?.rtlContentEnabledAt inside the first-render defaultValues, so it never updates once the program finishes loading. Result: on programs with RTL enabled, newly added short-text questions stay LTR unless the user toggles manually. Align with the other modals by seeding the field after the fetch—import useEffect, expose setValue/isDirty, and set "rtl" only when there isn’t an explicit defaultValues?.direction and the form hasn’t been touched.

-import { Dispatch, SetStateAction, useId } from "react";
+import { Dispatch, SetStateAction, useEffect, useId } from "react";-  const {
-    control,
-    handleSubmit,
-    register,
-    formState: { errors },
-    watch,
-  } = useForm<FormData>({
+  const {
+    control,
+    handleSubmit,
+    register,
+    setValue,
+    formState: { errors, isDirty },
+    watch,
+  } = useForm<FormData>({
     defaultValues: {
       direction: program?.rtlContentEnabledAt ? "rtl" : undefined,
       ...formDataForShortTextFieldData(defaultValues),
     },
   });
+
+  useEffect(() => {
+    if (!defaultValues?.direction && program?.rtlContentEnabledAt && !isDirty) {
+      setValue("direction", "rtl", { shouldDirty: false });
+    }
+  }, [
+    defaultValues?.direction,
+    program?.rtlContentEnabledAt,
+    isDirty,
+    setValue,
+  ]);
apps/web/ui/partners/groups/design/application-form/modals/long-text-field-modal.tsx (1)

86-105: Default RTL state never activates after async program load

useProgram() returns program asynchronously, so useForm freezes the initial default with direction: undefined. When the SWR request resolves, the form still thinks direction is unset, the toggle appears unchecked, and submissions persist "ltr" unless the user toggles manually. This breaks the expected default behavior for RTL-enabled programs. Please backfill direction when the program data arrives.

-import { Dispatch, SetStateAction, useId } from "react";
+import { Dispatch, SetStateAction, useEffect, useId } from "react";
@@
-  const {
-    control,
-    handleSubmit,
-    register,
-    formState: { errors },
-    watch,
-  } = useForm<FormData>({
+  const {
+    control,
+    handleSubmit,
+    register,
+    formState: { errors },
+    watch,
+    setValue,
+  } = useForm<FormData>({
@@
-  const maxLengthEnabled = watch("data.maxLengthEnabled");
+  const direction = watch("direction");
+  const maxLengthEnabled = watch("data.maxLengthEnabled");
+
+  useEffect(() => {
+    if (
+      program?.rtlContentEnabledAt &&
+      !defaultValues?.direction &&
+      !direction
+    ) {
+      setValue("direction", "rtl", { shouldDirty: false });
+    }
+  }, [program?.rtlContentEnabledAt, defaultValues?.direction, direction, setValue]);
apps/web/ui/partners/groups/design/application-form/modals/multiple-choice-field-modal.tsx (1)

47-113: Multiple-choice RTL toggle also starts in the wrong state

Same async timing problem here: useForm captures direction before program is available, so the toggle renders unchecked and saved data remains LTR unless the user intervenes. Please seed the field once the program arrives.

-import { Dispatch, SetStateAction, useId, useRef } from "react";
+import { Dispatch, SetStateAction, useEffect, useId, useRef } from "react";
@@
-  const {
-    handleSubmit,
-    register,
-    watch,
-    setValue,
-    setError,
-    clearErrors,
-    formState: { errors },
-    control,
-  } = form;
+  const {
+    handleSubmit,
+    register,
+    watch,
+    setValue,
+    setError,
+    clearErrors,
+    formState: { errors },
+    control,
+  } = form;
@@
-  const fields = watch("data.options");
+  const direction = watch("direction");
+  const fields = watch("data.options");
+
+  useEffect(() => {
+    if (
+      program?.rtlContentEnabledAt &&
+      !defaultValues?.direction &&
+      !direction
+    ) {
+      setValue("direction", "rtl", { shouldDirty: false });
+    }
+  }, [program?.rtlContentEnabledAt, defaultValues?.direction, direction, setValue]);
🧹 Nitpick comments (5)
apps/web/ui/partners/groups/design/right-to-left-toggle.tsx (1)

4-10: Consider making the component generic for type safety.

The Control<any> type loses type safety. Consider making the component generic to preserve form type information.

Apply this diff to improve type safety:

-export function RightToLeftToggle({
+export function RightToLeftToggle<T extends Record<string, any>>({
   control,
   name,
 }: {
-  control: Control<any>;
+  control: Control<T>;
   name: string;
 }) {
apps/web/ui/partners/groups/design/application-form/modals/select-field-modal.tsx (1)

61-61: Consider defaulting to "ltr" instead of undefined.

When rtlContentEnabledAt is falsy, direction is set to undefined. While RightToLeftToggle handles this, explicitly defaulting to "ltr" would be more consistent and clearer.

Apply this diff:

-      direction: program?.rtlContentEnabledAt ? "rtl" : undefined,
+      direction: program?.rtlContentEnabledAt ? "rtl" : "ltr",
apps/web/ui/partners/groups/design/lander/modals/files-block-modal.tsx (1)

62-62: Consider defaulting to "ltr" instead of undefined.

Similar to the select-field-modal, explicitly defaulting to "ltr" would be more consistent than using undefined.

Apply this diff:

-      direction: program?.rtlContentEnabledAt ? "rtl" : undefined,
+      direction: program?.rtlContentEnabledAt ? "rtl" : "ltr",
apps/web/ui/partners/lander/lander-hero.tsx (1)

26-26: Simplify the dir attribute logic.

The current conditional checks if content exists before applying direction, but this is unnecessary. Additionally, landerData.direction could be undefined, which would result in an undefined dir attribute.

Apply this diff to all three elements:

-        dir={landerData.label ? landerData.direction : "ltr"}
+        dir={landerData.direction || "ltr"}

This ensures:

  1. Direction applies whether using custom or default text
  2. Always falls back to "ltr" if direction is undefined

Also applies to: 35-35, 44-44

apps/web/ui/partners/lander/blocks/text-block.tsx (1)

13-16: Consider providing explicit fallback for dir attribute.

Since block.data.direction can be undefined, it's better to explicitly fall back to "ltr" to ensure consistent behavior.

Apply this diff:

-      <BlockTitle title={block.data.title} dir={block.data.direction} />
-      <BlockMarkdown dir={block.data.direction}>
+      <BlockTitle title={block.data.title} dir={block.data.direction || "ltr"} />
+      <BlockMarkdown dir={block.data.direction || "ltr"}>
         {block.data.content}
       </BlockMarkdown>
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 16f71a3 and 34ab9af.

📒 Files selected for processing (26)
  • apps/web/lib/zod/schemas/program-application-form.ts (6 hunks)
  • apps/web/lib/zod/schemas/program-lander.ts (5 hunks)
  • apps/web/lib/zod/schemas/programs.ts (1 hunks)
  • apps/web/ui/partners/groups/design/application-form/application-hero-preview.tsx (2 hunks)
  • apps/web/ui/partners/groups/design/application-form/fields/form-control.tsx (2 hunks)
  • apps/web/ui/partners/groups/design/application-form/fields/long-text-field.tsx (1 hunks)
  • apps/web/ui/partners/groups/design/application-form/fields/multiple-choice-field.tsx (2 hunks)
  • apps/web/ui/partners/groups/design/application-form/fields/select-field.tsx (1 hunks)
  • apps/web/ui/partners/groups/design/application-form/fields/short-text-field.tsx (1 hunks)
  • apps/web/ui/partners/groups/design/application-form/modals/edit-application-hero-modal.tsx (3 hunks)
  • apps/web/ui/partners/groups/design/application-form/modals/long-text-field-modal.tsx (5 hunks)
  • apps/web/ui/partners/groups/design/application-form/modals/multiple-choice-field-modal.tsx (5 hunks)
  • apps/web/ui/partners/groups/design/application-form/modals/select-field-modal.tsx (5 hunks)
  • apps/web/ui/partners/groups/design/application-form/modals/short-text-field-modal.tsx (5 hunks)
  • apps/web/ui/partners/groups/design/lander/modals/accordion-block-modal.tsx (5 hunks)
  • apps/web/ui/partners/groups/design/lander/modals/edit-hero-modal.tsx (3 hunks)
  • apps/web/ui/partners/groups/design/lander/modals/files-block-modal.tsx (5 hunks)
  • apps/web/ui/partners/groups/design/lander/modals/text-block-modal.tsx (4 hunks)
  • apps/web/ui/partners/groups/design/right-to-left-toggle.tsx (1 hunks)
  • apps/web/ui/partners/lander/blocks/accordion-block.tsx (1 hunks)
  • apps/web/ui/partners/lander/blocks/block-markdown.tsx (1 hunks)
  • apps/web/ui/partners/lander/blocks/block-title.tsx (1 hunks)
  • apps/web/ui/partners/lander/blocks/files-block.tsx (2 hunks)
  • apps/web/ui/partners/lander/blocks/text-block.tsx (1 hunks)
  • apps/web/ui/partners/lander/lander-hero.tsx (4 hunks)
  • packages/prisma/schema/program.prisma (1 hunks)
🧰 Additional context used
🧠 Learnings (9)
📓 Common learnings
Learnt from: TWilson023
Repo: dubinc/dub PR: 2872
File: apps/web/app/(ee)/partners.dub.co/(dashboard)/profile/profile-details-form.tsx:180-189
Timestamp: 2025-09-24T15:50:16.414Z
Learning: TWilson023 prefers to keep security vulnerability fixes separate from refactoring PRs when the vulnerable code is existing and was only moved/relocated rather than newly introduced.
📚 Learning: 2025-09-17T17:44:03.965Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2857
File: apps/web/lib/actions/partners/update-program.ts:96-0
Timestamp: 2025-09-17T17:44:03.965Z
Learning: In apps/web/lib/actions/partners/update-program.ts, the team prefers to keep the messagingEnabledAt update logic simple by allowing client-provided timestamps rather than implementing server-controlled timestamp logic to avoid added complexity.

Applied to files:

  • apps/web/lib/zod/schemas/programs.ts
📚 Learning: 2025-10-15T01:52:37.048Z
Learnt from: steven-tey
Repo: dubinc/dub PR: 2958
File: apps/web/app/(ee)/partners.dub.co/(dashboard)/profile/members/page-client.tsx:270-303
Timestamp: 2025-10-15T01:52:37.048Z
Learning: In React components with dropdowns or form controls that show modals for confirmation (e.g., role selection, delete confirmation), local state should be reverted to match the prop value when the modal is cancelled. This prevents the UI from showing an unconfirmed change. The solution is to either: (1) pass an onClose callback to the modal that resets the local state, or (2) observe modal visibility state and reset on close. Example context: RoleCell component in apps/web/app/(ee)/partners.dub.co/(dashboard)/profile/members/page-client.tsx where role dropdown should revert to user.role when UpdateUserModal is cancelled.

Applied to files:

  • apps/web/ui/partners/groups/design/application-form/modals/edit-application-hero-modal.tsx
  • apps/web/ui/partners/groups/design/lander/modals/edit-hero-modal.tsx
  • apps/web/ui/partners/groups/design/application-form/modals/multiple-choice-field-modal.tsx
  • apps/web/ui/partners/groups/design/application-form/modals/short-text-field-modal.tsx
  • apps/web/ui/partners/groups/design/lander/modals/files-block-modal.tsx
  • apps/web/ui/partners/groups/design/application-form/modals/long-text-field-modal.tsx
  • apps/web/ui/partners/groups/design/application-form/modals/select-field-modal.tsx
  • apps/web/ui/partners/groups/design/lander/modals/accordion-block-modal.tsx
  • apps/web/ui/partners/groups/design/lander/modals/text-block-modal.tsx
📚 Learning: 2025-07-30T15:25:13.936Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2673
File: apps/web/ui/partners/rewards/add-edit-reward-sheet.tsx:56-66
Timestamp: 2025-07-30T15:25:13.936Z
Learning: In apps/web/ui/partners/rewards/add-edit-reward-sheet.tsx, the form schema uses partial condition objects to allow users to add empty/unconfigured condition fields without type errors, while submission validation uses strict schemas to ensure data integrity. This two-stage validation pattern improves UX by allowing progressive completion of complex forms.

Applied to files:

  • apps/web/ui/partners/groups/design/application-form/modals/edit-application-hero-modal.tsx
  • apps/web/lib/zod/schemas/program-application-form.ts
📚 Learning: 2025-09-18T16:33:17.719Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2858
File: apps/web/ui/partners/partner-application-tabs.tsx:1-1
Timestamp: 2025-09-18T16:33:17.719Z
Learning: When a React component in Next.js App Router uses non-serializable props (like setState functions), adding "use client" directive can cause serialization warnings. If the component is only imported by Client Components, it's better to omit the "use client" directive to avoid these warnings while still getting client-side execution through promotion.

Applied to files:

  • apps/web/ui/partners/groups/design/application-form/modals/short-text-field-modal.tsx
  • apps/web/ui/partners/groups/design/application-form/modals/long-text-field-modal.tsx
  • apps/web/ui/partners/groups/design/lander/modals/accordion-block-modal.tsx
  • apps/web/ui/partners/groups/design/lander/modals/text-block-modal.tsx
📚 Learning: 2025-08-25T21:03:24.285Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2736
File: apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/bounties/bounty-card.tsx:1-1
Timestamp: 2025-08-25T21:03:24.285Z
Learning: In Next.js App Router, Server Components that use hooks can work without "use client" directive if they are only imported by Client Components, as they get "promoted" to run on the client side within the Client Component boundary.

Applied to files:

  • apps/web/ui/partners/groups/design/application-form/modals/short-text-field-modal.tsx
  • apps/web/ui/partners/groups/design/lander/modals/files-block-modal.tsx
  • apps/web/ui/partners/groups/design/application-form/modals/long-text-field-modal.tsx
  • apps/web/ui/partners/groups/design/application-form/modals/select-field-modal.tsx
  • apps/web/ui/partners/groups/design/lander/modals/accordion-block-modal.tsx
  • apps/web/ui/partners/groups/design/lander/modals/text-block-modal.tsx
📚 Learning: 2025-09-24T15:47:40.293Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2872
File: apps/web/app/(ee)/partners.dub.co/(dashboard)/profile/about-you-form.tsx:152-157
Timestamp: 2025-09-24T15:47:40.293Z
Learning: The Button component from dub/ui automatically adds type="button" when an onClick prop is passed, preventing accidental form submissions without requiring explicit type specification. The implementation uses: type={onClick ? "button" : type}

Applied to files:

  • apps/web/ui/partners/groups/design/application-form/fields/form-control.tsx
📚 Learning: 2025-09-24T15:47:40.293Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2872
File: apps/web/app/(ee)/partners.dub.co/(dashboard)/profile/about-you-form.tsx:152-157
Timestamp: 2025-09-24T15:47:40.293Z
Learning: The Button component from dub/ui automatically adds type="button" when an onClick prop is passed, preventing accidental form submissions without requiring explicit type specification.

Applied to files:

  • apps/web/ui/partners/groups/design/application-form/fields/form-control.tsx
📚 Learning: 2025-10-17T08:18:19.278Z
Learnt from: devkiran
Repo: dubinc/dub PR: 0
File: :0-0
Timestamp: 2025-10-17T08:18:19.278Z
Learning: In the apps/web codebase, `@/lib/zod` should only be used for places that need OpenAPI extended zod schema. All other places should import from the standard `zod` package directly using `import { z } from "zod"`.

Applied to files:

  • apps/web/lib/zod/schemas/program-lander.ts
  • apps/web/lib/zod/schemas/program-application-form.ts
🧬 Code graph analysis (16)
apps/web/ui/partners/groups/design/application-form/modals/edit-application-hero-modal.tsx (1)
apps/web/ui/partners/groups/design/right-to-left-toggle.tsx (1)
  • RightToLeftToggle (4-31)
apps/web/ui/partners/groups/design/right-to-left-toggle.tsx (1)
packages/ui/src/tooltip.tsx (1)
  • InfoTooltip (193-199)
apps/web/ui/partners/groups/design/lander/modals/edit-hero-modal.tsx (1)
apps/web/ui/partners/groups/design/right-to-left-toggle.tsx (1)
  • RightToLeftToggle (4-31)
apps/web/ui/partners/groups/design/application-form/modals/multiple-choice-field-modal.tsx (2)
apps/web/lib/swr/use-program.ts (1)
  • useProgram (6-40)
apps/web/ui/partners/groups/design/right-to-left-toggle.tsx (1)
  • RightToLeftToggle (4-31)
apps/web/ui/partners/groups/design/application-form/application-hero-preview.tsx (1)
apps/web/ui/partners/lander/blocks/block-markdown.tsx (1)
  • BlockMarkdown (5-35)
apps/web/ui/partners/lander/blocks/text-block.tsx (2)
apps/web/ui/partners/lander/blocks/block-title.tsx (1)
  • BlockTitle (3-14)
apps/web/ui/partners/lander/blocks/block-markdown.tsx (1)
  • BlockMarkdown (5-35)
apps/web/ui/partners/groups/design/application-form/modals/short-text-field-modal.tsx (2)
apps/web/lib/swr/use-program.ts (1)
  • useProgram (6-40)
apps/web/ui/partners/groups/design/right-to-left-toggle.tsx (1)
  • RightToLeftToggle (4-31)
apps/web/ui/partners/groups/design/lander/modals/files-block-modal.tsx (2)
apps/web/lib/swr/use-program.ts (1)
  • useProgram (6-40)
apps/web/ui/partners/groups/design/right-to-left-toggle.tsx (1)
  • RightToLeftToggle (4-31)
apps/web/ui/partners/groups/design/application-form/fields/select-field.tsx (1)
apps/web/ui/partners/groups/design/application-form/fields/form-control.tsx (1)
  • FormControl (20-54)
apps/web/ui/partners/lander/lander-hero.tsx (1)
apps/web/lib/types.ts (1)
  • ProgramLanderData (470-470)
apps/web/ui/partners/groups/design/application-form/modals/long-text-field-modal.tsx (2)
apps/web/lib/swr/use-program.ts (1)
  • useProgram (6-40)
apps/web/ui/partners/groups/design/right-to-left-toggle.tsx (1)
  • RightToLeftToggle (4-31)
apps/web/ui/partners/groups/design/application-form/modals/select-field-modal.tsx (2)
apps/web/lib/swr/use-program.ts (1)
  • useProgram (6-40)
apps/web/ui/partners/groups/design/right-to-left-toggle.tsx (1)
  • RightToLeftToggle (4-31)
apps/web/ui/partners/groups/design/lander/modals/accordion-block-modal.tsx (2)
apps/web/lib/swr/use-program.ts (1)
  • useProgram (6-40)
apps/web/ui/partners/groups/design/right-to-left-toggle.tsx (1)
  • RightToLeftToggle (4-31)
apps/web/ui/partners/groups/design/lander/modals/text-block-modal.tsx (2)
apps/web/lib/swr/use-program.ts (1)
  • useProgram (6-40)
apps/web/ui/partners/groups/design/right-to-left-toggle.tsx (1)
  • RightToLeftToggle (4-31)
apps/web/ui/partners/groups/design/application-form/fields/short-text-field.tsx (1)
apps/web/ui/partners/groups/design/application-form/fields/form-control.tsx (1)
  • FormControl (20-54)
apps/web/ui/partners/groups/design/application-form/fields/long-text-field.tsx (1)
apps/web/ui/partners/groups/design/application-form/fields/form-control.tsx (1)
  • FormControl (20-54)
🔇 Additional comments (20)
packages/prisma/schema/program.prisma (1)

51-51: LGTM!

The rtlContentEnabledAt field addition follows the established pattern for feature timestamp fields in the Program model.

apps/web/ui/partners/groups/design/right-to-left-toggle.tsx (1)

11-30: LGTM!

The component logic correctly toggles between "rtl" and "ltr" values, and the UI implementation with label and tooltip is clean and user-friendly.

apps/web/ui/partners/lander/blocks/accordion-block.tsx (1)

18-18: LGTM!

The dir attribute propagation correctly enables RTL layout support for the accordion block content.

apps/web/ui/partners/lander/blocks/files-block.tsx (2)

15-15: LGTM!

The dir attribute correctly enables RTL layout for the files block.


45-45: Nice touch with the icon flip!

The rtl:-scale-x-100 class appropriately mirrors the arrow icon in RTL mode, maintaining visual consistency with text direction.

apps/web/ui/partners/groups/design/application-form/fields/select-field.tsx (1)

29-38: LGTM!

The direction is correctly extracted and passed to FormControl via labelProps, enabling RTL support for the select field label.

apps/web/ui/partners/groups/design/application-form/fields/long-text-field.tsx (1)

27-31: LGTM!

The dir prop correctly enables RTL text direction for the long text field.

apps/web/ui/partners/groups/design/application-form/fields/short-text-field.tsx (1)

31-35: LGTM!

The dir prop correctly enables RTL text direction for the short text field.

apps/web/ui/partners/groups/design/application-form/fields/multiple-choice-field.tsx (1)

26-26: The dir propagation in multiple-choice-field is consistent with the standard pattern used across other field components.

Multiple-choice-field correctly passes dir={direction} directly to FormControl, matching the pattern used by short-text-field and long-text-field. Select-field is the outlier, using labelProps={{ dir: direction }} instead. If consistency is desired across all field types, select-field should be reviewed rather than multiple-choice-field.

apps/web/ui/partners/groups/design/application-form/modals/select-field-modal.tsx (2)

3-3: LGTM!

The integration of useProgram and RightToLeftToggle is consistent with the RTL support pattern used across other modals in this PR.

Also applies to: 18-18, 45-45


247-250: LGTM!

The conditional rendering and wiring of the RTL toggle is correctly implemented and consistent with other modals in this PR.

apps/web/ui/partners/groups/design/application-form/modals/edit-application-hero-modal.tsx (2)

21-21: LGTM!

The import and form setup for RTL support is correct.

Also applies to: 51-51


155-161: LGTM!

The RTL toggle is correctly integrated with the application form data structure.

apps/web/ui/partners/groups/design/lander/modals/edit-hero-modal.tsx (2)

15-15: LGTM!

The import and form setup for RTL support is correct.

Also applies to: 43-43


134-137: LGTM!

The RTL toggle integration with lander data is correctly implemented.

apps/web/ui/partners/groups/design/lander/modals/files-block-modal.tsx (2)

3-3: LGTM!

The integration of useProgram and RightToLeftToggle follows the established pattern.

Also applies to: 18-18, 49-49


261-264: LGTM!

The RTL toggle is correctly integrated into the files block modal.

apps/web/ui/partners/lander/lander-hero.tsx (1)

11-14: LGTM!

The type extension to include direction is appropriate for RTL support.

apps/web/ui/partners/lander/blocks/block-title.tsx (1)

1-14: LGTM!

The refactor to support HTML props forwarding is well-implemented and enables clean direction propagation.

apps/web/lib/zod/schemas/programs.ts (1)

39-39: Add rtlContentEnabledAt to updateProgramSchema to enable RTL control via the API.

The field is read-only in the current implementation but should follow the same pattern as messagingEnabledAt. Both are feature flag timestamps in ProgramSchema, but only messagingEnabledAt is included in updateProgramSchema (line 71). This prevents programs from enabling or disabling RTL support through the update endpoint. Add rtlContentEnabledAt: z.coerce.date().nullish() to updateProgramSchema and handle it in update-program.ts similar to messagingEnabledAt.

⛔ Skipped due to learnings
Learnt from: TWilson023
Repo: dubinc/dub PR: 2857
File: apps/web/lib/actions/partners/update-program.ts:96-0
Timestamp: 2025-09-17T17:44:03.965Z
Learning: In apps/web/lib/actions/partners/update-program.ts, the team prefers to keep the messagingEnabledAt update logic simple by allowing client-provided timestamps rather than implementing server-controlled timestamp logic to avoid added complexity.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 34ab9af and 6961298.

📒 Files selected for processing (1)
  • apps/web/lib/zod/schemas/program-lander.ts (5 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: TWilson023
Repo: dubinc/dub PR: 2872
File: apps/web/app/(ee)/partners.dub.co/(dashboard)/profile/profile-details-form.tsx:180-189
Timestamp: 2025-09-24T15:50:16.414Z
Learning: TWilson023 prefers to keep security vulnerability fixes separate from refactoring PRs when the vulnerable code is existing and was only moved/relocated rather than newly introduced.
🔇 Additional comments (1)
apps/web/lib/zod/schemas/program-lander.ts (1)

4-4: LGTM! Direction schema is well-defined.

The enum values match the HTML5 dir attribute standard, and marking it optional ensures backward compatibility.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/web/ui/partners/lander/blocks/accordion-block.tsx (1)

27-29: Add dir="auto" to the accordion content for consistent RTL support.

The accordion title has dir="auto" for RTL support, but the content (item.content) does not. If titles can be RTL, the content should also support automatic text direction.

Consider adding dir="auto" to the AccordionContent or BlockMarkdown component:

-              <AccordionContent>
+              <AccordionContent dir="auto">
                 <BlockMarkdown className="py-2">{item.content}</BlockMarkdown>
               </AccordionContent>
🧹 Nitpick comments (1)
apps/web/ui/partners/groups/design/application-form/fields/form-control.tsx (1)

41-50: Consider adding dir="auto" to error/helper text for consistency.

The error and helper text div doesn't inherit the labelDir attribute. If error messages or helper text can contain RTL content, they may benefit from dir="auto" for proper alignment.

If needed, apply this diff:

         {(error || helperText) && (
           <div
             className={cn(
               "mt-2 text-xs",
               error ? "text-red-500" : "text-neutral-500",
             )}
+            dir="auto"
           >
             {error || helperText}
           </div>
         )}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6961298 and 41caa17.

📒 Files selected for processing (11)
  • apps/web/ui/partners/groups/design/application-form/application-hero-preview.tsx (1 hunks)
  • apps/web/ui/partners/groups/design/application-form/fields/form-control.tsx (2 hunks)
  • apps/web/ui/partners/groups/design/application-form/fields/long-text-field.tsx (1 hunks)
  • apps/web/ui/partners/groups/design/application-form/fields/multiple-choice-field.tsx (3 hunks)
  • apps/web/ui/partners/groups/design/application-form/fields/select-field.tsx (1 hunks)
  • apps/web/ui/partners/groups/design/application-form/fields/short-text-field.tsx (1 hunks)
  • apps/web/ui/partners/lander/blocks/accordion-block.tsx (1 hunks)
  • apps/web/ui/partners/lander/blocks/block-markdown.tsx (1 hunks)
  • apps/web/ui/partners/lander/blocks/block-title.tsx (1 hunks)
  • apps/web/ui/partners/lander/blocks/files-block.tsx (1 hunks)
  • apps/web/ui/partners/lander/lander-hero.tsx (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • apps/web/ui/partners/lander/blocks/files-block.tsx
  • apps/web/ui/partners/groups/design/application-form/fields/select-field.tsx
  • apps/web/ui/partners/lander/lander-hero.tsx
  • apps/web/ui/partners/groups/design/application-form/fields/short-text-field.tsx
  • apps/web/ui/partners/groups/design/application-form/fields/long-text-field.tsx
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: TWilson023
Repo: dubinc/dub PR: 2872
File: apps/web/app/(ee)/partners.dub.co/(dashboard)/profile/profile-details-form.tsx:180-189
Timestamp: 2025-09-24T15:50:16.414Z
Learning: TWilson023 prefers to keep security vulnerability fixes separate from refactoring PRs when the vulnerable code is existing and was only moved/relocated rather than newly introduced.
📚 Learning: 2025-09-24T15:47:40.293Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2872
File: apps/web/app/(ee)/partners.dub.co/(dashboard)/profile/about-you-form.tsx:152-157
Timestamp: 2025-09-24T15:47:40.293Z
Learning: The Button component from dub/ui automatically adds type="button" when an onClick prop is passed, preventing accidental form submissions without requiring explicit type specification.

Applied to files:

  • apps/web/ui/partners/groups/design/application-form/fields/form-control.tsx
📚 Learning: 2025-09-24T15:47:40.293Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2872
File: apps/web/app/(ee)/partners.dub.co/(dashboard)/profile/about-you-form.tsx:152-157
Timestamp: 2025-09-24T15:47:40.293Z
Learning: The Button component from dub/ui automatically adds type="button" when an onClick prop is passed, preventing accidental form submissions without requiring explicit type specification. The implementation uses: type={onClick ? "button" : type}

Applied to files:

  • apps/web/ui/partners/groups/design/application-form/fields/form-control.tsx
🧬 Code graph analysis (1)
apps/web/ui/partners/groups/design/application-form/application-hero-preview.tsx (1)
packages/email/src/react-email.d.ts (1)
  • Heading (16-16)
🔇 Additional comments (8)
apps/web/ui/partners/lander/blocks/block-title.tsx (1)

3-5: LGTM! Consistent and correct RTL implementation.

The dir="auto" attribute enables automatic bidirectional text direction handling. Verification confirms this pattern is applied consistently across the lander components (spans, accordions, headings), validating the approach aligns with the PR's systematic RTL support additions.

apps/web/ui/partners/groups/design/application-form/fields/form-control.tsx (2)

2-10: LGTM! Clean type extension for bidirectional text support.

The approach of extending HTMLAttributes<HTMLLabelElement> and adding labelDir is clean and type-safe. This enables external control of label directionality while allowing additional HTML attributes to be passed through.


20-31: Implementation correctly separates concerns.

The labelDir is appropriately applied to the inner container div (line 31) where the label text renders, while rest props are spread to the outer label element (line 30). This separation allows for proper text direction control without conflicting with other label attributes.

apps/web/ui/partners/groups/design/application-form/fields/multiple-choice-field.tsx (3)

52-82: Proper RTL support for checkbox options.

The dir="auto" attribute on the label (line 55) enables automatic text direction handling for checkbox options. The text direction will appropriately cascade to the nested span element (lines 79-80).


116-130: Proper RTL support for radio button options.

The dir="auto" attribute on the label (line 119) enables automatic text direction handling for radio options, with appropriate cascading to the nested span (lines 127-129).


138-148: Correct usage of the updated FormControl API.

The labelDir="auto" prop correctly utilizes the new FormControl capability to enable automatic text direction for the field label, aligning with the RTL support objectives of this PR.

apps/web/ui/partners/lander/blocks/block-markdown.tsx (1)

12-31: RTL support implementation verified—no issues found.

The dir="auto" addition on the wrapper div is correct and consistent with the RTL support rollout across other block components (BlockTitle, FilesBlock). The prose styles properly cascade to the nested Markdown content, and all consumers (TextBlock, AccordionBlock) integrate correctly without breaking changes.

apps/web/ui/partners/groups/design/application-form/application-hero-preview.tsx (1)

33-35: LGTM! RTL support correctly implemented.

The dir="auto" attribute enables automatic text direction detection for the title, allowing the browser to handle both LTR and RTL content appropriately. This aligns with the PR objectives to add RTL content support.

@steven-tey steven-tey merged commit e927d05 into main Nov 7, 2025
7 of 8 checks passed
@steven-tey steven-tey deleted the lander-rtl branch November 7, 2025 20:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants