Skip to content
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

docs(Drawer): add API decision #2009

Merged
merged 12 commits into from
Feb 21, 2024
Merged

docs(Drawer): add API decision #2009

merged 12 commits into from
Feb 21, 2024

Conversation

saurabhdaware
Copy link
Member

@saurabhdaware saurabhdaware commented Feb 8, 2024

Copy link

changeset-bot bot commented Feb 8, 2024

⚠️ No Changeset found

Latest commit: 7831003

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Copy link
Contributor

github-actions bot commented Feb 8, 2024

✅ PR title follows Conventional Commits specification.

@saurabhdaware saurabhdaware marked this pull request as ready for review February 8, 2024 05:42
Copy link

codesandbox-ci bot commented Feb 8, 2024

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit 7831003:

Sandbox Source
razorpay/blade: basic Configuration

*
* Also decides if clicking outside on overlay closes the drawer or not
*/
showOverlay?: boolean;
Copy link
Collaborator

Choose a reason for hiding this comment

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

So overlay is optional? Won't that look weird? What is the use case?

Copy link
Member Author

Choose a reason for hiding this comment

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

We have usecases where Drawer is used for Announcements. In those cases, users should still be able to interact with dashboard items even with Drawer open so we cant show overlay or hide drawer on clicking outside.

image

Copy link
Member

Choose a reason for hiding this comment

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

when overlay is disabled, does the area outside the drawer remain interactive?

Copy link
Member Author

Choose a reason for hiding this comment

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

yes

Copy link
Collaborator

Choose a reason for hiding this comment

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

does the area outside the drawer remain interactive

We should ideally control this with a new prop like shouldDismissOnClickOutside


<img width="500px" src="./2024-02-07-20-04-07.png" alt="Drawer Figma Skeleton">

## Design
Copy link
Collaborator

Choose a reason for hiding this comment

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

Will Drawer be absolute positioned always? What if it needs to be used as a left/right navigation drawer?

Copy link
Member Author

Choose a reason for hiding this comment

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

It will be fixed positioned on top right. It is always positioned like navigation drawer

Copy link
Member

Choose a reason for hiding this comment

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

So we are setting a default position for Drawers on the top-right across all products? Like we set bottom-left for toasts?

Copy link
Member Author

Choose a reason for hiding this comment

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

yup

Copy link
Collaborator

Choose a reason for hiding this comment

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

There are use-cases where drawer is used for navigation on left side in a lot of apps. Won't that ever be a use-case for us?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Example:
image

Copy link
Member Author

Choose a reason for hiding this comment

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

There are use-cases where drawer is used for navigation on left side in a lot of apps. Won't that ever be a use-case for us?

Nope. So for desktop, our navigation bar itself is on left so there won't be anything opening from that side.

On mobile too we have drawers opening from right side only. Plus navigation component is something that we might tackle separately. This navigation component will use our Drawer internally on mobile. So at that time we can relook at this.

Anyway even if usecase comes up, its just addition of new prop so not much effort and no breaking change

/**
* Show or hide overlay.
*
* Also decides if clicking outside on overlay closes the drawer or not
Copy link
Collaborator

Choose a reason for hiding this comment

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

Wont there ever be a possibility where overlay isn't needed but click outside still needs to close the drawer?

Copy link
Member Author

Choose a reason for hiding this comment

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

no I did ask this to designers. If someone wants clicking outside to close drawer, they should always have overlay

Copy link
Member

Choose a reason for hiding this comment

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

Also decides if clicking outside on overlay closes the drawer or not

I feel we should have a separate prop for deciding this, it shouldn't be dependant on the presence of overlay.

Copy link
Member Author

Choose a reason for hiding this comment

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

you mean for a usecase where someone doesn't want to show overlay but still want to close Drawer on clicking outside? I can confirm this once with design if this should be possible. Ideally overlay should be present in most cases except few exceptional cases where outer items have to be interactive

Copy link
Contributor

Choose a reason for hiding this comment

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

I would also vote for the separation of the logic to dismiss the overlay items on click outside on a different prop. If Modal and BottomSheet have a prop tomorrow to disable dismiss on click outside on the overlay the same prop should be extended over here.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Agreed. Better to have a separate prop since we might be adding the same to Modal & BottomSheet too

Copy link
Member Author

Choose a reason for hiding this comment

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

Modal and BottomSheet would anyway have different prop than Drawer in this particular case no?

E.g. in Modal and BottomSheet, we always want to show overlay so there will never be a showOverlay prop. Whereas in Drawer, we definitely need to have showOverlay prop.

If we're having that prop and we know interactions outside have to be consistent with display of overlay, wouldn't adding new prop be extra overhead for consumers here?

Because if we add 2 props, it creates impossible states of

<>
  <Drawer
    showOverlay={true}
    shouldDismissOnOutsideClick={false}
  />
  <Drawer
    showOverlay={false}
    shouldDismissOnOutsideClick={true}
  />
</>

These scenarios should throw error in 2 props case because its not correct usage from UX perspective

Copy link
Member Author

Choose a reason for hiding this comment

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

Oh anyway just discussed this with design - https://razorpay.slack.com/archives/G01B3LQ9H0W/p1707808893726369

Usecase that we have on Modal is something that we would have it here as well. I'll make changes to add 2 props.

Comment on lines 127 to 131
- DrawerHeaderBadge
- DrawerHeaderIcon
- DrawerHeaderAsset
- DrawerHeaderLink
- DrawerHeaderButton
Copy link
Collaborator

Choose a reason for hiding this comment

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

We keep creating these components for multiple components... Modal, Bottomsheet, Drawer. We might need to look into changing these into just HeaderBadge, HeaderIcon, etc. This would keep adding unnecessary repetitive components.

Copy link
Member Author

Choose a reason for hiding this comment

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

true. HeaderBadge is a good idea. Lets discuss this with team once in next standup?

Copy link
Member

Choose a reason for hiding this comment

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

How are these components different from normal Badge/Icon? For example, I see _CardHeaderBadge is same as Badge. Why can't we use theBadge component directly?

const _CardHeaderBadge = (props: BadgeProps): React.ReactElement => {

Copy link
Member Author

Choose a reason for hiding this comment

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

These subcomponents usually have defined defaults that are different from defaults of actual component. E.g.

return <Badge size="medium" marginLeft="spacing.3" {...props} />;

However in some examples like CardHeaderBadge, the defaults of wrapper are same as defaults of actual component. There it is just for consistency in API otherwise some components will be like Badge while some be like CardHeaderText etc

## Accessibility

- **Aria Attributes:** Drawer will have `aria-modal="true"` and `role="dialog"` and will be treated as modal for voiceover users.
- **Focus Handling:** Ensure Close Icon is focussable
Copy link
Collaborator

Choose a reason for hiding this comment

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

Like Modal & Bottomsheet, should we also expose initialFocusRef?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes I think we should. Drawer will also have similar usecases like Modal and BottomSheet so requirement will anyway come

Copy link
Member

Choose a reason for hiding this comment

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

Add keyboard handling details, e.g, Esc should close the drawer.

Copy link
Member Author

Choose a reason for hiding this comment

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

done


## Design

- [Drawer - Figma Design](https://www.figma.com/file/jubmQL9Z8V7881ayUD95ps/Blade-DSL?node-id=78667%3A66663&mode=dev)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Does the drawer have a fixed width? Will the width change based on the content? If it is fixed width, why do we not have size options?

Copy link
Member Author

@saurabhdaware saurabhdaware Feb 8, 2024

Choose a reason for hiding this comment

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

It currently has a fixed max-width of 420px and inside that it takes width based on the content.

Let me check with design once if we want to go with max-width or defined size because in Modal I see its defined size

Copy link
Member Author

Choose a reason for hiding this comment

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

Just checked with RK. It is fixed width of 420px on desktop always. We will only support one size right now

Copy link
Collaborator

Choose a reason for hiding this comment

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

fixed width of 420px
Max width would be 420px right?

Copy link
Member Author

Choose a reason for hiding this comment

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

nope. Drawer is always 420px irrespective of the content.

/**
* Controlled state of drawer open or not
*/
isOpen: boolean;
Copy link
Collaborator

Choose a reason for hiding this comment

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

What happens if multiple drawers are opened together? I'm guessing same behaviour as Modal?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes similar but only 2 drawers can be kept open at once from design-side. And the 2nd drawer has a back button instead of close button.

Let me add the stacking behaviour to this API doc I didn't mention it in this

Copy link
Collaborator

Choose a reason for hiding this comment

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

Would we need a separate callback for the back button?

Copy link
Member Author

Choose a reason for hiding this comment

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

back button is just dismiss of 2nd Drawer. Consumer knows which is their second drawer so they can use that onDismiss itself.


<img width="500px" src="./2024-02-07-20-04-07.png" alt="Drawer Figma Skeleton">

## Design
Copy link
Member

Choose a reason for hiding this comment

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

So we are setting a default position for Drawers on the top-right across all products? Like we set bottom-left for toasts?

/**
* Show or hide overlay.
*
* Also decides if clicking outside on overlay closes the drawer or not
Copy link
Member

Choose a reason for hiding this comment

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

Also decides if clicking outside on overlay closes the drawer or not

I feel we should have a separate prop for deciding this, it shouldn't be dependant on the presence of overlay.

Comment on lines 127 to 131
- DrawerHeaderBadge
- DrawerHeaderIcon
- DrawerHeaderAsset
- DrawerHeaderLink
- DrawerHeaderButton
Copy link
Member

Choose a reason for hiding this comment

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

How are these components different from normal Badge/Icon? For example, I see _CardHeaderBadge is same as Badge. Why can't we use theBadge component directly?

const _CardHeaderBadge = (props: BadgeProps): React.ReactElement => {

## Accessibility

- **Aria Attributes:** Drawer will have `aria-modal="true"` and `role="dialog"` and will be treated as modal for voiceover users.
- **Focus Handling:** Ensure Close Icon is focussable
Copy link
Member

Choose a reason for hiding this comment

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

Add keyboard handling details, e.g, Esc should close the drawer.

/**
* Show or hide overlay.
*
* Also decides if clicking outside on overlay closes the drawer or not
Copy link
Contributor

Choose a reason for hiding this comment

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

I would also vote for the separation of the logic to dismiss the overlay items on click outside on a different prop. If Modal and BottomSheet have a prop tomorrow to disable dismiss on click outside on the overlay the same prop should be extended over here.

/**
* Override z-index of Drawer.
*
* @default 1002
Copy link
Contributor

Choose a reason for hiding this comment

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

@saurav12 Can design take up a decision on the alignment of all our default z-indices for our overlay components? Imo it should be Modal < Drawer < BottomSheet < Popover < Tooltip. We have the zIndex property to override for each component but by default the system should make a recommendation.

Copy link
Member

Choose a reason for hiding this comment

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

Sure, makes sense. We will document these in the Figma itself.

Copy link
Collaborator

Choose a reason for hiding this comment

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

+1

/>
<DrawerBody>
<Slot />
</DrawerBody>
Copy link
Member

Choose a reason for hiding this comment

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

No Footer?

Copy link
Member Author

Choose a reason for hiding this comment

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

nope

## Drawer Stacking

- Only 2 Drawers can be stacked on top of each other
- 2nd Drawer always has overlay independent of `showOverlay` prop
Copy link
Member

Choose a reason for hiding this comment

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

So, the showOverlay prop is redundant for the 2nd drawer? Why so? If I don't want to show overlay in 1st drawer because important information is present on the left then that should hold for the 2nd drawer as well.

So I feel, if we are giving control of showing overlay it should be either on both drawers or none. WDYT?

Copy link
Member Author

Choose a reason for hiding this comment

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

So, the showOverlay prop is redundant for the 2nd drawer? Why so? If I don't want to show overlay in 1st drawer because important information is present on the left then that should hold for the 2nd drawer as well.

For example in X, 1st Drawer is used for showing information based on the interaction on left side. But 2nd Drawer does not have that usecase.

Plus overlay on 2nd Drawer is also there to denote the stacking. If there's 2 Drawers open without overlay, there is no direct way to tell user that there is another drawer behind this drawer.

Also in most cases, Drawer should always have overlay. There are just few exceptions for 1st Drawer which is why we need to provide overlay prop

- 2nd Drawer always has overlay independent of `showOverlay` prop
- 2nd Drawer always has back button instead of close button. Clicking on back button closes the 2nd drawer.

<img width="500px" src="./2024-02-12-11-01-32.png" />
Copy link
Member

Choose a reason for hiding this comment

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

Can you add a code example for stacked drawers?

Copy link
Member Author

Choose a reason for hiding this comment

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

Good point. Adding.

## Drawer Stacking

- Only 2 Drawers can be stacked on top of each other
- 2nd Drawer always has overlay independent of `showOverlay` prop
Copy link
Collaborator

Choose a reason for hiding this comment

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

Won't this be counterintuitive? How will we communicate this to our devs? I can imagine this coming in as a bug in the future

Copy link
Member Author

Choose a reason for hiding this comment

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

Won't this be counterintuitive?

True but don't see any other way to implement this. We do want to show overlay on 2nd drawer.

#2009 (comment)

How will we communicate this to our devs?

We can throw error. Also its enforced from design side so its not possible to implement something like this on design as the UI itself is slightly different for 2nd drawer.


- Only 2 Drawers can be stacked on top of each other
- 2nd Drawer always has overlay independent of `showOverlay` prop
- 2nd Drawer always has back button instead of close button. Clicking on back button closes the 2nd drawer.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why though? a back button only makes sense when the navigation is within the drawer and not another drawer on top of it.

If we are doing this, then we should also have a back button on 2nd Modal? Same logic would be applicable there. I think we shouldn't have a back button in either cases.

Copy link
Member Author

Choose a reason for hiding this comment

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

In case of Modal, the size of the modal would also let people know about modal behind it no? If we put close button on 2nd Drawer, because all Drawers are same size and similarly placed, it feels like clicking close will close everything. But instead we only go back to the first Drawer in the stack.

Basically we would need something to let consumer know that this Drawer is stacked. Back button and overlay was our way to communicate that. But we can discuss this once with RK maybe?

Copy link
Member Author

Choose a reason for hiding this comment

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

@saurabhdaware saurabhdaware added the Review - L1 First level of review label Feb 16, 2024
Copy link
Member

@snitin315 snitin315 left a comment

Choose a reason for hiding this comment

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

:shipit:

@saurabhdaware saurabhdaware merged commit 58a6d9d into master Feb 21, 2024
14 checks passed
@saurabhdaware saurabhdaware deleted the drawer/api-decision branch February 21, 2024 05:43
anuraghazra pushed a commit that referenced this pull request Apr 9, 2024
* feat(Drawer): add API decisions

* feat: add full skeleton

* fix: image width

* fix: typo

* feat: add stacking section to api decision

* Update packages/blade/src/components/Drawer/_decisions/decisions.md

Co-authored-by: Nitin Kumar <snitin315@gmail.com>

* fix: remove DrawerHeaderLink and DrawerHeaderButton

* feat: add open questions

* feat: add discussion slack thread

* feat: update API decision with new API

---------

Co-authored-by: Nitin Kumar <snitin315@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Review - L1 First level of review
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants