Skip to content

Commit

Permalink
Merge pull request #896 from contiamo/feature/card-column-tabs
Browse files Browse the repository at this point in the history
**Feature:** Add tabs to CardColumn
  • Loading branch information
Tejas Kumar authored Jan 25, 2019
2 parents 3d42cca + fc62f00 commit 91d4a8e
Show file tree
Hide file tree
Showing 2 changed files with 155 additions and 25 deletions.
123 changes: 98 additions & 25 deletions src/CardColumn/CardColumn.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import * as React from "react"

import { Tab } from "../Internals/Tabs"
import { DefaultProps } from "../types"
import styled from "../utils/styled"

export interface CardColumnProps extends DefaultProps {
export interface BaseCardColumnProps extends DefaultProps {
/** Column title */
title?: string
/** Align the content to the right */
Expand All @@ -15,24 +17,46 @@ export interface CardColumnProps extends DefaultProps {
noPadding?: boolean
}

const Container = styled("div")<CardColumnProps>(({ theme, contentRight, flexColumn, fullWidth, noPadding }) => ({
label: "card-column",
height: "min-content",
minWidth: 280 / 2,
padding: noPadding ? 0 : theme.space.element / 2,
flex: fullWidth ? "1 1 100%" : "1 0",
" img": {
maxWidth: "100%",
},
textAlign: contentRight ? "right" : "left",
...(flexColumn
? {
display: "flex",
flexDirection: "column",
justifyContent: contentRight ? "flex-end" : "flex-start",
}
: {}),
}))
export interface CardColumnPropsWithTabs extends BaseCardColumnProps {
/** Tabs for the CardColumn header */
tabs: Tab[]
/** What's the currently active tab? */
activeTabName?: string
/** What happens when we change tabs? */
onTabChange?: (newTabName: string) => void
children?: never
}

export interface CardColumnPropsWithoutTabs extends BaseCardColumnProps {
/** Do we have tabs? */
tabs?: never
activeTabName?: never
onTabChange?: never
children?: React.ReactNode
}

export type CardColumnProps = CardColumnPropsWithTabs | CardColumnPropsWithoutTabs

const Container = styled("div")<Pick<CardColumnProps, "contentRight" | "flexColumn" | "fullWidth" | "noPadding">>(
({ theme, contentRight, flexColumn, fullWidth, noPadding }) => ({
label: "card-column",
height: "min-content",
minWidth: 280 / 2,
padding: noPadding ? 0 : theme.space.element / 2,
flex: fullWidth ? "1 1 100%" : "1 0",
img: {
maxWidth: "100%",
},
textAlign: contentRight ? "right" : "left",
...(flexColumn
? {
display: "flex",
flexDirection: "column",
justifyContent: contentRight ? "flex-end" : "flex-start",
}
: {}),
}),
)

const Title = styled("div")(({ theme }) => ({
fontFamily: theme.font.family.main,
Expand All @@ -42,13 +66,62 @@ const Title = styled("div")(({ theme }) => ({
borderBottom: `1px solid ${theme.color.separators.default}`,
paddingBottom: theme.space.small,
marginBottom: theme.space.content,
display: "flex",
alignItems: "center",
}))

const CardColumn: React.SFC<CardColumnProps> = ({ title, children, ...props }) => (
<Container {...props}>
{title && <Title>{title}</Title>}
{children}
</Container>
)
const Tabs = styled("div")`
display: flex;
align-items: center;
margin-left: ${({ theme }) => theme.space.medium}px;
`

const Tab = styled("div")<{ active: boolean }>`
padding: 0 ${({ theme }) => theme.space.content}px;
color: ${({ theme }) => theme.color.text.lighter};
font-size: ${({ theme }) => theme.font.size.small}px;
padding-bottom: ${({ theme }) => theme.space.base}px;
border-bottom: 2px solid ${({ theme, active }) => (active ? theme.color.text.lighter : "transparent")};
text-transform: uppercase;
margin-bottom: ${({ theme }) => -(theme.space.medium + 1)}px;
cursor: pointer;
`

const CardColumn = ({ title, tabs, activeTabName, onTabChange, children, ...props }: CardColumnProps) => {
if (tabs) {
return (
<Container {...props}>
{title && (
<Title>
{title}
<Tabs>
{tabs.map(({ name }, index) => (
<Tab
key={index}
onClick={() => {
if (onTabChange) {
onTabChange(name)
}
}}
active={activeTabName === name}
>
{name}
</Tab>
))}
</Tabs>
</Title>
)}
{(tabs.find(({ name }) => name === activeTabName) || { ...tabs[0] }).children}
</Container>
)
}

return (
<Container {...props}>
{title && <Title>{title}</Title>}
{children}
</Container>
)
}

export default CardColumn
57 changes: 57 additions & 0 deletions src/CardColumn/README.md
Original file line number Diff line number Diff line change
@@ -1 +1,58 @@
Card columns are used to group content within a card into vertical columns.

# Basic Usage

Here's how you can easily use this component.

```jsx
<Card title="Bundle Information">
<CardColumns>
<CardColumn title="Contributor">@tejasq</CardColumn>
<CardColumn title="Other Contributor">@imogenf</CardColumn>
<CardColumn title="Also other Contributor">@stereobooster</CardColumn>
<CardColumn title="Yet another Contributor">@fabien0102</CardColumn>
</CardColumns>
</Card>
```

# With Tabs

Card columns can be used with tabs when required. Here's how.

```jsx
const myData = {
_page: 1,
_pageSize: 1,
}
const myEndpointUrl = "https://me.now.sh/my-service"
initialState = {
playgroundBodyType: "CURL",
}

const tab1 = {
name: "CURL",
children: (
<Code syntax="bash">{`curl \\
'${myEndpointUrl}' \\
-H 'content-type: application/json' \\
-H "Authorization: Bearer $SERVICE_ACCOUNT_TOKEN" \\
-H 'accept: */*' \\
--data-binary '${JSON.stringify(myData, null, 2)}'`}</Code>
),
}

const tab2 = {
name: "JSON",
children: <Code syntax="javascript">{JSON.stringify(myData, null, 2)}</Code>,
}
;<Card title="Some Versions of Snippets">
<CardColumns>
<CardColumn
title="Request Body"
activeTabName={state.playgroundBodyType}
onTabChange={playgroundBodyType => setState({ playgroundBodyType })}
tabs={[tab1, tab2]}
/>
</CardColumns>
</Card>
```

0 comments on commit 91d4a8e

Please sign in to comment.