[Glitch] Wrapstodon design QA tweaks
Port 5651900b890ba5f1c36add6080b26640c5948086 to glitch-soc Signed-off-by: Claire <claire.github-309c@sitedethib.com>
This commit is contained in:
parent
53617cef5a
commit
5e0db46b2a
@ -0,0 +1,45 @@
|
|||||||
|
import { useCallback, useRef } from 'react';
|
||||||
|
|
||||||
|
export const InterceptStatusClicks: React.FC<{
|
||||||
|
onPreventedClick: (
|
||||||
|
clickedArea: 'account' | 'post',
|
||||||
|
event: React.MouseEvent,
|
||||||
|
) => void;
|
||||||
|
children: React.ReactNode;
|
||||||
|
}> = ({ onPreventedClick, children }) => {
|
||||||
|
const wrapperRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
const handleClick = useCallback(
|
||||||
|
(e: React.MouseEvent) => {
|
||||||
|
const clickTarget = e.target as Element;
|
||||||
|
const allowedElementsSelector =
|
||||||
|
'.video-player, .audio-player, .media-gallery, .content-warning';
|
||||||
|
const allowedElements = wrapperRef.current?.querySelectorAll(
|
||||||
|
allowedElementsSelector,
|
||||||
|
);
|
||||||
|
const isTargetClickAllowed =
|
||||||
|
allowedElements &&
|
||||||
|
Array.from(allowedElements).some((element) => {
|
||||||
|
return clickTarget === element || element.contains(clickTarget);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!isTargetClickAllowed) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
|
||||||
|
const wasAccountAreaClicked = !!clickTarget.closest(
|
||||||
|
'a.status__display-name',
|
||||||
|
);
|
||||||
|
|
||||||
|
onPreventedClick(wasAccountAreaClicked ? 'account' : 'post', e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[onPreventedClick],
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div ref={wrapperRef} onClickCapture={handleClick}>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -4,10 +4,14 @@
|
|||||||
@typescript-eslint/no-unsafe-member-access,
|
@typescript-eslint/no-unsafe-member-access,
|
||||||
@typescript-eslint/no-unsafe-call */
|
@typescript-eslint/no-unsafe-call */
|
||||||
|
|
||||||
|
import type { ComponentPropsWithoutRef } from 'react';
|
||||||
|
import { useCallback } from 'react';
|
||||||
|
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
import { InterceptStatusClicks } from 'flavours/glitch/components/status/intercept_status_clicks';
|
||||||
import { StatusQuoteManager } from 'flavours/glitch/components/status_quoted';
|
import { StatusQuoteManager } from 'flavours/glitch/components/status_quoted';
|
||||||
import type { TopStatuses } from 'flavours/glitch/models/annual_report';
|
import type { TopStatuses } from 'flavours/glitch/models/annual_report';
|
||||||
import { makeGetStatus } from 'flavours/glitch/selectors';
|
import { makeGetStatus } from 'flavours/glitch/selectors';
|
||||||
@ -29,6 +33,24 @@ export const HighlightedPost: React.FC<{
|
|||||||
statusId ? getStatus(state, { id: statusId }) : undefined,
|
statusId ? getStatus(state, { id: statusId }) : undefined,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const handleClick = useCallback<
|
||||||
|
ComponentPropsWithoutRef<typeof InterceptStatusClicks>['onPreventedClick']
|
||||||
|
>(
|
||||||
|
(clickedArea) => {
|
||||||
|
const link: string =
|
||||||
|
clickedArea === 'account'
|
||||||
|
? status.getIn(['account', 'url'])
|
||||||
|
: status.get('url');
|
||||||
|
|
||||||
|
if (context === 'standalone') {
|
||||||
|
window.location.href = link;
|
||||||
|
} else {
|
||||||
|
window.open(link, '_blank');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[status, context],
|
||||||
|
);
|
||||||
|
|
||||||
if (!status) {
|
if (!status) {
|
||||||
return <div className={classNames(styles.box, styles.mostBoostedPost)} />;
|
return <div className={classNames(styles.box, styles.mostBoostedPost)} />;
|
||||||
}
|
}
|
||||||
@ -72,7 +94,9 @@ export const HighlightedPost: React.FC<{
|
|||||||
{context === 'modal' && <p>{label}</p>}
|
{context === 'modal' && <p>{label}</p>}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<StatusQuoteManager showActions={false} id={statusId} />
|
<InterceptStatusClicks onPreventedClick={handleClick}>
|
||||||
|
<StatusQuoteManager showActions={false} id={statusId} />
|
||||||
|
</InterceptStatusClicks>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -21,7 +21,8 @@ $mobile-breakpoint: 540px;
|
|||||||
scrollbar-color: var(--color-text-secondary) var(--color-bg-secondary);
|
scrollbar-color: var(--color-text-secondary) var(--color-bg-secondary);
|
||||||
|
|
||||||
@media (width < $mobile-breakpoint) {
|
@media (width < $mobile-breakpoint) {
|
||||||
padding-inline: 10px;
|
padding-top: 0;
|
||||||
|
padding-inline: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.loading-indicator .circular-progress {
|
.loading-indicator .circular-progress {
|
||||||
@ -50,37 +51,51 @@ $mobile-breakpoint: 540px;
|
|||||||
}
|
}
|
||||||
|
|
||||||
.wrapper {
|
.wrapper {
|
||||||
|
--gradient-strength: 0.4;
|
||||||
|
|
||||||
|
box-sizing: border-box;
|
||||||
position: relative;
|
position: relative;
|
||||||
max-width: 600px;
|
max-width: 600px;
|
||||||
padding: 24px;
|
padding: 24px;
|
||||||
|
padding-top: 40px;
|
||||||
contain: layout;
|
contain: layout;
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
pointer-events: auto;
|
pointer-events: all;
|
||||||
color: var(--color-text-primary);
|
color: var(--color-text-primary);
|
||||||
background: var(--color-bg-primary);
|
background: var(--color-bg-primary);
|
||||||
background:
|
background:
|
||||||
radial-gradient(at 40% 87%, #240c9a99 0, transparent 50%),
|
radial-gradient(
|
||||||
radial-gradient(at 19% 10%, #6b0c9a99 0, transparent 50%),
|
at 10% 27%,
|
||||||
radial-gradient(at 90% 27%, #9a0c8299 0, transparent 50%),
|
rgba(83, 12, 154, var(--gradient-strength)) 0,
|
||||||
radial-gradient(at 16% 95%, #1e948299 0, transparent 50%),
|
transparent 50%
|
||||||
radial-gradient(at 80% 91%, #16dae499 0, transparent 50%)
|
),
|
||||||
|
radial-gradient(
|
||||||
|
at 91% 10%,
|
||||||
|
rgba(30, 24, 223, var(--gradient-strength)) 0,
|
||||||
|
transparent 25%
|
||||||
|
),
|
||||||
|
radial-gradient(
|
||||||
|
at 10% 91%,
|
||||||
|
rgba(22, 218, 228, var(--gradient-strength)) 0,
|
||||||
|
transparent 40%
|
||||||
|
),
|
||||||
|
radial-gradient(
|
||||||
|
at 75% 87%,
|
||||||
|
rgba(37, 31, 217, var(--gradient-strength)) 0,
|
||||||
|
transparent 20%
|
||||||
|
),
|
||||||
|
radial-gradient(
|
||||||
|
at 84% 60%,
|
||||||
|
rgba(95, 30, 148, var(--gradient-strength)) 0,
|
||||||
|
transparent 40%
|
||||||
|
)
|
||||||
var(--color-bg-primary);
|
var(--color-bg-primary);
|
||||||
border-radius: 40px;
|
border-radius: 40px;
|
||||||
|
|
||||||
@media (width < $mobile-breakpoint) {
|
@media (width < $mobile-breakpoint) {
|
||||||
padding-inline: 12px;
|
padding-inline: 12px;
|
||||||
padding-bottom: 12px;
|
padding-bottom: 12px;
|
||||||
border-radius: 28px;
|
border-radius: 0;
|
||||||
}
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
inset: 0;
|
|
||||||
z-index: -1;
|
|
||||||
background: inherit;
|
|
||||||
border-radius: inherit;
|
|
||||||
filter: blur(20px);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,7 +107,7 @@ $mobile-breakpoint: 540px;
|
|||||||
font-family: silkscreen-wrapstodon, monospace;
|
font-family: silkscreen-wrapstodon, monospace;
|
||||||
font-size: 28px;
|
font-size: 28px;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
margin-bottom: 8px;
|
margin-bottom: 4px;
|
||||||
padding-inline: 40px; // Prevent overlap with close button
|
padding-inline: 40px; // Prevent overlap with close button
|
||||||
|
|
||||||
@media (width < $mobile-breakpoint) {
|
@media (width < $mobile-breakpoint) {
|
||||||
@ -116,7 +131,7 @@ $mobile-breakpoint: 540px;
|
|||||||
|
|
||||||
.box {
|
.box {
|
||||||
position: relative;
|
position: relative;
|
||||||
padding: 16px;
|
padding: 24px;
|
||||||
border-radius: 16px;
|
border-radius: 16px;
|
||||||
background: rgb(from var(--color-bg-primary) r g b / 60%);
|
background: rgb(from var(--color-bg-primary) r g b / 60%);
|
||||||
box-shadow: inset 0 0 0 1px rgb(from var(--color-text-primary) r g b / 40%);
|
box-shadow: inset 0 0 0 1px rgb(from var(--color-text-primary) r g b / 40%);
|
||||||
@ -150,7 +165,6 @@ $mobile-breakpoint: 540px;
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
padding: 16px;
|
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
text-wrap: balance;
|
text-wrap: balance;
|
||||||
@ -164,6 +178,10 @@ $mobile-breakpoint: 540px;
|
|||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
color: #c2c8ff;
|
color: #c2c8ff;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: -3px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.statLarge {
|
.statLarge {
|
||||||
@ -185,7 +203,7 @@ $mobile-breakpoint: 540px;
|
|||||||
|
|
||||||
.mostBoostedPost {
|
.mostBoostedPost {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
padding-top: 8px;
|
padding-top: 24px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -260,7 +278,7 @@ $mobile-breakpoint: 540px;
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 12px;
|
gap: 16px;
|
||||||
|
|
||||||
p {
|
p {
|
||||||
max-width: 460px;
|
max-width: 460px;
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { useCallback, useEffect, useState } from 'react';
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
import type { FC } from 'react';
|
import type { FC } from 'react';
|
||||||
|
|
||||||
import { defineMessage, useIntl } from 'react-intl';
|
import { useIntl } from 'react-intl';
|
||||||
|
|
||||||
import { useLocation } from 'react-router';
|
import { useLocation } from 'react-router';
|
||||||
|
|
||||||
@ -23,11 +23,6 @@ import { NewPosts } from './new_posts';
|
|||||||
|
|
||||||
const moduleClassNames = classNames.bind(styles);
|
const moduleClassNames = classNames.bind(styles);
|
||||||
|
|
||||||
export const shareMessage = defineMessage({
|
|
||||||
id: 'annual_report.summary.share_message',
|
|
||||||
defaultMessage: 'I got the {archetype} archetype!',
|
|
||||||
});
|
|
||||||
|
|
||||||
export const AnnualReport: FC<{ context?: 'modal' | 'standalone' }> = ({
|
export const AnnualReport: FC<{ context?: 'modal' | 'standalone' }> = ({
|
||||||
context = 'standalone',
|
context = 'standalone',
|
||||||
}) => {
|
}) => {
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import type { FC } from 'react';
|
import type { FC } from 'react';
|
||||||
|
|
||||||
import { useIntl } from 'react-intl';
|
import { defineMessages, useIntl } from 'react-intl';
|
||||||
|
|
||||||
import { resetCompose, focusCompose } from '@/flavours/glitch/actions/compose';
|
import { resetCompose, focusCompose } from '@/flavours/glitch/actions/compose';
|
||||||
import { closeModal } from '@/flavours/glitch/actions/modal';
|
import { closeModal } from '@/flavours/glitch/actions/modal';
|
||||||
@ -9,9 +9,19 @@ import { Button } from '@/flavours/glitch/components/button';
|
|||||||
import type { AnnualReport as AnnualReportData } from '@/flavours/glitch/models/annual_report';
|
import type { AnnualReport as AnnualReportData } from '@/flavours/glitch/models/annual_report';
|
||||||
import { useAppDispatch } from '@/flavours/glitch/store';
|
import { useAppDispatch } from '@/flavours/glitch/store';
|
||||||
|
|
||||||
import { shareMessage } from '.';
|
|
||||||
import { archetypeNames } from './archetype';
|
import { archetypeNames } from './archetype';
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
share_message: {
|
||||||
|
id: 'annual_report.summary.share_message',
|
||||||
|
defaultMessage: 'I got the {archetype} archetype!',
|
||||||
|
},
|
||||||
|
share_on_mastodon: {
|
||||||
|
id: 'annual_report.summary.share_on_mastodon',
|
||||||
|
defaultMessage: 'Share on Mastodon',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const ShareButton: FC<{ report: AnnualReportData }> = ({ report }) => {
|
export const ShareButton: FC<{ report: AnnualReportData }> = ({ report }) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
@ -21,7 +31,7 @@ export const ShareButton: FC<{ report: AnnualReportData }> = ({ report }) => {
|
|||||||
archetypeNames[report.data.archetype],
|
archetypeNames[report.data.archetype],
|
||||||
);
|
);
|
||||||
const shareLines = [
|
const shareLines = [
|
||||||
intl.formatMessage(shareMessage, {
|
intl.formatMessage(messages.share_message, {
|
||||||
archetype: archetypeName,
|
archetype: archetypeName,
|
||||||
}),
|
}),
|
||||||
];
|
];
|
||||||
@ -37,5 +47,10 @@ export const ShareButton: FC<{ report: AnnualReportData }> = ({ report }) => {
|
|||||||
dispatch(closeModal({ modalType: 'ANNUAL_REPORT', ignoreFocus: false }));
|
dispatch(closeModal({ modalType: 'ANNUAL_REPORT', ignoreFocus: false }));
|
||||||
}, [report, intl, dispatch]);
|
}, [report, intl, dispatch]);
|
||||||
|
|
||||||
return <Button text='Share here' onClick={handleShareClick} />;
|
return (
|
||||||
|
<Button
|
||||||
|
text={intl.formatMessage(messages.share_on_mastodon)}
|
||||||
|
onClick={handleShareClick}
|
||||||
|
/>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,7 +1,15 @@
|
|||||||
|
$mobile-breakpoint: 540px;
|
||||||
|
|
||||||
.wrapper {
|
.wrapper {
|
||||||
max-width: max-content;
|
box-sizing: border-box;
|
||||||
|
max-width: 600px;
|
||||||
margin-inline: auto;
|
margin-inline: auto;
|
||||||
padding: 40px 10px;
|
padding: 40px 10px;
|
||||||
|
|
||||||
|
@media (width < $mobile-breakpoint) {
|
||||||
|
padding-top: 0;
|
||||||
|
padding-inline: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer {
|
.footer {
|
||||||
@ -5,7 +5,7 @@ import { FormattedMessage } from 'react-intl';
|
|||||||
import { IconLogo } from '@/flavours/glitch/components/logo';
|
import { IconLogo } from '@/flavours/glitch/components/logo';
|
||||||
|
|
||||||
import { AnnualReport } from './index';
|
import { AnnualReport } from './index';
|
||||||
import classes from './shared_page.module.css';
|
import classes from './shared_page.module.scss';
|
||||||
|
|
||||||
export const WrapstodonSharedPage: FC = () => {
|
export const WrapstodonSharedPage: FC = () => {
|
||||||
return (
|
return (
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user