-
Notifications
You must be signed in to change notification settings - Fork 122
FE-774: add dialog to ds #8802
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
Merged
FE-774: add dialog to ds #8802
Changes from all commits
Commits
Show all changes
36 commits
Select commit
Hold shift + click to select a range
0a77ba1
Initial pass of dialog component
alex-e-leon 33a0cba
Adjust dialog props
alex-e-leon 0d9012d
refactor dialog html slightly
alex-e-leon 1d2dc58
Switch dialog to use ds button
alex-e-leon dcbab0b
Adjust dialog spacings
alex-e-leon de702f3
Update spacing for close buttons
alex-e-leon aa63698
Rename actions to titleActions
alex-e-leon d2063d4
More dialog spacing adjustments
alex-e-leon bb22736
Add size variants
alex-e-leon 0189924
Move loading spinner into content
alex-e-leon 9bbdacf
Dialog loading styles
alex-e-leon 809ce22
More dialog loading style tweaks
alex-e-leon d380127
Slight re-arrange of dialog styles
alex-e-leon e145ac3
Tweak xs headerless combination padding
alex-e-leon fa50423
Add overflow example
alex-e-leon 381b8af
Adjust overflowing footer action styles in dialog
alex-e-leon 86470eb
Fix dialog scroll when loading
alex-e-leon 65f0ef1
Update dialog closeOn prop
alex-e-leon 96dc092
Add custom width story
alex-e-leon f9faabf
Float close button and actions for better title wrapping
alex-e-leon be3a3f1
Extra margin tweaks for headerless variation
alex-e-leon 5ca8d78
Add stacked dialog story
alex-e-leon 5072d29
Add nesting to dialogs
alex-e-leon 8e20c1e
Remove allowBodyScroll prop from dialog
alex-e-leon a262cf3
Better scrollable area outline
alex-e-leon 5f1b197
Add transition to nested transform
alex-e-leon d717811
Remove unused data-autofocus
alex-e-leon 6a29f02
Add a changeset
alex-e-leon 172b8a5
Add plain variant to dialog
alex-e-leon 93b04b1
Add description example
alex-e-leon 2b5660f
Adjust dialog vertical centering so its slightly biased to the top
alex-e-leon 7508ed1
Switch Dialog to a Slot based api
alex-e-leon f9a12c0
Add should close on "none" with no header story example
alex-e-leon 45af63e
Switch from defaultOpen to open in ArkDialog to keep it controlled
alex-e-leon abca449
Export Dialog from main
alex-e-leon 45bfeed
Add extra useMemo to classes in dialog
alex-e-leon 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
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,5 @@ | ||
| --- | ||
| "@hashintel/ds-components": patch | ||
| --- | ||
|
|
||
| Adds a Dialog component |
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
354 changes: 354 additions & 0 deletions
354
libs/@hashintel/ds-components/src/components/Dialog/dialog.recipe.ts
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,354 @@ | ||
| import { dialogAnatomy } from "@ark-ui/react/anatomy"; | ||
|
|
||
| import { sva } from "@hashintel/ds-helpers/css"; | ||
|
|
||
| export const styles = sva({ | ||
| className: "dialog", | ||
| slots: dialogAnatomy | ||
| .extendWith( | ||
| "stackRoot", | ||
| "header", | ||
| "titleIcon", | ||
| "headerActions", | ||
| "headerRight", | ||
| "hasCustomHeader", | ||
| "body", | ||
| "footer", | ||
| "footerActions", | ||
| "footerSecondaryActions", | ||
| "closeButton", | ||
| "loadingOverlay", | ||
| "loadingSpinner", | ||
| ) | ||
| .keys(), | ||
| base: { | ||
| stackRoot: { | ||
| display: "contents", | ||
| // Hide the backdrop of any dialog that has a nested dialog above it so | ||
| // the overlay doesn't darken cumulatively as the stack grows. | ||
| '&:has([data-scope="dialog"][data-part="content"][data-has-nested]) [data-scope="dialog"][data-part="backdrop"]': | ||
| { | ||
| visibility: "hidden", | ||
| }, | ||
| }, | ||
| backdrop: { | ||
| background: "black.a60", | ||
| position: "fixed", | ||
| inset: "0", | ||
| width: "[100dvw]", | ||
| height: "[100dvh]", | ||
| zIndex: "zIndex.modal", | ||
| _open: { | ||
| animationName: "fadeIn", | ||
| animationDuration: "normal", | ||
| }, | ||
| _closed: { | ||
| animationName: "fadeOut", | ||
| animationDuration: "fast", | ||
| }, | ||
| }, | ||
| positioner: { | ||
| display: "flex", | ||
| flexDirection: "column", | ||
| alignItems: "center", | ||
| justifyContent: "center", | ||
| position: "fixed", | ||
| inset: "0", | ||
| width: "[100dvw]", | ||
| height: "[100dvh]", | ||
| overflow: "auto", | ||
| overscrollBehaviorY: "none", | ||
| zIndex: "zIndex.modal", | ||
| padding: "4", | ||
| // Bias the dialog slightly above center: spacers split free vertical | ||
| // space 35/65 and shrink to 0 when the content fills the viewport. | ||
| _before: { | ||
| content: '""', | ||
| flex: "[38 1 0]", | ||
| }, | ||
| _after: { | ||
| content: '""', | ||
| flex: "[62 1 0]", | ||
| }, | ||
| }, | ||
| content: { | ||
| "--dialog-horizontal-padding": "var(--spacing-5\\.5)", | ||
| "--dialog-top-padding": "var(--spacing-4)", | ||
| "--dialog-close-button-gap": "var(--spacing-2)", | ||
| position: "relative", | ||
| display: "flex", | ||
| flexDirection: "column", | ||
| width: "[100%]", | ||
| maxHeight: "[calc(100dvh - 2rem)]", | ||
| outline: "none", | ||
| // boxShadow: | ||
| // "[0px 0px 1px 0px rgba(0,0,0,0.02), 0px 1px 1px -0.5px rgba(0,0,0,0.04), 0px 6px 6px -3px rgba(0,0,0,0.04), 0px 12px 12px -6px rgba(0,0,0,0.03), 0px 24px 24px -12px rgba(0,0,0,0.02)]", | ||
| boxShadow: "[0 10px 40px rgba(0, 0, 0, 0.2)]", | ||
| borderRadius: "xl", | ||
| backgroundColor: "neutral.s10", | ||
| padding: "1", | ||
|
|
||
| _open: { | ||
| animationName: "fadeIn", | ||
| animationDuration: "normal", | ||
| }, | ||
| _closed: { | ||
| animationName: "fadeOut", | ||
| animationDuration: "fast", | ||
| }, | ||
| // When another dialog is opened on top, shift this one up-and-left by | ||
| // 30px per layer above it so the stack reads visually. | ||
| "&[data-has-nested]": { | ||
| transition: "[transform 0.10s ease]", | ||
| transform: | ||
| "translate(calc(var(--nested-layer-count) * -22px), calc(var(--nested-layer-count) * -22px))", | ||
| }, | ||
| }, | ||
| header: { | ||
| flex: "[0 0 auto]", | ||
| backgroundColor: "white", | ||
| border: "[1px solid {colors.neutral.s50}]", | ||
| borderTopRadius: "lg", | ||
| borderBottom: "[1px solid {colors.neutral.s30}]", | ||
| paddingX: "[var(--dialog-horizontal-padding)]", | ||
| paddingTop: "[var(--dialog-top-padding)]", | ||
| paddingBottom: "3.5", | ||
| }, | ||
| hasCustomHeader: { | ||
| display: "flex", | ||
| alignItems: "flex-start", | ||
| gap: "2", | ||
| flex: "[1 1 auto]", | ||
| minWidth: "0", | ||
| }, | ||
| titleIcon: { | ||
| float: "start", | ||
| marginLeft: "-0.5", | ||
| marginRight: "2", | ||
| color: "neutral.s90", | ||
| flex: "[0 0 auto]", | ||
| backgroundColor: "neutral.s25", | ||
| borderRadius: "full", | ||
| padding: "1", | ||
| alignSelf: "flex-start", | ||
| top: "[1.5px]", | ||
| position: "relative", | ||
| }, | ||
| title: { | ||
| display: "inline", | ||
| fontWeight: "semibold", | ||
| textStyle: "lg", | ||
| color: "fg.body", | ||
| }, | ||
| description: { | ||
| color: "fg.muted", | ||
| textStyle: "sm", | ||
| marginTop: "-0.5", | ||
| }, | ||
| headerRight: { | ||
| float: "end", | ||
| display: "flex", | ||
| alignItems: "center", | ||
| gap: "[1px]", | ||
| }, | ||
| headerActions: { | ||
| display: "flex", | ||
| marginLeft: "auto", | ||
| alignItems: "center", | ||
| gap: "[1px]", | ||
| flex: "[0 0 auto]", | ||
| marginTop: | ||
| "[calc(var(--dialog-top-padding) * -1 + var(--dialog-close-button-gap))]", | ||
| }, | ||
| body: { | ||
| position: "relative", | ||
| flex: "[1 1 auto]", | ||
| minHeight: "0", | ||
| overflow: "auto", | ||
| background: "white", | ||
| border: "[1px solid {colors.neutral.s50}]", | ||
| borderTop: "none", | ||
| color: "fg.body", | ||
| textStyle: "sm", | ||
| paddingX: "[var(--dialog-horizontal-padding)]", | ||
| paddingTop: "4", | ||
| paddingBottom: "5", | ||
| // While loading, lock the body's scroll so the absolutely-positioned | ||
| // overlay stays pinned to the visible area instead of riding the | ||
| // scrolled content. | ||
| '[aria-busy="true"] &': { | ||
| overflow: "hidden", | ||
| }, | ||
| _focusVisible: { | ||
| outlineColor: "neutral.a50", | ||
| }, | ||
| }, | ||
| footer: { | ||
| flex: "[0 0 auto]", | ||
| display: "flex", | ||
| alignItems: "flex-start", | ||
| justifyContent: "space-between", | ||
| gap: "3", | ||
| paddingX: "[var(--dialog-horizontal-padding)]", | ||
| paddingTop: "3.5", | ||
| paddingBottom: "3", | ||
| }, | ||
| footerActions: { | ||
| display: "flex", | ||
| flexWrap: "wrap", | ||
| justifyContent: "flex-end", | ||
| alignItems: "center", | ||
| gap: "2", | ||
| marginLeft: "auto", | ||
| }, | ||
| footerSecondaryActions: { | ||
| display: "flex", | ||
| flexWrap: "wrap", | ||
| alignItems: "center", | ||
| gap: "2", | ||
| }, | ||
| closeButton: { | ||
| flex: "[0 0 auto]", | ||
| marginLeft: "auto", | ||
| float: "end", | ||
| position: "relative", | ||
| zIndex: "1", | ||
| marginTop: | ||
| "[calc(var(--dialog-top-padding) * -1 + var(--dialog-close-button-gap))]", | ||
| marginRight: | ||
| "[calc(var(--dialog-horizontal-padding) * -1 + var(--dialog-close-button-gap))]", | ||
| }, | ||
| loadingOverlay: { | ||
| position: "absolute", | ||
| inset: "0", | ||
| display: "flex", | ||
| alignItems: "center", | ||
| justifyContent: "center", | ||
| background: "[rgba(255, 255, 255, 0.88)]", | ||
| zIndex: "1", | ||
| borderRadius: "[inherit]", | ||
| }, | ||
| loadingSpinner: { | ||
| width: "[auto !important]", | ||
| aspectRatio: "1", | ||
| maxHeight: "[60%]", | ||
| color: "black", | ||
| }, | ||
| }, | ||
| variants: { | ||
| size: { | ||
| xs: { | ||
| content: { | ||
| maxWidth: "[400px]", | ||
| "--dialog-horizontal-padding": "var(--spacing-4)", | ||
| "--dialog-top-padding": "var(--spacing-3\\.5)", | ||
| }, | ||
| header: { | ||
| paddingBottom: "3", | ||
| }, | ||
| body: { | ||
| paddingTop: "4", | ||
| paddingBottom: "4.5", | ||
| }, | ||
| footer: { | ||
| paddingTop: "3", | ||
| paddingBottom: "2.5", | ||
| }, | ||
| }, | ||
| sm: { | ||
| content: { maxWidth: "[520px]" }, | ||
| loadingSpinner: { height: "[38px !important]" }, | ||
| }, | ||
| md: { | ||
| content: { maxWidth: "[640px]" }, | ||
| loadingSpinner: { height: "[40px !important]" }, | ||
| }, | ||
| lg: { | ||
| content: { maxWidth: "[860px]" }, | ||
| loadingSpinner: { | ||
| height: "[45px !important]", | ||
| color: "neutral.s115", | ||
| }, | ||
| }, | ||
| xl: { | ||
| content: { maxWidth: "[1060px]" }, | ||
| loadingSpinner: { | ||
| height: "[50px !important]", | ||
| color: "neutral.s115", | ||
| }, | ||
| }, | ||
| fullScreen: { | ||
| positioner: { padding: "0" }, | ||
| content: { | ||
| maxWidth: "[100dvw]", | ||
| width: "[100dvw]", | ||
| height: "[100dvh]", | ||
| maxHeight: "[100dvh]", | ||
| borderRadius: "[0]", | ||
| }, | ||
| loadingSpinner: { | ||
| height: "[50px !important]", | ||
| color: "neutral.s110", | ||
| }, | ||
| }, | ||
| }, | ||
| variant: { | ||
| partitionedFooter: { | ||
| body: { | ||
| borderBottomRadius: "lg", | ||
| }, | ||
| }, | ||
| plain: { | ||
| header: { | ||
| borderBottomColor: "neutral.s20", | ||
| }, | ||
| body: { | ||
| borderBottom: "none", | ||
| }, | ||
| footer: { | ||
| backgroundColor: "white", | ||
| border: "[1px solid {colors.neutral.s50}]", | ||
| borderBottomRadius: "lg", | ||
| borderTop: "[1px solid {colors.neutral.s20}]", | ||
| }, | ||
| }, | ||
| }, | ||
| hasIcon: { | ||
| true: { | ||
| description: { marginTop: "0.5" }, | ||
| }, | ||
| }, | ||
| headerless: { | ||
| true: { | ||
| header: { | ||
| paddingBottom: "0", | ||
| borderBottom: "none", | ||
| }, | ||
| closeButton: { | ||
| marginBottom: "-1.5", | ||
| }, | ||
| body: { | ||
| paddingTop: "0", | ||
| paddingBottom: "6", | ||
| }, | ||
| }, | ||
| }, | ||
| }, | ||
| compoundVariants: [ | ||
| { | ||
| headerless: true, | ||
| size: "xs", | ||
| css: { | ||
| header: { | ||
| paddingBottom: "0", | ||
| }, | ||
| body: { | ||
| paddingBottom: "5", | ||
| }, | ||
| }, | ||
| }, | ||
| ], | ||
| defaultVariants: { | ||
| size: "md", | ||
| }, | ||
| }); | ||
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.