components#Image TypeScript Examples

The following examples show how to use components#Image. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: browser.test.tsx    From geist-ui with MIT License 5 votes vote down vote up
describe('Image Browser', () => {
  it('should render correctly', () => {
    const wrapper = mount(
      <Image.Browser url={link}>
        <Image src={url} />
      </Image.Browser>,
    )
    expect(() => wrapper.unmount()).not.toThrow()

    const browser = render(
      <Image.Browser url={link}>
        <Image src={url} />
      </Image.Browser>,
    )
    expect(browser).toMatchSnapshot()
  })

  it('show title when url missing', () => {
    const wrapper = mount(
      <Image.Browser title="test-title">
        <Image src={url} />
      </Image.Browser>,
    )
    expect(wrapper.find('header').text()).toContain('test-title')
  })

  it('should work correctly with full link', () => {
    const wrapper = mount(
      <Image.Browser url={link}>
        <Image src={url} />
      </Image.Browser>,
    )
    expect(wrapper.find('.link').text()).not.toContain('http')
    wrapper.setProps({ showFullLink: true })
    expect(wrapper.find('.link').text()).toContain('http')
  })

  it('show full link when url parse error', () => {
    const errorLink = 'httpsw/com'
    const wrapper = mount(
      <Image.Browser url={errorLink}>
        <Image src={url} />
      </Image.Browser>,
    )
    expect(wrapper.find('.link').text()).toContain(errorLink)
  })

  it('should work correctly when props missing', () => {
    const wrapper = mount(<Image.Browser />)
    expect(() => wrapper.unmount()).not.toThrow()
  })

  it('anchor props should be passed through', () => {
    const anchorRel = 'noreferrer'
    const wrapper = mount(
      <Image.Browser url={link} anchorProps={{ rel: anchorRel }}>
        <Image src={url} />
      </Image.Browser>,
    )
    const rel = wrapper.find('a').getDOMNode().getAttribute('rel')
    expect(rel).toEqual(anchorRel)
  })
})
Example #2
Source File: index.test.tsx    From geist-ui with MIT License 5 votes vote down vote up
describe('Image', () => {
  it('should render correctly', async () => {
    let wrapper = mount(<Image src={url} />)
    expect(wrapper).toMatchSnapshot()
    expect(() => wrapper.unmount()).not.toThrow()

    wrapper = mount(<Image src={url} width={20} height={20} />)
    wrapper.find('img').at(0).simulate('load')
    expect(wrapper).toMatchSnapshot()
    expect(() => wrapper.unmount()).not.toThrow()

    wrapper = mount(<Image src={url} width={20} height={20} disableSkeleton />)
    wrapper.find('img').at(0).simulate('load')
    expect(wrapper).toMatchSnapshot()
    expect(() => wrapper.unmount()).not.toThrow()
  })

  it('should render correctly with svg string', () => {
    let wrapper = mount(<Image src={svg} />)
    expect(wrapper).toMatchSnapshot()
    expect(() => wrapper.unmount()).not.toThrow()

    wrapper = mount(<Image src={svg} width={20} height={20} />)
    wrapper.find('img').at(0).simulate('load')
    expect(wrapper).toMatchSnapshot()
    expect(() => wrapper.unmount()).not.toThrow()

    wrapper = mount(<Image src={svg} width={20} height={20} disableSkeleton />)
    wrapper.find('img').at(0).simulate('load')
    expect(wrapper).toMatchSnapshot()
    expect(() => wrapper.unmount()).not.toThrow()
  })

  it('should work correctly with skeleton', async () => {
    let wrapper = mount(<Image src={url} width={20} height={20} />)
    expect(wrapper.find('.skeleton').length).not.toBe(0)

    wrapper = mount(<Image src={url} width={20} height={20} />)
    wrapper.find('img').at(0).simulate('load')
    await updateWrapper(wrapper)
    expect(wrapper.find('.skeleton').length).not.toBe(0)

    wrapper = mount(<Image src={url} width={20} />)
    expect(wrapper.find('.skeleton').length).toBe(0)

    mount(<Image src={url} width={20} height={20} disableSkeleton />)
    expect(wrapper.find('.skeleton').length).toBe(0)
  })

  it('should remove skeleton when timeout', async () => {
    const animation = mount(<Image src={url} width={20} height={20} maxDelay={100} />)
    const NoAnimation = mount(
      <Image src={url} width={20} height={20} maxDelay={100} disableSkeleton />,
    )
    expect(animation.find('.skeleton').length).not.toBe(0)
    await updateWrapper(animation, 300)
    await updateWrapper(NoAnimation, 300)
    expect(animation.find('.skeleton').length).toBe(0)
    expect(NoAnimation.find('.skeleton').length).toBe(0)
  })

  it('should remove skeleton when image completed', async () => {
    Object.defineProperty((global as any).Image.prototype, 'complete', {
      get() {
        return true
      },
    })
    const wrapper = mount(<Image src={url} width={20} height={20} />)
    const img = wrapper.find('img').at(0)
    img.simulate('load')
    await updateWrapper(wrapper)
    expect((img.getDOMNode() as HTMLImageElement).complete).toEqual(true)
    expect(wrapper.find('.skeleton').length).toBe(0)
  })
})
Example #3
Source File: menu.tsx    From geist-ui with MIT License 4 votes vote down vote up
Menu: React.FC<unknown> = () => {
  const router = useRouter()
  const theme = useTheme()
  const { isChinese } = useConfigs()
  const { tabbar: currentUrlTabValue, locale } = useLocale()
  const [expanded, setExpanded] = useState<boolean>(false)
  const [, setBodyHidden] = useBodyScroll(null, { delayReset: 300 })
  const isMobile = useMediaQuery('xs', { match: 'down' })
  const allSides = useMemo(() => Metadata[locale], [locale])

  useEffect(() => {
    const prefetch = async () => {
      const urls = isChinese
        ? ['/zh-cn/guide/introduction', '/zh-cn/components/text', '/zh-cn/customization']
        : ['/en-us/guide/introduction', '/en-us/components/text', '/en-us/customization']
      await Promise.all(
        urls.map(async url => {
          await router.prefetch(url)
        }),
      )
    }
    prefetch()
      .then()
      .catch(err => console.log(err))
  }, [isChinese])

  useEffect(() => {
    setBodyHidden(expanded)
  }, [expanded])

  useEffect(() => {
    if (!isMobile) {
      setExpanded(false)
    }
  }, [isMobile])

  useEffect(() => {
    const handleRouteChange = () => {
      setExpanded(false)
    }

    router.events.on('routeChangeComplete', handleRouteChange)
    return () => router.events.off('routeChangeComplete', handleRouteChange)
  }, [router.events])

  const handleTabChange = useCallback(
    (tab: string) => {
      const shouldRedirectDefaultPage = currentUrlTabValue !== tab
      if (!shouldRedirectDefaultPage) return
      const defaultPath = `/${locale}/${tab}`
      router.push(defaultPath)
    },
    [currentUrlTabValue, locale],
  )
  const [isLocked, setIsLocked] = useState<boolean>(false)

  useEffect(() => {
    const handler = () => {
      const isLocked = document.body.style.overflow === 'hidden'
      setIsLocked(last => (last !== isLocked ? isLocked : last))
    }
    const observer = new MutationObserver(mutations => {
      mutations.forEach(function (mutation) {
        if (mutation.type !== 'attributes') return
        handler()
      })
    })

    observer.observe(document.body, {
      attributes: true,
    })
    return () => {
      observer.disconnect()
    }
  }, [])

  return (
    <>
      <div className="menu-wrapper">
        <nav className="menu">
          <div className="content">
            <div className="logo">
              <NextLink href={`/${locale}`}>
                <a aria-label="Go Home">
                  <Image
                    src="/images/logo.png"
                    width="20px"
                    height="20px"
                    mr={0.5}
                    draggable={false}
                    title="Logo"
                  />
                  Geist
                </a>
              </NextLink>
            </div>

            <div className="tabs">
              <Tabs
                value={currentUrlTabValue}
                leftSpace={0}
                activeClassName="current"
                align="center"
                hideDivider
                hideBorder
                onChange={handleTabChange}>
                <Tabs.Item font="14px" label={isChinese ? '主页' : 'Home'} value="" />
                {allSides.map((tab, index) => (
                  <Tabs.Item
                    font="14px"
                    label={tab.localeName || tab.name}
                    value={tab.name}
                    key={`${tab.localeName || tab.name}-${index}`}
                  />
                ))}
              </Tabs>
            </div>

            <div className="controls">
              {isMobile ? (
                <Button
                  className="menu-toggle"
                  auto
                  type="abort"
                  onClick={() => setExpanded(!expanded)}>
                  <MenuIcon size="1.125rem" />
                </Button>
              ) : (
                <Controls />
              )}
            </div>
          </div>
        </nav>
      </div>
      <MenuMobile expanded={expanded} />

      <style jsx>{`
        .menu-wrapper {
          height: var(--geist-page-nav-height);
        }
        .menu {
          position: fixed;
          top: 0;
          left: 0;
          right: 0;
          padding-right: ${isLocked ? 'var(--geist-page-scrollbar-width)' : 0};
          height: var(--geist-page-nav-height);
          //width: 100%;
          backdrop-filter: saturate(180%) blur(5px);
          background-color: ${addColorAlpha(theme.palette.background, 0.8)};
          box-shadow: ${theme.type === 'dark'
            ? '0 0 0 1px #333'
            : '0 0 15px 0 rgba(0, 0, 0, 0.1)'};
          z-index: 999;
        }
        nav .content {
          display: flex;
          align-items: center;
          justify-content: space-between;
          max-width: 1000px;
          height: 100%;
          margin: 0 auto;
          user-select: none;
          padding: 0 ${theme.layout.gap};
        }
        .logo {
          flex: 1 1;
          display: flex;
          align-items: center;
          justify-content: flex-start;
        }
        .logo a {
          display: inline-flex;
          flex-direction: row;
          align-items: center;
          font-size: 1.125rem;
          font-weight: 500;
          color: inherit;
          height: 28px;
        }
        .logo :global(.image) {
          border: 1px solid ${theme.palette.border};
          border-radius: 2rem;
        }
        .tabs {
          flex: 1 1;
          padding: 0 ${theme.layout.gap};
        }
        .tabs :global(.content) {
          display: none;
        }
        @media only screen and (max-width: ${theme.breakpoints.xs.max}) {
          .tabs {
            display: none;
          }
        }
        .controls {
          flex: 1 1;
          display: flex;
          align-items: center;
          justify-content: flex-end;
        }
        .controls :global(.menu-toggle) {
          display: flex;
          align-items: center;
          min-width: 40px;
          height: 40px;
          padding: 0;
        }
      `}</style>
    </>
  )
}
Example #4
Source File: _app.tsx    From geist-ui with MIT License 4 votes vote down vote up
Application: NextPage<AppProps<{}>> = ({ Component, pageProps }) => {
  const theme = useTheme()
  const [themeType, setThemeType] = useState<string>()
  const [customTheme, setCustomTheme] = useState<GeistUIThemes>(theme)
  const themeChangeHandle = (theme: GeistUIThemes) => {
    setCustomTheme(theme)
    setThemeType(theme.type)
  }

  useEffect(() => {
    const theme = window.localStorage.getItem('theme')
    if (theme !== 'dark') return
    setThemeType('dark')
  }, [])
  useDomClean()

  return (
    <>
      <Head>
        <title>Geist UI - Modern and minimalist React UI library</title>
        <meta name="google" content="notranslate" />
        <meta name="twitter:creator" content="@echo_witt" />
        <meta name="referrer" content="strict-origin" />
        <meta property="og:title" content="Geist UI" />
        <meta property="og:site_name" content="Geist UI" />
        <meta property="og:url" content="https://geist-ui.dev" />
        <link rel="dns-prefetch" href="//geist-ui.dev" />
        <meta name="twitter:card" content="summary_large_image" />
        <meta name="generator" content="Geist UI" />
        <meta
          name="description"
          content="An open-source design system for building modern websites and applications."
        />
        <meta
          property="og:description"
          content="An open-source design system for building modern websites and applications."
        />
        <meta
          itemProp="image"
          property="og:image"
          content="https://user-images.githubusercontent.com/11304944/91128466-dfc96c00-e6da-11ea-8b03-a96e6b98667d.png"
        />
        <meta
          property="og:image"
          content="https://user-images.githubusercontent.com/11304944/91128466-dfc96c00-e6da-11ea-8b03-a96e6b98667d.png"
        />
        <meta
          property="twitter:image"
          content="https://user-images.githubusercontent.com/11304944/91128466-dfc96c00-e6da-11ea-8b03-a96e6b98667d.png"
        />
        <meta
          name="viewport"
          content="initial-scale=1, maximum-scale=1, minimum-scale=1, viewport-fit=cover"
        />
      </Head>
      <GeistProvider themeType={themeType} themes={[customTheme]}>
        <CssBaseline />
        <ConfigContext
          onThemeChange={themeChangeHandle}
          onThemeTypeChange={type => setThemeType(type)}>
          <Menu />
          <Search />
          <MDXProvider
            components={{
              a: HybridLink,
              img: Image,
              pre: HybridCode,
            }}>
            <Component {...pageProps} />
          </MDXProvider>
        </ConfigContext>
        <style global jsx>{`
          .tag {
            color: ${theme.palette.accents_5};
          }
          .punctuation {
            color: ${theme.palette.accents_5};
          }
          .attr-name {
            color: ${theme.palette.accents_6};
          }
          .attr-value {
            color: ${theme.palette.accents_4};
          }
          .language-javascript {
            color: ${theme.palette.accents_4};
          }
          span.class-name {
            color: ${theme.palette.warning};
          }
          span.maybe-class-name {
            color: ${theme.palette.purple};
          }
          span.token.string {
            color: ${theme.palette.accents_5};
          }
          span.token.comment {
            color: ${theme.palette.accents_3};
          }
          span.keyword {
            color: ${theme.palette.success};
          }
          span.plain-text {
            color: ${theme.palette.accents_3};
          }
          body::-webkit-scrollbar {
            width: var(--geist-page-scrollbar-width);
            background-color: ${theme.palette.accents_1};
          }
          body::-webkit-scrollbar-thumb {
            background-color: ${theme.palette.accents_2};
            border-radius: ${theme.layout.radius};
          }
          :root {
            --geist-page-nav-height: 64px;
            --geist-page-scrollbar-width: 4px;
          }
        `}</style>
      </GeistProvider>
    </>
  )
}