Skip to content

Commit

Permalink
Add Tabs component
Browse files Browse the repository at this point in the history
  • Loading branch information
dgca committed Dec 3, 2024
1 parent 58b4dc5 commit 19fce6a
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 3 deletions.
28 changes: 27 additions & 1 deletion packages/mobile-app/app/(tabs)/balances.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
HStack,
Icon,
IconButton,
Tabs,
Text,
VStack,
} from "@ironfish/tackle-box";
Expand Down Expand Up @@ -31,7 +32,32 @@ export default function Balances() {
flexGrow={1}
borderTopLeftRadius={20}
borderTopRightRadius={20}
/>
>
<Tabs.Root defaultValue="assets">
<Tabs.List>
<Tabs.Trigger value="assets">Assets</Tabs.Trigger>
<Tabs.Trigger value="transactions">Transactions</Tabs.Trigger>
</Tabs.List>
<Tabs.Content value="assets">
<VStack>
<Text>Assets</Text>
<Text>Assets</Text>
<Text>Assets</Text>
<Text>Assets</Text>
<Text>Assets</Text>
</VStack>
</Tabs.Content>
<Tabs.Content value="transactions">
<VStack>
<Text>Transactions</Text>
<Text>Transactions</Text>
<Text>Transactions</Text>
<Text>Transactions</Text>
<Text>Transactions</Text>
</VStack>
</Tabs.Content>
</Tabs.Root>
</Box>
</SafeAreaGradient>
);
}
Expand Down
110 changes: 110 additions & 0 deletions packages/tackle-box/lib/components/Tabs/Tabs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import { Box } from "@/components/Box/Box";
import { HStack } from "@/components/Stack/Stack";
import { createContext, ReactNode, useContext, useState } from "react";
import { css, html } from "react-strict-dom";
import { Text } from "@/components/Text/Text";
import { colors } from "@/vars/colors.stylex";

const TabsContext = createContext<{
activeTab: string;
setActiveTab: (tab: string) => void;
}>({
activeTab: "",
setActiveTab: () => {},
});

function useTabsContext() {
return useContext(TabsContext);
}

type RootProps = {
children: ReactNode;
defaultValue?: string;
};

function Root({ children, defaultValue }: RootProps) {
const [activeTab, setActiveTab] = useState(defaultValue ?? "");

return (
<TabsContext.Provider value={{ activeTab, setActiveTab }}>
{children}
</TabsContext.Provider>
);
}

type ListProps = {
children: ReactNode;
};

function List({ children }: ListProps) {
return (
<HStack justifyContent="center" borderBottomWidth={1} borderColor="divider">
{children}
</HStack>
);
}

type TriggerProps = {
children: ReactNode;
value: string;
};

const triggerStyles = css.create({
wrapper: {
borderWidth: 0,
paddingLeft: 16,
paddingRight: 16,
},
activeIndicator: {
borderBottomWidth: 2,
borderColor: colors.textPrimary,
},
textActive: {
color: "textPrimary",
},
textInactive: {
color: "textSecondary",
},
});

function Trigger({ children, value }: TriggerProps) {
const context = useTabsContext();
const isActive = context.activeTab === value;

return (
<html.button
onClick={() => context.setActiveTab(value)}
style={triggerStyles.wrapper}
>
<Box
borderBottomWidth={2}
borderColor={isActive ? "textPrimary" : "transparent"}
py={4}
>
<Text color={isActive ? "textPrimary" : "textSecondary"}>
{children}
</Text>
</Box>
</html.button>
);
}

type ContentProps = {
children: ReactNode;
value: string;
};

function Content({ children, value }: ContentProps) {
const context = useTabsContext();

return context.activeTab === value ? <>{children}</> : null;
}

const Tabs = {
Root,
List,
Trigger,
Content,
};

export { Tabs };
21 changes: 19 additions & 2 deletions packages/tackle-box/lib/components/Text/Text.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Colors, getColorValue } from "@/vars/colors.stylex";
import { ReactNode } from "react";
import { css, html } from "react-strict-dom";

Expand Down Expand Up @@ -36,17 +37,33 @@ const styles = css.create({
textAlign: (textAlign: "left" | "center" | "right") => ({
textAlign,
}),
color: (color?: string) => ({
color,
}),
});

type Props = {
children?: ReactNode;
size?: Sizes;
textAlign?: "left" | "center" | "right";
color?: Colors;
};

export function Text({ children, size = "md", textAlign = "left" }: Props) {
export function Text({
children,
size = "md",
textAlign = "left",
color = "textPrimary",
}: Props) {
return (
<html.span style={[styles.base, styles[size], styles.textAlign(textAlign)]}>
<html.span
style={[
styles.base,
styles[size],
styles.textAlign(textAlign),
styles.color(getColorValue(color)),
]}
>
{children}
</html.span>
);
Expand Down
1 change: 1 addition & 0 deletions packages/tackle-box/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ export { HStack, VStack } from "@/components/Stack/Stack";
export { Text } from "@/components/Text/Text";
export { TextInput } from "@/components/TextInput/TextInput";
export { Icon } from "@/components/Icon/Icon";
export { Tabs } from "@/components/Tabs/Tabs";
export { css } from "react-strict-dom";
1 change: 1 addition & 0 deletions packages/tackle-box/lib/vars/colors.stylex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export const palette = css.defineVars({
black: "#101010",
white: "#FFFFFF",
pink: "#FFC0CB",
transparent: "transparent",
});

// Theme tokens
Expand Down

0 comments on commit 19fce6a

Please sign in to comment.