The theme parameter takes 'auto' (the default), 'ios' or 'md'. With auto, Framework7 572,986 matches the user agent against iPhone, iPad and iPod patterns and gives those the iOS theme; everything else, desktop browsers included, gets Material. Because iPadOS 13 and later report a Mac user agent, a touch-screen MacIntel with an iPad screen size also counts as an iPad. The result lands in app.theme and as a class on <html>. BookNest's constructor now reads test switches from the URL (the imports are unchanged):
// Test switches: ?theme=ios|md &dark=1|0 &scheme=vibrant|monochrome &color=%232e7d32
const query = new URLSearchParams(location.search);
const dark = query.get('dark');
const app = new Framework7({
name: 'BookNest', el: '#app', component: App, store, routes,
theme: query.get('theme') || 'auto',
darkMode: dark === null ? 'auto' : dark === '1',
mdColorScheme: query.get('scheme') || 'default',
colors: { primary: query.get('color') || '#b3541e' },
});
window.app = app; // lets DevTools and test scripts reach the instanceThis Playwright 26,280 script (pip 21,050 install playwright) tries three user agents, with and without ?theme=ios:
from playwright.sync_api import sync_playwright
UA = {'iPhone': 'Mozilla/5.0 (iPhone; CPU iPhone OS 26_0 like Mac OS X)',
'Android': 'Mozilla/5.0 (Linux; Android 16; Pixel 8)',
'Desktop': None} # None keeps Chrome's own Windows user agent
with sync_playwright() as p:
browser = p.chromium.launch(channel='chrome')
for query in ['', '?theme=ios']:
for device, ua in UA.items():
page = browser.new_page(user_agent=ua)
page.goto('http://localhost:5294/' + query)
page.wait_for_function('window.app && app.initialized')
theme, cls = page.evaluate('[app.theme, [...document.documentElement.classList]]')
cls = [c for c in cls if c == theme or 'device-' in c and 'ratio' not in c]
print(f'{query or "(none)":11} {device:8} theme={theme:4} html: {" ".join(cls)}')
browser.close()(none) iPhone theme=ios html: ios device-ios (none) Android theme=md html: md device-android (none) Desktop theme=md html: md device-desktop device-windows ?theme=ios iPhone theme=ios html: ios device-ios ?theme=ios Android theme=ios html: ios device-android ?theme=ios Desktop theme=ios html: ios device-desktop device-windows
Forcing leaves the device classes alone, and no method switches the theme later: reload instead. Where markup must differ, use the visibility classes: Material hides ios-only, if-ios and if-not-md elements, and iOS hides md-only, if-md and if-not-ios.