-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
229 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
48 changes: 48 additions & 0 deletions
48
packages/tackle-box/lib/components/Polymorphic/Polymorphic.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import { ComponentPropsWithoutRef, PropsWithChildren } from "react"; | ||
import { html } from "react-strict-dom"; | ||
|
||
/** | ||
* Union of possible react-strict-dom elements. E.g. html.div, html.p would equal "div" | "p" | ||
*/ | ||
export type RSDElementTypes = keyof typeof html; | ||
|
||
/** | ||
* Gets the React.ElementType for a given react-strict-dom element. | ||
*/ | ||
type RSDElement<T extends RSDElementTypes> = (typeof html)[T]; | ||
|
||
/** | ||
* Gets the props for a given react-strict-dom element. | ||
*/ | ||
type RSDElementProps<T extends RSDElementTypes> = ComponentPropsWithoutRef< | ||
RSDElement<T> | ||
>; | ||
|
||
/** | ||
* Props for the `as` prop that can be used to change the returned element type. | ||
*/ | ||
type AsProp<TAsProp extends RSDElementTypes> = { | ||
as?: TAsProp; | ||
}; | ||
|
||
/** | ||
* Utility to create props for polymorphic components. | ||
*/ | ||
export type PolymorphicComponentProps< | ||
TAsProp extends RSDElementTypes, | ||
// eslint-disable-next-line @typescript-eslint/no-empty-object-type | ||
TProps extends Record<string, unknown> = {}, | ||
> = PropsWithChildren< | ||
AsProp<TAsProp> & TProps & Omit<RSDElementProps<TAsProp>, keyof TProps> | ||
>; | ||
|
||
export function Polymorphic<TAsProp extends RSDElementTypes = "div">({ | ||
as, | ||
children, | ||
...rest | ||
}: PolymorphicComponentProps<TAsProp>) { | ||
const elementType: RSDElementTypes = as ?? "div"; | ||
const Component = html[elementType]; | ||
|
||
return <Component {...rest}>{children}</Component>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
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"; | ||
|
||
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, | ||
}, | ||
}); | ||
|
||
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 }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters