mcpbeat Sign in

Responsive Mobile First Agent Skill

Mobile-first responsive patterns with sticky headers, floating CTAs, accessible navigation, and touch-friendly interactions. Use when implementing responsive layouts, mobile navigation, or ensuring touch-friendly UI.

3k tokens
context cost
the whole folder, loaded on every use
3
files
instructions only
0
copies elsewhere
how many repositories repackaged it
254
stars on the repo
on the repository, not the skill itself

Install

one command, takes just this skill from the repository
npx skills add https://github.com/BlackBeltTechnology/pi-agent-dashboard --skill responsive-mobile-first

What comes with it

2 948 bytes besides the instruction
SKILL.agent.md
SKILL.md.AGENTS.md

The instruction itself

12 sections, as written by the author

Responsive Mobile-First

Breakpoint Strategy

// Tailwind default breakpoints (mobile-first)
// sm: 640px
// md: 768px
// lg: 1024px
// xl: 1280px
// 2xl: 1536px

// Write base styles for mobile, add breakpoints for larger screens
<div className="
  px-4 md:px-6 lg:px-8        // Padding increases
  text-sm md:text-base         // Font size scales
  grid-cols-1 md:grid-cols-2   // Grid expands
">
// components/layout/Header.tsx
'use client';

import { useState, useEffect } from 'react';
import { cn } from '@/lib/utils';

export function Header() {
  const [isScrolled, setIsScrolled] = useState(false);

  useEffect(() => {
    const handleScroll = () => setIsScrolled(window.scrollY > 10);
    window.addEventListener('scroll', handleScroll);
    return () => window.removeEventListener('scroll', handleScroll);
  }, []);

  return (
    <header
      className={cn(
        'fixed top-0 left-0 right-0 z-50 transition-all duration-300',
        isScrolled
          ? 'bg-background/95 backdrop-blur-sm shadow-sm'
          : 'bg-transparent'
      )}
    >
      <nav className="container mx-auto px-4 h-16 flex items-center justify-between">
        <Logo />
        
        {/* Desktop Navigation */}
        <div className="hidden md:flex items-center gap-6">
          <NavLinks />
          <Button>Book Now</Button>
        </div>
        
        {/* Mobile Menu Button */}
        <MobileMenuButton className="md:hidden" />
      </nav>
    </header>
  );
}

Mobile Navigation Drawer

'use client';

import { useState } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import { X, Menu } from 'lucide-react';

export function MobileNav() {
  const [isOpen, setIsOpen] = useState(false);

  return (
    <>
      <button
        onClick={() => setIsOpen(true)}
        className="md:hidden p-2"
        aria-label="Open menu"
      >
        <Menu className="w-6 h-6" />
      </button>

      <AnimatePresence>
        {isOpen && (
          <>
            {/* Backdrop */}
            <motion.div
              initial={{ opacity: 0 }}
              animate={{ opacity: 1 }}
              exit={{ opacity: 0 }}
              onClick={() => setIsOpen(false)}
              className="fixed inset-0 bg-black/50 z-50 md:hidden"
            />
            
            {/* Drawer */}
            <motion.div
              initial={{ x: '100%' }}
              animate={{ x: 0 }}
              exit={{ x: '100%' }}
              transition={{ type: 'tween', duration: 0.3 }}
              className="fixed top-0 right-0 bottom-0 w-80 bg-background z-50 md:hidden"
            >
              <div className="p-4 flex justify-end">
                <button
                  onClick={() => setIsOpen(false)}
                  className="p-2"
                  aria-label="Close menu"
                >
                  <X className="w-6 h-6" />
                </button>
              </div>
              
              <nav className="px-4 space-y-4">
                <NavLink href="/" onClick={() => setIsOpen(false)}>
                  Home
                </NavLink>
                <NavLink href="/services" onClick={() => setIsOpen(false)}>
                  Services
                </NavLink>
                {/* More links */}
              </nav>
              
              <div className="absolute bottom-8 left-4 right-4">
                <Button className="w-full" size="lg">
                  Book a Session
                </Button>
              </div>
            </motion.div>
          </>
        )}
      </AnimatePresence>
    </>
  );
}

Floating Mobile CTA

// components/FloatingCTA.tsx
'use client';

import { useState, useEffect } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import Link from 'next/link';
import { useLocale } from 'next-intl';

export function FloatingCTA() {
  const [isVisible, setIsVisible] = useState(false);
  const locale = useLocale();

  useEffect(() => {
    const handleScroll = () => {
      // Show after scrolling past hero
      setIsVisible(window.scrollY > 500);
    };
    
    window.addEventListener('scroll', handleScroll);
    return () => window.removeEventListener('scroll', handleScroll);
  }, []);

  return (
    <AnimatePresence>
      {isVisible && (
        <motion.div
          initial={{ y: 100, opacity: 0 }}
          animate={{ y: 0, opacity: 1 }}
          exit={{ y: 100, opacity: 0 }}
          className="fixed bottom-6 left-4 right-4 z-40 md:hidden"
        >
          <Link
            href={`/${locale}/book`}
            className="block w-full bg-primary text-primary-foreground text-center py-4 rounded-full font-medium shadow-lg"
          >
            Book a Session
          </Link>
        </motion.div>
      )}
    </AnimatePresence>
  );
}

Responsive Grid Patterns

// 1-2-3 column grid
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 md:gap-6">
  {items.map(item => <Card key={item.id} {...item} />)}
</div>

// Sidebar layout
<div className="flex flex-col lg:flex-row gap-8">
  <main className="flex-1">{/* Main content */}</main>
  <aside className="w-full lg:w-80">{/* Sidebar */}</aside>
</div>

// Hero with text/image
<div className="flex flex-col-reverse md:flex-row items-center gap-8">
  <div className="flex-1">{/* Text content */}</div>
  <div className="w-full md:w-1/2">{/* Image */}</div>
</div>

Touch-Friendly Targets

// Minimum 44x44px touch targets
<button className="min-h-[44px] min-w-[44px] p-3">
  <Icon className="w-5 h-5" />
</button>

// Adequate spacing between interactive elements
<div className="flex gap-3">
  <Button>Primary</Button>
  <Button variant="outline">Secondary</Button>
</div>

// Large tap areas for cards
<Link href={href} className="block p-4 md:p-6">
  <Card />
</Link>

Responsive Typography

// Heading scale
<h1 className="text-3xl md:text-4xl lg:text-5xl xl:text-6xl font-bold">
  Main Heading
</h1>

<h2 className="text-2xl md:text-3xl lg:text-4xl font-semibold">
  Section Heading
</h2>

// Body text
<p className="text-base md:text-lg leading-relaxed">
  Body content with comfortable reading line height.
</p>

// Small text
<span className="text-xs md:text-sm text-muted-foreground">
  Caption or meta text
</span>

Responsive Spacing

// Section padding
<section className="py-12 md:py-16 lg:py-24">

// Container with responsive padding
<div className="container mx-auto px-4 md:px-6 lg:px-8">

// Stack spacing
<div className="space-y-4 md:space-y-6 lg:space-y-8">

Hide/Show Utilities

// Show only on mobile
<div className="block md:hidden">Mobile only</div>

// Show only on desktop
<div className="hidden md:block">Desktop only</div>

// Different content per breakpoint
<span className="md:hidden">Menu</span>
<span className="hidden md:inline">Navigation</span>

Responsive Images

import Image from 'next/image';

// Full-width responsive image
<div className="relative aspect-video w-full">
  <Image
    src="/hero.jpg"
    alt="Hero"
    fill
    className="object-cover"
    sizes="100vw"
    priority
  />
</div>

// Responsive sizes attribute
<Image
  src="/service.jpg"
  alt="Service"
  fill
  sizes="(max-width: 768px) 100vw, (max-width: 1024px) 50vw, 33vw"
/>

Container Component

// components/shared/Container.tsx
import { cn } from '@/lib/utils';

interface ContainerProps {
  children: React.ReactNode;
  className?: string;
  size?: 'default' | 'narrow' | 'wide';
}

export function Container({ 
  children, 
  className,
  size = 'default' 
}: ContainerProps) {
  return (
    <div
      className={cn(
        'mx-auto px-4 md:px-6',
        {
          'max-w-7xl': size === 'default',
          'max-w-4xl': size === 'narrow',
          'max-w-screen-2xl': size === 'wide',
        },
        className
      )}
    >
      {children}
    </div>
  );
}

How to use it

Copy the folder

Take blackbelttechnology/responsive-mobile-first from the repository into ~/.claude/skills for personal use, or into .claude/skills inside a project.

Check the name does not clash

The agent identifies a skill by the name field in its header. Two skills with the same name cannot sit side by side — one of them will be ignored.