Skip to content

Instantly share code, notes, and snippets.

@nderscore
Last active October 16, 2024 17:26
Show Gist options
  • Save nderscore/6c5bdd04b844414c73b9e41a738556dc to your computer and use it in GitHub Desktop.
Save nderscore/6c5bdd04b844414c73b9e41a738556dc to your computer and use it in GitHub Desktop.
Example Tamagui Solito Text Link
@nandorojo
Copy link

Thanks for sharing! Here's an updated version:

import { View } from '@/components/tamagui/View'
import { LinkCore } from 'solito/link'
import { styled, Anchor } from 'tamagui'

const StyledTextLink = styled(Anchor, {
  name: 'TextLink',
})

export const TextLink = StyledTextLink.styleable<
  Pick<React.ComponentProps<typeof LinkCore>, 'href' | 'target'>
>(({ children, href, target, ...restProps }, ref) => {
  return (
    <LinkCore
      Component={StyledTextLink}
      componentProps={restProps}
      href={href}
      ref={ref}
      target={target}
    >
      {children}
    </LinkCore>
  )
})

const LinkFrame = styled(View, {
  name: 'AnchorView',
  tag: 'a',
  accessibilityRole: 'link',
})

export const Link = LinkFrame.styleable<
  Pick<React.ComponentProps<typeof LinkCore>, 'href' | 'target'>
>(({ children, href, target, ...restProps }, ref) => {
  return (
    <LinkCore
      Component={LinkFrame}
      componentProps={restProps}
      href={href}
      ref={ref}
      target={target}
    >
      {children}
    </LinkCore>
  )
})

@nderscore
Copy link
Author

@nandorojo Ah, I haven't updated this in a while, but this is what my text link looks like these days...

It's very similar to your version, except with a workaround for external links on web (the addition of extra wrapper elements by Tamagui breaks the default click handler from next.js's Link component)

const StyledTextLink = styled(Text, {
  name: 'TextLink',
  tag: 'a',
  accessibilityRole: 'link',
});

export const TextLink = StyledTextLink.styleable<
  Pick<LinkProps, 'href' | 'target'>
>(
  (
    { href, target, children, ...props },
    ref: Ref<HTMLAnchorElement>
  ) => {
    if (isWeb && isExternalUrl(href)) {
      // special case for external links on web - render it without LinkCore
      // tamagui _dsp-contents wrapper breaks next.js external link behavior
      return (
        <StyledTextLink
          href={href}
          ref={ref}
          target={target}
          {...componentProps}
        >
          {children}
        </StyledTextLink>
      );
    }

    return (
      <LinkCore
        Component={StyledTextLink}
        href={href}
        ref={ref}
        target={target}
        componentProps={componentProps}
      >
        {children}
      </LinkCore>
    );
  }
);

const isExternalUrl = (url: {}): url is string => {
  return (
    typeof url === 'string' &&
    (url.startsWith('http://') || url.startsWith('https://'))
  );
};

@nandorojo
Copy link

Cool! Good to know. Wondering about solito/image next

@nderscore
Copy link
Author

I've been using the solito image component raw with its default styles 🤐

For most styling, a wrapper view along with the fill + resizeMode props usually suffices.

@nandorojo
Copy link

Yeah agreed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment