This commit is contained in:
mgabdev
2020-04-29 18:32:49 -04:00
parent 5efe40f301
commit 03de4c4fea
92 changed files with 1132 additions and 787 deletions

View File

@@ -115,6 +115,7 @@ class Account extends ImmutablePureComponent {
expanded,
dismissAction,
showDismiss,
withBio,
} = this.props
if (!account) return null
@@ -148,13 +149,15 @@ class Account extends ImmutablePureComponent {
onClick={dismissAction}
icon='close'
iconSize='8px'
iconClassName={_s.fillColorSecondary}
iconClassName={_s.fillSecondary}
/>
)
const content = { __html: account.get('note_emojified') }
return (
<div className={[_s.default, _s.px15, _s.py5, _s.backgroundColorSubtle_onHover, _s.mb5].join(' ')}>
<div className={[_s.default, _s.flexRow, _s.alignItemsCenter].join(' ')}>
<div className={[_s.default, _s.px15, _s.py10, _s.borderBottom1PX, _s.borderColorSecondary, _s.bgSubtle_onHover].join(' ')}>
<div className={[_s.default, _s.flexRow, _s.alignItemsStart].join(' ')}>
<NavLink
className={[_s.default, _s.noUnderline].join(' ')}
@@ -164,20 +167,28 @@ class Account extends ImmutablePureComponent {
<Avatar account={account} size={avatarSize} />
</NavLink>
<NavLink
title={account.get('acct')}
to={`/${account.get('acct')}`}
className={[_s.default, _s.alignItemsStart, _s.noUnderline, _s.px10, _s.overflowHidden, _s.flexNormal].join(' ')}
>
<DisplayName account={account} isMultiline={compact} />
{!compact && actionButton}
</NavLink>
<div className={[_s.default, _s.px10, _s.overflowHidden, _s.flexNormal].join(' ')}>
<div className={[_s.default, _s.flexRow].join(' ')}>
<NavLink
title={account.get('acct')}
to={`/${account.get('acct')}`}
className={[_s.default, _s.alignItemsStart, _s.noUnderline, _s.overflowHidden, _s.flexNormal].join(' ')}
>
<DisplayName account={account} isMultiline={compact} />
{!compact && actionButton}
</NavLink>
<div className={[_s.default].join(' ')}>
{dismissBtn}
{compact && actionButton}
<div className={[_s.default].join(' ')}>
{dismissBtn}
{compact && actionButton}
</div>
</div>
{
withBio &&
<div className={[_s.py5, _s.dangerousContent].join(' ')} dangerouslySetInnerHTML={content} />
}
</div>
</div>
</div>
)

View File

@@ -233,12 +233,12 @@ export default class AutosuggestTextbox extends ImmutablePureComponent {
text: 1,
displayBlock: 1,
outlineNone: 1,
backgroundColorPrimary: !small,
backgroundColorSubtle: small,
bgPrimary: !small,
bgSubtle: small,
py15: !small,
py10: small,
fontSize16PX: !small,
fontSize14PX: small,
fs16PX: !small,
fs14PX: small,
mr5: small,
})

View File

@@ -11,7 +11,7 @@ export default class Block extends PureComponent {
const { children } = this.props
return (
<div className={[_s.default, _s.boxShadowBlock, _s.backgroundColorPrimary, _s.overflowHidden, _s.radiusSmall].join(' ')}>
<div className={[_s.default, _s.boxShadowBlock, _s.bgPrimary, _s.overflowHidden, _s.radiusSmall].join(' ')}>
{children}
</div>
)

View File

@@ -37,6 +37,8 @@ const COLORS = {
* @param {func} [props.onMouseEnter] - function to call on button mouse enter
* @param {func} [props.onMouseLeave] - function to call on button mouse leave
* @param {bool} [props.radiusSmall] - if the button has small radius
* @param {bool} [props.rel] - rel for the button
* @param {bool} [props.target] - target for the button
* @param {bool} [props.text] - if the button is just text (i.e. link)
* @param {bool} [props.title] - `title` attribute for button
* @param {bool} [props.to] - `to` to send to on click
@@ -68,6 +70,8 @@ export default class Button extends PureComponent {
onMouseLeave: PropTypes.func,
isOutline: PropTypes.bool,
radiusSmall: PropTypes.bool,
rel: PropTypes.string,
target: PropTypes.string,
title: PropTypes.string,
to: PropTypes.string,
type: PropTypes.string,
@@ -118,6 +122,8 @@ export default class Button extends PureComponent {
onMouseEnter,
onMouseLeave,
radiusSmall,
rel,
target,
title,
to,
type,
@@ -136,13 +142,13 @@ export default class Button extends PureComponent {
cursorNotAllowed: isDisabled,
opacity05: isDisabled,
backgroundColorPrimary: backgroundColor === COLORS.white,
backgroundColorBlack: backgroundColor === COLORS.black,
backgroundColorBrand: backgroundColor === COLORS.brand,
backgroundTransparent: backgroundColor === COLORS.none,
backgroundColorSubtle2: backgroundColor === COLORS.tertiary,
backgroundColorSubtle: backgroundColor === COLORS.secondary,
backgroundColorDanger: backgroundColor === COLORS.danger,
bgPrimary: backgroundColor === COLORS.white,
bgBlack: backgroundColor === COLORS.black,
bgBrand: backgroundColor === COLORS.brand,
bgTransparent: backgroundColor === COLORS.none,
bgSecondary: backgroundColor === COLORS.tertiary,
bgSubtle: backgroundColor === COLORS.secondary,
bgDanger: backgroundColor === COLORS.danger,
colorPrimary: !!children && color === COLORS.primary,
colorSecondary: !!children && color === COLORS.secondary,
@@ -164,18 +170,18 @@ export default class Button extends PureComponent {
underline_onHover: underlineOnHover,
backgroundColorSubtle2Dark_onHover: backgroundColor === COLORS.tertiary || backgroundColor === COLORS.secondary && !isDisabled,
backgroundColorBlackOpaque_onHover: backgroundColor === COLORS.black && !isDisabled,
backgroundColorBrandDark_onHover: backgroundColor === COLORS.brand && !isDisabled,
backgroundColorDangerDark_onHover: backgroundColor === COLORS.danger && !isDisabled,
bgSecondaryDark_onHover: backgroundColor === COLORS.tertiary || backgroundColor === COLORS.secondary && !isDisabled,
bgBlackOpaque_onHover: backgroundColor === COLORS.black && !isDisabled,
bgBrandDark_onHover: backgroundColor === COLORS.brand && !isDisabled,
bgDangerDark_onHover: backgroundColor === COLORS.danger && !isDisabled,
backgroundColorBrand_onHover: color === COLORS.brand && isOutline && !isDisabled,
bgBrand_onHover: color === COLORS.brand && isOutline && !isDisabled,
colorWhite_onHover: !!children && color === COLORS.brand && isOutline && !isDisabled,
fillColorSecondary: !!icon && color === COLORS.secondary,
fillColorWhite: !!icon && color === COLORS.white,
fillColorBrand: !!icon && color === COLORS.brand,
fillColorWhite_onHover: !!icon && color === COLORS.brand && isOutline,
fillSecondary: !!icon && color === COLORS.secondary,
fillWhite: !!icon && color === COLORS.white,
fillBrand: !!icon && color === COLORS.brand,
fillWhite_onHover: !!icon && color === COLORS.brand && isOutline,
})
const tagName = !!href ? 'a' : !!to ? 'NavLink' : 'button'
@@ -216,6 +222,8 @@ export default class Button extends PureComponent {
}
const options = {
rel,
target,
title,
type,
disabled: isDisabled,

View File

@@ -45,14 +45,14 @@ export default class ColumnHeader extends PureComponent {
className={[_s.alignItemsCenter, _s.pl0, _s.justifyContentCenter].join(' ')}
icon='back'
iconSize='20px'
iconClassName={[_s.mr5, _s.fillColorPrimary].join(' ')}
iconClassName={[_s.mr5, _s.fillPrimary].join(' ')}
onClick={this.handleBackClick}
/>
}
<div className={[_s.default, _s.height100PC, _s.justifyContentCenter, _s.mr10].join(' ')}>
<Heading size='h1'>
{title}
</Heading>
</div>
@@ -63,7 +63,7 @@ export default class ColumnHeader extends PureComponent {
{
!!actions &&
<div className={[_s.default, _s.backgroundTransparent, _s.flexRow, _s.alignItemsCenter, _s.justifyContentCenter, _s.mlAuto].join(' ')}>
<div className={[_s.default, _s.bgTransparent, _s.flexRow, _s.alignItemsCenter, _s.justifyContentCenter, _s.mlAuto].join(' ')}>
{
actions.map((action, i) => (
<Button

View File

@@ -61,7 +61,7 @@ class Comment extends ImmutablePureComponent {
</NavLink>
<div className={[_s.default, _s.flexNormal].join(' ')}>
<div className={[_s.default, _s.px10, _s.pt5, _s.pb10, _s.radiusSmall, _s.backgroundColorSubtle].join(' ')}>
<div className={[_s.default, _s.px10, _s.pt5, _s.pb10, _s.radiusSmall, _s.bgSubtle].join(' ')}>
<CommentHeader status={status} />
<StatusContent
status={status}
@@ -103,7 +103,7 @@ class CommentButton extends PureComponent {
radiusSmall
backgroundColor='none'
color='tertiary'
className={[_s.px5, _s.backgroundColorSubtle_onHover, _s.py2, _s.mr5].join(' ')}
className={[_s.px5, _s.bgSubtle_onHover, _s.py2, _s.mr5].join(' ')}
onClick={onClick}
>
<Text size='extraSmall' color='inherit' weight='bold'>

View File

@@ -183,8 +183,8 @@ class Composer extends PureComponent {
default: 1,
cursorText: 1,
text: 1,
fontSize16PX: !small,
fontSize14PX: small,
fs16PX: !small,
fs14PX: small,
pt15: !small,
px15: !small,
px10: small,

View File

@@ -98,9 +98,9 @@ class DisplayName extends ImmutablePureComponent {
colorPrimary: 1,
mr2: 1,
lineHeight125: !isSmall,
fontSize14PX: isSmall,
fontSize15PX: !isLarge,
fontSize24PX: isLarge && !isSmall,
fs14PX: isSmall,
fs15PX: !isLarge,
fs24PX: isLarge && !isSmall,
})
const usernameClasses = CX({
@@ -115,9 +115,9 @@ class DisplayName extends ImmutablePureComponent {
lineHeight15: isMultiline,
lineHeight125: !isMultiline,
ml5: !isMultiline,
fontSize14PX: isSmall,
fontSize15PX: !isLarge,
fontSize16PX: isLarge && !isSmall,
fs14PX: isSmall,
fs15PX: !isLarge,
fs16PX: isLarge && !isSmall,
})
const iconSize =
@@ -161,7 +161,7 @@ class DisplayName extends ImmutablePureComponent {
/>
{
!noRelationship && account.get('locked') &&
<Icon id='lock-filled' size={iconSize} className={[_s.fillColorPrimary, _s.ml5].join(' ')} />
<Icon id='lock-filled' size={iconSize} className={[_s.fillPrimary, _s.ml5].join(' ')} />
}
</bdi>
{
@@ -180,7 +180,7 @@ class DisplayName extends ImmutablePureComponent {
size='extraSmall'
isBadge
color='tertiary'
className={[_s.backgroundColorSubtle2, _s.py2].join(' ')}
className={[_s.bgSecondary, _s.py2].join(' ')}
>
{relationshipLabel}
</Text>

View File

@@ -86,8 +86,8 @@ class GroupCollectionItem extends ImmutablePureComponent {
mb10: 1,
ml5: 1,
mr5: 1,
backgroundColorPrimary: 1,
backgroundColorSubtle_onHover: isMember,
bgPrimary: 1,
bgSubtle_onHover: isMember,
})
return (
@@ -107,7 +107,7 @@ class GroupCollectionItem extends ImmutablePureComponent {
{
(!coverSrc || coverMissing) && (isMember || isAdmin) &&
<div className={[_s.default, _s.height40PX, _s.backgroundColorSubtle, _s.borderColorSecondary, _s.borderBottom1PX].join(' ')} />
<div className={[_s.default, _s.height40PX, _s.bgSubtle, _s.borderColorSecondary, _s.borderBottom1PX].join(' ')} />
}
{
@@ -117,7 +117,7 @@ class GroupCollectionItem extends ImmutablePureComponent {
isMember &&
<Text
isBadge
className={_s.backgroundColorWhite}
className={_s.bgWhite}
size='extraSmall'
color='brand'
>
@@ -128,7 +128,7 @@ class GroupCollectionItem extends ImmutablePureComponent {
isAdmin &&
<Text
isBadge
className={[_s.backgroundColorBlack, _s.ml5].join(' ')}
className={[_s.bgBlack, _s.ml5].join(' ')}
size='extraSmall'
color='white'
>

View File

@@ -3,7 +3,7 @@ import ImmutablePureComponent from 'react-immutable-pure-component'
import { Fragment } from 'react'
import { NavLink } from 'react-router-dom'
import { defineMessages, injectIntl } from 'react-intl'
import classNames from 'classnames/bind'
import { CX } from '../constants'
import { PLACEHOLDER_MISSING_HEADER_SRC } from '../constants'
import { shortNumberFormat } from '../utils/numbers'
import Image from './image'
@@ -17,11 +17,9 @@ const messages = defineMessages({
const mapStateToProps = (state, { id }) => ({
group: state.getIn(['groups', id]),
relationships: state.getIn(['group_relationships', id]),
relatioships: state.getIn(['group_relationships', id]),
})
const cx = classNames.bind(_s)
export default
@connect(mapStateToProps)
@injectIntl
@@ -50,17 +48,21 @@ class GroupListItem extends ImmutablePureComponent {
isHidden,
} = this.props
if (!relationships || !group) return null
if (!group) return null
const unreadCount = relationships.get('unread_count')
let unreadCount, subtitle
const subtitle = unreadCount > 0 ? (
<Fragment>
{shortNumberFormat(unreadCount)}
&nbsp;
{intl.formatMessage(messages.new_statuses)}
</Fragment>
) : intl.formatMessage(messages.no_recent_activity)
if (relationships) {
unreadCount = relationships.get('unread_count')
subtitle = unreadCount > 0 ? (
<Fragment>
{shortNumberFormat(unreadCount)}
&nbsp;
{intl.formatMessage(messages.new_statuses)}
</Fragment>
) : intl.formatMessage(messages.no_recent_activity)
}
if (isHidden) {
return (
@@ -71,22 +73,21 @@ class GroupListItem extends ImmutablePureComponent {
)
}
const containerClasses = cx({
const containerClasses = CX({
default: 1,
noUnderline: 1,
overflowHidden: 1,
backgroundColorSubtle_onHover: 1,
bgSubtle_onHover: 1,
borderColorSecondary: 1,
radiusSmall: !slim,
mt5: !slim,
mb10: !slim,
mb10: !slim && !isLast,
border1PX: !slim,
borderBottom1PX: slim && !isLast,
flexRow: slim,
py5: slim,
})
const imageClasses = cx({
const imageClasses = CX({
height122PX: !slim,
radiusSmall: slim,
height72PX: slim,
@@ -94,7 +95,7 @@ class GroupListItem extends ImmutablePureComponent {
ml15: slim,
})
const textContainerClasses = cx({
const textContainerClasses = CX({
default: 1,
px10: 1,
mt5: 1,
@@ -134,9 +135,12 @@ class GroupListItem extends ImmutablePureComponent {
</Text>
}
<Text color='secondary' size='small' className={_s.mt5}>
{subtitle}
</Text>
{
subtitle &&
<Text color='secondary' size='small' className={_s.mt5}>
{subtitle}
</Text>
}
</div>
</NavLink>

View File

@@ -24,12 +24,12 @@ export default class HashtagItem extends ImmutablePureComponent {
return (
<NavLink
to={`/tags/${hashtag.get('name')}`}
className={[_s.default, _s.noUnderline, _s.backgroundColorSubtle_onHover, _s.px15, _s.py5].join(' ')}
className={[_s.default, _s.noUnderline, _s.bgSubtle_onHover, _s.px15, _s.py5].join(' ')}
>
<div className={[_s.default, _s.flexRow, _s.alignItemsCenter].join(' ')}>
<div>
<Text color='brand' size='medium' weight='bold' className={[_s.py2, _s.lineHeight15].join(' ')}>
{hashtag.get('name')}
#{hashtag.get('name')}
</Text>
</div>
{
@@ -41,7 +41,7 @@ export default class HashtagItem extends ImmutablePureComponent {
title='Remove'
icon='close'
iconSize='8px'
iconClassName={_s.fillColorSecondary}
iconClassName={_s.fillSecondary}
className={_s.mlAuto}
/>
}

View File

@@ -42,11 +42,11 @@ export default class Heading extends PureComponent {
colorPrimary: [SIZES.h1, SIZES.h2].indexOf(size) > -1,
colorSecondary: [SIZES.h3, SIZES.h4, SIZES.h5].indexOf(size) > -1,
fontSize24PX: size === SIZES.h1,
fontSize19PX: size === SIZES.h2,
fontSize16PX: size === SIZES.h3,
fontSize13PX: size === SIZES.h4,
fontSize12PX: size === SIZES.h5,
fs24PX: size === SIZES.h1,
fs19PX: size === SIZES.h2,
fs16PX: size === SIZES.h3,
fs13PX: size === SIZES.h4,
fs12PX: size === SIZES.h5,
mt5: [SIZES.h4].indexOf(size) > -1,

View File

@@ -19,6 +19,7 @@ import DonorIcon from '../assets/donor_icon'
import EllipsisIcon from '../assets/ellipsis_icon'
import EmailIcon from '../assets/email_icon'
import ErrorIcon from '../assets/error_icon'
import ExploreIcon from '../assets/explore_icon'
import FullscreenIcon from '../assets/fullscreen_icon'
import GabLogoIcon from '../assets/gab_logo'
import GifIcon from '../assets/gif_icon'
@@ -89,6 +90,7 @@ const ICONS = {
'ellipsis': EllipsisIcon,
'email': EmailIcon,
'error': ErrorIcon,
'explore': ExploreIcon,
'fullscreen': FullscreenIcon,
'gab-logo': GabLogoIcon,
'gif': GifIcon,

View File

@@ -50,7 +50,7 @@ export default class Image extends PureComponent {
const classes = cx(className, {
default: 1,
objectFitCover: !!src && fit === 'cover',
backgroundColorSubtle2: 1,
bgSecondary: 1,
})
//If error and not our own image

View File

@@ -58,12 +58,12 @@ export default class Input extends PureComponent {
displayBlock: 1,
py10: !small,
py5: small,
backgroundTransparent: !readOnly,
backgroundColorSubtle2: readOnly,
bgTransparent: !readOnly,
bgSecondary: readOnly,
colorPrimary: !readOnly,
colorSecondary: readOnly,
fontSize15PX: !small,
fontSize13PX: small,
fs15PX: !small,
fs13PX: small,
flexGrow1: 1,
circle: 1,
px5: !!prependIcon,
@@ -87,10 +87,10 @@ export default class Input extends PureComponent {
</Text>
</div>
}
<div className={[_s.default, _s.backgroundColorPrimary, _s.border1PX, _s.borderColorSecondary, _s.flexRow, _s.circle, _s.alignItemsCenter].join(' ')}>
<div className={[_s.default, _s.bgPrimary, _s.border1PX, _s.borderColorSecondary, _s.flexRow, _s.circle, _s.alignItemsCenter].join(' ')}>
{
!!prependIcon &&
<Icon id={prependIcon} size='16px' className={[_s.fillColorPrimary, _s.ml15, _s.mr5].join(' ')} />
<Icon id={prependIcon} size='16px' className={[_s.fillPrimary, _s.ml15, _s.mr5].join(' ')} />
}
{

View File

@@ -51,7 +51,7 @@ export default class List extends ImmutablePureComponent {
))
}
</ScrollableList>
</Block>
</Block>
)
}

View File

@@ -56,7 +56,7 @@ export default class ListItem extends PureComponent {
flexRow: 1,
alignItemsCenter: 1,
width100PC: 1,
backgroundColorSubtle_onHover: 1,
bgSubtle_onHover: 1,
borderColorSecondary: !isLast,
borderBottom1PX: !isLast,
})
@@ -64,7 +64,7 @@ export default class ListItem extends PureComponent {
const iconClasses = cx({
mr10: !large,
mr15: large,
fillColorPrimary: 1,
fillPrimary: 1,
})
const textSize = small ? 'small' : large ? 'medium' : 'normal'
@@ -97,7 +97,7 @@ export default class ListItem extends PureComponent {
<Icon
id='angle-right'
size='10px'
className={[_s.mlAuto, _s.fillColorSecondary, _s.flexShrink1].join(' ')}
className={[_s.mlAuto, _s.fillSecondary, _s.flexShrink1].join(' ')}
/>
}
</Button>

View File

@@ -216,7 +216,7 @@ class Item extends ImmutablePureComponent {
playsInline
/>
<div className={[_s.default, _s.posAbs, _s.z2, _s.radiusSmall, _s.backgroundColorBlackOpaque, _s.px5, _s.py5, _s.mr10, _s.mb10, _s.bottom0, _s.right0].join(' ')}>
<div className={[_s.default, _s.posAbs, _s.z2, _s.radiusSmall, _s.bgBlackOpaque, _s.px5, _s.py5, _s.mr10, _s.mb10, _s.bottom0, _s.right0].join(' ')}>
<Text size='extraSmall' color='white' weight='medium'>GIF</Text>
</div>
</div>
@@ -574,7 +574,7 @@ class MediaGallery extends PureComponent {
title={intl.formatMessage(messages.toggle_visible)}
icon='hidden'
backgroundColor='none'
className={[_s.px10, _s.backgroundColorBlackOpaque_onHover].join(' ')}
className={[_s.px10, _s.bgBlackOpaque_onHover].join(' ')}
onClick={this.handleOpen}
/>
</div>

View File

@@ -137,13 +137,13 @@ export default class MediaItem extends ImmutablePureComponent {
<Icon
id='hidden'
size='22px'
className={[_s.fillColorWhite].join('')}
className={[_s.fillWhite].join('')}
/>
}
{
!!badge &&
<div className={[_s.default, _s.posAbs, _s.radiusSmall, _s.backgroundColorBlackOpaque, _s.px5, _s.py5, _s.mr5, _s.mt5, _s.mb5, _s.bottom0, _s.right0].join(' ')}>
<div className={[_s.default, _s.posAbs, _s.radiusSmall, _s.bgBlackOpaque, _s.px5, _s.py5, _s.mr5, _s.mt5, _s.mb5, _s.bottom0, _s.right0].join(' ')}>
<Text size='extraSmall' color='white'>
{badge}
</Text>

View File

@@ -89,7 +89,7 @@ class EmbedModal extends ImmutablePureComponent {
{intl.formatMessage(messages.preview)}
</Text>
<div className={[_s.default, _s.width100PC, _s.backgroundColorSubtle, _s.height220PX, _s.alignItemsCenter, _s.justifyContentCenter].join(' ')}>
<div className={[_s.default, _s.width100PC, _s.bgSubtle, _s.height220PX, _s.alignItemsCenter, _s.justifyContentCenter].join(' ')}>
<iframe
className={[_s.default, _s.width100PC, _s.height100PC, _s.z2].join(' ')}
frameBorder='0'

View File

@@ -45,7 +45,7 @@ class HomeTimelineSettingsModal extends ImmutablePureComponent {
icon='pro'
href='https://pro.gab.com'
className={_s.justifyContentCenter}
iconClassName={[_s.mr5, _s.fillColorWhite].join(' ')}
iconClassName={[_s.mr5, _s.fillWhite].join(' ')}
>
<Text color='inherit' weight='bold' align='center'>
{intl.formatMessage(messages.title)}

View File

@@ -137,7 +137,7 @@ class ModalBase extends PureComponent {
<Fragment>
<div
role='presentation'
className={[_s.default, _s.backgroundColorBlackOpaque, _s.posFixed, _s.z3, _s.top0, _s.right0, _s.bottom0, _s.left0].join(' ')}
className={[_s.default, _s.bgBlackOpaque, _s.posFixed, _s.z3, _s.top0, _s.right0, _s.bottom0, _s.left0].join(' ')}
/>
<div
ref={this.setDialog}

View File

@@ -50,7 +50,7 @@ class ProUpgradeModal extends ImmutablePureComponent {
icon='pro'
href='https://pro.gab.com'
className={_s.justifyContentCenter}
iconClassName={[_s.mr5, _s.fillColorWhite].join(' ')}
iconClassName={[_s.mr5, _s.fillWhite].join(' ')}
>
<Text color='inherit' weight='bold' align='center'>
{intl.formatMessage(messages.title)}

View File

@@ -5,8 +5,9 @@ import { BREAKPOINT_EXTRA_SMALL } from '../constants'
import { me } from '../initial_state'
import { makeGetAccount } from '../selectors'
import Responsive from '../features/ui/util/responsive_component'
import ColumnHeader from './column_header'
import { CX } from '../constants'
import Search from './search'
import Avatar from './avatar'
import Icon from './icon'
const mapStateToProps = (state) => ({
@@ -25,6 +26,10 @@ class NavigationBar extends ImmutablePureComponent {
showBackBtn: PropTypes.bool,
}
handleProfileClick = () => {
}
render() {
const {
title,
@@ -34,40 +39,118 @@ class NavigationBar extends ImmutablePureComponent {
account,
} = this.props
const isPro = account.get('is_pro')
return (
<div className={[_s.default, _s.height53PX, _s.flexRow, _s.backgroundColorPrimary, _s.borderBottom1PX, _s.borderColorSecondary, _s.alignItemsCenter, _s.z3, _s.top0, _s.right0, _s.left0, _s.posFixed].join(' ')} >
<div className={[_s.default, _s.flexGrow1, _s.z3, _s.alignItemsEnd].join(' ')}>
<div className={[_s.default, _s.width240PX].join(' ')}>
<div className={[_s.default, _s.height100PC, _s.alignItemsStart, _s.width240PX].join(' ')}>
<h1 className={[_s.default].join(' ')}>
<NavLink to='/' aria-label='Gab' className={[_s.default, _s.flexRow, _s.noSelect, _s.noUnderline, _s.height50PX, _s.cursorPointer, _s.px10].join(' ')}>
<Icon id='gab-logo' />
<div className={[_s.default, _s.z4, _s.height53PX, _s.width100PC].join(' ')}>
<div className={[_s.default, _s.height53PX, _s.bgBrand, _s.alignItemsCenter, _s.z3, _s.top0, _s.right0, _s.left0, _s.posFixed].join(' ')} >
<div className={[_s.default, _s.flexRow, _s.width1255PX].join(' ')}>
<div className={[_s.default, _s.flexRow].join(' ')}>
<h1 className={[_s.default, _s.mr15].join(' ')}>
<NavLink to='/' aria-label='Gab' className={[_s.default, _s.justifyContentCenter, _s.noSelect, _s.noUnderline, _s.height53PX, _s.cursorPointer, _s.px10, _s.mr15].join(' ')}>
<Icon id='gab-logo' className={_s.fillWhite} />
</NavLink>
</h1>
<Responsive min={BREAKPOINT_EXTRA_SMALL}>
<div className={[_s.default, _s.width340PX].join(' ')}>
<Search />
</div>
</Responsive>
</div>
</div>
</div>
<div className={[_s.default, _s.flexShrink1, _s.flexGrow1].join(' ')}>
<div className={[_s.default, _s.height53PX, _s.pl15, _s.width1015PX, _s.flexRow, _s.justifyContentSpaceBetween].join(' ')}>
<div className={[_s.default, _s.width645PX].join(' ')}>
<ColumnHeader
title={title}
showBackBtn={showBackBtn}
actions={actions}
tabs={tabs}
/>
</div>
<Responsive min={BREAKPOINT_EXTRA_SMALL}>
<div className={[_s.default, _s.width340PX].join(' ')}>
<Search />
<div className={[_s.default, _s.mlAuto].join(' ')}>
<div className={[_s.default, _s.height53PX, _s.pl15, _s.flexRow, _s.alignItemsCenter, _s.justifyContentSpaceBetween].join(' ')}>
<NavigationBarButton title='Home' icon='home' to='/home' />
<NavigationBarButtonDivider />
<NavigationBarButton icon='notifications' to='/notifications' />
<NavigationBarButton icon='cog' to='/notifications' />
<NavigationBarButtonDivider />
<button onClick={this.handleProfileClick} className={[_s.height53PX, _s.bgTransparent, _s.outlineNone, _s.cursorPointer, _s.default, _s.justifyContentCenter, _s.ml15].join(' ')}>
<Avatar account={account} size={32} />
</button>
</div>
</Responsive>
</div>
</div>
</div>
</div>
)
}
}
class NavigationBarButtonDivider extends PureComponent {
render() {
return (
<div className={[_s.default, _s.height20PX, _s.width1PX, _s.mr10, _s.ml10, _s.bgBrandDark].join(' ')} />
)
}
}
class NavigationBarButton extends PureComponent {
static propTypes = {
title: PropTypes.string,
icon: PropTypes.string,
to: PropTypes.string,
onClick: PropTypes.func,
}
render() {
const {
title,
icon,
to,
onClick,
} = this.props
const active = false
const classes = CX({
default: 1,
height53PX: 1,
flexRow: 1,
alignItemsCenter: 1,
justifyContentCenter: 1,
outlineNone: 1,
px10: !!title,
px5: !title,
cursorPointer: 1,
bgTransparent: 1,
colorWhite: !!title,
fs13PX: !!title,
fontWeightNormal: !!title,
textUppercase: !!title,
})
const iconClasses = CX({
fillWhite: !!title || active,
fillBrandDark: !title,
mr10: !!title,
})
const iconSize = !!title ? 16 : 18
return (
<button
noClasses
color='white'
className={classes}
>
<Icon className={iconClasses} id={icon} size={iconSize} />
{title}
</button>
)
}
}

View File

@@ -96,11 +96,11 @@ class Notification extends ImmutablePureComponent {
}
return (
<div className={[_s.default, _s.px10, _s.cursorPointer, _s.backgroundColorSubtle_onHover].join(' ')}>
<div className={[_s.default, _s.px10, _s.cursorPointer, _s.bgSubtle_onHover].join(' ')}>
<div className={[_s.default, _s.borderBottom1PX, _s.borderColorSecondary].join(' ')}>
<div className={[_s.default, _s.flexRow, _s.my10, _s.py10, _s.px10].join(' ')}>
<Icon id={icon} size='20px' className={[_s.fillColorPrimary, _s.mt5].join(' ')} />
<Icon id={icon} size='20px' className={[_s.fillPrimary, _s.mt5].join(' ')} />
<div className={[_s.default, _s.ml15, _s.flexNormal].join(' ')}>
<div className={[_s.default, _s.flexRow].join(' ')}>

View File

@@ -69,7 +69,7 @@ class GroupInfoPanel extends ImmutablePureComponent {
<Divider isSmall />
<div className={[_s.default, _s.flexRow, _s.alignItemsCenter].join(' ')}>
<Icon id='calendar' size='12px' className={_s.fillColorSecondary} />
<Icon id='calendar' size='12px' className={_s.fillSecondary} />
<Text
size='small'
color='secondary'

View File

@@ -17,15 +17,14 @@ const mapStateToProps = (state) => ({
})
const mapDispatchToProps = (dispatch) => ({
onFetchGroups: (type) => {
dispatch(fetchGroups(type))
}
onFetchGroups: (type) => dispatch(fetchGroups(type))
})
export default
@connect(mapStateToProps, mapDispatchToProps)
@injectIntl
class GroupSidebarPanel extends ImmutablePureComponent {
static propTypes = {
groupIds: ImmutablePropTypes.list,
isLazy: PropTypes.bool,
@@ -37,6 +36,12 @@ class GroupSidebarPanel extends ImmutablePureComponent {
fetched: false,
}
updateOnProps = [
'groupIds',
'isLazy',
'isSlim',
]
componentDidMount() {
if (!this.props.isLazy) {
this.props.onFetchGroups('member')
@@ -76,23 +81,20 @@ class GroupSidebarPanel extends ImmutablePureComponent {
footerButtonTo={count > maxCount ? '/groups/browse/member' : undefined}
noPadding={slim}
>
<div className={_s.default}>
<ScrollableList
scrollKey='groups-panel'
>
{
groupIds.slice(0, maxCount).map((groupId, i) => (
<GroupListItem
key={`group-panel-item-${groupId}`}
id={groupId}
slim={slim}
isLast={groupIds.length - 1 === i}
/>
))
}
</ScrollableList>
</div>
<ScrollableList scrollKey='groups_panel'>
{
groupIds.slice(0, maxCount).map((groupId, i) => (
<GroupListItem
key={`group-panel-item-${groupId}`}
id={groupId}
slim={slim}
isLast={groupIds.count() - 1 === i}
/>
))
}
</ScrollableList>
</PanelLayout>
)
}
}

View File

@@ -49,7 +49,7 @@ class ListDetailsPanel extends ImmutablePureComponent {
<Divider isSmall />
<div className={[_s.default, _s.flexRow, _s.alignItemsCenter].join(' ')}>
<Icon id='calendar' size='12px' className={_s.fillColorSecondary} />
<Icon id='calendar' size='12px' className={_s.fillSecondary} />
<Text
size='small'
color='secondary'

View File

@@ -17,9 +17,7 @@ const mapStateToProps = (state) => ({
})
const mapDispatchToProps = (dispatch) => ({
onFetchLists() {
return dispatch(fetchLists())
},
onFetchLists: () => dispatch(fetchLists()),
})
export default
@@ -64,7 +62,7 @@ class ListsPanel extends ImmutablePureComponent {
const maxCount = 6
const listItems = lists.slice(0, maxCount).map(list => ({
const listItems = lists.slice(0, maxCount).map((list) => ({
to: `/lists/${list.get('id')}`,
title: list.get('title'),
}))
@@ -79,10 +77,7 @@ class ListsPanel extends ImmutablePureComponent {
noPadding
>
<div className={[_s.default, _s.boxShadowNone].join(' ')}>
<List
scrollKey='lists_sidebar_panel'
items={listItems}
/>
<List scrollKey='lists_sidebar_panel' items={listItems} />
</div>
</PanelLayout>
)

View File

@@ -55,7 +55,6 @@ class MediaGalleryPanel extends ImmutablePureComponent {
} = this.props
if (!account || !attachments) return null
if (attachments.size === 0) return null
return (
<PanelLayout
@@ -63,19 +62,22 @@ class MediaGalleryPanel extends ImmutablePureComponent {
title={intl.formatMessage(messages.title)}
headerButtonTitle={intl.formatMessage(messages.show_all)}
headerButtonTo={`/${account.get('acct')}/media`}
>
<div className={[_s.default, _s.flexRow, _s.flexWrap, _s.px10, _s.py10].join(' ')}>
{
attachments.slice(0, 16).map((attachment, i) => (
<MediaItem
isSmall
key={attachment.get('id')}
attachment={attachment}
account={account}
/>
))
}
</div>
>
{
attachments.size > 0 &&
<div className={[_s.default, _s.flexRow, _s.flexWrap, _s.px10, _s.py10].join(' ')}>
{
attachments.slice(0, 16).map((attachment, i) => (
<MediaItem
isSmall
key={attachment.get('id')}
attachment={attachment}
account={account}
/>
))
}
</div>
}
</PanelLayout>
)
}

View File

@@ -87,7 +87,7 @@ export default class PanelLayout extends PureComponent {
backgroundColor='none'
to={footerButtonTo}
onClick={footerButtonAction}
className={[_s.px15, _s.py15, _s.backgroundColorSubtle_onHover].join(' ')}
className={[_s.px15, _s.py15, _s.bgSubtle_onHover].join(' ')}
>
<Text color='brand' size='medium'>
{footerButtonTitle}

View File

@@ -71,7 +71,7 @@ class ProfileInfoPanel extends ImmutablePureComponent {
}
<div className={[_s.default, _s.flexRow, _s.alignItemsCenter].join(' ')}>
<Icon id='calendar' size='12px' className={_s.fillColorSecondary} />
<Icon id='calendar' size='12px' className={_s.fillSecondary} />
<Text
size='small'
color='secondary'

View File

@@ -1,23 +1,42 @@
import { me, monthlyExpensesComplete } from '../../initial_state'
import { injectIntl, defineMessages } from 'react-intl'
import { monthlyExpensesComplete } from '../../initial_state'
import { URL_DISSENTER_SHOP } from '../../constants'
import PanelLayout from './panel_layout';
import ProgressBar from '../progress_bar'
export default class ProgressPanel extends PureComponent {
const messages = defineMessages({
progressTitle: { id: 'progress_title', defaultMessage: '{value}% covered this month' },
operationsTitle: { id: 'operations_title', defaultMessage: "Gab's Operational Expenses" },
operationsSubtitle: { id: 'operations_subtitle', defaultMessage: 'We are 100% funded by you' },
})
export default
@injectIntl
class ProgressPanel extends PureComponent {
static propTypes = {
intl: PropTypes.object.isRequired,
}
render() {
if (!monthlyExpensesComplete || !me) return null
const { intl } = this.props
if (!monthlyExpensesComplete) return null
const value = Math.min(parseFloat(monthlyExpensesComplete), 100)
return (
<PanelLayout
title="Gab's Operational Expenses"
subtitle="We are 100% funded by you"
hasBackground
title={intl.formatMessage(messages.operationsTitle)}
subtitle={intl.formatMessage(messages.operationsSubtitle)}
>
<ProgressBar
progress={monthlyExpensesComplete}
title={`${Math.min(parseFloat(monthlyExpensesComplete), 100)}% covered this month`}
href='https://shop.dissenter.com/category/donations'
title={intl.formatMessage(messages.progressTitle, { value })}
href={URL_DISSENTER_SHOP}
/>
</PanelLayout>
)
}
}

View File

@@ -3,9 +3,8 @@ import ImmutablePureComponent from 'react-immutable-pure-component'
import ImmutablePropTypes from 'react-immutable-proptypes'
import { fetchGabTrends } from '../../actions/gab_trends'
import PanelLayout from './panel_layout'
import ColumnIndicator from '../column_indicator'
import ScrollableList from '../scrollable_list'
import TrendingItem from '../trends_item'
import TrendsItem from '../trends_item'
const messages = defineMessages({
title: { id: 'trends.title', defaultMessage: 'Trending right now' },
@@ -30,6 +29,10 @@ class TrendsPanel extends ImmutablePureComponent {
onFetchGabTrends: PropTypes.func.isRequired,
}
updateOnProps = [
'gabtrends',
]
componentDidMount() {
this.props.onFetchGabTrends()
}
@@ -42,34 +45,21 @@ class TrendsPanel extends ImmutablePureComponent {
noPadding
title={intl.formatMessage(messages.title)}
>
<div className={_s.default}>
<ScrollableList
showLoading={gabtrends.size == 0}
scrollKey='trending-items'
>
{
gabtrends.isEmpty() &&
<ColumnIndicator type='loading' />
gabtrends.slice(0, 8).map((trend, i) => (
<TrendsItem
key={`gab-trend-${i}`}
index={i + 1}
isLast={i === 7}
trend={trend}
/>
))
}
{
!gabtrends.isEmpty() &&
<ScrollableList
scrollKey='trending-items'
>
{
gabtrends.slice(0, 8).map((trend, i) => (
<TrendingItem
key={`gab-trend-${i}`}
index={i + 1}
isLast={i === 7}
url={trend.get('url')}
title={trend.get('title')}
description={trend.get('description')}
imageUrl={trend.get('image')}
publishDate={trend.get('date_published')}
author={trend.getIn(['author', 'name'], '')}
/>
))
}
</ScrollableList>
}
</div>
</ScrollableList>
</PanelLayout>
)
}

View File

@@ -2,19 +2,20 @@ import { NavLink } from 'react-router-dom'
import { injectIntl, defineMessages } from 'react-intl'
import ImmutablePropTypes from 'react-immutable-proptypes'
import ImmutablePureComponent from 'react-immutable-pure-component'
import classNames from 'classnames/bind'
import { me } from '../../initial_state'
import { makeGetAccount } from '../../selectors'
import { shortNumberFormat } from '../../utils/numbers'
import { openModal } from '../../actions/modal'
import {
CX,
MODAL_EDIT_PROFILE,
} from '../../constants'
import PanelLayout from './panel_layout'
import Avatar from '../avatar'
import Button from '../button'
import DisplayName from '../display_name'
import Avatar from '../avatar'
import Image from '../image'
import UserStat from '../user_stat'
import PanelLayout from './panel_layout'
const cx = classNames.bind(_s)
const messages = defineMessages({
gabs: { id: 'account.posts', defaultMessage: 'Gabs' },
@@ -30,7 +31,7 @@ const mapStateToProps = (state) => ({
const mapDispatchToProps = (dispatch) => ({
onOpenEditProfile() {
dispatch(openModal('EDIT_PROFILE'))
dispatch(openModal(MODAL_EDIT_PROFILE))
},
})
@@ -38,6 +39,7 @@ export default
@connect(mapStateToProps, mapDispatchToProps)
@injectIntl
class UserPanel extends ImmutablePureComponent {
static propTypes = {
account: ImmutablePropTypes.map.isRequired,
intl: PropTypes.object.isRequired,
@@ -60,15 +62,15 @@ class UserPanel extends ImmutablePureComponent {
this.setState({ hovering: false })
}
handleOnOpenEditProfile = () => {
this.props.onOpenEditProfile()
}
render() {
const { account, intl } = this.props
const {
account,
intl,
onOpenEditProfile,
} = this.props
const { hovering } = this.state
const buttonClasses = cx({
const buttonClasses = CX({
posAbs: 1,
mt10: 1,
mr10: 1,
@@ -96,7 +98,7 @@ class UserPanel extends ImmutablePureComponent {
backgroundColor='secondary'
radiusSmall
className={buttonClasses}
onClick={this.handleOnOpenEditProfile}
onClick={onOpenEditProfile}
>
{intl.formatMessage(messages.edit_profile)}
</Button>
@@ -134,4 +136,5 @@ class UserPanel extends ImmutablePureComponent {
</PanelLayout>
)
}
}

View File

@@ -0,0 +1,96 @@
import { withRouter } from 'react-router-dom'
import { CX } from '../constants'
import Button from './button'
import Text from './text'
export default
@withRouter
class PillItem extends PureComponent {
static propTypes = {
icon: PropTypes.string,
isActive: PropTypes.bool,
onClick: PropTypes.func,
title: PropTypes.string,
to: PropTypes.string,
}
state = {
isCurrent: -1,
}
componentDidUpdate(prevProps) {
// If user navigates to different page, ensure tab bar item
// with this.props.to that is on location is set to active.
if (this.props.location !== prevProps.location) {
const isCurrent = this.props.to === this.props.location.pathname
if (this.state.isCurrent !== isCurrent) {
this.setState({ isCurrent })
}
}
}
render() {
const {
title,
to,
onClick,
location,
isActive,
} = this.props
const { isCurrent } = this.state
// Combine state, props, location to make absolutely
// sure of active status.
const active = isActive ||
(isCurrent === -1 ? to === location.pathname : false)
const containerClasses = CX({
default: 1,
noUnderline: 1,
text: 1,
alignItemsCenter: 1,
justifyContentCenter: 1,
py5: 1,
outlineNone: 1,
cursorPointer: 1,
circle: 1,
bgSecondary: !active,
bgSecondaryDark_onHover: !active,
bgBrand: active,
mr5: 1,
mb5: 1,
})
const textParentClasses = CX({
default: 1,
height100PC: 1,
alignItemsCenter: 1,
justifyContentCenter: 1,
py2: 1,
px15: 1,
})
const textOptions = {
size: 'small',
color: active ? 'white' : 'secondary',
weight: active ? 'bold' : 'medium',
}
return (
<Button
onClick={onClick}
className={containerClasses}
to={to || undefined}
noClasses
>
<span className={textParentClasses}>
<Text {...textOptions}>
{title}
</Text>
</span>
</Button>
)
}
}

View File

@@ -0,0 +1,34 @@
import PillItem from './pill_item'
/**
* Renders pills components
* @param {array} [props.pills] - tab bar data for creating `TabBarItem`
*/
export default class Pills extends PureComponent {
static propTypes = {
pills: PropTypes.array,
}
render() {
const { pills } = this.props
return (
<div className={[_s.default, _s.flexWrap, _s.px5, _s.flexRow].join(' ')}>
{
!!pills &&
pills.map((tab, i) => (
<PillItem
key={`pill-item-${i}`}
title={tab.title}
onClick={tab.onClick}
to={tab.to}
isActive={tab.active}
/>
))
}
</div>
)
}
}

View File

@@ -92,8 +92,8 @@ class Poll extends ImmutablePureComponent {
left0: 1,
radiusSmall: 1,
height100PC: 1,
backgroundColorSubtle2: !leading,
backgroundColorBrandLight: leading,
bgSecondary: !leading,
bgBrandLight: leading,
})
const inputClasses = cx('poll__input', {
@@ -107,11 +107,11 @@ class Poll extends ImmutablePureComponent {
py10: showResults,
mb10: 1,
border1PX: !showResults,
fillColorSecondary: !showResults,
fillSecondary: !showResults,
circle: !showResults,
cursorPointer: !showResults,
backgroundColorSubtle_onHover: !showResults,
backgroundColorSubtle: !showResults && active,
bgSubtle_onHover: !showResults,
bgSubtle: !showResults && active,
})
const textContainerClasses = cx({

View File

@@ -90,14 +90,14 @@ class StatusVisibilityDropdown extends PureComponent {
cursorPointer: 1,
borderBottom1PX: !isLast,
borderColorSecondary: !isLast,
backgroundColorSubtle_onHover: !isActive,
backgroundColorBrand: isActive,
bgSubtle_onHover: !isActive,
bgBrand: isActive,
})
const iconClasses = cx({
ml10: 1,
mt2: 1,
fillColorWhite: isActive,
fillWhite: isActive,
})
return (

View File

@@ -108,6 +108,7 @@ class ProfileHeader extends ImmutablePureComponent {
const headerSrc = !!account ? account.get('header') : ''
const headerMissing = headerSrc.indexOf(PLACEHOLDER_MISSING_HEADER_SRC) > -1 || !headerSrc
const avatarSize = headerMissing ? 75 : 150
const top = headerMissing ? -30 : -380
const avatarContainerClasses = CX({
default: 1,
@@ -131,96 +132,101 @@ class ProfileHeader extends ImmutablePureComponent {
return (
<div className={[_s.default, _s.z1, _s.width100PC].join(' ')}>
<Sticky top={top} enabled onStateChange={this.onStickyStateChange}>
<div className={[_s.default, _s.z1, _s.width100PC, _s.alignItemsCenter, _s.boxShadowBlock, _s.bgPrimary].join(' ')}>
{
!headerMissing &&
<div className={[_s.default, _s.height350PX, _s.width100PC, _s.radiusSmall, _s.overflowHidden].join(' ')}>
<Image
alt={intl.formatMessage(messages.headerPhoto)}
className={_s.height350PX}
src={headerSrc}
/>
</div>
}
<div className={[_s.default, _s.width100PC].join(' ')}>
<div className={[_s.default, _s.flexRow, _s.pr15, _s.pl25, _s.mb5].join(' ')}>
<div className={avatarContainerClasses}>
<Avatar size={avatarSize} account={account} noHover />
</div>
<div className={[_s.default, _s.flexRow, _s.px15, _s.flexNormal, _s.py10].join(' ')}>
<DisplayName account={account} isMultiline noRelationship isLarge noHover />
</div>
</div>
<Sticky enabled onStateChange={this.onStickyStateChange}>
<div className={[_s.default, _s.flexRow, _s.backgroundColorSecondary3, _s.borderBottom1PX, _s.borderColorSecondary, _s.height53PX].join(' ')}>
<div className={tabBarContainerClasses}>
<TabBar tabs={tabs} isLarge />
</div>
<div className={stickyBarContainerClasses}>
<Avatar size={36} account={account} noHover />
<div className={[_s.default, _s.ml10].join(' ')}>
<DisplayName account={account} noUsername noRelationship noHover isLarge />
</div>
</div>
<div className={[_s.default, _s.width1015PX].join(' ')}>
{
account && account.get('id') === me &&
<div className={[_s.default, _s.flexRow, _s.mlAuto, _s.py5].join(' ')}>
<Button
isOutline
backgroundColor='none'
color='brand'
className={[_s.justifyContentCenter, _s.alignItemsCenter].join(' ')}
onClick={this.handleOnEditProfile}
>
<Text color='inherit' weight='bold' size='medium' className={_s.px15}>
{intl.formatMessage(messages.editProfile)}
</Text>
</Button>
</div>
}
{
account && account.get('id') !== me &&
<div className={[_s.default, _s.flexRow, _s.mlAuto, _s.py5].join(' ')}>
<Button
isOutline
icon='ellipsis'
iconSize='18px'
iconClassName={_s.inheritFill}
color='brand'
backgroundColor='none'
className={[_s.justifyContentCenter, _s.alignItemsCenter, _s.mr10, _s.px10].join(' ')}
onClick={this.handleOpenMore}
buttonRef={this.setOpenMoreNodeRef}
!headerMissing &&
<div className={[_s.default, _s.height350PX, _s.width100PC, _s.bottomRightRadiusSmall, _s.bottomLeftRadiusSmall, _s.overflowHidden].join(' ')}>
<Image
alt={intl.formatMessage(messages.headerPhoto)}
className={_s.height350PX}
src={headerSrc}
/>
<form action='https://chat.gab.com/private-message' method='POST'>
<Button
isOutline
type='submit'
icon='chat'
iconSize='18px'
iconClassName={_s.inheritFill}
color='brand'
backgroundColor='none'
className={[_s.justifyContentCenter, _s.alignItemsCenter, _s.mr10, _s.px10].join(' ')}
/>
<input type='hidden' value={account.get('username')} name='username' />
</form>
<AccountActionButton account={account} />
</div>
}
<div className={[_s.default, _s.width100PC].join(' ')}>
<div className={[_s.default, _s.flexRow, _s.pr15, _s.pl25, _s.mb5].join(' ')}>
<div className={avatarContainerClasses}>
<Avatar size={avatarSize} account={account} noHover />
</div>
<div className={[_s.default, _s.flexRow, _s.px15, _s.flexNormal, _s.py10].join(' ')}>
<DisplayName account={account} isMultiline noRelationship isLarge noHover />
</div>
</div>
<div className={[_s.default, _s.flexRow, _s.bgPrimary, _s.height53PX].join(' ')}>
<div className={tabBarContainerClasses}>
<TabBar tabs={tabs} isLarge />
</div>
<div className={stickyBarContainerClasses}>
<Avatar size={36} account={account} noHover />
<div className={[_s.default, _s.ml10].join(' ')}>
<DisplayName account={account} noUsername noRelationship noHover isLarge />
</div>
</div>
{
account && account.get('id') === me &&
<div className={[_s.default, _s.flexRow, _s.mlAuto, _s.py5].join(' ')}>
<Button
isOutline
backgroundColor='none'
color='brand'
className={[_s.justifyContentCenter, _s.alignItemsCenter].join(' ')}
onClick={this.handleOnEditProfile}
>
<Text color='inherit' weight='bold' size='medium' className={_s.px15}>
{intl.formatMessage(messages.editProfile)}
</Text>
</Button>
</div>
}
{
account && account.get('id') !== me &&
<div className={[_s.default, _s.flexRow, _s.mlAuto, _s.py5].join(' ')}>
<Button
isOutline
icon='ellipsis'
iconSize='18px'
iconClassName={_s.inheritFill}
color='brand'
backgroundColor='none'
className={[_s.justifyContentCenter, _s.alignItemsCenter, _s.mr10, _s.px10].join(' ')}
onClick={this.handleOpenMore}
buttonRef={this.setOpenMoreNodeRef}
/>
<form action='https://chat.gab.com/private-message' method='POST'>
<Button
isOutline
type='submit'
icon='chat'
iconSize='18px'
iconClassName={_s.inheritFill}
color='brand'
backgroundColor='none'
className={[_s.justifyContentCenter, _s.alignItemsCenter, _s.mr10, _s.px10].join(' ')}
/>
<input type='hidden' value={account.get('username')} name='username' />
</form>
<AccountActionButton account={account} />
</div>
}
</div>
</div>
</div>
</Sticky>
</div>
</div>
</Sticky>
</div>
)
}

View File

@@ -1,14 +1,14 @@
import classNames from 'classnames/bind'
import { CX } from '../constants'
import Button from './button'
import Text from './text'
const cx = classNames.bind(_s)
export default class ProgressBar extends PureComponent {
static propTypes = {
progress: PropTypes.number,
small: PropTypes.bool,
title: PropTypes.string,
href: PropTypes.string,
}
render() {
@@ -16,7 +16,7 @@ export default class ProgressBar extends PureComponent {
progress,
small,
title,
href
href,
} = this.props
const completed = Math.min(parseFloat(progress), 100)
@@ -24,10 +24,10 @@ export default class ProgressBar extends PureComponent {
width: `${completed}%`,
}
const containerClassName = cx({
const containerClassName = CX({
default: 1,
backgroundColorLoading: !small,
backgroundColorSubtle2: small,
bgLoading: !small,
bgSecondary: small,
noUnderline: 1,
circle: 1,
overflowHidden: 1,
@@ -42,7 +42,7 @@ export default class ProgressBar extends PureComponent {
noClasses
className={containerClassName}
>
<div className={[_s.default, _s.backgroundColorBrand, _s.circle, _s.height100PC, _s.backgroundCandy].join(' ')} style={style} />
<div className={[_s.default, _s.bgBrand, _s.circle, _s.height100PC, _s.backgroundCandy].join(' ')} style={style} />
<div className={[_s.default, _s.posAbs, _s.width100PC, _s.height100PC, _s.alignItemsCenter, _s.justifyContentCenter].join(' ')}>
{
!!title &&

View File

@@ -116,7 +116,7 @@ class RichTextEditorBar extends PureComponent {
if (!rteControlsVisible || !isPro) return null
return (
<div className={[_s.default, _s.backgroundColorPrimary, _s.borderBottom1PX, _s.borderColorSecondary, _s.py5, _s.px15, _s.alignItemsCenter, _s.flexRow].join(' ')}>
<div className={[_s.default, _s.bgPrimary, _s.borderBottom1PX, _s.borderColorSecondary, _s.py5, _s.px15, _s.alignItemsCenter, _s.flexRow].join(' ')}>
{
RTE_ITEMS.map((item, i) => (
<StyleButton
@@ -179,8 +179,8 @@ class StyleButton extends PureComponent {
px10: 1,
mr5: 1,
noSelect: 1,
backgroundColorSubtle2Dark_onHover: 1,
backgroundColorBrandLight: active,
bgSecondaryDark_onHover: 1,
bgBrandLight: active,
// py10: !small,
// py5: small,
// px5: small,

View File

@@ -1,12 +1,13 @@
import { withRouter } from 'react-router-dom'
import queryString from 'query-string'
import { CX } from '../constants'
import {
changeSearch,
clearSearch,
submitSearch,
showSearch,
} from '../actions/search'
import Input from './input'
import Button from './button'
const mapStateToProps = (state) => ({
value: state.getIn(['search', 'value']),
@@ -40,7 +41,7 @@ class Search extends PureComponent {
}
state = {
expanded: false,
focused: false,
}
textbox = React.createRef()
@@ -57,17 +58,17 @@ class Search extends PureComponent {
}
}
handleChange = (value) => {
this.props.onChange(value)
handleOnChange = (e) => {
this.props.onChange(e.target.value)
}
handleFocus = () => {
this.setState({ expanded: true })
handleOnFocus = () => {
this.setState({ focused: true })
this.props.onShow()
}
handleBlur = () => {
this.setState({ expanded: false })
handleOnBlur = () => {
this.setState({ focused: false })
}
handleKeyUp = (e) => {
@@ -88,44 +89,80 @@ class Search extends PureComponent {
this.textbox = n
}
handleSubmit = () => {
this.props.onSubmit()
}
render() {
const {
value,
submitted,
onClear,
withOverlay
} = this.props
const { expanded } = this.state
const { focused } = this.state
const highlighted = focused || `${value}`.length > 0
const hasValue = value ? value.length > 0 || submitted : 0
const inputClasses = CX({
default: 1,
text: 1,
outlineNone: 1,
lineHeight125: 1,
displayBlock: 1,
py7: 1,
bgTransparent: !highlighted,
colorPrimary: 1,
fs14PX: 1,
flexGrow1: 1,
radiusSmall: 1,
pl15: 1,
searchInput: 1,
})
const containerClasses = CX({
default: 1,
bgBrandLight: !highlighted,
bgWhite: highlighted,
flexRow: 1,
radiusSmall: 1,
alignItemsCenter: 1,
})
const prependIconColor = highlighted ? 'brand' : 'white'
const id = 'nav-search'
return (
<div className={[_s.default, _s.justifyContentCenter, _s.height53PX].join(' ')}>
<Input
hasClear
value={value}
inputRef={this.setTextbox}
id='search'
prependIcon='search'
placeholder='Search Gab'
onChange={this.handleChange}
onKeyUp={this.handleKeyUp}
onFocus={this.handleFocus}
onBlur={this.handleBlur}
onClear={onClear}
hideLabel
title='Search'
/>
<div className={containerClasses}>
<label className={_s.visiblyHidden} htmlFor={id}>Search</label>
{
withOverlay &&
{/*<Overlay show={expanded && !hasValue} placement='bottom' target={this}>
<SearchPopout />
</Overlay>*/}
}
<input
id={id}
className={inputClasses}
type='text'
placeholder='Search for people, groups or news'
ref={this.setTextbox}
value={value}
onKeyUp={this.handleKeyUp}
onChange={this.handleOnChange}
onFocus={this.handleOnFocus}
onBlur={this.handleOnBlur}
/>
<Button
className={[_s.px10, _s.mr5].join(' ')}
tabIndex='0'
title='...'
backgroundColor='none'
color={prependIconColor}
onClick={this.handleSubmit}
icon='search'
iconClassName={_s.inheritFill}
iconSize='16px'
/>
</div>
</div>
)
}
}
}

View File

@@ -49,7 +49,7 @@ export default class Select extends ImmutablePureComponent {
<Icon
id='select'
size='14px'
className={[_s.fillColorSecondary, _s.posAbs, _s.right0, _s.mr10, _s.bottom0, _s.mb15].join(' ')}
className={[_s.fillSecondary, _s.posAbs, _s.right0, _s.mr10, _s.bottom0, _s.mb15].join(' ')}
/>
</div>
)

View File

@@ -24,7 +24,7 @@ class SensitiveMediaItem extends PureComponent {
return (
<div className={[_s.default, _s.px15, _s.pt5].join(' ')}>
<div className={[_s.default, _s.flexRow, _s.radiusSmall, _s.backgroundColorSecondary3, _s.py10, _s.px15, _s.height100PC, _s.width100PC].join(' ')}>
<div className={[_s.default, _s.flexRow, _s.radiusSmall, _s.bgTertiary, _s.py10, _s.px15, _s.height100PC, _s.width100PC].join(' ')}>
<div className={[_s.default, _s.justifyContentCenter, _s.flexNormal].join(' ')}>
<Text color='secondary'>
{intl.formatMessage(messages.warning)}
@@ -35,7 +35,7 @@ class SensitiveMediaItem extends PureComponent {
onClick={onClick}
color='tertiary'
backgroundColor='none'
className={_s.backgroundColorSubtle2Dark_onHover}
className={_s.bgSecondaryDark_onHover}
>
<Text color='inherit' weight='bold' size='medium'>
{intl.formatMessage(messages.view)}

View File

@@ -11,7 +11,9 @@ import { makeGetAccount } from '../selectors'
import Responsive from '../features/ui/util/responsive_component'
import SidebarSectionTitle from './sidebar_section_title'
import SidebarSectionItem from './sidebar_section_item'
import SidebarHeader from './sidebar_header'
import Heading from './heading'
import Pills from './pills'
import Divider from './divider'
const messages = defineMessages({
followers: { id: 'account.followers', defaultMessage: 'Followers' },
@@ -27,6 +29,8 @@ const messages = defineMessages({
lists: { id: 'column.lists', defaultMessage: 'Lists' },
apps: { id: 'tabs_bar.apps', defaultMessage: 'Apps' },
more: { id: 'sidebar.more', defaultMessage: 'More' },
explore: { id: 'explore', defaultMessage: 'Explore' },
menu: { id: 'menu', defaultMessage: 'Menu' },
pro: { id: 'promo.gab_pro', defaultMessage: 'Upgrade to GabPRO' },
trends: { id: 'promo.trends', defaultMessage: 'Trends' },
search: { id: 'tabs_bar.search', defaultMessage: 'Search' },
@@ -73,6 +77,10 @@ class Sidebar extends ImmutablePureComponent {
openSidebarMorePopover: PropTypes.func.isRequired,
notificationCount: PropTypes.number.isRequired,
homeItemsQueueCount: PropTypes.number.isRequired,
actions: PropTypes.array,
tabs: PropTypes.array,
title: PropTypes.string,
showBackBtn: PropTypes.bool,
}
handleOpenComposeModal = () => {
@@ -98,6 +106,10 @@ class Sidebar extends ImmutablePureComponent {
homeItemsQueueCount,
showCommunityTimeline,
moreOpen,
actions,
tabs,
title,
showBackBtn,
} = this.props
// : todo :
@@ -196,13 +208,23 @@ class Sidebar extends ImmutablePureComponent {
return (
<header role='banner' className={[_s.default, _s.flexGrow1, _s.z3, _s.alignItemsEnd].join(' ')}>
<div className={[_s.default, _s.width240PX].join(' ')}>
<div className={[_s.default, _s.posFixed, _s.top0, _s.height100PC].join(' ')}>
<div className={[_s.default, _s.posFixed, _s.heightCalc53PX, _s.bottom0].join(' ')}>
<div className={[_s.default, _s.height100PC, _s.alignItemsStart, _s.width240PX, _s.pr15, _s.py10, _s.overflowYScroll].join(' ')}>
<SidebarHeader />
<div className={_s.default}>
<div className={[_s.default, _s.px5, _s.py10].join(' ')}>
<Heading size='h1'>
{title}
</Heading>
</div>
{
!!tabs &&
<div className={[_s.default, _s.mt10, _s.pb15, _s.borderBottom1PX, _s.borderColorSecondary].join(' ')}>
<Pills pills={tabs} />
</div>
}
</div>
<nav aria-label='Primary' role='navigation' className={[_s.default, _s.width100PC, _s.mb15].join(' ')}>
<SidebarSectionTitle>Menu</SidebarSectionTitle>
<SidebarSectionTitle>{intl.formatMessage(messages.menu)}</SidebarSectionTitle>
{
menuItems.map((menuItem, i) => {
if (menuItem.hidden) return null
@@ -212,13 +234,7 @@ class Sidebar extends ImmutablePureComponent {
)
})
}
{ /* <SidebarSectionTitle>Shortcuts</SidebarSectionTitle> */ }
{
shortcutItems.map((shortcutItem, i) => (
<SidebarSectionItem {...shortcutItem} key={`sidebar-item-shortcut-${i}`} />
))
}
<SidebarSectionTitle>Explore</SidebarSectionTitle>
<SidebarSectionTitle>{intl.formatMessage(messages.explore)}</SidebarSectionTitle>
{
exploreItems.map((exploreItem, i) => (
<SidebarSectionItem {...exploreItem} key={`sidebar-item-explore-${i}`} />
@@ -230,7 +246,7 @@ class Sidebar extends ImmutablePureComponent {
<Button
isBlock
onClick={this.handleOpenComposeModal}
className={[_s.py15, _s.fontSize15PX, _s.fontWeightBold].join(' ')}
className={[_s.py15, _s.fs15PX, _s.fontWeightBold].join(' ')}
>
Gab
</Button>

View File

@@ -1,57 +0,0 @@
import { Fragment } from 'react'
import { NavLink } from 'react-router-dom'
import ImmutablePropTypes from 'react-immutable-proptypes'
import ImmutablePureComponent from 'react-immutable-pure-component'
import { me } from '../initial_state'
import { makeGetAccount } from '../selectors'
import Icon from './icon'
import SidebarSectionItem from './sidebar_section_item'
import Text from './text'
const mapStateToProps = (state) => {
const getAccount = makeGetAccount()
return {
account: getAccount(state, me),
}
}
export default
@connect(mapStateToProps)
class SidebarHeader extends ImmutablePureComponent {
static propTypes = {
account: ImmutablePropTypes.map,
}
render() {
const { account } = this.props
const isPro = account.get('is_pro')
return (
<Fragment>
<h1 className={[_s.default].join(' ')}>
<NavLink to='/' aria-label='Gab' className={[_s.default, _s.flexRow, _s.noSelect, _s.noUnderline, _s.height50PX, _s.cursorPointer, _s.px10].join(' ')}>
<Icon id='gab-logo' className={_s.fillColorBrand} />
{
isPro &&
<Text weight='bold' color='brand' size='extraSmall' className={[_s.pb5].join(' ')}>
PRO
</Text>
}
</NavLink>
</h1>
{
(!!me && !!account) &&
<SidebarSectionItem
image={account.get('avatar')}
title={account.get('acct')}
to={`/${account.get('acct')}`}
/>
}
</Fragment>
)
}
}

View File

@@ -69,35 +69,35 @@ export default class SidebarSectionItem extends PureComponent {
outlineNone: 1,
borderColorTransparent: !shouldShowActive,
borderColorSecondary: shouldShowActive,
backgroundTransparent: !shouldShowActive,
backgroundColorPrimary: shouldShowActive,
bgTransparent: !shouldShowActive,
bgPrimary: shouldShowActive,
})
const textClasses = cx({
default: 1,
fontWeightNormal: 1,
fontSize15PX: 1,
fs15PX: 1,
text: 1,
textOverflowEllipsis: 1,
colorPrimary: 1,
})
const iconClasses = cx({
fillColorPrimary: 1,
fillPrimary: 1,
})
const countClasses = cx({
default: 1,
text: 1,
mlAuto: 1,
fontSize12PX: 1,
fs12PX: 1,
px5: 1,
mr2: 1,
lineHeight15: 1,
ml5: 1,
colorSecondary: !isNotifications,
colorWhite: isNotifications,
backgroundColorBrand: isNotifications,
bgBrand: isNotifications,
radiusSmall: isNotifications,
})
@@ -110,7 +110,7 @@ export default class SidebarSectionItem extends PureComponent {
buttonRef={buttonRef}
onMouseEnter={() => this.handleOnMouseEnter()}
onMouseLeave={() => this.handleOnMouseLeave()}
className={[_s.default, _s.noUnderline, _s.outlineNone, _s.cursorPointer, _s.width100PC, _s.backgroundTransparent].join(' ')}
className={[_s.default, _s.noUnderline, _s.outlineNone, _s.cursorPointer, _s.width100PC, _s.bgTransparent].join(' ')}
>
<div className={containerClasses}>
{

View File

@@ -11,7 +11,7 @@ export default class SidebarSectionTitle extends PureComponent {
return (
<div className={[_s.default, _s.py5, _s.px10, _s.mt10].join(' ')}>
<Text size='small' weight='bold' color='tertiary'>
<Text color='tertiary'>
{children}
</Text>
</div>

View File

@@ -444,10 +444,9 @@ class Status extends ImmutablePureComponent {
const containerClasses = cx({
default: 1,
radiusSmall: !isChild,
pb15: isFeatured,
radiusSmall: !isChild,
backgroundColorPrimary: !isChild,
bgPrimary: !isChild,
boxShadowBlock: !isChild,
outlineNone: 1,
mb15: !isChild,
@@ -465,7 +464,7 @@ class Status extends ImmutablePureComponent {
pb10: isChild && status.get('media_attachments').size === 0,
pb5: isChild && status.get('media_attachments').size > 1,
cursorPointer: isChild,
backgroundColorSubtle_onHover: isChild,
bgSubtle_onHover: isChild,
})
return (

View File

@@ -2,9 +2,13 @@ import ImmutablePropTypes from 'react-immutable-proptypes'
import ImmutablePureComponent from 'react-immutable-pure-component'
import { defineMessages, injectIntl } from 'react-intl'
import { NavLink } from 'react-router-dom'
import classNames from 'classnames/bind'
import Text from './text'
import StatusActionBarItem from './status_action_bar_item'
import {
CX,
BREAKPOINT_EXTRA_SMALL,
} from '../constants'
import Responsive from '../features/ui/util/responsive_component'
const messages = defineMessages({
comment: { id: 'status.comment', defaultMessage: 'Comment' },
@@ -17,8 +21,6 @@ const messages = defineMessages({
commentsLabel: { id: 'comments.label', defaultMessage: '{number, plural, one {# comment} other {# comments}}' },
})
const cx = classNames.bind(_s)
export default
@injectIntl
class StatusActionBar extends ImmutablePureComponent {
@@ -88,14 +90,14 @@ class StatusActionBar extends ImmutablePureComponent {
const statusUrl = `/${status.getIn(['account', 'acct'])}/posts/${status.get('id')}`
const containerClasses = cx({
const containerClasses = CX({
default: 1,
px10: 1,
mt10: !shouldCondense,
mt5: shouldCondense,
})
const innerContainerClasses = cx({
const innerContainerClasses = CX({
default: 1,
py2: 1,
flexRow: 1,
@@ -105,14 +107,14 @@ class StatusActionBar extends ImmutablePureComponent {
mt5: hasInteractions,
})
const interactionBtnClasses = cx({
const interactionBtnClasses = CX({
default: 1,
text: 1,
cursorPointer: 1,
fontWeightNormal: 1,
noUnderline: 1,
underline_onHover: 1,
backgroundTransparent: 1,
bgTransparent: 1,
mr10: 1,
py5: 1,
})
@@ -179,12 +181,14 @@ class StatusActionBar extends ImmutablePureComponent {
buttonRef={this.setRepostButton}
onClick={this.handleRepostClick}
/>
<StatusActionBarItem
buttonRef={this.setShareButton}
title={intl.formatMessage(messages.share)}
icon='share'
onClick={this.handleShareClick}
/>
<Responsive min={BREAKPOINT_EXTRA_SMALL}>
<StatusActionBarItem
buttonRef={this.setShareButton}
title={intl.formatMessage(messages.share)}
icon='share'
onClick={this.handleShareClick}
/>
</Responsive>
</div>
</div>
</div>

View File

@@ -34,7 +34,7 @@ export default class StatusActionBarItem extends PureComponent {
justifyContentCenter: 1,
alignItemsCenter: 1,
px10: 1,
backgroundColorSubtle_onHover: !disabled,
bgSubtle_onHover: !disabled,
})
const color = active ? 'brand' : 'secondary'

View File

@@ -120,7 +120,7 @@ export default class Card extends ImmutablePureComponent {
return (
<div
ref={this.setRef}
className={[_s.default, _s.backgroundColorSecondary3, _s.posAbs, _s.top0, _s.right0, _s.bottom0, _s.left0, _s.statusCardVideo].join(' ')}
className={[_s.default, _s.bgTertiary, _s.posAbs, _s.top0, _s.right0, _s.bottom0, _s.left0, _s.statusCardVideo].join(' ')}
dangerouslySetInnerHTML={content}
/>
)
@@ -141,7 +141,7 @@ export default class Card extends ImmutablePureComponent {
const title = interactive ?
(
<a
className={[_s.default, _s.displayFlex, _s.text, _s.noUnderline, _s.overflowWrapBreakWord, _s.colorPrimary, _s.fontSize15PX, _s.fontWeightMedium].join(' ')}
className={[_s.default, _s.displayFlex, _s.text, _s.noUnderline, _s.overflowWrapBreakWord, _s.colorPrimary, _s.fs15PX, _s.fontWeightMedium].join(' ')}
href={card.get('url')}
title={card.get('title')}
rel='noopener noreferrer'
@@ -151,7 +151,7 @@ export default class Card extends ImmutablePureComponent {
</a>
)
: (
<span className={[_s.default, _s.displayFlex, _s.text, _s.overflowWrapBreakWord, _s.colorPrimary, _s.fontSize15PX, _s.fontWeightMedium].join(' ')}>
<span className={[_s.default, _s.displayFlex, _s.text, _s.overflowWrapBreakWord, _s.colorPrimary, _s.fs15PX, _s.fontWeightMedium].join(' ')}>
{card.get('title')}
</span>
)
@@ -159,11 +159,11 @@ export default class Card extends ImmutablePureComponent {
const description = (
<div className={[_s.default, _s.flexNormal, _s.px10, _s.py10, _s.borderColorSecondary, _s.borderLeft1PX].join(' ')}>
{title}
<p className={[_s.default, _s.displayFlex, _s.text, _s.mt5, _s.mb5, _s.overflowWrapBreakWord, _s.colorSecondary, _s.fontSize13PX, _s.fontWeightNormal].join(' ')}>
<p className={[_s.default, _s.displayFlex, _s.text, _s.mt5, _s.mb5, _s.overflowWrapBreakWord, _s.colorSecondary, _s.fs13PX, _s.fontWeightNormal].join(' ')}>
{trim(card.get('description') || '', maxDescription)}
</p>
<span className={[_s.default, _s.mtAuto, _s.flexRow, _s.alignItemsCenter, _s.colorSecondary, _s.text, _s.displayFlex, _s.textOverflowEllipsis, _s.fontSize13PX].join(' ')}>
<Icon id='link' size='10px' className={[_s.fillColorSecondary, _s.mr5].join(' ')} fixedWidth />
<span className={[_s.default, _s.mtAuto, _s.flexRow, _s.alignItemsCenter, _s.colorSecondary, _s.text, _s.displayFlex, _s.textOverflowEllipsis, _s.fs13PX].join(' ')}>
<Icon id='link' size='10px' className={[_s.fillSecondary, _s.mr5].join(' ')} fixedWidth />
{provider}
</span>
</div>
@@ -197,10 +197,10 @@ export default class Card extends ImmutablePureComponent {
{ !embed &&
<div className={[_s.default, _s.posAbs, _s.top0, _s.right0, _s.left0, _s.bottom0, _s.alignItemsCenter, _s.justifyContentCenter].join(' ')}>
<button
className={[_s.default, _s.cursorPointer, _s.backgroundColorBlackOpaque, _s.radiusSmall, _s.py15, _s.px15].join(' ')}
className={[_s.default, _s.cursorPointer, _s.bgBlackOpaque, _s.radiusSmall, _s.py15, _s.px15].join(' ')}
onClick={this.handleEmbedClick}
>
<Icon id={iconVariant} size='22px' className={[_s.fillColorWhite].join(' ')} />
<Icon id={iconVariant} size='22px' className={[_s.fillWhite].join(' ')} />
</button>
</div>
}
@@ -219,7 +219,7 @@ export default class Card extends ImmutablePureComponent {
} else {
embed = (
<div className={[_s.default, _s.py15, _s.px15, _s.width72PX, _s.alignItemsCenter, _s.justifyContentCenter].join(' ')}>
<Icon id='website' size='22px' className={_s.fillColorSecondary} />
<Icon id='website' size='22px' className={_s.fillSecondary} />
</div>
)
}
@@ -228,7 +228,7 @@ export default class Card extends ImmutablePureComponent {
<div className={[_s.default, _s.width100PC, _s.px10].join(' ')}>
<a
href={card.get('url')}
className={[_s.default, _s.cursorPointer, _s.flexRow, _s.overflowHidden, _s.noUnderline, _s.width100PC, _s.backgroundColorSubtle_onHover, _s.borderColorSecondary, _s.border1PX, _s.radiusSmall].join(' ')}
className={[_s.default, _s.cursorPointer, _s.flexRow, _s.overflowHidden, _s.noUnderline, _s.width100PC, _s.bgSubtle_onHover, _s.borderColorSecondary, _s.border1PX, _s.radiusSmall].join(' ')}
rel='noopener noreferrer'
ref={this.setRef}
>

View File

@@ -85,7 +85,7 @@ class StatusContent extends ImmutablePureComponent {
if (descendent.classList.contains('invisible')) {
descendent.classList.remove('invisible')
descendent.classList.add(_s.fontSize0, _s.text, _s.inherit)
descendent.classList.add(_s.fs0, _s.text, _s.inherit)
}
if (descendent.classList.contains('ellipsis')) {
descendent.classList.remove('ellipsis')
@@ -254,7 +254,7 @@ class StatusContent extends ImmutablePureComponent {
<div className={spoilerContainerClasses}>
<div className={[_s.default, _s.flexRow, _s.mr5].join(' ')}>
<Icon id='warning' size='14px' className={[_s.fillColorPrimary, _s.mt2, _s.mr5].join(' ')}/>
<Icon id='warning' size='14px' className={[_s.fillPrimary, _s.mt2, _s.mr5].join(' ')}/>
<div
className={_s.statusContent}
dangerouslySetInnerHTML={spoilerContent}

View File

@@ -104,7 +104,7 @@ class StatusHeader extends ImmutablePureComponent {
color='none'
icon='ellipsis'
iconSize='20px'
iconClassName={_s.fillColorSecondary}
iconClassName={_s.fillSecondary}
className={_s.mlAuto}
onClick={this.handleOpenStatusOptionsPopover}
buttonRef={this.setStatusOptionsButton}
@@ -127,7 +127,7 @@ class StatusHeader extends ImmutablePureComponent {
<DotTextSeperator />
<Icon id={visibilityIcon} size='12px' className={[_s.default, _s.displayInline, _s.ml5, _s.fillColorSecondary].join(' ')} />
<Icon id={visibilityIcon} size='12px' className={[_s.default, _s.displayInline, _s.ml5, _s.fillSecondary].join(' ')} />
{
!!status.get('group') &&

View File

@@ -42,7 +42,7 @@ class StatusPrepend extends ImmutablePureComponent {
return (
<div className={[_s.default, _s.width100PC, _s.alignItemsStart, _s.borderBottom1PX, _s.borderColorSecondary].join(' ')}>
<div className={[_s.default, _s.width100PC, _s.flexRow, _s.alignItemsCenter, _s.py5, _s.px15].join(' ')}>
<Icon id={iconId} size='12px' className={[_s.fillColorSecondary, _s.mr5].join(' ')} />
<Icon id={iconId} size='12px' className={[_s.fillSecondary, _s.mr5].join(' ')} />
{
isRepost &&
<div className={[_s.default, _s.flexRow].join(' ')}>

View File

@@ -36,18 +36,18 @@ export default class Switch extends PureComponent {
border1PX: 1,
mlAuto: 1,
borderColorSecondary: 1,
backgroundColorBrand: checked,
bgBrand: checked,
})
const checkboxLabelClasses = cx({
default: 1,
margin1PX: 1,
m1PX: 1,
height20PX: 1,
width20PX: 1,
circle: 1,
posAbs: 1,
backgroundColorSubtle2: !checked,
backgroundColorPrimary: checked,
bgSecondary: !checked,
bgPrimary: checked,
left0: !checked,
right0: checked,
})

View File

@@ -26,7 +26,6 @@ export default class TabBar extends PureComponent {
key={`tab-bar-item-${i}`}
title={tab.title}
onClick={tab.onClick}
icon={tab.icon}
to={tab.to}
isActive={tab.active}
isLarge={isLarge}

View File

@@ -1,7 +1,6 @@
import { withRouter } from 'react-router-dom'
import classNames from 'classnames/bind'
import Button from './button'
import Icon from './icon'
import Text from './text'
// Bind CSS Modules global variable `_s` to classNames module
@@ -9,7 +8,6 @@ const cx = classNames.bind(_s)
/**
* Renders a tab bar item component
* @param {string} [props.icon] - icon to use
* @param {bool} [props.isLarge] - to style the tab bar larger
* @param {bool} [props.isActive] - if item is active
* @param {func} [props.onClick] - function to call on click
@@ -21,7 +19,6 @@ export default
class TabBarItem extends PureComponent {
static propTypes = {
icon: PropTypes.string,
isLarge: PropTypes.bool,
isActive: PropTypes.bool,
onClick: PropTypes.func,
@@ -52,7 +49,6 @@ class TabBarItem extends PureComponent {
onClick,
location,
isLarge,
icon,
isActive,
} = this.props
const { isCurrent } = this.state
@@ -74,7 +70,7 @@ class TabBarItem extends PureComponent {
py5: 1,
outlineNone: 1,
cursorPointer: 1,
backgroundTransparent: 1,
bgTransparent: 1,
borderColorTransparent: !active,
borderColorBrand: active,
mr5: isLarge,
@@ -89,7 +85,7 @@ class TabBarItem extends PureComponent {
radiusSmall: 1,
px10: !isLarge,
px15: isLarge,
backgroundColorSubtle2Dark_onHover: !active,
bgSecondaryDark_onHover: !active,
})
const textOptions = {
@@ -98,12 +94,6 @@ class TabBarItem extends PureComponent {
weight: active ? 'bold' : isLarge ? 'medium' : 'normal',
}
const iconOptions = {
id: icon,
width: !!isLarge ? 20 : 14,
height: !!isLarge ? 20 : 14,
}
return (
<Button
onClick={onClick}
@@ -112,17 +102,9 @@ class TabBarItem extends PureComponent {
noClasses
>
<span className={textParentClasses}>
{
!!title &&
<Text {...textOptions}>
{title}
</Text>
}
{
!!icon &&
<Icon {...iconOptions} />
}
<Text {...textOptions}>
{title}
</Text>
</span>
</Button>
)

View File

@@ -103,11 +103,11 @@ export default class Text extends PureComponent {
colorWhite: color === COLORS.white,
inherit: color === COLORS.inherit,
fontSize19PX: size === SIZES.large,
fontSize15PX: size === SIZES.medium,
fontSize14PX: size === SIZES.normal,
fontSize13PX: size === SIZES.small,
fontSize12PX: size === SIZES.extraSmall,
fs19PX: size === SIZES.large,
fs15PX: size === SIZES.medium,
fs14PX: size === SIZES.normal,
fs13PX: size === SIZES.small,
fs12PX: size === SIZES.extraSmall,
fontWeightNormal: weight === WEIGHTS.normal,
fontWeightMedium: weight === WEIGHTS.medium,

View File

@@ -8,7 +8,6 @@ export default class Textarea extends PureComponent {
placeholder: PropTypes.string,
prependIcon: PropTypes.string,
value: PropTypes.string,
hasClear: PropTypes.bool,
onChange: PropTypes.func,
onKeyUp: PropTypes.func,
onFocus: PropTypes.func,
@@ -25,7 +24,6 @@ export default class Textarea extends PureComponent {
placeholder,
prependIcon,
value,
hasClear,
onKeyUp,
onFocus,
onBlur,
@@ -39,14 +37,13 @@ export default class Textarea extends PureComponent {
lineHeight125: 1,
displayBlock: 1,
py10: 1,
backgroundTransparent: 1,
fontSize15PX: 1,
bgTransparent: 1,
fs15PX: 1,
flexGrow1: 1,
heightMax100VH: 1,
resizeVertical: 1,
px5: !!prependIcon,
pl15: !prependIcon,
pr15: !hasClear,
})
return (
@@ -59,7 +56,7 @@ export default class Textarea extends PureComponent {
</Text>
</div>
}
<div className={[_s.default, _s.backgroundColorPrimary, _s.border1PX, _s.borderColorSecondary, _s.flexRow, _s.radiusSmall, _s.alignItemsCenter].join(' ')}>
<div className={[_s.default, _s.bgPrimary, _s.border1PX, _s.borderColorSecondary, _s.flexRow, _s.radiusSmall, _s.alignItemsCenter].join(' ')}>
<textarea
className={inputClasses}
type='text'

View File

@@ -53,7 +53,7 @@ class TimelineComposeBlock extends ImmutablePureComponent {
return (
<section className={[_s.default, _s.mb15].join(' ')}>
<Block>
<div className={[_s.default, _s.backgroundColorSubtle, _s.borderTop1PX, _s.borderBottom1PX, _s.borderColorSecondary, _s.px15, _s.py2, _s.alignItemsCenter, _s.flexRow].join(' ')}>
<div className={[_s.default, _s.bgSubtle, _s.borderTop1PX, _s.borderBottom1PX, _s.borderColorSecondary, _s.px15, _s.py2, _s.alignItemsCenter, _s.flexRow].join(' ')}>
<div className={_s.mr10}>
<Avatar account={account} size={20} noHover />
</div>

View File

@@ -1,27 +1,24 @@
import { Fragment } from 'react'
import classNames from 'classnames/bind'
import ImmutablePureComponent from 'react-immutable-pure-component'
import ImmutablePropTypes from 'react-immutable-proptypes'
import { urlRegex } from '../features/ui/util/url_regex'
import {
CX,
DEFAULT_REL,
} from '../constants'
import Button from './button'
import DotTextSeperator from './dot_text_seperator'
import Image from './image'
import RelativeTimestamp from './relative_timestamp'
import Text from './text'
const cx = classNames.bind(_s)
export default class TrendingItem extends PureComponent {
export default class TrendingItem extends ImmutablePureComponent {
static propTypes = {
index: PropTypes.number,
url: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
description: PropTypes.string,
imageUrl: PropTypes.string,
author: PropTypes.string,
publishDate: PropTypes.string,
trend: ImmutablePropTypes.map.isRequired,
isLast: PropTypes.bool,
isHidden: PropTypes.bool,
wide: PropTypes.bool,
}
static defaultProps = {
@@ -45,19 +42,18 @@ export default class TrendingItem extends PureComponent {
render() {
const {
index,
url,
title,
description,
imageUrl,
author,
publishDate,
trend,
isLast,
wide,
isHidden,
} = this.props
const { hovering } = this.state
const correctedAuthor = author.replace('www.', '')
if (!trend) return null
const title = trend.get('title')
const description = trend.get('description')
const correctedAuthor = trend.getIn(['author', 'name'], '').replace('www.', '')
const correctedDescription = description.length >= 120 ? `${description.substring(0, 120).trim()}...` : description
const descriptionHasLink = correctedDescription.match(urlRegex)
@@ -71,7 +67,7 @@ export default class TrendingItem extends PureComponent {
)
}
const containerClasses = cx({
const containerClasses = CX({
default: 1,
noUnderline: 1,
px15: 1,
@@ -82,35 +78,29 @@ export default class TrendingItem extends PureComponent {
backgroundColorSubtle_onHover: 1,
})
const subtitleClasses = cx({
const subtitleClasses = CX({
ml5: 1,
underline: hovering,
})
const image = (
<Image
nullable
width='116px'
height='78px'
alt={title}
src={imageUrl}
className={[_s.radiusSmall, _s.overflowHidden, _s.mb10].join(' ')}
/>
)
return (
<Button
noClasses
href={url}
href={trend.get('url')}
target='_blank'
rel='noopener noreferrer'
rel={DEFAULT_REL}
className={containerClasses}
onMouseEnter={() => this.handleOnMouseEnter()}
onMouseLeave={() => this.handleOnMouseLeave()}
>
{
!wide && image
}
<Image
nullable
width='116px'
height='78px'
alt={title}
src={trend.get('image')}
className={[_s.radiusSmall, _s.overflowHidden, _s.mb10].join(' ')}
/>
<div className={[_s.default, _s.flexNormal, _s.pb5].join(' ')}>
<div className={_s.default}>
@@ -127,6 +117,7 @@ export default class TrendingItem extends PureComponent {
</Text>
</div>
}
<div className={[_s.default, _s.flexRow].join(' ')}>
<Text color='secondary' size='small'>
{index}
@@ -137,13 +128,14 @@ export default class TrendingItem extends PureComponent {
</Text>
<DotTextSeperator />
<Text color='secondary' size='small' className={subtitleClasses}>
<RelativeTimestamp timestamp={publishDate} />
<RelativeTimestamp timestamp={trend.get('date_published')} />
</Text>
{
hovering &&
<Text color='secondary' size='small' className={_s.ml10}></Text>
}
</div>
</div>
</Button>
)

View File

@@ -54,7 +54,7 @@ class UploadArea extends PureComponent {
>
{({ backgroundOpacity, backgroundScale }) => (
<div
className={[_s.default, _s.alignItemsCenter, _s.justifyContentCenter, _s.backgroundColorPrimaryOpaque, _s.width100PC, _s.height100PC, _s.posAbs, _s.top0, _s.rightAuto, _s.bottomAuto, _s.left0].join(' ')}
className={[_s.default, _s.alignItemsCenter, _s.justifyContentCenter, _s.bgPrimaryOpaque, _s.width100PC, _s.height100PC, _s.posAbs, _s.top0, _s.rightAuto, _s.bottomAuto, _s.left0].join(' ')}
style={{
visibility: active ? 'visible' : 'hidden',
opacity: backgroundOpacity
@@ -62,7 +62,7 @@ class UploadArea extends PureComponent {
>
<div className={[_s.default, _s.width340PX, _s.height260PX, _s.px10, _s.py10].join(' ')}>
<div
className={[_s.default, _s.posAbs, _s.backgroundColorPrimary, _s.height100PC, _s.width100PC, _s.radiusSmall].join(' ')}
className={[_s.default, _s.posAbs, _s.bgPrimary, _s.height100PC, _s.width100PC, _s.radiusSmall].join(' ')}
style={{
transform: `scale(${backgroundScale})`
}}

View File

@@ -460,7 +460,7 @@ class Video extends PureComponent {
circle: 1,
px10: 1,
py10: 1,
backgroundColorBrand: 1,
bgBrand: 1,
mlNeg5PX: 1,
z3: 1,
boxShadow1: 1,
@@ -479,7 +479,7 @@ class Video extends PureComponent {
const volumeControlClasses = cx({
default: 1,
posAbs: 1,
backgroundColorBlackOpaque: 1,
bgBlackOpaque: 1,
videoPlayerVolume: 1,
height122PX: 1,
circle: 1,
@@ -550,19 +550,19 @@ class Video extends PureComponent {
ref={this.setVolumeRef}
>
<div
className={[_s.default, _s.radiusSmall, _s.my10, _s.posAbs, _s.width4PX, _s.ml10, _s.backgroundColorPrimaryOpaque].join(' ')}
className={[_s.default, _s.radiusSmall, _s.my10, _s.posAbs, _s.width4PX, _s.ml10, _s.bgPrimaryOpaque].join(' ')}
style={{
height: '102px',
}}
/>
<div
className={[_s.default, _s.radiusSmall, _s.my10, _s.bottom0, _s.posAbs, _s.width4PX, _s.ml10, _s.backgroundColorPrimary].join(' ')}
className={[_s.default, _s.radiusSmall, _s.my10, _s.bottom0, _s.posAbs, _s.width4PX, _s.ml10, _s.bgPrimary].join(' ')}
style={{
height: `${volumeHeight}px`
}}
/>
<span
className={[_s.default, _s.cursorPointer, _s.posAbs, _s.circle, _s.px5, _s.boxShadow1, _s.mbNeg5PX, _s.py5, _s.backgroundColorPrimary, _s.z3].join(' ')}
className={[_s.default, _s.cursorPointer, _s.posAbs, _s.circle, _s.px5, _s.boxShadow1, _s.mbNeg5PX, _s.py5, _s.bgPrimary, _s.z3].join(' ')}
tabIndex='0'
style={{
marginLeft: '7px',
@@ -579,9 +579,9 @@ class Video extends PureComponent {
ref={this.setSeekRef}
>
<div className={[progressClasses, _s.backgroundColorLoading, _s.width100PC].join(' ')} />
<div className={[progressClasses, _s.backgroundColorSubtle].join(' ')} style={{ width: `${buffer}%` }} />
<div className={[progressClasses, _s.backgroundColorBrand].join(' ')} style={{ width: `${progress}%` }} />
<div className={[progressClasses, _s.bgLoading, _s.width100PC].join(' ')} />
<div className={[progressClasses, _s.bgSubtle].join(' ')} style={{ width: `${buffer}%` }} />
<div className={[progressClasses, _s.bgBrand].join(' ')} style={{ width: `${progress}%` }} />
<span
className={seekHandleClasses}
@@ -600,7 +600,7 @@ class Video extends PureComponent {
onClick={this.togglePlay}
icon={paused ? 'play' : 'pause'}
iconSize='16px'
iconClassName={_s.fillColorWhite}
iconClassName={_s.fillWhite}
className={_s.pl0}
/>
@@ -619,7 +619,7 @@ class Video extends PureComponent {
onClick={this.toggleMute}
icon={muted ? 'audio-mute' : 'audio'}
iconSize='24px'
iconClassName={_s.fillColorWhite}
iconClassName={_s.fillWhite}
className={[_s.px10, _s.ml10].join(' ')}
onMouseEnter={this.handleMouseEnterAudio}
onMouseLeave={this.handleMouseLeaveAudio}
@@ -632,7 +632,7 @@ class Video extends PureComponent {
onClick={this.toggleFullscreen}
icon={fullscreen ? 'minimize-fullscreen' : 'fullscreen'}
iconSize='20px'
iconClassName={_s.fillColorWhite}
iconClassName={_s.fillWhite}
className={[_s.px10, _s.pr0].join(' ')}
/>
</div>