typescript src/tabs, src/typography (#491)

* first iteration

* tabs generic - remove as from typography

* typography using React.component function

* comma mistake

* ...

* review + add back `as` option for typography.

* linter

* quick fix

* us location descriptor
This commit is contained in:
Timo 2022-08-11 17:59:00 +02:00 committed by GitHub
parent 1dfffce606
commit c09380644b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 122 additions and 87 deletions

View file

@ -15,6 +15,7 @@ limitations under the License.
*/
import React from "react";
import { TabContainer, TabItem } from "./Tabs";
import { ReactComponent as AudioIcon } from "../icons/Audio.svg";
import { ReactComponent as VideoIcon } from "../icons/Video.svg";
@ -29,7 +30,7 @@ export default {
},
};
export const Tabs = () => (
export const Tabs: React.FC<{}> = () => (
<TabContainer>
<TabItem
title={

View file

@ -17,19 +17,28 @@ limitations under the License.
import React, { useRef } from "react";
import { useTabList, useTab, useTabPanel } from "@react-aria/tabs";
import { Item } from "@react-stately/collections";
import { useTabListState } from "@react-stately/tabs";
import styles from "./Tabs.module.css";
import { useTabListState, TabListState } from "@react-stately/tabs";
import classNames from "classnames";
import { AriaTabPanelProps, TabListProps } from "@react-types/tabs";
import { Node } from "@react-types/shared";
export function TabContainer(props) {
const state = useTabListState(props);
const ref = useRef();
import styles from "./Tabs.module.css";
interface TabContainerProps<T> extends TabListProps<T> {
className?: string;
}
export function TabContainer<T extends object>(
props: TabContainerProps<T>
): JSX.Element {
const state = useTabListState<T>(props);
const ref = useRef<HTMLUListElement>();
const { tabListProps } = useTabList(props, state, ref);
return (
<div className={classNames(styles.tabContainer, props.className)}>
<ul {...tabListProps} ref={ref} className={styles.tabList}>
{[...state.collection].map((item) => (
<Tab key={item.key} item={item} state={state} />
<Tab item={item} state={state} />
))}
</ul>
<TabPanel key={state.selectedItem?.key} state={state} />
@ -37,9 +46,14 @@ export function TabContainer(props) {
);
}
function Tab({ item, state }) {
interface TabProps<T> {
item: Node<T>;
state: TabListState<T>;
}
function Tab<T>({ item, state }: TabProps<T>): JSX.Element {
const { key, rendered } = item;
const ref = useRef();
const ref = useRef<HTMLLIElement>();
const { tabProps } = useTab({ key }, state, ref);
return (
@ -56,8 +70,12 @@ function Tab({ item, state }) {
);
}
function TabPanel({ state, ...props }) {
const ref = useRef();
interface TabPanelProps<T> extends AriaTabPanelProps {
state: TabListState<T>;
}
function TabPanel<T>({ state, ...props }: TabPanelProps<T>): JSX.Element {
const ref = useRef<HTMLDivElement>();
const { tabPanelProps } = useTabPanel(props, state, ref);
return (
<div {...tabPanelProps} ref={ref} className={styles.tabPanel}>

View file

@ -15,6 +15,7 @@ limitations under the License.
*/
import React from "react";
import { Headline, Title, Subtitle, Body, Caption, Micro } from "./Typography";
export default {
@ -24,7 +25,7 @@ export default {
},
};
export const Typography = () => (
export const Typography: React.FC<{}> = () => (
<>
<Headline>Headline Semi Bold</Headline>
<Title>Title</Title>

View file

@ -14,12 +14,22 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React, { forwardRef } from "react";
import { createElement, forwardRef, ReactNode } from "react";
import classNames from "classnames";
import { Link as RouterLink } from "react-router-dom";
import * as H from "history";
import styles from "./Typography.module.css";
export const Headline = forwardRef(
interface TypographyProps {
children: ReactNode;
fontWeight?: string;
className?: string;
overflowEllipsis?: boolean;
as?: string;
}
export const Headline = forwardRef<HTMLHeadingElement, TypographyProps>(
(
{
as: Component = "h1",
@ -31,23 +41,23 @@ export const Headline = forwardRef(
},
ref
) => {
return (
<Component
{...rest}
className={classNames(
return createElement(
Component,
{
...rest,
className: classNames(
styles[fontWeight],
{ [styles.overflowEllipsis]: overflowEllipsis },
className
)}
ref={ref}
>
{children}
</Component>
),
ref,
},
children
);
}
);
export const Title = forwardRef(
export const Title = forwardRef<HTMLHeadingElement, TypographyProps>(
(
{
as: Component = "h2",
@ -59,23 +69,23 @@ export const Title = forwardRef(
},
ref
) => {
return (
<Component
{...rest}
className={classNames(
return createElement(
Component,
{
...rest,
className: classNames(
styles[fontWeight],
{ [styles.overflowEllipsis]: overflowEllipsis },
className
)}
ref={ref}
>
{children}
</Component>
),
ref,
},
children
);
}
);
export const Subtitle = forwardRef(
export const Subtitle = forwardRef<HTMLParagraphElement, TypographyProps>(
(
{
as: Component = "h3",
@ -87,23 +97,23 @@ export const Subtitle = forwardRef(
},
ref
) => {
return (
<Component
{...rest}
className={classNames(
return createElement(
Component,
{
...rest,
className: classNames(
styles[fontWeight],
{ [styles.overflowEllipsis]: overflowEllipsis },
className
)}
ref={ref}
>
{children}
</Component>
),
ref,
},
children
);
}
);
export const Body = forwardRef(
export const Body = forwardRef<HTMLParagraphElement, TypographyProps>(
(
{
as: Component = "p",
@ -115,23 +125,23 @@ export const Body = forwardRef(
},
ref
) => {
return (
<Component
{...rest}
className={classNames(
return createElement(
Component,
{
...rest,
className: classNames(
styles[fontWeight],
{ [styles.overflowEllipsis]: overflowEllipsis },
className
)}
ref={ref}
>
{children}
</Component>
),
ref,
},
children
);
}
);
export const Caption = forwardRef(
export const Caption = forwardRef<HTMLParagraphElement, TypographyProps>(
(
{
as: Component = "p",
@ -143,24 +153,24 @@ export const Caption = forwardRef(
},
ref
) => {
return (
<Component
{...rest}
className={classNames(
return createElement(
Component,
{
...rest,
className: classNames(
styles.caption,
styles[fontWeight],
{ [styles.overflowEllipsis]: overflowEllipsis },
className
)}
ref={ref}
>
{children}
</Component>
),
ref,
},
children
);
}
);
export const Micro = forwardRef(
export const Micro = forwardRef<HTMLParagraphElement, TypographyProps>(
(
{
as: Component = "p",
@ -172,24 +182,29 @@ export const Micro = forwardRef(
},
ref
) => {
return (
<Component
{...rest}
className={classNames(
return createElement(
Component,
{
...rest,
className: classNames(
styles.micro,
styles[fontWeight],
{ [styles.overflowEllipsis]: overflowEllipsis },
className
)}
ref={ref}
>
{children}
</Component>
),
ref,
},
children
);
}
);
export const Link = forwardRef(
interface LinkProps extends TypographyProps {
to?: H.LocationDescriptor<unknown>;
color?: string;
href?: string;
}
export const Link = forwardRef<HTMLAnchorElement, LinkProps>(
(
{
as,
@ -204,8 +219,8 @@ export const Link = forwardRef(
},
ref
) => {
const Component = as || (to ? RouterLink : "a");
let externalLinkProps;
const Component: string | RouterLink = as || (to ? RouterLink : "a");
let externalLinkProps: { href: string; target: string; rel: string };
if (href) {
externalLinkProps = {
@ -215,21 +230,21 @@ export const Link = forwardRef(
};
}
return (
<Component
{...externalLinkProps}
{...rest}
to={to}
className={classNames(
return createElement(
Component,
{
...externalLinkProps,
...rest,
to: to,
className: classNames(
styles[color],
styles[fontWeight],
{ [styles.overflowEllipsis]: overflowEllipsis },
className
)}
ref={ref}
>
{children}
</Component>
),
ref: ref,
},
children
);
}
);