Bottom Sheet
Cancelable
Cancelable (true)
Esc and outside-tap (scrim) dismiss the sheet.
Not cancelable (false)
Esc and scrim taps are ignored. Use close() from the parent.
Code
<mdc-bottom-sheet id="bs-cancelable-true" variant="modal" cancelable>
<h2 style="margin: 0 0 8px 0; font: var(--mdc-typescale-title-medium);">Cancelable (true)</h2>
<p>Esc and outside-tap (scrim) dismiss the sheet.</p>
</mdc-bottom-sheet>
<mdc-bottom-sheet id="bs-cancelable-false" variant="modal" cancelable="false">
<h2 style="margin: 0 0 8px 0; font: var(--mdc-typescale-title-medium);">Not cancelable (false)</h2>
<p>Esc and scrim taps are ignored. Use <code>close()</code> from the parent.</p>
</mdc-bottom-sheet>
<mdc-button onclick="this.getRootNode().querySelector('#bs-cancelable-true').show()"><span>Cancelable</span></mdc-button>
<mdc-button onclick="this.getRootNode().querySelector('#bs-cancelable-false').show()"><span>Not cancelable</span></mdc-button>Detent
Recent Files (Peek Detent - Header Slot)
Default compact height (~40vh)Order & Inventory Report (Full Detent - All Slots)
Expanded full viewport (~96vh) with tabular data| Item ID | Product Name | Category | Status | Stock | Unit Price |
|---|---|---|---|---|---|
#PRD-1092 |
Pixel 9 Pro XL | Hardware | In Stock | 142 | $1,099.00 |
#PRD-1093 |
Pixel Watch 3 (45mm) | Wearables | In Stock | 68 | $399.00 |
#PRD-1094 |
Pixel Buds Pro 2 | Audio | Low Stock | 12 | $229.00 |
#PRD-1095 |
45W USB-C Fast Charger | Accessories | In Stock | 310 | $29.99 |
#PRD-1096 |
M3E Folio Protective Case | Accessories | In Stock | 85 | $49.99 |
Code
<style>
.demo-sheet-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 12px;
}
.demo-sheet-title {
margin: 0;
font: var(--mdc-typescale-title-medium, 500 1rem/1.5rem system-ui);
}
.demo-table-container {
width: 100%;
overflow-x: auto;
margin: 12px 0;
}
.demo-table {
width: 100%;
border-collapse: collapse;
text-align: left;
font: var(--mdc-typescale-body-medium, 400 0.875rem/1.25rem system-ui);
}
.demo-table th {
padding: 10px 12px;
background: var(--mdc-color-surface-container-high, #ece6f0);
font: var(--mdc-typescale-label-large, 500 0.875rem/1.25rem system-ui);
border-bottom: 2px solid var(--mdc-color-outline-variant, #cac4d0);
}
.demo-table td {
padding: 10px 12px;
border-bottom: 1px solid var(--mdc-color-outline-variant, #cac4d0);
}
.demo-table tr:hover td {
background: var(--mdc-color-surface-container-lowest, #fdf8fd);
}
.demo-badge-success {
display: inline-block;
padding: 2px 8px;
border-radius: 12px;
font-size: 11px;
font-weight: 500;
background: #e8f5e9;
color: #2e7d32;
}
.demo-badge-warning {
display: inline-block;
padding: 2px 8px;
border-radius: 12px;
font-size: 11px;
font-weight: 500;
background: #fff3e0;
color: #e65100;
}
</style>
<mdc-bottom-sheet id="bs-detent-peek" variant="modal" detent="peek">
<div slot="header" class="demo-sheet-header">
<div>
<h2 class="demo-sheet-title">Recent Files (Peek Detent - Header Slot)</h2>
<span style="font: var(--mdc-typescale-body-small); opacity: 0.7;">Default compact height (~40vh)</span>
</div>
<mdc-button variant="text" onclick="this.closest('mdc-bottom-sheet').close()"><span>Close</span></mdc-button>
</div>
<mdc-list aria-label="Recent files list">
<mdc-list-item type="button">
<mdc-icon slot="start">description</mdc-icon>
<span>Q3_Financial_Report.pdf</span>
<span slot="supporting-text">Modified 2 hours ago · 2.4 MB</span>
<mdc-icon slot="end">more_vert</mdc-icon>
</mdc-list-item>
<mdc-list-item type="button">
<mdc-icon slot="start">image</mdc-icon>
<span>Design_System_M3E_Hero.png</span>
<span slot="supporting-text">Modified Yesterday · 14.8 MB</span>
<mdc-icon slot="end">more_vert</mdc-icon>
</mdc-list-item>
<mdc-list-item type="button">
<mdc-icon slot="start">code</mdc-icon>
<span>bottom-sheet.animation.ts</span>
<span slot="supporting-text">Modified 3 days ago · 5.6 KB</span>
<mdc-icon slot="end">more_vert</mdc-icon>
</mdc-list-item>
</mdc-list>
</mdc-bottom-sheet>
<mdc-bottom-sheet id="bs-detent-full" variant="modal" detent="full">
<div slot="header" class="demo-sheet-header">
<div>
<h2 class="demo-sheet-title">Order & Inventory Report (Full Detent - All Slots)</h2>
<span style="font: var(--mdc-typescale-body-small); opacity: 0.7;">Expanded full viewport (~96vh) with tabular data</span>
</div>
<mdc-button variant="text" onclick="this.closest('mdc-bottom-sheet').close()"><span>Close</span></mdc-button>
</div>
<div class="demo-table-container">
<table class="demo-table">
<thead>
<tr>
<th>Item ID</th>
<th>Product Name</th>
<th>Category</th>
<th>Status</th>
<th>Stock</th>
<th>Unit Price</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>#PRD-1092</code></td>
<td><b>Pixel 9 Pro XL</b></td>
<td>Hardware</td>
<td><span class="demo-badge-success">In Stock</span></td>
<td>142</td>
<td>$1,099.00</td>
</tr>
<tr>
<td><code>#PRD-1093</code></td>
<td><b>Pixel Watch 3 (45mm)</b></td>
<td>Wearables</td>
<td><span class="demo-badge-success">In Stock</span></td>
<td>68</td>
<td>$399.00</td>
</tr>
<tr>
<td><code>#PRD-1094</code></td>
<td><b>Pixel Buds Pro 2</b></td>
<td>Audio</td>
<td><span class="demo-badge-warning">Low Stock</span></td>
<td>12</td>
<td>$229.00</td>
</tr>
<tr>
<td><code>#PRD-1095</code></td>
<td><b>45W USB-C Fast Charger</b></td>
<td>Accessories</td>
<td><span class="demo-badge-success">In Stock</span></td>
<td>310</td>
<td>$29.99</td>
</tr>
<tr>
<td><code>#PRD-1096</code></td>
<td><b>M3E Folio Protective Case</b></td>
<td>Accessories</td>
<td><span class="demo-badge-success">In Stock</span></td>
<td>85</td>
<td>$49.99</td>
</tr>
</tbody>
</table>
</div>
<div style="display: flex; justify-content: flex-end; gap: 8px; margin-top: 16px;">
<mdc-button variant="outlined" onclick="this.closest('mdc-bottom-sheet').close()"><span>Export CSV</span></mdc-button>
<mdc-button variant="filled" onclick="this.closest('mdc-bottom-sheet').close()"><span>Done</span></mdc-button>
</div>
</mdc-bottom-sheet>
<mdc-button onclick="this.getRootNode().querySelector('#bs-detent-peek').show()"><span>Peek (File List)</span></mdc-button>
<mdc-button onclick="this.getRootNode().querySelector('#bs-detent-full').show()"><span>Full (Data Table)</span></mdc-button>Draggable
Create & Edit Tools (Draggable)
Drag handle down to dismiss; release to snap backMore Options
Privacy Permissions (Non-Draggable)
Swipe gestures disabled — must confirm or close explicitlyCode
<style>
.demo-sheet-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 12px;
}
.demo-sheet-title {
margin: 0;
font: var(--mdc-typescale-title-medium, 500 1rem/1.5rem system-ui);
}
.demo-tool-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 12px 8px;
text-align: center;
margin: 12px 0;
}
.demo-tool-btn {
display: flex;
flex-direction: column;
align-items: center;
gap: 6px;
cursor: pointer;
background: none;
border: none;
padding: 4px;
color: inherit;
font: var(--mdc-typescale-label-medium, 500 0.75rem/1rem system-ui);
}
.demo-tool-icon-box {
width: 44px;
height: 44px;
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
background: var(--mdc-color-surface-container-high, #ece6f0);
color: var(--mdc-color-primary, #6750a4);
transition: transform 0.15s ease;
}
.demo-tool-btn:hover .demo-tool-icon-box {
transform: translateY(-2px);
}
</style>
<mdc-bottom-sheet id="bs-draggable-true" variant="modal" detent="peek" draggable>
<div class="demo-sheet-header">
<div>
<h2 class="demo-sheet-title">Create & Edit Tools (Draggable)</h2>
<span style="font: var(--mdc-typescale-body-small); opacity: 0.7;">Drag handle down to dismiss; release to snap back</span>
</div>
<mdc-button variant="text" onclick="this.closest('mdc-bottom-sheet').close()"><span>Close</span></mdc-button>
</div>
<!-- Tool Grid -->
<div class="demo-tool-grid">
<button class="demo-tool-btn" type="button">
<div class="demo-tool-icon-box"><mdc-icon>add_photo_alternate</mdc-icon></div>
<span>Photo</span>
</button>
<button class="demo-tool-btn" type="button">
<div class="demo-tool-icon-box"><mdc-icon>document_scanner</mdc-icon></div>
<span>Scan doc</span>
</button>
<button class="demo-tool-btn" type="button">
<div class="demo-tool-icon-box"><mdc-icon>mic</mdc-icon></div>
<span>Audio</span>
</button>
<button class="demo-tool-btn" type="button">
<div class="demo-tool-icon-box"><mdc-icon>draw</mdc-icon></div>
<span>Draw</span>
</button>
</div>
<mdc-divider style="margin: 16px 0;"></mdc-divider>
<!-- Detailed List Section -->
<div style="font: var(--mdc-typescale-label-large); opacity: 0.8; margin-bottom: 4px;">More Options</div>
<mdc-list aria-label="Tool options">
<mdc-list-item type="button">
<mdc-icon slot="start">folder_open</mdc-icon>
<span>Import from Google Drive</span>
<span slot="supporting-text">Synced automatically with workspace</span>
<mdc-icon slot="end">chevron_right</mdc-icon>
</mdc-list-item>
<mdc-list-item type="button">
<mdc-icon slot="start">settings</mdc-icon>
<span>Canvas & Grid Settings</span>
<span slot="supporting-text">Customize background, snap-to-grid</span>
<mdc-icon slot="end">chevron_right</mdc-icon>
</mdc-list-item>
</mdc-list>
</mdc-bottom-sheet>
<mdc-bottom-sheet id="bs-draggable-false" variant="modal" detent="peek" draggable="false">
<div class="demo-sheet-header">
<div>
<h2 class="demo-sheet-title">Privacy Permissions (Non-Draggable)</h2>
<span style="font: var(--mdc-typescale-body-small); opacity: 0.7;">Swipe gestures disabled — must confirm or close explicitly</span>
</div>
<mdc-button variant="text" onclick="this.closest('mdc-bottom-sheet').close()"><span>Cancel</span></mdc-button>
</div>
<mdc-list aria-label="Privacy checkboxes">
<mdc-list-item type="text">
<mdc-checkbox slot="control" checked></mdc-checkbox>
<span>Location Access</span>
<span slot="supporting-text">Allow app to use precise location</span>
</mdc-list-item>
<mdc-list-item type="text">
<mdc-checkbox slot="control" checked></mdc-checkbox>
<span>Camera & Microphone</span>
<span slot="supporting-text">Required for video call capture</span>
</mdc-list-item>
<mdc-list-item type="text">
<mdc-checkbox slot="control"></mdc-checkbox>
<span>Diagnostic Telemetry</span>
<span slot="supporting-text">Help improve performance and stability</span>
</mdc-list-item>
</mdc-list>
<div style="display: flex; justify-content: flex-end; gap: 8px; margin-top: 16px;">
<mdc-button variant="filled" onclick="this.closest('mdc-bottom-sheet').close()"><span>Save Preferences</span></mdc-button>
</div>
</mdc-bottom-sheet>
<mdc-button onclick="this.getRootNode().querySelector('#bs-draggable-true').show()"><span>Draggable (Grid + Divider + List)</span></mdc-button>
<mdc-button onclick="this.getRootNode().querySelector('#bs-draggable-false').show()"><span>Static (Permission Checkboxes)</span></mdc-button>Hide Drag Handle
Handle Visible (Default)
Code
<mdc-bottom-sheet id="bs-handle-shown" variant="modal">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px;">
<h2 style="margin: 0; font: var(--mdc-typescale-title-medium);">Handle Visible (Default)</h2>
<mdc-button variant="text" onclick="this.closest('mdc-bottom-sheet').close()"><span>Close</span></mdc-button>
</div>
<mdc-list aria-label="Audio output devices">
<mdc-list-item type="button">
<mdc-icon slot="start">speaker</mdc-icon>
<span>Living Room Soundbar</span>
<span slot="supporting-text">Connected · 85% Volume</span>
</mdc-list-item>
<mdc-list-item type="button">
<mdc-icon slot="start">headphones</mdc-icon>
<span>Pixel Buds Pro 2</span>
<span slot="supporting-text">Bluetooth · Active Noise Cancellation</span>
</mdc-list-item>
</mdc-list>
</mdc-bottom-sheet>
<mdc-bottom-sheet id="bs-handle-hidden" variant="modal" hide-drag-handle>
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px;">
<div>
<h2 style="margin: 0; font: var(--mdc-typescale-title-medium);">Handle Hidden (Seamless)</h2>
<span style="font: var(--mdc-typescale-body-small); opacity: 0.7;">Top region is still draggable</span>
</div>
<mdc-button variant="text" onclick="this.closest('mdc-bottom-sheet').close()"><span>Done</span></mdc-button>
</div>
<mdc-list aria-label="Network connections">
<mdc-list-item type="button">
<mdc-icon slot="start">wifi</mdc-icon>
<span>Office-5G-Ultra</span>
<span slot="supporting-text">Connected · 1200 Mbps</span>
<mdc-icon slot="end">check</mdc-icon>
</mdc-list-item>
<mdc-list-item type="button">
<mdc-icon slot="start">signal_cellular_alt</mdc-icon>
<span>5G Mobile Data</span>
<span slot="supporting-text">Carrier fallback enabled</span>
</mdc-list-item>
</mdc-list>
</mdc-bottom-sheet>
<mdc-button onclick="this.getRootNode().querySelector('#bs-handle-shown').show()"><span>Handle visible</span></mdc-button>
<mdc-button onclick="this.getRootNode().querySelector('#bs-handle-hidden').show()"><span>Handle hidden</span></mdc-button>Max Height
Task List (No max-height cap)
Container height natural with contentTransaction Ledger (max-height: 400px)
Capped at 400px; internal table scrolls vertically| Tx ID | Description | Date | Amount |
|---|---|---|---|
#TX-901 | AWS Cloud Infrastructure | Aug 20 | -$142.50 |
#TX-902 | Figma Organization License | Aug 19 | -$45.00 |
#TX-903 | Google Workspace Subscription | Aug 18 | -$72.00 |
#TX-904 | Client Payment - Acme Corp | Aug 17 | +$3,400.00 |
#TX-905 | GitHub Enterprise Seats | Aug 16 | -$84.00 |
#TX-906 | Domain Registration Renewal | Aug 15 | -$18.00 |
#TX-907 | Stripe Processing Payout | Aug 14 | +$1,280.00 |
#TX-908 | Vercel Pro Team Plan | Aug 13 | -$20.00 |
Code
<style>
.demo-sheet-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 12px;
}
.demo-sheet-title {
margin: 0;
font: var(--mdc-typescale-title-medium, 500 1rem/1.5rem system-ui);
}
.demo-table-container {
width: 100%;
overflow-x: auto;
margin: 12px 0;
}
.demo-table {
width: 100%;
border-collapse: collapse;
text-align: left;
font: var(--mdc-typescale-body-medium, 400 0.875rem/1.25rem system-ui);
}
.demo-table th {
padding: 8px 12px;
background: var(--mdc-color-surface-container-high, #ece6f0);
font: var(--mdc-typescale-label-large, 500 0.875rem/1.25rem system-ui);
border-bottom: 2px solid var(--mdc-color-outline-variant, #cac4d0);
}
.demo-table td {
padding: 8px 12px;
border-bottom: 1px solid var(--mdc-color-outline-variant, #cac4d0);
}
</style>
<mdc-bottom-sheet id="bs-maxheight-0" variant="modal" max-height="0">
<div class="demo-sheet-header">
<div>
<h2 class="demo-sheet-title">Task List (No max-height cap)</h2>
<span style="font: var(--mdc-typescale-body-small); opacity: 0.7;">Container height natural with content</span>
</div>
<mdc-button variant="text" onclick="this.closest('mdc-bottom-sheet').close()"><span>Close</span></mdc-button>
</div>
<mdc-list aria-label="Tasks list">
<mdc-list-item type="text">
<mdc-checkbox slot="control" checked></mdc-checkbox>
<span>Review M3 Expressive Tokens Specification</span>
<span slot="supporting-text">Completed by Engineering team</span>
</mdc-list-item>
<mdc-list-item type="text">
<mdc-checkbox slot="control"></mdc-checkbox>
<span>Implement Drag-to-Dismiss Gestures</span>
<span slot="supporting-text">In Progress · ETA Today</span>
</mdc-list-item>
<mdc-list-item type="text">
<mdc-checkbox slot="control"></mdc-checkbox>
<span>Add Comprehensive Interactive Demos</span>
<span slot="supporting-text">Pending Review</span>
</mdc-list-item>
</mdc-list>
</mdc-bottom-sheet>
<mdc-bottom-sheet id="bs-maxheight-400" variant="modal" max-height="400">
<div class="demo-sheet-header">
<div>
<h2 class="demo-sheet-title">Transaction Ledger (max-height: 400px)</h2>
<span style="font: var(--mdc-typescale-body-small); opacity: 0.7;">Capped at 400px; internal table scrolls vertically</span>
</div>
<mdc-button variant="text" onclick="this.closest('mdc-bottom-sheet').close()"><span>Close</span></mdc-button>
</div>
<div class="demo-table-container">
<table class="demo-table">
<thead>
<tr>
<th>Tx ID</th>
<th>Description</th>
<th>Date</th>
<th>Amount</th>
</tr>
</thead>
<tbody>
<tr><td><code>#TX-901</code></td><td>AWS Cloud Infrastructure</td><td>Aug 20</td><td>-$142.50</td></tr>
<tr><td><code>#TX-902</code></td><td>Figma Organization License</td><td>Aug 19</td><td>-$45.00</td></tr>
<tr><td><code>#TX-903</code></td><td>Google Workspace Subscription</td><td>Aug 18</td><td>-$72.00</td></tr>
<tr><td><code>#TX-904</code></td><td>Client Payment - Acme Corp</td><td>Aug 17</td><td>+$3,400.00</td></tr>
<tr><td><code>#TX-905</code></td><td>GitHub Enterprise Seats</td><td>Aug 16</td><td>-$84.00</td></tr>
<tr><td><code>#TX-906</code></td><td>Domain Registration Renewal</td><td>Aug 15</td><td>-$18.00</td></tr>
<tr><td><code>#TX-907</code></td><td>Stripe Processing Payout</td><td>Aug 14</td><td>+$1,280.00</td></tr>
<tr><td><code>#TX-908</code></td><td>Vercel Pro Team Plan</td><td>Aug 13</td><td>-$20.00</td></tr>
</tbody>
</table>
</div>
</mdc-bottom-sheet>
<mdc-button onclick="this.getRootNode().querySelector('#bs-maxheight-0').show()"><span>Natural Height (Task List)</span></mdc-button>
<mdc-button onclick="this.getRootNode().querySelector('#bs-maxheight-400').show()"><span>400px Cap (Scrollable Table)</span></mdc-button>No Focus Trap
Focus trap enabled (default)
Tab cycles within the sheet. Try tabbing from the buttons.
Focus trap disabled
Tab leaves the sheet and moves to the page.
Code
<mdc-bottom-sheet id="bs-focus-trap-on" variant="modal">
<h2 style="margin: 0 0 8px 0; font: var(--mdc-typescale-title-medium);">Focus trap enabled (default)</h2>
<p>Tab cycles within the sheet. Try tabbing from the buttons.</p>
<mdc-button variant="text"><span>First</span></mdc-button>
<mdc-button variant="text"><span>Last</span></mdc-button>
</mdc-bottom-sheet>
<mdc-bottom-sheet id="bs-focus-trap-off" variant="modal" no-focus-trap>
<h2 style="margin: 0 0 8px 0; font: var(--mdc-typescale-title-medium);">Focus trap disabled</h2>
<p>Tab leaves the sheet and moves to the page.</p>
<mdc-button variant="text"><span>First</span></mdc-button>
<mdc-button variant="text"><span>Last</span></mdc-button>
</mdc-bottom-sheet>
<mdc-button onclick="this.getRootNode().querySelector('#bs-focus-trap-on').show()"><span>Trap enabled</span></mdc-button>
<mdc-button onclick="this.getRootNode().querySelector('#bs-focus-trap-off').show()"><span>Trap disabled</span></mdc-button>Open
Opened via show()
Imperative: sheet.show() sets open and promotes the dialog to the top layer.
Opened via the open property
Declarative: setting open = true (or the open attribute) drives the same lifecycle.
Code
<mdc-bottom-sheet id="bs-open-imperative" variant="modal">
<h2 style="margin: 0 0 8px 0; font: var(--mdc-typescale-title-medium);">Opened via show()</h2>
<p>Imperative: <code>sheet.show()</code> sets <code>open</code> and promotes the dialog to the top layer.</p>
</mdc-bottom-sheet>
<mdc-bottom-sheet id="bs-open-declarative" variant="modal" open>
<h2 style="margin: 0 0 8px 0; font: var(--mdc-typescale-title-medium);">Opened via the open property</h2>
<p>Declarative: setting <code>open = true</code> (or the <code>open</code> attribute) drives the same lifecycle.</p>
</mdc-bottom-sheet>
<mdc-button onclick="this.getRootNode().querySelector('#bs-open-imperative').show()"><span>show()</span></mdc-button>Quick
Quick (true)
Open / close jump directly to the target state — no animation.
Quick (false, default)
Open / close animate via WAAPI.
Code
<mdc-bottom-sheet id="bs-quick-true" variant="modal" quick>
<h2 style="margin: 0 0 8px 0; font: var(--mdc-typescale-title-medium);">Quick (true)</h2>
<p>Open / close jump directly to the target state — no animation.</p>
</mdc-bottom-sheet>
<mdc-bottom-sheet id="bs-quick-false" variant="modal">
<h2 style="margin: 0 0 8px 0; font: var(--mdc-typescale-title-medium);">Quick (false, default)</h2>
<p>Open / close animate via WAAPI.</p>
</mdc-bottom-sheet>
<mdc-button onclick="this.getRootNode().querySelector('#bs-quick-true').show()"><span>Quick</span></mdc-button>
<mdc-button onclick="this.getRootNode().querySelector('#bs-quick-false').show()"><span>Animated</span></mdc-button>Variant
3 Photos Selected (Google Photos style)
Standard Sheet · No scrim · Background 100% interactiveDetailed Information & Operations
Captured on August 20, 2026 · Sony A7R V · 24-70mm F2.8 GM II · Location: Tokyo, Japan
Share & Actions (Modal with Scrim)
Share via
Actions
Code
<style>
.demo-sheet-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16px;
}
.demo-sheet-title {
margin: 0;
font: var(--mdc-typescale-title-medium, 500 1rem/1.5rem system-ui);
}
.demo-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 16px 8px;
text-align: center;
margin: 12px 0;
}
.demo-grid-item {
display: flex;
flex-direction: column;
align-items: center;
gap: 6px;
cursor: pointer;
background: none;
border: none;
padding: 4px;
color: inherit;
font: var(--mdc-typescale-label-medium, 500 0.75rem/1rem system-ui);
}
.demo-grid-icon-circle {
width: 48px;
height: 48px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
background: var(--mdc-color-surface-container-high, #ece6f0);
color: var(--mdc-color-primary, #6750a4);
transition: transform 0.15s ease;
}
.demo-grid-item:hover .demo-grid-icon-circle {
transform: scale(1.08);
}
</style>
<!-- Standard variant: 3 states (Closed, Peek [Header only], Full [Header + Content]) -->
<mdc-bottom-sheet id="bs-variant-standard" variant="standard" detent="peek">
<div slot="header" class="demo-sheet-header">
<div>
<h2 class="demo-sheet-title">3 Photos Selected (Google Photos style)</h2>
<span style="font: var(--mdc-typescale-body-small); opacity: 0.7;">Standard Sheet · No scrim · Background 100% interactive</span>
</div>
<div style="display: flex; gap: 8px;">
<mdc-button
variant="outlined"
onclick="const s = this.closest('mdc-bottom-sheet'); s.detent = s.detent === 'peek' ? 'full' : 'peek'"
>
<span>Toggle Peek / Full</span>
</mdc-button>
<mdc-button variant="text" onclick="this.closest('mdc-bottom-sheet').close()"><span>Close</span></mdc-button>
</div>
</div>
<!-- Lower slot (content / details): displayed only in 'full' state -->
<div style="margin-top: 8px;">
<h3 style="margin: 0 0 8px 0; font: var(--mdc-typescale-title-small);">Detailed Information & Operations</h3>
<p style="margin: 0 0 12px 0; font: var(--mdc-typescale-body-small); opacity: 0.8;">
Captured on August 20, 2026 · Sony A7R V · 24-70mm F2.8 GM II · Location: Tokyo, Japan
</p>
<mdc-list aria-label="Photo operations">
<mdc-list-item type="button">
<mdc-icon slot="start">share</mdc-icon>
<span>Share Album to Contacts</span>
<span slot="supporting-text">Send high-res link via cloud</span>
<mdc-icon slot="end">chevron_right</mdc-icon>
</mdc-list-item>
<mdc-list-item type="button">
<mdc-icon slot="start">auto_fix_high</mdc-icon>
<span>Enhance & Magic Eraser</span>
<span slot="supporting-text">AI background cleanup & color boost</span>
<mdc-icon slot="end">chevron_right</mdc-icon>
</mdc-list-item>
<mdc-list-item type="button">
<mdc-icon slot="start">drive_file_move</mdc-icon>
<span>Move to Locked Folder</span>
<span slot="supporting-text">Protected by biometrics</span>
<mdc-icon slot="end">chevron_right</mdc-icon>
</mdc-list-item>
<mdc-list-item type="button">
<mdc-icon slot="start">delete_outline</mdc-icon>
<span>Move to Trash</span>
<span slot="supporting-text">Items in trash deleted after 30 days</span>
<mdc-icon slot="end">chevron_right</mdc-icon>
</mdc-list-item>
</mdc-list>
</div>
</mdc-bottom-sheet>
<!-- Modal variant -->
<mdc-bottom-sheet id="bs-variant-modal" variant="modal">
<div slot="header" class="demo-sheet-header">
<h2 class="demo-sheet-title">Share & Actions (Modal with Scrim)</h2>
<mdc-button variant="text" onclick="this.closest('mdc-bottom-sheet').close()"><span>Done</span></mdc-button>
</div>
<!-- First Grid Section: Share channels -->
<div style="font: var(--mdc-typescale-label-large); opacity: 0.8; margin-bottom: 4px;">Share via</div>
<div class="demo-grid">
<button class="demo-grid-item" type="button">
<div class="demo-grid-icon-circle"><mdc-icon>chat</mdc-icon></div>
<span>Messages</span>
</button>
<button class="demo-grid-item" type="button">
<div class="demo-grid-icon-circle"><mdc-icon>mail</mdc-icon></div>
<span>Email</span>
</button>
<button class="demo-grid-item" type="button">
<div class="demo-grid-icon-circle"><mdc-icon>cloud_upload</mdc-icon></div>
<span>Drive</span>
</button>
<button class="demo-grid-item" type="button">
<div class="demo-grid-icon-circle"><mdc-icon>bluetooth</mdc-icon></div>
<span>Nearby</span>
</button>
</div>
<mdc-divider style="margin: 16px 0;"></mdc-divider>
<!-- Second Grid Section: File Actions -->
<div style="font: var(--mdc-typescale-label-large); opacity: 0.8; margin-bottom: 4px;">Actions</div>
<div class="demo-grid">
<button class="demo-grid-item" type="button">
<div class="demo-grid-icon-circle"><mdc-icon>content_copy</mdc-icon></div>
<span>Copy link</span>
</button>
<button class="demo-grid-item" type="button">
<div class="demo-grid-icon-circle"><mdc-icon>bookmark_border</mdc-icon></div>
<span>Bookmark</span>
</button>
<button class="demo-grid-item" type="button">
<div class="demo-grid-icon-circle"><mdc-icon>print</mdc-icon></div>
<span>Print</span>
</button>
<button class="demo-grid-item" type="button">
<div class="demo-grid-icon-circle"><mdc-icon>qr_code</mdc-icon></div>
<span>QR Code</span>
</button>
</div>
</mdc-bottom-sheet>
<mdc-button onclick="const s = this.getRootNode().querySelector('#bs-variant-standard'); s.detent = 'peek'; s.show()"><span>Standard (Peek State - Header Only)</span></mdc-button>
<mdc-button onclick="const s = this.getRootNode().querySelector('#bs-variant-standard'); s.detent = 'full'; s.show()"><span>Standard (Full State - All Slots)</span></mdc-button>
<mdc-button onclick="const s = this.getRootNode().querySelector('#bs-variant-modal'); s.detent = 'peek'; s.show()"><span>Modal (Peek State)</span></mdc-button>
<mdc-button onclick="const s = this.getRootNode().querySelector('#bs-variant-modal'); s.detent = 'full'; s.show()"><span>Modal (Full State)</span></mdc-button>