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

@ -41,14 +41,20 @@ export function submitSearch() {
}).then(response => { }).then(response => {
if (response.data.accounts) { if (response.data.accounts) {
dispatch(importFetchedAccounts(response.data.accounts)); dispatch(importFetchedAccounts(response.data.accounts));
dispatch(fetchRelationships(response.data.accounts.map(item => item.id)));
} }
if (response.data.statuses) { if (response.data.statuses) {
dispatch(importFetchedStatuses(response.data.statuses)); dispatch(importFetchedStatuses(response.data.statuses));
} }
console.log("response.data.", response.data)
// if (response.data.groups) {
// dispatch(importFetchedStatuses(response.data.statuses));
// }
dispatch(fetchSearchSuccess(response.data)); dispatch(fetchSearchSuccess(response.data));
dispatch(fetchRelationships(response.data.accounts.map(item => item.id)));
}).catch(error => { }).catch(error => {
dispatch(fetchSearchFail(error)); dispatch(fetchSearchFail(error));
}); });

View File

@ -1,5 +1,5 @@
const ErrorIcon = ({ const ErrorIcon = ({
className = _s.fillColorPrimary, className = _s.fillPrimary,
size = '32px', size = '32px',
title = 'Error', title = 'Error',
}) => ( }) => (

View File

@ -0,0 +1,39 @@
const ExploreIcon = ({
className = '',
size = '12px',
title = 'Explore',
}) => (
<svg
className={className}
version='1.1'
xmlns='http://www.w3.org/2000/svg'
x='0px'
y='0px'
width={size}
height={size}
viewBox='0 0 24 24'
xmlSpace='preserve'
aria-label={title}
>
<g>
<path d='M 11.296875 23.875 L 11.296875 18.773438 C 10.019531 18.824219 8.753906 19.003906 7.550781 19.300781 C 7.742188 19.769531 7.957031 20.21875 8.183594 20.640625 C 9.101562 22.332031 10.242188 23.5 11.296875 23.875 Z M 11.296875 23.875' />
<path d='M 15.8125 20.640625 C 16.042969 20.21875 16.257812 19.769531 16.449219 19.300781 C 15.246094 19.003906 13.980469 18.824219 12.703125 18.773438 L 12.703125 23.875 C 13.757812 23.5 14.898438 22.332031 15.8125 20.640625 Z M 15.8125 20.640625' />
<path d='M 11.296875 17.367188 L 11.296875 12.6875 L 6.167969 12.6875 C 6.234375 14.515625 6.546875 16.332031 7.066406 17.976562 C 8.425781 17.625 9.855469 17.417969 11.296875 17.367188 Z M 11.296875 17.367188' />
<path d='M 11.296875 11.28125 L 11.296875 6.601562 C 9.855469 6.550781 8.425781 6.34375 7.066406 5.996094 C 6.546875 7.640625 6.234375 9.457031 6.167969 11.28125 Z M 11.296875 11.28125' />
<path d='M 17.808594 4.273438 C 18.664062 3.984375 19.476562 3.632812 20.222656 3.222656 C 18.914062 1.996094 17.328125 1.054688 15.574219 0.507812 C 16.097656 1.101562 16.597656 1.820312 17.050781 2.65625 C 17.328125 3.167969 17.582031 3.710938 17.808594 4.273438 Z M 17.808594 4.273438' />
<path d='M 8.1875 3.328125 C 7.957031 3.75 7.742188 4.199219 7.550781 4.667969 C 8.753906 4.96875 10.019531 5.148438 11.296875 5.195312 L 11.296875 0.09375 C 10.242188 0.46875 9.101562 1.636719 8.1875 3.328125 Z M 8.1875 3.328125' />
<path d='M 12.703125 12.6875 L 12.703125 17.367188 C 14.144531 17.417969 15.574219 17.625 16.933594 17.976562 C 17.453125 16.332031 17.765625 14.515625 17.832031 12.6875 Z M 12.703125 12.6875' />
<path d='M 12.703125 6.601562 L 12.703125 11.28125 L 17.832031 11.28125 C 17.765625 9.457031 17.453125 7.640625 16.933594 5.996094 C 15.574219 6.34375 14.144531 6.550781 12.703125 6.601562 Z M 12.703125 6.601562' />
<path d='M 5.714844 18.375 C 5.152344 16.605469 4.824219 14.667969 4.761719 12.6875 L 0 12.6875 C 0.152344 15.34375 1.175781 17.773438 2.78125 19.691406 C 3.679688 19.171875 4.667969 18.730469 5.714844 18.375 Z M 5.714844 18.375' />
<path d='M 17.808594 19.699219 C 17.582031 20.261719 17.328125 20.800781 17.050781 21.3125 C 16.597656 22.148438 16.097656 22.871094 15.574219 23.464844 C 17.328125 22.914062 18.914062 21.976562 20.222656 20.746094 C 19.476562 20.335938 18.664062 19.988281 17.808594 19.699219 Z M 17.808594 19.699219' />
<path d='M 6.191406 19.699219 C 5.335938 19.988281 4.523438 20.335938 3.777344 20.746094 C 5.085938 21.976562 6.671875 22.914062 8.425781 23.464844 C 7.902344 22.871094 7.402344 22.148438 6.949219 21.3125 C 6.671875 20.800781 6.417969 20.261719 6.191406 19.699219 Z M 6.191406 19.699219' />
<path d='M 18.285156 5.59375 C 18.847656 7.363281 19.175781 9.300781 19.238281 11.28125 L 24 11.28125 C 23.847656 8.625 22.824219 6.199219 21.21875 4.277344 C 20.320312 4.796875 19.332031 5.238281 18.285156 5.59375 Z M 18.285156 5.59375' />
<path d='M 18.285156 18.375 C 19.332031 18.730469 20.320312 19.171875 21.21875 19.691406 C 22.824219 17.773438 23.847656 15.34375 24 12.6875 L 19.238281 12.6875 C 19.175781 14.667969 18.847656 16.605469 18.285156 18.375 Z M 18.285156 18.375' />
<path d='M 12.703125 0.09375 L 12.703125 5.195312 C 13.980469 5.148438 15.246094 4.96875 16.449219 4.667969 C 16.257812 4.199219 16.042969 3.75 15.8125 3.328125 C 14.898438 1.636719 13.757812 0.46875 12.703125 0.09375 Z M 12.703125 0.09375' />
<path d='M 5.714844 5.59375 C 4.667969 5.238281 3.679688 4.796875 2.78125 4.277344 C 1.175781 6.199219 0.152344 8.625 0 11.28125 L 4.761719 11.28125 C 4.824219 9.300781 5.152344 7.363281 5.714844 5.59375 Z M 5.714844 5.59375' />
<path d='M 6.191406 4.273438 C 6.417969 3.710938 6.671875 3.167969 6.949219 2.65625 C 7.402344 1.820312 7.902344 1.101562 8.425781 0.507812 C 6.671875 1.054688 5.085938 1.996094 3.777344 3.222656 C 4.523438 3.632812 5.335938 3.984375 6.191406 4.273438 Z M 6.191406 4.273438' />
</g>
</svg>
)
export default ExploreIcon

View File

@ -1,6 +1,5 @@
const GabLogo = ({ const GabLogo = ({
className = _s.fillColorBrand, className = _s.fillBrand,
size = '50px',
}) => ( }) => (
<svg <svg
className={className} className={className}
@ -8,8 +7,8 @@ const GabLogo = ({
xmlns='http://www.w3.org/2000/svg' xmlns='http://www.w3.org/2000/svg'
x='0px' x='0px'
y='0px' y='0px'
width={size} width='50px'
height={size} height='30px'
viewBox='0 0 50 30' viewBox='0 0 50 30'
xmlSpace='preserve' xmlSpace='preserve'
> >

View File

@ -1,4 +1,3 @@
// : todo : fill, stroke colors
const GlobeIcon = ({ const GlobeIcon = ({
className = '', className = '',
size = '12px', size = '12px',

View File

@ -13,7 +13,7 @@ const LoadingIcon = ({
> >
<g transform='translate(82,50)'> <g transform='translate(82,50)'>
<g transform='rotate(0)'> <g transform='rotate(0)'>
<circle cx='0' cy='0' r='6' className={_s.fillColorSecondary} fillOpacity='1' transform='scale(1.03405 1.03405)'> <circle cx='0' cy='0' r='6' className={_s.fillSecondary} fillOpacity='1' transform='scale(1.03405 1.03405)'>
<animateTransform attributeName='transform' type='scale' begin='-1.0294117647058822s' values='1.5 1.5;1 1' keyTimes='0;1' dur='1.176470588235294s' repeatCount='indefinite'></animateTransform> <animateTransform attributeName='transform' type='scale' begin='-1.0294117647058822s' values='1.5 1.5;1 1' keyTimes='0;1' dur='1.176470588235294s' repeatCount='indefinite'></animateTransform>
<animate attributeName='fill-opacity' keyTimes='0;1' dur='1.176470588235294s' repeatCount='indefinite' values='1;0' begin='-1.0294117647058822s'></animate> <animate attributeName='fill-opacity' keyTimes='0;1' dur='1.176470588235294s' repeatCount='indefinite' values='1;0' begin='-1.0294117647058822s'></animate>
</circle> </circle>
@ -21,7 +21,7 @@ const LoadingIcon = ({
</g> </g>
<g transform='translate(72.62741699796952,72.62741699796952)'> <g transform='translate(72.62741699796952,72.62741699796952)'>
<g transform='rotate(45)'> <g transform='rotate(45)'>
<circle cx='0' cy='0' r='6' className={_s.fillColorSecondary} fillOpacity='0.875' transform='scale(1.09655 1.09655)'> <circle cx='0' cy='0' r='6' className={_s.fillSecondary} fillOpacity='0.875' transform='scale(1.09655 1.09655)'>
<animateTransform attributeName='transform' type='scale' begin='-0.8823529411764705s' values='1.5 1.5;1 1' keyTimes='0;1' dur='1.176470588235294s' repeatCount='indefinite'></animateTransform> <animateTransform attributeName='transform' type='scale' begin='-0.8823529411764705s' values='1.5 1.5;1 1' keyTimes='0;1' dur='1.176470588235294s' repeatCount='indefinite'></animateTransform>
<animate attributeName='fill-opacity' keyTimes='0;1' dur='1.176470588235294s' repeatCount='indefinite' values='1;0' begin='-0.8823529411764705s'></animate> <animate attributeName='fill-opacity' keyTimes='0;1' dur='1.176470588235294s' repeatCount='indefinite' values='1;0' begin='-0.8823529411764705s'></animate>
</circle> </circle>
@ -29,7 +29,7 @@ const LoadingIcon = ({
</g> </g>
<g transform='translate(50,82)'> <g transform='translate(50,82)'>
<g transform='rotate(90)'> <g transform='rotate(90)'>
<circle cx='0' cy='0' r='6' className={_s.fillColorSecondary} fillOpacity='0.75' transform='scale(1.15905 1.15905)'> <circle cx='0' cy='0' r='6' className={_s.fillSecondary} fillOpacity='0.75' transform='scale(1.15905 1.15905)'>
<animateTransform attributeName='transform' type='scale' begin='-0.7352941176470588s' values='1.5 1.5;1 1' keyTimes='0;1' dur='1.176470588235294s' repeatCount='indefinite'></animateTransform> <animateTransform attributeName='transform' type='scale' begin='-0.7352941176470588s' values='1.5 1.5;1 1' keyTimes='0;1' dur='1.176470588235294s' repeatCount='indefinite'></animateTransform>
<animate attributeName='fill-opacity' keyTimes='0;1' dur='1.176470588235294s' repeatCount='indefinite' values='1;0' begin='-0.7352941176470588s'></animate> <animate attributeName='fill-opacity' keyTimes='0;1' dur='1.176470588235294s' repeatCount='indefinite' values='1;0' begin='-0.7352941176470588s'></animate>
</circle> </circle>
@ -37,7 +37,7 @@ const LoadingIcon = ({
</g> </g>
<g transform='translate(27.37258300203048,72.62741699796952)'> <g transform='translate(27.37258300203048,72.62741699796952)'>
<g transform='rotate(135)'> <g transform='rotate(135)'>
<circle cx='0' cy='0' r='6' className={_s.fillColorSecondary} fillOpacity='0.625' transform='scale(1.22155 1.22155)'> <circle cx='0' cy='0' r='6' className={_s.fillSecondary} fillOpacity='0.625' transform='scale(1.22155 1.22155)'>
<animateTransform attributeName='transform' type='scale' begin='-0.588235294117647s' values='1.5 1.5;1 1' keyTimes='0;1' dur='1.176470588235294s' repeatCount='indefinite'></animateTransform> <animateTransform attributeName='transform' type='scale' begin='-0.588235294117647s' values='1.5 1.5;1 1' keyTimes='0;1' dur='1.176470588235294s' repeatCount='indefinite'></animateTransform>
<animate attributeName='fill-opacity' keyTimes='0;1' dur='1.176470588235294s' repeatCount='indefinite' values='1;0' begin='-0.588235294117647s'></animate> <animate attributeName='fill-opacity' keyTimes='0;1' dur='1.176470588235294s' repeatCount='indefinite' values='1;0' begin='-0.588235294117647s'></animate>
</circle> </circle>
@ -45,7 +45,7 @@ const LoadingIcon = ({
</g> </g>
<g transform='translate(18,50)'> <g transform='translate(18,50)'>
<g transform='rotate(180)'> <g transform='rotate(180)'>
<circle cx='0' cy='0' r='6' className={_s.fillColorSecondary} fillOpacity='0.5' transform='scale(1.28405 1.28405)'> <circle cx='0' cy='0' r='6' className={_s.fillSecondary} fillOpacity='0.5' transform='scale(1.28405 1.28405)'>
<animateTransform attributeName='transform' type='scale' begin='-0.4411764705882352s' values='1.5 1.5;1 1' keyTimes='0;1' dur='1.176470588235294s' repeatCount='indefinite'></animateTransform> <animateTransform attributeName='transform' type='scale' begin='-0.4411764705882352s' values='1.5 1.5;1 1' keyTimes='0;1' dur='1.176470588235294s' repeatCount='indefinite'></animateTransform>
<animate attributeName='fill-opacity' keyTimes='0;1' dur='1.176470588235294s' repeatCount='indefinite' values='1;0' begin='-0.4411764705882352s'></animate> <animate attributeName='fill-opacity' keyTimes='0;1' dur='1.176470588235294s' repeatCount='indefinite' values='1;0' begin='-0.4411764705882352s'></animate>
</circle> </circle>
@ -53,7 +53,7 @@ const LoadingIcon = ({
</g> </g>
<g transform='translate(27.372583002030474,27.37258300203048)'> <g transform='translate(27.372583002030474,27.37258300203048)'>
<g transform='rotate(225)'> <g transform='rotate(225)'>
<circle cx='0' cy='0' r='6' className={_s.fillColorSecondary} fillOpacity='0.375' transform='scale(1.34655 1.34655)'> <circle cx='0' cy='0' r='6' className={_s.fillSecondary} fillOpacity='0.375' transform='scale(1.34655 1.34655)'>
<animateTransform attributeName='transform' type='scale' begin='-0.2941176470588235s' values='1.5 1.5;1 1' keyTimes='0;1' dur='1.176470588235294s' repeatCount='indefinite'></animateTransform> <animateTransform attributeName='transform' type='scale' begin='-0.2941176470588235s' values='1.5 1.5;1 1' keyTimes='0;1' dur='1.176470588235294s' repeatCount='indefinite'></animateTransform>
<animate attributeName='fill-opacity' keyTimes='0;1' dur='1.176470588235294s' repeatCount='indefinite' values='1;0' begin='-0.2941176470588235s'></animate> <animate attributeName='fill-opacity' keyTimes='0;1' dur='1.176470588235294s' repeatCount='indefinite' values='1;0' begin='-0.2941176470588235s'></animate>
</circle> </circle>
@ -61,7 +61,7 @@ const LoadingIcon = ({
</g> </g>
<g transform='translate(50,18)'> <g transform='translate(50,18)'>
<g transform='rotate(270)'> <g transform='rotate(270)'>
<circle cx='0' cy='0' r='6' className={_s.fillColorSecondary} fillOpacity='0.25' transform='scale(1.40905 1.40905)'> <circle cx='0' cy='0' r='6' className={_s.fillSecondary} fillOpacity='0.25' transform='scale(1.40905 1.40905)'>
<animateTransform attributeName='transform' type='scale' begin='-0.14705882352941174s' values='1.5 1.5;1 1' keyTimes='0;1' dur='1.176470588235294s' repeatCount='indefinite'></animateTransform> <animateTransform attributeName='transform' type='scale' begin='-0.14705882352941174s' values='1.5 1.5;1 1' keyTimes='0;1' dur='1.176470588235294s' repeatCount='indefinite'></animateTransform>
<animate attributeName='fill-opacity' keyTimes='0;1' dur='1.176470588235294s' repeatCount='indefinite' values='1;0' begin='-0.14705882352941174s'></animate> <animate attributeName='fill-opacity' keyTimes='0;1' dur='1.176470588235294s' repeatCount='indefinite' values='1;0' begin='-0.14705882352941174s'></animate>
</circle> </circle>
@ -69,7 +69,7 @@ const LoadingIcon = ({
</g> </g>
<g transform='translate(72.62741699796952,27.372583002030474)'> <g transform='translate(72.62741699796952,27.372583002030474)'>
<g transform='rotate(315)'> <g transform='rotate(315)'>
<circle cx='0' cy='0' r='6' className={_s.fillColorSecondary} fillOpacity='0.125' transform='scale(1.47155 1.47155)'> <circle cx='0' cy='0' r='6' className={_s.fillSecondary} fillOpacity='0.125' transform='scale(1.47155 1.47155)'>
<animateTransform attributeName='transform' type='scale' begin='0s' values='1.5 1.5;1 1' keyTimes='0;1' dur='1.176470588235294s' repeatCount='indefinite'></animateTransform> <animateTransform attributeName='transform' type='scale' begin='0s' values='1.5 1.5;1 1' keyTimes='0;1' dur='1.176470588235294s' repeatCount='indefinite'></animateTransform>
<animate attributeName='fill-opacity' keyTimes='0;1' dur='1.176470588235294s' repeatCount='indefinite' values='1;0' begin='0s'></animate> <animate attributeName='fill-opacity' keyTimes='0;1' dur='1.176470588235294s' repeatCount='indefinite' values='1;0' begin='0s'></animate>
</circle> </circle>

View File

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

View File

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

View File

@ -11,7 +11,7 @@ export default class Block extends PureComponent {
const { children } = this.props const { children } = this.props
return ( 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} {children}
</div> </div>
) )

View File

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

View File

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

View File

@ -61,7 +61,7 @@ class Comment extends ImmutablePureComponent {
</NavLink> </NavLink>
<div className={[_s.default, _s.flexNormal].join(' ')}> <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} /> <CommentHeader status={status} />
<StatusContent <StatusContent
status={status} status={status}
@ -103,7 +103,7 @@ class CommentButton extends PureComponent {
radiusSmall radiusSmall
backgroundColor='none' backgroundColor='none'
color='tertiary' 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} onClick={onClick}
> >
<Text size='extraSmall' color='inherit' weight='bold'> <Text size='extraSmall' color='inherit' weight='bold'>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -42,11 +42,11 @@ export default class Heading extends PureComponent {
colorPrimary: [SIZES.h1, SIZES.h2].indexOf(size) > -1, colorPrimary: [SIZES.h1, SIZES.h2].indexOf(size) > -1,
colorSecondary: [SIZES.h3, SIZES.h4, SIZES.h5].indexOf(size) > -1, colorSecondary: [SIZES.h3, SIZES.h4, SIZES.h5].indexOf(size) > -1,
fontSize24PX: size === SIZES.h1, fs24PX: size === SIZES.h1,
fontSize19PX: size === SIZES.h2, fs19PX: size === SIZES.h2,
fontSize16PX: size === SIZES.h3, fs16PX: size === SIZES.h3,
fontSize13PX: size === SIZES.h4, fs13PX: size === SIZES.h4,
fontSize12PX: size === SIZES.h5, fs12PX: size === SIZES.h5,
mt5: [SIZES.h4].indexOf(size) > -1, 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 EllipsisIcon from '../assets/ellipsis_icon'
import EmailIcon from '../assets/email_icon' import EmailIcon from '../assets/email_icon'
import ErrorIcon from '../assets/error_icon' import ErrorIcon from '../assets/error_icon'
import ExploreIcon from '../assets/explore_icon'
import FullscreenIcon from '../assets/fullscreen_icon' import FullscreenIcon from '../assets/fullscreen_icon'
import GabLogoIcon from '../assets/gab_logo' import GabLogoIcon from '../assets/gab_logo'
import GifIcon from '../assets/gif_icon' import GifIcon from '../assets/gif_icon'
@ -89,6 +90,7 @@ const ICONS = {
'ellipsis': EllipsisIcon, 'ellipsis': EllipsisIcon,
'email': EmailIcon, 'email': EmailIcon,
'error': ErrorIcon, 'error': ErrorIcon,
'explore': ExploreIcon,
'fullscreen': FullscreenIcon, 'fullscreen': FullscreenIcon,
'gab-logo': GabLogoIcon, 'gab-logo': GabLogoIcon,
'gif': GifIcon, 'gif': GifIcon,

View File

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

View File

@ -58,12 +58,12 @@ export default class Input extends PureComponent {
displayBlock: 1, displayBlock: 1,
py10: !small, py10: !small,
py5: small, py5: small,
backgroundTransparent: !readOnly, bgTransparent: !readOnly,
backgroundColorSubtle2: readOnly, bgSecondary: readOnly,
colorPrimary: !readOnly, colorPrimary: !readOnly,
colorSecondary: readOnly, colorSecondary: readOnly,
fontSize15PX: !small, fs15PX: !small,
fontSize13PX: small, fs13PX: small,
flexGrow1: 1, flexGrow1: 1,
circle: 1, circle: 1,
px5: !!prependIcon, px5: !!prependIcon,
@ -87,10 +87,10 @@ export default class Input extends PureComponent {
</Text> </Text>
</div> </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 && !!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

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

View File

@ -216,7 +216,7 @@ class Item extends ImmutablePureComponent {
playsInline 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> <Text size='extraSmall' color='white' weight='medium'>GIF</Text>
</div> </div>
</div> </div>
@ -574,7 +574,7 @@ class MediaGallery extends PureComponent {
title={intl.formatMessage(messages.toggle_visible)} title={intl.formatMessage(messages.toggle_visible)}
icon='hidden' icon='hidden'
backgroundColor='none' backgroundColor='none'
className={[_s.px10, _s.backgroundColorBlackOpaque_onHover].join(' ')} className={[_s.px10, _s.bgBlackOpaque_onHover].join(' ')}
onClick={this.handleOpen} onClick={this.handleOpen}
/> />
</div> </div>

View File

@ -137,13 +137,13 @@ export default class MediaItem extends ImmutablePureComponent {
<Icon <Icon
id='hidden' id='hidden'
size='22px' size='22px'
className={[_s.fillColorWhite].join('')} className={[_s.fillWhite].join('')}
/> />
} }
{ {
!!badge && !!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'> <Text size='extraSmall' color='white'>
{badge} {badge}
</Text> </Text>

View File

@ -89,7 +89,7 @@ class EmbedModal extends ImmutablePureComponent {
{intl.formatMessage(messages.preview)} {intl.formatMessage(messages.preview)}
</Text> </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 <iframe
className={[_s.default, _s.width100PC, _s.height100PC, _s.z2].join(' ')} className={[_s.default, _s.width100PC, _s.height100PC, _s.z2].join(' ')}
frameBorder='0' frameBorder='0'

View File

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

View File

@ -137,7 +137,7 @@ class ModalBase extends PureComponent {
<Fragment> <Fragment>
<div <div
role='presentation' 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 <div
ref={this.setDialog} ref={this.setDialog}

View File

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

View File

@ -5,8 +5,9 @@ import { BREAKPOINT_EXTRA_SMALL } from '../constants'
import { me } from '../initial_state' import { me } from '../initial_state'
import { makeGetAccount } from '../selectors' import { makeGetAccount } from '../selectors'
import Responsive from '../features/ui/util/responsive_component' import Responsive from '../features/ui/util/responsive_component'
import ColumnHeader from './column_header' import { CX } from '../constants'
import Search from './search' import Search from './search'
import Avatar from './avatar'
import Icon from './icon' import Icon from './icon'
const mapStateToProps = (state) => ({ const mapStateToProps = (state) => ({
@ -25,6 +26,10 @@ class NavigationBar extends ImmutablePureComponent {
showBackBtn: PropTypes.bool, showBackBtn: PropTypes.bool,
} }
handleProfileClick = () => {
}
render() { render() {
const { const {
title, title,
@ -34,40 +39,118 @@ class NavigationBar extends ImmutablePureComponent {
account, account,
} = this.props } = this.props
const isPro = account.get('is_pro')
return ( 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.z4, _s.height53PX, _s.width100PC].join(' ')}>
<div className={[_s.default, _s.flexGrow1, _s.z3, _s.alignItemsEnd].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.width240PX].join(' ')}>
<div className={[_s.default, _s.height100PC, _s.alignItemsStart, _s.width240PX].join(' ')}> <div className={[_s.default, _s.flexRow, _s.width1255PX].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(' ')}> <div className={[_s.default, _s.flexRow].join(' ')}>
<Icon id='gab-logo' />
<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> </NavLink>
</h1> </h1>
</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}> <Responsive min={BREAKPOINT_EXTRA_SMALL}>
<div className={[_s.default, _s.width340PX].join(' ')}> <div className={[_s.default, _s.width340PX].join(' ')}>
<Search /> <Search />
</div> </div>
</Responsive> </Responsive>
</div> </div>
<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>
</div>
</div>
</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 ( 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.borderBottom1PX, _s.borderColorSecondary].join(' ')}>
<div className={[_s.default, _s.flexRow, _s.my10, _s.py10, _s.px10].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.ml15, _s.flexNormal].join(' ')}>
<div className={[_s.default, _s.flexRow].join(' ')}> <div className={[_s.default, _s.flexRow].join(' ')}>

View File

@ -69,7 +69,7 @@ class GroupInfoPanel extends ImmutablePureComponent {
<Divider isSmall /> <Divider isSmall />
<div className={[_s.default, _s.flexRow, _s.alignItemsCenter].join(' ')}> <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 <Text
size='small' size='small'
color='secondary' color='secondary'

View File

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

View File

@ -49,7 +49,7 @@ class ListDetailsPanel extends ImmutablePureComponent {
<Divider isSmall /> <Divider isSmall />
<div className={[_s.default, _s.flexRow, _s.alignItemsCenter].join(' ')}> <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 <Text
size='small' size='small'
color='secondary' color='secondary'

View File

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

View File

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

View File

@ -87,7 +87,7 @@ export default class PanelLayout extends PureComponent {
backgroundColor='none' backgroundColor='none'
to={footerButtonTo} to={footerButtonTo}
onClick={footerButtonAction} 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'> <Text color='brand' size='medium'>
{footerButtonTitle} {footerButtonTitle}

View File

@ -71,7 +71,7 @@ class ProfileInfoPanel extends ImmutablePureComponent {
} }
<div className={[_s.default, _s.flexRow, _s.alignItemsCenter].join(' ')}> <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 <Text
size='small' size='small'
color='secondary' 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 PanelLayout from './panel_layout';
import ProgressBar from '../progress_bar' 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() { render() {
if (!monthlyExpensesComplete || !me) return null const { intl } = this.props
if (!monthlyExpensesComplete) return null
const value = Math.min(parseFloat(monthlyExpensesComplete), 100)
return ( return (
<PanelLayout <PanelLayout
title="Gab's Operational Expenses" title={intl.formatMessage(messages.operationsTitle)}
subtitle="We are 100% funded by you" subtitle={intl.formatMessage(messages.operationsSubtitle)}
hasBackground
> >
<ProgressBar <ProgressBar
progress={monthlyExpensesComplete} progress={monthlyExpensesComplete}
title={`${Math.min(parseFloat(monthlyExpensesComplete), 100)}% covered this month`} title={intl.formatMessage(messages.progressTitle, { value })}
href='https://shop.dissenter.com/category/donations' href={URL_DISSENTER_SHOP}
/> />
</PanelLayout> </PanelLayout>
) )
} }
} }

View File

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

View File

@ -2,19 +2,20 @@ import { NavLink } from 'react-router-dom'
import { injectIntl, defineMessages } from 'react-intl' import { injectIntl, defineMessages } from 'react-intl'
import ImmutablePropTypes from 'react-immutable-proptypes' import ImmutablePropTypes from 'react-immutable-proptypes'
import ImmutablePureComponent from 'react-immutable-pure-component' import ImmutablePureComponent from 'react-immutable-pure-component'
import classNames from 'classnames/bind'
import { me } from '../../initial_state' import { me } from '../../initial_state'
import { makeGetAccount } from '../../selectors' import { makeGetAccount } from '../../selectors'
import { shortNumberFormat } from '../../utils/numbers' import { shortNumberFormat } from '../../utils/numbers'
import { openModal } from '../../actions/modal' 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 Button from '../button'
import DisplayName from '../display_name' import DisplayName from '../display_name'
import Avatar from '../avatar'
import Image from '../image' import Image from '../image'
import UserStat from '../user_stat' import UserStat from '../user_stat'
import PanelLayout from './panel_layout'
const cx = classNames.bind(_s)
const messages = defineMessages({ const messages = defineMessages({
gabs: { id: 'account.posts', defaultMessage: 'Gabs' }, gabs: { id: 'account.posts', defaultMessage: 'Gabs' },
@ -30,7 +31,7 @@ const mapStateToProps = (state) => ({
const mapDispatchToProps = (dispatch) => ({ const mapDispatchToProps = (dispatch) => ({
onOpenEditProfile() { onOpenEditProfile() {
dispatch(openModal('EDIT_PROFILE')) dispatch(openModal(MODAL_EDIT_PROFILE))
}, },
}) })
@ -38,6 +39,7 @@ export default
@connect(mapStateToProps, mapDispatchToProps) @connect(mapStateToProps, mapDispatchToProps)
@injectIntl @injectIntl
class UserPanel extends ImmutablePureComponent { class UserPanel extends ImmutablePureComponent {
static propTypes = { static propTypes = {
account: ImmutablePropTypes.map.isRequired, account: ImmutablePropTypes.map.isRequired,
intl: PropTypes.object.isRequired, intl: PropTypes.object.isRequired,
@ -60,15 +62,15 @@ class UserPanel extends ImmutablePureComponent {
this.setState({ hovering: false }) this.setState({ hovering: false })
} }
handleOnOpenEditProfile = () => {
this.props.onOpenEditProfile()
}
render() { render() {
const { account, intl } = this.props const {
account,
intl,
onOpenEditProfile,
} = this.props
const { hovering } = this.state const { hovering } = this.state
const buttonClasses = cx({ const buttonClasses = CX({
posAbs: 1, posAbs: 1,
mt10: 1, mt10: 1,
mr10: 1, mr10: 1,
@ -96,7 +98,7 @@ class UserPanel extends ImmutablePureComponent {
backgroundColor='secondary' backgroundColor='secondary'
radiusSmall radiusSmall
className={buttonClasses} className={buttonClasses}
onClick={this.handleOnOpenEditProfile} onClick={onOpenEditProfile}
> >
{intl.formatMessage(messages.edit_profile)} {intl.formatMessage(messages.edit_profile)}
</Button> </Button>
@ -134,4 +136,5 @@ class UserPanel extends ImmutablePureComponent {
</PanelLayout> </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, left0: 1,
radiusSmall: 1, radiusSmall: 1,
height100PC: 1, height100PC: 1,
backgroundColorSubtle2: !leading, bgSecondary: !leading,
backgroundColorBrandLight: leading, bgBrandLight: leading,
}) })
const inputClasses = cx('poll__input', { const inputClasses = cx('poll__input', {
@ -107,11 +107,11 @@ class Poll extends ImmutablePureComponent {
py10: showResults, py10: showResults,
mb10: 1, mb10: 1,
border1PX: !showResults, border1PX: !showResults,
fillColorSecondary: !showResults, fillSecondary: !showResults,
circle: !showResults, circle: !showResults,
cursorPointer: !showResults, cursorPointer: !showResults,
backgroundColorSubtle_onHover: !showResults, bgSubtle_onHover: !showResults,
backgroundColorSubtle: !showResults && active, bgSubtle: !showResults && active,
}) })
const textContainerClasses = cx({ const textContainerClasses = cx({

View File

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

View File

@ -108,6 +108,7 @@ class ProfileHeader extends ImmutablePureComponent {
const headerSrc = !!account ? account.get('header') : '' const headerSrc = !!account ? account.get('header') : ''
const headerMissing = headerSrc.indexOf(PLACEHOLDER_MISSING_HEADER_SRC) > -1 || !headerSrc const headerMissing = headerSrc.indexOf(PLACEHOLDER_MISSING_HEADER_SRC) > -1 || !headerSrc
const avatarSize = headerMissing ? 75 : 150 const avatarSize = headerMissing ? 75 : 150
const top = headerMissing ? -30 : -380
const avatarContainerClasses = CX({ const avatarContainerClasses = CX({
default: 1, default: 1,
@ -131,10 +132,13 @@ class ProfileHeader extends ImmutablePureComponent {
return ( return (
<div className={[_s.default, _s.z1, _s.width100PC].join(' ')}> <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(' ')}>
<div className={[_s.default, _s.width1015PX].join(' ')}>
{ {
!headerMissing && !headerMissing &&
<div className={[_s.default, _s.height350PX, _s.width100PC, _s.radiusSmall, _s.overflowHidden].join(' ')}> <div className={[_s.default, _s.height350PX, _s.width100PC, _s.bottomRightRadiusSmall, _s.bottomLeftRadiusSmall, _s.overflowHidden].join(' ')}>
<Image <Image
alt={intl.formatMessage(messages.headerPhoto)} alt={intl.formatMessage(messages.headerPhoto)}
className={_s.height350PX} className={_s.height350PX}
@ -155,8 +159,8 @@ class ProfileHeader extends ImmutablePureComponent {
</div> </div>
</div> </div>
<Sticky enabled onStateChange={this.onStickyStateChange}>
<div className={[_s.default, _s.flexRow, _s.backgroundColorSecondary3, _s.borderBottom1PX, _s.borderColorSecondary, _s.height53PX].join(' ')}> <div className={[_s.default, _s.flexRow, _s.bgPrimary, _s.height53PX].join(' ')}>
<div className={tabBarContainerClasses}> <div className={tabBarContainerClasses}>
<TabBar tabs={tabs} isLarge /> <TabBar tabs={tabs} isLarge />
</div> </div>
@ -219,9 +223,11 @@ class ProfileHeader extends ImmutablePureComponent {
</div> </div>
} }
</div> </div>
</Sticky>
</div> </div>
</div> </div>
</div>
</Sticky>
</div>
) )
} }

View File

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

View File

@ -116,7 +116,7 @@ class RichTextEditorBar extends PureComponent {
if (!rteControlsVisible || !isPro) return null if (!rteControlsVisible || !isPro) return null
return ( 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) => ( RTE_ITEMS.map((item, i) => (
<StyleButton <StyleButton
@ -179,8 +179,8 @@ class StyleButton extends PureComponent {
px10: 1, px10: 1,
mr5: 1, mr5: 1,
noSelect: 1, noSelect: 1,
backgroundColorSubtle2Dark_onHover: 1, bgSecondaryDark_onHover: 1,
backgroundColorBrandLight: active, bgBrandLight: active,
// py10: !small, // py10: !small,
// py5: small, // py5: small,
// px5: small, // px5: small,

View File

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

View File

@ -49,7 +49,7 @@ export default class Select extends ImmutablePureComponent {
<Icon <Icon
id='select' id='select'
size='14px' 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> </div>
) )

View File

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

View File

@ -11,7 +11,9 @@ import { makeGetAccount } from '../selectors'
import Responsive from '../features/ui/util/responsive_component' import Responsive from '../features/ui/util/responsive_component'
import SidebarSectionTitle from './sidebar_section_title' import SidebarSectionTitle from './sidebar_section_title'
import SidebarSectionItem from './sidebar_section_item' 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({ const messages = defineMessages({
followers: { id: 'account.followers', defaultMessage: 'Followers' }, followers: { id: 'account.followers', defaultMessage: 'Followers' },
@ -27,6 +29,8 @@ const messages = defineMessages({
lists: { id: 'column.lists', defaultMessage: 'Lists' }, lists: { id: 'column.lists', defaultMessage: 'Lists' },
apps: { id: 'tabs_bar.apps', defaultMessage: 'Apps' }, apps: { id: 'tabs_bar.apps', defaultMessage: 'Apps' },
more: { id: 'sidebar.more', defaultMessage: 'More' }, 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' }, pro: { id: 'promo.gab_pro', defaultMessage: 'Upgrade to GabPRO' },
trends: { id: 'promo.trends', defaultMessage: 'Trends' }, trends: { id: 'promo.trends', defaultMessage: 'Trends' },
search: { id: 'tabs_bar.search', defaultMessage: 'Search' }, search: { id: 'tabs_bar.search', defaultMessage: 'Search' },
@ -73,6 +77,10 @@ class Sidebar extends ImmutablePureComponent {
openSidebarMorePopover: PropTypes.func.isRequired, openSidebarMorePopover: PropTypes.func.isRequired,
notificationCount: PropTypes.number.isRequired, notificationCount: PropTypes.number.isRequired,
homeItemsQueueCount: PropTypes.number.isRequired, homeItemsQueueCount: PropTypes.number.isRequired,
actions: PropTypes.array,
tabs: PropTypes.array,
title: PropTypes.string,
showBackBtn: PropTypes.bool,
} }
handleOpenComposeModal = () => { handleOpenComposeModal = () => {
@ -98,6 +106,10 @@ class Sidebar extends ImmutablePureComponent {
homeItemsQueueCount, homeItemsQueueCount,
showCommunityTimeline, showCommunityTimeline,
moreOpen, moreOpen,
actions,
tabs,
title,
showBackBtn,
} = this.props } = this.props
// : todo : // : todo :
@ -196,13 +208,23 @@ class Sidebar extends ImmutablePureComponent {
return ( return (
<header role='banner' className={[_s.default, _s.flexGrow1, _s.z3, _s.alignItemsEnd].join(' ')}> <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.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(' ')}> <div className={[_s.default, _s.height100PC, _s.alignItemsStart, _s.width240PX, _s.pr15, _s.py10, _s.overflowYScroll].join(' ')}>
<div className={_s.default}>
<SidebarHeader /> <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(' ')}> <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) => { menuItems.map((menuItem, i) => {
if (menuItem.hidden) return null if (menuItem.hidden) return null
@ -212,13 +234,7 @@ class Sidebar extends ImmutablePureComponent {
) )
}) })
} }
{ /* <SidebarSectionTitle>Shortcuts</SidebarSectionTitle> */ } <SidebarSectionTitle>{intl.formatMessage(messages.explore)}</SidebarSectionTitle>
{
shortcutItems.map((shortcutItem, i) => (
<SidebarSectionItem {...shortcutItem} key={`sidebar-item-shortcut-${i}`} />
))
}
<SidebarSectionTitle>Explore</SidebarSectionTitle>
{ {
exploreItems.map((exploreItem, i) => ( exploreItems.map((exploreItem, i) => (
<SidebarSectionItem {...exploreItem} key={`sidebar-item-explore-${i}`} /> <SidebarSectionItem {...exploreItem} key={`sidebar-item-explore-${i}`} />
@ -230,7 +246,7 @@ class Sidebar extends ImmutablePureComponent {
<Button <Button
isBlock isBlock
onClick={this.handleOpenComposeModal} onClick={this.handleOpenComposeModal}
className={[_s.py15, _s.fontSize15PX, _s.fontWeightBold].join(' ')} className={[_s.py15, _s.fs15PX, _s.fontWeightBold].join(' ')}
> >
Gab Gab
</Button> </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, outlineNone: 1,
borderColorTransparent: !shouldShowActive, borderColorTransparent: !shouldShowActive,
borderColorSecondary: shouldShowActive, borderColorSecondary: shouldShowActive,
backgroundTransparent: !shouldShowActive, bgTransparent: !shouldShowActive,
backgroundColorPrimary: shouldShowActive, bgPrimary: shouldShowActive,
}) })
const textClasses = cx({ const textClasses = cx({
default: 1, default: 1,
fontWeightNormal: 1, fontWeightNormal: 1,
fontSize15PX: 1, fs15PX: 1,
text: 1, text: 1,
textOverflowEllipsis: 1, textOverflowEllipsis: 1,
colorPrimary: 1, colorPrimary: 1,
}) })
const iconClasses = cx({ const iconClasses = cx({
fillColorPrimary: 1, fillPrimary: 1,
}) })
const countClasses = cx({ const countClasses = cx({
default: 1, default: 1,
text: 1, text: 1,
mlAuto: 1, mlAuto: 1,
fontSize12PX: 1, fs12PX: 1,
px5: 1, px5: 1,
mr2: 1, mr2: 1,
lineHeight15: 1, lineHeight15: 1,
ml5: 1, ml5: 1,
colorSecondary: !isNotifications, colorSecondary: !isNotifications,
colorWhite: isNotifications, colorWhite: isNotifications,
backgroundColorBrand: isNotifications, bgBrand: isNotifications,
radiusSmall: isNotifications, radiusSmall: isNotifications,
}) })
@ -110,7 +110,7 @@ export default class SidebarSectionItem extends PureComponent {
buttonRef={buttonRef} buttonRef={buttonRef}
onMouseEnter={() => this.handleOnMouseEnter()} onMouseEnter={() => this.handleOnMouseEnter()}
onMouseLeave={() => this.handleOnMouseLeave()} 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}> <div className={containerClasses}>
{ {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -85,7 +85,7 @@ class StatusContent extends ImmutablePureComponent {
if (descendent.classList.contains('invisible')) { if (descendent.classList.contains('invisible')) {
descendent.classList.remove('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')) { if (descendent.classList.contains('ellipsis')) {
descendent.classList.remove('ellipsis') descendent.classList.remove('ellipsis')
@ -254,7 +254,7 @@ class StatusContent extends ImmutablePureComponent {
<div className={spoilerContainerClasses}> <div className={spoilerContainerClasses}>
<div className={[_s.default, _s.flexRow, _s.mr5].join(' ')}> <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 <div
className={_s.statusContent} className={_s.statusContent}
dangerouslySetInnerHTML={spoilerContent} dangerouslySetInnerHTML={spoilerContent}

View File

@ -104,7 +104,7 @@ class StatusHeader extends ImmutablePureComponent {
color='none' color='none'
icon='ellipsis' icon='ellipsis'
iconSize='20px' iconSize='20px'
iconClassName={_s.fillColorSecondary} iconClassName={_s.fillSecondary}
className={_s.mlAuto} className={_s.mlAuto}
onClick={this.handleOpenStatusOptionsPopover} onClick={this.handleOpenStatusOptionsPopover}
buttonRef={this.setStatusOptionsButton} buttonRef={this.setStatusOptionsButton}
@ -127,7 +127,7 @@ class StatusHeader extends ImmutablePureComponent {
<DotTextSeperator /> <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') && !!status.get('group') &&

View File

@ -42,7 +42,7 @@ class StatusPrepend extends ImmutablePureComponent {
return ( return (
<div className={[_s.default, _s.width100PC, _s.alignItemsStart, _s.borderBottom1PX, _s.borderColorSecondary].join(' ')}> <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(' ')}> <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 && isRepost &&
<div className={[_s.default, _s.flexRow].join(' ')}> <div className={[_s.default, _s.flexRow].join(' ')}>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -53,7 +53,7 @@ class TimelineComposeBlock extends ImmutablePureComponent {
return ( return (
<section className={[_s.default, _s.mb15].join(' ')}> <section className={[_s.default, _s.mb15].join(' ')}>
<Block> <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}> <div className={_s.mr10}>
<Avatar account={account} size={20} noHover /> <Avatar account={account} size={20} noHover />
</div> </div>

View File

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

View File

@ -54,7 +54,7 @@ class UploadArea extends PureComponent {
> >
{({ backgroundOpacity, backgroundScale }) => ( {({ backgroundOpacity, backgroundScale }) => (
<div <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={{ style={{
visibility: active ? 'visible' : 'hidden', visibility: active ? 'visible' : 'hidden',
opacity: backgroundOpacity 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.width340PX, _s.height260PX, _s.px10, _s.py10].join(' ')}>
<div <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={{ style={{
transform: `scale(${backgroundScale})` transform: `scale(${backgroundScale})`
}} }}

View File

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

View File

@ -3,6 +3,8 @@ export const CX = classNames.bind(_s)
export const APP_NAME = 'Gab' export const APP_NAME = 'Gab'
export const DEFAULT_REL = 'noopener noreferrer'
export const BREAKPOINT_EXTRA_LARGE = 1480 export const BREAKPOINT_EXTRA_LARGE = 1480
export const BREAKPOINT_LARGE = 1280 export const BREAKPOINT_LARGE = 1280
export const BREAKPOINT_MEDIUM = 1160 export const BREAKPOINT_MEDIUM = 1160
@ -12,6 +14,8 @@ export const BREAKPOINT_EXTRA_SMALL = 992
export const ALLOWED_AROUND_SHORT_CODE = '><\u0085\u0020\u00a0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029\u0009\u000a\u000b\u000c\u000d' export const ALLOWED_AROUND_SHORT_CODE = '><\u0085\u0020\u00a0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029\u0009\u000a\u000b\u000c\u000d'
export const MAX_POST_CHARACTER_COUNT = 3000 export const MAX_POST_CHARACTER_COUNT = 3000
export const URL_DISSENTER_SHOP = 'https://shop.dissenter.com'
export const PLACEHOLDER_MISSING_HEADER_SRC = '/original/missing.png' export const PLACEHOLDER_MISSING_HEADER_SRC = '/original/missing.png'
export const POPOVER_CONTENT_WARNING = 'CONTENT_WARNING' export const POPOVER_CONTENT_WARNING = 'CONTENT_WARNING'

View File

@ -48,7 +48,13 @@ const makeMapStateToProps = () => {
const getStatus = makeGetStatus(); const getStatus = makeGetStatus();
const mapStateToProps = (state, props) => { const mapStateToProps = (state, props) => {
const status = getStatus(state, props) const statusId = props.id || props.params.statusId
const username = props.params ? props.params.username : undefined
const status = getStatus(state, {
id: statusId,
username: username,
})
// : todo : if is comment (i.e. if any ancestorsIds) use comment not status // : todo : if is comment (i.e. if any ancestorsIds) use comment not status

View File

@ -27,8 +27,8 @@ export default class ComposeExtraButton extends PureComponent {
} = this.props } = this.props
const btnClasses = cx({ const btnClasses = cx({
backgroundColorSubtle_onHover: !active, bgSubtle_onHover: !active,
backgroundColorBrandLight: active, bgBrandLight: active,
py10: !small, py10: !small,
px10: !small, px10: !small,
py5: small, py5: small,
@ -37,8 +37,8 @@ export default class ComposeExtraButton extends PureComponent {
}) })
const iconClasses = cx({ const iconClasses = cx({
fillColorSecondary: !active, fillSecondary: !active,
fillColorWhite: active, fillWhite: active,
}) })
const iconSize = !!small ? '14px' : '16px' const iconSize = !!small ? '14px' : '16px'

View File

@ -257,7 +257,7 @@ class ComposeForm extends ImmutablePureComponent {
alignItemsEnd: shouldCondense, alignItemsEnd: shouldCondense,
flexRow: shouldCondense, flexRow: shouldCondense,
radiusSmall: shouldCondense, radiusSmall: shouldCondense,
backgroundColorSubtle: shouldCondense, bgSubtle: shouldCondense,
px5: shouldCondense, px5: shouldCondense,
}) })
@ -427,7 +427,7 @@ class ComposeForm extends ImmutablePureComponent {
isDisabled={disabledButton} isDisabled={disabledButton}
backgroundColor='none' backgroundColor='none'
color='brand' color='brand'
className={[_s.fontSize15PX, _s.px15].join(' ')} className={[_s.fs15PX, _s.px15].join(' ')}
onClick={this.handleSubmit} onClick={this.handleSubmit}
> >
{intl.formatMessage(scheduledAt ? messages.schedulePost : messages.publish)} {intl.formatMessage(scheduledAt ? messages.schedulePost : messages.publish)}

View File

@ -278,7 +278,7 @@ class PollFormOption extends ImmutablePureComponent {
className={[_s.ml5, _s.justifyContentCenter].join(' ')} className={[_s.ml5, _s.justifyContentCenter].join(' ')}
icon='close' icon='close'
iconSize='8px' iconSize='8px'
iconClassName={_s.fillColorSecondary} iconClassName={_s.fillSecondary}
disabled={index <= 1} disabled={index <= 1}
title={intl.formatMessage(messages.remove_option)} title={intl.formatMessage(messages.remove_option)}
onClick={this.handleOptionRemove} onClick={this.handleOptionRemove}

View File

@ -88,7 +88,7 @@ class Followers extends ImmutablePureComponent {
> >
{ {
!!accountIds && accountIds.map((id) => ( !!accountIds && accountIds.map((id) => (
<Account key={`follower-${id}`} id={id} compact /> <Account key={`follower-${id}`} id={id} compact withBio />
)) ))
} }
</ScrollableList> </ScrollableList>

View File

@ -88,7 +88,7 @@ class Following extends ImmutablePureComponent {
> >
{ {
!!accountIds && accountIds.map((id) => ( !!accountIds && accountIds.map((id) => (
<Account key={`following-${id}`} id={id} compact /> <Account key={`following-${id}`} id={id} compact withBio />
)) ))
} }
</ScrollableList> </ScrollableList>

View File

@ -10,6 +10,7 @@ import StatusList from '../components/status_list'
import ColumnIndicator from '../components/column_indicator' import ColumnIndicator from '../components/column_indicator'
import Button from '../components/button' import Button from '../components/button'
import Text from '../components/text' import Text from '../components/text'
import Block from '../components/block'
const mapStateToProps = (state, props) => ({ const mapStateToProps = (state, props) => ({
list: state.getIn(['lists', props.params.id]), list: state.getIn(['lists', props.params.id]),
@ -85,7 +86,7 @@ class ListTimeline extends ImmutablePureComponent {
} }
const emptyMessage = ( const emptyMessage = (
<div className={[_s.default].join(' ')}> <div className={[_s.default, _s.py15, _s.px15].join(' ')}>
<FormattedMessage <FormattedMessage
id='empty_column.list' id='empty_column.list'
defaultMessage='There is nothing in this list yet. When members of this list post new statuses, they will appear here.' defaultMessage='There is nothing in this list yet. When members of this list post new statuses, they will appear here.'
@ -95,7 +96,7 @@ class ListTimeline extends ImmutablePureComponent {
onClick={this.handleEditClick} onClick={this.handleEditClick}
className={[_s.mt10]} className={[_s.mt10]}
> >
<Text color='inherit'> <Text color='inherit' align='center'>
<FormattedMessage id='list.click_to_add' defaultMessage='Click here to add people' /> <FormattedMessage id='list.click_to_add' defaultMessage='Click here to add people' />
</Text> </Text>
</Button> </Button>

View File

@ -16,9 +16,7 @@ const mapStateToProps = (state) => ({
}) })
const mapDispatchToProps = (dispatch) => ({ const mapDispatchToProps = (dispatch) => ({
onFetchLists() { onFetchLists: () => dispatch(fetchLists()),
return dispatch(fetchLists())
},
}) })
export default export default
@ -37,7 +35,7 @@ class ListsDirectory extends ImmutablePureComponent {
} }
updateOnProps = [ updateOnProps = [
'lists' 'lists',
] ]
componentDidMount() { componentDidMount() {

View File

@ -13,6 +13,7 @@ import Heading from '../components/heading'
import Button from '../components/button' import Button from '../components/button'
import Text from '../components/text' import Text from '../components/text'
import Account from '../components/account' import Account from '../components/account'
import PanelLayout from '../components/panel/panel_layout'
const mapStateToProps = (state) => ({ const mapStateToProps = (state) => ({
results: state.getIn(['search', 'results']), results: state.getIn(['search', 'results']),
@ -38,14 +39,14 @@ class Search extends ImmutablePureComponent {
isSmallScreen: (window.innerWidth <= 895), isSmallScreen: (window.innerWidth <= 895),
} }
render () { render() {
const { results, location } = this.props const { results, location } = this.props
const { isSmallScreen } = this.state const { isSmallScreen } = this.state
console.log("results:", results)
if (results.isEmpty() && isSmallScreen) { if (results.isEmpty() && isSmallScreen) {
return ( return null
<div />
)
} }
const pathname = location.pathname || '' const pathname = location.pathname || ''
@ -53,58 +54,94 @@ class Search extends ImmutablePureComponent {
const showHashtags = pathname === '/search/hashtags' const showHashtags = pathname === '/search/hashtags'
const showGroups = pathname === '/search/groups' const showGroups = pathname === '/search/groups'
const isTop = !showPeople && !showHashtags && !showGroups const isTop = !showPeople && !showHashtags && !showGroups
const theLimit = 10
let accounts, statuses, hashtags, groups let accounts, statuses, hashtags, groups
if (results.get('accounts') && results.get('accounts').size > 0 && (isTop || showPeople)) { // : todo : statuses
const size = isTop ? Math.min(results.get('accounts').size, 5) : results.get('accounts').size;
accounts = (
<Block>
<div className={[_s.default, _s.py15].join(' ')}>
<div className={[_s.default, _s.flexRow, _s.mb15, _s.px15].join(' ')}>
<Heading size='h2'>
People
</Heading>
<div className={[_s.default, _s.mlAuto].join(' ')}>
<Button
isText
backgroundColor='none'
color='brand'
to='/search/people'
>
<Text size='small' color='inherit' weight='bold'>
See All
</Text>
</Button>
</div>
</div>
{ if (results.get('accounts') && results.get('accounts').size > 0 && (isTop || showPeople)) {
results.get('accounts').slice(0, size).map(accountId => <Account compact key={accountId} id={accountId} />) const size = isTop ? Math.min(results.get('accounts').size, theLimit) : results.get('accounts').size;
} const isMax = size === results.get('accounts').size
accounts = (
<PanelLayout
title='People'
headerButtonTo={isMax ? undefined : '/search/people'}
headerButtonTitle={isMax ? undefined : 'See more'}
footerButtonTo={isMax ? undefined : '/search/people'}
footerButtonTitle={isMax ? undefined : 'See more'}
noPadding
>
<div className={[_s.default, _s.pb10, _s.px15, _s.borderBottom1PX, _s.borderColorSecondary].join(' ')}>
<Text color='tertiary' size='small'>
Showing {size} of {results.get('accounts').size} results
</Text>
</div> </div>
</Block> {
results.get('accounts').slice(0, size).map(accountId => (
<Account
compact
withBio
key={accountId}
id={accountId}
/>
))
}
</PanelLayout>
) )
} }
if (results.get('groups') && results.get('groups').size > 0 && (isTop || showGroups)) { if (results.get('groups') && results.get('groups').size > 0 && (isTop || showGroups)) {
const size = isTop ? Math.min(results.get('groups').size, 5) : results.get('groups').size; const size = isTop ? Math.min(results.get('groups').size, theLimit) : results.get('groups').size;
const isMax = size === results.get('groups').size
groups = ( groups = (
<div className='search-results__section'> <PanelLayout
<h5><Icon id='users' fixedWidth /><FormattedMessage id='search_results.groups' defaultMessage='Groups' /></h5> title='Groups'
{results.get('groups').slice(0, size).map(group => <GroupListItem key={`search-${group.get('name')}`} group={group} />)} headerButtonTo={isMax ? undefined : '/search/groups'}
headerButtonTitle={isMax ? undefined : 'See more'}
footerButtonTo={isMax ? undefined : '/search/groups'}
footerButtonTitle={isMax ? undefined : 'See more'}
noPadding
>
<div className={[_s.default, _s.pb10, _s.px15, _s.borderBottom1PX, _s.borderColorSecondary].join(' ')}>
<Text color='tertiary' size='small'>
Showing {size} of {results.get('groups').size} results
</Text>
</div> </div>
); {
results.get('groups').slice(0, size).map(group => (
<GroupListItem
key={`search-${group.get('name')}`}
id={group.get('id')}
/>
))
}
</PanelLayout>
)
} }
if (results.get('hashtags') && results.get('hashtags').size > 0 && (isTop || showHashtags)) { if (results.get('hashtags') && results.get('hashtags').size > 0 && (isTop || showHashtags)) {
const size = isTop ? Math.min(results.get('hashtags').size, 5) : results.get('hashtags').size; const size = isTop ? Math.min(results.get('hashtags').size, theLimit) : results.get('hashtags').size;
const isMax = size === results.get('hashtags').size
hashtags = ( hashtags = (
<div className='search-results__section'> <PanelLayout
<h5><Icon id='hashtag' fixedWidth /><FormattedMessage id='search_results.hashtags' defaultMessage='Hashtags' /></h5> title='Hashtags'
{results.get('hashtags').slice(0, size).map(hashtag => <HashtagItem isCompact key={hashtag.get('name')} hashtag={hashtag} />)} headerButtonTo={isMax ? undefined : '/search/hashtags'}
headerButtonTitle={isMax ? undefined : 'See more'}
footerButtonTo={isMax ? undefined : '/search/hashtags'}
footerButtonTitle={isMax ? undefined : 'See more'}
noPadding
>
<div className={[_s.default, _s.pb10, _s.px15, _s.borderBottom1PX, _s.borderColorSecondary].join(' ')}>
<Text color='tertiary' size='small'>
Showing {size} of {results.get('hashtags').size} results
</Text>
</div> </div>
); {results.get('hashtags').slice(0, size).map(hashtag => <HashtagItem isCompact key={hashtag.get('name')} hashtag={hashtag} />)}
</PanelLayout>
)
} }
return ( return (

View File

@ -0,0 +1,12 @@
import StatusContainer from '../containers/status_container'
export default class Status extends PureComponent {
render() {
console.log("this.props:", this.props)
return (
<StatusContainer {...this.props} />
)
}
}

View File

@ -63,7 +63,7 @@ import {
Notifications, Notifications,
Search, Search,
// Shortcuts, // Shortcuts,
Status, StatusFeature,
StatusLikes, StatusLikes,
StatusReposts, StatusReposts,
} from './util/async_components' } from './util/async_components'
@ -206,7 +206,7 @@ class SwitchingArea extends PureComponent {
<WrappedRoute path='/:username/likes' page={ProfilePage} component={LikedStatuses} content={children} /> <WrappedRoute path='/:username/likes' page={ProfilePage} component={LikedStatuses} content={children} />
<Redirect from='/@:username/posts/:statusId' to='/:username/posts/:statusId' exact /> <Redirect from='/@:username/posts/:statusId' to='/:username/posts/:statusId' exact />
<WrappedRoute path='/:username/posts/:statusId' publicRoute exact page={BasicPage} component={Status} content={children} componentParams={{ title: 'Status' }} /> <WrappedRoute path='/:username/posts/:statusId' publicRoute exact page={BasicPage} component={StatusFeature} content={children} componentParams={{ title: 'Status' }} />
<Redirect from='/@:username/posts/:statusId/reposts' to='/:username/posts/:statusId/reposts' /> <Redirect from='/@:username/posts/:statusId/reposts' to='/:username/posts/:statusId/reposts' />
<WrappedRoute path='/:username/posts/:statusId/reposts' page={BasicPage} component={StatusReposts} content={children} componentParams={{ title: 'Reposts' }} /> <WrappedRoute path='/:username/posts/:statusId/reposts' page={BasicPage} component={StatusReposts} content={children} componentParams={{ title: 'Reposts' }} />
@ -497,7 +497,7 @@ class UI extends PureComponent {
return ( return (
<div ref={this.setRef}> <div ref={this.setRef}>
<LoadingBar className={[_s.height1PX, _s.z3, _s.backgroundColorBrandLight].join(' ')} /> <LoadingBar className={[_s.height1PX, _s.z3, _s.bgBrandLight].join(' ')} />
<SwitchingArea location={location} onLayoutChange={this.handleLayoutChange}> <SwitchingArea location={location} onLayoutChange={this.handleLayoutChange}>
{children} {children}

View File

@ -59,6 +59,7 @@ export function ReportModal() { return import(/* webpackChunkName: "modals/repor
export function RepostOptionsPopover() { return import(/* webpackChunkName: "components/repost_options_popover" */'../../../components/popover/repost_options_popover') } export function RepostOptionsPopover() { return import(/* webpackChunkName: "components/repost_options_popover" */'../../../components/popover/repost_options_popover') }
export function Search() { return import(/*webpackChunkName: "features/search" */'../../search') } export function Search() { return import(/*webpackChunkName: "features/search" */'../../search') }
export function Status() { return import(/* webpackChunkName: "components/status" */'../../../components/status') } export function Status() { return import(/* webpackChunkName: "components/status" */'../../../components/status') }
export function StatusFeature() { return import(/* webpackChunkName: "features/status" */'../../status') }
export function SearchPopover() { return import(/* webpackChunkName: "components/search_popover" */'../../../components/popover/search_popover') } export function SearchPopover() { return import(/* webpackChunkName: "components/search_popover" */'../../../components/popover/search_popover') }
export function SidebarMorePopover() { return import(/* webpackChunkName: "components/sidebar_more_popover" */'../../../components/popover/sidebar_more_popover') } export function SidebarMorePopover() { return import(/* webpackChunkName: "components/sidebar_more_popover" */'../../../components/popover/sidebar_more_popover') }
export function StatusLikes() { return import(/* webpackChunkName: "features/status_likes" */'../../status_likes') } export function StatusLikes() { return import(/* webpackChunkName: "features/status_likes" */'../../status_likes') }

View File

@ -1,9 +1,9 @@
import Sticky from 'react-stickynode' import Sticky from 'react-stickynode'
import * as Constants from '../constants'
import Search from '../components/search' import Search from '../components/search'
import ColumnHeader from '../components/column_header' import ColumnHeader from '../components/column_header'
import Sidebar from '../components/sidebar' import Sidebar from '../components/sidebar'
// import Header from '../components/header' import { BREAKPOINT_EXTRA_SMALL } from '../constants'
import NavigationBar from '../components/navigation_bar'
// import Footer from '../components/footer' // import Footer from '../components/footer'
import FloatingActionButton from '../components/floating_action_button' import FloatingActionButton from '../components/floating_action_button'
import Responsive from '../features/ui/util/responsive_component' import Responsive from '../features/ui/util/responsive_component'
@ -36,44 +36,25 @@ export default class Layout extends PureComponent {
} = this.props } = this.props
return ( return (
<div className={[_s.default, _s.flexRow, _s.width100PC, _s.heightMin100VH, _s.backgroundColorSecondary3].join(' ')}> <div className={[_s.default, _s.width100PC, _s.heightMin100VH, _s.bgTertiary].join(' ')}>
<NavigationBar
title={title}
tabs={tabs}
actions={actions}
/>
<div className={[_s.default, _s.flexRow, _s.width100PC].join(' ')}>
{ {
!noSidebar && !noSidebar &&
<Responsive min={Constants.BREAKPOINT_EXTRA_SMALL}> <Responsive min={BREAKPOINT_EXTRA_SMALL}>
<Sidebar /> <Sidebar title={title} tabs={tabs} actions={actions} />
</Responsive> </Responsive>
} }
<main role='main' className={[_s.default, _s.flexShrink1, _s.flexGrow1, _s.borderColorSecondary, _s.borderLeft1PX].join(' ')}> <main role='main' className={[_s.default, _s.flexShrink1, _s.flexGrow1].join(' ')}>
{ <div className={[_s.default, _s.width1015PX, _s.flexRow, _s.justifyContentEnd, _s.py15].join(' ')}>
!noHeader &&
<div className={[_s.default, _s.height53PX, _s.borderBottom1PX, _s.borderColorSecondary, _s.backgroundColorSecondary3, _s.z3, _s.top0, _s.posFixed].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={Constants.BREAKPOINT_EXTRA_SMALL}>
<div className={[_s.default, _s.width340PX].join(' ')}>
<Search />
</div>
</Responsive>
</div>
</div>
}
{
!noHeader &&
<div className={[_s.default, _s.height53PX].join(' ')}></div>
}
<div className={[_s.default, _s.width1015PX, _s.flexRow, _s.justifyContentSpaceBetween, _s.pl15, _s.py15].join(' ')}>
{ {
noRightSidebar && children noRightSidebar && children
@ -90,8 +71,8 @@ export default class Layout extends PureComponent {
{ {
!noRightSidebar && !noRightSidebar &&
<Responsive min={Constants.BREAKPOINT_EXTRA_SMALL}> <Responsive min={BREAKPOINT_EXTRA_SMALL}>
<div className={[_s.default, _s.width340PX].join(' ')}> <div className={[_s.default, _s.width340PX, _s.ml15].join(' ')}>
<Sticky top={73} enabled> <Sticky top={73} enabled>
<div className={[_s.default, _s.width340PX].join(' ')}> <div className={[_s.default, _s.width340PX].join(' ')}>
{layout} {layout}
@ -103,7 +84,7 @@ export default class Layout extends PureComponent {
{ {
!noComposeButton && !noComposeButton &&
<Responsive max={Constants.BREAKPOINT_EXTRA_SMALL}> <Responsive max={BREAKPOINT_EXTRA_SMALL}>
<FloatingActionButton /> <FloatingActionButton />
</Responsive> </Responsive>
} }
@ -111,7 +92,7 @@ export default class Layout extends PureComponent {
</div> </div>
</main> </main>
</div>
</div> </div>
) )
} }

View File

@ -1,8 +1,8 @@
import ImmutablePropTypes from 'react-immutable-proptypes' import ImmutablePropTypes from 'react-immutable-proptypes'
import ImmutablePureComponent from 'react-immutable-pure-component' import ImmutablePureComponent from 'react-immutable-pure-component'
import Sticky from 'react-stickynode' import Sticky from 'react-stickynode'
import Layout from './layout'
import ProfileHeader from '../components/profile_header' import ProfileHeader from '../components/profile_header'
import NavigationBar from '../components/navigation_bar'
export default class ProfileLayout extends ImmutablePureComponent { export default class ProfileLayout extends ImmutablePureComponent {
static propTypes = { static propTypes = {
@ -18,38 +18,48 @@ export default class ProfileLayout extends ImmutablePureComponent {
account, account,
children, children,
layout, layout,
title,
showBackBtn,
} = this.props } = this.props
return ( return (
<Layout <div className={[_s.default, _s.width100PC, _s.heightMin100VH, _s.bgTertiary].join(' ')}>
noRightSidebar
noComposeButton <NavigationBar />
>
<div className={[_s.default, _s.width1015PX, _s.flexRow, _s.justifyContentSpaceBetween, _s.pr15].join(' ')}> <main role='main' className={[_s.default, _s.width100PC].join(' ')}>
<div className={[_s.default, _s.z1, _s.width100PC].join(' ')}>
<div className={[_s.default, _s.width100PC, _s.flexRow, _s.pb15].join(' ')}>
<div className={[_s.default, _s.width100PC, _s.flexRow, _s.justifyContentSpaceBetween].join(' ')}>
<div className={[_s.default, _s.z1, _s.width100PC, _s.alignItemsCenter].join(' ')}>
<ProfileHeader account={account} /> <ProfileHeader account={account} />
<div className={[_s.default, _s.width100PC, _s.flexRow, _s.justifyContentSpaceBetween, _s.py15].join(' ')}> <div className={[_s.default, _s.width1015PX,, _s.flexRow, _s.justifyContentEnd, _s.py15].join(' ')}>
<div className={[_s.default, _s.width645PX, _s.z1].join(' ')}> <div className={[_s.default, _s.width340PX, _s.mr15].join(' ')}>
<div className={_s.default}>
{children}
</div>
</div>
<div className={[_s.default, _s.width340PX].join(' ')}>
<Sticky top={63} enabled> <Sticky top={63} enabled>
<div className={[_s.default, _s.width340PX].join(' ')}> <div className={[_s.default, _s.width340PX].join(' ')}>
{layout} {layout}
</div> </div>
</Sticky> </Sticky>
</div> </div>
<div className={[_s.default, _s.width645PX, _s.z1].join(' ')}>
<div className={_s.default}>
{children}
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
</Layout>
</div>
</main>
</div>
) )
} }

View File

@ -14,13 +14,13 @@ export default class SettingsLayout extends PureComponent {
const { children, actions, tabs, title } = this.props const { children, actions, tabs, title } = this.props
return ( return (
<div className={[_s.default, _s.flexRow, _s.width100PC, _s.heightMin100VH, _s.backgroundColorSecondary3].join(' ')}> <div className={[_s.default, _s.flexRow, _s.width100PC, _s.heightMin100VH, _s.bgTertiary].join(' ')}>
<Sidebar /> <Sidebar />
<main role='main' className={[_s.default, _s.flexShrink1, _s.flexGrow1, _s.borderColorSecondary, _s.borderLeft1PX].join(' ')}> <main role='main' className={[_s.default, _s.flexShrink1, _s.flexGrow1, _s.borderColorSecondary, _s.borderLeft1PX].join(' ')}>
<div className={[_s.default, _s.height53PX, _s.borderBottom1PX, _s.borderColorSecondary, _s.backgroundColorSecondary3, _s.z3, _s.top0, _s.posFixed].join(' ')}> <div className={[_s.default, _s.height53PX, _s.borderBottom1PX, _s.borderColorSecondary, _s.bgTertiary, _s.z3, _s.top0, _s.posFixed].join(' ')}>
<div className={[_s.default, _s.height53PX, _s.pl15, _s.width1015PX, _s.flexRow, _s.justifyContentSpaceBetween].join(' ')}> <div className={[_s.default, _s.height53PX, _s.pl15, _s.width1015PX, _s.flexRow, _s.justifyContentSpaceBetween].join(' ')}>
<div className={[_s.default, _s.width100PC].join(' ')}> <div className={[_s.default, _s.width100PC].join(' ')}>
<ColumnHeader <ColumnHeader

View File

@ -12,7 +12,7 @@ import DefaultLayout from '../layouts/default_layout'
const messages = defineMessages({ const messages = defineMessages({
groups: { id: 'groups', defaultMessage: 'Groups' }, groups: { id: 'groups', defaultMessage: 'Groups' },
featured: { id: 'featured', defaultMessage: 'Featured' }, featured: { id: 'featured', defaultMessage: 'Featured' },
new: { id: 'new', defaultMessage: 'New' }, new: { id: 'new', defaultMessage: 'Just Added' },
myGroups: { id: 'my_groups', defaultMessage: 'My Groups' }, myGroups: { id: 'my_groups', defaultMessage: 'My Groups' },
admin: { id: 'admin', defaultMessage: 'Admin' }, admin: { id: 'admin', defaultMessage: 'Admin' },
}) })
@ -50,7 +50,7 @@ class GroupsPage extends PureComponent {
const actions = [] const actions = []
const tabs = [ const tabs = [
{ {
title: intl.formatMessage(messages.groups), title: intl.formatMessage(messages.featured),
to: '/groups', to: '/groups',
}, },
{ {

View File

@ -38,10 +38,6 @@ class SearchPage extends PureComponent {
title: 'Groups', title: 'Groups',
to: '/search/groups' to: '/search/groups'
}, },
{
title: 'Gabs',
to: '/search/gabs'
},
{ {
title: 'Trends', title: 'Trends',
to: '/search/trends' to: '/search/trends'

View File

@ -2,6 +2,7 @@ import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
import { GROUPS_FETCH_SUCCESS } from '../actions/groups'; import { GROUPS_FETCH_SUCCESS } from '../actions/groups';
const initialState = ImmutableMap({ const initialState = ImmutableMap({
new: ImmutableList(),
featured: ImmutableList(), featured: ImmutableList(),
member: ImmutableList(), member: ImmutableList(),
admin: ImmutableList(), admin: ImmutableList(),

View File

@ -12,8 +12,8 @@
--font_size_extra_large: 19px; --font_size_extra_large: 19px;
--font_size_extra_extra_large: 24px; --font_size_extra_extra_large: 24px;
--color_brand-dark: #38a16b; --color_brand-dark: #378e61;
--color_brand-light: #36e991; --color_brand-light: #63DA9D;
--color_brand-light-opaque: rgb(54, 233, 145, .125); --color_brand-light-opaque: rgb(54, 233, 145, .125);
--color_brand: #21cf7a; --color_brand: #21cf7a;
@ -30,7 +30,7 @@
--solid_color_primary-opaque:rgba(255, 255, 255,.6); --solid_color_primary-opaque:rgba(255, 255, 255,.6);
--solid_color_secondary: #e2e8ec; --solid_color_secondary: #e2e8ec;
--solid_color_secondary-dark: #d9e0e5; --solid_color_secondary-dark: #d9e0e5;
--solid_color_tertiary: #f6f6f9; --solid_color_tertiary: #f5f5f7;
--solid_color_block: #f5f8fa; --solid_color_block: #f5f8fa;
--text_color_primary: #2d3436; --text_color_primary: #2d3436;
@ -214,6 +214,7 @@ body {
.justifyContentSpaceBetween { justify-content: space-between; } .justifyContentSpaceBetween { justify-content: space-between; }
.justifyContentCenter { justify-content: center; } .justifyContentCenter { justify-content: center; }
.justifyContentEnd { justify-content: flex-end; }
.overflowHidden { .overflowHidden {
overflow-x: hidden; overflow-x: hidden;
@ -230,6 +231,8 @@ body {
white-space: nowrap; white-space: nowrap;
} }
.textUppercase { text-transform: uppercase; }
.whiteSpaceNoWrap { white-space: nowrap; } .whiteSpaceNoWrap { white-space: nowrap; }
.outlineNone { outline: none; } .outlineNone { outline: none; }
@ -295,39 +298,39 @@ body {
); );
} }
.backgroundTransparent { background-color: transparent; } .bgTransparent { background-color: transparent; }
.backgroundColorLoading { background-color: #ccc; } .bgLoading { background-color: #ccc; }
.backgroundColorSubtle { background-color: var(--solid_color_block); } .bgSubtle { background-color: var(--solid_color_block); }
.backgroundColorSubtle_onHover:hover { background-color: var(--solid_color_block); } .bgSubtle_onHover:hover { background-color: var(--solid_color_block); }
.backgroundColorSubtle2 { background-color: var(--solid_color_secondary); } .bgSecondary { background-color: var(--solid_color_secondary); }
.backgroundColorSubtle2Dark_onHover:hover { background-color: var(--solid_color_secondary-dark); } .bgSecondaryDark_onHover:hover { background-color: var(--solid_color_secondary-dark); }
.backgroundColorSecondary3 { background-color: var(--solid_color_tertiary); } .bgTertiary { background-color: var(--solid_color_tertiary); }
.backgroundColorPrimary { background-color: var(--solid_color_primary); } .bgPrimary { background-color: var(--solid_color_primary); }
.backgroundColorPrimaryOpaque { background-color: var(--solid_color_primary-opaque) } .bgPrimaryOpaque { background-color: var(--solid_color_primary-opaque) }
.backgroundColorWhite { background-color: var(--color_white); } .bgWhite { background-color: var(--color_white); }
.backgroundColorBlack { background-color: var(--color_black); } .bgBlack { background-color: var(--color_black); }
.backgroundColorBlackOpaque { background-color: var(--color_black-opaquer); } .bgBlackOpaque { background-color: var(--color_black-opaquer); }
.backgroundColorBlackOpaque_onHover:hover { background-color: var(--color_black-opaque); } .bgBlackOpaque_onHover:hover { background-color: var(--color_black-opaque); }
.backgroundColorBrand { background-color: var(--color_brand); } .bgBrand { background-color: var(--color_brand); }
.backgroundColorBrand_onHover:hover { background-color: var(--color_brand); } .bgBrand_onHover:hover { background-color: var(--color_brand); }
.backgroundColorBrandLight { background-color: var(--color_brand-light); } .bgBrandLight { background-color: var(--color_brand-light); }
.backgroundColorBrandLightOpaque { background-color: var(--color_brand-light-opaque); } .bgBrandLightOpaque { background-color: var(--color_brand-light-opaque); }
.backgroundColorBrandLightOpaque_onHover:hover { background-color: var(--color_brand-light-opaque); } .bgBrandLightOpaque_onHover:hover { background-color: var(--color_brand-light-opaque); }
.backgroundColorBrandDark { background-color: var(--color_brand-dark); } .bgBrandDark { background-color: var(--color_brand-dark); }
.backgroundColorBrandDark_onHover:hover { background-color: var(--color_brand-dark); } .bgBrandDark_onHover:hover { background-color: var(--color_brand-dark); }
.backgroundColorDanger { background-color: var(--color_red); } .bgDanger { background-color: var(--color_red); }
.backgroundColorDangerDark_onHover:hover { background-color: var(--color_red-dark); } .bgDangerDark_onHover:hover { background-color: var(--color_red-dark); }
/* */ /* */
@ -344,14 +347,15 @@ body {
/* */ /* */
.fillColorPrimary { fill: var(--text_color_primary); } .fillPrimary { fill: var(--text_color_primary); }
.fillColorSecondary { fill: var(--text_color_secondary); } .fillSecondary { fill: var(--text_color_secondary); }
.fillColorWhite { fill: var(--color_white); } .fillWhite { fill: var(--color_white); }
.fillColorWhite_onHover:hover { fill: var(--color_white); } .fillWhite_onHover:hover { fill: var(--color_white); }
.fillColorBrand { fill: var(--color_brand); } .fillBrand { fill: var(--color_brand); }
.fillColorBrand_onHover:hover { fill: var(--color_brand);} .fillBrandDark { fill: var(--color_brand-dark); }
.fillBrand_onHover:hover { fill: var(--color_brand);}
.fillColorGabPro { fill: var(--color_gold); } .fillColorGabPro { fill: var(--color_gold); }
@ -391,12 +395,12 @@ body {
.heightMax100VH { max-height: 100vh; } .heightMax100VH { max-height: 100vh; }
.heightMax80VH { max-height: 80vh; } .heightMax80VH { max-height: 80vh; }
.heightMax56PX { max-height: 56px; } .heightMax56PX { max-height: 56px; }
.heightCalc53PX { height: calc(100vh - 53px); }
.heightMin100VH { min-height: 100vh; } .heightMin100VH { min-height: 100vh; }
.heightMin50VH { min-height: 50vh; } .heightMin50VH { min-height: 50vh; }
.heightMin50PX { min-height: 50px; } .heightMin50PX { min-height: 50px; }
.height100VH { height: 100vh; }
.height100PC { height: 100%; } .height100PC { height: 100%; }
.height350PX { height: 350px; } .height350PX { height: 350px; }
.height260PX { height: 260px; } .height260PX { height: 260px; }
@ -405,7 +409,6 @@ body {
.height122PX { height: 122px; } .height122PX { height: 122px; }
.height72PX { height: 72px; } .height72PX { height: 72px; }
.height53PX { height: 53px; } .height53PX { height: 53px; }
.height50PX { height: 50px; }
.height40PX { height: 40px; } .height40PX { height: 40px; }
.height24PX { height: 24px; } .height24PX { height: 24px; }
.height22PX { height: 22px; } .height22PX { height: 22px; }
@ -418,6 +421,7 @@ body {
.width100PC { width: 100%; } .width100PC { width: 100%; }
.width50PC { width: 50%; } .width50PC { width: 50%; }
.width25PC { width: 25%; } .width25PC { width: 25%; }
.width1255PX { width: 1255px; }
.width1015PX { width: 1015px; } .width1015PX { width: 1015px; }
.width645PX { width: 645px; } .width645PX { width: 645px; }
.width340PX { width: 340px; } .width340PX { width: 340px; }
@ -429,6 +433,7 @@ body {
.width50PX { width: 50px; } .width50PX { width: 50px; }
.width20PX { width: 20px; } .width20PX { width: 20px; }
.width4PX { width: 4px; } .width4PX { width: 4px; }
.width1PX { width: 1px; }
@media (min-width: 1480px) { @media (min-width: 1480px) {
@ -507,6 +512,8 @@ body {
.width1015PX { .width1015PX {
max-width: 600px; max-width: 600px;
width: 100%; width: 100%;
margin-left: auto;
margin-right: auto;
} }
.width645PX { .width645PX {
@ -526,14 +533,14 @@ body {
.textAlignLeft { text-align: left; } .textAlignLeft { text-align: left; }
.textAlignCenter { text-align: center; } .textAlignCenter { text-align: center; }
.fontSize24PX { font-size: var(--font_size_extra_extra_large); } .fs24PX { font-size: var(--font_size_extra_extra_large); }
.fontSize19PX { font-size: var(--font_size_extra_large); } .fs19PX { font-size: var(--font_size_extra_large); }
.fontSize16PX { font-size: var(--font_size_large); } .fs16PX { font-size: var(--font_size_large); }
.fontSize15PX { font-size: var(--font_size_medium); } .fs15PX { font-size: var(--font_size_medium); }
.fontSize14PX { font-size: var(--font_size_normal); } .fs14PX { font-size: var(--font_size_normal); }
.fontSize13PX { font-size: var(--font_size_small); } .fs13PX { font-size: var(--font_size_small); }
.fontSize12PX { font-size: var(--font_size_extra_small); } .fs12PX { font-size: var(--font_size_extra_small); }
.fontSize0 { font-size: 0; } .fs0 { font-size: 0; }
.fontWeightNormal { font-weight: 400; } .fontWeightNormal { font-weight: 400; }
.fontWeightMedium { font-weight: 500; } .fontWeightMedium { font-weight: 500; }
@ -562,7 +569,7 @@ body {
margin-bottom: 10px; margin-bottom: 10px;
} }
.margin1PX { margin: 1px; } .m1PX { margin: 1px; }
.mr15 { margin-right: 15px; } .mr15 { margin-right: 15px; }
.mr10 { margin-right: 10px; } .mr10 { margin-right: 10px; }
@ -602,9 +609,12 @@ body {
.pl25 { padding-left: 25px; } .pl25 { padding-left: 25px; }
.pl15 { padding-left: 15px; } .pl15 { padding-left: 15px; }
.pl10 { padding-left: 10px; }
.pl5 { padding-left: 5px; }
.pl0 { padding-left: 0; } .pl0 { padding-left: 0; }
.pr15 { padding-right: 15px; } .pr15 { padding-right: 15px; }
.pr10 { padding-right: 10px; }
.pr5 { padding-right: 5px; } .pr5 { padding-right: 5px; }
.pr0 { padding-right: 0; } .pr0 { padding-right: 0; }
@ -618,6 +628,11 @@ body {
padding-bottom: 5px; padding-bottom: 5px;
} }
.py7 {
padding-top: 7px;
padding-bottom: 7px;
}
.py10 { .py10 {
padding-top: 10px; padding-top: 10px;
padding-bottom: 10px; padding-bottom: 10px;
@ -658,6 +673,7 @@ body {
.boxShadowNone .boxShadowBlock { .boxShadowNone .boxShadowBlock {
box-shadow: none !important; box-shadow: none !important;
border-radius: 0 !important;
} }
.boxShadowAvatarPro { .boxShadowAvatarPro {
@ -727,6 +743,19 @@ body {
visibility: hidden; visibility: hidden;
} }
.searchInput::placeholder {
color: rgba(255,255,255,0.65);
opacity: 1;
}
.searchInput:-ms-input-placeholder {
color: rgba(255,255,255,0.65);
}
.searchInput::-ms-input-placeholder {
color: rgba(255,255,255,0.65);
}
/** /**
* Rich Text Editor * Rich Text Editor
*/ */

View File

@ -2,7 +2,7 @@
class SearchService < BaseService class SearchService < BaseService
def call(query, account, limit, options = {}) def call(query, account, limit, options = {})
@query = query.strip @query = query&.strip
@account = account @account = account
@options = options @options = options
@limit = limit.to_i @limit = limit.to_i
@ -10,8 +10,10 @@ class SearchService < BaseService
@resolve = options[:resolve] || false @resolve = options[:resolve] || false
default_results.tap do |results| default_results.tap do |results|
next if @query.blank? || @limit.zero?
if url_query? if url_query?
results.merge!(url_resource_results) unless url_resource.nil? results.merge!(url_resource_results) unless url_resource.nil? || @offset.positive? || (@options[:type].present? && url_resource_symbol != @options[:type].to_sym)
elsif @query.present? elsif @query.present?
results[:accounts] = perform_accounts_search! if account_searchable? results[:accounts] = perform_accounts_search! if account_searchable?
results[:statuses] = perform_statuses_search! if full_text_searchable? results[:statuses] = perform_statuses_search! if full_text_searchable?
@ -79,7 +81,7 @@ class SearchService < BaseService
end end
def url_query? def url_query?
@options[:type].blank? && @query =~ /\Ahttps?:\/\// @resolve && @query =~ /\Ahttps?:\/\//
end end
def url_resource_results def url_resource_results