@@ -14,6 +14,7 @@ import {
1414} from "@mui/material" ;
1515import { makeStyles } from "@mui/styles" ;
1616import { PUBLISHED_STATE } from "@prisma/client" ;
17+ import clsx from "clsx" ;
1718import { useSession } from "next-auth/react" ;
1819import Link from "next/link" ;
1920import { useRouter } from "next/router" ;
@@ -50,7 +51,7 @@ import { useUserConfig } from "@/domain/user-configs";
5051import { useFlag } from "@/flags" ;
5152import { useDataCubesComponentsQuery } from "@/graphql/hooks" ;
5253import { Icon , IconName } from "@/icons" ;
53- import { useLocale } from "@/src " ;
54+ import { defaultLocale , useLocale } from "@/locales " ;
5455import { createConfig , updateConfig } from "@/utils/chart-config/api" ;
5556import { createChartId } from "@/utils/create-chart-id" ;
5657import { getRouterChartId } from "@/utils/router/helpers" ;
@@ -104,6 +105,7 @@ export const ChartSelectionTabs = () => {
104105 const [ state ] = useConfiguratorState ( hasChartConfigs ) ;
105106 const editable =
106107 isConfiguring ( state ) || isLayouting ( state ) || isPublishing ( state ) ;
108+ const locale = useLocale ( ) ;
107109
108110 if ( ! editable && state . chartConfigs . length === 1 ) {
109111 return null ;
@@ -115,6 +117,12 @@ export const ChartSelectionTabs = () => {
115117 key : d . key ,
116118 chartType : d . chartType ,
117119 active : d . key === chartConfig . key ,
120+ label :
121+ d . meta . title [ locale ] !== ""
122+ ? d . meta . title [ locale ]
123+ : d . meta . title [ defaultLocale ] !== ""
124+ ? d . meta . title [ defaultLocale ]
125+ : t ( { id : "annotation.add.title" } ) ,
118126 } ;
119127 } ) ;
120128
@@ -347,6 +355,7 @@ type TabDatum = {
347355 key : string ;
348356 chartType : ChartType ;
349357 active : boolean ;
358+ label : string ;
350359} ;
351360
352361type TabsFixedProps = {
@@ -618,7 +627,55 @@ const PassthroughTab = ({
618627 return < > { children } </ > ;
619628} ;
620629
630+ const useTabsInnerStyles = makeStyles < Theme > ( ( theme ) => ( {
631+ root : {
632+ display : "flex" ,
633+ alignItems : "center" ,
634+ justifyContent : "space-between" ,
635+ gap : 1 ,
636+ } ,
637+ tab : {
638+ zIndex : 1 ,
639+ "&:first-child" : {
640+ marginLeft : - 1 ,
641+ } ,
642+ "&:last-child" : {
643+ marginRight : - 1 ,
644+ } ,
645+ } ,
646+ tabList : {
647+ top : 1 ,
648+ border : "1px solid" ,
649+ borderColor : theme . palette . divider ,
650+ borderTop : 0 ,
651+ borderBottom : 0 ,
652+ position : "relative" ,
653+ "--bg" : theme . palette . background . paper ,
654+ "--cut-off-width" : "1rem" ,
655+ "&:before, &:after" : {
656+ top : 1 ,
657+ content : '""' ,
658+ bottom : 1 ,
659+ position : "absolute" ,
660+ width : "var(--cut-off-width)" ,
661+ zIndex : 1 ,
662+ } ,
663+ "&:before" : {
664+ borderBottom : 0 ,
665+ left : 0 ,
666+ right : "auto" ,
667+ backgroundImage : "linear-gradient(to left, transparent, var(--bg))" ,
668+ } ,
669+ "&:after" : {
670+ left : "auto" ,
671+ right : 0 ,
672+ backgroundImage : "linear-gradient(to right, transparent, var(--bg))" ,
673+ } ,
674+ } ,
675+ } ) ) ;
676+
621677const TabsInner = ( props : TabsInnerProps ) => {
678+ const classes = useTabsInnerStyles ( ) ;
622679 const {
623680 data,
624681 addable,
@@ -636,14 +693,7 @@ const TabsInner = (props: TabsInnerProps) => {
636693 const activeTabIndex = data . findIndex ( ( x ) => x . active ) ;
637694
638695 return (
639- < Box
640- sx = { {
641- display : "flex" ,
642- alignItems : "flex-start" ,
643- justifyContent : "space-between" ,
644- gap : 5 ,
645- } }
646- >
696+ < div className = { classes . root } >
647697 < TabContext value = { `${ activeTabIndex } ` } >
648698 < DragDropContext
649699 onDragEnd = { ( d ) => {
@@ -664,7 +714,7 @@ const TabsInner = (props: TabsInnerProps) => {
664714 ref = { provided . innerRef }
665715 variant = "scrollable"
666716 scrollButtons = { false }
667- sx = { { top : 1 } }
717+ className = { classes . tabList }
668718 >
669719 { data . map ( ( d , i ) => (
670720 < PassthroughTab key = { d . key } value = { `${ i } ` } >
@@ -684,14 +734,17 @@ const TabsInner = (props: TabsInnerProps) => {
684734 component = "div"
685735 key = { d . key }
686736 value = { `${ i } ` }
687- className = { `${
737+ className = { clsx (
738+ classes . tab ,
688739 // We need to add the "selected" class ourselves since we are wrapping
689740 // the tabs by Draggable.
690741 i === activeTabIndex ? "Mui-selected" : ""
691- } ` }
742+ ) }
692743 sx = { {
693744 px : 0 ,
694- minWidth : "fit-content" ,
745+ flexShrink : 1 ,
746+ minWidth : 180 ,
747+ flexBasis : "100%" ,
695748 } }
696749 label = {
697750 < TabContent
@@ -700,6 +753,7 @@ const TabsInner = (props: TabsInnerProps) => {
700753 editable = { editable }
701754 draggable = { draggable }
702755 active = { d . active }
756+ label = { d . label }
703757 dragging = { snapshot . isDragging }
704758 onChevronDownClick = { ( e ) => {
705759 onChartEdit ?.( e , d . key ) ;
@@ -718,25 +772,31 @@ const TabsInner = (props: TabsInnerProps) => {
718772 < PassthroughTab >
719773 < div style = { { opacity : 0 } } > { provided . placeholder } </ div >
720774 </ PassthroughTab >
721-
722- { addable && (
723- < VisualizeTab
724- component = "div"
725- sx = { {
726- px : 0 ,
727- minWidth : "fit-content" ,
728- } }
729- onClick = { onChartAdd }
730- label = { < TabContent iconName = "add" chartKey = "" /> }
731- />
732- ) }
733775 </ VisualizeTabList >
734776 ) }
735777 </ Droppable >
736778 </ DragDropContext >
737779 </ TabContext >
738780
739- < Box gap = "0.5rem" display = "flex" >
781+ { addable && (
782+ < VisualizeTab
783+ component = "div"
784+ className = { classes . tab }
785+ sx = { {
786+ px : 0 ,
787+ pt : "2px" ,
788+ top : 1 ,
789+ margin : "0 1rem" ,
790+ height : "100%" ,
791+ border : "1px solid" ,
792+ borderColor : "divider" ,
793+ minWidth : "fit-content" ,
794+ } }
795+ onClick = { onChartAdd }
796+ label = { < TabContent iconName = "add" chartKey = "" /> }
797+ />
798+ ) }
799+ < Box gap = "0.5rem" display = "flex" flexShrink = { 0 } >
740800 { isConfiguring ( state ) ? < SaveDraftButton chartId = { chartId } /> : null }
741801 { editable &&
742802 isConfiguring ( state ) &&
@@ -746,7 +806,7 @@ const TabsInner = (props: TabsInnerProps) => {
746806 < PublishChartButton chartId = { chartId } />
747807 ) ) }
748808 </ Box >
749- </ Box >
809+ </ div >
750810 ) ;
751811} ;
752812
@@ -755,11 +815,44 @@ export const useIconStyles = makeStyles<
755815 { active : boolean | undefined ; dragging : boolean | undefined }
756816> ( ( { palette, spacing } ) => ( {
757817 root : {
818+ "--bg" : palette . background . paper ,
819+ backgroundColor : "var(--bg)" ,
758820 alignItems : "center" ,
759821 padding : spacing ( 2 ) ,
760822 borderTopLeftRadius : spacing ( 1 ) ,
761823 borderTopRightRadius : spacing ( 1 ) ,
762824 cursor : "default" ,
825+ textTransform : "none" ,
826+ width : "100%" ,
827+ justifyContent : "stretch" ,
828+ } ,
829+ label : {
830+ flexShrink : 1 ,
831+ flexGrow : 1 ,
832+ marginLeft : "-0.5rem" ,
833+ color : "inherit" ,
834+ flexWrap : "nowrap" ,
835+ whiteSpace : "nowrap" ,
836+ minWidth : 0 ,
837+ overflow : "hidden" ,
838+ minHeight : "100%" ,
839+ position : "relative" ,
840+ display : "flex" ,
841+ cursor : "pointer" ,
842+ alignItems : "center" ,
843+ marginRight : "0.15rem" ,
844+
845+ "&:after" : {
846+ content : '" "' ,
847+ position : "absolute" ,
848+ right : 0 ,
849+ top : 0 ,
850+ bottom : 0 ,
851+ height : "auto" ,
852+ width : "10px" ,
853+ backgroundImage :
854+ "linear-gradient(to right, rgba(255, 255, 255, 0), var(--bg))" ,
855+ } ,
763856 } ,
764857 chartIconWrapper : {
765858 minWidth : "fit-content" ,
@@ -795,6 +888,7 @@ type TabContentProps = {
795888 draggable ?: boolean ;
796889 active ?: boolean ;
797890 dragging ?: boolean ;
891+ label ?: string ;
798892 onChevronDownClick ?: (
799893 e : React . MouseEvent < HTMLElement > ,
800894 activeChartKey : string
@@ -809,6 +903,7 @@ const TabContent = (props: TabContentProps) => {
809903 editable,
810904 draggable,
811905 active,
906+ label,
812907 dragging,
813908 onChevronDownClick,
814909 onSwitchClick,
@@ -825,6 +920,16 @@ const TabContent = (props: TabContentProps) => {
825920 < Icon name = { iconName } />
826921 </ Button >
827922
923+ { label ? (
924+ < Button
925+ variant = "text"
926+ color = "primary"
927+ className = { classes . label }
928+ onClick = { onSwitchClick }
929+ >
930+ { label }
931+ </ Button >
932+ ) : null }
828933 { editable && (
829934 < Button
830935 variant = "text"
0 commit comments