Skip to content

Commit 3312da2

Browse files
committed
feat: Add titles to tabs
1 parent 2e55915 commit 3312da2

2 files changed

Lines changed: 134 additions & 27 deletions

File tree

app/components/chart-selection-tabs.tsx

Lines changed: 132 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
} from "@mui/material";
1515
import { makeStyles } from "@mui/styles";
1616
import { PUBLISHED_STATE } from "@prisma/client";
17+
import clsx from "clsx";
1718
import { useSession } from "next-auth/react";
1819
import Link from "next/link";
1920
import { useRouter } from "next/router";
@@ -50,7 +51,7 @@ import { useUserConfig } from "@/domain/user-configs";
5051
import { useFlag } from "@/flags";
5152
import { useDataCubesComponentsQuery } from "@/graphql/hooks";
5253
import { Icon, IconName } from "@/icons";
53-
import { useLocale } from "@/src";
54+
import { defaultLocale, useLocale } from "@/locales";
5455
import { createConfig, updateConfig } from "@/utils/chart-config/api";
5556
import { createChartId } from "@/utils/create-chart-id";
5657
import { 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

352361
type 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+
621677
const 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"

app/locales/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export { defaultLocale, i18n, locales, parseLocaleString } from "./locales";
2+
export { LocaleProvider, useLocale } from "./use-locale";

0 commit comments

Comments
 (0)