Bottom Sheet
GameBottomSheet is a slide-up panel from the bottom edge, commonly used in mobile games for menus, selections, and information displays.
Live Demo
🎮GameBottomSheet Component
Loading demo...
Features
- Slides up from bottom of screen
- Drag handle for visual affordance
- Swipe down to close gesture
- Height options: fixed pixel, auto, half screen, full screen
- Top-only rounded corners for native feel
- Extends GamePanel with all panel features
Basic Usage
import { GameBottomSheet, PanelManager } from '@gamebyte/framework';
const sheet = new GameBottomSheet({
height: 'half',
title: 'Select Item',
showHandle: true,
dragToClose: true
});
// Add content
const button = new GameStyleButton({ text: 'Option 1', width: 280 });
sheet.addContent(button.getContainer());
// Show using PanelManager
const panelManager = new PanelManager(stage, app.screen.width, app.screen.height);
panelManager.show(sheet);
Configuration Options
GameBottomSheet extends GamePanelConfig with bottom-sheet specific options:
interface GameBottomSheetConfig extends Omit<GamePanelConfig, 'height'> {
height?: BottomSheetHeight; // Height option (default: 'auto')
showHandle?: boolean; // Show drag handle (default: true)
dragToClose?: boolean; // Enable swipe to close (default: true)
animationDuration?: number; // Animation duration in ms (default: 300)
}
type BottomSheetHeight = number | 'auto' | 'half' | 'full';
Height Options
// Fixed pixel height
const fixedSheet = new GameBottomSheet({
height: 400 // 400 pixels tall
});
// Auto height (default: 400px)
const autoSheet = new GameBottomSheet({
height: 'auto'
});
// Half screen height (50%)
const halfSheet = new GameBottomSheet({
height: 'half'
});
// Full screen height (90%)
const fullSheet = new GameBottomSheet({
height: 'full'
});
Drag Handle
The drag handle is a visual indicator that the sheet can be dragged:
// With handle (default)
const withHandle = new GameBottomSheet({
showHandle: true,
dragToClose: true
});
// Without handle
const noHandle = new GameBottomSheet({
showHandle: false,
dragToClose: false // Usually disable drag too
});
Animation
GameBottomSheet slides in from the bottom:
// Faster animation
const fastSheet = new GameBottomSheet({
height: 'half',
animationDuration: 200
});
// Slower animation
const slowSheet = new GameBottomSheet({
height: 'half',
animationDuration: 500
});
Animation details:
- Show: Slides up from below screen with
easeOutCubic - Hide: Slides down with
easeInCubic - Snap back: If dragged but not far enough to close
Methods
Show/Hide
// Show sheet
panelManager.show(sheet);
// Close sheet
sheet.close();
Content
// Add content
sheet.addContent(myComponent);
// Clear content
sheet.clearContent();
Item Selection Sheet Example
import { GameBottomSheet, GameList, GameStyleButton } from '@gamebyte/framework';
function showItemPicker(
items: Item[],
onSelect: (item: Item) => void
): void {
const sheet = new GameBottomSheet({
height: 'half',
title: 'Select Item',
showHandle: true
});
const list = new GameList({ direction: 'vertical', gap: 12 });
items.forEach(item => {
const btn = new GameStyleButton({
text: item.name,
width: sheet.config.width - 40,
height: 60
});
btn.on('click', () => {
onSelect(item);
sheet.close();
});
list.addItem(btn.getContainer());
});
sheet.addContent(list.getContainer());
panelManager.show(sheet);
}
// Usage
showItemPicker(weapons, (weapon) => {
player.equip(weapon);
});
Level Complete Sheet Example
import {
GameBottomSheet,
GameStyleButton,
GameStyleColors
} from '@gamebyte/framework';
function showLevelComplete(score: number, stars: number): void {
const sheet = new GameBottomSheet({
height: 400,
title: '🎉 Level Complete!',
showHandle: false,
dragToClose: false,
closeOnOverlay: false
});
// Stars display
const starsText = graphics().createText('⭐'.repeat(stars), {
fontSize: 48
});
starsText.x = 100;
starsText.y = 20;
// Score
const scoreText = graphics().createText(`Score: ${score}`, {
fontSize: 28,
fill: 0xFFD700
});
scoreText.x = 120;
scoreText.y = 90;
// Buttons
const nextBtn = new GameStyleButton({
text: 'Next Level',
width: 200,
height: 60,
colorScheme: GameStyleColors.GREEN_BUTTON
});
nextBtn.setPosition(90, 160);
nextBtn.on('click', () => {
sheet.close();
loadNextLevel();
});
const replayBtn = new GameStyleButton({
text: 'Replay',
width: 140,
height: 50,
colorScheme: GameStyleColors.BLUE_BUTTON
});
replayBtn.setPosition(120, 240);
replayBtn.on('click', () => {
sheet.close();
replayLevel();
});
sheet.addContent(starsText);
sheet.addContent(scoreText);
sheet.addContent(nextBtn.getContainer());
sheet.addContent(replayBtn.getContainer());
panelManager.show(sheet);
}
Settings Sheet Example
import {
GameBottomSheet,
GameToggle,
GameSlider,
GameRadioGroup
} from '@gamebyte/framework';
class SettingsSheet extends GameBottomSheet {
constructor() {
super({
height: 'half',
title: 'Settings',
showHandle: true,
onClose: () => this.saveSettings()
});
this.buildUI();
}
private buildUI(): void {
let y = 0;
// Sound toggle row
const soundLabel = graphics().createText('Sound', { fontSize: 18 });
soundLabel.y = y;
const soundToggle = new GameToggle({
value: settings.sound,
onChange: (val) => settings.sound = val
});
soundToggle.setPosition(250, y);
y += 50;
// Music toggle row
const musicLabel = graphics().createText('Music', { fontSize: 18 });
musicLabel.y = y;
const musicToggle = new GameToggle({
value: settings.music,
onChange: (val) => settings.music = val
});
musicToggle.setPosition(250, y);
y += 60;
// Difficulty selection
const diffLabel = graphics().createText('Difficulty', { fontSize: 18 });
diffLabel.y = y;
y += 30;
const diffRadio = new GameRadioGroup({
options: [
{ label: 'Easy', value: 'easy' },
{ label: 'Normal', value: 'normal' },
{ label: 'Hard', value: 'hard' }
],
selectedValue: settings.difficulty,
direction: 'horizontal',
gap: 20,
onChange: (val) => settings.difficulty = val
});
diffRadio.setPosition(0, y);
// Add all content
this.addContent(soundLabel);
this.addContent(soundToggle.getContainer());
this.addContent(musicLabel);
this.addContent(musicToggle.getContainer());
this.addContent(diffLabel);
this.addContent(diffRadio.getContainer());
}
private saveSettings(): void {
saveSettingsToStorage(settings);
}
}
Drag-to-Close Behavior
When dragToClose is enabled:
- Drag from the handle area (top 50px)
- Drag down to pull the sheet
- Release after dragging 100+ pixels to close
- Release before 100px to snap back
// Disable drag to close for important content
const importantSheet = new GameBottomSheet({
height: 'half',
dragToClose: false, // Must use close button or action
closeOnOverlay: false
});
Visual Structure
GameBottomSheet uses specific styling:
- Overlay - Semi-transparent background
- Panel container - Full width at bottom
- Background - Top-only rounded corners (extends below screen)
- Drag handle - Centered pill shape at top
- Title - Positioned below handle
- Close button - Top right (if enabled)
- Content area - Scrollable area below title
Notes
- Bottom sheet spans full screen width
- Top corners are rounded, bottom extends below screen
- Swipe gesture only works from handle area
- Combine with GameScrollBox for long content
- Use
height: 'full'for content-heavy sheets