tldraw/components/style-panel/style-panel.tsx

142 lines
3.4 KiB
TypeScript
Raw Normal View History

2021-05-28 20:30:27 +00:00
import styled from 'styles'
import state, { useSelector } from 'state'
import * as Panel from 'components/panel'
import { useRef } from 'react'
import { IconButton } from 'components/shared'
import { ChevronDown, X } from 'react-feather'
import ShapesFunctions from './shapes-functions'
2021-05-28 20:30:27 +00:00
import AlignDistribute from './align-distribute'
import SizePicker from './size-picker'
2021-06-01 21:49:32 +00:00
import DashPicker from './dash-picker'
import QuickColorSelect from './quick-color-select'
import ColorPicker from './color-picker'
import IsFilledPicker from './is-filled-picker'
import QuickSizeSelect from './quick-size-select'
import QuickdashSelect from './quick-dash-select'
2021-06-02 21:17:38 +00:00
import Tooltip from 'components/tooltip'
2021-05-26 10:34:10 +00:00
const breakpoints = { '@initial': 'mobile', '@sm': 'small' } as any
const handleStylePanelOpen = () => state.send('TOGGLED_STYLE_PANEL_OPEN')
2021-06-21 21:35:28 +00:00
export default function StylePanel(): JSX.Element {
2021-05-26 10:34:10 +00:00
const rContainer = useRef<HTMLDivElement>(null)
2021-05-26 10:34:10 +00:00
const isOpen = useSelector((s) => s.data.settings.isStyleOpen)
return (
<StylePanelRoot dir="ltr" ref={rContainer} isOpen={isOpen}>
2021-05-26 10:34:10 +00:00
{isOpen ? (
<SelectedShapeStyles />
) : (
2021-06-01 21:49:32 +00:00
<>
<QuickColorSelect />
<QuickSizeSelect />
<QuickdashSelect />
2021-06-01 21:49:32 +00:00
<IconButton
bp={breakpoints}
2021-06-01 21:49:32 +00:00
title="Style"
size="small"
onClick={handleStylePanelOpen}
2021-06-01 21:49:32 +00:00
>
2021-06-02 21:17:38 +00:00
<Tooltip label="More">
<ChevronDown />
</Tooltip>
2021-06-01 21:49:32 +00:00
</IconButton>
</>
2021-05-26 10:34:10 +00:00
)}
</StylePanelRoot>
)
}
// This panel is going to be hard to keep cool, as we're selecting computed
// information, based on the user's current selection. We might have to keep
// track of this data manually within our state.
2021-06-21 21:35:28 +00:00
function SelectedShapeStyles(): JSX.Element {
const selectedShapesCount = useSelector((s) => s.values.selectedIds.length)
2021-05-26 21:47:46 +00:00
2021-05-26 10:34:10 +00:00
return (
<Panel.Layout>
2021-05-28 20:30:27 +00:00
<Panel.Header side="right">
2021-05-26 10:34:10 +00:00
<h3>Style</h3>
<IconButton
bp={breakpoints}
size="small"
onClick={handleStylePanelOpen}
>
2021-05-27 17:59:40 +00:00
<X />
</IconButton>
2021-05-26 10:34:10 +00:00
</Panel.Header>
2021-05-26 19:20:52 +00:00
<Content>
<ColorPicker />
<IsFilledPicker />
2021-05-28 20:30:27 +00:00
<Row>
<label htmlFor="size">Size</label>
<SizePicker />
2021-05-28 20:30:27 +00:00
</Row>
2021-06-01 21:49:32 +00:00
<Row>
<label htmlFor="dash">Dash</label>
<DashPicker />
2021-06-01 21:49:32 +00:00
</Row>
<ShapesFunctions />
2021-05-29 22:27:19 +00:00
<AlignDistribute
hasTwoOrMore={selectedShapesCount > 1}
hasThreeOrMore={selectedShapesCount > 2}
2021-05-29 22:27:19 +00:00
/>
2021-05-26 19:20:52 +00:00
</Content>
2021-05-26 10:34:10 +00:00
</Panel.Layout>
)
}
const StylePanelRoot = styled(Panel.Root, {
2021-05-26 19:20:52 +00:00
minWidth: 1,
width: 184,
maxWidth: 184,
2021-05-28 20:30:27 +00:00
overflow: 'hidden',
position: 'relative',
2021-05-30 13:49:33 +00:00
border: '1px solid $panel',
boxShadow: '0px 2px 4px rgba(0,0,0,.2)',
2021-06-01 21:49:32 +00:00
display: 'flex',
alignItems: 'center',
pointerEvents: 'all',
2021-05-26 10:34:10 +00:00
variants: {
isOpen: {
2021-05-26 19:20:52 +00:00
true: {},
2021-05-26 10:34:10 +00:00
false: {
2021-05-30 13:49:33 +00:00
padding: 2,
2021-06-01 21:49:32 +00:00
width: 'fit-content',
2021-05-26 10:34:10 +00:00
},
},
},
})
2021-05-26 19:20:52 +00:00
const Content = styled(Panel.Content, {
padding: 8,
2021-05-26 10:34:10 +00:00
})
2021-05-28 20:30:27 +00:00
const Row = styled('div', {
position: 'relative',
display: 'flex',
width: '100%',
background: 'none',
border: 'none',
outline: 'none',
alignItems: 'center',
justifyContent: 'space-between',
padding: '4px 2px 4px 12px',
'& label': {
fontFamily: '$ui',
2021-06-27 21:30:37 +00:00
fontWeight: 400,
fontSize: '$1',
2021-05-28 20:30:27 +00:00
margin: 0,
padding: 0,
},
'& > svg': {
position: 'relative',
},
})