Skip to content
This repository has been archived by the owner on Oct 8, 2022. It is now read-only.

Commit

Permalink
feat: Allow the board to be styled (#278)
Browse files Browse the repository at this point in the history
BREAKING CHANGE: You need to import the default styles or provide your own: `import '@lourenci/react-kanban/dist/styles.css'`.
  • Loading branch information
lourenci committed Mar 11, 2020
1 parent b359677 commit 0d64493
Show file tree
Hide file tree
Showing 22 changed files with 339 additions and 275 deletions.
30 changes: 27 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,15 @@ Yet another Kanban/Trello board lib for React.
## ❓ Why?

- 👊 Reliable: 100% tested on CI; 100% coverage; 100% SemVer.
- 🎮 Having fun: Play with Hooks 🎣 and Styled Components 💅🏻.
- 🎮 Having fun: Play with Hooks 🎣 and ~~Styled Components~~.
- ♿️ Accessible: Keyboard and mobile friendly.
- 🔌 Pluggable: For use in projects.

## 🛠 Install and usage

Since this project use Hooks and Styled Components, you have to install them:
Since this project use Hooks, you have to install them:

- `react>=16.8.5`
- `styled-components>=4`

After, Install the lib on your project:

Expand All @@ -37,6 +36,7 @@ Import the lib and use it on your project:

```js
import Board from '@lourenci/react-kanban'
import '@lourenci/react-kanban/dist/styles.css'

const board = {
columns: [
Expand Down Expand Up @@ -496,6 +496,30 @@ function onCardNew (newCard) {
| `fromColumn` | Column where the card is |
| `card` | Card to be removed |

## 💅🏻 Styling

**🚧 WIP \* This might change in the future.**

You can either style all the board or import our style and override the styles you want:

| Class |
| ----- |
| `react-kanban-board` |
| `react-kanban-card` |
| `react-kanban-card-skeleton` |
| `react-kanban-card--dragging` |
| `react-kanban-card__description` |
| `react-kanban-card__title` |
| `react-kanban-column` |
| `react-kanban-card-adder-form` |
| `react-kanban-card-adder-button` |
| `react-kanban-card-adder-form__title` |
| `react-kanban-card-adder-form__description` |
| `react-kanban-card-adder-form__button` |
| `react-kanban-column-header` |
| `react-kanban-column-header__button` |
| `react-kanban-column-adder-button` |

## 🧪 Tests

### Unit
Expand Down
1 change: 1 addition & 0 deletions assets/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from 'react'
import { render } from 'react-dom'
import Board from '../src'
import getUrlParams from './services/getUrlParams'
import '../src/styles.scss'

const board = {
columns: [
Expand Down
3 changes: 2 additions & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ module.exports = {
setupFilesAfterEnv: ['@testing-library/jest-dom/extend-expect'],
moduleNameMapper: {
'^@services/(.*)$': '<rootDir>/src/services/$1',
'^@components/(.*)$': '<rootDir>/src/components/$1'
'^@components/(.*)$': '<rootDir>/src/components/$1',
'\\.s?css$': 'identity-obj-proxy'
}
}
12 changes: 8 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
"description": "Yet another Kanban/Trello board lib for React.",
"main": "dist/index.js",
"files": [
"dist/index.js"
"dist/index.js",
"dist/styles.css"
],
"repository": "https://github.com/lourenci/react-kanban",
"author": "Leandro Lourenci",
"license": "MIT",
"peerDependencies": {
"react": "^16.8.0",
"react-dom": "^16.8.0",
"styled-components": ">=3"
"react-dom": "^16.8.0"
},
"devDependencies": {
"@babel/core": "7.8.7",
Expand All @@ -28,6 +28,7 @@
"babel-plugin-istanbul": "6.0.0",
"babel-plugin-react-remove-properties": "0.3.0",
"cross-env": "7.0.2",
"css-loader": "^3.4.2",
"cypress": "4.1.0",
"eslint": "6.8.0",
"eslint-config-prettier": "6.10.0",
Expand All @@ -43,15 +44,18 @@
"eslint-plugin-react-hooks": "2.5.0",
"eslint-plugin-standard": "4.0.1",
"html-webpack-plugin": "3.2.0",
"identity-obj-proxy": "^3.0.0",
"istanbul-lib-coverage": "3.0.0",
"jest": "25.1.0",
"mini-css-extract-plugin": "^0.9.0",
"node-sass": "^4.13.1",
"nyc": "15.0.0",
"prettier": "1.19.1",
"react": "16.13.0",
"react-dom": "16.13.0",
"sass-loader": "^8.0.2",
"semantic-release": "17.0.4",
"start-server-and-test": "1.10.8",
"styled-components": "5.0.1",
"webpack": "4.42.0",
"webpack-cli": "3.3.11",
"webpack-dev-server": "3.10.3"
Expand Down
7 changes: 0 additions & 7 deletions src/components/Board/components/CardSkeleton/index.js

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,19 +1,13 @@
import React from 'react'
import { Draggable } from 'react-beautiful-dnd'
import styled from 'styled-components'

const CardTemplate = styled.div`
display: inline-block;
white-space: normal;
`

function Card({ children, index, renderCard, disableCardDrag }) {
return (
<Draggable draggableId={String(children.id)} index={index} isDragDisabled={disableCardDrag}>
{(provided, { isDragging }) => {
return (
<div ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps} data-testid='card'>
<CardTemplate>{renderCard(isDragging)}</CardTemplate>
<div style={{ display: 'inline-block', whiteSpace: 'normal' }}>{renderCard(isDragging)}</div>
</div>
)
}}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,56 +1,5 @@
import React, { useRef } from 'react'
import styled from 'styled-components'
import { when } from '@services/utils'
import CardSkeleton from '@components/Board/components/CardSkeleton'

const DefaultCard = styled(CardSkeleton)`
border-radius: 3px;
background-color: #fff;
padding: 10px;
margin-bottom: 7px;
input {
border: 0px;
font-family: inherit;
font-size: inherit;
}
`

const CardTitle = styled.input`
font-weight: bold;
border-bottom: 1px solid #eee;
padding-bottom: 5px;
font-weight: bold;
display: flex;
justify-content: space-between;
width: 100%;
padding: 0px;
`

const CardDescription = styled.input`
input {
width: 100%;
}
margin-top: 10px;
`
const StyledFormButtons = styled.div`
display: flex;
justify-content: space-between;
margin-top: 5px;
`

const StyledButton = styled.button`
background-color: #eee;
border: none;
padding: 5px;
width: 45%;
margin-top: 5px;
border-radius: 3px;
&:hover {
transition: 0.3s;
cursor: pointer;
background-color: #ccc;
}
`

function CardForm({ onConfirm, onCancel }) {
const inputCardTitle = useRef()
Expand All @@ -64,18 +13,31 @@ function CardForm({ onConfirm, onCancel }) {
}

return (
<DefaultCard>
<div className='react-kanban-card-adder-form'>
<form onSubmit={addCard}>
<CardTitle name='title' autoFocus defaultValue='Title' ref={inputCardTitle} />
<CardDescription name='description' defaultValue='Description' ref={inputCardDescription} />
<StyledFormButtons>
<StyledButton type='submit'>Add</StyledButton>
<StyledButton type='button' onClick={onCancel}>
<input
className='react-kanban-card-adder-form__title'
name='title'
autoFocus
defaultValue='Title'
ref={inputCardTitle}
/>
<input
className='react-kanban-card-adder-form__description'
name='description'
defaultValue='Description'
ref={inputCardDescription}
/>
<div style={{ display: 'flex', justifyContent: 'space-between', marginTop: '5px' }}>
<button className='react-kanban-card-adder-form__button' type='submit'>
Add
</button>
<button className='react-kanban-card-adder-form__button' type='button' onClick={onCancel}>
Cancel
</StyledButton>
</StyledFormButtons>
</button>
</div>
</form>
</DefaultCard>
</div>
)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,6 @@
import React, { useState } from 'react'
import styled from 'styled-components'
import CardForm from './components/CardForm'

const AddCardButton = styled.button`
width: 100%;
margin-top: 5px;
background-color: transparent;
cursor: pointer;
border: 1px solid #ccc;
transition: 0.3s;
:hover {
background-color: #ccc;
}
border-radius: 3px;
font-size: 20px;
margin-bottom: 10px;
font-weight: bold;
`

export default function CardAdder({ column, onConfirm }) {
function confirmCard(card) {
onConfirm(column, card)
Expand All @@ -31,7 +14,9 @@ export default function CardAdder({ column, onConfirm }) {
{addingCard ? (
<CardForm onConfirm={confirmCard} onCancel={() => setAddingCard(false)} />
) : (
<AddCardButton onClick={() => setAddingCard(!addingCard)}>+</AddCardButton>
<button className='react-kanban-card-adder-button' onClick={() => setAddingCard(!addingCard)}>
+
</button>
)}
</>
)
Expand Down
80 changes: 43 additions & 37 deletions src/components/Board/components/Column/index.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,15 @@
import React from 'react'
import styled from 'styled-components'
import { Draggable } from 'react-beautiful-dnd'
import Card from './components/Card'
import CardSkeleton from '../CardSkeleton'
import withDroppable from '../../../withDroppable'
import CardAdder from './components/CardAdder'
import { pickPropOut } from '@services/utils'

export const StyledColumn = styled.div`
height: 100%;
display: inline-block;
padding: 15px;
border-radius: 2px;
background-color: #eee;
margin: 5px;
vertical-align: top;
`
const ColumnEmptyPlaceholder = React.forwardRef((props, ref) => (
<div ref={ref} style={{ minHeight: '28px' }} {...props} />
))

const DroppableColumn = withDroppable(styled.div`
min-height: 28px;
`)
const DroppableColumn = withDroppable(ColumnEmptyPlaceholder)

function Column({
children,
Expand All @@ -32,30 +23,45 @@ function Column({
}) {
return (
<Draggable draggableId={`column-draggable-${children.id}`} index={columnIndex} isDragDisabled={disableColumnDrag}>
{columnProvided => (
<StyledColumn ref={columnProvided.innerRef} {...columnProvided.draggableProps} data-testid='column'>
<div {...columnProvided.dragHandleProps} data-testid='column-header'>
{renderColumnHeader(children)}
{columnProvided => {
const draggablePropsWithoutStyle = pickPropOut(columnProvided.draggableProps, 'style')

return (
<div
ref={columnProvided.innerRef}
{...draggablePropsWithoutStyle}
style={{
height: '100%',
display: 'inline-block',
verticalAlign: 'top',
...columnProvided.draggableProps.style
}}
className='react-kanban-column'
data-testid='column'
>
<div {...columnProvided.dragHandleProps} data-testid='column-header'>
{renderColumnHeader(children)}
</div>
{allowAddCard && <CardAdder column={children} onConfirm={onCardNew} />}
<DroppableColumn droppableId={String(children.id)}>
{children.cards.length ? (
children.cards.map((card, index) => (
<Card
key={card.id}
index={index}
renderCard={dragging => renderCard(children, card, dragging)}
disableCardDrag={disableCardDrag}
>
{card}
</Card>
))
) : (
<div className='react-kanban-card-skeleton' />
)}
</DroppableColumn>
</div>
{allowAddCard && <CardAdder column={children} onConfirm={onCardNew} />}
<DroppableColumn droppableId={String(children.id)}>
{children.cards.length ? (
children.cards.map((card, index) => (
<Card
key={card.id}
index={index}
renderCard={dragging => renderCard(children, card, dragging)}
disableCardDrag={disableCardDrag}
>
{card}
</Card>
))
) : (
<CardSkeleton />
)}
</DroppableColumn>
</StyledColumn>
)}
)
}}
</Draggable>
)
}
Expand Down

0 comments on commit 0d64493

Please sign in to comment.