Skip to content

Commit

Permalink
Migrate tabs stories to typescript (#814)
Browse files Browse the repository at this point in the history
* 🚚 Rename to tsx extension

* ♻️ Fix props table and default Tab example

* ♻️ Add typescript version of states example

* ♻️ Add width example

* 🚧 Typescript version of panels example

* ♻️ Fix issue with onChange event on div

* ♻️ Typescript version of search story

* ♻️ Typescript for input in panel story

* ♻️ Typescript for styled component example

* ♻️ Add onBlur and onFocus to types and check for their existence

* ♻️ Remove margins

* ♻️ Remove onBlur and onFocus from types

Because we don't change the default method signature anyway

* ♻️ Remove panel header

* Fix args. Sneaky
  • Loading branch information
wenche authored and vnys committed Nov 13, 2020
1 parent 9a5104d commit ec0be28
Show file tree
Hide file tree
Showing 9 changed files with 111 additions and 92 deletions.
16 changes: 8 additions & 8 deletions apps/storybook-react/stories/Banner.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ export const Basic: Story<BannerProps> = (args) => (
</Banner>
)

export const IconAndText: Story<BannerProps> = (args) => (
export const IconAndText: Story<BannerProps> = () => (
<>
<Banner {...args}>
<Banner>
<BannerIcon>
<Icon name="thumbs_up" />
</BannerIcon>
Expand All @@ -52,9 +52,9 @@ export const IconAndText: Story<BannerProps> = (args) => (
</>
)

export const TextAndAction: Story<BannerProps> = (args) => (
export const TextAndAction: Story<BannerProps> = () => (
<>
<Banner {...args}>
<Banner>
<BannerMessage>
You are signed on with another account than Equinor account:
name.lastname@mail.com.
Expand All @@ -66,7 +66,7 @@ export const TextAndAction: Story<BannerProps> = (args) => (
<Button variant="ghost">OK</Button>
</InlineBannerActions>
</Banner>
<Banner {...args}>
<Banner>
<BannerMessage>
You are signed on with another account than Equinor account:
name.lastname@mail.com. This means you have to do something to be able
Expand All @@ -82,9 +82,9 @@ export const TextAndAction: Story<BannerProps> = (args) => (
</>
)

export const IconAndTextAndActions: Story<BannerProps> = (args) => (
export const IconAndTextAndActions: Story<BannerProps> = () => (
<>
<Banner {...args}>
<Banner>
<BannerIcon variant="warning">
<Icon name="mood_sad" />
</BannerIcon>
Expand All @@ -96,7 +96,7 @@ export const IconAndTextAndActions: Story<BannerProps> = (args) => (
<Button>Action</Button>
</BannerActions>
</Banner>
<Banner {...args}>
<Banner>
<BannerIcon>
<Icon name="save" />
</BannerIcon>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,81 +1,89 @@
import React, { useState, useEffect, useRef } from 'react'
import styled from 'styled-components'
import { Tabs, Typography, Search } from '@equinor/eds-core-react'
import { Tabs, TabsProps, Typography, Search } from '@equinor/eds-core-react'
import { Story, Meta } from '@storybook/react'
import { action } from '@storybook/addon-actions'

const { TabList, Tab, TabPanels, TabPanel } = Tabs

// eslint-disable-next-line @typescript-eslint/no-empty-function
const noop = () => {}

export default {
title: 'Components/Tabs',
component: Tabs,
}
subcomponents: { TabList, Tab, TabPanels, TabPanel },
} as Meta

const Wrapper = styled.div`
margin: 32px;
display: grid;
grid-gap: 24px;
`
export const Default: Story<TabsProps> = (args) => (
<Tabs {...args}>
<TabList>
<Tab>One</Tab>
<Tab>Two</Tab>
</TabList>
<TabPanels>
<TabPanel>Panel one</TabPanel>
<TabPanel>Panel two</TabPanel>
</TabPanels>
</Tabs>
)

export const tabStates = () => {
const focusedRef = useRef(null)
export const States: Story<TabsProps> = () => {
const focusedRef = useRef<HTMLButtonElement>(null)

useEffect(() => {
focusedRef.current.focus()
}, [])

return (
<Wrapper>
<Tabs activeTab={2} onChange={noop}>
<TabList>
<Tab>Enabled</Tab>
<Tab disabled>Disabled</Tab>
<Tab active>Active</Tab>
<Tab data-hover>Hover</Tab>
<Tab data-focus ref={focusedRef}>
Focus
</Tab>
</TabList>
</Tabs>
</Wrapper>
<Tabs activeTab={2} onChange={noop}>
<TabList>
<Tab>Enabled</Tab>
<Tab disabled>Disabled</Tab>
<Tab active>Active</Tab>
<Tab data-hover>Hover</Tab>
<Tab data-focus ref={focusedRef}>
Focus
</Tab>
</TabList>
</Tabs>
)
}

export const tabWidths = () => {
export const Widths: Story<TabsProps> = () => {
return (
<Wrapper>
<Typography variant="h1">Tab widths</Typography>
<Typography variant="h2">minWidth</Typography>
<>
<Typography variant="h4">minWidth</Typography>
<Tabs activeTab={1} onChange={noop} variant="minWidth">
<TabList>
<Tab>Text</Tab>
<Tab>More text</Tab>
<Tab>A really long line of text</Tab>
</TabList>
</Tabs>
<Typography variant="h2">fullWidth</Typography>
<Typography variant="h4" style={{ marginTop: '1rem' }}>
fullWidth
</Typography>
<Tabs activeTab={1} onChange={noop} variant="fullWidth">
<TabList>
<Tab>Text</Tab>
<Tab>More text</Tab>
<Tab>A really long line of text</Tab>
</TabList>
</Tabs>
</Wrapper>
</>
)
}

export const tabPanels = () => {
export const Panels: Story<TabsProps> = () => {
const [activeTab, setActiveTab] = useState(1)

const handleChange = (index) => {
const handleChange = (index: number) => {
setActiveTab(index)
}

return (
<Wrapper>
<Typography variant="h1">Tab with panels</Typography>
<>
<Typography variant="body_long">
To navigate using they keyboard, use tab key to move from tab to tab
panel, shift + tab to go backwards, use left and right arrow keys to
Expand All @@ -96,32 +104,32 @@ export const tabPanels = () => {
<TabPanel>Panel four</TabPanel>
</TabPanels>
</Tabs>
</Wrapper>
</>
)
}

export const tabsAndSearch = () => {
export const WithSearch: Story<TabsProps> = () => {
const [searchText, setSearchText] = useState('')
const [activeTab, setActiveTab] = useState(0)

const handleOnTextChange = (event) => {
const handleOnTextChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const value = event.target.value
setSearchText(value)
}
const handleChange = (index) => {
const handleChange = (index: number) => {
setActiveTab(index)
}

const handleFocus = (e) => {
const handleFocus = (e: React.FocusEvent<HTMLDivElement>) => {
action('handleFocus')(e.target.textContent)
}

const handleBlur = (e) => {
const handleBlur = (e: React.FocusEvent<HTMLDivElement>) => {
action('handleBlur')(e.target.textContent)
}

return (
<div style={{ margin: '4rem' }}>
<>
<Search
value={searchText}
placeholder={'Search '}
Expand All @@ -144,32 +152,32 @@ export const tabsAndSearch = () => {
<TabPanel>Panel two</TabPanel>
</TabPanels>
</Tabs>
</div>
</>
)
}

export const tabsAndInputInPanel = () => {
export const WithInputInPanel: Story<TabsProps> = () => {
const [searchText, setSearchText] = useState('')
const [activeTab, setActiveTab] = useState(0)

const handleOnTextChange = (event) => {
const handleOnTextChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const value = event.target.value
setSearchText(value)
}
const handleChange = (index) => {
const handleChange = (index: number) => {
setActiveTab(index)
}

const handleFocus = (e) => {
const handleFocus = (e: React.FocusEvent<HTMLDivElement>) => {
action('handleFocus')(e.target.textContent)
}

const handleBlur = (e) => {
const handleBlur = (e: React.FocusEvent<HTMLDivElement>) => {
action('handleBlur')(e.target.textContent)
}

return (
<div style={{ margin: '4rem' }}>
<>
<Tabs
style={{ marginTop: '2rem' }}
activeTab={activeTab}
Expand Down Expand Up @@ -198,7 +206,7 @@ export const tabsAndInputInPanel = () => {
</TabPanel>
</TabPanels>
</Tabs>
</div>
</>
)
}

Expand All @@ -210,10 +218,10 @@ const StyledTabPanel = styled(TabPanel)`
padding: 32px;
background: peachpuff;
`
export const tabsWithStyledComponents = () => {
export const WithStyledComponent: Story<TabsProps> = () => {
const [activeTab, setActiveTab] = useState(1)

const handleChange = (index) => {
const handleChange = (index: number) => {
setActiveTab(index)
}

Expand All @@ -224,7 +232,7 @@ export const tabsWithStyledComponents = () => {
]

return (
<Wrapper>
<>
<Typography variant="h1">
Tab with panels rendered from collection
</Typography>
Expand All @@ -240,6 +248,10 @@ export const tabsWithStyledComponents = () => {
))}
</TabPanels>
</Tabs>
</Wrapper>
</>
)
}

WithSearch.storyName = 'With search'
WithInputInPanel.storyName = 'With input in panel'
WithStyledComponent.storyName = 'With styled component'
18 changes: 9 additions & 9 deletions libraries/core-react/src/Tabs/Tab.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { forwardRef } from 'react'
import React, { forwardRef, ButtonHTMLAttributes } from 'react'
import styled, { css } from 'styled-components'
import { tab as tokens } from './Tabs.tokens'

Expand Down Expand Up @@ -27,15 +27,15 @@ const focusedStyles = css`
outline-offset: ${outlineOffset};
`

const StyledTab = styled.button.attrs<Props>(
const StyledTab = styled.button.attrs<TabProps>(
({ active = false, disabled = false }) => ({
type: 'button',
role: 'tab',
'aria-selected': active,
'aria-disabled': disabled,
tabIndex: active ? '0' : '-1',
}),
)<Props>`
)<TabProps>`
appearance: none;
box-sizing: border-box;
font-family: inherit;
Expand Down Expand Up @@ -82,16 +82,16 @@ const StyledTab = styled.button.attrs<Props>(
}
`

export type Props = {
export type TabProps = {
/** If `true`, the tab will be active. */
active?: boolean
/** If `true`, the tab will be disabled. */
disabled?: boolean
}
} & ButtonHTMLAttributes<HTMLButtonElement>

export const Tab = forwardRef<
HTMLButtonElement,
Props & React.HTMLAttributes<HTMLButtonElement>
>(function Tab(props, ref) {
export const Tab = forwardRef<HTMLButtonElement, TabProps>(function Tab(
props,
ref,
) {
return <StyledTab ref={ref} {...props} />
})
13 changes: 7 additions & 6 deletions libraries/core-react/src/Tabs/TabList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import React, {
useCallback,
useEffect,
ReactElement,
HTMLAttributes,
} from 'react'
import styled from 'styled-components'
import { useCombinedRefs } from '../_common/useCombinedRefs'
Expand All @@ -21,26 +22,26 @@ const variants: VariantsRecord = {
minWidth: 'max-content',
}

type StyledProps = Props
type StyledProps = TabListProps

const StyledTabList = styled.div.attrs(
(): React.HTMLAttributes<HTMLDivElement> => ({
(): HTMLAttributes<HTMLDivElement> => ({
role: 'tablist',
}),
)<StyledProps>`
display: grid;
grid-auto-flow: column;
grid-auto-columns: ${({ variant }) => variants[variant]};
grid-auto-columns: ${({ variant }) => variants[variant] as VariantsRecord};
`

type Props = {
type TabListProps = {
/** Sets the width of the tabs */
variant?: Variants
} & React.HTMLAttributes<HTMLDivElement>
} & HTMLAttributes<HTMLDivElement>

type TabChild = JSX.IntrinsicElements['button'] & ReactElement

const TabList = forwardRef<HTMLDivElement, Props>(function TabsList(
const TabList = forwardRef<HTMLDivElement, TabListProps>(function TabsList(
{ children = [], ...props },
ref,
) {
Expand Down
Loading

0 comments on commit ec0be28

Please sign in to comment.