Skip to content

Commit

Permalink
feat: initial version
Browse files Browse the repository at this point in the history
  • Loading branch information
stipsan authored Nov 30, 2020
1 parent 8cd16bd commit ef3ecfa
Show file tree
Hide file tree
Showing 45 changed files with 16,041 additions and 1 deletion.
35 changes: 35 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,38 @@ dist

# TernJS port file
.tern-port

# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# local env files
.env.local
.env.development.local
.env.test.local
.env.production.local

# vercel
.vercel
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
# react-spring-bottom-sheet
# react-spring-bottom-sheet

# Work in progress!

Hold off using this until v1 is out, or you're gonna have a _bad time_!
17 changes: 17 additions & 0 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Dragging, and transitions, need to be completely outside reacts render loop.
Stop relying on memo stuff.
If react's render loop triggers, communicate to outside fn's via refs and the like.
A change to snap points affects how far one can drag.

- minHeight should be renamed safeHeight or similar, as it denotes the smallest height while still being able to render the drag handle. Isn't it header height technically?
- maxHeight renamed to contentHeight, as that's what it is.
- rename initialHeight to initialSnapPoint.
- rename viewportHeight to maxHeight?
- rename isOpen to open, like the <details> tag works.
- rename setHeight to setSnapPoint

# Credits

- Play icon: https://fontawesome.com/icons/play-circle?style=regular
- Phone frame used in logo: https://www.figma.com/community/file/896042888090872154/Mono-Devices-1.0
- iPhone frame used to wrap examples: https://www.figma.com/community/file/858143367356468985/(Variants)-iOS-%26-iPadOS-14-UI-Kit-for-Figma
50 changes: 50 additions & 0 deletions docs/Hero.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
.wrapper {
background: linear-gradient(171.09deg, #f1c7a7 0.47%, #ff8fcb 96.54%), #c4c4c4;
height: 336px;
width: 100%;

position: relative;
}
.wrapper:before {
content: '';
display: block;
position: absolute;
left: 0;
right: 0;
bottom: 0;
height: 1px;
background: rgba(89, 35, 64, 0.4);
z-index: 1;
}
.subtitle,
.text {
font-size: 32px;
line-height: 46px;
}

.text {
transition-property: transform, opacity;
transition-timing-function: ease-out, ease-in;
}
.text.text {
--tw-translate-y: 40px;
opacity: 0;
}
.open .text {
transition-duration: 300ms;
--tw-translate-y: 0px;
opacity: 1;
}
/* Only set delay while open to avoid weird artifacts with fast toggling */
.open .text {
transition-delay: calc(150ms + 80ms * var(--index, 0));
}
.text + .text {
--index: 1;
& + .text {
--index: 2;
& + .text {
--index: 3;
}
}
}
172 changes: 172 additions & 0 deletions docs/Hero.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
import cx from 'classnames'
import NextLink from 'next/link'
import { forwardRef, useEffect, useRef, useState } from 'react'
import { animated, config, useSpring } from 'react-spring'
import styles from './Hero.module.css'

const subtitle = 'Accessible, Delightful, and Performant'

const Link: React.FC<{
href?: string
target?: string
className?: string
}> = forwardRef(
({ children, className, ...props }, ref: React.Ref<HTMLAnchorElement>) => (
<a
{...props}
className={cx(
'bg-hero rounded-full px-4 py-2 mr-2 text-xl hover:text-hero focus:outline-none focus:text-hero focus:ring-2 focus:ring-hero transition-colors duration-150 focus:duration-0',
className
)}
ref={ref}
>
{children}
</a>
)
)

const Links = ({ className }: { className?: string }) => (
<>
<NextLink href="/docs" passHref>
<Link className={className}>Get started</Link>
</NextLink>
<Link
className={className}
href="https://github.com/stipsan/react-spring-bottom-sheet"
target="_blank"
>
GitHub
</Link>
</>
)
// The wrapping in <g> is because of Safari 🙄 https://bug-149617-attachments.webkit.org/attachment.cgi?id=262048
const SvgText: React.FC<{ x?: string; y?: string; className?: string }> = ({
children,
className,
x = '23',
y,
...props
}) => (
<g
{...props}
className={cx(className, styles.text, 'transform-gpu duration-0 opacity-0')}
>
<text
x={x}
y={y}
className="text-hero fill-current font-display font-black select-none pointer-events-none"
>
{children}
</text>
</g>
)

export default function Hero({ className }: { className?: string }) {
const [open, setOpen] = useState(false)
const openClassRef = useRef(false)
const classNameRef = useRef(null)
const { y, state } = useSpring<any>({
config: config.stiff,
from: { y: '208px', state: 0 },
to: {
y: open ? '0px' : '208px',
state: open ? 1 : 0,
},
onFrame: ({ state }) => {
if (state > 0) {
if (!openClassRef.current) {
classNameRef.current.classList.add(styles.open)
openClassRef.current = true
}
} else {
if (openClassRef.current) {
classNameRef.current.classList.remove(styles.open)
openClassRef.current = false
}
}
},
})

useEffect(() => {
setOpen(true)
}, [])

return (
<>
<div className={cx(styles.wrapper, 'flex justify-center', className)}>
<div className="inline-flex items-end">
<svg
onPointerDown={() => setOpen((open) => !open)}
className={cx(styles.svg, 'flex-shrink-0')}
width="200"
height="286"
viewBox="0 0 200 286"
fill="none"
xmlns="http://www.w3.org/2000/svg"
aria-label="Phone illustration of a bottom sheet containing the text: React Spring Bottom Sheet"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M33.1779 0C10.0158 0 3.8147e-05 10.4712 3.8147e-05 33.4574V377.457C3.8147e-05 400.443 10.0158 410.496 33.1779 410.496H166.41C188.769 410.496 200 399.634 200 377.457C200 377.457 200 56.4435 200 33.4574C200 10.4712 189.34 0 166.178 0H33.1779Z"
fill="#592340"
/>
<animated.path
style={{
fill: state.interpolate({ output: ['#fed7e6', '#FC9EC2'] }),
}}
fillRule="evenodd"
clipRule="evenodd"
d="M49 13.5C49.5 18 52.6325 23 60.5 23H139C146.868 23 149.5 18 150 13.5C150.282 10.9661 151.291 9 155 9L169.527 9.08597C182.598 9.08597 191 16.9649 191 30V379.5C191 392.535 182.598 400.468 169.527 400.468H30.0545C16.9836 400.468 9 392.585 9 379.55V30C9 16.9649 16.929 9 30 9H45C48.7085 9 48.7791 11.5122 49 13.5Z"
fill="#fed7e6"
/>
<animated.g
ref={classNameRef}
className="transform-gpu origin-center"
style={{
['--tw-translate-y' as any]: y,
/*
['--tw-scale-x' as any]: state.interpolate({
output: [0.9, 1],
}),
['--tw-scale-y' as any]: state.interpolate({
output: [0.9, 1],
}),
// */
}}
>
<path
d="M9 99.75C9 93.4642 9 90.3213 9.92713 87.8082C11.4459 83.6913 14.6913 80.4459 18.8082 78.9271C21.3213 78 24.4642 78 30.75 78H169.25C175.536 78 178.679 78 181.192 78.9271C185.309 80.4459 188.554 83.6913 190.073 87.8082C191 90.3213 191 93.4642 191 99.75V372C191 380.381 191 384.572 189.764 387.922C187.739 393.412 183.412 397.739 177.922 399.764C174.572 401 170.381 401 162 401H38C29.619 401 25.4285 401 22.0777 399.764C16.5884 397.739 12.2613 393.412 10.2362 387.922C9 384.572 9 380.381 9 372V99.75Z"
fill="white"
/>
<rect
x="89"
y="85"
width="22"
height="2"
rx="1"
fill="hsl(328deg 44% 24% / 50%)"
/>
<SvgText y="128">React</SvgText>
<SvgText y="174">Spring</SvgText>
<SvgText y="220">Bottom</SvgText>
<SvgText y="266">Sheet</SvgText>
</animated.g>
</svg>
<div className="font-display ml-10 mb-10 text-hero hidden md:block">
<h1 className={cx(styles.subtitle, 'pb-4 max-w-sm')}>{subtitle}</h1>
<div className="mt-4">
<Links className="text-hero-lighter hover:bg-hero-lighter focus:bg-hero-lighter" />
</div>
</div>
</div>
</div>
<div className="md:hidden font-display text-hero px-8 py-4">
<h1 className={cx(styles.subtitle, 'pb-4')}>{subtitle}</h1>
<div className="mt-4">
<Links className="text-white hover:bg-white focus:bg-white" />
</div>
</div>
</>
)
}
14 changes: 14 additions & 0 deletions docs/Nugget.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export default function Nugget({
heading,
lead,
}: {
heading: React.ReactNode
lead: React.ReactNode
}) {
return (
<article className="md:text-center">
<h2 className="text-3xl text-hero font-display">{heading}</h2>
<p className="text-1xl px-0.5">{lead}</p>
</article>
)
}
Loading

0 comments on commit ef3ecfa

Please sign in to comment.