Composer: use Tabler svg icons
This commit is contained in:
parent
5ac5ef2e38
commit
3eb4eeed59
9 changed files with 133 additions and 61 deletions
45
app/soapbox/features/compose/components/markdown_button.js
Normal file
45
app/soapbox/features/compose/components/markdown_button.js
Normal file
|
@ -0,0 +1,45 @@
|
|||
import React from 'react';
|
||||
import IconButton from '../../../components/icon_button';
|
||||
import PropTypes from 'prop-types';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import classNames from 'classnames';
|
||||
|
||||
const messages = defineMessages({
|
||||
marked: { id: 'compose_form.markdown.marked', defaultMessage: 'Post markdown enabled' },
|
||||
unmarked: { id: 'compose_form.markdown.unmarked', defaultMessage: 'Post markdown disabled' },
|
||||
});
|
||||
|
||||
export default @injectIntl
|
||||
class MarkdownButton extends React.PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
active: PropTypes.bool,
|
||||
onClick: PropTypes.func.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
unavailable: PropTypes.bool,
|
||||
};
|
||||
|
||||
handleClick = () => {
|
||||
this.props.onClick();
|
||||
}
|
||||
|
||||
render() {
|
||||
const { intl, active, unavailable } = this.props;
|
||||
|
||||
if (unavailable) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='compose-form__markdown-button'>
|
||||
<IconButton
|
||||
className={classNames('compose-form__markdown-button-icon', { active })}
|
||||
src={require('@tabler/icons/icons/markdown.svg')}
|
||||
title={intl.formatMessage(active ? messages.marked : messages.unmarked)}
|
||||
onClick={this.handleClick}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -8,11 +8,6 @@ const messages = defineMessages({
|
|||
remove_poll: { id: 'poll_button.remove_poll', defaultMessage: 'Remove poll' },
|
||||
});
|
||||
|
||||
const iconStyle = {
|
||||
height: null,
|
||||
lineHeight: '27px',
|
||||
};
|
||||
|
||||
export default
|
||||
@injectIntl
|
||||
class PollButton extends React.PureComponent {
|
||||
|
@ -39,14 +34,11 @@ class PollButton extends React.PureComponent {
|
|||
return (
|
||||
<div className='compose-form__poll-button'>
|
||||
<IconButton
|
||||
icon='bar-chart'
|
||||
className={`compose-form__poll-button-icon ${active ? 'active' : ''}`}
|
||||
src={require('@tabler/icons/icons/chart-bar.svg')}
|
||||
title={intl.formatMessage(active ? messages.remove_poll : messages.add_poll)}
|
||||
disabled={disabled}
|
||||
onClick={this.handleClick}
|
||||
className={`compose-form__poll-button-icon ${active ? 'active' : ''}`}
|
||||
size={18}
|
||||
inverted
|
||||
style={iconStyle}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -131,7 +131,7 @@ class PrivacyDropdownMenu extends React.PureComponent {
|
|||
{items.map(item => (
|
||||
<div role='option' tabIndex='0' key={item.value} data-index={item.value} onKeyDown={this.handleKeyDown} onClick={this.handleClick} className={classNames('privacy-dropdown__option', { active: item.value === value })} aria-selected={item.value === value} ref={item.value === value ? this.setFocusRef : null}>
|
||||
<div className='privacy-dropdown__option__icon'>
|
||||
<Icon id={item.icon} fixedWidth />
|
||||
<Icon src={item.icon} />
|
||||
</div>
|
||||
|
||||
<div className='privacy-dropdown__option__content'>
|
||||
|
@ -171,10 +171,10 @@ class PrivacyDropdown extends React.PureComponent {
|
|||
const { intl: { formatMessage } } = props;
|
||||
|
||||
this.options = [
|
||||
{ icon: 'globe-w', value: 'public', text: formatMessage(messages.public_short), meta: formatMessage(messages.public_long) },
|
||||
{ icon: 'unlock', value: 'unlisted', text: formatMessage(messages.unlisted_short), meta: formatMessage(messages.unlisted_long) },
|
||||
{ icon: 'lock', value: 'private', text: formatMessage(messages.private_short), meta: formatMessage(messages.private_long) },
|
||||
{ icon: 'envelope', value: 'direct', text: formatMessage(messages.direct_short), meta: formatMessage(messages.direct_long) },
|
||||
{ icon: require('@tabler/icons/icons/world.svg'), value: 'public', text: formatMessage(messages.public_short), meta: formatMessage(messages.public_long) },
|
||||
{ icon: require('@tabler/icons/icons/lock-open.svg'), value: 'unlisted', text: formatMessage(messages.unlisted_short), meta: formatMessage(messages.unlisted_long) },
|
||||
{ icon: require('@tabler/icons/icons/lock.svg'), value: 'private', text: formatMessage(messages.private_short), meta: formatMessage(messages.private_long) },
|
||||
{ icon: require('@tabler/icons/icons/mail.svg'), value: 'direct', text: formatMessage(messages.direct_short), meta: formatMessage(messages.direct_long) },
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -252,16 +252,13 @@ class PrivacyDropdown extends React.PureComponent {
|
|||
<div className={classNames('privacy-dropdown__value', { active: this.options.indexOf(valueOption) === 0 })}>
|
||||
<IconButton
|
||||
className='privacy-dropdown__value-icon'
|
||||
icon={valueOption.icon}
|
||||
src={valueOption.icon}
|
||||
title={intl.formatMessage(messages.change_privacy)}
|
||||
size={18}
|
||||
expanded={open}
|
||||
active={open}
|
||||
inverted
|
||||
onClick={this.handleToggle}
|
||||
onMouseDown={this.handleMouseDown}
|
||||
onKeyDown={this.handleButtonKeyDown}
|
||||
style={{ height: null, lineHeight: '27px' }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -2,17 +2,13 @@ import React from 'react';
|
|||
import IconButton from '../../../components/icon_button';
|
||||
import PropTypes from 'prop-types';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import classNames from 'classnames';
|
||||
|
||||
const messages = defineMessages({
|
||||
add_schedule: { id: 'schedule_button.add_schedule', defaultMessage: 'Schedule post for later' },
|
||||
remove_schedule: { id: 'schedule_button.remove_schedule', defaultMessage: 'Post immediately' },
|
||||
});
|
||||
|
||||
const iconStyle = {
|
||||
height: null,
|
||||
lineHeight: '27px',
|
||||
};
|
||||
|
||||
export default
|
||||
@injectIntl
|
||||
class ScheduleButton extends React.PureComponent {
|
||||
|
@ -34,14 +30,11 @@ class ScheduleButton extends React.PureComponent {
|
|||
return (
|
||||
<div className='compose-form__schedule-button'>
|
||||
<IconButton
|
||||
icon='calendar'
|
||||
className={classNames('compose-form__schedule-button-icon', { active })}
|
||||
src={require('@tabler/icons/icons/calendar-stats.svg')}
|
||||
title={intl.formatMessage(active ? messages.remove_schedule : messages.add_schedule)}
|
||||
disabled={disabled}
|
||||
onClick={this.handleClick}
|
||||
className={`compose-form__schedule-button-icon ${active ? 'active' : ''}`}
|
||||
size={18}
|
||||
inverted
|
||||
style={iconStyle}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
|
40
app/soapbox/features/compose/components/spoiler_button.js
Normal file
40
app/soapbox/features/compose/components/spoiler_button.js
Normal file
|
@ -0,0 +1,40 @@
|
|||
import React from 'react';
|
||||
import IconButton from '../../../components/icon_button';
|
||||
import PropTypes from 'prop-types';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import classNames from 'classnames';
|
||||
|
||||
const messages = defineMessages({
|
||||
marked: { id: 'compose_form.spoiler.marked', defaultMessage: 'Text is hidden behind warning' },
|
||||
unmarked: { id: 'compose_form.spoiler.unmarked', defaultMessage: 'Text is not hidden' },
|
||||
});
|
||||
|
||||
export default @injectIntl
|
||||
class SpoilerButton extends React.PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
active: PropTypes.bool,
|
||||
onClick: PropTypes.func.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
handleClick = () => {
|
||||
this.props.onClick();
|
||||
}
|
||||
|
||||
render() {
|
||||
const { intl, active } = this.props;
|
||||
|
||||
return (
|
||||
<div className='compose-form__spoiler-button'>
|
||||
<IconButton
|
||||
className={classNames('compose-form__spoiler-button-icon', { active })}
|
||||
src={require('@tabler/icons/icons/alert-triangle.svg')}
|
||||
title={intl.formatMessage(active ? messages.marked : messages.unmarked)}
|
||||
onClick={this.handleClick}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -18,11 +18,6 @@ const makeMapStateToProps = () => {
|
|||
return mapStateToProps;
|
||||
};
|
||||
|
||||
const iconStyle = {
|
||||
height: null,
|
||||
lineHeight: '27px',
|
||||
};
|
||||
|
||||
export default @connect(makeMapStateToProps)
|
||||
@injectIntl
|
||||
class UploadButton extends ImmutablePureComponent {
|
||||
|
@ -60,7 +55,13 @@ class UploadButton extends ImmutablePureComponent {
|
|||
|
||||
return (
|
||||
<div className='compose-form__upload-button'>
|
||||
<IconButton icon='paperclip' title={intl.formatMessage(messages.upload)} disabled={disabled} onClick={this.handleClick} className='compose-form__upload-button-icon' size={18} inverted style={iconStyle} />
|
||||
<IconButton
|
||||
className='compose-form__upload-button-icon'
|
||||
src={require('@tabler/icons/icons/paperclip.svg')}
|
||||
title={intl.formatMessage(messages.upload)}
|
||||
disabled={disabled}
|
||||
onClick={this.handleClick}
|
||||
/>
|
||||
<label>
|
||||
<span style={{ display: 'none' }}>{intl.formatMessage(messages.upload)}</span>
|
||||
<input
|
||||
|
|
|
@ -1,23 +1,14 @@
|
|||
import { connect } from 'react-redux';
|
||||
import TextIconButton from '../components/text_icon_button';
|
||||
import MarkdownButton from '../components/markdown_button';
|
||||
import { changeComposeContentType } from '../../../actions/compose';
|
||||
import { injectIntl, defineMessages } from 'react-intl';
|
||||
import { getFeatures } from 'soapbox/utils/features';
|
||||
|
||||
const messages = defineMessages({
|
||||
marked: { id: 'compose_form.markdown.marked', defaultMessage: 'Post markdown enabled' },
|
||||
unmarked: { id: 'compose_form.markdown.unmarked', defaultMessage: 'Post markdown disabled' },
|
||||
});
|
||||
|
||||
const mapStateToProps = (state, { intl }) => {
|
||||
const instance = state.get('instance');
|
||||
const features = getFeatures(instance);
|
||||
|
||||
return {
|
||||
label: 'MD',
|
||||
title: intl.formatMessage(state.getIn(['compose', 'content_type']) === 'text/markdown' ? messages.marked : messages.unmarked),
|
||||
active: state.getIn(['compose', 'content_type']) === 'text/markdown',
|
||||
ariaControls: 'markdown-input',
|
||||
unavailable: !features.richText,
|
||||
};
|
||||
};
|
||||
|
@ -30,4 +21,4 @@ const mapDispatchToProps = dispatch => ({
|
|||
|
||||
});
|
||||
|
||||
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(TextIconButton));
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(MarkdownButton);
|
||||
|
|
|
@ -1,18 +1,9 @@
|
|||
import { connect } from 'react-redux';
|
||||
import TextIconButton from '../components/text_icon_button';
|
||||
import SpoilerButton from '../components/spoiler_button';
|
||||
import { changeComposeSpoilerness } from '../../../actions/compose';
|
||||
import { injectIntl, defineMessages } from 'react-intl';
|
||||
|
||||
const messages = defineMessages({
|
||||
marked: { id: 'compose_form.spoiler.marked', defaultMessage: 'Text is hidden behind warning' },
|
||||
unmarked: { id: 'compose_form.spoiler.unmarked', defaultMessage: 'Text is not hidden' },
|
||||
});
|
||||
|
||||
const mapStateToProps = (state, { intl }) => ({
|
||||
label: 'CW',
|
||||
title: intl.formatMessage(state.getIn(['compose', 'spoiler']) ? messages.marked : messages.unmarked),
|
||||
active: state.getIn(['compose', 'spoiler']),
|
||||
ariaControls: 'cw-spoiler-input',
|
||||
});
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
|
@ -23,4 +14,4 @@ const mapDispatchToProps = dispatch => ({
|
|||
|
||||
});
|
||||
|
||||
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(TextIconButton));
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(SpoilerButton);
|
||||
|
|
|
@ -344,18 +344,40 @@
|
|||
justify-content: center;
|
||||
}
|
||||
|
||||
.compose-form__upload-button-icon { line-height: 27px; }
|
||||
|
||||
.compose-form__sensitive-button {
|
||||
display: none;
|
||||
&.compose-form__sensitive-button--visible { display: block; }
|
||||
.compose-form__sensitive-button__icon { line-height: 27px; }
|
||||
|
||||
&.compose-form__sensitive-button--visible {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.svg-icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
|
||||
svg {
|
||||
stroke-width: 1.5px;
|
||||
}
|
||||
}
|
||||
|
||||
.privacy-dropdown__value {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
.icon-button {
|
||||
box-sizing: content-box;
|
||||
padding: 0 3px;
|
||||
opacity: 0.5;
|
||||
transition: 0.2s;
|
||||
|
||||
&.active,
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.character-counter__wrapper {
|
||||
|
|
Loading…
Reference in a new issue