Skilling Panel Components
Shared React components for consistent skilling panel layouts across Fletching, Cooking, Smelting, Smithing, Crafting, and Tanning interfaces.Overview
Added: March 26, 2026 (PR #1093) Purpose: Eliminate ~500 lines of duplicated styling and provide consistent visual language for all crafting/processing interfaces. Location:packages/client/src/game/panels/skilling/SkillingPanelShared.tsx
Components
SkillingPanelBody
Outer container for skilling panels with intro text and empty state handling.theme- Theme object fromuseThemeStorechildren- Panel content (recipe lists, quantity selectors)emptyMessage- Message to show when no recipes available (optional)intro- Introductory text explaining the panel (optional)
- Automatic empty state rendering when
emptyMessageprovided and no children - Intro text with secondary color styling
- Consistent padding and layout
SkillingSection
Section container for grouping related recipes or controls.theme- Theme objectchildren- Section contentclassName- Additional CSS classes (optional)style- Additional inline styles (optional)
- Rounded corners with border
- Panel secondary background
- Inset highlight for depth
- Consistent padding (12px)
SkillingQuantitySelector
Reusable quantity selector with preset buttons and custom input mode.theme- Theme objectshowCustomInput- Whether custom input mode is activecustomQuantity- Current custom quantity input valuelastCustomQuantity- Last custom quantity (for placeholder)onCustomQuantityChange- Handler for input value changesonCustomSubmit- Handler for custom quantity submissiononCancelCustomInput- Handler for cancelling custom inputonPresetQuantity- Handler for preset button clicks (1, 5, 10, All)allQuantity- Value for “All” button (-1 for max, or specific number like 28)onShowCustomInput- Handler for “X” button click
- Preset buttons: 1, 5, 10, All, X
- Custom input mode with Enter/Escape key handling
- Remembers last custom quantity (OSRS feature)
- Responsive grid layout (2 columns mobile, 5 columns desktop)
- Cancel button in custom input mode
Enter- Submit custom quantityEscape- Cancel custom input mode
Style Helpers
getSkillingSelectableStyle()
Generate consistent style for selectable recipe items.theme- Theme objectselected- Whether item is currently selecteddisabled- Whether item is disabled (optional, default: false)
- Selected: Accent primary background (18% opacity), accent border, inset glow
- Unselected: Dark background, default border
- Disabled: 48% opacity
getSkillingBadgeStyle()
Generate consistent style for info badges (level, XP, cost).theme- Theme object
- Dark background (rgba(6, 8, 12, 0.34))
- Default border
- Secondary text color
- Pill shape (rounded-full)
Example: Complete Skilling Panel
Migration from Old Panels
Before (Duplicated Code)
Each skilling panel had ~200 lines of duplicated styling:After (Shared Components)
Panels Using Shared Components
All skilling panels now use shared components:- FletchingPanel - Arrow shafts, bows, stringing, arrows
- CookingPanel - Fish, meat, bread (uses range/fire)
- SmeltingPanel - Bars from ores
- SmithingPanel - Weapons, armor, tools from bars
- CraftingPanel - Leather armor, jewelry, gem cutting
- TanningPanel - Hides to leather
- Same layout and spacing
- Same color scheme and hover states
- Same quantity selector behavior
- Same keyboard shortcuts
- Same responsive breakpoints
Accessibility
Keyboard Navigation
Tab- Navigate between recipe buttonsEnter/Space- Select recipe1,5,0(zero) - Quick quantity selectionX- Open custom quantity inputEnter- Submit custom quantityEscape- Cancel custom input
Screen Readers
- Recipe buttons have descriptive labels
- Quantity buttons announce their values
- Custom input has placeholder text
- Empty state messages are announced
Focus Management
- Focus trap within custom input mode
- Autofocus on custom input when opened
- Focus returns to “X” button after cancel
Theming
All components respect the active theme: Hyperscape Theme:- Warm gradients (bronze/gold accents)
- Subtle inset highlights
- Parchment-style backgrounds
- Accent primary color for selections
- Theme-specific backgrounds and borders
- Consistent with theme’s visual language
Performance
Memoization
Components useuseMemo for expensive style calculations:
Render Optimization
React.memonot used (components are lightweight)- Style objects memoized to prevent re-creation
- No expensive computations in render path
See Also
- FletchingPanel - Example usage
- CraftingPanel - Example usage
- SmithingPanel - Example usage
- Theme System - Theme definitions