Menu Grid
Nokia-style 3x3 phone app menu with icons and labels
Size
Material
State
<div class="menu-grid-wrap">
<div class="menu-grid">
<div class="menu-grid-item active"><div class="mgi-icon">☎</div>PHONE</div>
<div class="menu-grid-item"><div class="mgi-icon">✉</div>MSG</div>
<div class="menu-grid-item"><div class="mgi-icon">⚙</div>SET</div>
<div class="menu-grid-item"><div class="mgi-icon">♫</div>MUSIC</div>
<div class="menu-grid-item"><div class="mgi-icon">📷</div>CAM</div>
<div class="menu-grid-item"><div class="mgi-icon">🌐</div>WEB</div>
</div>
</div> .menu-grid-wrap {
display: flex; flex-direction: column;
background: var(--bg-raised); border: 1px solid var(--border-subtle);
border-radius: var(--radius-lg); padding: 12px;
box-shadow: var(--shadow-deep); max-width: 200px;
}
.menu-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }
.menu-grid-item {
display: flex; flex-direction: column; align-items: center; justify-content: center;
gap: 4px; padding: 10px 6px; border-radius: var(--radius-md);
cursor: pointer; transition: background 0.12s;
font-family: var(--font-ui); font-size: 8px; font-weight: 500;
color: var(--text-muted); letter-spacing: 1px;
}
.menu-grid-item:hover { background: var(--glow-color); }
.menu-grid-item.active { background: var(--glow-color); color: var(--blue-info); }
.menu-grid-item .mgi-icon {
width: 24px; height: 24px; border-radius: var(--radius-sm);
display: flex; align-items: center; justify-content: center; font-size: 14px;
} API
| Class | Type | Description |
|---|---|---|
.menu-grid | Base | Primary component class |
.default | Size | Extra large variant |
.active | State | Active state |
Design Notes
Physical Analog
Reference devices: Nokia Series 40 app menu, Sony Ericsson main menu, Samsung SGH series phone menus. Mechanism: A matrix navigation pattern originating from feature phone operating systems. The 3x3 grid (or 3x4) maps to the phone's numeric keypad -- press 1 for the top-left app, 2 for top-center, etc. Each cell contains an icon and a short label. The grid is navigated via the D-pad with a visual highlight showing the currently selected cell.
Geometry
| Property | Value |
|---|---|
| Grid | 3-column via repeat(3, 1fr) |
| Gap | 6px |
| Wrapper max-width | 200px |
| Wrapper padding | 12px |
| Item padding | 10px 6px |
| Icon size | 24x24px |
CSS Recipe
Wrapper (.menu-grid-wrap)
.menu-grid-wrap {
display: flex; flex-direction: column;
background: var(--bg-raised); border: 1px solid var(--border-subtle);
border-radius: var(--radius-lg); padding: 12px;
box-shadow: var(--shadow-deep); max-width: 200px;
}
Grid (.menu-grid)
.menu-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }
Item (.menu-grid-item)
.menu-grid-item {
display: flex; flex-direction: column; align-items: center; justify-content: center;
gap: 4px; padding: 10px 6px; border-radius: var(--radius-md);
cursor: pointer; transition: background 0.12s;
font-family: var(--font-ui); font-size: 8px; font-weight: 500;
color: var(--text-muted); letter-spacing: 1px;
}
Hover
.menu-grid-item:hover { background: var(--glow-color); }
Active
.menu-grid-item.active { background: var(--glow-color); color: var(--blue-info); }
Icon (.mgi-icon)
.menu-grid-item .mgi-icon {
width: 24px; height: 24px; border-radius: var(--radius-sm);
display: flex; align-items: center; justify-content: center; font-size: 14px;
}
HTML Structure
<div class="menu-grid-wrap">
<div class="menu-grid">
<div class="menu-grid-item active"><div class="mgi-icon">☎</div>PHONE</div>
<div class="menu-grid-item"><div class="mgi-icon">✉</div>MSG</div>
<div class="menu-grid-item"><div class="mgi-icon">⚙</div>SET</div>
<div class="menu-grid-item"><div class="mgi-icon">♫</div>MUSIC</div>
<div class="menu-grid-item"><div class="mgi-icon">📷</div>CAM</div>
<div class="menu-grid-item"><div class="mgi-icon">🌐</div>WEB</div>
</div>
</div>
Size Variants
No size variants defined. Single default size.
Material Variants
No material variants. Uses standard raised panel surface (--bg-raised).
Theme Behavior
- Wrapper background swaps via
--bg-raisedtoken (dark:#1c1a18, light:#ffffff) - Shadow depth reduces in light mode via
--shadow-deeptoken - Text and border colors swap via theme tokens
Constraints
- MUST use 3-column grid layout to match phone keypad mapping
- MUST NOT exceed 200px max-width (phone screen proportion)
- MUST use
--radius-lgon wrapper to match device bezel curvature - MUST show hover background highlight using
--glow-color - Active item MUST use
--blue-infocolor (iPod-era selection blue)
Accessibility
- Each grid item should be a
<button>or haverole="menuitem" - Container should have
role="menu"orrole="grid" - Support arrow key navigation between grid items
- Active item should have
aria-current="true"
♿
Accessibility
- Element
- Use <nav> with aria-label
- Keyboard
- Arrow keys to navigate, Enter to select
- Focus
-
Visible focus indicator required. Use native browser focus ring or custom
:focus-visiblestyles.