Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • 2.0.x
  • 8.x-1.x
  • 2.0.0
  • 2.0.0-alpha1
  • 2.0.0-alpha2
  • 2.0.0-alpha3
  • 2.0.0-beta1
  • 2.0.0-beta2
  • 2.0.0-beta3
  • 2.0.0-beta4
  • 2.0.0-beta5
  • 2.0.0-beta6
  • 2.0.0-rc1
  • 2.0.0-rc2
  • 2.0.1
  • 2.0.2
  • 2.0.3
  • 8.x-1.0
  • 8.x-1.0-beta1
  • 8.x-1.0-beta2
  • 8.x-1.0-beta3
  • 8.x-1.0-beta4
  • 8.x-1.0-beta5
  • 8.x-1.0-beta6
  • 8.x-1.0-beta7
  • 8.x-1.0-rc1
  • 8.x-1.0-rc2
  • 8.x-1.1
  • 8.x-1.10
  • 8.x-1.2
  • 8.x-1.3
  • 8.x-1.4
  • 8.x-1.5
  • 8.x-1.6
  • 8.x-1.7
  • 8.x-1.8
  • 8.x-1.9
  • previous/3395953-2.0.x-add-new/2024-01-11
  • previous/3395960-2.0.x-add-new/2024-01-30
  • previous/3395960-2.0.x-add-new/2024-01-30-1
  • previous/3395960-2.0.x-add-new/2024-01-30-2
  • previous/3395960-2.0.x-test-new-context/2024-04-05-2
  • previous/3413589-2.0.0-beta1-add-alterinfocomponentinfo/2024-07-22
  • previous/3414291-2.0.0-alpha1-source-pluginsmethods/2024-02-24
  • previous/3414291-2.0.0-alpha1-source-pluginsmethods/2024-02-24-1
  • previous/3423185-2.0.0-alpha3-add-allowexpose-derivable_contexts/2024-06-24-2
  • previous/3423185-2.0.0-alpha3-add-allowexpose/2024-06-09
  • previous/3423185-2.0.0-alpha3-add-allowexpose/2024-06-15
  • previous/3423185-2.0.0-alpha3-add-allowexpose/2024-06-20
  • previous/3423185-2.0.0-alpha3-add-allowexpose/2024-06-20-1
  • previous/3423185-2.0.0-alpha3-add-allowexpose/2024-06-21
  • previous/3443441-one-block-per-component/2024-05-27
  • previous/3444770-2.0.0-beta1-componentformbuilder-make/2024-07-26
  • previous/3444770-2.0.0-beta1-componentformbuilder-make/2024-08-05
  • previous/3461566-2.0.0-beta2-ux-slots/2024-09-09-1
  • previous/3469814-2.0.0-beta2-kernel-source/2024-09-05
  • previous/3470386--2.0.0-beta2-render/2024-08-26
57 results

Target

Select target project
  • project/ui_patterns
  • issue/ui_patterns-3290197
  • issue/ui_patterns-3311088
  • issue/ui_patterns-3311340
  • issue/ui_patterns-3311342
  • issue/ui_patterns-3311471
  • issue/ui_patterns-3314293
  • issue/ui_patterns-3313689
  • issue/ui_patterns-3314463
  • issue/ui_patterns-3318269
  • issue/ui_patterns-3314998
  • issue/ui_patterns-3316487
  • issue/ui_patterns-3311455
  • issue/ui_patterns-3314789
  • issue/ui_patterns-3326826
  • issue/ui_patterns-3315661
  • issue/ui_patterns-3311452
  • issue/ui_patterns-3315533
  • issue/ui_patterns-3315660
  • issue/ui_patterns-3311464
  • issue/ui_patterns-3328272
  • issue/ui_patterns-3333738
  • issue/ui_patterns-3342949
  • issue/ui_patterns-3335833
  • issue/ui_patterns-3341073
  • issue/ui_patterns-3311480
  • issue/ui_patterns-3348852
  • issue/ui_patterns-3342390
  • issue/ui_patterns-3349076
  • issue/ui_patterns-3349077
  • issue/ui_patterns-3349079
  • issue/ui_patterns-3353287
  • issue/ui_patterns-3353289
  • issue/ui_patterns-3347891
  • issue/ui_patterns-3351682
  • issue/ui_patterns-3336970
  • issue/ui_patterns-3406383
  • issue/ui_patterns-3371032
  • issue/ui_patterns-3369867
  • issue/ui_patterns-3377457
  • issue/ui_patterns-3381188
  • issue/ui_patterns-3383762
  • issue/ui_patterns-3344405
  • issue/ui_patterns-3395953
  • issue/ui_patterns-3395963
  • issue/ui_patterns-3395960
  • issue/ui_patterns-3410258
  • issue/ui_patterns-3424696
  • issue/ui_patterns-3441490
  • issue/ui_patterns-3413043
  • issue/ui_patterns-3413703
  • issue/ui_patterns-3414116
  • issue/ui_patterns-3414363
  • issue/ui_patterns-3414293
  • issue/ui_patterns-3414774
  • issue/ui_patterns-3417517
  • issue/ui_patterns-3382718
  • issue/ui_patterns-3420517
  • issue/ui_patterns-3420628
  • issue/ui_patterns-3420653
  • issue/ui_patterns-3421484
  • issue/ui_patterns-3421688
  • issue/ui_patterns-3414291
  • issue/ui_patterns-3438996
  • issue/ui_patterns-3438998
  • issue/ui_patterns-3427538
  • issue/ui_patterns-3441326
  • issue/ui_patterns-3446471
  • issue/ui_patterns-3438952
  • issue/ui_patterns-3438432
  • issue/ui_patterns-3437218
  • issue/ui_patterns-3435188
  • issue/ui_patterns-3435827
  • issue/ui_patterns-3441484
  • issue/ui_patterns-3439414
  • issue/ui_patterns-3440202
  • issue/ui_patterns-3440319
  • issue/ui_patterns-3440310
  • issue/ui_patterns-3440278
  • issue/ui_patterns-3438949
  • issue/ui_patterns-3395959
  • issue/ui_patterns-3441987
  • issue/ui_patterns-3440441
  • issue/ui_patterns-3439407
  • issue/ui_patterns-3444348
  • issue/ui_patterns-3437250
  • issue/ui_patterns-3445079
  • issue/ui_patterns-3447833
  • issue/ui_patterns-3443441
  • issue/ui_patterns-3444716
  • issue/ui_patterns-3449932
  • issue/ui_patterns-3444711
  • issue/ui_patterns-3444822
  • issue/ui_patterns-3447985
  • issue/ui_patterns-3452751
  • issue/ui_patterns-3450015
  • issue/ui_patterns-3423185
  • issue/ui_patterns-3444768
  • issue/ui_patterns-3447902
  • issue/ui_patterns-3453793
  • issue/ui_patterns-3454499
  • issue/ui_patterns-3454615
  • issue/ui_patterns-3455076
  • issue/ui_patterns-3455074
  • issue/ui_patterns-3395954
  • issue/ui_patterns-3360373
  • issue/ui_patterns-3438360
  • issue/ui_patterns-3455951
  • issue/ui_patterns-3456083
  • issue/ui_patterns-3456295
  • issue/ui_patterns-3456335
  • issue/ui_patterns-3456484
  • issue/ui_patterns-3457273
  • issue/ui_patterns-3457505
  • issue/ui_patterns-3457620
  • issue/ui_patterns-3456571
  • issue/ui_patterns-3458364
  • issue/ui_patterns-3413609
  • issue/ui_patterns-3459187
  • issue/ui_patterns-3459271
  • issue/ui_patterns-3413589
  • issue/ui_patterns-3459741
  • issue/ui_patterns-3459113
  • issue/ui_patterns-3462312
  • issue/ui_patterns-3462329
  • issue/ui_patterns-3452481
  • issue/ui_patterns-3462505
  • issue/ui_patterns-3460800
  • issue/ui_patterns-3460784
  • issue/ui_patterns-3461858
  • issue/ui_patterns-3462504
  • issue/ui_patterns-3444770
  • issue/ui_patterns-3461579
  • issue/ui_patterns-3461274
  • issue/ui_patterns-3461277
  • issue/ui_patterns-3462818
  • issue/ui_patterns-3464287
  • issue/ui_patterns-3464288
  • issue/ui_patterns-3464291
  • issue/ui_patterns-3464290
  • issue/ui_patterns-3464289
  • issue/ui_patterns-3464879
  • issue/ui_patterns-3441232
  • issue/ui_patterns-3465262
  • issue/ui_patterns-3465264
  • issue/ui_patterns-3464894
  • issue/ui_patterns-3465432
  • issue/ui_patterns-3465453
  • issue/ui_patterns-3465497
  • issue/ui_patterns-3465517
  • issue/ui_patterns-3465488
  • issue/ui_patterns-3465524
  • issue/ui_patterns-3465764
  • issue/ui_patterns-3465821
  • issue/ui_patterns-3465823
  • issue/ui_patterns-3463153
  • issue/ui_patterns-3466385
  • issue/ui_patterns-3466495
  • issue/ui_patterns-3466381
  • issue/ui_patterns-3464630
  • issue/ui_patterns-3466958
  • issue/ui_patterns-3467219
  • issue/ui_patterns-3467398
  • issue/ui_patterns-3467411
  • issue/ui_patterns-3467502
  • issue/ui_patterns-3467653
  • issue/ui_patterns-3461566
  • issue/ui_patterns-3467825
  • issue/ui_patterns-3466359
  • issue/ui_patterns-3466353
  • issue/ui_patterns-3469814
  • issue/ui_patterns-3469665
  • issue/ui_patterns-3470386
  • issue/ui_patterns-3470231
  • issue/ui_patterns-3469808
  • issue/ui_patterns-3471426
  • issue/ui_patterns-3471587
  • issue/ui_patterns-3462146
  • issue/ui_patterns-3455354
  • issue/ui_patterns-3473038
  • issue/ui_patterns-3472571
  • issue/ui_patterns-3467655
  • issue/ui_patterns-3467652
  • issue/ui_patterns-3473344
  • issue/ui_patterns-3473372
  • issue/ui_patterns-3473393
  • issue/ui_patterns-3473412
  • issue/ui_patterns-3462737
  • issue/ui_patterns-3473021
  • issue/ui_patterns-3473621
  • issue/ui_patterns-3456072
  • issue/ui_patterns-3469805
  • issue/ui_patterns-3473804
  • issue/ui_patterns-3473346
  • issue/ui_patterns-3464869
  • issue/ui_patterns-3474113
  • issue/ui_patterns-3474140
  • issue/ui_patterns-3474141
  • issue/ui_patterns-3474137
  • issue/ui_patterns-3474892
  • issue/ui_patterns-3475282
  • issue/ui_patterns-3475564
  • issue/ui_patterns-3475574
  • issue/ui_patterns-3474822
  • issue/ui_patterns-3475857
  • issue/ui_patterns-3474641
  • issue/ui_patterns-3473852
  • issue/ui_patterns-3475163
  • issue/ui_patterns-3467657
  • issue/ui_patterns-3475962
  • issue/ui_patterns-3476246
  • issue/ui_patterns-3476469
  • issue/ui_patterns-3440293
  • issue/ui_patterns-3477106
  • issue/ui_patterns-3477296
  • issue/ui_patterns-3477573
  • issue/ui_patterns-3477625
  • issue/ui_patterns-3467656
  • issue/ui_patterns-3477702
  • issue/ui_patterns-3477419
  • issue/ui_patterns-3478622
  • issue/ui_patterns-3478655
  • issue/ui_patterns-3478648
  • issue/ui_patterns-3479095
  • issue/ui_patterns-3477287
  • issue/ui_patterns-3479850
  • issue/ui_patterns-3480474
  • issue/ui_patterns-3479656
  • issue/ui_patterns-3480553
  • issue/ui_patterns-3478657
  • issue/ui_patterns-3481051
  • issue/ui_patterns-3481405
  • issue/ui_patterns-3481479
  • issue/ui_patterns-3481896
  • issue/ui_patterns-3482208
  • issue/ui_patterns-3483508
  • issue/ui_patterns-3483939
  • issue/ui_patterns-3483489
  • issue/ui_patterns-3485290
  • issue/ui_patterns-3485497
  • issue/ui_patterns-3485900
  • issue/ui_patterns-3486050
  • issue/ui_patterns-3485895
  • issue/ui_patterns-3486547
  • issue/ui_patterns-3483496
  • issue/ui_patterns-3462325
  • issue/ui_patterns-3383544
  • issue/ui_patterns-3449653
  • issue/ui_patterns-3487819
  • issue/ui_patterns-3484830
  • issue/ui_patterns-3488044
  • issue/ui_patterns-3488166
  • issue/ui_patterns-3488167
  • issue/ui_patterns-3488582
  • issue/ui_patterns-3477890
  • issue/ui_patterns-3481540
  • issue/ui_patterns-3488879
  • issue/ui_patterns-3490387
  • issue/ui_patterns-3489973
  • issue/ui_patterns-3490599
  • issue/ui_patterns-3490615
  • issue/ui_patterns-3490696
  • issue/ui_patterns-3490733
  • issue/ui_patterns-3473889
  • issue/ui_patterns-3491238
  • issue/ui_patterns-3491369
  • issue/ui_patterns-3491536
  • issue/ui_patterns-3491560
  • issue/ui_patterns-3487818
  • issue/ui_patterns-3492211
  • issue/ui_patterns-3474511
  • issue/ui_patterns-3437220
  • issue/ui_patterns-3481491
  • issue/ui_patterns-3490872
  • issue/ui_patterns-3492962
  • issue/ui_patterns-3483831
  • issue/ui_patterns-3494404
  • issue/ui_patterns-3494336
  • issue/ui_patterns-3472993
  • issue/ui_patterns-3490873
  • issue/ui_patterns-3494794
  • issue/ui_patterns-3494338
  • issue/ui_patterns-3490476
  • issue/ui_patterns-3494949
  • issue/ui_patterns-3491705
  • issue/ui_patterns-3490150
  • issue/ui_patterns-3487548
  • issue/ui_patterns-3493134
  • issue/ui_patterns-3495847
  • issue/ui_patterns-3495982
  • issue/ui_patterns-3498128
  • issue/ui_patterns-3498184
  • issue/ui_patterns-3496114
  • issue/ui_patterns-3496111
  • issue/ui_patterns-3497683
  • issue/ui_patterns-3498428
  • issue/ui_patterns-3499625
  • issue/ui_patterns-3498456
  • issue/ui_patterns-3495984
  • issue/ui_patterns-3498137
  • issue/ui_patterns-3500243
  • issue/ui_patterns-3499983
  • issue/ui_patterns-3500669
  • issue/ui_patterns-3500244
  • issue/ui_patterns-3498496
  • issue/ui_patterns-3501430
  • issue/ui_patterns-3501400
  • issue/ui_patterns-3501914
  • issue/ui_patterns-3502069
  • issue/ui_patterns-3502079
  • issue/ui_patterns-3502916
  • issue/ui_patterns-3503141
  • issue/ui_patterns-3504119
  • issue/ui_patterns-3504351
  • issue/ui_patterns-3504811
  • issue/ui_patterns-3504857
  • issue/ui_patterns-3506138
  • issue/ui_patterns-3506145
  • issue/ui_patterns-3508054
  • issue/ui_patterns-3507007
  • issue/ui_patterns-3508463
  • issue/ui_patterns-3510560
  • issue/ui_patterns-3510596
  • issue/ui_patterns-3511027
  • issue/ui_patterns-3511112
  • issue/ui_patterns-3511203
  • issue/ui_patterns-3512018
  • issue/ui_patterns-3511397
  • issue/ui_patterns-3512477
  • issue/ui_patterns-3511351
  • issue/ui_patterns-3513456
  • issue/ui_patterns-3513546
  • issue/ui_patterns-3513568
  • issue/ui_patterns-3513653
  • issue/ui_patterns-3514270
  • issue/ui_patterns-3514800
  • issue/ui_patterns-3514886
  • issue/ui_patterns-3488418
  • issue/ui_patterns-3515500
  • issue/ui_patterns-3516308
  • issue/ui_patterns-3516369
  • issue/ui_patterns-3508748
  • issue/ui_patterns-3517343
  • issue/ui_patterns-3517621
  • issue/ui_patterns-3517724
  • issue/ui_patterns-3517695
  • issue/ui_patterns-3518099
  • issue/ui_patterns-3519282
  • issue/ui_patterns-3519517
  • issue/ui_patterns-3519543
  • issue/ui_patterns-3519934
  • issue/ui_patterns-3506207
  • issue/ui_patterns-3523040
353 results
Select Git revision
  • 2.0.x
  • 3414293-2.0.0-alpha1-implement-proptypeinterfaceconvertfrom
  • 3465488-2.0.0-beta1-drupal-11
  • 8.x-1.x
  • 2.0.0-alpha1
  • 2.0.0-alpha2
  • 2.0.0-alpha3
  • 8.x-1.0
  • 8.x-1.0-beta1
  • 8.x-1.0-beta2
  • 8.x-1.0-beta3
  • 8.x-1.0-beta4
  • 8.x-1.0-beta5
  • 8.x-1.0-beta6
  • 8.x-1.0-beta7
  • 8.x-1.0-rc1
  • 8.x-1.0-rc2
  • 8.x-1.1
  • 8.x-1.2
  • 8.x-1.3
  • 8.x-1.4
  • 8.x-1.5
  • 8.x-1.6
  • 8.x-1.7
  • 8.x-1.8
  • previous/3395953-2.0.x-add-new/2024-01-11
  • previous/3395960-2.0.x-add-new/2024-01-30
  • previous/3395960-2.0.x-add-new/2024-01-30-1
  • previous/3395960-2.0.x-add-new/2024-01-30-2
  • previous/3395960-2.0.x-test-new-context/2024-04-05-2
  • previous/3414291-2.0.0-alpha1-source-pluginsmethods/2024-02-24
  • previous/3414291-2.0.0-alpha1-source-pluginsmethods/2024-02-24-1
  • previous/3414293-2.0.0-alpha1-implement-proptypeinterfaceconvertfrom/2024-02-24
  • previous/3414293-2.0.0-alpha1-implement-proptypeinterfaceconvertfrom/2024-03-28
  • previous/3414293-2.0.0-alpha1-implement-proptypeinterfaceconvertfrom/2024-04-02
  • previous/3414293-2.0.0-alpha1-implement-proptypeinterfaceconvertfrom/2024-04-03
  • previous/3414293-2.0.0-alpha1-implement-proptypeinterfaceconvertfrom/2024-04-04
  • previous/3414293-2.0.0-alpha1-implement-proptypeinterfaceconvertfrom/2024-04-16
  • previous/3414293-2.0.0-alpha1-implement-proptypeinterfaceconvertfrom/2024-05-13
  • previous/3414293-2.0.0-alpha1-implement-proptypeinterfaceconvertfrom/2024-06-05
  • previous/3423185-2.0.0-alpha3-add-allowexpose/2024-06-09
  • previous/3427538-2.0.0-alpha2-form-builder/2024-04-16
  • previous/3427538-2.0.0-alpha2-form-builder/2024-04-16-1
  • previous/3427538-2.0.0-alpha2-form-builder/2024-05-03
  • previous/3443441-one-block-per-component/2024-05-27
  • previous/3456571-2.0.0-alpha3-rename-source/2024-07-01
  • previous/3458364-2.0.0-alpha3-little-cleanups/2024-07-02
47 results
Show changes
Commits on Source (184)
Showing
with 824 additions and 12 deletions
behaviours
ctahref
hotwire
htmx
canonicalizer
canonicalized
coloris
contextful
corge
criticals
daisyui
dsfr
endsandbox
favourite
getattr
grault
kint
maxcontains
mincontains
pdureau
proptype
pymdownx
recursivity
sameas
sdc's
spottable
subcomponent
toolset
uswds
......@@ -28,7 +28,7 @@ include:
- vendor/bin/phpmd --version
- vendor/bin/phpmd $_WEB_ROOT/modules/custom/$CI_PROJECT_NAME gitlab $_WEB_ROOT/modules/custom/$CI_PROJECT_NAME/.phpmd.xml --exclude 'tests/*,**/tests/*' > phpmd-quality-report.json || true
- vendor/bin/phpmd $_WEB_ROOT/modules/custom/$CI_PROJECT_NAME text $_WEB_ROOT/modules/custom/$CI_PROJECT_NAME/.phpmd.xml --exclude 'tests/*,**/tests/*'
allow_failure: true
allow_failure: false
artifacts:
expose_as: phpmd
when: always
......@@ -39,5 +39,69 @@ include:
paths:
- phpmd-quality-report.json
.twig-lint-base:
stage: validate
before_script:
- composer require --dev vincentlanglet/twig-cs-fixer
script:
- vendor/bin/twig-cs-fixer lint --config=$_WEB_ROOT/modules/custom/$CI_PROJECT_NAME/.twig-cs-fixer.php $_WEB_ROOT/modules/custom/$CI_PROJECT_NAME
rules:
- changes:
- "**/*.twig"
- if: '$CI_PIPELINE_SOURCE == "push"'
allow_failure: false
artifacts:
expose_as: twig-lint
when: always
expire_in: 6 mos
reports:
codequality: twig-lint-quality-report.xml
name: artifacts-$CI_PIPELINE_ID-$CI_JOB_NAME_SLUG
paths:
- twig-lint-quality-report.xml
.prettier-lint-base:
stage: validate
script:
- echo "Prettier version $(${CI_PROJECT_DIR}/${_WEB_ROOT}/core/node_modules/.bin/prettier --version)"
- ${CI_PROJECT_DIR}/${_WEB_ROOT}/core/node_modules/.bin/prettier --check ${CI_PROJECT_DIR}/docs/
rules:
- changes:
- "docs/*.md"
- "docs/**/*.md"
allow_failure: false
artifacts:
expose_as: prettier-lint
when: always
expire_in: 6 mos
reports:
codequality: prettier-lint-quality-report.xml
name: artifacts-$CI_PIPELINE_ID-$CI_JOB_NAME_SLUG
paths:
- prettier-lint-quality-report.xml
phpmd:
extends: .phpmd-base
twig-lint:
extends: .twig-lint-base
prettier-lint:
extends: .prettier-lint-base
composer-lint:
allow_failure: false
cspell:
allow_failure: false
variables:
_CSPELL_IGNORE_PATHS: '**/tests/fixtures/config/*.yml, **/tests/fixtures/*.yml'
eslint:
allow_failure: false
phpcs:
allow_failure: false
phpstan:
allow_failure: false
phpunit:
allow_failure: false
variables:
_PHPUNIT_EXTRA: ''
<?php
$ruleset = new TwigCsFixer\Ruleset\Ruleset();
// Add a default standard.
$ruleset->addStandard(new TwigCsFixer\Standard\TwigCsFixer());
// Add some specific rules.
$ruleset->addRule(new TwigCsFixer\Rules\File\FileExtensionRule());
$config = new TwigCsFixer\Config\Config();
$config->setRuleset($ruleset);
return $config;
......@@ -8,28 +8,27 @@ Components are reusable, nestable, guided by clear standards, and can be assembl
The UI Patterns project provides 3 "toolset" modules:
- **UI Patterns**: the main module, based on Drupal Core SDC API, with additional powerful API and quality-of-life improvements
- **UI Patterns Library**: generates a pattern library page available at `/patterns`
- **UI Patterns**: the main module, based on Drupal Core SDC API, with some extra features and quality-of-life improvements
- **UI Patterns Library**: generates a pattern library page available at `/admin/appearance/ui/components`
to be used as documentation for content editors or as a showcase for business. Use this module if you don't plan to
use more advanced component library systems such as Storybook, PatternLab or Fractal.
[Learn more](https://www.drupal.org/docs/contributed-modules/ui-patterns/define-your-patterns)
- **UI Patterns Legacy**: Load your UI Patterns 1.x components inside UI Patterns 2.x
4 "integration" modules:
- **UI Patterns Layouts**: allows to use components as layouts. This allows patterns to be used with Layout Builder,
[Display Suite](https://www.drupal.org/project/ds) or [Panels](https://www.drupal.org/project/panels)
out of the box. [Learn more](https://www.drupal.org/docs/contributed-modules/ui-patterns/use-patterns-as-layouts)
[Display Suite](https://www.drupal.org/project/ds) or [Layout Paragraphs](https://www.drupal.org/project/layout_paragraphs)
out of the box.
- **UI Patterns Blocks**: allows to use components as Blocks plugins.
- **UI Patterns Field Formatters**: allows to use components as Field Formatters plugins.
- **UI Patterns Views**: allows to use components as Views styles or Views rows plugins.
[Learn more](https://www.drupal.org/docs/contributed-modules/ui-patterns/use-patterns-with-views)
1 "devel" module:
- **UI Patterns Devel**: provide some tools to help developers working with Component. Currently a Twig static
validator to detect errors and help follow good practices for UI Patterns.
## Documentation
Documentation is available [here](https://www.drupal.org/docs/contributed-modules/ui-patterns).
## Testing
### Performance testing
UI Patterns uses [Gander](https://www.drupal.org/docs/develop/automated-testing/performance-tests) to automate performance measuring.
We suggest to use ddev with the [Gander Addon](https://github.com/tag1consulting/ddev-gander) to view render results.
ui_patterns_component:
type: mapping
label: 'Component configuration'
constraints:
FullyValidatable: ~
mapping:
component_id:
type: string
label: 'Component ID'
nullable: true
variant_id:
type: ui_patterns_prop
nullable: true
label: 'Variant ID'
# @todo make a mechanism that will check the props keys depending on the
# the component ID. And so maybe convert into mapping.
props:
type: sequence
label: 'Props'
sequence:
type: ui_patterns_prop
label: 'Prop'
# @todo make a mechanism that will check the slots keys depending on the
# the component ID. And so maybe convert into mapping.
slots:
type: sequence
label: 'Slots'
sequence:
type: ui_patterns_slot
label: 'Slot'
ui_patterns_prop:
type: mapping
label: 'Prop'
mapping:
source_id:
type: string
label: 'Prop source ID'
source:
type: ui_patterns_source.[%parent.source_id]
label: 'Prop source configuration'
ui_patterns_slot:
type: mapping
label: 'Slot'
mapping:
sources:
type: sequence
label: 'Slot sources'
sequence:
type: ui_patterns_slot_source
label: 'Slot source'
ui_patterns_slot_source:
type: mapping
label: 'Slot source'
mapping:
source_id:
type: string
label: 'Slot source ID'
source:
type: ui_patterns_source.[%parent.source_id]
label: 'Slot source configuration'
_weight:
type: string
label: 'Slot source weight'
ui_patterns_source.checkbox:
type: mapping
label: 'Source: checkbox'
mapping:
value:
type: boolean
label: 'Checkbox value'
ui_patterns_source.attribute:
type: mapping
label: 'Source: attribute'
mapping:
value:
type: boolean
label: 'Attribute value'
ui_patterns_source.path:
type: mapping
label: 'Source: Path'
mapping:
value:
type: path
label: 'Path value'
ui_patterns_source.url:
type: mapping
label: 'Source: URL'
mapping:
value:
type: uri
label: 'URL value'
ui_patterns_source.textfield:
type: mapping
label: 'Source: Textfield'
mapping:
value:
type: string
label: 'String value'
ui_patterns_source.select:
type: mapping
label: 'Source: Select'
mapping:
value:
type: string
label: 'Select value'
ui_patterns_source.selects:
type: mapping
label: 'Source: Selects'
mapping:
value:
type: sequence
label: 'Selects value'
sequence:
type: string
label: 'Values'
ui_patterns_source.attributes:
type: mapping
label: 'Source: Attributes'
mapping:
value:
type: string
label: 'Attribute value'
ui_patterns_source.attributes_class:
type: mapping
label: 'Source: Attributes Class'
mapping:
value:
type: string
label: 'Attributes Class value'
ui_patterns_source.list_textarea:
type: mapping
label: 'Source: List Text area'
mapping:
value:
type: string
label: 'Source List Text area values'
ui_patterns_source.number:
type: mapping
label: 'Source: Number'
mapping:
value:
type: string
label: 'Number value'
ui_patterns_source.wysiwyg:
type: mapping
label: 'Source: WYSIWYG'
mapping:
value:
type: text_format
label: 'WYSIWYG value'
ui_patterns_source.component:
type: mapping
label: 'Source: Component'
mapping:
component:
type: ui_patterns_component
ui_patterns_source.checkboxes:
type: mapping
label: 'Source: Checkboxes'
mapping:
value:
type: sequence
label: 'Selects value'
sequence:
type: string
label: 'Select Item Value'
ui_patterns_source.entity_link:
type: mapping
label: 'Source: Entity Link'
mapping:
template:
type: string
ui_patterns_source.menu:
type: mapping
label: 'Source: Menu'
mapping:
menu:
type: string
label: 'Menu Name'
level:
type: string
label: 'Entry Level'
depth:
type: string
label: 'Menu depth'
ui_patterns_source.token:
type: mapping
label: 'Source: Token'
mapping:
value:
type: string
label: 'Token value'
ui_patterns_source.field_property:*:*:*:
type: mapping
label: 'Source: Field Property'
mapping:
type:
type: string
label: 'Field Property type'
# block uses dynamic subkeys not under a specific key.
# The configuration looks like:
# plugin_id: block_id
# block_id:
# config_1: #
# I cant find a solution to handle this correct. Sequences would work
# if the the block_id key would be under an extra key. Something like config.block_id
ui_patterns_source.block:
type: ignore
# Same here ui_patterns_source.block
ui_patterns_source.entity_field:
type: ignore
# This source uses a dynamic subkey.
# The configuration looks like:
# source_id: entity_reference
# source:
# derivable_context: 'context:id'
# 'context:id':
ui_patterns_source.entity_reference:
type: ignore
# Component form
The biggest feature of UI Patterns is the generation of forms from the components definition:
| From component definition.... | ... to component form |
| --------------------------------- | ----------------------- |
| ![](images/bs-alert-example.webp) | ![](images/form-1.webp) |
Those forms will be shown everywhere a component is used:
- [as blocks](1-as-block.md)
- [as layouts](1-as-block.md)
- [in field formatters](1-as-block.md)
- [in views](1-as-block.md)
- ...
## Data sources
Values are taken from sources:
- "Widgets": simple form elements storing directly the data filled by the user. For example, a `textfield` for a string or a `checkbox` for a boolean.
- Sources retrieving data from Drupal API: they can be context agnostic (ex: a menu for links) or context specific (ex: the title field for a string)
- Context switchers: They don't retrieve data but they give access to other data sources. For example, the author fields from an article content.
If there is only a single source available, the source form is directly displayed:
![](images/sources-1.webp)
If there are at least 2, a source selector is shown:
![](images/sources-2.webp)
Some sources doesn't have a form, selecting the source is enough:
![](images/sources-3.webp)
## Context
Sometimes sources require another object in order to retrieve the data. This is known as context.
Some source doesn't need a context and are site wide, for example:
- All “widgets” which are source plugins with only direct input: Textfield, Select, Checkbox…
- List of all menus
- The breadcrumb
-
But some of them will need context. Examples:
| Context | Source | Prop type | Description |
| --------------- | ------------------- | --------- | ------------------------------------------ |
| Content entity | Data from a field | | Switch to a Field context. |
| Content entity | Entity link | URL |
| Content entity | Referenced entities | | Switch to an other Content entity context. |
| Field | Field formatter | Slot |
| Field | Field label | String |
| Field | Field prop : \* | (many) |
| Reference field | Field prop: entity | | Switch to a Content entity context. |
| View | View title | String |
| View | View rows | Slot |
| View row | View title | String |
| View row | View field | Slot |
## Variant selector
Some components have variants, a list of different "look" of the component. Variants doesn't change the model or the meaning of the component, only the look.
![](images/variant-1.webp)
## Slots
SDC components are made of slots & props:
- **Slots**: “areas” for free renderables only, like Drupal blocks or other SDC components for example.
- **Props**: strictly typed data only, for some UI logic in the template.
You can draw the slots areas in a component screenshot:
![](images/slots-vs-props.webp)
For each slots, its is possible to add one or many sources:
![](images/slot-1.webp)
For example:
- "Component": nest another SDC component in the slot.
- "Block": add a Drupal block plugin
- "Wysiwyg": a simple text editor, using the text formats defined in your site.
Other modules can add other sources. For example, "Icon" in this screenshot is brought by https://www.drupal.org/project/ui_icons
Once a source is added, it can be configured and we can add more because the selector is still present:
![](images/slot-2.webp)
Sources can be reordered inside a slot.
Using the "Component" source, we have access to the embedded component slots and we can nest data:
![](images/slot-3.webp)
## Props
A bit like the form for slots with 2 main differences:
- We don’t allow multiple items, so we can replace the source but not add some (and of course no reordering)
- The default source form is already loaded.
![](images/props-1.webp)
The available sources are varying according to both:
- the prop type. Each prop as a type, which is related to its JSON schema typing, but not exactly the same. You can check what type has a prop in the [component library](../2-authors/1-stories-and-library.md). A prop without a type is not displayed in the form.
- the context, as explained before.
# Using a component as a Drupal block
You need to activate `ui_patterns_blocks` sub-module.
Blocks are boxes of content rendered into an area, or region, of a web page (such as "User Login" or "Who's online") that can be displayed in regions (such as footer or sidebar) on your page or content display.
## In Block Layout (`/admin/structure/block`)
Every UI component is a Drupal block plugin, available in the "Place block" modal:
![](images/block-1.webp)
For example, to assign any component in the Header region, click on "Place Block" button and choose the component to be placed in this particular region.
The component is configurable as an usual block plugin, with the [Component form](3.0-component-form.md) alongside the block title, the visibility settings and the block placement:
![](images/block-2.webp)
### Contextual data sources
There is no specific context here. Only the generic data sources are available.
## In Layout Builder
Drupal's Layout Builder allows content editors and site builders to create visual layouts for displaying content. Users can customize how content is arranged on a single page, across types of content, or even create custom landing pages with an easy to use drag-and-drop interface.
The Layout Builder provides the ability to drag and drop site-wide blocks and content fields into regions within a given layout.
![](images/block-3.webp)
Component props are available in the sidebar as block settings:
![](images/block-4.webp)
### Contextual data sources
| Context | Source | Prop type | Description |
| -------------- | ------------------- | --------- | ------------------------------------------ |
| Content entity | Data from a field | | Switch to a Field context. |
| Content entity | Entity link | URL |
| Content entity | Referenced entities | | Switch to an other Content entity context. |
# Using a component as a layout
You need to activate `ui_patterns_layouts` sub-module.
## Layout plugins
SDC components have a model quite similar to Drupal layout plugins:
- Component slots are layout plugin regions
- Component props are layout plugin settings
## In Layout Builder
Drupal's Layout Builder allows content editors and site builders to create visual layouts for displaying content. Users can customize how content is arranged on a single page, across types of content, or even create custom landing pages with an easy to use drag-and-drop interface.
The Layout Builder provides the ability to drag and drop site-wide blocks and content fields into regions within a given layout.
Each section can contain content arranged in a certain layout. Each UI component is exposed as a layout plugin:
![](images/layout-1.webp)
If a component has a `thumbnail.webp`, it will be shown in the layouts list:
![](images/layout-3.webp)
Section configuration is a [Component form](3.0-component-form.md), without the slots because slots are directly managed by Layout Builder as regions of the layout:
![](images/layout-2.webp)
### Contextual data sources
There is no UI Patterns sources for slots here because slots are directly managed by Layout Builder as regions. So, only Drupal blocks plugins are available.
| Context | Source | Prop type | Description |
| -------------- | ------------------- | --------- | ------------------------------------------ |
| Content entity | Data from a field | | Switch to a Field context. |
| Content entity | Entity link | URL |
| Content entity | Referenced entities | | Switch to an other Content entity context. |
# Using a component in field formatters
Field Formatters are Drupal plugins formatting the output of a content field. For example:
- Date field formatted as "... time ago"
- Date field formatted with a custom date format
- Entity reference field formatted as label
- Entity reference field formatted as a rendered entity
- ...
There are 2 field formatters provided by `ui_patterns_field_formatters` sub-module:
- **Component per item**: Each item will be displayed as a component.
- **Component**: Available only for multi-valued fields. The full field is displayed as a component.
## In Manage Display
Manage display manages the way your content is displayed on the frontend.
The UI Patterns field formatters are available in the format select list, for every fields,
![](images/formatter-1.webp)
Once selected, the field formatters are configurable as usual field formatters, with the UI Patterns 2's [Component form](3.0-component-form.md)
![](images/formatter-2.webp)
### Contextual data sources
| Context | Source | Prop type | Description |
| --------------- | ------------------- | --------- | ------------------------------------------ |
| Field | Field formatter | Slot |
| Field | Field label | String |
| Field | Field prop: \* | (many) |
| Reference field | Field prop: entity | | Switch to a Content entity context. |
| Content entity | Data from a field | | Switch to a Field context. |
| Content entity | Entity link | URL |
| Content entity | Referenced entities | | Switch to an other Content entity context. |
## In Layout Builder
Drupal's Layout Builder allows content editors and site builders to create visual layouts for displaying content. Users can customize how content is arranged on a single page, across types of content, or even create custom landing pages with an easy to use drag-and-drop interface.
Fields are available as blocks:
![](images/formatter-3.webp)
Once selected, the field formatters are configurable as usual field formatters, with the UI Patterns 2's [Component form](3.0-component-form.md):
![](images/formatter-4.webp)
### Contextual data sources
| Context | Source | Prop type | Description |
| --------------- | ------------------- | --------- | ------------------------------------------ |
| Field | Field formatter | Slot |
| Field | Field label | String |
| Field | Field prop : \* | (many) |
| Reference field | Field prop: entity | | Switch to a Content entity context. |
| Content entity | Data from a field | | Switch to a Field context. |
| Content entity | Entity link | URL |
| Content entity | Referenced entities | | Switch to an other Content entity context. |
## In Views
Drupal Views is both:
- a query builder: fetch content from the database, with filters, sorts and grouping.
- a display builder: present the results as lists, galleries, tables, maps, graphs, reports...
If your display accepts fields, the field formatters are available:
![](images/formatter-5.webp)
Once selected, the field formatters are configurable as usual field formatters, with the UI Patterns 2's [Component form](3.0-component-form.md):
![](images/formatter-6.webp)
### Contextual data sources
| Context | Source | Prop type | Description |
| --------------- | ------------------- | --------- | ------------------------------------------ |
| Field | Field formatter | Slot |
| Field | Field label | String |
| Field | Field prop: \* | (many) |
| Reference field | Field prop: entity | | Switch to a Content entity context. |
| Content entity | Data from a field | | Switch to a Field context. |
| Content entity | Entity link | URL |
| Content entity | Referenced entities | | Switch to an other Content entity context. |
# Using a component with Views
Drupal Views is both:
- a query builder: fetch content from the database, with filters, sorts and grouping.
- a display builder: present the results as lists, galleries, tables, maps, graphs, reports...
You need to activate `ui_patterns_views` sub-module.
## View style plugin
To build the display around the results:
- the table and not the rows
- the slider and not the slides
- the map and not the points of interest
- the mosaic and not the pictures
### Steps
Pick "Component" in the modal:
![](images/views-1.webp)
Select the component and fill the configuration form:
[Component form](3.0-component-form.md)
![](images/views-2.webp)
### Contextual data sources
| Context | Source | Prop type | Description |
| ------- | ---------- | --------- | ----------- |
| View | View title | String |
| View | View rows | Slot |
## View row plugin
To build the display of each result:
- the rows instead of the table
- the sliders instead of the slides
- the point of interests instead of the map
- the pictures instead of the mosaic
Pick "Component" in the modal:
![](images/views-3.webp)
Select the component and fill the configuration form:
![](images/views-4.webp)
### Contextual data sources
| Context | Source | Prop type | Description |
| -------------- | ------------------- | --------- | ------------------------------------------ |
| View row | View title | String |
| View row | View field | Slot |
| Content entity | Data from a field | | Switch to a Field context. |
| Content entity | Entity link | URL |
| Content entity | Referenced entities | | Switch to an other Content entity context. |
# Using a component in Drupal templates
## Presenter templates
Presenter templates are standard Drupal templates that:
- transform data received from Drupal
- use Twig [include()](http://twig.sensiolabs.org/doc/function/include.html) function to include one or more components and pass the transformed data.
- should be totally free of markup
- use [theme suggestions](https://www.drupal.org/docs/8/theming/twig/twig-template-naming-conventions) to plug itself to data model
For example, a “normal” template has markup:
```twig
{% if subtitle %}
<h3 class="callout__subtitle">{{ subtitle }}</h3>
{% endif %}
```
But a presenter template has only a call to a component (and sometimes a bit of logic):
```twig
{{ include('my_theme:menu', {
'items': items,
'attributes': attributes.addClass('bg-primary'),
}, with_context=false)}}
```
Examples of presenter templates can be found on those folders:
- https://git.drupalcode.org/project/ui_suite_bootstrap/-/tree/5.1.x/templates
- https://git.drupalcode.org/project/ui_suite_daisyui/-/tree/4.0.x/templates
- https://git.drupalcode.org/project/ui_suite_dsfr/-/tree/1.1.x/templates
- https://git.drupalcode.org/project/ui_suite_material/-/tree/2.0.x/templates
- https://git.drupalcode.org/project/ui_suite_uswds/-/tree/4.0.x/templates
More about presenter templates:
- https://www.aleksip.net/presenting-component-projects (May 2016)
- https://www.mediacurrent.com/blog/accommodating-drupal-your-components/ (Broken link)
### Don’t use presenter templates when site building is possible
Presenter templates are a clever trick, however they hurt the site building because everything which is normally set in the display settings by the site builder has to be done in a Twig file by the developer.
However, there are some cases when site building is not easily possible. For examples:
- rendering a menu. Menu are config entities without configurable displays.
- rendering a content entity where the configurable display has no admin UI.
🚫 Don't do presenter templates when display building is available:
- Node: `/admin/structure/types/manage/{bundle}/display`
- BlockContent: `/admin/structure/block/block-content/manage/{bundle}/display`
- Comment: `/admin/structure/comment/manage/{bundle}/display`
- Media: `/admin/structure/media/manage/{bundle}/display`
- Taxonomy Term: `/admin/structure/taxonomy/manage/{bundle}/overview/display`
- User: `/admin/config/people/accounts/display`
- Views
✅ Presenter templates are OK for renderables without display building:
- Page layout: `page.html.twig` and `region.html.twig`
- Menu config entity: `menu.html.twig`
- ...
### Slots & props
Most of those templates have distinct variables for data to send to slots or props.
For example, in `node.html.twig`:
- `node` variable has the typed data to send to props
- `content` has the renderable data to send to slots
Other example, in `user.html.twig`:
- `user` variable has the typed data to send to props
- `content` has the renderable data to send to slots
## Clean default templates
Even without doing presenter templates, template overriding can be useful to clean some cruft from templates provided by core or contrib modules.
The node.html.twig template is a good example, because it carries a lot of legacy junk, like a title base field display condition based on view mode name (!) and a poor man submitted by.
It is better to keep those templates as lean as possible, and to push the complexity to layouts and other display modes plugins.
For example:
- `field.html.twig`
- `block.html.twig`
- `node.html.twig`
- `taxonomy-term.html.twig`
- `media.html.twig`
- `comment.html.twig`
- ...
Those templates content can be replaced by:
```twig
{% if attributes.storage() %}
<div{{ attributes }}>
{% endif %}
{{ content }}
{% if attributes.storage() %}
</div>
{% endif %}
```
Or sometimes, by more complex stuff like:
```twig
{% if attributes.storage() %}
<div{{ attributes }}>
{% endif %}
{{ title_prefix }}
{{ title_suffix }}
{{ content }}
{% if attributes.storage() %}
<div{{ content_attributes }}>
{% endif %}
{{ content }}
{% if attributes.storage() %}
</div>
{% endif %}
{% if attributes.storage() %}
</div>
{% endif %}
```
Some markup of components or some utilities style expect specific markup with direct children like flex feature. Currently when trying to use those components in lists the wrappers inside templates like field.html.twig and node.html.twig will interfere with the expected markup. So sometimes even the wrappers need to be removed with templates override.
Use the <a href="https://www.drupal.org/project/entity_vdts" rel="nofollow">Entity View Display Template Suggestions module</a> to be able to remove the wrapper of some entity displays. If the theme provides templates with bare minimum markup like just the "content" variable printed, for content entities with the module you will be able to remove the wrapper with configuration.
docs/1-users/images/block-1.webp

9.97 KiB

docs/1-users/images/block-2.webp

21.6 KiB

docs/1-users/images/block-3.webp

17 KiB

docs/1-users/images/block-4.webp

39.6 KiB

docs/1-users/images/bs-alert-example.webp

34.6 KiB

docs/1-users/images/form-1.webp

9.78 KiB

docs/1-users/images/formatter-1.webp

14.1 KiB

docs/1-users/images/formatter-2.webp

18.8 KiB