Zuplo
Extending

Slots

This documentation is for the preview version of the Dev Portal. If you are using the legacy developer portal, please refer to the docs.

Slots provide a powerful way to inject custom content into predefined locations throughout Zudoku. They allow you to extend the default layout and functionality without modifying the core components.

Configuration

You can define slots in your zudoku.config.tsx file using the slots property:

Code(tsx)
import type { ZudokuConfig } from "zudoku"; import { Button } from "zudoku/ui/Button.js"; const config: ZudokuConfig = { // ... other config slots: { "head-navigation-end": () => ( <div className="flex items-center gap-2"> <Button variant="ghost" size="icon" asChild> <a href="https://github.com/your-repo"> <GithubIcon className="w-4 h-4" /> </a> </Button> </div> ), "footer-before": <div>Custom footer content</div>, }, }; export default config;

Slot Types

Slots accept either:

  • React components/elements: JSX elements
  • Function components: Functions that return JSX elements and receive routing props
Code(tsx)
slots: { // JSX element "footer-after": <CustomFooter />, // Function with access to routing props "head-navigation-end": ({ navigate, location, searchParams }) => ( <Button onClick={() => navigate('/settings')} variant={location.pathname === '/settings' ? 'default' : 'ghost'} > Settings </Button> ), }

Functions receive an object with routing properties:

  • location - Current route location
  • navigate - Navigation function
  • searchParams - URL search parameters
  • setSearchParams - Function to update search parameters
  • params - Route parameters

Type Safety

Dev Portal provides full TypeScript support for slot names. All predefined slot names will show up with autocomplete when you type them in your configuration.

Advanced Usage

For more advanced slot usage, including programmatic slot management, dynamic content, and adding custom slot names, see the Slot Component documentation.

Examples

Code(tsx)
slots: { "head-navigation-end": () => ( <div className="flex items-center gap-2"> <Button variant="ghost" size="icon" asChild> <a href="https://github.com/your-org" target="_blank"> <GithubIcon className="w-4 h-4" /> </a> </Button> <Button variant="ghost" size="icon" asChild> <a href="https://discord.gg/your-server" target="_blank"> <DiscordIcon className="w-4 h-4" /> </a> </Button> </div> ), }

Dynamic Content with Routing

Code(tsx)
slots: { "top-navigation-side": ({ location, navigate }) => ( <div className="flex items-center gap-2"> <Button variant={location.pathname === '/docs' ? 'default' : 'ghost'} onClick={() => navigate('/docs')} > Documentation </Button> <Button variant={location.pathname === '/api' ? 'default' : 'ghost'} onClick={() => navigate('/api')} > API Reference </Button> </div> ), }
Last modified on