Skip to content

Dialog#1723

Merged
shinokada merged 5 commits intothemesberg:mainfrom
jjagielka:dialog
Aug 14, 2025
Merged

Dialog#1723
shinokada merged 5 commits intothemesberg:mainfrom
jjagielka:dialog

Conversation

@jjagielka
Copy link
Copy Markdown
Contributor

@jjagielka jjagielka commented Aug 14, 2025

Closes #

📑 Description

Corrections to new Drawer implementation

  • dismissable defaults to false
  • non-modal drawer has fixed position by default
  • removal of stray <div> thanks to new click outside implementation

Status

  • Not Completed
  • Completed

✅ Checks

  • My pull request adheres to the code style of this project
  • My code requires changes to the documentation
  • I have updated the documentation and api-check directory as required
  • All the tests and check have passed by running pnpm check && pnpm test:e2e
  • My pull request is based on the latest commit (not the npm version).
  • I have checked the page with https://validator.unl.edu/

ℹ Additional Information

Summary by CodeRabbit

  • New Features

    • Drawer gains a dismissible mode and explicit modal option to control overlay/behavior; outside-click behavior can be configured.
  • Bug Fixes

    • Dialog outside-click handling improved: clicks inside dialog content no longer close it; buttons still trigger auto-close appropriately.
    • Removed an unnecessary spacer that affected dialog layout.
  • Style

    • Drawer sizing relaxed (no viewport constraints by default); top/bottom placements enforce full-width.
    • Theming aligned between Drawer, Modal, and Dialog for consistent visuals.

@vercel
Copy link
Copy Markdown

vercel bot commented Aug 14, 2025

@jjagielka is attempting to deploy a commit to the Themesberg Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Aug 14, 2025

Walkthrough

Updates dialog outside-click handling to detect clicks inside dialog content, adds optional form wrapping when open, removes a placeholder layout element, introduces backward-compatible Drawer props (hidden, activateClickOutside), adds dismissable/outsideclose wiring and modal forwarding, and adjusts Drawer/Modal theme imports and variants.

Changes

Cohort / File(s) Summary
Dialog behavior & DOM
src/lib/dialog/Dialog.svelte
Outside-click handler now computes content rect and cancels only when outsideclose is true and the click is outside content; preserves autoclose button behavior; when open and form is true wraps content in <form method="dialog">; removes placeholder layout <div>; no exported signature changes.
Drawer props, wiring & render
src/lib/drawer/Drawer.svelte, src/lib/types.ts
Adds deprecated back-compat props hidden and activateClickOutside, new dismissable and optional outsideclose; maps activateClickOutsideoutsideclose if unset; keeps hiddenopen sync; forwards dismissable/outsideclose to Dialog; passes modal: restProps.modal into drawer construction; updates DrawerProps typings.
Drawer theme adjustments
src/lib/drawer/theme.ts
Imports dialog theme from dialog/theme, changes slots.base to p-4 max-h-none max-w-none, forces full width for top/bottom placements (!w-full), and adds a new modal variant controlling base classes.
Modal theme import
src/lib/modal/theme.ts
Switches import to $lib/dialog/theme so Modal extends themed dialog variants; no signature changes.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant DOM
  participant Dialog
  participant Content

  User->>DOM: click
  DOM->>Dialog: _onclick(MouseEvent)
  Dialog->>Content: getBoundingClientRect()
  Dialog->>Dialog: compute clickedInContent (point vs rect)
  alt outsideclose && !clickedInContent
    Dialog->>Dialog: cancel(dlg)
  else if autoclose && target is button && !permanent
    Dialog->>Dialog: close(dlg)
  else
    Dialog->>Dialog: no-op
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~35 minutes

Possibly related PRs

  • Drawer as Dialog #1715 — touches Dialog and Drawer with related outside-click, dismissable and prop mapping changes.
  • Modal #1668 — implements content-aware outside-click handling and optional <form method="dialog"> wrapping in related components.
  • Dialog #1665 — modifies dialog/modal close and form-handling behavior closely related to the dialog changes.

Poem

A rabbit taps the dialog’s frame,
Clicks inside and out — not the same.
Drawers learn new rules to mind,
Forms embrace the content kind.
Hop on, code — a gentler tame. 🐇✨

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these settings in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 0a510fc and b9e8569.

📒 Files selected for processing (2)
  • src/lib/drawer/Drawer.svelte (2 hunks)
  • src/lib/types.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/lib/types.ts
  • src/lib/drawer/Drawer.svelte
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Playwright and Lint
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@jjagielka
Copy link
Copy Markdown
Contributor Author

@shinokada - should we add deprecation warnings and backward compatibility?

  $effect(() => {
    if (activateClickOutside && restProps.outsideclose === undefined) restProps.outsideclose = activateClickOutside;
  });
  $effect(() => {
    open = !hidden;
  });
  $effect(() => {
    hidden = !open;
  });

Copy link
Copy Markdown
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: 2

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these settings in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 1b38747 and 536f72b.

📒 Files selected for processing (4)
  • src/lib/dialog/Dialog.svelte (2 hunks)
  • src/lib/drawer/Drawer.svelte (2 hunks)
  • src/lib/drawer/theme.ts (1 hunks)
  • src/lib/modal/theme.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/lib/drawer/theme.ts (2)
src/lib/theme/themeUtils.ts (1)
  • Classes (14-16)
src/lib/dialog/theme.ts (1)
  • dialog (6-21)
🔇 Additional comments (9)
src/lib/modal/theme.ts (1)

3-3: Switching to the themed dialog import is correct

Importing dialog from $lib/dialog/theme aligns Modal with the shared dialog theme. This is the right dependency for consistent theming.

src/lib/drawer/Drawer.svelte (2)

10-10: New dismissable prop default looks good

Exposing dismissable with a default of false matches the PR intent and avoids accidentally rendering a close button.


27-29: Forwarding modal through restProps is fine

Forwarding modal via {...restProps} and also feeding it to the theme keeps behavioral and visual variants in sync.

src/lib/drawer/theme.ts (4)

3-3: Importing the dialog theme is the right dependency

Extending from $lib/dialog/theme ensures Drawer inherits the same baseline dialog structure and slots (e.g., base/form/close).


10-11: Base slot adjustments look correct

Switching to "p-4 max-h-none max-w-none" removes artificial clamping and gives the drawer more flexibility.


16-17: Full-width top/bottom placements

Using !w-full ensures the drawer spans the viewport horizontally for top/bottom placements. Good for predictability across container contexts.


24-27: Modal variant is well-aligned with the runtime modal prop

The modal variant cleanly separates styling concerns:

  • false: "fixed inset-0" for non-modal drawers (ensures fixed positioning)
  • true: no override (inherits from dialog theme)

This pairs well with Drawer.svelte passing restProps.modal into the theme call.

src/lib/dialog/Dialog.svelte (2)

37-45: More robust outside-click detection

Using getBoundingClientRect() and client coordinates gives a reliable check for clicks outside the content area (including ::backdrop). This should behave better than strict ev.target === dlg checks across browsers.


110-119: Conditional form wrapper is correct and removes stray DOM

Wrapping content with

only when form is true is the right approach and keeps the non-form path clean.

@shinokada
Copy link
Copy Markdown
Collaborator

Yes, we should add deprecation warnings and backward compatibility.

Copy link
Copy Markdown
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: 3

♻️ Duplicate comments (2)
src/lib/drawer/Drawer.svelte (2)

31-31: Pass classes into the tv() call so slot overrides work

User-supplied slot classes are ignored if classes isn’t passed to the theme instance.

-const { base } = $derived(drawer({ placement, width, modal: restProps.modal }));
+const { base } = $derived(drawer({ placement, width, modal: restProps.modal, classes }));

44-44: Include classes?.base when computing the base slot class

Without this, consumer overrides for the base slot are dropped.

-<Dialog bind:open {transition} {dismissable} {outsideclose} transitionParams={transition_params} {...restProps} class={base({ class: clsx(theme?.base, className) })}>
+<Dialog bind:open {transition} {dismissable} {outsideclose} transitionParams={transition_params} {...restProps} class={base({ class: clsx(theme?.base, classes?.base, className) })}>
🧹 Nitpick comments (1)
src/lib/drawer/Drawer.svelte (1)

12-16: Deprecation warning messages: good addition (minor nit on wording)

Nice to warn on legacy props. Minor nit: “compability” → “compatibility” in types file. Also consider using a consistent deprecation phrasing across the codebase (“Will be removed in next minor version”) as in other components.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these settings in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 536f72b and 0a510fc.

📒 Files selected for processing (2)
  • src/lib/drawer/Drawer.svelte (2 hunks)
  • src/lib/types.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/lib/types.ts (1)
src/lib/drawer/theme.ts (1)
  • DrawerVariants (5-5)

Comment on lines +10 to +11
let { children, open = $bindable(false), hidden = $bindable(), width, dismissable = false, placement = "left", class: className, classes, transitionParams, transition = fly, outsideclose, activateClickOutside, ...restProps }: DrawerProps = $props();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Prop typing mismatch: children isn’t declared on DrawerProps

You destructure children from $props() and render it, but DrawerProps (types.ts) doesn’t currently declare children?: Snippet. This breaks TS ergonomics.

If you accept the types change I suggested in types.ts (adding children?: Snippet), this resolves cleanly.


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo ">>> Locate Drawer.svelte"
if command -v fd >/dev/null 2>&1; then
  drawer_path=$(fd --hidden --follow --type f Drawer.svelte | head -n1 || true)
else
  drawer_path=$(find . -type f -name Drawer.svelte | head -n1 || true)
fi
if [ -z "$drawer_path" ]; then
  echo "Drawer.svelte not found"
else
  echo "Found: $drawer_path"
  echo "---- Drawer.svelte (lines 1-160) ----"
  sed -n '1,160p' "$drawer_path"
  echo "---- Drawer.svelte (lines 1-40, showing destructuring lines around 10-11) ----"
  sed -n '1,40p' "$drawer_path"
fi

echo
echo ">>> Search for DrawerProps declaration"
# Search for likely type/interface declaration using rg if available, otherwise use grep+find
if command -v rg >/dev/null 2>&1; then
  rg --hidden -n --line-number "type\s+DrawerProps|interface\s+DrawerProps|DrawerProps\s*=" || true
else
  find . -type f -name '*.ts' -or -name '*.d.ts' | xargs grep -n --line-number -E "type\s+DrawerProps|interface\s+DrawerProps|DrawerProps\s*=" || true
fi

echo
echo ">>> If a file containing DrawerProps was found above, show the first matching file (first 240 lines)"
first_file=$( 
  if command -v rg >/dev/null 2>&1; then
    rg --hidden -n --files-with-matches -S "type\s+DrawerProps|interface\s+DrawerProps|DrawerProps\s*=" | head -n1 || true
  else
    find . -type f -name '*.ts' -or -name '*.d.ts' | xargs grep -l -E "type\s+DrawerProps|interface\s+DrawerProps|DrawerProps\s*=" | head -n1 || true
  fi
)
if [ -n "$first_file" ]; then
  echo "Found DrawerProps in: $first_file"
  sed -n '1,240p' "$first_file"
  echo
  echo "---- Search for 'children' within that file ----"
  rg -n "children" "$first_file" || grep -n "children" "$first_file" || true
else
  echo "No DrawerProps declaration found. Listing types.ts files for inspection..."
  if command -v fd >/dev/null 2>&1; then
    fd --hidden --type f types.ts || true
  else
    find . -type f -name 'types.ts' | sed -n '1,120p' || true
  fi
fi

Length of output: 21427


🏁 Script executed:

#!/bin/bash
set -euo pipefail

file="src/lib/types.ts"

echo ">>> Locate export interface DrawerProps"
rg --hidden -n "export interface DrawerProps" "$file" || true
start_line=$(rg --hidden -n "export interface DrawerProps" "$file" | cut -d: -f1 || true)

if [ -z "$start_line" ]; then
  echo "DrawerProps not found in $file"
  exit 0
fi

echo ">>> Showing DrawerProps (start at line $start_line, next 120 lines)"
sed -n "${start_line},$((start_line+120))p" "$file" || true

echo
echo ">>> Search for DialogProps declaration (to see inherited props)"
rg --hidden -n "export interface DialogProps|interface DialogProps|type DialogProps" "$file" || true
dialog_line=$(rg --hidden -n "export interface DialogProps|interface DialogProps|type DialogProps" "$file" | head -n1 | cut -d: -f1 || true)

if [ -n "$dialog_line" ]; then
  echo ">>> Showing DialogProps (start at line $dialog_line, next 200 lines)"
  sed -n "${dialog_line},$((dialog_line+200))p" "$file" || true
else
  echo "DialogProps declaration not found in $file"
fi

Length of output: 10200


Add missing children?: Snippet to DrawerProps

Drawer.svelte destructures and renders children, but DrawerProps (src/lib/types.ts) doesn't declare it — add the prop to restore correct TS ergonomics.

  • Files to update:
    • src/lib/drawer/Drawer.svelte — destructures children at ~lines 10–11 and renders it.
    • src/lib/types.ts — export interface DrawerProps at line ~571.

Suggested change (types.ts):

export interface DrawerProps extends DrawerVariants, DialogProps {
  activateClickOutside?: boolean; // for backward compability
  hidden?: boolean | null; // for backward compability
  children?: Snippet;
}
🤖 Prompt for AI Agents
In src/lib/drawer/Drawer.svelte around lines 10–11 the component destructures
and renders `children` but the DrawerProps type in src/lib/types.ts (around line
~571) does not declare `children`, causing TypeScript ergonomics to break;
update the DrawerProps interface to include an optional children?: Snippet
property (alongside existing DrawerVariants and DialogProps extensions and the
backward-compatibility props) so the prop is typed correctly and no runtime
changes are needed.

src/lib/types.ts Outdated
Comment on lines +571 to +574
export interface DrawerProps extends DrawerVariants, DialogProps {
activateClickOutside?: boolean; // for backward compability
hidden?: boolean | null; // for backward compability
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

⚠️ Potential issue

Avoid conflicting redeclaration of hidden; add deprecation JSDoc and missing children type

DrawerProps extends DialogProps, which already includes the HTML hidden attribute via HTMLDialogAttributes. Redeclaring hidden here with a different type can cause type incompatibilities and confuses semantics (your hidden is a back-compat inverse of open, not the HTML attribute). Also, children is used by Drawer.svelte but isn’t declared on DrawerProps.

Refactor to omit hidden from DialogProps, annotate deprecations, and add children?: Snippet:

-export interface DrawerProps extends DrawerVariants, DialogProps {
-  activateClickOutside?: boolean; // for backward compability
-  hidden?: boolean | null; // for backward compability
-}
+export interface DrawerProps extends DrawerVariants, Omit<DialogProps, "hidden"> {
+  /** @deprecated Use `outsideclose` instead. Will be removed in next minor version. */
+  activateClickOutside?: boolean;
+  /** @deprecated Use `open` instead. Will be removed in next minor version. */
+  hidden?: boolean | null;
+  // Drawer renders arbitrary content
+  children?: Snippet;
+}

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/lib/types.ts around lines 571-574, avoid redeclaring the HTML `hidden`
attribute by changing DrawerProps to extend Omit<DialogProps, "hidden">, add a
deprecated JSDoc on the backward-compat `hidden?: boolean | null` explaining it
is not the HTML attribute and should not be used going forward, and add the
missing children?: Snippet property (ensure Snippet is imported/available). This
preserves the DialogProps HTML `hidden`, prevents type conflict, documents
deprecation, and declares the children used by Drawer.svelte.

@shinokada
Copy link
Copy Markdown
Collaborator

Can you complete the boxes above?
My pull request adheres to the code style of this project
My code requires changes to the documentation
I have updated the documentation and api-check directory as required
All the tests and check have passed by running pnpm check && pnpm test:e2e
My pull request is based on the latest commit (not the npm version).
I have checked the page with https://validator.unl.edu/

@jjagielka
Copy link
Copy Markdown
Contributor Author

Done.

@shinokada shinokada closed this Aug 14, 2025
@shinokada shinokada reopened this Aug 14, 2025
@shinokada shinokada merged commit 33e2291 into themesberg:main Aug 14, 2025
0 of 3 checks passed
@jjagielka jjagielka deleted the dialog branch August 14, 2025 14:11
@coderabbitai coderabbitai bot mentioned this pull request Aug 17, 2025
8 tasks
@shinokada
Copy link
Copy Markdown
Collaborator

When I run pnpm check I get this error:

Interface 'DrawerProps' cannot simultaneously extend types 'DrawerVariants' and 'Omit<DialogProps, "hidden">'.
Named property 'classes' of types 'DrawerVariants' and 'Omit<DialogProps, "hidden">' are not identical.ts(2320)
interface DrawerProps

@shinokada
Copy link
Copy Markdown
Collaborator

My VSCode shows this type error on requestClose in Dialog.svelte: Property 'requestClose' does not exist on type 'HTMLDialogElement'.ts(2339)
any

image

@jjagielka
Copy link
Copy Markdown
Contributor Author

When I run pnpm check I get this error:

Interface 'DrawerProps' cannot simultaneously extend types 'DrawerVariants' and 'Omit<DialogProps, "hidden">'. Named property 'classes' of types 'DrawerVariants' and 'Omit<DialogProps, "hidden">' are not identical.ts(2320) interface DrawerProps

Small typo. I will correct it in the next PR.

@jjagielka
Copy link
Copy Markdown
Contributor Author

My VSCode shows this type error on requestClose in Dialog.svelte: Property 'requestClose' does not exist on type 'HTMLDialogElement'.ts(2339) any

requestClose is a new feature not supported by all browser yet, and not defined in typescript yet. That's why you can see:

if (typeof dlg.requestClose === "function") ...

we can add // @ts-ignore if you want.

@coderabbitai coderabbitai bot mentioned this pull request Dec 31, 2025
15 tasks
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.

2 participants