My language learning journey
The word itself was a mistery, but I understood what it meant: it meant that my game would start....
15 min read
<section className="w-[95%] lg:w-full border-x-[1px] border-b-[1px] border-[#FFFFFF]/[0.16] max-w-screen-lg m-auto relative flex flex-wrap"> <div className="absolute top-0 left-0 right-0 mx-auto w-1/3 h-full pointer-events-none border-[#FFFFFF]/[0.16] border-r-[1px] border-l-[1px] hidden md:block"></div> <IconPlus className="absolute -bottom-3 -left-3 w-6 h-6" /> <IconPlus className="absolute -bottom-3 -right-3 w-6 h-6" /> <div className="w-full flex flex-col md:flex-row"> <div className="w-full md:w-1/3 flex flex-col p-6"> <Image src={ImgEstacio} width={150} alt="Estácio Logo" /> <h3 className="text-2xl font-bold w-full mt-4"> Software Engineer </h3> <p className="text-base mt-2">Bachelor{"'"}s Degree</p> <small className="text-gray-400"> 2022 - 2025 (Currently attending) </small> </div> <div className="w-full md:w-1/3 flex flex-col p-6 border-[#FFFFFF]/[0.16] border-t-[1px] md:border-t-0"> <Image src={ImgEstacio} width={150} alt="Estácio Logo" /> <h3 className="text-2xl font-bold w-full mt-4"> Information Systems </h3> <p className="text-base mt-2">Bachelor{"'"}s Degree</p> <small className="text-gray-400">2014 - 2015 (60 credits)</small> </div> <div className="w-full md:w-1/3 flex flex-col p-6 border-[#FFFFFF]/[0.16] border-t-[1px] md:border-t-0"> <Image src={ImgEasyComp} width={80} alt="EasyComp Logo" /> <h3 className="text-2xl font-bold w-full mt-4">Web Design</h3> <p className="text-base mt-2">Certificate Program</p> <small className="text-gray-400">2011 - 2012</small> </div> </div> </section>
<section class="w-[95%] lg:w-full border-x-[1px] border-b-[1px] border-[#FFFFFF]/[0.16] max-w-screen-lg m-auto relative flex flex-wrap"> <div class="absolute top-0 left-0 right-0 mx-auto w-1/3 h-full pointer-events-none border-[#FFFFFF]/[0.16] border-r-[1px] border-l-[1px] hidden md:block"></div> <%= lucide_icon('plus', class: 'absolute -bottom-3 -left-3 w-6 h-6') %> <%= lucide_icon('plus', class: 'absolute -bottom-3 -right-3 w-6 h-6') %> <div class="w-full flex flex-col md:flex-row"> <div class="w-full md:w-1/3 flex flex-col p-6"> <img src="<%= asset_path('estacio-logo-1024x260.png') %>" alt="Estácio Logo" class="w-[150px]" /> <h3 class="text-2xl font-bold w-full mt-4"> Software Engineer </h3> <p class="text-base mt-2">Bachelor's Degree</p> <small class="text-gray-400"> 2022 - 2026 (Currently attending) </small> </div> <div class="w-full md:w-1/3 flex flex-col p-6 border-[#FFFFFF]/[0.16] border-t-[1px] md:border-t-0"> <img src="<%= asset_path('estacio-logo-1024x260.png') %>" alt="Estácio Logo" class="w-[150px]" /> <h3 class="text-2xl font-bold w-full mt-4"> Information Systems </h3> <p class="text-base mt-2">Bachelor's Degree</p> <small class="text-gray-400">2014 - 2015 (60 credits)</small> </div> <div class="w-full md:w-1/3 flex flex-col p-6 border-[#FFFFFF]/[0.16] border-t-[1px] md:border-t-0"> <img src="<%= asset_path('logo-easy-comp.png') %>" alt="EasyComp Logo" class="w-[80px]" /> <h3 class="text-2xl font-bold w-full mt-4">Web Design</h3> <p class="text-base mt-2">Certificate Program</p> <small class="text-gray-400">2011 - 2012</small> </div> </div> </section>
'use client'; import { motion } from "framer-motion"; const HandWave = () => { return ( <motion.span transition={{ duration: 5, delay: 1, ease: "easeInOut", }} animate={{ rotate: [0, 35, -25, 25, -35, 0], }} initial={{ rotate: 0, }} className="inline-block" > 👋 </motion.span> ); }; export default HandWave;
<span data-controller="hand-wave" class="hand-wave inline-block">👋</span>
@keyframes wave { 0% { transform: rotate(0deg); } 20% { transform: rotate(35deg); } 40% { transform: rotate(-25deg); } 60% { transform: rotate(25deg); } 80% { transform: rotate(-35deg); } 100% { transform: rotate(0deg); } } .wave-animation { animation: wave 5s ease-in-out 1; }
import { Controller } from "@hotwired/stimulus"; export default class extends Controller { connect() { setTimeout(() => { this.element.classList.add("wave-animation"); }, 1000); // 1s delay } }
"use client"; import { useMemo, useRef, useState } from "react"; import { motion, useScroll, useTransform, useSpring, } from "framer-motion"; import { ProductCard } from "./ProductCard"; import ProductModal from "./ProductModal"; export interface Product { title: string; name: string; thumbnail: string; slides: string[]; description: string; }; interface HeroParallaxProps { products: Product[]; }; const HeroParallax: React.FC<HeroParallaxProps> = ({ products, }) => { const [currentProduct, setCurrentProduct] = useState<Product | null>(null); const firstRow = useMemo(() => products.slice(0, 5), [products]); const secondRow = useMemo(() => products.slice(5, 10), [products]); const thirdRow = useMemo(() => products.slice(10, 15), [products]); const ref = useRef(null); const { scrollYProgress } = useScroll({ target: ref, offset: ["start start", "end start"], }); const springConfig = { stiffness: 300, damping: 30, bounce: 100 }; const translateX = useSpring( useTransform(scrollYProgress, [0, 1], [0, 1000]), springConfig ); const translateXReverse = useSpring( useTransform(scrollYProgress, [0, 1], [0, -1000]), springConfig ); const rotateX = useSpring( useTransform(scrollYProgress, [0, 0.2], [15, 0]), springConfig ); const opacity = useSpring( useTransform(scrollYProgress, [0, 0.2], [0.2, 1]), springConfig ); const rotateZ = useSpring( useTransform(scrollYProgress, [0, 0.2], [20, 0]), springConfig ); const translateY = useSpring( useTransform(scrollYProgress, [0, 0.2], [-700, 500]), springConfig ); return ( <> <div ref={ref} className="h-[300vh] py-40 relative flex flex-col self-auto [perspective:1000px] [transform-style:preserve-3d]" > <div className="max-w-screen-lg relative mx-auto py-20 md:py-40 px-4 w-full left-0 top-0"> <h1 className="text-2xl md:text-7xl font-bold text-neutral-200"> My Work </h1> <p className="max-w-2xl text-base md:text-xl mt-8 text-neutral-300"> I bring websites and apps to life, from idea to launch. See what I've built. </p> </div> <motion.div style={{ rotateX, rotateZ, translateY, opacity, }} > <motion.div className="flex flex-row-reverse space-x-reverse space-x-20 mb-20"> {firstRow.map((product) => ( <ProductCard product={product} translate={translateX} key={product.title} onClick={() => setCurrentProduct(product)} /> ))} </motion.div> <motion.div className="flex flex-row mb-20 space-x-20 "> {secondRow.map((product) => ( <ProductCard product={product} translate={translateXReverse} key={product.title} onClick={() => setCurrentProduct(product)} /> ))} </motion.div> <motion.div className="flex flex-row-reverse space-x-reverse space-x-20"> {thirdRow.map((product) => ( <ProductCard product={product} translate={translateX} key={product.title} onClick={() => setCurrentProduct(product)} /> ))} </motion.div> </motion.div> </div> <ProductModal product={currentProduct} onRequestClose={() => setCurrentProduct(null)} /> </> ); }; export default HeroParallax;
"use client"; import React from "react"; import { motion, MotionValue, } from "framer-motion"; import Image from "next/image"; interface ProductCardProps { product: { title: string; name: string; thumbnail: string; }; translate: MotionValue<number>; onClick?: () => void; }; export const ProductCard: React.FC<ProductCardProps> = ({ product, translate, onClick, }) => { return ( <motion.div style={{ x: translate, }} whileHover={{ y: -20, }} key={product.title} className="group/produc h-80 w-[35rem] relative flex-shrink-0" onClick={onClick} > <div className="block group-hover/product:shadow-2xl hover:cursor-pointer"> <Image src={product.thumbnail} height="1280" width="832" className="object-cover object-left-top absolute h-full w-full inset-0 rounded-md" alt={product.title} /> </div> <div className="absolute inset-0 h-full w-full opacity-0 group-hover/product:opacity-80 bg-black pointer-events-none"></div> <h2 className="absolute bottom-4 left-4 opacity-0 group-hover/product:opacity-100 text-white"> {product.title} </h2> </motion.div> ); };
<div class="antialiased overflow-hidden relative w-full" data-controller="hero-parallax"> <div class="flex flex-col items-center justify-between pt-4 sm:pt-24 pb-4 sm:pb-12"> <%= render 'shared/header-menu' %> </div> <div class="pb-10"> <div data-hero-parallax-target="scrollContainer" class="h-[300vh] py-40 relative flex flex-col self-auto perspective-[1000px] transform-preserve-3d"> <div class="max-w-screen-lg relative mx-auto py-20 md:py-40 px-4 w-full left-0 top-0"> <h1 class="text-2xl md:text-7xl font-bold text-neutral-200"> My Work </h1> <p class="max-w-2xl text-base md:text-xl mt-8 text-neutral-300"> I bring websites and apps to life, from idea to launch. See what I've built. </p> </div> <div data-hero-parallax-target="productGrid" class="transition-all duration-300 ease-out will-change-transform" style="transform: perspective(1000px) rotateX(15deg) rotateZ(20deg) translateY(-700px); opacity: 0.2;"> <% @products.each_slice((@products.size / 3.0).ceil).with_index do |slice, index| %> <div class="<%= index.odd? ? 'flex flex-row' : 'flex flex-row-reverse space-x-reverse' %> mb-20 space-x-20"> <% slice.each do |product| %> <%= render 'product_card', product: product, reverse: index.odd? %> <% end %> </div> <% end %> </div> </div> </div> <div class="fixed top-0 left-0 w-full h-full bg-black bg-opacity-80 flex items-center justify-center" style="display:none;" data-hero-parallax-target="productModal" data-action="click->hero-parallax#closeModal"> <turbo-frame id="product-modal-content" data-action="turbo:frame-load->hero-parallax#openModal"></turbo-frame> </div> <%= render 'shared/footer' %> </div>
<%= link_to "/work/#{product[:name]}/modal", class: "group/produc h-80 w-[35rem] relative flex-shrink-0 transform transition-all", data: { "hero-parallax-target": "translateX#{reverse ? 'reverse' : ''}", "action": "mouseenter->hero-parallax#onMouseEnter mouseleave->hero-parallax#onMouseLeave", "turbo-frame": "product-modal-content" } do %> <div class="block group-hover/product:shadow-2xl hover:cursor-pointer"> <img src="<%= asset_path(product[:thumbnail]) %>" height="1280" width="832" class="object-cover object-left-top absolute h-full w-full inset-0 rounded-md" alt="Product image" /> </div> <div class="absolute inset-0 h-full w-full opacity-0 group-hover/product:opacity-80 bg-black pointer-events-none"></div> <h2 class="absolute bottom-4 left-4 opacity-0 group-hover/product:opacity-100 text-white"> <%= product[:title] %> </h2> <% end %>
import { Controller } from "@hotwired/stimulus"; import { animate, scroll, transform, } from "https://cdn.jsdelivr.net/npm/[email protected]/+esm"; export default class extends Controller { static targets = [ "scrollContainer", "productGrid", "translateX", "translateXreverse", "productModal", ]; animConfig = { type: "spring", stiffness: 300, damping: 30, bounce: 100, delay: 0, duration: 0, }; connect() { this.setupScroll(); } disconnect() { this.cancelScroll?.(); } setupScroll() { this.cancelScroll = scroll( (progress) => this.animateScrollProgress(progress), { axis: "y", target: this.scrollContainerTarget, offset: ["start start", "end start"], }, ); } animateScrollProgress(progress) { const animations = [ { target: this.productGridTarget, props: this.getGridProps(progress) }, { target: this.translateXTargets, props: { x: transform([0, 1], [0, 1000])(progress) }, }, { target: this.translateXreverseTargets, props: { x: transform([0, 1], [0, -1000])(progress) }, }, ]; animations.forEach(({ target, props }) => animate(target, props, this.animConfig), ); } getGridProps(progress) { return { transformPerspective: 1000, y: transform([0, 0.2], [-700, 500])(progress), rotateX: transform([0, 0.2], [15, 0])(progress), rotateZ: transform([0, 0.2], [20, 0])(progress), opacity: transform([0, 0.2], [0.2, 1])(progress), }; } onMouseEnter(event) { animate(event.target, { y: -20 }, this.animConfig); } onMouseLeave(event) { animate(event.target, { y: 0 }, this.animConfig); } openModal() { const modal = document.querySelector(".productModalContent"); const modalContainer = this.productModalTarget; modalContainer.style.opacity = 0; modalContainer.style.display = "flex"; animate(modalContainer, { opacity: 1 }); animate(modal, { y: "-100vh", opacity: 0 }, { duration: 0, delay: 0 }).then( () => { document.body.style.overflow = "hidden"; animate( modal, { y: 0, opacity: 1 }, { type: "spring", damping: 10, stiffness: 100 }, ); }, ); } closeModal() { const modalContainer = this.productModalTarget; const modal = document.querySelector(".productModalContent"); document.body.style.overflow = "auto"; const backDropAnim = animate(modalContainer, { opacity: 0 }); const modalAnim = animate( modal, { y: "-100vh", opacity: 0 }, { type: "spring", damping: 10, stiffness: 100 }, ); Promise.all([backDropAnim, modalAnim]).then(() => { modalContainer.style.display = "none"; }); } modalClick(event) { event.stopPropagation(); } }
rails generate authentication
flyctl launch
flyctl deploy
Talk is cheap, show me the code