Skip to main content

Getting Started

View as Markdown

Install Fluid Primitives, register your component collection and build your first component.

Install both the PHP and JavaScript packages:

composer require jramke/fluid-primitives:"^1.0@beta"
npm install fluid-primitives@beta

Your sitepackage should require jramke/fluid-primitives in its own composer.json. Otherwise overrides, like the global context, could load before the library and lose.

Using TypeScript? Add the optional jramke/fluid-types package to generate typed client props for mountAll/mount. Read more about Generating TypeScript Types.

composer require --dev jramke/fluid-types

Need a fix before the next release? Use the canary builds:

composer require jramke/fluid-primitives:"dev-main"
npm install fluid-primitives@next

Create a ComponentCollection class in your sitepackage to register your component paths and contexts:

<?php

declare(strict_types=1);

namespace MyVendor\MyExtension\Components;

use Jramke\FluidPrimitives\Component\AbstractComponentCollection;
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use TYPO3Fluid\Fluid\View\TemplatePaths;

final class ComponentCollection extends AbstractComponentCollection
{
    public function getTemplatePaths(): TemplatePaths
    {
        $templatePaths = new TemplatePaths();
        $templatePaths->setTemplateRootPaths([
            ExtensionManagementUtility::extPath('my_extension', 'Resources/Private/Components/ui'),
            ExtensionManagementUtility::extPath('my_extension', 'Resources/Private/Components'),
        ]);
        return $templatePaths;
    }

    public function getContextNamespaces(): array
    {
        return [
            'MyVendor\\MyExtension\\Components\\Contexts',
        ];
    }
}

Registering ui/ as its own root path makes <ui:accordion.root> resolve to ui/Accordion/Root.html. File Structure shows the layout.

The collection extends AbstractComponentCollection of Fluid Primitives. A collection built on the Fluid core class, or registered in Configuration/Fluid/ComponentCollections.php, cannot resolve ui:prop and the other ui:* ViewHelpers.

Add the ui namespace to your ext_localconf.php:

$GLOBALS['TYPO3_CONF_VARS']['SYS']['fluid']['namespaces']['ui'][] =
    'MyVendor\\MyExtension\\Components\\ComponentCollection';

Add the library's site set to the dependencies of your own set:

name: my-vendor/my-extension
label: 'My Extension'
dependencies:
    - jramke/fluid-primitives

Expose custom settings to component templates:

plugin.tx_fluidprimitives {
    settings {
        privacyPageUid = 12
    }
}

These merge with lib.contentElement.settings and are available as {settings} in component templates.

A tooltip that shows a short text for a trigger.

<ui:useProps name="primitives:tooltip.root" as="rootProps" />
<ui:prop name="content" type="string" />

<primitives:tooltip.root spreadProps="{rootProps}">
    <primitives:tooltip.trigger class="{ui:cn(value: 'tooltip-trigger {class}')}">
        <f:slot />
    </primitives:tooltip.trigger>
    <ui:portal>
        <primitives:tooltip.positioner class="tooltip-positioner">
            <primitives:tooltip.content class="tooltip">
                <primitives:tooltip.arrow class="tooltip-arrow" />
                {content}
            </primitives:tooltip.content>
        </primitives:tooltip.positioner>
    </ui:portal>
</primitives:tooltip.root>

<vite:asset entry="EXT:my_extension/Resources/Private/Components/ui/Tooltip/Tooltip.entry.ts" />

Use it anywhere in your templates. The slot is the label of the trigger, content is the text of the tooltip:

<ui:tooltip content="Orders ship within 2 working days.">Delivery time</ui:tooltip>

Every prop of the primitive works on your component too, like openDelay, disabled or positioning:

<ui:tooltip content="Free returns for 30 days" openDelay="200" positioning="{placement: 'bottom'}">
    Returns
</ui:tooltip>

The template uses:

The entry file hydrates every tooltip on the page in the browser:

import { mountAll } from 'fluid-primitives';
import { Tooltip } from 'fluid-primitives/tooltip';

mountAll('ui:tooltip', ({ props }) => new Tooltip(props).init());

Hydration covers the client-side setup in full, Styling the data attributes you can target.