Skip to content

Commit

Permalink
Improved displaying of document links, especially long ones.
Browse files Browse the repository at this point in the history
  • Loading branch information
TPReal committed Oct 8, 2024
1 parent 25a8956 commit 0b8431a
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 11 deletions.
61 changes: 61 additions & 0 deletions resources/js/components/ui/ExternalLink.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import {A, AnchorProps} from "@solidjs/router";
import {createMemo, VoidComponent} from "solid-js";
import {title} from "./title";

const _Directives = typeof title;

const URL_REGEXP = /^(ftp|https?|app):\S+$/;

interface Props {
readonly link: string;
readonly linkProps?: Partial<AnchorProps>;
/** Whether to show the full URL as a hover title. Default: true */
readonly showTitle?: boolean;
/**
* Whether to allow specifying link text in link. Default: true.
* Supported variants:
* - `http://example.com link text`
* - `link text http://example.com`
* - `link text: http://example.com`
*/
readonly allowLabel?: boolean;
}

export const ExternalLink: VoidComponent<Props> = (props) => {
const linkData = createMemo(() => {
const link = props.link.trim();
const parts = link.trim().split(" ");
if (parts.length === 1 || !(props.allowLabel ?? true)) {
return {href: link, text: link};
}
const firstPart = parts[0]!;
const lastPart = parts.at(-1)!;
if (URL_REGEXP.test(lastPart)) {
const text = parts.slice(0, -1).join(" ");
return {href: lastPart, text: text.at(-1) === ":" ? text.slice(0, -1).trim() || lastPart : text};
} else if (URL_REGEXP.test(firstPart)) {
return {href: firstPart, text: parts.slice(1).join(" ")};
} else {
return {href: link, text: link};
}
});
return (
<span
use:title={
(props.showTitle ?? true)
? [<div class="wrapLinkAnywhere">{linkData().href}</div>, {delay: [1000, undefined]}]
: undefined
}
>
<A
class="line-clamp-2 wrapLinkAnywhere"
{...props.linkProps}
href={linkData().href}
target="_blank"
{...props.linkProps}
>
{linkData().text}
</A>
</span>
);
};
10 changes: 3 additions & 7 deletions resources/js/components/ui/LinksList.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {A} from "@solidjs/router";
import {VoidComponent} from "solid-js";
import {ExternalLink} from "./ExternalLink";
import {ThingsList} from "./ThingsList";

interface Props {
Expand All @@ -11,12 +11,8 @@ export const LinksList: VoidComponent<Props> = (props) => {
<div class="text-sm">
<ThingsList
things={props.links}
map={(link) => (
<A href={link} target="_blank">
{link}
</A>
)}
mode="bullets"
map={(link) => <ExternalLink link={link} />}
mode={props.links.length <= 1 ? "commas" : "bullets"}
/>
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion resources/js/components/ui/title.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
.tippy-box[data-theme~="memo"] {
@apply text-black bg-select border-solid border-memo-active;
@apply overflow-clip text-black bg-select border-solid border-memo-active;

&[data-placement^="top"] > .tippy-arrow::before {
@apply border-t-select;
Expand Down
14 changes: 11 additions & 3 deletions resources/js/features/meeting/MeetingAttendantsFields.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -693,7 +693,12 @@ export const MeetingAttendantsFields: VoidComponent<Props> = (props) => {
{
value: "none",
label: () => (
<span use:title={[translations.fieldName("clientsGroupsMode.none.desc"), {delay: 500}]}>
<span
use:title={[
translations.fieldName("clientsGroupsMode.none.desc"),
{delay: [800, undefined]},
]}
>
{translations.fieldName("clientsGroupsMode.none")}
</span>
),
Expand All @@ -710,7 +715,7 @@ export const MeetingAttendantsFields: VoidComponent<Props> = (props) => {
? "clientsGroupsMode.shared.desc"
: "clientsGroupsMode.shared.desc_no_shared_options",
),
{delay: 500},
{delay: [800, undefined]},
]}
>
{translations.fieldName(
Expand All @@ -727,7 +732,10 @@ export const MeetingAttendantsFields: VoidComponent<Props> = (props) => {
value: "separate",
label: () => (
<span
use:title={[translations.fieldName("clientsGroupsMode.separate.desc"), {delay: 500}]}
use:title={[
translations.fieldName("clientsGroupsMode.separate.desc"),
{delay: [800, undefined]},
]}
>
{translations.fieldName("clientsGroupsMode.separate")}
</span>
Expand Down
5 changes: 5 additions & 0 deletions resources/js/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -228,4 +228,9 @@ html {
@apply wrapText;
overflow-wrap: anywhere;
}

.wrapLinkAnywhere {
word-break: break-all;
overflow-wrap: anywhere;
}
}

0 comments on commit 0b8431a

Please sign in to comment.