diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..6ab5b04 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +shamefullyHoist=true diff --git a/content/articles/2025-09-15-smooth-scrolling.md b/content/articles/2025-09-15-smooth-scrolling.md new file mode 100644 index 0000000..96d3de9 --- /dev/null +++ b/content/articles/2025-09-15-smooth-scrolling.md @@ -0,0 +1,39 @@ +--- +title: Smooth Scrolling in Agentic Chat Interfaces +date: 2025-09-15 +coverImage: + author: mariosant + url: "/agentic-ui.png" +--- + +When building conversational UIs, small interaction details can make a huge difference in how natural the experience feels. Recently, while working on an agentic chat interface, I ran into a deceptively simple requirement: + +Whenever the user submits a question, the viewport should scroll to that question, position it neatly at the top, and then let the user read the agent’s response at their own pace. + +It sounds straightforward, but the implementation had a few subtle challenges. + +## The Core Challenge + +Most chat apps scroll new messages to the bottom, where they stack endlessly. For this interface, I wanted something more intentional: + +* The user’s own question should appear at the top of the viewport. +* There should be extra breathing room below it so the agent’s reply flows in naturally. +* That extra whitespace shouldn’t stick around forever - otherwise the layout starts looking broken. + +## Creating the Right Spacing + +To achieve the temporary space effect, I leaned on modern CSS units like viewport height (vh) and dynamic CSS variables. The idea was simple: whenever the user sends a question, create some space at the bottom of the chat, which effectively pushes their question to the top of the screen. + +From a user perspective, this feels intentional: their message takes center stage, while the agent’s answer appears in a comfortable, readable position just below. + +## Knowing When to Remove It + +The real trick was deciding when to get rid of that artificial space. Leaving it there permanently made the UI look odd, as if something was missing below the messages. + +This is where the Intersection Observer API came into play. By watching a small invisible element placed in that whitespace, the system could detect when the user scrolled and the space was no longer visible. At that moment, the extra space was removed - restoring the chat to a normal flow. + +## Why This Matters + +This kind of interaction is easy to overlook, but it shapes how people experience a conversational product. Instead of feeling like a chat feed bolted onto a webpage, the interface feels deliberate and respectful of the user’s focus. + +By combining viewport-relative layout techniques with scroll-aware cleanup logic, I was able to create a chat UI that feels smooth, intentional, and more human. diff --git a/pages/articles/[...slug].vue b/pages/articles/[...slug].vue index db8c8b5..659265a 100644 --- a/pages/articles/[...slug].vue +++ b/pages/articles/[...slug].vue @@ -42,6 +42,7 @@ const { data: article } = useAsyncData(path, async () => { class="rounded-lg" />