Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
bbf8508
[Toolkit][Flowbite] Add Badge component
DcgRG Feb 27, 2026
e6c3ef4
[Toolkit][Flowbite] Add Badge component
DcgRG Feb 28, 2026
70a141a
[Toolkit][Flowbite] Add Button component
DcgRG Feb 28, 2026
116f752
[Toolkit][Flowbite] Add Kbd component
DcgRG Mar 1, 2026
af4c59c
[Toolkit][Flowbite] Add Card component
DcgRG Mar 1, 2026
2652b0c
[Toolkit][Flowbite] Add Table component
DcgRG Mar 1, 2026
d53f5e2
[Toolkit][Flowbite] Add Input and Label component
DcgRG Mar 2, 2026
bdd75b1
[Toolkit][Flowbite] Add Textarea component
DcgRG Mar 2, 2026
a34c9f1
[Toolkit][Flowbite] Add Select component
DcgRG Mar 2, 2026
6fbee08
[Toolkit][Flowbite] Add Checkbox component
DcgRG Mar 2, 2026
7192f5e
[Toolkit][Flowbite] Add Skeleton component
DcgRG Mar 2, 2026
59c234a
[Toolkit][Flowbite] Add Alert component
DcgRG Mar 3, 2026
226f0c4
[Toolkit][Flowbite] Add Indicator component
DcgRG Mar 3, 2026
4fdf938
[Toolkit][Flowbite] Add Toggle component
DcgRG Mar 3, 2026
f8ef967
[Toolkit][Flowbite] Add Spinner component
DcgRG Mar 4, 2026
346e930
[Toolkit][Flowbite] Add Modal component
DcgRG Mar 5, 2026
17f18c2
[Toolkit][Flowbite] Add Button group component
DcgRG Mar 6, 2026
e4a8ce6
[Toolkit][Flowbite] Add Pagination component
DcgRG Mar 6, 2026
d8aace8
[Toolkit][Flowbite] Add Radio component
DcgRG Mar 6, 2026
7935faf
[Toolkit][Flowbite] Add Tabs component
DcgRG Mar 6, 2026
5bda055
[Toolkit][Flowbite] import flowbite
DcgRG Mar 8, 2026
d6d51ad
[Toolkit][Flowbite] fix assets imports
DcgRG Mar 13, 2026
8e56e1e
[Toolkit][Flowbite] add main color
DcgRG Mar 13, 2026
6a14628
[Toolkit][Flowbite] update alert component
DcgRG Mar 17, 2026
8c2c0d9
[Toolkit][Flowbite] fix doc
DcgRG Mar 17, 2026
a6514eb
[Toolkit][Flowbite] add composer script
DcgRG Mar 20, 2026
279cd48
[Toolkit][Flowbite] doc select + skeleton + spinner + tabs
DcgRG Mar 20, 2026
a6b76a9
[Toolkit][Flowbite] fix Alert
DcgRG Apr 1, 2026
62d3254
tweaks
Kocal Apr 4, 2026
2019ac8
Tweaks
Kocal Apr 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .twig-cs-fixer.dist.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@
$uxRuleset = (new Ruleset())
->addStandard(new Twig())
// Symfony standard (customized for Symfony UX)
->addRule(new DirectoryNameRule(baseDirectory: 'templates', ignoredSubDirectories: ['bundles', 'components', 'demos/live_memory/components']))
->addRule(new DirectoryNameRule(baseDirectory: 'templates', ignoredSubDirectories: ['bundles', 'components', 'demos/live_memory/components', 'toolkit/docs']))
->addRule(new FileNameRule(baseDirectory: 'templates', ignoredSubDirectories: ['bundles', 'components', 'demos/live_memory/components', 'toolkit'], optionalPrefix: '_'))
->addRule(new DirectoryNameRule(case: FileNameRule::PASCAL_CASE, baseDirectory: 'templates/components'))
->addRule(new FileNameRule(case: FileNameRule::PASCAL_CASE, baseDirectory: 'templates/components'))
->addRule(new DirectoryNameRule(case: DirectoryNameRule::PASCAL_CASE, baseDirectory: 'demos/live_memory/components'))
->addRule(new FileNameRule(case: FileNameRule::PASCAL_CASE, baseDirectory: 'demos/live_memory/components'))
->addRule(new DirectoryNameRule(case: FileNameRule::KEBAB_CASE, baseDirectory: 'templates/toolkit/docs/'))
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DirectoryNameRule is being configured with case: FileNameRule::KEBAB_CASE. This looks like the wrong enum/constant source (DirectoryNameRule already uses its own constants, e.g. DirectoryNameRule::PASCAL_CASE above). Switch to the matching DirectoryNameRule::KEBAB_CASE constant to avoid misconfiguration or runtime errors if the constants diverge.

Suggested change
->addRule(new DirectoryNameRule(case: FileNameRule::KEBAB_CASE, baseDirectory: 'templates/toolkit/docs/'))
->addRule(new DirectoryNameRule(case: DirectoryNameRule::KEBAB_CASE, baseDirectory: 'templates/toolkit/docs/'))

Copilot uses AI. Check for mistakes.
->addRule(new FileNameRule(case: FileNameRule::KEBAB_CASE, baseDirectory: 'templates/toolkit/docs/', optionalPrefix: '_'))
->addRule(new FileExtensionRule())
// TwigCsFixer standard (customized for Symfony UX)
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ Download the importmap packages locally:
symfony console importmap:install
```

Build Toolkit assets:
```bash
composer tailwind:build
```

## Testing

```bash
Expand Down
6 changes: 6 additions & 0 deletions assets/icons/toolkit/flowbite-4.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
238 changes: 238 additions & 0 deletions assets/styles/toolkit-flowbite-4.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
@import "tailwindcss";
@import "../vendor/flowbite/dist/flowbite.min.css";
@source "../vendor/flowbite";
@source "../../vendor/symfony/ux-toolkit/kits/flowbite-4";

@custom-variant dark (&:is(.dark *));

@theme {
--font-sans: 'Inter', 'ui-sans-serif', 'system-ui', '-apple-system', 'system-ui', 'Segoe UI', 'Roboto', 'Helvetica Neue', 'Arial', 'Noto Sans', 'sans-serif', 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
--font-body: 'Inter', 'ui-sans-serif', 'system-ui', '-apple-system', 'system-ui', 'Segoe UI', 'Roboto', 'Helvetica Neue', 'Arial', 'Noto Sans', 'sans-serif', 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
--font-mono: 'ui-monospace', 'SFMono-Regular', 'Menlo', 'Monaco', 'Consolas', 'Liberation Mono', 'Courier New', 'monospace';

/* TEXT VARIABLES */
--text-2xs: 0.625rem;
--spacing-8xl: 90rem;
--leading-9: 36px; /* rem pls */
--leading-7: 28px;
--leading-8: 32px;
--leading-6: 24px;
--leading-4: 16px;
--leading-none: 1px;
--leading-5: 20px;
--tracking-tighter: -0.8px;
--leading-heading-none: 60px;
--tracking-tight: -0.4px;

/* BORDER RADIUS VARIABLES */
--radius-0: 0px;
--radius-xxs: 2px;
--radius-xs: 4px;
--radius-sm: 6px;
--radius: 8px;
--radius-base: 12px;
--radius-lg: 16px;

/* BORDER WIDTH VARIABLES */
--default-border-width: 1px;

/* TEXT COLORS VARIABLES */
/* main text color */
--color-body: var(--color-gray-600);
--color-body-subtle: var(--color-gray-500);

/* text heading colors */
--color-heading: var(--color-gray-900);

/* used for custom brand colors */
--color-fg-brand-subtle: var(--color-blue-200);
--color-fg-brand: var(--color-blue-700);
--color-fg-brand-strong: var(--color-blue-900);

/* used for status colors */
--color-fg-success: var(--color-emerald-700);
--color-fg-success-strong: var(--color-emerald-900);
--color-fg-danger: var(--color-rose-700);
--color-fg-danger-strong: var(--color-rose-900);
--color-fg-warning-subtle: var(--color-orange-600);
--color-fg-warning: var(--color-orange-900);
--color-fg-yellow: var(--color-yellow-400);
--color-fg-disabled: var(--color-gray-400);
--color-fg-purple: var(--color-purple-600);
--color-fg-cyan: var(--color-cyan-600);
--color-fg-indigo: var(--color-indigo-600);
--color-fg-pink: var(--color-pink-600);
--color-fg-lime: var(--color-lime-600);

/* BACKGROUND COLOR VARIABLES */
/* used for neutral colors */
--color-neutral-primary-soft: var(--color-white);
--color-neutral-primary: var(--color-white);
--color-neutral-primary-medium: var(--color-white);
--color-neutral-primary-strong: var(--color-white);
--color-neutral-secondary-soft: var(--color-gray-50);
--color-neutral-secondary: var(--color-gray-50);
--color-neutral-secondary-medium: var(--color-gray-50);
--color-neutral-secondary-strong: var(--color-gray-50);
--color-neutral-secondary-strongest: var(--color-gray-50);
--color-neutral-tertiary-soft: var(--color-gray-100);
--color-neutral-tertiary: var(--color-gray-100);
--color-neutral-tertiary-medium: var(--color-gray-100);
--color-neutral-quaternary: var(--color-gray-200);
--color-neutral-quaternary-medium: var(--color-gray-200);
--color-gray: var(--color-gray-300);

/* used for brand colors */
--color-brand-softer: var(--color-blue-50);
--color-brand-soft: var(--color-blue-100);
--color-brand: var(--color-blue-700);
--color-brand-medium: var(--color-blue-200);
--color-brand-strong: var(--color-blue-800);

/* used for status colors */
--color-success-soft: var(--color-emerald-50);
--color-success: var(--color-emerald-700);
--color-success-medium: var(--color-emerald-100);
--color-success-strong: var(--color-emerald-800);
--color-danger-soft: var(--color-rose-50);
--color-danger: var(--color-rose-700);
--color-danger-medium: var(--color-rose-100);
--color-danger-strong: var(--color-rose-800);
--color-warning-soft: var(--color-orange-50);
--color-warning: var(--color-orange-500);
--color-warning-medium: var(--color-orange-100);
--color-warning-strong: var(--color-orange-700);
--color-dark-soft: var(--color-gray-800);
--color-dark: var(--color-gray-800);
--color-dark-strong: var(--color-gray-900);
--color-disabled: var(--color-gray-100);
--color-purple: var(--color-purple-500);
--color-sky: var(--color-sky-500);
--color-teal: var(--color-teal-600);
--color-pink: var(--color-pink-600);
--color-cyan: var(--color-cyan-500);
--color-fuchsia: var(--color-fuchsia-600);
--color-indigo: var(--color-indigo-600);
--color-orange: var(--color-orange-400);

/* BORDER COLOR VARIABLES */
--color-buffer: var(--color-white);
--color-buffer-medium: var(--color-white);
--color-buffer-strong: var(--color-white);
--color-muted: var(--color-gray-50);
--color-light-subtle: var(--color-gray-100);
--color-light: var(--color-gray-100);
--color-light-medium: var(--color-gray-100);
--color-default-subtle: var(--color-gray-200);
--color-default: var(--color-gray-200);
--color-default-medium: var(--color-gray-200);
--color-default-strong: var(--color-gray-200);

/* used for status colors */
--color-success-subtle: var(--color-emerald-200);
--color-danger-subtle: var(--color-rose-200);
--color-warning-subtle: var(--color-orange-200);
--color-brand-subtle: var(--color-blue-200);
--color-brand-light: var(--color-blue-600);
--color-dark-subtle: var(--color-gray-800);
--color-dark-backdrop: var(--color-gray-950);

/* shiki variables */
--color-shiki-fg-brand: #79b8ff;
--color-shiki-fg-brand-subtle: #9ecbff;
}

.dark {
/* text color variables */
--color-body: var(--color-gray-400);
--color-body-subtle: var(--color-gray-400);
--color-heading: var(--color-white);
--color-fg-brand-subtle: var(--color-blue-200);
--color-fg-brand: var(--color-blue-500);
--color-fg-brand-strong: var(--color-blue-400);
--color-fg-success: var(--color-emerald-600);
--color-fg-success-strong: var(--color-emerald-300);
--color-fg-danger: var(--color-rose-500);
--color-fg-danger-strong: var(--color-rose-300);
--color-fg-warning-subtle: var(--color-orange-500);
--color-fg-warning: var(--color-orange-300);
--color-fg-yellow: var(--color-yellow-400);
--color-fg-disabled: var(--color-gray-600);
--color-fg-purple: var(--color-purple-500);
--color-fg-cyan: var(--color-cyan-500);
--color-fg-indigo: var(--color-indigo-500);
--color-fg-pink: var(--color-pink-500);
--color-fg-lime: var(--color-lime-500);

/* background color variables */
--color-neutral-primary-soft: var(--color-gray-900);
--color-neutral-primary: var(--color-gray-950);
--color-neutral-primary-medium: var(--color-gray-800);
--color-neutral-primary-strong: var(--color-gray-700);
--color-neutral-secondary-soft: var(--color-gray-900);
--color-neutral-secondary: var(--color-gray-950);
--color-neutral-secondary-medium: var(--color-gray-800);
--color-neutral-secondary-strong: var(--color-gray-700);
--color-neutral-secondary-strongest: var(--color-gray-600);
--color-neutral-tertiary-soft: var(--color-gray-900);
--color-neutral-tertiary: var(--color-gray-800);
--color-neutral-tertiary-medium: var(--color-gray-700);
--color-neutral-quaternary: var(--color-gray-700);
--color-neutral-quaternary-medium: var(--color-gray-600);
--color-gray: var(--color-gray-600);
--color-brand-softer: var(--color-blue-950);
--color-brand-soft: var(--color-blue-900);
--color-brand: var(--color-blue-600);
--color-brand-medium: var(--color-blue-900);
--color-brand-strong: var(--color-blue-700);
--color-success-soft: var(--color-emerald-950);
--color-success: var(--color-emerald-600);
--color-success-medium: var(--color-emerald-900);
--color-success-strong: var(--color-emerald-700);
--color-danger-soft: var(--color-rose-950);
--color-danger: var(--color-rose-700);
--color-danger-medium: var(--color-rose-900);
--color-danger-strong: var(--color-rose-800);
--color-warning-soft: var(--color-orange-950);
--color-warning: var(--color-orange-600);
--color-warning-medium: var(--color-orange-900);
--color-warning-strong: var(--color-orange-700);
--color-dark-soft: var(--color-gray-700);
--color-dark: var(--color-gray-800);
--color-dark-strong: var(--color-gray-700);
--color-disabled: var(--color-gray-800);
--color-purple: var(--color-purple-500);
--color-sky: var(--color-sky-500);
--color-teal: var(--color-teal-500);
--color-pink: var(--color-pink-500);
--color-cyan: var(--color-cyan-500);
--color-fuchsia: var(--color-fuchsia-500);
--color-indigo: var(--color-indigo-500);
--color-orange: var(--color-orange-400);

/* border color variables */
--color-buffer: var(--color-gray-950);
--color-buffer-medium: var(--color-gray-900);
--color-buffer-strong: var(--color-gray-800);
--color-muted: var(--color-gray-900);
--color-light-subtle: var(--color-gray-900);
--color-light: var(--color-gray-800);
--color-light-medium: var(--color-gray-700);
--color-default-subtle: var(--color-gray-900);
--color-default: var(--color-gray-800);
--color-default-medium: var(--color-gray-700);
--color-default-strong: var(--color-gray-600);
--color-success-subtle: var(--color-emerald-900);
--color-danger-subtle: var(--color-rose-900);
--color-warning-subtle: var(--color-orange-900);
--color-brand-subtle: var(--color-blue-900);
--color-brand-light: var(--color-blue-600);
--color-dark-subtle: var(--color-gray-700);
--color-dark-backdrop: var(--color-gray-950);
}

@layer base {
body {
@apply bg-neutral-primary;
}
}
11 changes: 11 additions & 0 deletions assets/toolkit-flowbite-4.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import './styles/toolkit-flowbite-4.css';
import 'flowbite';
import { startStimulusApp } from '@symfony/stimulus-bundle';
import Alert from '@symfony/ux-toolkit/kits/flowbite-4/alert/assets/controllers/alert_controller.js';
import Modal from '@symfony/ux-toolkit/kits/flowbite-4/modal/assets/controllers/modal_controller.js';
import Tabs from '@symfony/ux-toolkit/kits/flowbite-4/tabs/assets/controllers/tabs_controller.js';

const app = startStimulusApp();
app.register('alert', Alert);
app.register('modal', Modal);
app.register('tabs', Tabs);
17 changes: 11 additions & 6 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -136,17 +136,22 @@
},
"scripts": {
"post-install-cmd": [
"@auto-scripts"
"@auto-scripts",
"@tailwind:build"
],
"post-update-cmd": [
"@auto-scripts"
"@auto-scripts",
"@tailwind:build"
],
"auto-scripts": {
"cache:clear": "symfony-cmd",
"assets:install %PUBLIC_DIR%": "symfony-cmd",
"importmap:install": "symfony-cmd",
"tailwind:build assets/styles/app-tailwind.css": "symfony-cmd",
"tailwind:build assets/styles/toolkit-shadcn.css": "symfony-cmd"
}
"importmap:install": "symfony-cmd"
},
"tailwind:build": [
"@php bin/console tailwind:build assets/styles/app-tailwind.css",
"@php bin/console tailwind:build assets/styles/toolkit-shadcn.css",
"@php bin/console tailwind:build assets/styles/toolkit-flowbite-4.css"
Comment on lines +151 to +154
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new tailwind:build script uses @php bin/console ... while the rest of the Flex auto-scripts use symfony-cmd. Using symfony-cmd here as well keeps behavior consistent (env vars, Symfony CLI integration) and avoids differences between local/CI execution.

Copilot uses AI. Check for mistakes.
]
}
}
8 changes: 4 additions & 4 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions config/packages/symfonycasts_tailwind.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ symfonycasts_tailwind:
input_css:
- assets/styles/app-tailwind.css
- assets/styles/toolkit-shadcn.css
- assets/styles/toolkit-flowbite-4.css
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is not built when running tailwind:build, only the first is (I don't know why this choice?)

But it now means that we should replace our calls to tailwind:build to:

bin/console tailwind:build assets/styles/toolkit-shadcn.css
bin/console tailwind:build assets/styles/toolkit-flowbite-4.css

Maybe we can create a Composer script to make things easier?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, i'll do it ! :)

4 changes: 4 additions & 0 deletions config/reference.php
Original file line number Diff line number Diff line change
Expand Up @@ -965,6 +965,7 @@
* }
* @psalm-type LiveComponentConfig = array{
* secret?: scalar|null|Param, // The secret used to compute fingerprints and checksums // Default: "%kernel.secret%"
* fetch_credentials?: "same-origin"|"include"|"omit"|Param, // The default fetch credentials mode for all Live Components ('same-origin', 'include', 'omit') // Default: "same-origin"
* }
* @psalm-type LazyImageConfig = array{
* cache?: scalar|null|Param,
Expand Down Expand Up @@ -1279,6 +1280,9 @@
* path?: scalar|null|Param, // The local icon set directory path. (cannot be used with 'alias')
* alias?: scalar|null|Param, // The remote icon set identifier. (cannot be used with 'path')
* icon_attributes?: array<string, scalar|null|Param>,
* suffixes?: array<string, array{ // The suffix name (e.g. "solid", "20-solid") // Default: []
* icon_attributes?: array<string, scalar|null|Param>,
* }>,
* }>,
* aliases?: array<string, string|Param>,
* iconify?: bool|array{ // Configuration for the remote icon service.
Expand Down
Loading
Loading