-
Notifications
You must be signed in to change notification settings - Fork 504
dbeaver/pro#5232 [CB] Trap Focus In the Right Panel #3952
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Wroud
merged 59 commits into
devel
from
5232-cb-6326-add-focus-trap-component-from-ui-kit-for-side-panel-to-prevent-focus-escaping-the-panel
Jan 8, 2026
Merged
Changes from all commits
Commits
Show all changes
59 commits
Select commit
Hold shift + click to select a range
90d5b38
dbeaver/pro#5232 feat: add Dialog component to UI-kit
SychevAndrey 716929d
dbeaver/pro#5232 feat: add slide variant for Dialog component
SychevAndrey 31e47e2
dbeaver/pro#5232 refactor: dialog backdrop component
SychevAndrey 7dbeaf0
dbeaver/pro#5232 feat: use dialog component for side panel to prevent…
SychevAndrey 401e189
dbeaver/pro#5232 feat: add DialogHeader, DialogBody, and DialogFooter…
SychevAndrey b31f246
dbeaver/pro#5232 feat: add Storysource addon to Storybook configuration
SychevAndrey c1d6027
dbeaver/pro#5232 refactor: use ui-kit dialog for CommonDialog impleme…
SychevAndrey ad889f7
dbeaver/pro#5232 feat: add animated prop to Dialog component to contr…
SychevAndrey 3375f0a
dbeaver/pro#5232 refactor: remove dialog animation for side panel
SychevAndrey 5303196
dbeaver/pro#5232 refactor: remove unused backdrop and focus managemen…
SychevAndrey b0f889e
dbeaver/pro#5232 style: adjust dialog padding and size for large variant
SychevAndrey cefd346
dbeaver/pro#5232 feat: add dialog to admin part implementation
SychevAndrey 6f393cc
dbeaver/pro#5232 fix: remove autofocus prop from CommonDialogWrapper …
SychevAndrey 48aadde
dbeaver/pro#5232 style: correct apostrophe in label text for NestedDi…
SychevAndrey 69cb56b
dbeaver/pro#5232 fix: update dialog component styles for improved acc…
SychevAndrey 3ca2cf1
dbeaver/pro#5232 refactor: add DialogElement component to get rid of …
SychevAndrey e5960a0
dbeaver/pro#5232 fix: correct min-width for large fixedWidth dialog size
SychevAndrey 1811d90
dbeaver/pro#5232 refactor: update DialogElement properties for improv…
SychevAndrey 33293b1
dbeaver/pro#5232 fix: use l10n for DialogElement close buttons
SychevAndrey fa02dea
dbeaver/pro#5232 refactor: update DialogElement to be a modal to trap…
SychevAndrey 6d2b2ed
dbeaver/pro#5232 refactor: remove unmountOnHide prop from CommonDialo…
SychevAndrey a540197
dbeaver/pro#5232 feat: return ESC hotkey handling in SlideBox
SychevAndrey 16f84ce
dbeaver/pro#5232 feat: make background panel inert to make focus neve…
SychevAndrey fcf394f
dbeaver/pro#5232 feat: add SlidePanel component to replace DialogElem…
SychevAndrey c13138e
dbeaver/pro#5232 feat: add inert prop to SlideElement for focus trapp…
SychevAndrey dc1aeb3
dbeaver/pro#5232 feat: pass onClose handler to SlideBox to activate h…
SychevAndrey c750898
dbeaver/pro#5232 style: return to initial state to avoid redundant diffs
SychevAndrey 6b9fa46
dbeaver/pro#5232 style: update copyright year in SlideElement.module.css
SychevAndrey a24e915
dbeaver/pro#5232 chore: remove ui-kit dependency from package.json an…
SychevAndrey 471753c
dbeaver/pro#5232 build: update @storybook/addon-storysource dependenc…
SychevAndrey c1be619
dbeaver/pro#5232 build: update @storybook/addon-storysource dependenc…
SychevAndrey 12e0ad3
Merge branch 'devel' into 5232-cb-6326-add-focus-trap-component-from-…
dariamarutkina e93fb04
dbeaver/pro#5232 style: remove border styles from dialog header and f…
SychevAndrey 6d45d03
dbeaver/pro#5232 fix: update hover background color for icon button
SychevAndrey 2e11cf2
dbeaver/pro#5232 feat: move focus from driver dialog to panel when ap…
SychevAndrey 05f2e34
Merge branch 'devel' into 5232-cb-6326-add-focus-trap-component-from-…
mr-anton-t 63d10d3
Merge branch 'devel' into 5232-cb-6326-add-focus-trap-component-from-…
EvgeniaBzzz 8e12248
Merge branch 'devel' into 5232-cb-6326-add-focus-trap-component-from-…
EvgeniaBzzz b31818f
dbeaver/pro#6326 fix: large window size
SychevAndrey 3662cb7
dbeaver/pro#5232 fix: update focus on hide logic
SychevAndrey cd61a9a
dbeaver/pro#5232 fix: update hover and focus styles for icon button i…
SychevAndrey 9aec4df
dbeaver/pro#5232 feat: return back the common backdrop, replace commo…
SychevAndrey fb0536e
dbeaver/pro#5232 fix: replace useFocus by dialog's initial focus in R…
SychevAndrey 3dc8778
Merge branch 'devel' into 5232-cb-6326-add-focus-trap-component-from-…
SychevAndrey 48b98cb
dbeaver/pro#5232 build: update deps after merge
SychevAndrey 443d362
dbeaver/pro#5232 refactor: use constant for button id
SychevAndrey 15b79f2
dbeaver/pro#5232 feat: add Loader component to DialogsPortal
SychevAndrey 6039f84
Merge branch 'devel' into 5232-cb-6326-add-focus-trap-component-from-…
mr-anton-t f2f247f
dbeaver/pro#5232 refactor: update Dialog component to use semantic HT…
SychevAndrey 5bf2404
dbeaver/pro#5232 fix: gap in footer of dialogs
SychevAndrey 7ee771c
Merge branch 'devel' into 5232-cb-6326-add-focus-trap-component-from-…
mr-anton-t e41ffe2
dbeaver/pro#5232 feat: focus input initially in New Folder dialog
SychevAndrey 4b7b2e6
dbeaver/pro#5232 feat: add autoFocusOnShow prop to CommonDialogWrappe…
SychevAndrey 3753d6d
Merge branch 'devel' into 5232-cb-6326-add-focus-trap-component-from-…
mr-anton-t 15be0a5
dbeaver/pro#5232 fix: padding for CommonDialogFooter
SychevAndrey 910d9ab
Merge branch 'devel' into 5232-cb-6326-add-focus-trap-component-from-…
mr-anton-t 99a90cd
Merge branch 'devel' into 5232-cb-6326-add-focus-trap-component-from-…
mr-anton-t d5a3f61
Merge branch 'devel' into 5232-cb-6326-add-focus-trap-component-from-…
dariamarutkina d71a57d
Merge branch 'devel' into 5232-cb-6326-add-focus-trap-component-from-…
dariamarutkina File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
213 changes: 213 additions & 0 deletions
213
webapp/common-react/@dbeaver/ui-kit/src/Dialog/Dialog.css
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,213 @@ | ||
| @import './_base.css'; | ||
|
|
||
| @layer base { | ||
| .dbv-kit-dialog__backdrop { | ||
| background-color: transparent; | ||
| opacity: 0; | ||
| transition-property: opacity, background-color; | ||
| transition-timing-function: ease-in-out; | ||
| transition-duration: 100ms; | ||
|
|
||
| &[data-enter] { | ||
| opacity: 1; | ||
| background-color: var(--dbv-kit-dialog-backdrop-background); | ||
| } | ||
|
|
||
| &:not([data-enter]) { | ||
| opacity: 0; | ||
| } | ||
|
|
||
| &[data-animated='false'] { | ||
| transition: none !important; | ||
| opacity: 1; | ||
| background-color: var(--dbv-kit-dialog-backdrop-background); | ||
| } | ||
|
|
||
| @media (prefers-reduced-motion: reduce) { | ||
| transition: none !important; | ||
| opacity: 1; | ||
| background-color: var(--dbv-kit-dialog-backdrop-background); | ||
| } | ||
| } | ||
|
|
||
| .dbv-kit-dialog { | ||
| position: fixed; | ||
| top: 50%; | ||
| left: 50%; | ||
| transform: translate(-50%, -50%); | ||
| z-index: 1000; | ||
| display: flex; | ||
| flex-direction: column; | ||
| padding: 0; | ||
| background-color: var(--dbv-kit-dialog-content-background); | ||
| color: var(--dbv-kit-dialog-content-foreground); | ||
| border: none; | ||
| border-radius: var(--dbv-kit-dialog-content-border-radius); | ||
| box-shadow: var(--dbv-kit-dialog-content-shadow); | ||
| outline: 0; | ||
| overflow: hidden; | ||
| margin: 0; | ||
| max-width: var(--dbv-kit-dialog-large-width); | ||
|
|
||
| @media (prefers-reduced-motion: no-preference) { | ||
| opacity: 0; | ||
| transform: translate(-50%, -50%) scale(0.95); | ||
| transition-property: opacity, transform; | ||
| transition-timing-function: ease-in-out; | ||
| transition-duration: 150ms; | ||
|
|
||
| &:not([data-enter]) { | ||
| opacity: 0; | ||
| transform: translate(-50%, -50%) scale(0.95); | ||
| } | ||
| &[data-enter] { | ||
| opacity: 1; | ||
| transform: translate(-50%, -50%) scale(1); | ||
| } | ||
|
|
||
| &[data-animated='false'] { | ||
| transition: none !important; | ||
| opacity: 1; | ||
| transform: translate(-50%, -50%) scale(1); | ||
| } | ||
| } | ||
|
|
||
| @media (prefers-reduced-motion: reduce) { | ||
| transition: none !important; | ||
| opacity: 1; | ||
| transform: translate(-50%, -50%) scale(1); | ||
| } | ||
|
|
||
| &[data-size='small'] { | ||
| min-width: var(--dbv-kit-dialog-small-width); | ||
| min-height: var(--dbv-kit-dialog-small-height); | ||
| max-height: max(var(--app-height, 100vh) - 48px, var(--dbv-kit-dialog-small-height)); | ||
| } | ||
|
|
||
| &[data-size='medium'] { | ||
| min-width: var(--dbv-kit-dialog-medium-width); | ||
| min-height: var(--dbv-kit-dialog-medium-height); | ||
| max-height: max(var(--app-height, 100vh) - 48px, var(--dbv-kit-dialog-medium-height)); | ||
| } | ||
|
|
||
| &[data-size='large'] { | ||
| min-width: var(--dbv-kit-dialog-large-width); | ||
| min-height: var(--dbv-kit-dialog-large-height); | ||
| max-height: max(var(--app-height, 100vh) - 48px, var(--dbv-kit-dialog-large-height)); | ||
| } | ||
|
|
||
| &[data-size='free'] { | ||
| min-width: auto; | ||
| min-height: auto; | ||
| max-width: calc(100vw - 48px); | ||
| max-height: calc(100vh - 48px); | ||
| } | ||
|
|
||
| /* Slide variant (side panel from right) */ | ||
| &[data-variant='slide'] { | ||
| position: absolute; | ||
| top: 0; | ||
| left: 0; | ||
| right: 0; | ||
| bottom: 0; | ||
| transform: translateX(100%); | ||
| width: 100%; | ||
| max-width: none; | ||
| height: 100%; | ||
| max-height: 100%; | ||
| min-width: 0; | ||
| min-height: 0; | ||
| border-radius: 0; | ||
|
|
||
| @media (prefers-reduced-motion: no-preference) { | ||
| opacity: 1; | ||
| transition-property: transform; | ||
| transition-timing-function: var(--dbv-kit-dialog-slide-transition-timing); | ||
| transition-duration: var(--dbv-kit-dialog-slide-transition-duration); | ||
|
|
||
| &[data-enter] { | ||
| transform: translateX(0); | ||
| } | ||
|
|
||
| &:not([data-enter]) { | ||
| transform: translateX(100%); | ||
| } | ||
|
|
||
| &[data-animated='false'] { | ||
| transition: none !important; | ||
| transform: translateX(0); | ||
| } | ||
| } | ||
|
|
||
| @media (prefers-reduced-motion: reduce) { | ||
| transition: none !important; | ||
| opacity: 1; | ||
| transform: translateX(0); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| .dbv-kit-dialog__header { | ||
| flex-shrink: 0; | ||
| padding: var(--dbv-kit-dialog-header-padding); | ||
| border-bottom: var(--dbv-kit-dialog-header-border-bottom); | ||
| } | ||
|
|
||
| .dbv-kit-dialog__body { | ||
| flex: 1 1 auto; | ||
| overflow-y: auto; | ||
| padding: var(--dbv-kit-dialog-body-padding); | ||
| } | ||
|
|
||
| .dbv-kit-dialog__footer { | ||
| flex-shrink: 0; | ||
| padding: var(--dbv-kit-dialog-footer-padding); | ||
| border-top: var(--dbv-kit-dialog-footer-border-top); | ||
| display: flex; | ||
| gap: var(--dbv-kit-dialog-footer-gap); | ||
| justify-content: flex-end; | ||
| } | ||
|
|
||
| .dbv-kit-dialog__disclosure { | ||
| background-color: var(--dbv-kit-dialog-disclosure-background); | ||
| color: var(--dbv-kit-dialog-disclosure-foreground); | ||
| } | ||
|
|
||
| .dbv-kit-dialog__heading { | ||
| margin: var(--dbv-kit-dialog-heading-margin); | ||
| font-size: var(--dbv-kit-dialog-heading-font-size); | ||
| font-weight: var(--dbv-kit-dialog-heading-font-weight); | ||
| line-height: var(--dbv-kit-dialog-heading-line-height); | ||
| color: var(--dbv-kit-dialog-heading-color); | ||
| overflow: hidden; | ||
| text-overflow: ellipsis; | ||
| white-space: nowrap; | ||
| } | ||
|
|
||
| .dbv-kit-dialog__description { | ||
| margin: var(--dbv-kit-dialog-description-margin); | ||
| font-size: var(--dbv-kit-dialog-description-font-size); | ||
| color: var(--dbv-kit-dialog-description-color); | ||
| } | ||
|
|
||
| .dbv-kit-dialog__dismiss { | ||
| background-color: var(--dbv-kit-dialog-dismiss-background); | ||
| color: var(--dbv-kit-dialog-dismiss-foreground); | ||
| padding: 0.5rem 1rem; | ||
| border-radius: 0.375rem; | ||
| border: none; | ||
| cursor: pointer; | ||
| font-weight: 500; | ||
| font-size: 0.875rem; | ||
| transition: background-color 150ms var(--tw-ease-in-out); | ||
|
|
||
| &:hover:not([aria-disabled='true']) { | ||
| background-color: var(--dbv-kit-dialog-dismiss-hover-background); | ||
| } | ||
|
|
||
| &[aria-disabled='true'] { | ||
| opacity: var(--dbv-kit-control-disabled-opacity, 0.5); | ||
| cursor: not-allowed; | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,92 @@ | ||
| /* | ||
| * CloudBeaver - Cloud Database Manager | ||
| * Copyright (C) 2020-2025 DBeaver Corp and others | ||
| * | ||
| * Licensed under the Apache License, Version 2.0. | ||
| * you may not use this file except in compliance with the License. | ||
| */ | ||
|
|
||
| import { | ||
| Dialog as AriakitDialog, | ||
| DialogDescription as AriakitDialogDescription, | ||
| DialogDisclosure as AriakitDialogDisclosure, | ||
| DialogDismiss as AriakitDialogDismiss, | ||
| DialogHeading as AriakitDialogHeading, | ||
| DialogProvider, | ||
| type DialogDescriptionProps, | ||
| type DialogDismissProps, | ||
| type DialogDisclosureProps, | ||
| type DialogHeadingProps, | ||
| type DialogProps, | ||
| type DialogProviderProps, | ||
| type DialogStore, | ||
| type DialogStoreProps, | ||
| type DialogStoreState, | ||
| useDialogContext, | ||
| useDialogStore, | ||
| } from '@ariakit/react'; | ||
| import clsx from 'clsx'; | ||
| import type { ComponentPropsWithoutRef, JSX } from 'react'; | ||
|
|
||
| import './Dialog.css'; | ||
|
|
||
| interface ExtendedDialogProps extends DialogProps { | ||
| animated?: boolean; | ||
| } | ||
|
|
||
| function Dialog({ className, backdrop, animated = true, ...props }: ExtendedDialogProps): JSX.Element { | ||
| const backdropElement = backdrop === true ? <div className="dbv-kit-dialog__backdrop" data-animated={animated} /> : backdrop; | ||
|
|
||
| return <AriakitDialog className={clsx('dbv-kit-dialog', className)} backdrop={backdropElement} data-animated={animated} {...props} />; | ||
| } | ||
|
|
||
| function DialogDisclosure({ className, ...props }: DialogDisclosureProps): JSX.Element { | ||
| return <AriakitDialogDisclosure className={clsx('dbv-kit-dialog__disclosure', className)} {...props} />; | ||
| } | ||
|
|
||
| function DialogHeader({ className, ...props }: ComponentPropsWithoutRef<'header'>): JSX.Element { | ||
| return <header className={clsx('dbv-kit-dialog__header', className)} {...props} />; | ||
| } | ||
|
|
||
| function DialogBody({ className, ...props }: ComponentPropsWithoutRef<'div'>): JSX.Element { | ||
| return <div className={clsx('dbv-kit-dialog__body', className)} {...props} />; | ||
| } | ||
|
|
||
| function DialogFooter({ className, ...props }: ComponentPropsWithoutRef<'footer'>): JSX.Element { | ||
| return <footer className={clsx('dbv-kit-dialog__footer', className)} {...props} />; | ||
| } | ||
|
|
||
| function DialogHeading({ className, ...props }: DialogHeadingProps): JSX.Element { | ||
| return <AriakitDialogHeading className={clsx('dbv-kit-dialog__heading', className)} {...props} />; | ||
| } | ||
|
|
||
| function DialogDescription({ className, ...props }: DialogDescriptionProps): JSX.Element { | ||
| return <AriakitDialogDescription className={clsx('dbv-kit-dialog__description', className)} {...props} />; | ||
| } | ||
|
|
||
| function DialogDismiss({ className, ...props }: DialogDismissProps): JSX.Element { | ||
| return <AriakitDialogDismiss className={clsx('dbv-kit-dialog__dismiss', className)} {...props} />; | ||
| } | ||
|
|
||
| export { | ||
| Dialog, | ||
| DialogDisclosure, | ||
| DialogHeader, | ||
| DialogBody, | ||
| DialogFooter, | ||
| DialogHeading, | ||
| DialogDescription, | ||
| DialogDismiss, | ||
| DialogProvider, | ||
| useDialogStore, | ||
| useDialogContext, | ||
| type ExtendedDialogProps as DialogProps, | ||
| type DialogProviderProps, | ||
| type DialogDisclosureProps, | ||
| type DialogHeadingProps, | ||
| type DialogDescriptionProps, | ||
| type DialogDismissProps, | ||
| type DialogStore, | ||
| type DialogStoreProps, | ||
| type DialogStoreState, | ||
| }; | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| @layer base { | ||
| :root { | ||
| /* Dialog container */ | ||
| --dbv-kit-dialog-content-background: #ffffff; | ||
| --dbv-kit-dialog-content-foreground: #353535; | ||
| --dbv-kit-dialog-content-border-radius: 0.25rem; | ||
| --dbv-kit-dialog-content-shadow: 0 6px 6px -3px #0003, 0 10px 14px 1px #00000024, 0 4px 18px 3px #0000001f; | ||
|
|
||
| /* Dialog layout */ | ||
| --dbv-kit-dialog-header-padding: 1rem 1.5rem; | ||
| --dbv-kit-dialog-header-border-bottom: none; | ||
| --dbv-kit-dialog-body-padding: 1.5rem; | ||
| --dbv-kit-dialog-footer-padding: 1rem 1.5rem; | ||
| --dbv-kit-dialog-footer-border-top: none; | ||
| --dbv-kit-dialog-footer-gap: 0.75rem; | ||
|
|
||
| /* Dialog sizes */ | ||
| --dbv-kit-dialog-small-width: 404px; | ||
| --dbv-kit-dialog-small-height: 262px; | ||
| --dbv-kit-dialog-medium-width: 576px; | ||
| --dbv-kit-dialog-medium-height: 374px; | ||
| --dbv-kit-dialog-large-width: 720px; | ||
| --dbv-kit-dialog-large-height: 468px; | ||
| --dbv-kit-dialog-max-width: 720px; | ||
|
|
||
| /* Slide variant (side panel) */ | ||
| --dbv-kit-dialog-slide-transition-duration: 300ms; | ||
| --dbv-kit-dialog-slide-transition-timing: ease-in-out; | ||
|
|
||
| /* Backdrop */ | ||
| --dbv-kit-dialog-backdrop-background: #0000007a; | ||
|
|
||
| /* Heading */ | ||
| --dbv-kit-dialog-heading-margin: 0; | ||
| --dbv-kit-dialog-heading-font-size: 1.25rem; | ||
| --dbv-kit-dialog-heading-font-weight: 400; | ||
| --dbv-kit-dialog-heading-line-height: 2rem; | ||
| --dbv-kit-dialog-heading-color: var(--dbv-kit-dialog-content-foreground); | ||
|
|
||
| /* Description */ | ||
| --dbv-kit-dialog-description-margin: 0; | ||
| --dbv-kit-dialog-description-font-size: 0.875rem; | ||
| --dbv-kit-dialog-description-color: inherit; | ||
|
|
||
| /* Disclosure */ | ||
| --dbv-kit-dialog-disclosure-background: transparent; | ||
| --dbv-kit-dialog-disclosure-foreground: inherit; | ||
|
|
||
| /* Dismiss */ | ||
| --dbv-kit-dialog-dismiss-background: #f2f2f2; | ||
| --dbv-kit-dialog-dismiss-foreground: #353535; | ||
| --dbv-kit-dialog-dismiss-hover-background: #e5e5e5; | ||
| } | ||
|
|
||
| @media (prefers-color-scheme: dark) { | ||
| :root { | ||
| --dbv-kit-dialog-content-background: hsl(240deg, 10%, 16%); | ||
| --dbv-kit-dialog-content-foreground: #ffffff; | ||
| --dbv-kit-dialog-header-border-bottom: none; | ||
| --dbv-kit-dialog-footer-border-top: none; | ||
| --dbv-kit-dialog-dismiss-background: hsl(240deg, 10%, 18%); | ||
| --dbv-kit-dialog-dismiss-foreground: #cbcbcb; | ||
| --dbv-kit-dialog-dismiss-hover-background: hsl(240deg, 10%, 22%); | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.