Skip to content
Draft

Misc #137

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion public/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
"locale": {
"en": "English",
"zh-TW": "Taiwanese Mandarin"
}
},
"openInNewTab": "Open in new tab"
}
3 changes: 2 additions & 1 deletion public/locales/zh-TW/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
"locale": {
"en": "英文",
"zh-TW": "中文"
}
},
"openInNewTab": "開啟新分頁"
}
24 changes: 18 additions & 6 deletions src/components/parser-components/external-link/external-link.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,36 @@
import React from 'react';
import React, { useId } from 'react';
import PropTypes from 'prop-types';
import { IconExternalLink } from '@tabler/icons-react';

import Tooltip from '@/components/core/tooltip';
import { useTranslation } from '@/lib/i18n';

const linkClassName =
'inline-flex items-center gap-1 px-2 py-1 rounded text-primary underline hover:text-blue-900 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary';
'inline-flex items-center text-primary underline rounded-sm hover:text-blue-900 focus-visible:outline focus-visible:outline-2 focus-visible:outline-primary';

const ExternalLink = ({ display = '', target = '', title = '', newTab = false }) => {
const anchor = (
const t = useTranslation('common');
const newTabDescriptionId = useId();

return (
<a
href={target}
{...(newTab && { target: '_blank', rel: 'noopener noreferrer' })}
{...(newTab && {
target: '_blank',
rel: 'noopener noreferrer',
'aria-describedby': newTabDescriptionId,
})}
{...(title && { title })}
className={linkClassName}
>
{display}
{newTab && <IconExternalLink size={20} aria-hidden="true" />}
{newTab && (
<span id={newTabDescriptionId} className="sr-only" aria-hidden="true">
{t('openInNewTab')}
</span>
)}
</a>
);
return title ? <Tooltip label={title}>{anchor}</Tooltip> : anchor;
};

ExternalLink.propTypes = {
Expand Down
82 changes: 33 additions & 49 deletions src/components/parser-components/image/image.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React, { useState } from 'react';
import React, { useId, useState } from 'react';
import PropTypes from 'prop-types';
import { IconExternalLink } from '@tabler/icons-react';

import Tooltip from '@/components/core/tooltip';
import { useTranslation } from '@/lib/i18n';

const useImageBroken = (source) => {
const [erroredSource, setErroredSource] = useState(null);
Expand All @@ -22,19 +22,32 @@ Img.propTypes = {
onError: PropTypes.func,
};

const LinkedImg = ({ source = '', alt = '', target = '', broken = false, onError }) => (
<a href={target} target="_blank" rel="noopener noreferrer" className="relative block">
<Img source={source} alt={alt} onError={onError} />
{!broken && (
<span
aria-hidden="true"
className="absolute top-2 left-2 flex items-center justify-center bg-white rounded p-1 text-gray-700 shadow-shadow1"
>
<IconExternalLink size={20} />
const LinkedImg = ({ source = '', alt = '', target = '', broken = false, onError }) => {
const t = useTranslation('common');
const newTabDescriptionId = useId();
return (
<a
href={target}
target="_blank"
rel="noopener noreferrer"
aria-describedby={newTabDescriptionId}
className="relative block"
>
<Img source={source} alt={alt} onError={onError} />
{!broken && (
<span
aria-hidden="true"
className="absolute top-2 left-2 flex items-center justify-center bg-white rounded p-1 text-gray-700 shadow-shadow1"
>
<IconExternalLink size={20} />
</span>
)}
<span id={newTabDescriptionId} className="sr-only" aria-hidden="true">
{t('openInNewTab')}
</span>
)}
</a>
);
</a>
);
};

LinkedImg.propTypes = {
source: PropTypes.string,
Expand All @@ -44,23 +57,6 @@ LinkedImg.propTypes = {
onError: PropTypes.func,
};

const AltTooltip = ({ alt = '', disabled = false, children }) => {
if (!alt || disabled) return children;
return (
<span className="block overflow-hidden">
<Tooltip label={alt}>
<span className="block -mt-[15px] pt-[15px]">{children}</span>
</Tooltip>
</span>
);
};

AltTooltip.propTypes = {
alt: PropTypes.string,
disabled: PropTypes.bool,
children: PropTypes.node.isRequired,
};

const Caption = ({ display = '', children }) => (
<figure>
{children}
Expand All @@ -74,12 +70,8 @@ Caption.propTypes = {
};

const Image = ({ alt = '', source = '' }) => {
const { broken, onError } = useImageBroken(source);
return (
<AltTooltip alt={alt} disabled={broken}>
<Img source={source} alt={alt} onError={onError} />
</AltTooltip>
);
const { onError } = useImageBroken(source);
return <Img source={source} alt={alt} onError={onError} />;
};

Image.propTypes = {
Expand All @@ -89,11 +81,7 @@ Image.propTypes = {

export const ImageLink = ({ alt = '', source = '', target = '' }) => {
const { broken, onError } = useImageBroken(source);
return (
<AltTooltip alt={alt} disabled={broken}>
<LinkedImg source={source} alt={alt} target={target} broken={broken} onError={onError} />
</AltTooltip>
);
return <LinkedImg source={source} alt={alt} target={target} broken={broken} onError={onError} />;
};

ImageLink.propTypes = {
Expand All @@ -103,12 +91,10 @@ ImageLink.propTypes = {
};

export const ImageDisplay = ({ alt = '', display = '', source = '' }) => {
const { broken, onError } = useImageBroken(source);
const { onError } = useImageBroken(source);
return (
<Caption display={display}>
<AltTooltip alt={alt} disabled={broken}>
<Img source={source} alt={alt} onError={onError} />
</AltTooltip>
<Img source={source} alt={alt} onError={onError} />
</Caption>
);
};
Expand All @@ -123,9 +109,7 @@ export const ImageDisplayLink = ({ alt = '', display = '', source = '', target =
const { broken, onError } = useImageBroken(source);
return (
<Caption display={display}>
<AltTooltip alt={alt} disabled={broken}>
<LinkedImg source={source} alt={alt} target={target} broken={broken} onError={onError} />
</AltTooltip>
<LinkedImg source={source} alt={alt} target={target} broken={broken} onError={onError} />
</Caption>
);
};
Expand Down
9 changes: 8 additions & 1 deletion src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,13 @@ math {
padding-left: 1.5em;
}

.right-side-preview-area table {
display: block;
width: max-content;
max-width: 100%;
overflow-x: auto;
}

.right-side-preview-area table td,
.right-side-preview-area table th {
padding: 8px;
Expand Down Expand Up @@ -99,5 +106,5 @@ math {
}

.right-side-preview-area a:not([class]) {
@apply inline-flex items-center gap-1 px-2 py-1 rounded text-primary underline hover:text-blue-900 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary;
@apply inline-flex items-center text-primary underline rounded-sm hover:text-blue-900 focus-visible:outline focus-visible:outline-2 focus-visible:outline-primary;
}
Loading