<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Rohan Satkar | Coderxrohan</title>
    <description>The latest articles on DEV Community by Rohan Satkar | Coderxrohan (@coderxrohan).</description>
    <link>https://dev.to/coderxrohan</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3673854%2F22a6241a-2590-4baf-ab68-e3b964f46a67.jpg</url>
      <title>DEV Community: Rohan Satkar | Coderxrohan</title>
      <link>https://dev.to/coderxrohan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/coderxrohan"/>
    <language>en</language>
    <item>
      <title>My First Feature Contribution to Open Source: A Learning Journey with GitLab</title>
      <dc:creator>Rohan Satkar | Coderxrohan</dc:creator>
      <pubDate>Wed, 28 Jan 2026 17:24:06 +0000</pubDate>
      <link>https://dev.to/coderxrohan/my-first-feature-contribution-to-open-source-a-learning-journey-with-gitlab-5c2e</link>
      <guid>https://dev.to/coderxrohan/my-first-feature-contribution-to-open-source-a-learning-journey-with-gitlab-5c2e</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo0ly4z65fbyope5uqgwq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo0ly4z65fbyope5uqgwq.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
Contributing a feature to a large open-source project for the first time is both exciting and intimidating—and recently, I had the opportunity to experience exactly that. My merge request &lt;a href="https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/merge_requests/3074" rel="noopener noreferrer"&gt;&lt;strong&gt;!3074&lt;/strong&gt;&lt;/a&gt;, which adds support for parsing &lt;strong&gt;absolute SSH remote URLs&lt;/strong&gt; in the GitLab VS Code extension, was merged into &lt;code&gt;main&lt;/code&gt;, marking my first feature-level contribution to a widely used open-source tool.&lt;/p&gt;

&lt;p&gt;When I started exploring the issue, I didn’t initially set out to “build a feature.” I was browsing open issues to understand how real production bugs are identified and handled in mature projects. That’s when I came across a report explaining that SSH remotes formatted like&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git@gitlab.com:/group/project.git&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;were not being recognized correctly. &lt;br&gt;
On the surface, this looked like a minor parsing issue—but digging deeper revealed why it mattered.&lt;/p&gt;

&lt;p&gt;The colon-slash (&lt;code&gt;:/&lt;/code&gt;) syntax represents an &lt;strong&gt;absolute path on the remote server&lt;/strong&gt;, and while it’s a valid SSH format, the existing logic didn’t account for it. This meant that for some users, the GitLab VS Code extension couldn’t correctly identify or link their repositories. It was a small gap, but one that directly affected user experience.&lt;/p&gt;

&lt;p&gt;My first learning moment came from understanding the existing codebase. I spent time reading through the SSH normalization logic, understanding the different regex patterns already in use, and seeing how small ordering decisions could have big consequences. One key realization was that the fix wasn’t just about adding a new pattern—it had to be placed &lt;strong&gt;before&lt;/strong&gt; the general SSH path matcher to avoid incorrect matches. That insight alone taught me how careful and intentional maintainers need to be when working with parsing logic.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmtf081tl5fpsufvr6o9k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmtf081tl5fpsufvr6o9k.png" alt=" " width="800" height="292"&gt;&lt;/a&gt;&lt;br&gt;
Implementing the fix itself was straightforward, but doing it the right way took thought. I added a dedicated regex to detect absolute SSH paths and normalized them to a standard &lt;code&gt;ssh://&lt;/code&gt; format so downstream parsing would work consistently. More importantly, I backed the change with unit tests—something I’ve learned is non-negotiable in serious open-source projects. Writing tests for both simple and nested group paths helped me understand how edge cases are treated as first-class citizens in production code.&lt;/p&gt;

&lt;p&gt;The review process was another major learning experience. Maintainers and reviewers provided clear, supportive feedback, and the overall tone was collaborative rather than intimidating. Seeing all threads resolved, tests passing, and the merge train succeed reinforced how much process and trust goes into every change—no matter how small it looks from the outside.&lt;/p&gt;

&lt;p&gt;What stood out to me most was how &lt;strong&gt;focused&lt;/strong&gt; the contribution needed to be. This wasn’t about adding new functionality for its own sake, but about fixing a specific user-facing issue without introducing regressions or breaking changes. That mindset—solve one problem well—has reshaped how I now think about open-source contributions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb4p8ey04ovg5y9cqck6t.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb4p8ey04ovg5y9cqck6t.jpg" alt=" " width="800" height="164"&gt;&lt;/a&gt;&lt;br&gt;
Having this merge request included as part of the &lt;a href="https://contributors.gitlab.com/hackathon&amp;lt;br&amp;gt;%0A![%20](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s0f9tuis4upm86rjb4hx.png)" rel="noopener noreferrer"&gt;January 2026 GitLab Hackathon&lt;/a&gt; makes the experience even more meaningful. It validated not just the code, but the effort to understand the problem deeply, communicate clearly, and follow project standards.&lt;/p&gt;

&lt;p&gt;This contribution gave me confidence that I can meaningfully participate in large open-source ecosystems. More importantly, it taught me that impactful contributions don’t always require massive features—sometimes, they come from noticing a small gap and taking the time to fix it properly.&lt;/p&gt;

&lt;p&gt;This is just the beginning of my open-source journey, and I’m excited to keep learning, contributing, and giving back to the community that builds the tools we all rely on every day.&lt;/p&gt;

&lt;p&gt;My successfully merged PRs:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/merge_requests/3074" rel="noopener noreferrer"&gt;https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/merge_requests/3074&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://gitlab.com/gitlab-org/gitlab/-/merge_requests/220833" rel="noopener noreferrer"&gt;https://gitlab.com/gitlab-org/gitlab/-/merge_requests/220833&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/merge_requests/3070" rel="noopener noreferrer"&gt;https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/merge_requests/3070&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;"I'm proud to have earned the Level 2 Contributor badge from the GitLab community. It reflects the time and effort I've put into meaningful contributions, and it's motivating to see that impact recognized. Being part of an open-source ecosystem where collaboration drives innovation is incredibly rewarding, and this milestone pushes me to keep learning and giving back."&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqy2d0le9kgbvpuzajus0.png" alt=" " width="200" height="200"&gt;
&lt;/h2&gt;




&lt;p&gt;Official Page&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://contributors.gitlab.com/hackathon" rel="noopener noreferrer"&gt;https://contributors.gitlab.com/hackathon&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Profile:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://gitlab.com/Coderxrohan" rel="noopener noreferrer"&gt;https://gitlab.com/Coderxrohan&lt;/a&gt;
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftzrvhj1eocjij5vcikbf.png" alt=" " width="800" height="159"&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>programming</category>
      <category>opensource</category>
      <category>gitlab</category>
      <category>hackathon</category>
    </item>
    <item>
      <title>🧠 The React Bug That Only Appears When Your Code Is Too Fast</title>
      <dc:creator>Rohan Satkar | Coderxrohan</dc:creator>
      <pubDate>Thu, 01 Jan 2026 18:07:32 +0000</pubDate>
      <link>https://dev.to/coderxrohan/the-react-bug-that-only-appears-when-your-code-is-too-fast-371g</link>
      <guid>https://dev.to/coderxrohan/the-react-bug-that-only-appears-when-your-code-is-too-fast-371g</guid>
      <description>&lt;p&gt;While working with PrimeReact’s DataTable, I ran into a bug that nearly broke my brain.&lt;/p&gt;

&lt;p&gt;Buttons inside table rows were logging different state values, even though the state was global and clearly up to date.&lt;/p&gt;

&lt;p&gt;At first glance, it looked like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a React Hook Form issue&lt;/li&gt;
&lt;li&gt;or a state sync problem&lt;/li&gt;
&lt;li&gt;or even a React bug&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It turned out to be none of those.&lt;/p&gt;

&lt;p&gt;This post walks through:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the exact problem&lt;/li&gt;
&lt;li&gt;why it was so confusing&lt;/li&gt;
&lt;li&gt;how I isolated the root cause&lt;/li&gt;
&lt;li&gt;and how a one-line fix resolved it without sacrificing performance
________________________________________________________&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🧩 The Problem: “Why does each row see a different state?”&lt;/p&gt;

&lt;p&gt;I had a DataTable where each row had a button.&lt;/p&gt;

&lt;p&gt;Clicking the buttons produced this output:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Button 0 clicked → items.length = 1&lt;br&gt;
Button 1 clicked → items.length = 2&lt;br&gt;
Button 2 clicked → items.length = 3&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;But this made &lt;strong&gt;no sense.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;At the time of clicking:&lt;/p&gt;

&lt;p&gt;the global state clearly had 3 items&lt;/p&gt;

&lt;p&gt;every button should have logged 3&lt;/p&gt;

&lt;p&gt;Instead, each button behaved as if it remembered an older version of state.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;🔬 Reproducing the Issue&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Steps to reproduce:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add 3 rows to the table&lt;/li&gt;
&lt;li&gt;Click the button in row 1 → logs 1&lt;/li&gt;
&lt;li&gt;Click row 2 → logs 2&lt;/li&gt;
&lt;li&gt;Click row 3 → logs 3&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each row was somehow “stuck” in the past.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;🤔 Why This Was So Confusing&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here’s what made this bug especially sneaky:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The UI looked &lt;strong&gt;correct&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;State updates were &lt;strong&gt;working&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;No errors, no warnings&lt;/li&gt;
&lt;li&gt;Disabling memoization (cellMemo={false}) “fixed” it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last part was the clue.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;🧠 The Hidden Culprit: Memoization + Closures&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;PrimeReact’s DataTable uses cell memoization (cellMemo=true by default) to improve performance.&lt;/p&gt;

&lt;p&gt;That means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cells do not re-render&lt;/li&gt;
&lt;li&gt;unless specific memo keys change&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What went wrong?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Existing rows kept the same object reference&lt;/li&gt;
&lt;li&gt;Memoized cells were not re-rendered&lt;/li&gt;
&lt;li&gt;Event handlers (&lt;code&gt;onClick&lt;/code&gt;) kept the closure from the render they were created in&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So each button captured a snapshot of state at creation time.&lt;/p&gt;

&lt;p&gt;This is classic stale closure behavior — but caused by memoization, not state logic.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;🧪 Minimal Reproduction (Pure React)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I recreated the exact same bug with &lt;code&gt;React.memo&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const Row = React.memo(
  ({ item, index, snapshotLength }) =&amp;gt; {
    const onClick = () =&amp;gt; {
      console.log(index, snapshotLength);
    };
    return &amp;lt;button onClick={onClick}&amp;gt;Click&amp;lt;/button&amp;gt;;
  },
  (prev, next) =&amp;gt; prev.item === next.item // ❌ ignores snapshotLength
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because &lt;code&gt;snapshotLength&lt;/code&gt; was ignored:&lt;/p&gt;

&lt;p&gt;the row never re-rendered&lt;/p&gt;

&lt;p&gt;the click handler kept stale data&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This was the exact same failure mode as DataTable’s&lt;/strong&gt; &lt;code&gt;cellMemo&lt;/code&gt;.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;🛠️ The Actual Fix (Not the Hack)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The easy workaround was:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;DataTable cellMemo={false} /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;disables performance optimizations&lt;/li&gt;
&lt;li&gt;hurts large tables&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The real fix&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The memoization key needed to change when row structure changed.&lt;/p&gt;

&lt;p&gt;In PrimeReact, the fix was simple:&lt;/p&gt;

&lt;p&gt;Before&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cellMemoProps = { index }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cellMemoProps = { rowIndex }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why this works:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;rowIndex changes when rows are added/removed/reordered&lt;/li&gt;
&lt;li&gt;Memoized cells now re-render when they should&lt;/li&gt;
&lt;li&gt;Fresh closures, same performance benefits&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;✅ Result&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After the fix:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Button 0 → items.length = 3
Button 1 → items.length = 3
Button 2 → items.length = 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;No stale closures.&lt;/li&gt;
&lt;li&gt;No performance regression.&lt;/li&gt;
&lt;li&gt;No API changes.
________________________________________________________&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;🤯 Bonus Insight: Why &lt;code&gt;useFieldArray&lt;/code&gt; “Just Worked”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One interesting discovery:&lt;/p&gt;

&lt;p&gt;When using React Hook Form’s &lt;code&gt;useFieldArray&lt;/code&gt;, this bug never appeared.&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;Because &lt;code&gt;useFieldArray&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;creates new object references on updates&lt;/p&gt;

&lt;p&gt;naturally invalidates memoization&lt;/p&gt;

&lt;p&gt;So rows re-render automatically.&lt;/p&gt;

&lt;p&gt;It wasn’t magic — &lt;strong&gt;just object identity working in your favor.&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;🧠 Key Takeaways&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Memoization bugs are identity bugs, not state bugs&lt;/li&gt;
&lt;li&gt;If a prop affects behavior, it must participate in memo invalidation&lt;/li&gt;
&lt;li&gt;Stale closures can exist even when state is correct&lt;/li&gt;
&lt;li&gt;Disabling memoization is a workaround, not a solution&lt;/li&gt;
&lt;li&gt;Performance optimizations demand extra correctness discipline&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;🚀 Final Thoughts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This was one of those bugs that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;looks impossible&lt;/li&gt;
&lt;li&gt;survives logging&lt;/li&gt;
&lt;li&gt;disappears when you “simplify” things&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But once you think in &lt;strong&gt;render snapshots&lt;/strong&gt;, everything clicks.&lt;/p&gt;

&lt;p&gt;Huge thanks to the PrimeReact maintainers for quick feedback and collaboration — and to the original reporter for the excellent reproduction.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>performance</category>
      <category>react</category>
    </item>
    <item>
      <title>🛠 Fixing a Real UI Bug in PrimeReact: My Open Source Contribution Journey</title>
      <dc:creator>Rohan Satkar | Coderxrohan</dc:creator>
      <pubDate>Wed, 31 Dec 2025 20:52:51 +0000</pubDate>
      <link>https://dev.to/coderxrohan/fixing-a-real-ui-bug-in-primereact-my-open-source-contribution-journey-428b</link>
      <guid>https://dev.to/coderxrohan/fixing-a-real-ui-bug-in-primereact-my-open-source-contribution-journey-428b</guid>
      <description>&lt;p&gt;Recently, I contributed a fix to PrimeReact’s OrganizationChart component, addressing a visual bug that affected real-world use cases. I wanted to share the full journey — from identifying the issue to implementing a maintainable fix and navigating CI/style checks — because this is what real open-source work looks like.&lt;/p&gt;

&lt;p&gt;🐞 The Bug&lt;/p&gt;

&lt;p&gt;The issue occurred in OrganizationChart when a node had a large number of child nodes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What users were seeing:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Connector lines between parent and children appeared broken or misaligned&lt;/li&gt;
&lt;li&gt;Some child nodes looked visually disconnected&lt;/li&gt;
&lt;li&gt;The hierarchy became difficult to understand&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Important detail:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The data was correct&lt;/li&gt;
&lt;li&gt;The component did not crash&lt;/li&gt;
&lt;li&gt;The issue was purely visual, but highly misleading&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This bug was already reported and labeled as a Bug by the PrimeReact team.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;📊 Impact Assessment&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I’d rate the severity of this bug as 7/10.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it mattered:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Organization charts are meant to communicate hierarchy clearly&lt;/li&gt;
&lt;li&gt;Broken connectors lead to incorrect interpretation&lt;/li&gt;
&lt;li&gt;The issue appeared in real-world org charts with large teams, not just edge cases&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why it wasn’t critical:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No runtime errors&lt;/li&gt;
&lt;li&gt;Small and medium charts worked fine&lt;/li&gt;
&lt;li&gt;No data loss or crashes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Still, for teams using OrganizationChart at scale, this was a real UX problem.&lt;/p&gt;




&lt;p&gt;🔍 Root Cause Analysis&lt;/p&gt;

&lt;p&gt;After digging into the component’s implementation, I found the core issue:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All child nodes of a parent were rendered in a single table row&lt;/li&gt;
&lt;li&gt;Connector lines were drawn using CSS borders&lt;/li&gt;
&lt;li&gt;When the number of children increased:&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;-    The row became extremely wide&lt;/li&gt;
&lt;li&gt;-    Browser layout rounding and CSS limitations kicked in&lt;/li&gt;
&lt;li&gt;-    Connector lines no longer aligned correctly&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This wasn’t a styling mistake or incorrect data — it was a structural layout limitation.&lt;/p&gt;

&lt;p&gt;🧠 The Fix Strategy&lt;/p&gt;

&lt;p&gt;The key was to &lt;strong&gt;fix the layout without breaking existing behavior.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Constraints:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No public API changes&lt;/li&gt;
&lt;li&gt;No new props&lt;/li&gt;
&lt;li&gt;No CSS hacks&lt;/li&gt;
&lt;li&gt;Maintain backward compatibility&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The approach:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Split large sibling groups into multiple rows instead of one wide row&lt;/li&gt;
&lt;li&gt;Keep each row’s width within reasonable bounds&lt;/li&gt;
&lt;li&gt;Render connector lines per row&lt;/li&gt;
&lt;li&gt;Preserve the existing connector logic and styling&lt;/li&gt;
&lt;li&gt;Ensure expand/collapse and selection still worked as before&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This way, small charts behaved exactly the same, while large charts became readable and stable.&lt;/p&gt;

&lt;p&gt;🧩 Implementation Details&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Introduced internal chunking logic to batch child nodes&lt;/li&gt;
&lt;li&gt;Calculated colSpan per row instead of globally&lt;/li&gt;
&lt;li&gt;Grouped connector rendering (linesDown, linesMiddle, child nodes) per row&lt;/li&gt;
&lt;li&gt;Avoided DOM measurements or SVG rewrites to keep risk low&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clean hierarchy&lt;/li&gt;
&lt;li&gt;Correct connector alignment&lt;/li&gt;
&lt;li&gt;No breaking changes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🧪 CI, Formatting &amp;amp; ESLint Challenges (Real OSS Life)&lt;/p&gt;

&lt;p&gt;Fixing the bug was only half the job.&lt;/p&gt;

&lt;p&gt;PrimeReact has strict CI checks, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prettier&lt;/li&gt;
&lt;li&gt;ESLint (with padding-line-between-statements)&lt;/li&gt;
&lt;li&gt;Style consistency rules&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I had to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Normalize formatting&lt;/li&gt;
&lt;li&gt;Add required blank lines between statements&lt;/li&gt;
&lt;li&gt;Separate logic commits from style-only commits&lt;/li&gt;
&lt;li&gt;Ensure everything passed locally before pushing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This part may look small, but it’s critical in large OSS projects.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;✅ Final Result&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Before:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Large org charts looked broken&lt;/p&gt;

&lt;p&gt;Connector lines misled users&lt;/p&gt;

&lt;p&gt;Visual hierarchy was unreliable&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;After:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Large sibling groups render across multiple rows&lt;/p&gt;

&lt;p&gt;Connector lines remain aligned&lt;/p&gt;

&lt;p&gt;Hierarchy is clear and readable&lt;/p&gt;

&lt;p&gt;Existing behavior remains unchanged&lt;/p&gt;

&lt;p&gt;The fix is now linked to the original issue and ready for maintainers to review.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;📚 What I Learned&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;UI bugs can be high impact even without errors&lt;/li&gt;
&lt;li&gt;CSS-based layouts have scaling limits&lt;/li&gt;
&lt;li&gt;Good OSS fixes are:&lt;/li&gt;
&lt;li&gt;- Minimal&lt;/li&gt;
&lt;li&gt;- Backward-compatible&lt;/li&gt;
&lt;li&gt;- Easy to review&lt;/li&gt;
&lt;li&gt;CI failures are part of the process — not a failure of the solution&lt;/li&gt;
&lt;li&gt;Clear communication with maintainers matters as much as code
__________________________________________________________________&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;🙌 Why This Matters&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This contribution wasn’t about adding features — it was about *&lt;em&gt;making existing functionality reliable at scale.&lt;br&gt;
*&lt;/em&gt;&lt;br&gt;
That’s the kind of work that quietly improves developer experience and user trust.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you’re thinking about contributing to open source:&lt;/li&gt;
&lt;li&gt;Don’t wait for “perfect” issues&lt;/li&gt;
&lt;li&gt;Pick a real bug&lt;/li&gt;
&lt;li&gt;Fix it cleanly&lt;/li&gt;
&lt;li&gt;Learn from the review process&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s where the real growth happens.&lt;/p&gt;

</description>
      <category>ui</category>
      <category>css</category>
      <category>opensource</category>
      <category>react</category>
    </item>
    <item>
      <title>Fixing Focus Management in PrimeReact Calendar (Open Source Contribution)</title>
      <dc:creator>Rohan Satkar | Coderxrohan</dc:creator>
      <pubDate>Mon, 22 Dec 2025 15:03:20 +0000</pubDate>
      <link>https://dev.to/coderxrohan/fixing-focus-management-in-primereact-calendar-open-source-contribution-2on7</link>
      <guid>https://dev.to/coderxrohan/fixing-focus-management-in-primereact-calendar-open-source-contribution-2on7</guid>
      <description>&lt;p&gt;Open-source contributions don’t always mean adding big features. Sometimes, the most impactful changes are small UX fixes that improve how thousands of users interact with a component every day.&lt;/p&gt;

&lt;p&gt;This post walks through a usability issue I fixed in the Calendar component of PrimeReact, and how a &lt;a href="https://linktr.ee/rohansatkar" rel="noopener noreferrer"&gt;minimal&lt;/a&gt;, targeted change improved user interaction without breaking accessibility.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Coderxrohan" rel="noopener noreferrer"&gt;Background&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://primereact.org/" rel="noopener noreferrer"&gt;PrimeReact&lt;/a&gt; is a popular React UI component library used by 50k+ projects. Its Calendar component supports different selection modes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;single&lt;/li&gt;
&lt;li&gt;range&lt;/li&gt;
&lt;li&gt;multiple&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each mode has slightly different interaction expectations, especially around keyboard &lt;a href="https://linktr.ee/rohansatkar" rel="noopener noreferrer"&gt;focus&lt;/a&gt; and accessibility.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Coderxrohan" rel="noopener noreferrer"&gt;The Problem&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In single selection mode, the following behavior occurred:&lt;/li&gt;
&lt;li&gt;User clicks the input → calendar opens&lt;/li&gt;
&lt;li&gt;User selects a date&lt;/li&gt;
&lt;li&gt;Calendar closes ✔️&lt;/li&gt;
&lt;li&gt;Input field is immediately auto-focused ❌&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Also Read: &lt;a href="https://github.com/Coderxrohan/Youtube-PIP-Automation-Extension" rel="noopener noreferrer"&gt;Youtube PIP Automation Extension&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Because the input regained focus programmatically, clicking it again did not reopen the calendar. From a user’s perspective, the component felt broken.&lt;/p&gt;

&lt;p&gt;This issue was reported and tracked in the PrimeReact repository.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Coderxrohan" rel="noopener noreferrer"&gt;Why This Matters&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;This wasn’t just a cosmetic issue:&lt;/li&gt;
&lt;li&gt;It blocked normal mouse interaction&lt;/li&gt;
&lt;li&gt;It created confusion for users&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It behaved differently than expected for a single-selection date picker&lt;/p&gt;

&lt;p&gt;At the same time, focus restoration is important for accessibility, especially in range and multiple selection modes. So the solution had to be careful — not just “remove focus handling”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Coderxrohan" rel="noopener noreferrer"&gt;Root Cause&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While tracing the code path after date selection, I found that the following function was being called unconditionally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;reFocusInputField();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This made sense for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;range selection&lt;/li&gt;
&lt;li&gt;multiple selection&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;…but not for single selection, where the calendar overlay closes immediately.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/coderxrohan/fixing-focus-management-in-primereact-calendar-open-source-contribution-2on7"&gt;The Fix&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Instead of removing the logic entirely, I made it context-aware by checking the selection mode:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- reFocusInputField();
+ if (props.selectionMode !== 'single') {
+     reFocusInputField();
+ }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://dev.to/coderxrohan/fixing-focus-management-in-primereact-calendar-open-source-contribution-2on7"&gt;Result&lt;/a&gt;&lt;br&gt;
Selection Mode  Behavior After Fix&lt;br&gt;
Single  Calendar closes, no forced refocus, input clickable again&lt;br&gt;
Range   Refocus preserved&lt;br&gt;
Multiple    Refocus preserved&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/coderxrohan/fixing-focus-management-in-primereact-calendar-open-source-contribution-2on7"&gt;The fix:&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Solved the reported issue&lt;/li&gt;
&lt;li&gt;Preserved keyboard accessibility&lt;/li&gt;
&lt;li&gt;Avoided regressions&lt;/li&gt;
&lt;li&gt;Passed CI checks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Was &lt;a href="https://dev.to/coderxrohan/fixing-focus-management-in-primereact-calendar-open-source-contribution-2on7"&gt;reviewed and merged&lt;/a&gt; by PrimeReact maintainers&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc5c1cmhdrxm9iokiyo2s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc5c1cmhdrxm9iokiyo2s.png" alt=" " width="375" height="900"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv4q48176dtcw84olj3le.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv4q48176dtcw84olj3le.png" alt=" " width="784" height="664"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn7roilj8igq0mkgwrcvq.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn7roilj8igq0mkgwrcvq.jpg" alt=" " width="285" height="177"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What I Learned&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;UX bugs often live in “working” code&lt;/li&gt;
&lt;li&gt;Accessibility and usability need to be balanced, not traded off&lt;/li&gt;
&lt;li&gt;Maintainers value small, well-scoped fixes&lt;/li&gt;
&lt;li&gt;Explaining why a change is needed is as important as the change itself&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://linktr.ee/rohansatkar" rel="noopener noreferrer"&gt;Closing Thoughts&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This &lt;a href="https://dev.to/coderxrohan/fixing-focus-management-in-primereact-calendar-open-source-contribution-2on7"&gt;contribution&lt;/a&gt; reinforced that meaningful open-source work doesn’t have to be large or complex. A few lines of carefully considered code can improve the experience of thousands of users.&lt;/p&gt;

&lt;p&gt;If you’re looking to &lt;a href="https://dev.to/coderxrohan/fixing-focus-management-in-primereact-calendar-open-source-contribution-2on7"&gt;contribute&lt;/a&gt; to open source, fixing small usability issues is a great place to start.&lt;/p&gt;

&lt;p&gt;Follow me on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/Coderxrohan" rel="noopener noreferrer"&gt;Github&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.linkedin.com/in/rohansatkar" rel="noopener noreferrer"&gt;Linkedin&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>programming</category>
      <category>opensource</category>
      <category>github</category>
      <category>react</category>
    </item>
  </channel>
</rss>
