chore: update website dependencies (#357)

This commit is contained in:
Pascal Jufer 2023-09-25 00:31:45 +02:00 committed by GitHub
parent 413c8d957b
commit 37700c8700
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
32 changed files with 1370 additions and 1162 deletions

View file

@ -1,11 +1,12 @@
module.exports = { module.exports = {
root: true,
env: { env: {
es2021: true, es2022: true,
node: true, node: true,
}, },
extends: ['eslint:recommended', 'plugin:prettier/recommended'], extends: ['eslint:recommended', 'plugin:prettier/recommended'],
parserOptions: { parserOptions: {
ecmaVersion: 13, ecmaVersion: 'latest',
sourceType: 'module', sourceType: 'module',
}, },
rules: { rules: {

View file

@ -1,5 +1,4 @@
{ {
"root": true,
"extends": ["next/core-web-vitals"], "extends": ["next/core-web-vitals"],
"rules": { "rules": {
"react/no-unescaped-entities": ["off"] "react/no-unescaped-entities": ["off"]
@ -9,7 +8,7 @@
"files": ["*.js"], "files": ["*.js"],
"parser": "espree", "parser": "espree",
"parserOptions": { "parserOptions": {
"ecmaVersion": 2020 "ecmaVersion": "latest"
} }
} }
] ]

View file

@ -21,31 +21,31 @@ export function Ad() {
} }
const AdContainer = styled.div` const AdContainer = styled.div`
#carbonads { #carbonads {
margin: 24px 0 0 0; margin: 24px 0 0 0;
a { a {
text-decoration: none !important; text-decoration: none !important;
}
.carbon-wrap {
display: flex;
align-items: flex-start;
> :first-child {
margin-right: 12px;
} }
& > a > img { .carbon-wrap {
width:100px; display: flex;
height:74px; align-items: flex-start;
filter: grayscale(100%); > :first-child {
margin-right: 12px;
}
& > a > img {
width: 100px;
height: 74px;
filter: grayscale(100%);
}
}
.carbon-text {
color: var(--black-80);
font-size: 14px;
}
.carbon-poweredby {
text-align: center;
font-size: 12px;
color: var(--black-40);
} }
} }
.carbon-text {
color: var(--black-80);
font-size: 14px;
}
.carbon-poweredby {
text-align: center;
font-size: 12px;
color: var(--black-40);
}
}
`; `;

View file

@ -1,4 +1,4 @@
import styled, { keyframes } from 'styled-components'; import styled, { css, keyframes } from 'styled-components';
import useResizeObserver from 'use-resize-observer'; import useResizeObserver from 'use-resize-observer';
import { import {
FEEDBACK_LINK, FEEDBACK_LINK,
@ -14,7 +14,7 @@ export function AvailableFor() {
<> <>
<MobileHeader>Available For</MobileHeader> <MobileHeader>Available For</MobileHeader>
<AvailableForOuter> <AvailableForOuter>
<AvailableForContainer contentWidth={width || 0} ref={ref}> <AvailableForContainer $contentWidth={width || 0} ref={ref}>
<DesktopHeader>Available for</DesktopHeader> <DesktopHeader>Available for</DesktopHeader>
<a href={LIBRARY_LINKS.React} target={'_blank'} rel={'noreferrer'}> <a href={LIBRARY_LINKS.React} target={'_blank'} rel={'noreferrer'}>
<AvailableForImage <AvailableForImage
@ -112,16 +112,18 @@ const AvailableForOuter = styled.div`
padding: 0; padding: 0;
} }
`; `;
const AvailableForContainer = styled.div<{ contentWidth: number }>` const AvailableForContainer = styled.div<{ $contentWidth: number }>`
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: flex-start; justify-content: flex-start;
width: max-content; width: max-content;
--content-width: ${(props) => props.contentWidth}px; --content-width: ${(props) => props.$contentWidth}px;
${(props) => (props.contentWidth ? '&' : '&.noop')} { ${(props) =>
animation: ${AvailableForAnimation} 40s cubic-bezier(0.37, 0, 0.63, 1) props.$contentWidth &&
infinite; css`
} animation: ${AvailableForAnimation} 40s cubic-bezier(0.37, 0, 0.63, 1)
infinite;
`}
> :not(:last-child) { > :not(:last-child) {
margin-right: 30px; margin-right: 30px;
} }

View file

@ -76,4 +76,4 @@ export const CopyButton = styled(Button)`
font-weight: 700; font-weight: 700;
color: var(--black); color: var(--black);
font-family: var(--font-family) !important; font-family: var(--font-family) !important;
`; `;

View file

@ -51,7 +51,7 @@ export function ChangelogEntry({
<Text15>{moment(created_at).format('MMM DD, YYYY')}</Text15> <Text15>{moment(created_at).format('MMM DD, YYYY')}</Text15>
</TitleContainer> </TitleContainer>
</ContainerLeft> </ContainerLeft>
<EntryBody expanded={expanded}> <EntryBody $expanded={expanded}>
{body ? <MDXRemote {...body} /> : 'No changelog'} {body ? <MDXRemote {...body} /> : 'No changelog'}
{shouldExpand ? ( {shouldExpand ? (
<ExpandContainer> <ExpandContainer>
@ -103,10 +103,10 @@ const ExpandContainer = styled.div`
bottom: 16px; bottom: 16px;
right: 23px; right: 23px;
`; `;
const EntryBody = styled(Code)<{ expanded?: boolean }>` const EntryBody = styled(Code)<{ $expanded?: boolean }>`
flex: 1; flex: 1;
margin: 0; margin: 0;
max-height: ${(props) => (props.expanded ? 'none' : `${EXPAND_HEIGHT}px`)}; max-height: ${(props) => (props.$expanded ? 'none' : `${EXPAND_HEIGHT}px`)};
position: relative; position: relative;
overflow: hidden; overflow: hidden;
* { * {

View file

@ -8,9 +8,7 @@ export interface CurrentVersionProps {
export function CurrentVersion({ version }: CurrentVersionProps) { export function CurrentVersion({ version }: CurrentVersionProps) {
return ( return (
<Link href={'/docs/changelog'} passHref legacyBehavior> <Link href={'/docs/changelog'} passHref legacyBehavior>
<Container as={'a'}> <Container as={'a'}>{version}</Container>
{version}
</Container>
</Link> </Link>
); );
} }
@ -24,7 +22,9 @@ const Container = styled(Text13)`
border-radius: 200px; border-radius: 200px;
display: block; display: block;
text-decoration: none !important; text-decoration: none !important;
transition: color 0.1s linear, background 0.1s linear; transition:
color 0.1s linear,
background 0.1s linear;
&:hover { &:hover {
background: var(--black) !important; background: var(--black) !important;
color: var(--white); color: var(--white);

View file

@ -1,6 +1,5 @@
import React from 'react'; import React from 'react';
import styled from 'styled-components'; import styled from 'styled-components';
import { Button } from './Button';
import { DEFAULT_CUSTOMIZATIONS, IconListCustomizations } from './IconList'; import { DEFAULT_CUSTOMIZATIONS, IconListCustomizations } from './IconList';
import { ColorButton, ColorInput } from './Input'; import { ColorButton, ColorInput } from './Input';
import { Slider } from './Slider'; import { Slider } from './Slider';
@ -20,7 +19,7 @@ export function CustomizationEditor({
const [color, setColor] = React.useState(customizations.hexColor); const [color, setColor] = React.useState(customizations.hexColor);
const [size, setSize] = React.useState(customizations.size); const [size, setSize] = React.useState(customizations.size);
const [strokeWidth, setStrokeWidth] = React.useState( const [strokeWidth, setStrokeWidth] = React.useState(
customizations.strokeWidth customizations.strokeWidth,
); );
React.useEffect(() => { React.useEffect(() => {
setColor(customizations.hexColor); setColor(customizations.hexColor);
@ -39,60 +38,61 @@ export function CustomizationEditor({
return ( return (
<> <>
<CustomizationBox> <CustomizationBox>
<Header> <Header>
<Text15 style={{ fontWeight: 700, color: 'var(--black)' }}> <Text15 style={{ fontWeight: 700, color: 'var(--black)' }}>
Customize Customize
</Text15> </Text15>
<ResetButton onClick={() => onChange(DEFAULT_CUSTOMIZATIONS)}>Reset</ResetButton> <ResetButton onClick={() => onChange(DEFAULT_CUSTOMIZATIONS)}>
</Header> Reset
<Field> </ResetButton>
<Slider </Header>
label={'Optical Size'} <Field>
minValue={16} <Slider
maxValue={64} label={'Optical Size'}
value={[size]} minValue={16}
formatOptions={{ maximumFractionDigits: 0 }} maxValue={64}
onChange={(values) => { value={[size]}
setSize(values[0]); formatOptions={{ maximumFractionDigits: 0 }}
updateCustomizations({ size: values[0] }); onChange={(values) => {
}} setSize(values[0]);
/> updateCustomizations({ size: values[0] });
</Field> }}
<Field> />
<Slider </Field>
label={'Stroke Weight'} <Field>
minValue={0.5} <Slider
maxValue={3} label={'Stroke Weight'}
value={[strokeWidth]} minValue={0.5}
step={0.1} maxValue={3}
formatOptions={{ maximumFractionDigits: 1 }} value={[strokeWidth]}
onChange={(values) => { step={0.1}
setStrokeWidth(values[0]); formatOptions={{ maximumFractionDigits: 1 }}
updateCustomizations({ strokeWidth: values[0] }); onChange={(values) => {
}} setStrokeWidth(values[0]);
/> updateCustomizations({ strokeWidth: values[0] });
</Field> }}
<HorizontalField> />
<Text13>Color</Text13> </Field>
<ColorInput <HorizontalField>
type={'color'} <Text13>Color</Text13>
value={color} <ColorInput
onChange={(e) => { type={'color'}
setColor(e.target.value); value={color}
updateCustomizations({ hexColor: e.target.value }); onChange={(e) => {
}} setColor(e.target.value);
/> updateCustomizations({ hexColor: e.target.value });
<ColorButton /> }}
/>
</HorizontalField> <ColorButton />
</CustomizationBox> </HorizontalField>
</CustomizationBox>
</> </>
); );
} }
const CustomizationBox = styled.div` const CustomizationBox = styled.div`
background-color:var(--g7); background-color: var(--g7);
width: 84%; width: 84%;
padding: 8%; padding: 8%;
border-radius: 10px; border-radius: 10px;
@ -124,7 +124,7 @@ const ResetButton = styled(Field)`
color: var(--dark-gray); color: var(--dark-gray);
font-size: 13px; font-size: 13px;
&:hover{ &:hover {
color: var(--black); color: var(--black);
cursor: pointer; cursor: pointer;
} }

View file

@ -24,7 +24,7 @@ export function DocumentationNavigation({
normalized === item.path || normalized === item.path ||
item.children?.some((child) => { item.children?.some((child) => {
return activePath.startsWith( return activePath.startsWith(
[item.path, child.path].filter(Boolean).join('/') [item.path, child.path].filter(Boolean).join('/'),
); );
}) })
); );
@ -51,12 +51,12 @@ export function DocumentationNavigation({
}); });
}} }}
> >
<HeaderItemIcon active={active}> <HeaderItemIcon $active={active}>
<NavArrowUp /> <NavArrowUp />
</HeaderItemIcon> </HeaderItemIcon>
{documentationItem.title} {documentationItem.title}
</HeaderItem> </HeaderItem>
<ChildrenContainer expanded={active}> <ChildrenContainer $expanded={active}>
<DocumentationNavigation <DocumentationNavigation
documentationItems={documentationItem.children} documentationItems={documentationItem.children}
pathPrefix={[ pathPrefix={[
@ -75,7 +75,7 @@ export function DocumentationNavigation({
legacyBehavior legacyBehavior
key={documentationItem.path} key={documentationItem.path}
> >
<NavigationItem as={'a'} active={activePath === path}> <NavigationItem as={'a'} $active={activePath === path}>
<span>{documentationItem.title}</span> <span>{documentationItem.title}</span>
{documentationItem.label ? ( {documentationItem.label ? (
<NavigationItemLabel> <NavigationItemLabel>
@ -91,10 +91,10 @@ export function DocumentationNavigation({
); );
} }
const HeaderItemIcon = styled.div<{ active?: boolean }>` const HeaderItemIcon = styled.div<{ $active?: boolean }>`
font-size: 13px; font-size: 13px;
transition: transform 0.25s linear; transition: transform 0.25s linear;
transform: rotate(${(props) => (props.active ? 180 : 0)}deg); transform: rotate(${(props) => (props.$active ? 180 : 0)}deg);
margin-right: 7px; margin-right: 7px;
position: relative; position: relative;
top: 6px; top: 6px;
@ -105,8 +105,8 @@ const HeaderItemIcon = styled.div<{ active?: boolean }>`
display: none; display: none;
} }
`; `;
const ChildrenContainer = styled.div<{ expanded?: boolean }>` const ChildrenContainer = styled.div<{ $expanded?: boolean }>`
display: ${(props) => (props.expanded ? 'block' : 'none')}; display: ${(props) => (props.$expanded ? 'block' : 'none')};
${media.lg} { ${media.lg} {
display: block; display: block;
} }
@ -129,9 +129,11 @@ const HeaderItem = styled.div`
} }
} }
`; `;
const NavigationItem = styled.div<{ active?: boolean }>` const NavigationItem = styled.div<{ $active?: boolean }>`
padding: 12px 45px 12px 75px; padding: 12px 45px 12px 75px;
transition: background 0.1s linear, color 0.1s linear; transition:
background 0.1s linear,
color 0.1s linear;
font-weight: 500; font-weight: 500;
font-size: 16px; font-size: 16px;
line-height: 14.5px; line-height: 14.5px;
@ -147,11 +149,11 @@ const NavigationItem = styled.div<{ active?: boolean }>`
margin-right: 14px; margin-right: 14px;
} }
&:hover, &:hover,
${(props) => (props.active ? '&' : '&.noop')} { ${(props) => (props.$active ? '&' : '&.noop')} {
color: var(--g0); color: var(--g0);
text-decoration: underline; text-decoration: underline;
} }
${(props) => (props.active ? 'span' : '&.noop')} { ${(props) => (props.$active ? 'span' : '&.noop')} {
font-weight: 700; font-weight: 700;
} }
${media.lg} { ${media.lg} {

View file

@ -18,7 +18,7 @@ export function Explore({ allIcons }: ExploreProps) {
return ( return (
<Container> <Container>
<Left> <Left>
<FilterContainer isMobile> <FilterContainer $isMobile>
<FiltersEditor filters={filters} onChange={setFilters} /> <FiltersEditor filters={filters} onChange={setFilters} />
</FilterContainer> </FilterContainer>
<IconoirProvider <IconoirProvider
@ -76,8 +76,8 @@ const Right = styled.div`
z-index: 1; z-index: 1;
} }
`; `;
const FilterContainer = styled.div<{ isMobile?: boolean }>` const FilterContainer = styled.div<{ $isMobile?: boolean }>`
display: ${(props) => (props.isMobile ? 'block' : 'none')}; display: ${(props) => (props.$isMobile ? 'block' : 'none')};
margin-bottom: 40px; margin-bottom: 40px;
position: sticky; position: sticky;
top: 20px; top: 20px;
@ -86,7 +86,7 @@ const FilterContainer = styled.div<{ isMobile?: boolean }>`
${media.md} { ${media.md} {
position: relative; position: relative;
top: 0; top: 0;
display: ${(props) => (props.isMobile ? 'none' : 'block')}; display: ${(props) => (props.$isMobile ? 'none' : 'block')};
margin-bottom: 10px; margin-bottom: 10px;
} }
`; `;

View file

@ -1,13 +1,18 @@
import { PeaceHand } from 'iconoir-react'; import { PeaceHand } from 'iconoir-react';
import styled from 'styled-components'; import styled from 'styled-components';
import { LICENSE_LINK } from '../lib/constants'; import {
GITHUB_LINK,
ISSUE_LINK,
LICENSE_LINK,
PRIVACY_LINK,
SUPPORT_LINK,
} from '../lib/constants';
import { Logo, LogoContainer, LogoIcon } from './Header'; import { Logo, LogoContainer, LogoIcon } from './Header';
import { NavigationItemContainer } from './NavigationItem';
import { Text13, Text17 } from './Typography'; import { Text13, Text17 } from './Typography';
export interface FooterCategoryProps { export interface FooterCategoryProps {
category: string; category: string;
links: { name: string, url: string }[]; links: { name: string; url: string }[];
} }
function FooterCategory({ category, links }: FooterCategoryProps) { function FooterCategory({ category, links }: FooterCategoryProps) {
return ( return (
@ -15,7 +20,9 @@ function FooterCategory({ category, links }: FooterCategoryProps) {
<FooterCategoryTitle>{category}</FooterCategoryTitle> <FooterCategoryTitle>{category}</FooterCategoryTitle>
<FooterCategoryLinks> <FooterCategoryLinks>
{links.map((link) => ( {links.map((link) => (
<FooterCategoryLink key={link.url} href={link.url}>{link.name}</FooterCategoryLink> <FooterCategoryLink key={link.url} href={link.url}>
{link.name}
</FooterCategoryLink>
))} ))}
</FooterCategoryLinks> </FooterCategoryLinks>
</FooterCategoryContainer> </FooterCategoryContainer>
@ -31,29 +38,62 @@ export function Footer() {
<Logo src={'/iconoir-logo.svg'} alt={'Iconoir Logo'} /> <Logo src={'/iconoir-logo.svg'} alt={'Iconoir Logo'} />
</LogoContainer> </LogoContainer>
<FooterCategories> <FooterCategories>
<FooterCategory category={'Project'} links={[ <FooterCategory
{ name: 'Our Mission', url:'/support' }, category={'Project'}
{ name: 'Contribute', url:'/docs/contributing' }, links={[
{ name: 'Donate', url:'https://opencollective.com/iconoir/donate' } { name: 'Our Mission', url: '/support' },
]} /> { name: 'Contribute', url: '/docs/contributing' },
<FooterCategory category={'Support'} links={[ {
{ name: 'License', url:'https://github.com/iconoir-icons/iconoir/blob/main/LICENSE' }, name: 'Donate',
{ name: 'GitHub Repository', url:'https://github.com/iconoir-icons/iconoir' }, url: SUPPORT_LINK,
{ name: 'File a Request', url:'https://github.com/iconoir-icons/iconoir/issues/new/choose' } },
]} /> ]}
<FooterCategory category={'Developers'} links={[ />
{ name: 'Changelog',url:'/docs/changelog' }, <FooterCategory
{ name: 'React and React Native', url:'/docs/packages/iconoir-react' }, category={'Support'}
{ name: 'Flutter', url:'/docs/packages/iconoir-flutter'} , links={[
{ name: 'Framer and Figma', url:'/docs/packages/framer' }, {
{ name: 'CSS', url:'/docs/packages/css' } name: 'License',
]} /> url: LICENSE_LINK,
},
{
name: 'GitHub Repository',
url: GITHUB_LINK,
},
{
name: 'File a Request',
url: ISSUE_LINK,
},
]}
/>
<FooterCategory
category={'Developers'}
links={[
{ name: 'Changelog', url: '/docs/changelog' },
{
name: 'React and React Native',
url: '/docs/packages/iconoir-react',
},
{ name: 'Flutter', url: '/docs/packages/iconoir-flutter' },
{ name: 'Framer and Figma', url: '/docs/packages/framer' },
{ name: 'CSS', url: '/docs/packages/css' },
]}
/>
</FooterCategories> </FooterCategories>
<FooterEnd> <FooterEnd>
<Text13 style={{ fontWeight: 400 }}>Parts of this content are &copy;2020-2023 by individual Iconoir contributors. Content available under a <a href={'https://github.com/iconoir-icons/iconoir/blob/main/LICENSE'} target={'_blank'} rel={'noreferrer'}>MIT License</a>.</Text13> <Text13 style={{ fontWeight: 400 }}>
<Text13 style={{ fontWeight: 400 }}><a href={'https://www.freeprivacypolicy.com/live/ba00d743-a0cd-44f8-8cb5-6f58911db0fb'} target={'_blank'} rel={'noreferrer'}>Privacy</a></Text13> Parts of this content are &copy;2020-2023 by individual Iconoir
contributors. Content available under a{' '}
<a href={LICENSE_LINK} target={'_blank'} rel={'noreferrer'}>
MIT License
</a>
.
</Text13>
<Text13 style={{ fontWeight: 400 }}>
<a href={PRIVACY_LINK} target={'_blank'} rel={'noreferrer'}>
Privacy
</a>
</Text13>
</FooterEnd> </FooterEnd>
</Container> </Container>
); );
@ -94,9 +134,7 @@ const FooterCategoryTitle = styled(Text17)`
display: block; display: block;
color: var(--g0); color: var(--g0);
`; `;
const FooterCategoryLinks = styled.div` const FooterCategoryLinks = styled.div``;
`;
const FooterCategoryLink = styled.a` const FooterCategoryLink = styled.a`
display: block; display: block;
font-size: 17px; font-size: 17px;
@ -104,7 +142,7 @@ const FooterCategoryLink = styled.a`
width: fit-content; width: fit-content;
margin-bottom: 12px; margin-bottom: 12px;
text-decoration: none; text-decoration: none;
&:hover{ &:hover {
text-decoration: underline; text-decoration: underline;
color: var(--g0); color: var(--g0);
} }

View file

@ -1,12 +1,12 @@
import { Cancel, Heart, Menu } from 'iconoir-react'; import { Cancel, Heart, Menu } from 'iconoir-react';
import Link from 'next/link'; import Link from 'next/link';
import React from 'react'; import React from 'react';
import styled from 'styled-components'; import styled, { css } from 'styled-components';
import { AnimatedSvg } from './AnimatedSvg'; import { AnimatedSvg } from './AnimatedSvg';
import { ResetButton } from './Button'; import { ResetButton } from './Button';
import { SHARE_LINK } from '../lib/constants'; import { SHARE_LINK } from '../lib/constants';
import { CurrentVersion } from './CurrentVersion'; import { CurrentVersion } from './CurrentVersion';
import { NavigationItem, NavigationItemContainer } from './NavigationItem'; import { NavigationItem } from './NavigationItem';
import { media } from '../lib/responsive'; import { media } from '../lib/responsive';
import { Text15 } from './Typography'; import { Text15 } from './Typography';
@ -29,13 +29,13 @@ export function Header({ currentVersion }: HeaderProps) {
<CurrentVersion version={currentVersion} /> <CurrentVersion version={currentVersion} />
</HeaderLeft> </HeaderLeft>
<HeaderCenter> <HeaderCenter>
<MobileMenuContainer visible={menuVisible}> <MobileMenuContainer $visible={menuVisible}>
<NavigationItem href={'/'}>Icons</NavigationItem> <NavigationItem href={'/'}>Icons</NavigationItem>
<NavigationItem href={'/docs'}>Documentation</NavigationItem> <NavigationItem href={'/docs'}>Documentation</NavigationItem>
<NavigationItem href={'/support'} style={{ marginRight: 0 }}> <NavigationItem href={'/support'} style={{ marginRight: 0 }}>
Donate &mdash; Our Mission Donate &mdash; Our Mission
</NavigationItem> </NavigationItem>
<BuiltWith isMobile> <BuiltWith $isMobile>
Share with <Heart width={'1em'} height={'1em'} /> on{' '} Share with <Heart width={'1em'} height={'1em'} /> on{' '}
<a href={SHARE_LINK} target={'_blank'} rel={'noreferrer'}> <a href={SHARE_LINK} target={'_blank'} rel={'noreferrer'}>
Twitter Twitter
@ -64,7 +64,7 @@ export const LogoContainer = styled.div`
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
transition: 0.1s; transition: 0.1s;
&:hover{ &:hover {
scale: 1.1; scale: 1.1;
transition: 0.2s; transition: 0.2s;
} }
@ -84,7 +84,7 @@ const MobileMenuButton = styled(ResetButton)`
display: none; display: none;
} }
`; `;
const MobileMenuContainer = styled.div<{ visible?: boolean }>` const MobileMenuContainer = styled.div<{ $visible?: boolean }>`
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
@ -92,7 +92,9 @@ const MobileMenuContainer = styled.div<{ visible?: boolean }>`
z-index: 100; z-index: 100;
background: white; background: white;
padding-top: 100px; padding-top: 100px;
transition: transform 0.5s cubic-bezier(0.16, 1, 0.3, 1), opacity 0.25s linear; transition:
transform 0.5s cubic-bezier(0.16, 1, 0.3, 1),
opacity 0.25s linear;
box-shadow: 0px 4px 20px rgba(0, 0, 0, 0.1); box-shadow: 0px 4px 20px rgba(0, 0, 0, 0.1);
transform: translateY(-100%); transform: translateY(-100%);
pointer-events: none; pointer-events: none;
@ -100,11 +102,13 @@ const MobileMenuContainer = styled.div<{ visible?: boolean }>`
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: stretch; align-items: stretch;
${(props) => (props.visible ? '&' : '&.noop')} { ${(props) =>
pointer-events: all; props.$visible &&
transform: translateY(0); css`
opacity: 1; pointer-events: all;
} transform: translateY(0);
opacity: 1;
`}
${media.lg} { ${media.lg} {
background: none; background: none;
padding-top: 0; padding-top: 0;
@ -161,10 +165,10 @@ export const LogoIcon = styled.div`
height: 36px; height: 36px;
} }
`; `;
const BuiltWith = styled(Text15)<{ isMobile?: boolean }>` const BuiltWith = styled(Text15)<{ $isMobile?: boolean }>`
display: ${(props) => (props.isMobile ? 'flex' : 'none')}; display: ${(props) => (props.$isMobile ? 'flex' : 'none')};
${media.lg} { ${media.lg} {
display: ${(props) => (props.isMobile ? 'none' : 'flex')}; display: ${(props) => (props.$isMobile ? 'none' : 'flex')};
} }
align-items: center; align-items: center;
justify-content: center; justify-content: center;

View file

@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import styled from 'styled-components'; import styled from 'styled-components';
import { media } from '../lib/responsive'; import { media } from '../lib/responsive';
import {useRef, useEffect} from 'react'; import { useRef, useEffect } from 'react';
export interface HeaderBackgroundProps { export interface HeaderBackgroundProps {
children: React.ReactElement; children: React.ReactElement;
@ -12,14 +12,20 @@ export function HeaderBackground({ children }: HeaderBackgroundProps) {
useEffect(() => { useEffect(() => {
if (!parallaxRef.current) return; if (!parallaxRef.current) return;
const parallaxElements = parallaxRef.current.querySelectorAll('[data-parallax-factor]'); const parallaxElements = parallaxRef.current.querySelectorAll(
'[data-parallax-factor]',
);
const handleMouseMove = (event: MouseEvent) => { const handleMouseMove = (event: MouseEvent) => {
const x = event.clientX / window.innerWidth; const x = event.clientX / window.innerWidth;
const y = event.clientY / window.innerHeight; const y = event.clientY / window.innerHeight;
parallaxElements.forEach((el) => { parallaxElements.forEach((el) => {
const factor = parseFloat(el.getAttribute('data-parallax-factor') || '1'); const factor = parseFloat(
(el as HTMLElement).style.transform = `translate3d(${x * factor * 40}px, ${y * factor * 80}px, 0)`; el.getAttribute('data-parallax-factor') || '1',
);
(el as HTMLElement).style.transform = `translate3d(${
x * factor * 40
}px, ${y * factor * 80}px, 0)`;
}); });
}; };
@ -29,15 +35,14 @@ export function HeaderBackground({ children }: HeaderBackgroundProps) {
document.removeEventListener('mousemove', handleMouseMove); document.removeEventListener('mousemove', handleMouseMove);
}; };
}, []); }, []);
return ( return (
<HeaderContainer ref={parallaxRef}> <HeaderContainer ref={parallaxRef}>
<FloatingIconCellar data-parallax-factor="0.75"/> <FloatingIconCellar data-parallax-factor="0.75" />
<FloatingIconPay data-parallax-factor="1.5"/> <FloatingIconPay data-parallax-factor="1.5" />
<FloatingFaceID data-parallax-factor="0.5"/> <FloatingFaceID data-parallax-factor="0.5" />
<FloatingCommand data-parallax-factor="1.25"/> <FloatingCommand data-parallax-factor="1.25" />
<FloatingFill data-parallax-factor="2"/> <FloatingFill data-parallax-factor="2" />
{children} {children}
</HeaderContainer> </HeaderContainer>
); );
@ -62,61 +67,61 @@ const FloatingIcon = styled.div`
`; `;
const FloatingIconCellar = styled(FloatingIcon)` const FloatingIconCellar = styled(FloatingIcon)`
-webkit-transform: rotate(6deg); -webkit-transform: rotate(6deg);
-moz-transform: rotate(6deg); -moz-transform: rotate(6deg);
top: -120px; top: -120px;
right: 0px; right: 0px;
width:200px; width: 200px;
height:200px; height: 200px;
background-image: url(/cellar.gif); background-image: url(/cellar.gif);
background-size:70%; background-size: 70%;
${media.lg} { ${media.lg} {
} }
`; `;
const FloatingIconPay = styled(FloatingIcon)` const FloatingIconPay = styled(FloatingIcon)`
-webkit-transform: rotate(18deg); -webkit-transform: rotate(18deg);
-moz-transform: rotate(18deg); -moz-transform: rotate(18deg);
top: -50px; top: -50px;
right: -100px; right: -100px;
width:130px; width: 130px;
height:130px; height: 130px;
background-image: url(/pay-bitcoin.gif); background-image: url(/pay-bitcoin.gif);
background-size:70%; background-size: 70%;
${media.lg} { ${media.lg} {
} }
`; `;
const FloatingFaceID = styled(FloatingIcon)` const FloatingFaceID = styled(FloatingIcon)`
-webkit-transform: rotate(6deg); -webkit-transform: rotate(6deg);
-moz-transform: rotate(6deg); -moz-transform: rotate(6deg);
top: -130px; top: -130px;
right: 380px; right: 380px;
width:110px; width: 110px;
height:110px; height: 110px;
background-image: url(/face-id.gif); background-image: url(/face-id.gif);
background-size:70%; background-size: 70%;
${media.lg} { ${media.lg} {
} }
`; `;
const FloatingCommand = styled(FloatingIcon)` const FloatingCommand = styled(FloatingIcon)`
-webkit-transform: rotate(-7deg); -webkit-transform: rotate(-7deg);
-moz-transform: rotate(-7deg); -moz-transform: rotate(-7deg);
top: -94px; top: -94px;
left: 150px; left: 150px;
width:110px; width: 110px;
height:110px; height: 110px;
background-image: url(/command.gif); background-image: url(/command.gif);
background-size:70%; background-size: 70%;
${media.lg} { ${media.lg} {
} }
`; `;
const FloatingFill = styled(FloatingIcon)` const FloatingFill = styled(FloatingIcon)`
-webkit-transform: rotate(-14deg); -webkit-transform: rotate(-14deg);
-moz-transform: rotate(-14deg); -moz-transform: rotate(-14deg);
top: -64px; top: -64px;
left: -75px; left: -75px;
width:110px; width: 110px;
height:110px; height: 110px;
background-image: url(/fill.gif); background-image: url(/fill.gif);
background-size:70%; background-size: 70%;
${media.lg} { ${media.lg} {
} }
`; `;

View file

@ -1,22 +1,15 @@
import React from 'react'; import React from 'react';
import styled from 'styled-components'; import styled from 'styled-components';
import { media } from '../lib/responsive';
import {useRef, useEffect} from 'react';
export interface HeaderSecondaryProps { export interface HeaderSecondaryProps {
children: React.ReactElement; children: React.ReactElement;
} }
export function HeaderSecondary({ children }: HeaderSecondaryProps) { export function HeaderSecondary({ children }: HeaderSecondaryProps) {
return <HeaderContainer>{children}</HeaderContainer>;
return (
<HeaderContainer>
{children}
</HeaderContainer>
);
} }
const HeaderContainer = styled.div` const HeaderContainer = styled.div`
position: relative; position: relative;
width: fit-content; width: fit-content;
margin: auto; margin: auto;
`; `;

View file

@ -9,14 +9,14 @@ const HEADER = '<?xml version="1.0" encoding="UTF-8"?>';
function bakeSvg( function bakeSvg(
svgString: string, svgString: string,
color: string, color: string,
strokeWidth: string | number strokeWidth: string | number,
) { ) {
return ( return (
HEADER + HEADER +
svgString svgString
.replace( .replace(
/stroke="currentColor"/g, /stroke="currentColor"/g,
`stroke="currentColor" stroke-width="${strokeWidth}"` `stroke="currentColor" stroke-width="${strokeWidth}"`,
) )
.replace(/currentColor/g, color) .replace(/currentColor/g, color)
); );
@ -36,7 +36,7 @@ export function Icon({ iconWidth, icon }: IconProps) {
React.useEffect(() => { React.useEffect(() => {
setSupportsClipboard( setSupportsClipboard(
typeof window !== 'undefined' && typeof window !== 'undefined' &&
typeof window?.navigator?.clipboard?.writeText !== 'undefined' typeof window?.navigator?.clipboard?.writeText !== 'undefined',
); );
}, []); }, []);
React.useEffect(() => { React.useEffect(() => {
@ -44,7 +44,7 @@ export function Icon({ iconWidth, icon }: IconProps) {
htmlContentsRef.current = bakeSvg( htmlContentsRef.current = bakeSvg(
iconContainerRef.current.innerHTML, iconContainerRef.current.innerHTML,
iconContext.color || DEFAULT_CUSTOMIZATIONS.hexColor, iconContext.color || DEFAULT_CUSTOMIZATIONS.hexColor,
iconContext.strokeWidth || DEFAULT_CUSTOMIZATIONS.strokeWidth iconContext.strokeWidth || DEFAULT_CUSTOMIZATIONS.strokeWidth,
); );
} }
}, [iconContext, supportsClipboard]); }, [iconContext, supportsClipboard]);
@ -54,13 +54,13 @@ export function Icon({ iconWidth, icon }: IconProps) {
(iconContainerRef.current as unknown as HTMLAnchorElement); (iconContainerRef.current as unknown as HTMLAnchorElement);
if (element) { if (element) {
element.href = `data:image/svg+xml;base64,${btoa( element.href = `data:image/svg+xml;base64,${btoa(
htmlContentsRef.current htmlContentsRef.current,
)}`; )}`;
} }
}, [iconContext, supportsClipboard]); }, [iconContext, supportsClipboard]);
return ( return (
<div className={'icon-container'}> <div className={'icon-container'}>
<BorderContainer iconWidth={iconWidth}> <BorderContainer $iconWidth={iconWidth}>
<IconContainer <IconContainer
ref={iconContainerRef} ref={iconContainerRef}
{...((supportsClipboard {...((supportsClipboard
@ -76,10 +76,10 @@ export function Icon({ iconWidth, icon }: IconProps) {
</IconContainer> </IconContainer>
{supportsClipboard ? ( {supportsClipboard ? (
<HoverContainer> <HoverContainer>
<CornerBR/> <CornerBR />
<CornerTR/> <CornerTR />
<CornerBL/> <CornerBL />
<CornerTL/> <CornerTL />
<HoverButton <HoverButton
onClick={() => { onClick={() => {
if (htmlContentsRef.current) { if (htmlContentsRef.current) {
@ -108,7 +108,7 @@ export function Icon({ iconWidth, icon }: IconProps) {
</HoverContainer> </HoverContainer>
) : null} ) : null}
</BorderContainer> </BorderContainer>
<Subtitle iconWidth={iconWidth} title={icon.filename}> <Subtitle $iconWidth={iconWidth} title={icon.filename}>
{icon.filename} {icon.filename}
</Subtitle> </Subtitle>
</div> </div>
@ -124,31 +124,30 @@ const Overlay = styled.div`
height: 8px; height: 8px;
`; `;
const CornerBR = styled(Overlay)` const CornerBR = styled(Overlay)`
bottom: -6px; bottom: -6px;
right: -6px; right: -6px;
z-index: 999; z-index: 999;
`; `;
const CornerTR = styled(Overlay)` const CornerTR = styled(Overlay)`
top: -6px; top: -6px;
right: -6px; right: -6px;
`; `;
const CornerBL = styled(Overlay)` const CornerBL = styled(Overlay)`
bottom: -6px; bottom: -6px;
left: -6px; left: -6px;
`; `;
const CornerTL = styled(Overlay)` const CornerTL = styled(Overlay)`
top: -6px; top: -6px;
left: -6px; left: -6px;
`; `;
const HoverContainer = styled.div<{ supportsCopy?: boolean }>` const HoverContainer = styled.div`
position: absolute; position: absolute;
display: ${(props) => (props.supportsCopy ? 'block' : 'none')};
inset: 0; inset: 0;
display: flex; display: flex;
align-items: stretch; align-items: stretch;
justify-content: stretch; justify-content: stretch;
flex-direction: column; flex-direction: column;
transform: translateZ(0px); // Safari Fix transform: translateZ(0px); // Safari Fix
transition: opacity 0.1s linear; transition: opacity 0.1s linear;
opacity: 0; opacity: 0;
@ -175,8 +174,8 @@ const HoverButton = styled(ResetButton)`
color: var(--white); color: var(--white);
} }
`; `;
const BorderContainer = styled.div<{ iconWidth: number }>` const BorderContainer = styled.div<{ $iconWidth: number }>`
width: ${(props) => props.iconWidth}px; width: ${(props) => props.$iconWidth}px;
box-sizing: border-box; box-sizing: border-box;
padding-bottom: 100%; padding-bottom: 100%;
position: relative; position: relative;
@ -198,7 +197,7 @@ const IconContainer = styled.div`
align-items: center; align-items: center;
justify-content: center; justify-content: center;
`; `;
const Subtitle = styled.div<{ iconWidth: number }>` const Subtitle = styled.div<{ $iconWidth: number }>`
font-size: 11px; font-size: 11px;
font-weight: 500; font-weight: 500;
line-height: 14.74px; line-height: 14.74px;
@ -207,5 +206,5 @@ const Subtitle = styled.div<{ iconWidth: number }>`
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
width: ${(props) => props.iconWidth}px; width: ${(props) => props.$iconWidth}px;
`; `;

View file

@ -41,7 +41,7 @@ function normalizeString(s: string) {
function filterIcons(allIcons: Icon[], filters: IconListFilters): Icon[] { function filterIcons(allIcons: Icon[], filters: IconListFilters): Icon[] {
if (filters.search) { if (filters.search) {
const normalSearch = normalizeString(filters.search!); const normalSearch = normalizeString(filters.search!);
let result = allIcons let result = allIcons;
for (const term of normalSearch.split(' ')) { for (const term of normalSearch.split(' ')) {
result = result.filter((icon) => { result = result.filter((icon) => {
return ( return (
@ -49,7 +49,7 @@ function filterIcons(allIcons: Icon[], filters: IconListFilters): Icon[] {
normalizeString(icon.category).includes(term) || normalizeString(icon.category).includes(term) ||
icon.tags.some((tag) => normalizeString(tag).includes(term)) icon.tags.some((tag) => normalizeString(tag).includes(term))
); );
}) });
} }
return result; return result;
} else return allIcons; } else return allIcons;
@ -69,7 +69,7 @@ function isCategoryRow(iconRow: IconRow): iconRow is IconCategoryRow {
function getRowsFromIcons( function getRowsFromIcons(
filteredIcons: Icon[], filteredIcons: Icon[],
iconsPerRow: number iconsPerRow: number,
): IconRow[] { ): IconRow[] {
const categoryGroups: Record<string, Icon[]> = {}; const categoryGroups: Record<string, Icon[]> = {};
for (const icon of filteredIcons) { for (const icon of filteredIcons) {
@ -199,6 +199,6 @@ const Row = React.memo(
return <IconsRow icons={row.icons} style={style} iconWidth={iconWidth} />; return <IconsRow icons={row.icons} style={style} iconWidth={iconWidth} />;
} }
}, },
areEqual areEqual,
); );
Row.displayName = 'Row'; Row.displayName = 'Row';

View file

@ -31,11 +31,11 @@ export const Input = styled(ResetInput)`
font-weight: 500; font-weight: 500;
color: var(--black); color: var(--black);
border: solid 1px var(--g6); border: solid 1px var(--g6);
&:hover{ &:hover {
border: solid 2px var(--g0); border: solid 2px var(--g0);
} }
&:focus{ &:focus {
border: solid 2px var(--g0); border: solid 2px var(--g0);
} }
`; `;
@ -51,7 +51,7 @@ export const LargeInput = styled(Input)`
box-sizing: border-box; box-sizing: border-box;
outline: none; outline: none;
transition: 0.2s; transition: 0.2s;
&:hover{ &:hover {
transform: scale(1.02); transform: scale(1.02);
} }
`; `;
@ -65,7 +65,7 @@ export const ColorButton = styled.div`
right: 20px; right: 20px;
position: absolute; position: absolute;
pointer-events: none; pointer-events: none;
&:hover{ &:hover {
transition: 0.2s; transition: 0.2s;
scale: 1.2; scale: 1.2;
} }
@ -82,10 +82,10 @@ export const ColorInput = styled.input`
border: none; border: none;
} }
background-color: var(--gray-200); background-color: var(--gray-200);
opacity:0; opacity: 0;
transition: 0.2s; transition: 0.2s;
&:hover + ${ColorButton} { &:hover + ${ColorButton} {
transition: 0.2s; transition: 0.2s;
scale: 1.3; scale: 1.3;
} }
`; `;

View file

@ -1,5 +1,4 @@
import Link from 'next/link'; import Link from 'next/link';
import { useRouter } from 'next/router';
import React from 'react'; import React from 'react';
import styled from 'styled-components'; import styled from 'styled-components';
import { media } from '../lib/responsive'; import { media } from '../lib/responsive';
@ -11,25 +10,16 @@ export interface NavigationItemProps {
style?: any; style?: any;
} }
export function NavigationItem({ href, children, style }: NavigationItemProps) { export function NavigationItem({ href, children, style }: NavigationItemProps) {
const router = useRouter();
return ( return (
<Link href={href} passHref legacyBehavior> <Link href={href} passHref legacyBehavior>
<NavigationItemContainer <NavigationItemContainer as={'a'} style={style}>
as={'a'}
isActive={
href.slice(1)
? router.asPath.slice(1).startsWith(href.slice(1))
: router.asPath === href
}
style={style}
>
{children} {children}
</NavigationItemContainer> </NavigationItemContainer>
</Link> </Link>
); );
} }
export const NavigationItemContainer = styled(Text15)<{ isActive?: boolean }>` export const NavigationItemContainer = styled(Text15)`
font-weight: 700; font-weight: 700;
font-size: 18px; font-size: 18px;
line-height: 28px; line-height: 28px;
@ -54,7 +44,7 @@ export const NavigationItemContainer = styled(Text15)<{ isActive?: boolean }>`
color: var(--g0); color: var(--g0);
width: auto; width: auto;
border-bottom: none !important; border-bottom: none !important;
transition: 0.2s; transition: 0.2s;
&::before { &::before {
position: absolute; position: absolute;
@ -76,6 +66,5 @@ export const NavigationItemContainer = styled(Text15)<{ isActive?: boolean }>`
left: -20px; left: -20px;
right: -20px; right: -20px;
} }
} }
`; `;

View file

@ -7,7 +7,7 @@ import React, { useEffect, useRef } from 'react';
import { GridProps, ListProps } from 'react-window'; import { GridProps, ListProps } from 'react-window';
function isHtmlElement( function isHtmlElement(
element: HTMLElement | typeof window element: HTMLElement | typeof window,
): element is HTMLElement { ): element is HTMLElement {
return (element as HTMLElement).scrollTop !== undefined; return (element as HTMLElement).scrollTop !== undefined;
} }
@ -28,7 +28,7 @@ const documentScrollPositionKey: PositionKey = {
const getScrollPosition = ( const getScrollPosition = (
axis: keyof PositionKey, axis: keyof PositionKey,
element?: HTMLElement | null element?: HTMLElement | null,
): number => ): number =>
// @ts-ignore indexing as string // @ts-ignore indexing as string
element?.[documentScrollPositionKey[axis] as any] || element?.[documentScrollPositionKey[axis] as any] ||
@ -53,7 +53,7 @@ interface ReactWindowScrollerProps<Props extends ListProps | GridProps> {
isGrid?: boolean; isGrid?: boolean;
} }
export function ReactWindowScroller< export function ReactWindowScroller<
Props extends ListProps | GridProps = ListProps Props extends ListProps | GridProps = ListProps,
>({ >({
children, children,
throttleTime = 10, throttleTime = 10,

View file

@ -1,4 +1,3 @@
import { NumberFormatOptions } from '@internationalized/number';
import { useFocusRing } from '@react-aria/focus'; import { useFocusRing } from '@react-aria/focus';
import { useNumberFormatter } from '@react-aria/i18n'; import { useNumberFormatter } from '@react-aria/i18n';
import { useSlider, useSliderThumb } from '@react-aria/slider'; import { useSlider, useSliderThumb } from '@react-aria/slider';
@ -11,7 +10,7 @@ import styled from 'styled-components';
import { Text13 } from './Typography'; import { Text13 } from './Typography';
export interface SliderProps extends ReactSliderProps<number[]> { export interface SliderProps extends ReactSliderProps<number[]> {
formatOptions?: NumberFormatOptions; formatOptions?: Parameters<typeof useNumberFormatter>[0];
} }
export function Slider(props: SliderProps) { export function Slider(props: SliderProps) {
let trackRef = React.useRef(null); let trackRef = React.useRef(null);
@ -20,7 +19,7 @@ export function Slider(props: SliderProps) {
let { groupProps, trackProps, labelProps, outputProps } = useSlider( let { groupProps, trackProps, labelProps, outputProps } = useSlider(
props, props,
state, state,
trackRef trackRef,
); );
return ( return (
@ -56,7 +55,7 @@ function Thumb({ state, trackRef, index }: ThumbProps) {
trackRef, trackRef,
inputRef, inputRef,
}, },
state state,
); );
let { focusProps, isFocusVisible } = useFocusRing(); let { focusProps, isFocusVisible } = useFocusRing();
@ -129,7 +128,7 @@ const ThumbInner = styled.div`
box-shadow: 0px 3px 0px 0px var(--g0); box-shadow: 0px 3px 0px 0px var(--g0);
border-radius: 50%; border-radius: 50%;
cursor: pointer; cursor: pointer;
&:hover{ &:hover {
transition: 0.2s; transition: 0.2s;
scale: 1.2; scale: 1.2;
} }

View file

@ -3,20 +3,24 @@ import styled from 'styled-components';
import { media } from '../lib/responsive'; import { media } from '../lib/responsive';
export function Sponsor() { export function Sponsor() {
return <SponsorContainer> return (
<SponsorText> <SponsorContainer>
<SponsorLeft> <SponsorText>
<SponsorLogo /> <SponsorLeft>
</SponsorLeft> <SponsorLogo />
<SponsorRight> </SponsorLeft>
<SponsorTitle>Get 3 months free of Framer with Iconoir.</SponsorTitle> <SponsorRight>
<SponsorDescr>Click the link and use the code pro-yearly-partner.</SponsorDescr> <SponsorTitle>Get 3 months free of Framer with Iconoir.</SponsorTitle>
</SponsorRight> <SponsorDescr>
</SponsorText> Click the link and use the code pro-yearly-partner.
<a href="https://www.framer.com?via=iconoir"> </SponsorDescr>
<SponsorCTA>Get the offer</SponsorCTA> </SponsorRight>
</a> </SponsorText>
</SponsorContainer>; <a href="https://www.framer.com?via=iconoir">
<SponsorCTA>Get the offer</SponsorCTA>
</a>
</SponsorContainer>
);
} }
const SponsorContainer = styled.div` const SponsorContainer = styled.div`
@ -42,38 +46,34 @@ const SponsorText = styled.div`
padding 8px; padding 8px;
`; `;
const SponsorRight = styled.div` const SponsorRight = styled.div``;
`;
const SponsorLeft = styled.div` const SponsorLeft = styled.div``;
`;
const SponsorLogo = styled.div` const SponsorLogo = styled.div`
@keyframes my-animation {
@keyframes my-animation { 0% {
0% { transform: scale(1);
transform: scale(1); }
45% {
transform: scale(1);
}
50% {
transform: scale(1.2) rotate(-15deg);
}
55% {
transform: scale(1);
}
90% {
transform: scale(1);
}
95% {
transform: scale(1.6) rotate(15deg);
}
100% {
transform: scale(1);
}
} }
45% {
transform: scale(1);
}
50% {
transform: scale(1.2) rotate(-15deg);
}
55% {
transform: scale(1);
}
90% {
transform: scale(1);
}
95% {
transform: scale(1.6) rotate(15deg);
}
100% {
transform: scale(1);
}
}
width: 34px; width: 34px;
height: 34px; height: 34px;
@ -110,4 +110,4 @@ const SponsorCTA = styled.div`
background-color: var(--g0); background-color: var(--g0);
color: var(--white); color: var(--white);
} }
`; `;

View file

@ -26,7 +26,7 @@ export const Text13 = styled.div`
export const Text17 = styled.div` export const Text17 = styled.div`
font-size: 17px; font-size: 17px;
`; `;
export const Text18 = styled.div` export const Text18 = styled.div`
font-size: 16px; font-size: 16px;
line-height: 25px; line-height: 25px;
@ -140,7 +140,7 @@ export function Pre({ children, ...props }: React.PropsWithChildren<any>) {
React.useEffect(() => { React.useEffect(() => {
setSupportsClipboard( setSupportsClipboard(
typeof window !== 'undefined' && typeof window !== 'undefined' &&
typeof window?.navigator?.clipboard?.writeText !== 'undefined' typeof window?.navigator?.clipboard?.writeText !== 'undefined',
); );
}, []); }, []);
return ( return (

View file

@ -6,10 +6,10 @@ const CUSTOMIZATIONS_KEY = 'iconoir-customize';
export function useCustomizationPersistence(): [ export function useCustomizationPersistence(): [
IconListCustomizations, IconListCustomizations,
// eslint-disable-next-line no-unused-vars // eslint-disable-next-line no-unused-vars
(customizations: IconListCustomizations) => void (customizations: IconListCustomizations) => void,
] { ] {
const [customizations, _setCustomizations] = React.useState( const [customizations, _setCustomizations] = React.useState(
DEFAULT_CUSTOMIZATIONS DEFAULT_CUSTOMIZATIONS,
); );
React.useEffect(() => { React.useEffect(() => {
const localStorageValue = localStorage.getItem(CUSTOMIZATIONS_KEY); const localStorageValue = localStorage.getItem(CUSTOMIZATIONS_KEY);
@ -28,7 +28,7 @@ export function useCustomizationPersistence(): [
(newCustomizations) => { (newCustomizations) => {
localStorage.setItem( localStorage.setItem(
CUSTOMIZATIONS_KEY, CUSTOMIZATIONS_KEY,
JSON.stringify(newCustomizations) JSON.stringify(newCustomizations),
); );
_setCustomizations(newCustomizations); _setCustomizations(newCustomizations);
}, },

View file

@ -1,31 +1,39 @@
export const REPO = { export const REPO = {
owner: 'iconoir-icons', owner: 'iconoir-icons',
repo: 'iconoir', repo: 'iconoir',
}; } as const;
export const SHARE_LINK = 'https://twitter.com/intent/tweet?text=Check%20out%20Iconoir%20by%20%40burgioluca%20and%20the%20amazing%20team%20with%20%40therealsammarks%20%F0%9F%94%A5&url=https%3A%2F%2Ficonoir.com';
export const GITHUB_LINK = `https://github.com/${REPO.owner}/${REPO.repo}`;
export const SUGGEST_ICON_LINK = `${GITHUB_LINK}/issues/new?assignees=lucaburgio&labels=icon+request&template=icon_request.md&title=%5BICON%5D`;
export const SUPPORT_LINK = 'https://opencollective.com/iconoir/donate';
export const DISCORD_LINK = 'https://discord.gg/c3uzjx6k';
export const LICENSE_LINK = `${GITHUB_LINK}/blob/main/LICENSE`;
export const ICON_WIDTH = 140;
export const ICON_SPACE = 20;
export const SUGGEST_LIBRARY_LINK = `${GITHUB_LINK}/issues/new?assignees=&labels=enhancement&template=feature_request.md&title=%5BFEAT%5D`; export const GITHUB_LINK =
export const FEEDBACK_LINK = 'https://forms.gle/3HvwVYow7D6T8zad7'; `https://github.com/${REPO.owner}/${REPO.repo}` as const;
export const ISSUE_LINK = `${GITHUB_LINK}/issues/new/choose` as const;
export const SUGGEST_ICON_LINK =
`${GITHUB_LINK}/issues/new?assignees=lucaburgio&labels=icon+request&template=icon_request.md&title=%5BICON%5D` as const;
export const LICENSE_LINK = `${GITHUB_LINK}/blob/main/LICENSE` as const;
export const SUGGEST_LIBRARY_LINK =
`${GITHUB_LINK}/issues/new?assignees=&labels=enhancement&template=feature_request.md&title=%5BFEAT%5D` as const;
export const GITHUB_TREE_PREFIX = export const GITHUB_TREE_PREFIX = `${GITHUB_LINK}/tree/main` as const;
'https://github.com/iconoir-icons/iconoir/tree/main';
export const LIBRARY_LINKS = { export const LIBRARY_LINKS = {
React: `${GITHUB_TREE_PREFIX}/packages/iconoir-react`, React: `${GITHUB_TREE_PREFIX}/packages/iconoir-react`,
ReactNative: `${GITHUB_TREE_PREFIX}/packages/iconoir-react-native`, ReactNative: `${GITHUB_TREE_PREFIX}/packages/iconoir-react-native`,
Flutter: `${GITHUB_TREE_PREFIX}/packages/iconoir-flutter`, Flutter: `${GITHUB_TREE_PREFIX}/packages/iconoir-flutter`,
Framer: 'https://framer.com/', Framer: 'https://framer.com/',
Figma: 'https://www.figma.com/community/file/983248991460488027/Iconoir-Pack', Figma: 'https://www.figma.com/community/file/983248991460488027/Iconoir-Pack',
}; } as const;
export const SHARE_LINK =
'https://twitter.com/intent/tweet?text=Check%20out%20Iconoir%20by%20%40burgioluca%20and%20the%20amazing%20team%20with%20%40therealsammarks%20%F0%9F%94%A5&url=https%3A%2F%2Ficonoir.com' as const;
export const SUPPORT_LINK =
'https://opencollective.com/iconoir/donate' as const;
export const DISCORD_LINK = 'https://discord.gg/c3uzjx6k' as const;
export const FEEDBACK_LINK = 'https://forms.gle/3HvwVYow7D6T8zad7' as const;
export const PRIVACY_LINK =
'https://www.freeprivacypolicy.com/live/ba00d743-a0cd-44f8-8cb5-6f58911db0fb' as const;
export const AUTHOR_LINKS = { export const AUTHOR_LINKS = {
Luca: 'https://twitter.com/burgioluca', Luca: 'https://twitter.com/burgioluca',
Sam: 'https://twitter.com/therealsammarks', Sam: 'https://twitter.com/therealsammarks',
}; } as const;
export const ICON_WIDTH = 140 as const;
export const ICON_SPACE = 20 as const;

View file

@ -25,11 +25,11 @@ export async function getAllIcons(): Promise<Icon[]> {
const matchingKey = Object.keys(AllIcons).find( const matchingKey = Object.keys(AllIcons).find(
(k) => (k) =>
k.toLowerCase() === iconComponentName.toLowerCase() || k.toLowerCase() === iconComponentName.toLowerCase() ||
k.toLowerCase() === `svg${iconComponentName.toLowerCase()}` k.toLowerCase() === `svg${iconComponentName.toLowerCase()}`,
); );
if (!matchingKey) if (!matchingKey)
throw new Error( throw new Error(
`Cannot find icon '${iconComponentName}' in iconoir-react.` `Cannot find icon '${iconComponentName}' in iconoir-react.`,
); );
return { return {
filename: row.filename, filename: row.filename,

View file

@ -9,42 +9,39 @@
"lint": "next lint" "lint": "next lint"
}, },
"devDependencies": { "devDependencies": {
"@internationalized/number": "^3.1.2", "@nodesecure/npm-registry-sdk": "^1.6.1",
"@nodesecure/npm-registry-sdk": "^1.4.1", "@octokit/rest": "^20.0.1",
"@octokit/rest": "^19.0.5", "@react-aria/focus": "^3.14.1",
"@react-aria/focus": "^3.10.1", "@react-aria/i18n": "^3.8.2",
"@react-aria/i18n": "^3.6.3", "@react-aria/slider": "^3.7.0",
"@react-aria/slider": "^3.2.4", "@react-aria/utils": "^3.20.0",
"@react-aria/ssr": "^3.4.1", "@react-aria/visually-hidden": "^3.8.4",
"@react-aria/utils": "^3.14.2", "@react-stately/slider": "^3.4.2",
"@react-aria/visually-hidden": "^3.6.1", "@react-types/slider": "^3.6.1",
"@react-stately/slider": "^3.2.4", "@types/animejs": "^3.1.8",
"@react-types/slider": "^3.3.1", "@types/lodash": "^4.14.199",
"@types/animejs": "^3.1.6", "@types/node": "^20.6.5",
"@types/lodash": "^4.14.191", "@types/react": "^18.2.22",
"@types/node": "^18.11.18", "@types/react-dom": "^18.2.7",
"@types/react": "^17.0.52",
"@types/react-dom": "^18.0.10",
"@types/react-window": "^1.8.5", "@types/react-window": "^1.8.5",
"@types/styled-components": "^5.1.26",
"animejs": "^3.2.1", "animejs": "^3.2.1",
"case": "^1.6.3", "case": "^1.6.3",
"csvtojson": "^2.0.10", "csvtojson": "^2.0.10",
"eslint": "^8.31.0", "eslint": "^8.50.0",
"eslint-config-next": "^13.1.1", "eslint-config-next": "^13.5.2",
"iconoir-react": "workspace:*", "iconoir-react": "workspace:*",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"moment": "^2.29.4", "moment": "^2.29.4",
"next": "^13.1.1", "next": "^13.5.2",
"next-mdx-remote": "^4.2.1", "next-mdx-remote": "^4.4.1",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-is": "^18.2.0", "react-is": "^18.2.0",
"react-window": "^1.8.8", "react-window": "^1.8.9",
"remark-gfm": "^3.0.1", "remark-gfm": "^3.0.1",
"remark-prism": "^1.3.6", "remark-prism": "^1.3.6",
"styled-components": "^5.3.6", "styled-components": "^6.0.8",
"typescript": "^4.9.4", "typescript": "^5.1.6",
"use-resize-observer": "^9.1.0" "use-resize-observer": "^9.1.0"
} }
} }

View file

@ -1,14 +1,7 @@
import { SSRProvider } from '@react-aria/ssr';
import type { AppProps } from 'next/app'; import type { AppProps } from 'next/app';
import '../styles/prism-theme.css'; import '../styles/prism-theme.css';
import '../styles/theme.css'; import '../styles/theme.css';
function MyApp({ Component, pageProps }: AppProps) { export default function App({ Component, pageProps }: AppProps) {
return ( return <Component {...pageProps} />;
<SSRProvider>
<Component {...pageProps} />
</SSRProvider>
);
} }
export default MyApp;

View file

@ -10,7 +10,7 @@ import { ServerStyleSheet } from 'styled-components';
export default class IconoirDocument extends Document { export default class IconoirDocument extends Document {
static async getInitialProps( static async getInitialProps(
ctx: DocumentContext ctx: DocumentContext,
): Promise<DocumentInitialProps> { ): Promise<DocumentInitialProps> {
const sheet = new ServerStyleSheet(); const sheet = new ServerStyleSheet();
const originalRenderPage = ctx.renderPage; const originalRenderPage = ctx.renderPage;

View file

@ -175,7 +175,7 @@ export function getDocumentationStructure(): DocumentationItem[] {
function structureItemsToPaths( function structureItemsToPaths(
items: DocumentationItem[], items: DocumentationItem[],
slugPrefix?: string[] slugPrefix?: string[],
): ParsedUrlQuery[] { ): ParsedUrlQuery[] {
const result: ParsedUrlQuery[] = []; const result: ParsedUrlQuery[] = [];
const filteredItems = items.filter((item) => !item.skip); const filteredItems = items.filter((item) => !item.skip);
@ -187,8 +187,8 @@ function structureItemsToPaths(
result.push( result.push(
...structureItemsToPaths( ...structureItemsToPaths(
item.children, item.children,
[...(slugPrefix || []), item.path].filter(Boolean) [...(slugPrefix || []), item.path].filter(Boolean),
) ),
); );
} }
} }
@ -198,7 +198,7 @@ function structureItemsToPaths(
function flattenItems( function flattenItems(
items: DocumentationItem[], items: DocumentationItem[],
prefix?: string[] prefix?: string[],
): DocumentationItem[] { ): DocumentationItem[] {
return items.reduce<DocumentationItem[]>((acc, item) => { return items.reduce<DocumentationItem[]>((acc, item) => {
return [ return [
@ -214,7 +214,7 @@ function flattenItems(
...(item.children?.length ...(item.children?.length
? flattenItems( ? flattenItems(
item.children, item.children,
[...(prefix || []), item.path].filter(Boolean) [...(prefix || []), item.path].filter(Boolean),
) )
: []), : []),
]; ];
@ -223,7 +223,7 @@ function flattenItems(
function itemFromSlug( function itemFromSlug(
items: DocumentationItem[], items: DocumentationItem[],
slug: string[] slug: string[],
): DocumentationItem { ): DocumentationItem {
const flatItems = flattenItems(items); const flatItems = flattenItems(items);
const joinedSlug = slug.filter(Boolean).join('/'); const joinedSlug = slug.filter(Boolean).join('/');

View file

@ -36,13 +36,14 @@ const Home: NextPage<HomeProps> = ({
<Header currentVersion={currentVersion} /> <Header currentVersion={currentVersion} />
<HeaderBackground> <HeaderBackground>
<HeroHead> <HeroHead>
<HeroText>Say hello</HeroText> <HeroText>Say hello</HeroText>
<HeroTextSecondary>to your new icon library.</HeroTextSecondary> <HeroTextSecondary>to your new icon library.</HeroTextSecondary>
</HeroHead> </HeroHead>
</HeaderBackground> </HeaderBackground>
<HeroDescription> <HeroDescription>
A high-quality selection of free icons. No premium options or sign-ups. Your new alternative to Noun Project, Flaticon, and all Figma resources. Available in SVG, A high-quality selection of free icons. No premium options or sign-ups.
Font, React, React Native, Flutter, Figma and Framer. Your new alternative to Noun Project, Flaticon, and all Figma resources.
Available in SVG, Font, React, React Native, Flutter, Figma and Framer.
</HeroDescription> </HeroDescription>
<StatsContainer> <StatsContainer>
<Stat <Stat
@ -59,7 +60,7 @@ const Home: NextPage<HomeProps> = ({
/> />
<Stat <Stat
value={new Intl.NumberFormat('en-US', { notation: 'compact' }).format( value={new Intl.NumberFormat('en-US', { notation: 'compact' }).format(
numDownloads numDownloads,
)} )}
description={ description={
'downloads/month on React only. Iconoir also supports React Native, Flutter and CSS.' 'downloads/month on React only. Iconoir also supports React Native, Flutter and CSS.'
@ -67,7 +68,7 @@ const Home: NextPage<HomeProps> = ({
/> />
<Stat <Stat
value={new Intl.NumberFormat('en-US', { notation: 'compact' }).format( value={new Intl.NumberFormat('en-US', { notation: 'compact' }).format(
numStars numStars,
)} )}
description={ description={
'people who starred the project on GitHub. Show your support and be one of them.' 'people who starred the project on GitHub. Show your support and be one of them.'
@ -85,7 +86,8 @@ const Home: NextPage<HomeProps> = ({
<span>Donate</span> <span>Donate</span>
</LargeButton> </LargeButton>
<Text18> <Text18>
If you find Iconoir valuable for you, consider making a donation to help us pursuing even bigger goals. If you find Iconoir valuable for you, consider making a donation to
help us pursuing even bigger goals.
</Text18> </Text18>
</SupportContainer> </SupportContainer>
<Explore allIcons={allIcons} /> <Explore allIcons={allIcons} />
@ -116,10 +118,9 @@ export const HeroText = styled.h1`
-webkit-text-stroke: 2.5px; -webkit-text-stroke: 2.5px;
} }
&:hover { &:hover {
transform:scale(1.04); transform: scale(1.04);
transition:0.3s; transition: 0.3s;
} }
`; `;
export const HeroTextSecondary = styled(HeroText)` export const HeroTextSecondary = styled(HeroText)`
color: var(--g4); color: var(--g4);
@ -149,7 +150,6 @@ const SupportContainer = styled.div`
} }
`; `;
export default Home; export default Home;
export async function getStaticProps() { export async function getStaticProps() {
@ -164,7 +164,7 @@ export async function getStaticProps() {
const { downloads: numDownloads } = await npmDownloads( const { downloads: numDownloads } = await npmDownloads(
'iconoir-react', 'iconoir-react',
'last-month' 'last-month',
); );
if (!numDownloads) throw new Error('Could not find NPM downloads'); if (!numDownloads) throw new Error('Could not find NPM downloads');
@ -176,5 +176,4 @@ export async function getStaticProps() {
numDownloads, numDownloads,
}, },
}; };
} }

View file

@ -11,7 +11,7 @@ import { HeaderSecondary } from '../components/HeaderSecondary';
import { Layout } from '../components/Layout'; import { Layout } from '../components/Layout';
import { media } from '../lib/responsive'; import { media } from '../lib/responsive';
import { SEO } from '../components/SEO'; import { SEO } from '../components/SEO';
import { Body, Code, Heading2, Text18 } from '../components/Typography'; import { Body, Heading2, Text18 } from '../components/Typography';
import { getHeaderProps } from '../lib/getHeaderProps'; import { getHeaderProps } from '../lib/getHeaderProps';
import { Praise } from '../components/Praise'; import { Praise } from '../components/Praise';
@ -20,29 +20,44 @@ const Support: NextPage<SupportProps> = ({ ...headerProps }) => {
return ( return (
<Layout> <Layout>
<SEO title={'Donate - Our Mission'} /> <SEO title={'Donate - Our Mission'} />
<Header {...headerProps}/> <Header {...headerProps} />
<HeaderSecondary> <HeaderSecondary>
<SupportHead> <SupportHead>
<HeroText>Our Goal</HeroText> <HeroText>Our Goal</HeroText>
<HeroTextSecondary>A free, complete, and open icon library.</HeroTextSecondary> <HeroTextSecondary>
A free, complete, and open icon library.
</HeroTextSecondary>
</SupportHead> </SupportHead>
</HeaderSecondary> </HeaderSecondary>
<PageContainer> <PageContainer>
<PillarsContainer> <PillarsContainer>
<Pillar> <Pillar>
<PillarIcon R={"140"} G={"26"} B={"245"}><Flash /></PillarIcon> <PillarIcon $R={'140'} $G={'26'} $B={'245'}>
<Flash />
</PillarIcon>
<PillarTitle>Free</PillarTitle> <PillarTitle>Free</PillarTitle>
<PillarDescription>We want to give to developers and users high-quality free icons. Hassle-free.</PillarDescription> <PillarDescription>
We want to give to developers and users high-quality free icons.
Hassle-free.
</PillarDescription>
</Pillar> </Pillar>
<Pillar> <Pillar>
<PillarIcon R={"72"} G={"88"} B={"255"}><DesignNib /></PillarIcon> <PillarIcon $R={'72'} $G={'88'} $B={'255'}>
<DesignNib />
</PillarIcon>
<PillarTitle>Complete</PillarTitle> <PillarTitle>Complete</PillarTitle>
<PillarDescription>Were aiming at having as much unique icons as possible.</PillarDescription> <PillarDescription>
Were aiming at having as much unique icons as possible.
</PillarDescription>
</Pillar> </Pillar>
<Pillar> <Pillar>
<PillarIcon R={"65"} G={"209"} B={"255"}><Globe /></PillarIcon> <PillarIcon $R={'65'} $G={'209'} $B={'255'}>
<Globe />
</PillarIcon>
<PillarTitle>Ambitious</PillarTitle> <PillarTitle>Ambitious</PillarTitle>
<PillarDescription>We want to help and be part of as many projects as possible.</PillarDescription> <PillarDescription>
We want to help and be part of as many projects as possible.
</PillarDescription>
</Pillar> </Pillar>
</PillarsContainer> </PillarsContainer>
<WideSection> <WideSection>
@ -52,12 +67,15 @@ const Support: NextPage<SupportProps> = ({ ...headerProps }) => {
support Iconoir with a donation to help us sustain costs and support Iconoir with a donation to help us sustain costs and
development time. development time.
</Text18> </Text18>
<CallToAction as={'a'} href={SUPPORT_LINK} target={'_blank'}><span>Donate</span><ArrowRight /></CallToAction> <CallToAction as={'a'} href={SUPPORT_LINK} target={'_blank'}>
<span>Donate</span>
<ArrowRight />
</CallToAction>
</WideSection> </WideSection>
<PraiseContainer> <PraiseContainer>
<PraiseTitle>What our friends say</PraiseTitle> <PraiseTitle>What our friends say</PraiseTitle>
<Praise /> <Praise />
</PraiseContainer> </PraiseContainer>
<DonateContainer> <DonateContainer>
<DonateLeft> <DonateLeft>
<DonateHeader>Join us on Discord</DonateHeader> <DonateHeader>Join us on Discord</DonateHeader>
@ -82,7 +100,6 @@ const Support: NextPage<SupportProps> = ({ ...headerProps }) => {
); );
}; };
const PillarsContainer = styled.div` const PillarsContainer = styled.div`
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
@ -125,14 +142,15 @@ const PillarDescription = styled(Body)`
margin: 0; margin: 0;
`; `;
const PillarIcon = styled.span<{ R?: string, G?: string, B?: string }>` const PillarIcon = styled.span<{ $R?: string; $G?: string; $B?: string }>`
font-size: 18px; font-size: 18px;
padding: 20px 11px 6px 11px; padding: 20px 11px 6px 11px;
color: var(--white); color: var(--white);
width: 100px; width: 100px;
height: 100px; height: 100px;
background: rgb(${({ R }) => R}, ${({ G }) => G}, ${({ B }) => B}); background: rgb(${({ $R }) => $R}, ${({ $G }) => $G}, ${({ $B }) => $B});
box-shadow: 2px 6px 20px rgba(${({ R }) => R}, ${({ G }) => G}, ${({ B }) => B}, 0.5); box-shadow: 2px 6px 20px
rgba(${({ $R }) => $R}, ${({ $G }) => $G}, ${({ $B }) => $B}, 0.5);
border-radius: 18px; border-radius: 18px;
`; `;

File diff suppressed because it is too large Load diff