duckly-ds
v0.1.3
Published
Duckly Design System - Neo-Brutalism style React components with bold borders, sharp shadows, and vibrant colors
Downloads
625
Maintainers
Readme
Duckly DS
Bold borders. Sharp shadows. Vibrant colors.
A Neo-Brutalism design system for React with 88+ components.
Installation
Install from npm:
npm install duckly-ds framer-motion lucide-reactSee the full Usage Guide for detailed setup instructions.
Optional Dependencies
Some components require additional peer dependencies:
| Dependency | Required For |
|------------|--------------|
| leaflet + react-leaflet | Map components (MapView, DistrictMarker, etc.) |
| socket.io-client | Real-time multiplayer features |
| zustand | State management integration |
| react-router-dom | Routing features |
# For map components
npm install leaflet react-leaflet
# For real-time features
npm install socket.io-client zustandRequired Fonts
This is required - add to your HTML <head>:
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=Cairo:wght@400;600;700&display=swap" rel="stylesheet">Or with Next.js:
// app/layout.tsx
import { Space_Grotesk, Cairo } from 'next/font/google'
const spaceGrotesk = Space_Grotesk({
subsets: ['latin'],
variable: '--font-sans'
})
const cairo = Cairo({
subsets: ['arabic'],
variable: '--font-arabic'
})
export default function RootLayout({ children }) {
return (
<html className={`${spaceGrotesk.variable} ${cairo.variable}`}>
<body>{children}</body>
</html>
)
}Quick Start (Standalone - No Tailwind Required)
The bundled CSS includes all styles. No Tailwind setup needed for basic usage:
import { Button, Card, Badge } from 'duckly-ds'
import 'duckly-ds/styles.css'
function App() {
return (
<Card>
<Badge>New</Badge>
<h2>Welcome to Duckly DS</h2>
<Button variant="neoBrutalism">Get Started</Button>
</Card>
)
}Tailwind CSS Integration (Optional)
For projects using Tailwind CSS, use the preset to access design tokens:
// tailwind.config.js
module.exports = {
presets: [require('duckly-ds/tailwind-preset')],
content: [
'./src/**/*.{js,ts,jsx,tsx}',
'./node_modules/duckly-ds/dist/**/*.js',
],
}This enables:
- Neo-Brutalism utility classes (
border-neo,shadow-neo,rounded-neo) - Design system colors (
bg-primary-orange,text-text-black) - Typography scale (
text-display-lg,text-body-md) - All spacing and animation tokens
Deep Imports (Tree-Shakeable)
Import from specific categories for smaller bundles:
// Tree-shakeable imports
import { Button, Card } from 'duckly-ds/ui'
import { Countdown, Leaderboard } from 'duckly-ds/game'
import { Confetti } from 'duckly-ds/effects'
import { ActionCard } from 'duckly-ds/patterns'
import { Header, Sidebar } from 'duckly-ds/layout'
import { useConfetti } from 'duckly-ds/hooks'
import { ThemeProvider } from 'duckly-ds/providers'
import { FormBuilder } from 'duckly-ds/forms'
import { colors, animations } from 'duckly-ds/tokens'Components (88 total)
UI Components (31)
Avatar, Badge, Box, Button, Card, CategoryCard, Checkbox, ConnectionStatusIndicator, Dialog, Dropdown, EmptyState, ErrorPage, FlexLayout, GridLayout, Icon, IconButton, Label, ListItem, LoadingSpinner, OTPInput, PhoneInput, Progress, Radio, RadioGroup, ScoreBadge, Surface, Text, TextField, Toast, Toggle, Typography
Layout Components (6)
AppScaffold, Header, Layout, PageContainer, SectionContainer, Sidebar
Game Components (38)
AnswerInput, CharacterSelector, Countdown, GameHUD, GameModeSelector, GameStatusBanner, HintDisplay, HistoryList, HostControls, HostIndicator, HowToPlayCard, InviteShareSheet, JoinRoom, Leaderboard, OptionButton, PhaseAnnouncement, PlayAgainPanel, PlayerList, PlayerMiniCards, PlayerNameplate, PlayerSetup, PromptDisplay, QuestionCard, ReactionButtons, ResultReveal, RoomCodeDisplay, RoundIndicator, RoundSettingsPanel, ScoreChangeAnimation, ScreenTransition, StatsSummary, StreakIndicator, TeamAssignment, TurnIndicator, VoteDisplay, WaitingRoom, WinnerPodium, YearInput
Map Subcomponents (5): DistrictMarker, GeoJSONLayer, MapControls, MapLegend, MapView
Notable Compound Components:
OptionButtonexports: OptionButton, OptionButtonGroupQuestionCardexports: QuestionCard, QuestionCardSimple, TriviaCardVoteDisplayexports: VoteDisplay, VoteNowOverlay, VotingTimer, StarRating, ThumbsVoting, VoteActions, PlayerVoteCard, OptionCard, ResponseCardTeamAssignmentexports: TeamAssignment, useTeamAssignment (hook)
Effects (2)
Confetti, GlowEffect
Patterns (6)
ActionCard, InfoCard, MediaCard, NotificationCard, ProfileCard, StatCard
Providers (1)
ThemeProvider
FormBuilder
Declarative form construction with React Hook Form and Zod validation:
import { FormBuilder } from 'duckly-ds/forms'
import { z } from 'zod'
const schema = z.object({
email: z.string().email(),
password: z.string().min(8),
})
function LoginForm() {
return (
<FormBuilder
schema={schema}
fields={[
{ name: 'email', type: 'email', label: 'Email' },
{ name: 'password', type: 'password', label: 'Password' },
]}
onSubmit={(data) => console.log(data)}
/>
)
}Also exports: useFormBuilder, FormBuilderField, FormBuilderSection, FormBuilderSubmit
Design Tokens
Full programmatic access to all design values:
import {
// Colors
colors,
primaryColors,
statusColors,
scoreColors,
getScoreColorKey,
// Typography
fontFamily,
fontSize,
textStyles,
// Spacing & Layout
spacing,
spacingValues,
// Shadows & Borders
shadows,
neoShadows,
borders,
borderRadius,
// Animations (Framer Motion ready)
animations,
duration,
easing,
transitions,
// Neo-Brutalism helpers
createNeoShadow,
createNeoBorder,
neoButtonTapAnimation,
neoCardHoverAnimation,
// WCAG Contrast utilities
getContrastRatio,
checkWcagCompliance,
suggestTextColor,
isAccessible,
} from 'duckly-ds/tokens'
// Use in Framer Motion
<motion.div whileTap={neoButtonTapAnimation} />
// Use in Canvas
ctx.fillStyle = colors.primary.orange
// Check accessibility
const ratio = getContrastRatio('#FF6B2E', '#1A1A1A') // 4.9:1Utilities
import { cn, isRTLText, getTextDirection } from 'duckly-ds'
// cn - Merge Tailwind classes (clsx + tailwind-merge)
cn('px-4 py-2', 'px-6') // 'px-6 py-2'
cn('text-red-500', condition && 'font-bold')
// RTL detection for Arabic text
isRTLText('مرحبا') // true
isRTLText('Hello') // false
getTextDirection('مرحبا') // 'rtl'
getTextDirection('Hello') // 'ltr'Checking for Updates
Check if a newer version is available:
npx duckly-ds check-updateOr programmatically:
import { checkForUpdates, useVersionCheck } from 'duckly-ds'
// Async function
const result = await checkForUpdates()
if (result.isOutdated) {
console.log(`Update: ${result.updateCommand}`)
}
// React hook
const { result, isChecking } = useVersionCheck()See the Usage Guide for more options.
Storybook
View all components and documentation:
https://duckly-ds-storybook.pages.dev
Neo-Brutalism Style
The design system implements these core principles:
- Bold Borders: 3px standard, 5px thick
- Sharp Shadows: Hard offset shadows without blur
- Vibrant Colors: Orange, Yellow, Blue primary palette
- High Contrast: Black borders on vibrant backgrounds
- Rounded Corners: Consistent 8px border radius
Browser Support
- Chrome (last 2 versions)
- Firefox (last 2 versions)
- Safari (last 2 versions)
- Edge (last 2 versions)
Development Worktrees
This project uses git worktrees for parallel development. Each worktree can run its own Storybook on a different port.
List Active Worktrees
git worktree listFind Which Worktree is Running on Which Port
# List all Node processes listening on ports
lsof -i -P -n | grep node | grep LISTEN
# Find which worktree a process belongs to (replace PID)
lsof -p <PID> | grep cwdRun Multiple Storybooks Simultaneously
# Main worktree (default port)
npm run dev # localhost:6006
# Other worktrees (specify different ports)
cd /path/to/worktree
npm run dev -- -p 6007 # localhost:6007
npm run dev -- -p 6008 # localhost:6008Recommended Port Convention
| Worktree | Branch | Port |
|----------|--------|------|
| main | main | 6006 |
| design_system | components_audit | 6007 |
| enhance_storybook | guidelines_tokens_stories | 6008 |
| package_setup | package_usge | 6009 |
Clean Up Merged Worktrees
# Remove worktree and delete merged branch
git worktree remove /path/to/worktree
git branch -d branch_nameReleasing
To publish a new version to npm:
# 1. Bump version (creates commit + tag automatically)
npm version patch # or minor/major
# 2. Push commits and tag
git push origin main --tagsnpm version automatically creates a commit and a vX.Y.Z tag. Pushing the tag triggers GitHub Actions to publish to npm.
Alternative: Push separately
npm version patch
git push origin main
git push origin v0.1.1 # push specific tagManual release (if tag doesn't exist)
npm run release:tagContributing
See CONTRIBUTING.md for development setup and guidelines.
License
CC-BY-NC-4.0 (Non-Commercial) - see LICENSE for details.
For commercial licensing, contact the author via GitHub.
