Giter VIP home page Giter VIP logo

kevinpapst / tablerbundle Goto Github PK

View Code? Open in Web Editor NEW
86.0 7.0 17.0 3.5 MB

Tabler.io bundle for Symfony 6 - admin theme for easy integration, coming with Bootstrap 5.3, Webpack-Encore integration and many more features...

License: MIT License

PHP 39.21% JavaScript 1.06% SCSS 0.47% Twig 59.26%
admin-template php symfony symfony-bundle tabler tabler-io symfony6 theme bootstrap5 webpack-encore

tablerbundle's Introduction

Tabler Bundle for Symfony

This repository contains a Symfony bundle, integrating the fantastic Tabler.io HTML Template into your Symfony project. It ships with many twig helper (functions, filter, embeds, macros and includes) to speed up your development and simplify future upgrades!

It requires Symfony >= 6.0 and PHP >= 8.1 ๐Ÿš€ Read the documentation to find out more ๐Ÿ‘

Preview

Tabler is fully responsive and compatible with all modern browsers. Thanks to its modern, user-friendly design you can create a fully functional interface that users will love! Choose the layouts and components you need and customize them to make your design consistent and eye-catching. Every component has been created with attention to detail to make your interface beautiful! Show me the demo.

Tabler preview

Features

  • Two main layouts for your backend/admin application: a vertical and horizontal one
  • Security layouts for login, forgot password, register account
  • Many includes, embeds and macros to help speed up the development

Demo application

There is even a demo application, that showcases most of the components and can serve as a starting point for new projects ๐Ÿ˜„

You can check it out here at Github in the TablerBundle-Demo repository.

Technical details

  • Webpack-Encore support for building assets
  • Event-driven handling of menu entries, tasks and notifications
  • ContextHelper for dynamic layout changes (e.g. based on user preferences)
  • Translations for: english, german, italian, czech, spanish, russian, arabic, finnish, japanese, swedish, portuguese (brazilian), dutch, french, turkish, danish, chinese, slovakian, basque, polish, esperanto, hebrew, romanian (please help translating it to more languages)
  • Based on Bootstrap 5
  • Supports FontAwesome 5

Installation

Step 1: Download the Bundle

Open a command console, enter your project directory and execute the following command to download the latest stable version of this bundle:

composer require kevinpapst/tabler-bundle

Step 2: Configure the Bundle

Copy the default config to your config/packages/ directory:

cp vendor/kevinpapst/tabler-bundle/config/packages/tabler.yaml config/packages/

Step 3: Enable the Bundle

Enable the bundle by adding it to the list of registered bundles in the config/bundles.php file of your project:

// config/bundles.php

return [
    // ...
    KevinPapst\TablerBundle\TablerBundle::class => ['all' => true],
];

Step 4: Documentation

Now read what you should do in order to use the theme at docs/.

License and contributors

Published under the MIT, read the LICENSE file for more information.

Translations managed with the fantastic Weblate project.

tablerbundle's People

Contributors

cavasinf avatar creiner avatar ejolivares avatar etrimi avatar kevinpapst avatar tacman avatar thepanz avatar weblate avatar wucherpfennig avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

tablerbundle's Issues

Flash messages not displayed after redirectToRoute()

When using $this->addFlash(...) before using $this->redirectToRoute(...) flash messages are not displayed.
It works when adjusting conditions in flash_messages.html.twig:

- {% if app.session and app.session.started and app.session.flashbag.peekAll|length > 0 %}
+ {% app.session.flashbag.peekAll|length > 0 %}
    <div class="row">
        <div class="col-sm-12">
            {{ macro.session_flash(true, false, '', 'flashmessages') }}
        </div>
    </div>
{% endif %}

It also works when calling $this->container->get('request_stack')->getSession()->start(); in the target route.
I'm not sure whats the better way. In official symfony discussion, there is no check if the session is started. But I think it is needed here in case that session component is not enabled. But in my opinion it is also not best practice to start session explicit.

What do you think?

Card always have padding bottom

<div {% if _id is not null %}id="{{ _id }}"{% endif %} class="card mb-3{% if block('box_class') is defined %} {{ block('box_class') }}{% endif %}"{% if block('box_attributes') is defined %} {{ block('box_attributes') }}{% endif %}>

With the current state, there's no way to remove padding bottom from embeded card.

 <div ... class="card mb-3" ... >

How it looks today:
image

What I want to achieve:
image

Component - Accordion

I do need the accordion quite often. Therefore I decided to write a macro to implement in the project.

(FYI #82 (comment))

Before I add a PR (with docs etc.) please comment on the macro.

  • I do need the extraClass on the item level to indicate some success / danger etc.
    I would very much keep this extra functionality ๐Ÿ˜‰
  • I noticed that extraClass on title and / or body cause the affected element to animate poorly.
    I do think we do not need that...
  • Accordions have no mb-3 as default
    Should we add it if extraClass is not set?
  • Accordions have no background as default
    Should we add it if extraClass is not set?
{% macro accordion(items, options) %}
    {% set _id = options.id ?? ('accordion-' ~ random(0, 999)) %}
    {% set _raw = options.raw ?? true %}
    {% set _flush = options.flush ?? false %}
    {% set _always_open = options.always_open ?? false %}
    {% set _extraClass = options.extraClass ?? '' %}

    <div id="{{ _id }}" class="accordion {% if _flush == true %}accordion-flush{% endif %} {{ _extraClass }}">
        {% for item in items %}
            {% set _id_collapse = _id ~ '-collapse-' ~ loop.index %}
            {% set _item_extraClass = item.options.extraClass ?? '' %}
            {% set _item_title_extraClass = item.options.title_extraClass ?? '' %}
            {% set _item_body_extraClass = item.options.body_extraClass ?? '' %}
            <div class="accordion-item {{ _item_extraClass }}">
                <div class="accordion-header {{ _item_title_extraClass }}" id="{{ _id }}-heading-{{ loop.index }}">
                    <button class="accordion-button {% if loop.first == false %}collapsed{% endif %}"
                            type="button" data-bs-toggle="collapse" data-bs-target="#{{ _id_collapse }}"
                            aria-expanded="true">
                        {% if _raw == true %}{{ item.title | raw }}{% else %}{{ item.title }}{% endif %}
                    </button>
                </div>
                <div id="{{ _id_collapse }}" {% if _always_open == false %}data-bs-parent="#{{ _id }}"{% endif %}
                     class="accordion-collapse collapse {% if loop.first %}show{% endif %} {{ _item_body_extraClass }}">
                    <div class="accordion-body pt-0">
                        {% if _raw == true %}{{ item.body | raw }}{% else %}{{ item.body }}{% endif %}
                    </div>
                </div>
            </div>
        {% endfor %}
    </div>

{% endmacro %}

Usage:

     {% embed '@Tabler/embeds/card.html.twig' %}
        {% block box_body %}
            {% from 'macro/accordion.html.twig' import accordion %}

            {% set items =
                {
                    'key1':
                    {
                        'title': 'Title 1',
                        'body': 'Body 1',
                    },
                    'key2':
                    {
                        'title': 'Title 1',
                        'body': 'Body 2',
                        'options':
                        {
                            'title_extraClass': 'bg-success text-white',
                            'body_extraClass': 'bg-danger pt-3',
                        },
                    },
                    'key3':
                    {
                        'title': 'Title 3',
                        'body': 'Body 3',
                        'options':
                        {
                            'extraClass': 'bg-danger-lt'
                        }
                    },
                    'key4':
                    {
                        'title': '<div>Title 4 <strong>with HTML</strong></div>',
                        'body': '<div>Body 4 <strong>with HTML</strong></div',
                    },
                } %}

            {% set options = {
                'id': 'example-accordion',
                'raw': null,
                'always_open': false,
                'extraClass': 'mb-0',
            } %}

            {{ accordion(items, options) }}

        {% endblock %}
    {% endembed %}

grafik

Breadcrumb that is not a real breadcrumb

Context ๐Ÿ“‹

In the page-header,
I want to add buttons like Create new,
image

and still have the breadcrumb: Items > Actions.
image

Current state ๐Ÿ‘€

Page header buttons are at the position of Breadcrumb.

<div class="col-auto ms-auto d-print-none">
{% block breadcrumb %}
<div class="btn-list">
<a href="#" class="btn btn-white">
New view
</a>
<a href="#" class="btn btn-primary d-none d-sm-inline-block">
Create new report
</a>
</div>
{% endblock %}
</div>
</div>
</div>

Problem โŒ

With that current state,

  • If I want to add my buttons, I'll put them INSIDE breadcrumb block with custom HTML to allow to have Buttons + Breadcrumb.
  • Plus, we are declaring a block about Breadcrumb with buttons on default values. In that case, it's not really a "Breadcrumb".

Possible solution โœ”๏ธ

Split current {% block breadcrumb %} into 3 blocks

{% block page_header_right %}
    <div class="col-auto ms-auto d-print-none">
        {% block page_header_actions %}
            <div class="btn-list">
                <a href="#" class="btn btn-white">
                    New view
                </a>
                <a href="#" class="btn btn-primary d-none d-sm-inline-block">
                    Create new report
                </a>
            </div>
        {% endblock %}
        {% block breadcrumb_container %}
            <div class="text-end">
                {% block breadcrumb %}
                    Entity > Action > ...
                {% endblock %}
            </div>
        {% endblock %}
    </div>
{% endblock %}

[Twig] Rename all `url` params to `href`

As discussed in #157,
we should stop using url param for twig function/components/... and other.
Instead, use the common HTML attribute href.

Add "deprecated" for now, but in 1.0 should be gone.

How to set body class in fullpage.html.twig

I am trying to override the body class with the fullpage template:

<body{% block body_start %}{% endblock %} class="d-flex flex-column {{ 'border-top-wide border-primary theme-light'|tabler_body }}">
{% block after_body_start %}{% endblock %}

I am able to "override" it but this is definitively not correct ๐Ÿ˜€

{% extends '@Tabler/error.html.twig' %}

{% block title %}Zugriff verweigert!{% endblock %}

{% block body_start %} class="border-top-wide border-danger theme-light" {% endblock %}

{% block error_title %}
    ASDFLJL""22
{% endblock %}

I do not understand how to do it properly. Any help appreciated.

Update Tabler assets

Could you update the CSS and JS with the latest version of Tabler? The package uses v1.0.0-beta2, while beta6 is currently the latest version. I am implementing some elements of the Tabler preview and have the feeling I'm missing some styling.

Title block names - Wrongly named

When using the blocks for header titles, there names can be not comprehended by devs (and me).

We are talking about subtitle and title.
Or in Tabler, it's more pretitle and title.

Example

My page is a List of products that come from Products.
Breadcrumb would be : Products > List of products.

Tabler.io TablerBundle
Variable image image
Example image image

I think it's more normal/user friendly to have the main title more bigger and wider than the pretitle.

โš ๏ธ Renaming a block can break existing projects โš ๏ธ

Though on `symfonycasts/reset-password-bundle`

FOSUserBundle being deprecated,
Symfony allows devs by using MakerBundle to implement what is missing from FOSUserBundle.
eg :

  • make:user
  • make:reset-password depend on symfonycasts/reset-password-bundle
  • make:registration-form
  • ...

ATM, TablerBundle use raw input and custom names to implement the template,
which doesn't work with what MakerBundle has created.

Wouldn't it be better to use forms that MakerBundle "auto-code/auto-create" ?
Instead of creating our own form by raw html inputs.

I know Tabler.io use raw inputs to match with most uses,
but in our case we are making a Bundle for Symfony.
It will be more natural to use Symfony form instead of manual HTML inputs.

What do you think about that @kevinpapst ?

Macro utilities ?

Due to #84

I was searching in the Bundle, what is the best way to handle custom attr for components.

I really like the button component way.

{%- if attr is not empty %}
{% for name, value in attr %}
{{ ' ' ~ name }}={% if '"' in value %}'{{ value|raw }}'{% else %}"{{ value|raw }}"{% endif %}
{% endfor %}
{% endif %}>

But the code is "heavy" to copy pasta between component and child component.

I was implementing a macro for this component only,
but it will be nice if we do utilities that can be called between all components.
Twig Filter or Function is maybe overpower.

Maybe a simple twig file under /templates/components/macros.html.twig โ”

Example macro:

{% macro attr_to_html(attr) %}
    {%- if attr is not empty %}
        {% for name, value in attr %}
            {{ ' ' ~ name }}={% if '"' in value %}'{{ value|raw }}'{% else %}"{{ value|raw }}"{% endif %}
        {% endfor %}
    {% endif %}
{% endmacro %}

Usage will be:

<div class="steps {{ _counter ? 'steps-counter' : '' }} {{ 'steps-'~_color }}" {{ attr_to_html(_attr) }}>

TablerBundle card `collapsible` VS Tabler `Accordion`

Collapsible cards doesn't have the "current state" effect on the button to know if it's collapsed or not.

CardCollapsible

I was trying to find how Tabler handle collapsible cards, and I don't find any.
But instead I've found those Accordions.

It made me thinking that it was a custom card made by @kevinpapst. Am I right ?

Is that conceivable to use Accordions effect for collapsible card instead ?

Certain FontAwesome icons are too wide

Context

With FontAwesome in certain icon case:

  • fa-users
  • fa-cogs
  • ...

When using twig macro tabler_icon(),
icons are to wide and overflow the parent element.
image

Problem

At the end,
the margin right on the icon class is not enough and label is too close from the icon.

Home โŒ
Tiers โŒ
Liste des Tiers โœ”๏ธ
Crรฉer un Tiers โœ”๏ธ

Possible better case

If I remove the icon class from the <i>
image

Drop support for Symfony 4.4 and PHP < 8.0

Given that this is a new bundle, with no existing user base with promises of backwards compatibility, I'd like to advocate for PHP8 and dropping Symfony support less than 5.4.

In particular, I really like using attributes instead of annotations. Also, strong type-hinting makes coding easier and more robust.

I've switched to 8.1, and although I'm not using any 8.1 specific features yet, given the newness of this bundle, I'm not sure how many people we'd lose if that were a requirement.

For example, MenuItemModel could be MUCH shorter by defining properties in the constructor (PHP 8.0) and I think some of those properties are readonly, and could be defined as such in the constructor (PHP 8.1)

While not essential, I think it would make for a better bundle, and certainly a better developer experience.

release 1.0

composer req kevinpapst/tabler-bundle

still pulls 0.22, can you tag 1.0 as a release?

Auto-detection/Auto-completetion by IDE from vendor

What IDE are you using ?
Mine is PHPStorm and I don't know why but your Bundle with Tabler is not recognized by it.
AdminLTEBundle work like a charm, but not that one.

TablerBundle:
image

AdminLTEBundle:
image

It look's like he doesn't know where to find the @Tabler.
How do you declare the @Tabler isn't it from the xxxxBundle.php.

TablerBundle.php is deeper in the vendor directory than AdminLTEBundle.

image

Alert macro and `alert-important` class

Why the class alert-important is automated when title or description are empty?

{% set background = title is empty or description is empty ? true : false %}

It blocks me to add title + description AND full alert background color.
I don't think it is a good idea.

We can let this automation but add a new param important and change de background condition like
{% set background = title is empty or description is empty or important ? true : false %}

Tabler icons VS FontAwesome

As i can see from Tabler.io,
they have implemented there own icon lib.

I assumed you also use FontAwesome.

What is the "work around" of the icons param in tabler.yml.
Are you whiling to add each FontAwesome you will use in that config part ?
How are you gonna make the distinct between fas and far ?

I'm not sure if its a good idea to have that.
Unless there is something that oblige us to do that.

Component - Carousel

Dear All

Again a new component. Please provide some feedback before I create a PR + Docs.

I have tried to cover most of BS5 configuration options. The latest tabler options with dots, thumbs and vertical are included but not available as we are not on the latest version (https://preview.tabler.io/changelog.html).

Remarks:

  • Adding custom content works fine. It is just 'worthless' as I found no easy way to fix the height of the carousel without breaking all mobile breakpoints etc.
{% macro carousel(items, options) %}
    {% set _id = options.id ?? ('carousel-' ~ random(0, 999)) %}
    {% set _extraClass = options.extraClass ?? '' %}

    {% set _interval = options.interval ?? 5000 %}
    {% set _touch_enabled = options.touch ?? true %}
    {% set _pause = options.pause ?? false %}
    {% set _wrap = options.wrap ?? true %}

    {% set _show_controls = options.controls ?? false %}

    {% set _caption_class = options.caption_custom_class ?? 'd-none d-md-block' %}
    {% set _show_caption_background = options.caption_background ?? true %}

    {% set _show_indicators = options.indicators ?? true %}
    {% set _indicators_type = options.indicators_type ?? '' %}
    {% set _indicators_ratio = options.indicators_ratio ?? '' %}
    {% set _indicators_orientation = options.indicators_orientation ?? 'horizontal' %}

    <div id="{{ _id }}" class="carousel slide {{ _extraClass }}" data-bs-ride="carousel"
         data-bs-interval="{{ _interval == false ? 'false' : _interval }}"
         data-bs-touch="{{ _touch_enabled ? 'true' : 'false' }}"
         data-bs-pause="{{ _pause == true ? 'true' : 'hover' }}" data-bs-wrap="{{ _wrap ? 'true' : 'false' }}">
        {% if _show_indicators %}
            {{ _self.carousel_indicators(items, _id, _indicators_type, _indicators_orientation, _indicators_ratio) }}
        {% endif %}
        {% if _show_controls %}
            <button class="carousel-control-prev" type="button" data-bs-target="#{{ _id }}" data-bs-slide="prev">
                <span class="carousel-control-prev-icon" aria-hidden="true"></span>
            </button>
            <button class="carousel-control-next" type="button" data-bs-target="#{{ _id }}" data-bs-slide="next">
                <span class="carousel-control-next-icon" aria-hidden="true"></span>
            </button>
        {% endif %}
        <div class="carousel-inner">
            {% for item in items %}
                {% set _has_custom = item.custom_content is defined %}
                {% if _has_custom %}
                    {# This is useless: breaks contents and no additional value as making everything same size is cumbersome #}
                    <div class="carousel-item">
                        {{ item.custom_content | raw }}
                    </div>
                {% else %}
                    <div class="carousel-item {% if loop.first %}active{% endif %}">
                        <img src="{{ item.image }}" class="d-block w-100" alt="DEMO 123">
                        {% if item.title is defined or item.description is defined %}
                            {% if _show_caption_background %}
                                <div class="carousel-caption-background {{ _caption_class }}"></div>
                            {% endif %}
                            <div class="carousel-caption {{ _caption_class }}">
                                {% if item.title %}
                                    <h3>{{ item.title }}</h3>
                                {% endif %}
                                {% if item.description %}
                                    {{ item.description }}
                                {% endif %}
                            </div>
                        {% endif %}
                    </div>
                {% endif %}
            {% endfor %}
        </div>
    </div>

{% endmacro %}

{% macro carousel_indicators(items, id, type, orientation, ratio) %}
    {% set _typeClass = '' %}
    {% if type == 'dots' %}{% set _typeClass = 'carousel-indicators-dot' %}{% endif %}
    {% if type == 'thumbs' %}{% set _typeClass = 'carousel-indicators-thumb' %}{% endif %}

    {% set _orientationClass = '' %}
    {% if orientation == 'vertical' %}{% set _orientationClass = 'carousel-indicators-vertical' %}{% endif %}
    {% set _ratio = 'ratio ' ~ (ratio == '' ? 'ratio-1x1' : ratio) %}

    <div class="carousel-indicators {{ _typeClass }} {{ _orientationClass }}">
        {% for item in items %}
            {% set _item_class = loop.first ? 'active' : '' %}
            {% set _item_style = '' %}
            {% if type == 'thumbs' %}
                {% set _item_image = item.image ?? '' %}
                {% set _item_class = _item_class ~ ' ' ~ _ratio %}
                {% set _item_style = 'background-image: url(\'' ~ _item_image ~ '\');' %}
            {% endif %}
            <button type="button" data-bs-target="#{{ id }}" data-bs-slide-to="{{ loop.index - 1 }}"
                    class="{{ _item_class }}" style="{{ _item_style }}"></button>
        {% endfor %}
    </div>
{% endmacro %}

Usage:

    {% embed '@Tabler/embeds/card.html.twig' %}
        {% block box_body %}
            {% from 'macro/carousel.html.twig' import carousel %}

            {% set items =
                {
                    'key0' :
                    {
                        'image': 'https://via.placeholder.com/640x360/1485bc/ffffff?text=Image+0',
                    },
                    'keyContent':
                    {
                        'custom_content': '<h1>Hello World</h1>',
                    },
                    'key1' :
                    {
                        'image': 'https://via.placeholder.com/640x360/9dbf00/ffffff?text=Image+1',
                        'title': 'SOME Fancy Title',
                        'description': 'Lorem Ipsum NO HTML',
                    },
                    'key2' :
                    {
                        'image': 'https://via.placeholder.com/640x360/bc147a/ffffff?text=Image+2',
                    },
                    'key3' :
                    {
                        'image': 'https://via.placeholder.com/640x360/1454bc/ffffff?text=Image+3',
                    }
                }
            %}

            {% set options =
                {
                    'interval': false,
                    'controls': true,
                    'indicators': true,
                    'indicators_type': 'thumbs',
                    'indicators_orientation': 'vertical',
                }
            %}

            {{ carousel(items, options) }}

        {% endblock %}
    {% endembed %}

[Templating] Create macro for submit_button

Discussed in #23

Originally posted by cavasinf December 14, 2021
@kevinpapst just curious, how do you render your submit form button.

From the embeds/button macro you can only create a fake button through <a> element. In that case, no submit type possible.

So, did you create it from your formbuilder and render it via form_row() ?

Card embed block names

Big BC BREAK but we should rename blocks inside card embed.

<div class="card-header{% if block('box_header_class') is defined %} {{ block('box_header_class') }}{% endif %}">

They are called box_xxxxx as a remnant of AdminLTE. And classes card-xxxx
We should stick to Bootstrap and/or Tabler name convention and use card_xxxx instead.

WDYT ?

[Button] Bootstrap tooltip

{%- if not forceTitle and title is not null and type is not same as (false) %} data-toggle="tooltip" data-bs-placement="top" title="{{ title|trans({}, translation_domain) }}"{% endif %}

If using Tabler JS import file:

Should we use Tabler default behavior or Bootstrap configuration ?

[Twig] File Name convention

Big BC BREAK, rename twig file names to snake_case

  • card-vertical-navigation.html.twig to card_navigation_vertical.html.twig
  • card_nav.html.twig to card_navigation.html.twig
  • card_nav_header.html.twig to card_navigation_header.html.twig
  • and more...

milestone 1.0 because this has to be done BEFORE the first "real" release

[Button] `btn-sm` and `icon` class

Displaying button with btn-sm WITH an icon creates an ugly button.
Due to the icon class on the FontAwesome , it oversize the icon.

image

<a href="#" class="btn btn-default  btn-icon btn-sm">
   <i class="icon fas fa-search-location"></i>
</a>

{{ tabler_icon(icon, true, icon) }}

Removing that icon class resolve this display
image

<a href="#" class="btn btn-default  btn-icon btn-sm">
-   <i class="fas fa-search-location"></i>
+   <i class="icon fas fa-search-location"></i>
</a>

support ux components

I'm a huge fan of Symfony UX Components, and greatly prefer them to macros. I think it's worth considering supporting them in this bundle as well.

In addition to not needing the import, I find the syntax cleaner, and of course the big benefit is that you can inject services, like security. Plus, setting defaults and handling logic is easier in PHP than in Twig.

// using macros
{% from '@Tabler/components/alert.html.twig' import alert %}
{{ alert({title : 'Title V2', description: 'Description V2', icon : 'warning', dismissible : true}) }}

// using a component
<twig:alert title="Title V2" description="Description" icon='warning' dismissable="true" />

{# Since often the data passed to the component is dynamic, it's even shorter, from a different theme bundle  #}

                    {% for bsClass in bootstrap_theme_colors() %}
                        {% set message ="Look, a %s alert โ€” check it out!"|format(bsClass)   %}
                        <twig:alert :message="message" :type="bsClass" />
                    {% endfor %}

There's a lot of power in the UX components, I have a whole set of them that I wrote for the sneat theme that would likely port pretty easily.

[Icon] Bye bye `tabler_icon` โžก๏ธ Welcome Symfony UX Icon ๐ŸŽ‰

As already discussed in #17, we've got a gap in how to handle icons in this bundle:

  • Lib Tabler icons? not really (as it should because of the theme)
  • Lib FontAwesome icon (which version? How to switch to Tabler? ...)
  • <svg>? <i>?
  • Tabler's 'icon' class that doesn't work at all with FontAwesome

Possible solution

We've been using Symfony Ux icon for the past months and it's been a total game-changer!
It works like a charm and the best part is how easy it is to switch between icon sets (Bootstrap, Tabler, FontAwesome).
And we can send the search page to our clients and let them find what they like on their own.
Furthermore, they can provide us with their SVG icons, which we can incorporate into our Symfony application.

Great feature of today's bundle icons

The best part of tabler_icon today is the shortcut/library of words that are equal to an icon:

tabler:
   icons:
      issue: fas fa-bug

Same concept with UX Icon

But we ended to reproduce this same feature with UX Icon.

  1. By "importing" (downloading) the icon:

      php bin/console ux:icons:import tabler:bug

    Downloaded at: assets/icons/tabler/bug.svg

  2. Rename it to our "shortcut" and move it to the parent icon folder:
    assets/icons/issue.svg

  3. We can now call it like this:

    • {{ ux_icon('issue') }}
    • Or with twig component: <twig:ux:icon name="issue" />

TablerBundle pros

With that external bundle, we can get out of a tight spot with "custom" code that isn't related to the Tabler theme
Plus, we get to remove code to maintain!

TablerBundle cons

  • Deprecating tabler_icon ๐Ÿ˜ข

WDYT ?

[csrf_token] Symfony 5 without FosUserBundle

I'm currently migrating my project to Symfony 5.
FOSUserBundle being deprecated, I've unplugged it from my project.

But now I've an error at that line:

{% if csrf_token %}
<input type="hidden" name="_csrf_token" value="{{ csrf_token('authenticate') }}"/>
{% endif %}

image

โ” Who define that variable โ”

If I change the line by {% if csrf_token | default(true) %}, it works.
What is the purpose of that "if" condition ?

Login form - Tabulation navigation

I can resolve that "issue" on my side by override some block,
but I want to know what is your (@kevinpapst) point of view about that.

In the Tabler demo : https://preview.tabler.io/sign-in.html
When you are in the input form,
and try to move from Email address to Password by tabulation,
it places you on I forgot password.

LoginTabNavigation

It would be nicer if the tabulation action place us in the password input.

We can achieve that by adding tabindex="-1" in the HTML attr of the <a> tabler_password_reset link.

<a href="{{ path('tabler_password_reset'|tabler_route) }}">{{ 'I forgot my password'|trans({}, 'TablerBundle') }}</a>

โ“ The question is โ“
Do you allow in your bundle, extra functionalities/modifications that is not part from Tabler ?
Or do you try to keep as close as possible from the original ?

[Templating] "Missing" Twig Block page_header

Hi,
I'm currently experimenting with the bundle in a prototype. Thanks for the effort!
I would propose to add a new block (maybe named: page_header) to the default layout.
The content of the block would be the following div;

<div class="{{ ''|tabler_container }}">
<!-- Page title -->
<div class="page-header d-print-none">
<div class="row align-items-center">
<div class="col">
<div class="page-pretitle">
{% block page_subtitle %}Overview{% endblock %}
</div>
<h2 class="page-title">
{% block page_title %}Dashboard{% endblock %}
</h2>
{% block page_stats %}
<div class="text-muted mt-1">
1-10 of 100
</div>
{% endblock %}
</div>
<div class="col-auto ms-auto d-print-none">
{% block breadcrumb %}
<div class="btn-list">
<a href="#" class="btn btn-white">
New view
</a>
<a href="#" class="btn btn-primary d-none d-sm-inline-block">
Create new report
</a>
</div>
{% endblock %}
</div>
</div>
</div>
</div>

With this block it would be possible to hide all the header elements (page_subtitle, page_title, page_stats and breadcrumb) for a clean layout.
Thanks
Chris

[Symfony FLEX] tabler.yaml not copied

When installing the bundle from composer with Symfony FLEX,
the file config/packages/tabler.yaml is not copied from the bundle.

bundles.php works fine, but not tabler.yaml.

Need to register a Flex recipe

Support Symfony 7 in TablerBundle

Since Symfony 7 will be out in 2 months, it would be great if this bundle supported it.

I've updated my branch of the Tabler Demo and it appears to be working well with Symfony 6.4. I can test with Symfony 7 as well.

Also, if we made the minimum requirement as 6.1, we could benefit from the easier bundle configuration, by extending from AbstractBundle.

[icon] extra class when FontAwesome

Question: How to handle extra classes for tabler_icon macro ?
Keep in mind that tabler_icon should works with Tabler svg and FontAwesome.

Today:

{{ tabler_icon(icon, false, icon) }}

What it should be:

<i class="far fa-folder fa-7x"></i>

Any idea ?

[Trans] Auto trans on devs content should not be a thing

Edit: You committed something about that in menu.html.twig @kevinpapst
added method to configure translation domain for menu items (#150)

But still the case for the navbar

<a href="#" class="dropdown-item">{{ link.label|trans }}</a>

I'm currently experiencing some translation errors when using the menu and navbar.

What I got

From a subscriber, I implement some items to the menu.
These items have labels that are already translated inside the subscriber.

$changePassword = new MenuItemModel(
    'change_password', 
    $this->translator->trans('action.edit_profile'), // <----- HERE
    'user_edit', 
    ['user_uuid' => $user->getUuid()]
);
$event->addLink($changePassword);

What TablerBundle does

When TablerBundle print the twig result of the menu item, it tries to trans a content that is already translated.
Like {{ 'Modifier mon profil'|trans }}.

What is the problem?

Because of this, Symfony tells me that I have missing/wrong translations.

image

What is the solution?

  1. Add the trans domain to any trans function/filter that the bundle uses
    โŒ I don't think this is a good idea:
  • Translations like that are not auto discovered by bin/console translation:extract (huge nono for me)
  • I found it easier to expect as a dev, to do a "raw" print by the bundle if my label is a message ID.
  1. DO NOT try to translate content that devs define.
    Only word/phrase that we define in the bundle.
    โœ”๏ธ Rude, but I'll take it!

[Styling] Button icons seem to be off if using fontawesome

I do not know whether somebody noticed it but with the default tabler css the button icons just seem to be off if you are using fontawesome. (they always seem to have the same size)

grafik

However if I add some "corrections" to the icon class like:

.page {
  .icon {
    font-size: 1em !important;
    height: 1.25em;
    margin: 0 .5em 0 -.5em;
    width: 1.25em;
    line-height: 1.25em;
  }
}

grafik

It just looks better.

I do not know what to do with this information but I wanted to share this "fix" if somebody is using multiple button sizes on their project.

BR wucherpfennig

[Menu] Set it more customizable?

I need to make a "special" menu for a client with specific needs.
To be more detail, I need:

  1. A drop-down menu
  2. Item with a button
  3. Menu separators/dividers

image

Problems:

  • Tabler has no such menu items, even a simple menu separator is not implemented -> tabler/tabler#1224
  • The current MenuItemModel is not complete enough to customised in this way (raw HTML link content).

To be able to create the screenshot menu, I've overwritten the entire TWIG menu template as there's no navbar_menu block to overwrite it from an extend:
https://github.com/kevinpapst/TablerBundle/blob/main/templates/layout-vertical.html.twig#L47-L51

Do we allows custom menu (from the subscriber), or it is a dev problem and overwriting the template is a good way to go?

Support KNP Menu

AdminLTEBundle supported KnpMenu, which was nice. It's a powerful library.

I see that the key for knp_menu support is in the config, but if it's enabled it fails, because knp-menu.yml is missing from the config.

I've added that file, but of course the rendering doesn't work. @kevinpapst , is that something you can bring over from the old bundle? Especially since it looks like we should have vertical menu support soon.

[Buttons] Error with `templates/components`

Expected behavior

I'm trying to figure out how to use the button components created for Tabler.
What I want is a button of class btn-link without any icon.

Here's what I'm trying to achieve:
image

Cases

Two cases messing me out:

Nยฐ 1

By using components/button.html.twig,
I cannot find a way to use the macro button() without an icon.

My code:

{% from '@Tabler/components/button.html.twig' import button %}
{{ button(false, { title : 'action.back_to_list'|trans, combined : true, url : path('admin_post_index') }, 'link') }}

Result:
image

Nยฐ 2

By using components/buttons.html.twig,
I've got an error with the macro link_button() about the ContextHelper. (even with no default values)

My code:

{% from '@Tabler/components/buttons.html.twig' import link_button %}
{{ link_button('test', '#', 'eye', "link", "lg") }}

default(tabler_bundle.button.size) trigger that error:

image

[Docs] Dynamic theme options (like dark mode)

The dark theme is defined from tabler.yaml for each user.
This should be a default value if the user hasn't set his preferences.
If the user wants to switch to dark theme (and tabler.yaml is set to light),
there's no way to override this behavior.

We should allow to set the dark mode with a subscriber/listener,
and the current value of tabler_theme() should be the default value if there is no subscriber/data provided.

Example in a simple twig data-bs-theme="{{ app.request.cookies.get('tablerTheme', tabler_theme()) }}",
dark theme comes from a cookie, and if undefined it will get the value of tabler_theme() (which is tabler.yaml).

Cookie is not the only case, some projects get user preferences from the database (hence the need for subscriber).

WDYT?

Menu badges not rendering

// MenuBuilderSubscriber.php
        $forms = new MenuItemModel('forms', 'Forms', null, [], 'fab fa-wpforms');
        $forms->setBadge('1');
        $forms->setBadgeColor('red');

but the red badge isn't rendering

image

`tabler_icon` change $default param

Hey @kevinpapst,

wondering what is the purpose of $default in the tabler_icon TWIG function.

public function icon(string $name, string $default = null, bool $isIcon = true): string
{
return ($isIcon ? 'icon ' : '') . ($this->icons[str_replace('-', '_', $name)] ?? ($default ?? $name));
}

Due to that,
all of my calls of this function (when not using buttons), are made with null for that parameter.

{{ tabler_icon('email', null, false) }}

Two questions arise from this:

  1. Should we use false to remove .icon class.
  2. Should we override .icon css when using it outside of .btn.

My current problem is that the render with icon class and font-awesome is kinda ugly:

  • Too big
  • Not vertically centered
  • Overlap with label when large icon (e.g : fas fa-cogs)

Today .icon class: ๐Ÿฅ‰
image

.icon class overridden: ๐Ÿฅˆ
image

Without .icon class: ๐Ÿฅ‡
image

WDYT ?

Originally posted by @cavasinf in #67

Allow Symfony 6

I updated the bundle to allow for Syfmony 6, then updated to the demo to do the same. I'll submit PRs now.

Menu item allows `null` route name but not when rendered

When building the User menu item, we allow to add null route name.

public function __construct(
string $id,
string $label,
?string $route = null,
array $routeArgs = [],
?string $icon = null
) {

But when MenuItem is used to render the actual item,
PHP throw an error that null cannot be of type sting.

KevinPapst\TablerBundle\Twig\RuntimeExtension::getRouteByAlias(): Argument #1 ($routeName) must be of type string, null given

public function getRouteByAlias(string $routeName): string
{
// this does not throw an exception on unknown routes, because those could be injected via events!
return $this->routes[$routeName] ?? $routeName;
}


Possible fix

When route is null set # as href link.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.