mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-26 17:38:36 +00:00
feat(desktop): style inline links as tinted chips
Content links read as a small primary-tinted chip instead of an underline, dropping the trailing external-link arrow. The tint is currentColor-relative, so one class carries text and fill in the same hue across every theme, and `box-decoration-break: clone` gives a wrapped link a chip per line fragment.
This commit is contained in:
parent
4dae897265
commit
6893faf472
6 changed files with 37 additions and 19 deletions
|
|
@ -510,7 +510,7 @@ export const SessionRefLink: FC<{
|
|||
|
||||
return (
|
||||
<a
|
||||
className="font-semibold text-foreground underline underline-offset-4 decoration-current/20 wrap-anywhere"
|
||||
className="link-chip font-semibold wrap-anywhere"
|
||||
href="#"
|
||||
onClick={event => {
|
||||
event.preventDefault()
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ function OpenMediaButton({ kind, path }: { kind: 'audio' | 'video'; path: string
|
|||
return (
|
||||
<span className="block">
|
||||
<button
|
||||
className="mt-2 bg-transparent text-xs font-medium text-muted-foreground underline underline-offset-4 decoration-current/20 hover:text-foreground"
|
||||
className="mt-2 link-chip bg-transparent text-xs font-medium text-muted-foreground hover:text-foreground"
|
||||
onClick={open}
|
||||
type="button"
|
||||
>
|
||||
|
|
@ -196,7 +196,7 @@ function MediaAttachment({ path }: { path: string }) {
|
|||
return (
|
||||
<span className="wrap-anywhere">
|
||||
<a
|
||||
className="font-semibold text-foreground underline underline-offset-4 decoration-current/20 wrap-anywhere"
|
||||
className="link-chip font-semibold wrap-anywhere"
|
||||
href="#"
|
||||
onClick={event => {
|
||||
event.preventDefault()
|
||||
|
|
@ -246,10 +246,7 @@ function MarkdownLink({ children, className, href, ...props }: ComponentProps<'a
|
|||
if (!target || !/^https?:\/\//i.test(target)) {
|
||||
return (
|
||||
<a
|
||||
className={cn(
|
||||
'font-semibold text-foreground underline underline-offset-4 decoration-current/20 wrap-anywhere',
|
||||
className
|
||||
)}
|
||||
className={cn('link-chip font-semibold wrap-anywhere', className)}
|
||||
href={href}
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
|
|
@ -324,7 +321,7 @@ function MarkdownImage({ className, src, alt, ...props }: ComponentProps<'img'>)
|
|||
<span className="my-2 block text-sm text-muted-foreground">
|
||||
Couldn't load {name}.{' '}
|
||||
<button
|
||||
className="bg-transparent font-medium text-foreground underline underline-offset-4 decoration-current/20 hover:text-foreground"
|
||||
className="link-chip bg-transparent font-medium text-foreground hover:text-foreground"
|
||||
onClick={open}
|
||||
type="button"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import type { ComponentProps, ElementType, FC } from 'react'
|
|||
import { memo } from 'react'
|
||||
import { Streamdown } from 'streamdown'
|
||||
|
||||
import { ExternalLink, ExternalLinkIcon } from '@/lib/external-link'
|
||||
import { ExternalLink } from '@/lib/external-link'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
// Compact markdown renderer for tool detail bodies. Same Streamdown pipeline
|
||||
|
|
@ -42,20 +42,15 @@ function tagged<T extends keyof typeof TAG_CLASSES>(Tag: T) {
|
|||
function MarkdownAnchor({ children, className, href, ...rest }: ComponentProps<'a'>) {
|
||||
if (!href || !/^https?:\/\//i.test(href)) {
|
||||
return (
|
||||
<a
|
||||
className={cn('font-medium underline underline-offset-4 decoration-current/20', className)}
|
||||
href={href}
|
||||
{...rest}
|
||||
>
|
||||
<a className={cn('link-chip font-medium', className)} href={href} {...rest}>
|
||||
{children}
|
||||
</a>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<ExternalLink className={cn('decoration-current/20', className)} href={href} showExternalIcon={false}>
|
||||
<ExternalLink className={className} href={href}>
|
||||
{children}
|
||||
<ExternalLinkIcon />
|
||||
</ExternalLink>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ export const GeneratedImage: FC<{ aspectRatio?: string; result?: unknown }> = ({
|
|||
if (failed && image) {
|
||||
return (
|
||||
<a
|
||||
className="mt-2 inline-block font-semibold text-foreground underline underline-offset-4 decoration-current/20 wrap-anywhere"
|
||||
className="mt-2 link-chip inline-block font-semibold wrap-anywhere"
|
||||
href="#"
|
||||
onClick={event => {
|
||||
event.preventDefault()
|
||||
|
|
|
|||
|
|
@ -215,14 +215,14 @@ export function ExternalLink({
|
|||
className,
|
||||
href,
|
||||
onClick,
|
||||
showExternalIcon = true,
|
||||
showExternalIcon = false,
|
||||
...rest
|
||||
}: ExternalLinkProps) {
|
||||
const target = normalizeExternalUrl(href)
|
||||
|
||||
return (
|
||||
<a
|
||||
className={cn('font-semibold text-foreground underline underline-offset-4 decoration-current/20', className)}
|
||||
className={cn('link-chip font-semibold', className)}
|
||||
href={target}
|
||||
onClick={event => {
|
||||
event.stopPropagation()
|
||||
|
|
|
|||
|
|
@ -514,6 +514,32 @@
|
|||
background: repeating-conic-gradient(currentColor 0% 25%, transparent 0% 50%) 0 0 / 0.125rem 0.125rem;
|
||||
}
|
||||
|
||||
/* Inline content links: a small tinted chip instead of an underline. Tint is
|
||||
currentColor-relative (the old `decoration-current/20` idiom), so text and
|
||||
fill share a hue on every theme from one `color` declaration. */
|
||||
.link-chip {
|
||||
--link-chip-tint: 8%;
|
||||
|
||||
/* `ch`/`em` so the chip tracks the text at any size. Block padding is
|
||||
asymmetric because an inline box's content area is ascent+descent — equal
|
||||
padding paints the glyphs high. Keep it small: `padding-block` doesn't grow
|
||||
the line box, so an over-padded chip creeps into the line above. */
|
||||
padding: 0.05ch 0.5ch 0.2ch;
|
||||
border-radius: 0.25rem;
|
||||
color: var(--dt-primary);
|
||||
background: color-mix(in srgb, currentColor var(--link-chip-tint), transparent);
|
||||
/* Explicit: the base layer underlines every `a` (see the :where(a, …) reset). */
|
||||
text-decoration: none;
|
||||
/* A wrapped link gets a chip per line fragment, not one ragged box. */
|
||||
-webkit-box-decoration-break: clone;
|
||||
box-decoration-break: clone;
|
||||
transition: background-color 0.12s ease;
|
||||
}
|
||||
|
||||
.link-chip:hover {
|
||||
--link-chip-tint: 15%;
|
||||
}
|
||||
|
||||
/* Hover-reveal suppression — the shared, declarative escape hatch.
|
||||
A collapsed pane slides in when the pointer dwells on its thin edge trigger.
|
||||
Controls that sit over that edge gutter would drag the panel in by accident.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue