The Grain Exchange

The Grain Exchange

The Grain Exchange sits on the site of the town’s Meal Market where cereals were traded. The building is now used as a multi-purpose market, cultural and creative space named in honour of its heritage. Look out for weekend markets showcasing Ayrshire’s most talented crafters, makers and creators, as well as artists in residence days throughout the week. 

So come along, meet the makers and shop local!

Additional Information

Accessible rooms
Disabled access
Free Wi-Fi
The Grain Exchange, 77-81 High Street, Ayr KA7 1LU

Map

You might also like...

Prestwick
Prestwick
Exterior of shop front.

Well Heeled

Well Heeled is a small and professionally run family business established in 1997, based in the centre of Prestwick. All...
Well Heeled
Prestwick
Prestwick
Belle Boutique

Belle Boutique

Situated in Prestwick Main Street, Belle Boutique is a unique ladies clothing and jewellery boutique. Selling smart, casual layering collections...
Belle Boutique
Prestwick
Prestwick
Exterior of barber and coffee shop.

McIntyre Barberista

McIntyre Barberista is a barber and cafe in one. Browse and listen to vinyls while you wait in our fun...
McIntyre Barberista
Prestwick
Prestwick
Delicious looking pies on a table.

West Coast Foods

West Coast Foods is an award winning Scottish butcher and rated one of the best online butchers in the UK....
West Coast Foods
Prestwick
Prestwick
Boutique shop exterior.

Luna Boutique

Luna Boutique specialises in stylish, comfortable womenswear and accessories. It’s stocked full of stunning statement pieces for effortless elegance. Whatever...
Luna Boutique
Prestwick
Prestwick
Boutique shop exterior.

Swoon Boutique

Swoon Boutique offers an exciting array of women’s occasion wear – perfect for weddings, party nights, the races and more!...
Swoon Boutique

Join our newsletter

Get the latest Destination South Ayrshire news and events delivered straight to your inbox…

Sign up for our newsletter

Get the latest Destination South Ayrshire news and events delivered straight to your inbox.

Copyright © 2025 Destination South Ayrshire. Provided by South Ayrshire Council.

Sign up for our newsletter

Get the latest Destination South Ayrshire news and events delivered straight to your inbox…

document.addEventListener('DOMContentLoaded', () => { // Robust selectors for 2025 Elementor (covers Pro, Hello, Astra) const toggle = document.querySelector('.elementor-menu-toggle, .elementor-nav-menu--toggle button, [aria-expanded][role="button"]'); const menu = document.querySelector('.elementor-nav-menu--dropdown, .elementor-nav-menu__container, nav[role="navigation"]'); if (!toggle || !menu) { console.error('ZoomFix: Elements not found. Inspect hamburger/menu HTML.'); return; } console.log('ZoomFix: Found toggle and menu. Testing at 400% zoom...'); let focusables = []; let firstItem, lastItem; let isOpen = false; let tabCountAtEnd = 0; // Detects repeated Tabs to auto-close const MAX_TABS_BEFORE_CLOSE = 2; // Closes after 2 Tabs on last item const updateFocusables = () => { focusables = Array.from(menu.querySelectorAll('a[href], button:not([disabled]), [tabindex]:not([tabindex="-1"])')); firstItem = focusables[0]; lastItem = focusables[focusables.length - 1]; console.log('ZoomFix: Updated focusables:', focusables.length); }; // Monitor for menu open/close (handles Elementor's mutations at zoom) const observer = new MutationObserver((mutations) => { const expanded = toggle.getAttribute('aria-expanded') === 'true' || toggle.classList.contains('elementor-active'); if (expanded !== isOpen) { isOpen = expanded; console.log('ZoomFix: Menu state:', isOpen ? 'OPEN' : 'CLOSED'); if (isOpen) { updateFocusables(); setTimeout(() => firstItem?.focus(), 100); // Delay for zoom reflow startFocusPolling(); // Start zoom-safe polling } else { stopFocusPolling(); toggle.focus(); } } }); observer.observe(toggle, { attributes: true, subtree: true }); // Zoom-proof focus trap: Global Tab listener const handleTab = (e) => { if (!isOpen || !focusables.length) return; updateFocusables(); // Re-scan for zoom/DOM changes if (document.activeElement === lastItem && e.key === 'Tab' && !e.shiftKey) { e.preventDefault(); tabCountAtEnd++; console.log('ZoomFix: Tab at end (#', tabCountAtEnd, ')'); if (tabCountAtEnd >= MAX_TABS_BEFORE_CLOSE) { console.log('ZoomFix: Auto-closing after repeated Tabs'); closeMenu(); tabCountAtEnd = 0; } else { firstItem.focus(); // Trap: Loop to start } } else if (document.activeElement === firstItem && e.key === 'Tab' && e.shiftKey) { e.preventDefault(); lastItem.focus(); // Trap: Loop to end } }; // Polling for zoom event loss (runs only when open) let pollInterval; const startFocusPolling = () => { pollInterval = setInterval(() => { if (isOpen && document.activeElement && !menu.contains(document.activeElement)) { console.log('ZoomFix: Focus escaped during zoom—trapping back'); firstItem?.focus(); } }, 50); // 50ms check survives zoom reflow }; const stopFocusPolling = () => clearInterval(pollInterval); const closeMenu = () => { console.log('ZoomFix: Forcing close'); toggle.click(); // Elementor's native close tabCountAtEnd = 0; }; // Attach listeners document.addEventListener('keydown', handleTab); document.addEventListener('keyup', (e) => { if (e.key === 'Escape' && isOpen) closeMenu(); }); // Fallback: Click outside document.addEventListener('click', (e) => { if (isOpen && !menu.contains(e.target) && !toggle.contains(e.target)) closeMenu(); }); // Initial scan updateFocusables(); });