diff --git a/.changeset/wicked-oranges-whisper.md b/.changeset/wicked-oranges-whisper.md new file mode 100644 index 00000000000..40c47c1b373 --- /dev/null +++ b/.changeset/wicked-oranges-whisper.md @@ -0,0 +1,9 @@ +--- +"@razorpay/blade": minor +--- + +feat(blade): revamped top-nav component + +> NOTE: +> This might be a breaking change for you, if your project uses the older deprecated TopNav. + diff --git a/packages/blade/src/components/Menu/VisualSubComponents/MenuHeaderFooter.web.tsx b/packages/blade/src/components/Menu/VisualSubComponents/MenuHeaderFooter.web.tsx index 631bb6f69d0..e22bfb6e3c9 100644 --- a/packages/blade/src/components/Menu/VisualSubComponents/MenuHeaderFooter.web.tsx +++ b/packages/blade/src/components/Menu/VisualSubComponents/MenuHeaderFooter.web.tsx @@ -18,7 +18,7 @@ const _MenuHeader = ({ testID, }: MenuHeaderProps): React.ReactElement => { return ( - <> + - + ); }; @@ -47,7 +47,7 @@ const MenuHeader = assignWithoutSideEffects(_MenuHeader, { const _MenuFooter = ({ children, testID }: MenuFooterProps): React.ReactElement => { return ( - +
-

+

+ Header Title +

+
+

- Header Title + Subtitle

-

- Subtitle -

- -
+ data-blade-component="base-box" + > +
+
+ - diff --git a/packages/blade/src/components/TopNav/__tests__/__snapshots__/TopNav.web.test.tsx.snap b/packages/blade/src/components/TopNav/__tests__/__snapshots__/TopNav.web.test.tsx.snap index 42e0731dfa6..9fe67227bfd 100644 --- a/packages/blade/src/components/TopNav/__tests__/__snapshots__/TopNav.web.test.tsx.snap +++ b/packages/blade/src/components/TopNav/__tests__/__snapshots__/TopNav.web.test.tsx.snap @@ -14,10 +14,12 @@ exports[`TopNav should render 1`] = ` align-items: center; position: -webkit-sticky; position: sticky; - z-index: 1; - grid-template-columns: minmax(0,1fr) auto; - padding-right: 8px; - padding-left: 8px; + z-index: 100; + grid-template-columns: auto minmax(0,1fr) auto; + padding-top: 8px; + padding-bottom: 8px; + padding-right: 12px; + padding-left: 12px; height: 56px; width: 100%; top: 0px; @@ -25,7 +27,6 @@ exports[`TopNav should render 1`] = ` } .c2.c2.c2.c2.c2 { - display: none; -webkit-flex-direction: row; -ms-flex-direction: row; flex-direction: row; @@ -39,23 +40,6 @@ exports[`TopNav should render 1`] = ` } .c4.c4.c4.c4.c4 { - display: none; - -webkit-align-self: center; - -ms-flex-item-align: center; - align-self: center; -} - -.c5.c5.c5.c5.c5 { - -webkit-align-self: center; - -ms-flex-item-align: center; - align-self: center; - margin-right: -1px; - height: 20px; - border-left-color: hsla(211,20%,52%,0.18); - border-left-style: solid; -} - -.c7.c7.c7.c7.c7 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -64,11 +48,13 @@ exports[`TopNav should render 1`] = ` -webkit-box-align: center; -ms-flex-align: center; align-items: center; + -webkit-align-self: end; + -ms-flex-item-align: end; + align-self: end; padding-right: 0px; - margin-left: 0px; } -.c8.c8.c8.c8.c8 { +.c5.c5.c5.c5.c5 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -77,82 +63,54 @@ exports[`TopNav should render 1`] = ` -webkit-box-align: center; -ms-flex-align: center; align-items: center; + -webkit-align-self: end; + -ms-flex-item-align: end; + align-self: end; position: relative; - margin-bottom: -12px; width: 100%; } -.c12.c12.c12.c12.c12 { +.c6.c6.c6.c6.c6 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; - -webkit-flex: 1; - -ms-flex: 1; - flex: 1; - -webkit-flex-direction: row; - -ms-flex-direction: row; - flex-direction: row; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; - z-index: 1; + position: relative; + width: 100%; } -.c14.c14.c14.c14.c14 { +.c7.c7.c7.c7.c7 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + width: -webkit-max-content; + width: -moz-max-content; + width: max-content; } -.c15.c15.c15.c15.c15 { +.c8.c8.c8.c8.c8 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; - overflow-x: auto; - overflow-y: hidden; - white-space: nowrap; position: relative; width: 100%; gap: 0px; + left: -1px; } -.c17.c17.c17.c17.c17 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: row; - -ms-flex-direction: row; - flex-direction: row; - width: -webkit-max-content; - width: -moz-max-content; - width: max-content; -} - -.c21.c21.c21.c21.c21 { +.c12.c12.c12.c12.c12 { margin: auto; height: 16px; border-left-color: hsla(211,20%,52%,0.18); border-left-style: solid; } -.c24.c24.c24.c24.c24 { +.c14.c14.c14.c14.c14 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -161,25 +119,25 @@ exports[`TopNav should render 1`] = ` -webkit-box-align: center; -ms-flex-align: center; align-items: center; + -webkit-align-self: end; + -ms-flex-item-align: end; + align-self: end; + padding: 8px; margin-top: 2px; gap: 8px; -} - -.c26.c26.c26.c26.c26 { background-color: hsla(0,0%,100%,1); + border-top-left-radius: 4px; + border-top-right-radius: 4px; } -.c28.c28.c28.c28.c28 { - position: relative; - height: 100%; - width: 100%; -} - -.c30.c30.c30.c30.c30 { +.c17.c17.c17.c17.c17 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; + -webkit-flex: 1; + -ms-flex: 1; + flex: 1; -webkit-flex-direction: row; -ms-flex-direction: row; flex-direction: row; @@ -192,252 +150,81 @@ exports[`TopNav should render 1`] = ` -ms-flex-pack: center; justify-content: center; z-index: 1; - height: 100%; -} - -.c32.c32.c32.c32.c32 { - position: absolute; - top: 0px; - left: 0px; - pointer-events: none; } -.c10.c10.c10.c10.c10 { - min-height: 28px; - height: 28px; - width: 28px; - cursor: pointer; - background-color: hsla(211,20%,52%,0.12); - border-color: hsla(214,28%,84%,1); - border-width: 0px; - border-radius: 4px; - border-style: solid; - padding-top: 0px; - padding-bottom: 0px; - padding-left: 0px; - padding-right: 0px; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; +.c19.c19.c19.c19.c19 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; -webkit-align-items: center; -webkit-box-align: center; -ms-flex-align: center; align-items: center; - -webkit-text-decoration: none; - text-decoration: none; - overflow: hidden; - display: -webkit-inline-box; - display: -webkit-inline-flex; - display: -ms-inline-flexbox; - display: inline-flex; - -webkit-transition-property: background-color,border-color,box-shadow; - transition-property: background-color,border-color,box-shadow; - -webkit-transition-timing-function: cubic-bezier(0.3,0,0.2,1); - transition-timing-function: cubic-bezier(0.3,0,0.2,1); - -webkit-transition-duration: 150ms; - transition-duration: 150ms; - position: relative; -} - -.c10.c10.c10.c10.c10:hover { - background-color: hsla(211,20%,52%,0.18); -} - -.c10.c10.c10.c10.c10:active { - background-color: hsla(211,20%,52%,0.18); -} - -.c10.c10.c10.c10.c10:focus-visible { - background-color: hsla(211,20%,52%,0.18); - outline: 1px solid hsla(227,100%,59%,0.09); - box-shadow: 0px 0px 0px 4px hsla(227,100%,59%,0.18); -} - -.c10.c10.c10.c10.c10 * { - -webkit-transition-property: color,fill,opacity; - transition-property: color,fill,opacity; - -webkit-transition-duration: 150ms; - transition-duration: 150ms; - -webkit-transition-timing-function: cubic-bezier(0.3,0,0.2,1); - transition-timing-function: cubic-bezier(0.3,0,0.2,1); -} - -.c25.c25.c25.c25.c25 { - min-height: 36px; - height: 36px; - width: 36px; - cursor: pointer; - background-color: hsla(211,20%,52%,0.12); - border-color: hsla(214,28%,84%,1); - border-width: 0px; - border-radius: 4px; - border-style: solid; - padding-top: 0px; - padding-bottom: 0px; - padding-left: 0px; - padding-right: 0px; -webkit-box-pack: center; -webkit-justify-content: center; -ms-flex-pack: center; justify-content: center; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-text-decoration: none; - text-decoration: none; - overflow: hidden; - display: -webkit-inline-box; - display: -webkit-inline-flex; - display: -ms-inline-flexbox; - display: inline-flex; - -webkit-transition-property: background-color,border-color,box-shadow; - transition-property: background-color,border-color,box-shadow; - -webkit-transition-timing-function: cubic-bezier(0.3,0,0.2,1); - transition-timing-function: cubic-bezier(0.3,0,0.2,1); - -webkit-transition-duration: 150ms; - transition-duration: 150ms; - position: relative; -} - -.c25.c25.c25.c25.c25:hover { - background-color: hsla(211,20%,52%,0.18); -} - -.c25.c25.c25.c25.c25:active { - background-color: hsla(211,20%,52%,0.18); -} - -.c25.c25.c25.c25.c25:focus-visible { - background-color: hsla(211,20%,52%,0.18); - outline: 1px solid hsla(227,100%,59%,0.09); - box-shadow: 0px 0px 0px 4px hsla(227,100%,59%,0.18); -} - -.c25.c25.c25.c25.c25 * { - -webkit-transition-property: color,fill,opacity; - transition-property: color,fill,opacity; - -webkit-transition-duration: 150ms; - transition-duration: 150ms; - -webkit-transition-timing-function: cubic-bezier(0.3,0,0.2,1); - transition-timing-function: cubic-bezier(0.3,0,0.2,1); -} - -.c11.c11.c11.c11.c11 { - -webkit-transform: scale(1); - -ms-transform: scale(1); - transform: scale(1); - -webkit-transition-duration: cubic-bezier(0.3,0,0.2,1); - transition-duration: cubic-bezier(0.3,0,0.2,1); - -webkit-transition-timing-function: 150px; - transition-timing-function: 150px; -} - -.c31.c31.c31.c31.c31 { - color: hsla(211,33%,21%,1); - font-family: "Inter","Inter Fallback Arial",Arial; - font-size: 0.75rem; - font-weight: 600; - font-style: normal; - -webkit-text-decoration-line: none; - text-decoration-line: none; - line-height: 1.125rem; - -webkit-letter-spacing: 0px; - -moz-letter-spacing: 0px; - -ms-letter-spacing: 0px; - letter-spacing: 0px; - margin: 0; - padding: 0; -} - -.c13.c13.c13.c13.c13 { - opacity: 1; } -.c6.c6.c6.c6.c6 { - border-width: 0; - border-left-style: solid; - border-left-width: 1px; - -webkit-align-self: stretch; - -ms-flex-item-align: stretch; - align-self: stretch; - height: 20px; +.c20.c20.c20.c20.c20 { + background-color: hsla(0,0%,100%,1); } .c22.c22.c22.c22.c22 { - border-width: 0; - border-left-style: solid; - border-left-width: 1px; - -webkit-align-self: stretch; - -ms-flex-item-align: stretch; - align-self: stretch; - height: 16px; -} - -.c16.c16.c16.c16.c16::-webkit-scrollbar { - display: none; + position: relative; + height: 100%; + width: 100%; } -.c9.c9.c9.c9.c9 { - position: absolute; - left: 0; - pointer-events: none; - -webkit-transform: scale(0.5); - -ms-transform: scale(0.5); - transform: scale(0.5); - opacity: 0; - -webkit-transition-timing-function: cubic-bezier(0.5,0,0,1); - transition-timing-function: cubic-bezier(0.5,0,0,1); - -webkit-transition-duration: 150ms; - transition-duration: 150ms; - -webkit-transition-property: opacity,-webkit-transform; - -webkit-transition-property: opacity,transform; - transition-property: opacity,transform; +.c24.c24.c24.c24.c24 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; z-index: 1; + height: 100%; } - -.c9.c9.c9.c9.c9:before { - content: ''; - pointer-events: none; - position: absolute; - left: 0; - top: -8px; - bottom: -8px; - width: 54px; - background: linear-gradient(to left,transparent 0%,hsla(0,0%,100%,1) 30%,hsla(0,0%,100%,1) 100%); -} - -.c23.c23.c23.c23.c23 { - position: absolute; - right: 0; - pointer-events: none; - -webkit-transform: scale(0.5); - -ms-transform: scale(0.5); - transform: scale(0.5); - opacity: 0; - -webkit-transition-timing-function: cubic-bezier(0.5,0,0,1); - transition-timing-function: cubic-bezier(0.5,0,0,1); - -webkit-transition-duration: 150ms; - transition-duration: 150ms; - -webkit-transition-property: opacity,-webkit-transform; - -webkit-transition-property: opacity,transform; - transition-property: opacity,transform; - z-index: 1; + +.c13.c13.c13.c13.c13 { + border-width: 0; + border-left-style: solid; + border-left-width: 1px; + -webkit-align-self: stretch; + -ms-flex-item-align: stretch; + align-self: stretch; + height: 16px; } -.c23.c23.c23.c23.c23:before { - content: ''; - pointer-events: none; - position: absolute; - right: 0; - top: -8px; - bottom: -8px; - width: 54px; - background: linear-gradient(to right,transparent 0%,hsla(0,0%,100%,1) 30%,hsla(0,0%,100%,1) 100%); +.c25.c25.c25.c25.c25 { + color: hsla(211,33%,21%,1); + font-family: "Inter","Inter Fallback Arial",Arial; + font-size: 0.75rem; + font-weight: 600; + font-style: normal; + -webkit-text-decoration-line: none; + text-decoration-line: none; + line-height: 1.125rem; + -webkit-letter-spacing: 0px; + -moz-letter-spacing: 0px; + -ms-letter-spacing: 0px; + letter-spacing: 0px; + margin: 0; + padding: 0; } -.c20.c20.c20.c20.c20 { +.c11.c11.c11.c11.c11 { color: hsla(211,26%,34%,1); font-family: "Inter","Inter Fallback Arial",Arial; font-size: 0.875rem; @@ -477,13 +264,19 @@ exports[`TopNav should render 1`] = ` padding-left: 12px; padding-right: 12px; border-radius: 4px; + border: none; + background: none; } -.c20.c20.c20.c20.c20:hover { +.c11.c11.c11.c11.c11[aria-expanded="true"] { background-color: hsla(211,20%,52%,0.12); } -.c18.c18.c18.c18.c18 { +.c11.c11.c11.c11.c11:hover { + background-color: hsla(211,20%,52%,0.12); +} + +.c9.c9.c9.c9.c9 { position: relative; -webkit-flex-shrink: 0; -ms-flex-negative: 0; @@ -492,21 +285,17 @@ exports[`TopNav should render 1`] = ` background-color: transparent; border-color: transparent; border-style: solid; - border-bottom-width: 0; border-width: 1px; + border-bottom-width: 0; border-top-left-radius: 4px; border-top-right-radius: 4px; - -webkit-transform: none; - -ms-transform: none; - transform: none; -webkit-transition: 250ms cubic-bezier(0.3,0,0.2,1); transition: 250ms cubic-bezier(0.3,0,0.2,1); - -webkit-transition-property: background,-webkit-transform; - -webkit-transition-property: background,transform; - transition-property: background,transform; + -webkit-transition-property: background; + transition-property: background; } -.c19.c19.c19.c19.c19 { +.c10.c10.c10.c10.c10 { position: absolute; top: 0; left: 0; @@ -523,7 +312,7 @@ exports[`TopNav should render 1`] = ` transition-property: opacity; } -.c27.c27.c27.c27.c27 { +.c21.c21.c21.c21.c21 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -534,7 +323,7 @@ exports[`TopNav should render 1`] = ` outline: 0.5px solid hsla(214,28%,84%,1); } -.c29.c29.c29.c29.c29 { +.c23.c23.c23.c23.c23 { display: block; text-align: center; -webkit-text-decoration: none; @@ -548,7 +337,7 @@ exports[`TopNav should render 1`] = ` background-color: hsla(211,20%,52%,0.18); } -.c29.c29.c29.c29.c29 img { +.c23.c23.c23.c23.c23 img { display: block; height: 36px; width: 36px; @@ -556,130 +345,132 @@ exports[`TopNav should render 1`] = ` object-fit: cover; } -@media screen and (min-width:768px) { - .c1.c1.c1.c1.c1 { - grid-template-columns: auto minmax(0,1fr) auto; - } +.c15.c15.c15.c15.c15 { + min-height: 36px; + height: 36px; + width: 36px; + cursor: pointer; + background-color: hsla(211,20%,52%,0.12); + border-color: hsla(214,28%,84%,1); + border-width: 0px; + border-radius: 4px; + border-style: solid; + padding-top: 0px; + padding-bottom: 0px; + padding-left: 0px; + padding-right: 0px; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-text-decoration: none; + text-decoration: none; + overflow: hidden; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + -webkit-transition-property: background-color,border-color,box-shadow; + transition-property: background-color,border-color,box-shadow; + -webkit-transition-timing-function: cubic-bezier(0.3,0,0.2,1); + transition-timing-function: cubic-bezier(0.3,0,0.2,1); + -webkit-transition-duration: 150ms; + transition-duration: 150ms; + position: relative; } -@media screen and (min-width:768px) { - .c2.c2.c2.c2.c2 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - } +.c15.c15.c15.c15.c15:hover { + background-color: hsla(211,20%,52%,0.18); } -@media screen and (min-width:1200px) { - .c2.c2.c2.c2.c2 { - width: 264px; - } +.c15.c15.c15.c15.c15:active { + background-color: hsla(211,20%,52%,0.18); } -@media screen and (min-width:768px) { - .c4.c4.c4.c4.c4 { - display: block; - } +.c15.c15.c15.c15.c15:focus-visible { + background-color: hsla(211,20%,52%,0.18); + outline: 1px solid hsla(227,100%,59%,0.09); + box-shadow: 0px 0px 0px 4px hsla(227,100%,59%,0.18); } -@media screen and (min-width:320px) { - .c5.c5.c5.c5.c5 { - border-left-style: solid; - } +.c15.c15.c15.c15.c15 * { + -webkit-transition-property: color,fill,opacity; + transition-property: color,fill,opacity; + -webkit-transition-duration: 150ms; + transition-duration: 150ms; + -webkit-transition-timing-function: cubic-bezier(0.3,0,0.2,1); + transition-timing-function: cubic-bezier(0.3,0,0.2,1); } -@media screen and (min-width:480px) { - .c5.c5.c5.c5.c5 { - border-left-style: solid; - } +.c16.c16.c16.c16.c16 { + -webkit-transform: scale(1); + -ms-transform: scale(1); + transform: scale(1); + -webkit-transition-duration: cubic-bezier(0.3,0,0.2,1); + transition-duration: cubic-bezier(0.3,0,0.2,1); + -webkit-transition-timing-function: 150px; + transition-timing-function: 150px; } -@media screen and (min-width:768px) { - .c5.c5.c5.c5.c5 { - border-left-style: solid; - } +.c18.c18.c18.c18.c18 { + opacity: 1; } -@media screen and (min-width:1024px) { - .c5.c5.c5.c5.c5 { - border-left-style: solid; +@media screen and (min-width:768px) { + .c1.c1.c1.c1.c1 { + padding-top: 0px; + padding-bottom: 0px; + padding-right: 8px; + padding-left: 8px; } } @media screen and (min-width:1200px) { - .c5.c5.c5.c5.c5 { - border-left-style: solid; + .c2.c2.c2.c2.c2 { + width: 264px; } } @media screen and (min-width:768px) { - .c7.c7.c7.c7.c7 { + .c4.c4.c4.c4.c4 { padding-right: 80px; - margin-left: 12px; } } @media screen and (min-width:320px) { - .c21.c21.c21.c21.c21 { + .c12.c12.c12.c12.c12 { border-left-style: solid; } } @media screen and (min-width:480px) { - .c21.c21.c21.c21.c21 { + .c12.c12.c12.c12.c12 { border-left-style: solid; } } @media screen and (min-width:768px) { - .c21.c21.c21.c21.c21 { + .c12.c12.c12.c12.c12 { border-left-style: solid; } } @media screen and (min-width:1024px) { - .c21.c21.c21.c21.c21 { + .c12.c12.c12.c12.c12 { border-left-style: solid; } } @media screen and (min-width:1200px) { - .c21.c21.c21.c21.c21 { + .c12.c12.c12.c12.c12 { border-left-style: solid; } } -@media screen and (min-width:320px) { - .c32.c32.c32.c32.c32 { - pointer-events: none; - } -} - -@media screen and (min-width:480px) { - .c32.c32.c32.c32.c32 { - pointer-events: none; - } -} - -@media screen and (min-width:768px) { - .c32.c32.c32.c32.c32 { - pointer-events: none; - } -} - -@media screen and (min-width:1024px) { - .c32.c32.c32.c32.c32 { - pointer-events: none; - } -} - -@media screen and (min-width:1200px) { - .c32.c32.c32.c32.c32 { - pointer-events: none; - } -} -
-
-

AH @@ -1048,44 +768,6 @@ exports[`TopNav should render 1`] = `

-
- - - - - - - - - -
diff --git a/packages/blade/src/components/TopNav/docs/TabNav.stories.tsx b/packages/blade/src/components/TopNav/docs/TabNav.stories.tsx index e8cdebc32f4..7ee8d6e1cbb 100644 --- a/packages/blade/src/components/TopNav/docs/TabNav.stories.tsx +++ b/packages/blade/src/components/TopNav/docs/TabNav.stories.tsx @@ -1,19 +1,28 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable jsx-a11y/label-has-associated-control */ /* eslint-disable @typescript-eslint/explicit-function-return-type */ import React from 'react'; import type { StoryFn, Meta } from '@storybook/react'; import type { TabNavItemProps } from '../TabNav'; -import { TabNav, TabNavItem } from '../TabNav'; +import { TabNavItems, TabNav, TabNavItem } from '../TabNav'; import { tabNavExample } from './code'; import { Box } from '~components/Box'; import iconMap from '~components/Icons/iconMap'; -import { ChevronDownIcon, ChevronRightIcon, HomeIcon } from '~components/Icons'; -import { Menu, MenuFooter, MenuHeader, MenuItem, MenuOverlay } from '~components/Menu'; +import { + AcceptPaymentsIcon, + AwardIcon, + ChevronDownIcon, + HomeIcon, + ShoppingBagIcon, +} from '~components/Icons'; +import { Menu, MenuItem, MenuOverlay } from '~components/Menu'; import { Badge } from '~components/Badge'; import { Link } from '~components/Link'; import { Code, Text } from '~components/Typography'; import { Sandbox } from '~utils/storybook/Sandbox'; import StoryPageWrapper from '~utils/storybook/StoryPageWrapper'; +import { List, ListItem, ListItemCode } from '~components/List'; +import { Alert } from '~components/Alert'; const DocsPage = (): React.ReactElement => { return ( @@ -31,38 +40,86 @@ const trailingMapping = { 'NEW': NEW, }; +const propsCategory = { + TAB_NAV_ITEM: 'TabNavItem Props', + ITEM_DATA: 'Extra props for "item" data', +}; + export default { title: 'Components/TopNav/TabNav', component: TabNavItem, argTypes: { + title: { + type: 'string', + table: { category: propsCategory.TAB_NAV_ITEM }, + }, + href: { + type: 'string', + table: { category: propsCategory.TAB_NAV_ITEM }, + }, + target: { + type: 'string', + table: { category: propsCategory.TAB_NAV_ITEM }, + }, + accessibilityLabel: { + type: 'string', + table: { category: propsCategory.TAB_NAV_ITEM }, + }, + as: { + type: 'string', + table: { category: propsCategory.TAB_NAV_ITEM }, + }, icon: { name: 'icon', type: 'select', options: Object.keys(iconMap), - mapping: iconMap, + table: { category: propsCategory.TAB_NAV_ITEM }, } as unknown, trailing: { name: 'trailing', type: 'select', options: Object.keys(trailingMapping), - mapping: trailingMapping, + table: { category: propsCategory.TAB_NAV_ITEM }, } as unknown, + isAlwaysOverflowing: { + type: 'boolean', + table: { category: propsCategory.ITEM_DATA }, + }, + isActive: { + type: 'boolean', + table: { category: propsCategory.TAB_NAV_ITEM }, + }, + description: { + type: 'string', + table: { category: propsCategory.ITEM_DATA }, + }, onClick: { type: 'function', + table: { category: propsCategory.TAB_NAV_ITEM }, }, onKeyDown: { type: 'function', + table: { category: propsCategory.TAB_NAV_ITEM }, }, onKeyUp: { type: 'function', + table: { category: propsCategory.TAB_NAV_ITEM }, }, onMouseDown: { type: 'function', + table: { category: propsCategory.TAB_NAV_ITEM }, }, onPointerDown: { type: 'function', + table: { category: propsCategory.TAB_NAV_ITEM }, }, }, + args: { + title: 'Payroll', + description: 'Manage payroll effortlessly.', + isAlwaysOverflowing: false, + isActive: false, + }, tags: ['autodocs'], parameters: { docs: { @@ -71,121 +128,149 @@ export default { }, } as Meta; -const TabNavTemplate: StoryFn = (args) => { - return ( - - - - - {args.children} - - Payments - Magic Checkout - - - ); -}; +const TabNavTemplate: StoryFn = ( + args: TabNavItemProps & { + isAlwaysOverflowing: boolean; + description: string; + }, +) => { + const icon = iconMap[(args.icon as unknown) as keyof typeof iconMap]; + const trailing = trailingMapping[(args.trailing as unknown) as keyof typeof trailingMapping]; -const TabNavTemplateWithMenu: StoryFn = (args) => { return ( - - - You can compose TabNav with Menu component to create a dropdown - menus within TabNav. - - - Each TabNavItem component can be wrapped with Menu component to - achieve this. - - - - - - {args.children} - - Payments - Magic Checkout - - }> - Explore - - - - Recommended - - } - /> - - - Payroll - - - - - Payout - - - - - View all products - - - - - - - ); -}; + + TabNav component provides a flexible way for you to build tabs which automatically handles + responsiveness and overflows as screen size reduces + -const TabNavTemplateOverFlowing: StoryFn = (args) => { - return ( - - - - If there are more TabNavItems than we can fit in the available space, the TabNav will - become horizontally scrollable with left/right arrow buttons. - - - - - - - {args.children} - - Payments - Magic Checkout - Item 1 - Item 2 - Item 3 - Item 4 - Item 5 - + + TabNav component takes in an array of items and gives you the flexibility of + the rendering via a render prop + + + + The render prop exposes two arrays: + + + items - an array of items that fit in the available space + + + overflowingItems - an array of items that overflow the + available space + + + + + You can map over these arrays and render the TabNavItem component for each item + or for the overflowing items you can render a Menu component to create a + dropdown "More" menu. + + + + + + {({ items, overflowingItems }) => { + return ( + <> + + {items.map((item) => { + return ( + + ); + })} + + {overflowingItems.length ? ( + + } /> + + {overflowingItems.map((item) => { + const Icon = item.icon; + return ( + { + console.log('clicked', item.title); + }} + > + + + {Icon && } + {item.title} + + + {item.description} + + + + ); + })} + + + ) : null} + + ); + }} + ); }; export const TabNavExample = TabNavTemplate.bind({}); TabNavExample.args = { - children: 'Payroll', + title: 'Payroll', isActive: true, }; TabNavExample.storyName = 'TabNavExample'; - -export const WithMenu = TabNavTemplateWithMenu.bind({}); -WithMenu.args = { - children: 'Payroll', - isActive: true, -}; -WithMenu.storyName = 'With Menu'; - -export const OverFlowing = TabNavTemplateOverFlowing.bind({}); -OverFlowing.args = { - children: 'Payroll', - isActive: true, -}; -OverFlowing.storyName = 'Overflowing'; diff --git a/packages/blade/src/components/TopNav/docs/TopNav.stories.tsx b/packages/blade/src/components/TopNav/docs/TopNav.stories.tsx index 80ec9f96558..ac7bc589435 100644 --- a/packages/blade/src/components/TopNav/docs/TopNav.stories.tsx +++ b/packages/blade/src/components/TopNav/docs/TopNav.stories.tsx @@ -1,14 +1,14 @@ -/* eslint-disable jsx-a11y/label-has-associated-control */ /* eslint-disable @typescript-eslint/explicit-function-return-type */ import React from 'react'; import type { StoryFn, Meta } from '@storybook/react'; import { Link, matchPath, useHistory, useLocation } from 'react-router-dom'; import storyRouterDecorator from 'storybook-react-router'; import { Title } from '@storybook/addon-docs'; +import styled from 'styled-components'; import type { TopNavProps } from '../TopNav'; import { TopNav, TopNavActions, TopNavContent, TopNavBrand } from '../TopNav'; import type { TabNavItemProps } from '../TabNav'; -import { TabNav, TabNavItem } from '../TabNav'; +import { TabNavItems, TabNav, TabNavItem } from '../TabNav'; import { topNavFullExample } from './code'; import { Box } from '~components/Box'; import type { SideNavLinkProps, SideNavProps } from '~components/SideNav'; @@ -21,14 +21,16 @@ import { } from '~components/SideNav'; import type { IconComponent } from '~components/Icons'; import { + SearchIcon, + AcceptPaymentsIcon, + AwardIcon, + ShoppingBagIcon, ChevronDownIcon, ActivityIcon, AnnouncementIcon, - BulkPayoutsIcon, ChevronRightIcon, HomeIcon, LayoutIcon, - MenuIcon, PaymentButtonIcon, PaymentGatewayIcon, PaymentLinkIcon, @@ -40,8 +42,7 @@ import { SearchInput } from '~components/Input/SearchInput'; import { Button } from '~components/Button'; import { Tooltip } from '~components/Tooltip'; import { Avatar } from '~components/Avatar'; -import { useIsMobile } from '~utils/useIsMobile'; -import { Text } from '~components/Typography'; +import { Heading, Text } from '~components/Typography'; import { Menu, MenuFooter, MenuHeader, MenuItem, MenuOverlay } from '~components/Menu'; import { Link as BladeLink } from '~components/Link'; import { Badge } from '~components/Badge'; @@ -50,7 +51,7 @@ import StoryPageWrapper from '~utils/storybook/StoryPageWrapper'; import { Alert } from '~components/Alert'; import { List, ListItem } from '~components/List'; -import { makeSize } from '~utils'; +import { makeSize, useBreakpoint, useTheme } from '~utils'; import { SIDE_NAV_EXPANDED_L1_WIDTH_XL, SIDE_NAV_EXPANDED_L1_WIDTH_BASE, @@ -190,7 +191,7 @@ const ExploreItem = ({ description, }: { icon: IconComponent; - title: string; + title?: string; description: string; }): React.ReactElement => { return ( @@ -214,134 +215,226 @@ const ExploreItem = ({ ); }; +const DashboardBackground = styled.div(() => { + return { + height: '100vh', + background: 'radial-gradient(94.74% 64.44% at 29.03% 15.17%, #FFFFFF 0%, #90A5BB 100%)', + }; +}); + const TopNavFullExample = () => { - const isMobile = useIsMobile(); const history = useHistory(); + const { theme } = useTheme(); + const { matchedBreakpoint, matchedDeviceType } = useBreakpoint({ + breakpoints: theme.breakpoints, + }); + const isTablet = matchedBreakpoint === 'm'; + const isMobile = matchedDeviceType === 'mobile'; const [isSideBarOpen, setIsSideBarOpen] = React.useState(false); const [selectedProduct, setSelectedProduct] = React.useState(null); + const activeUrl = useLocation().pathname; + React.useEffect(() => { + setSelectedProduct(activeUrl); + }, [activeUrl]); + return ( - + - {/* TopNavBrand gets hidden on mobile */} - - - - - {/* Desktop - render TabNav */} - - - Payroll - Payments - Magic Checkout - - }> - {selectedProduct ? `Explore: ${selectedProduct}` : 'Explore'} - + {isMobile ? ( + <> + + Home + + + Payments + + + - - Recommended - - } - /> - { - history.push('/explore/payroll'); - setSelectedProduct('Payroll'); - }} - > - + + + + + + John Doe + + + Razorpay Trusted Merchant + + + + + Settings - { - history.push('/explore/payouts'); - setSelectedProduct('Payout'); - }} - > - + + Logout - - - View all products - - - - {/* Mobile - render hamburger button */} - - - - {/* Mobile - render hamburger button */} - -