From 787f9693dbb421dbae8985877cd5133b17f6dc37 Mon Sep 17 00:00:00 2001 From: Bartosz-Do Date: Thu, 10 Sep 2026 00:31:13 +0200 Subject: [PATCH] Add per-directory `_index.scss` barrels for `core/scss` (#3021) Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: codecalm <1282324+codecalm@users.noreply.github.com> --- .agents/skills/core-scss/SKILL.md | 6 +- .changeset/scss-directory-barrels.md | 5 + core/scss/_core.scss | 113 ++----------------- core/scss/bootstrap/_index.scss | 31 ++++++ core/scss/helpers/_helpers.scss | 153 ++++++++++++++++++++++++++ core/scss/helpers/_index.scss | 156 +-------------------------- core/scss/layout/_index.scss | 11 ++ core/scss/marketing/_index.scss | 8 ++ core/scss/tabler-marketing.scss | 8 +- core/scss/tabler-vendors.scss | 16 +-- core/scss/ui/_index.scss | 67 ++++++++++++ core/scss/utils/_index.scss | 9 ++ core/scss/vendor/_index.scss | 16 +++ 13 files changed, 317 insertions(+), 282 deletions(-) create mode 100644 .changeset/scss-directory-barrels.md create mode 100644 core/scss/bootstrap/_index.scss create mode 100644 core/scss/helpers/_helpers.scss create mode 100644 core/scss/layout/_index.scss create mode 100644 core/scss/marketing/_index.scss create mode 100644 core/scss/ui/_index.scss create mode 100644 core/scss/utils/_index.scss create mode 100644 core/scss/vendor/_index.scss diff --git a/.agents/skills/core-scss/SKILL.md b/.agents/skills/core-scss/SKILL.md index 8882d8fcd..eee0918da 100644 --- a/.agents/skills/core-scss/SKILL.md +++ b/.agents/skills/core-scss/SKILL.md @@ -26,7 +26,9 @@ description: >- | `vendor/` | overrides for third-party plugin CSS | | `tests/` | sass-true unit tests (see section 7) | -Entry points: `tabler.scss` (which forwards `_core.scss`, then `_extends.scss` last), plus the standalone bundles `tabler-flags`, `tabler-marketing`, `tabler-payments`, `tabler-props`, `tabler-socials`, `tabler-themes`, `tabler-vendors`. A new partial is not compiled until it is `@forward`ed from `_core.scss` (or the bundle it belongs to). +Entry points: `tabler.scss` (which forwards `_core.scss`, then `_extends.scss` last), plus the standalone bundles `tabler-flags`, `tabler-marketing`, `tabler-payments`, `tabler-props`, `tabler-socials`, `tabler-themes`, `tabler-vendors`. + +Each directory has a forward-only `_index.scss` barrel (`bootstrap/`, `layout/`, `ui/`, `utils/`, `helpers/`, `marketing/`, `vendor/`). `_core.scss` forwards the barrels, not individual partials. A new partial is not compiled until it is `@forward`ed from its directory's `_index.scss` (or, for a barrel-less path like `fonts/webfonts`, directly from `_core.scss` or the bundle it belongs to). Add the `@forward` in the position the load order requires — ordering constraints between partials are noted as comments in the barrels (`bootstrap/root` before `props`, `layout/dark` after `layout/root`, `ui/steps` before `ui/type`, `extends` last). `helpers/`'s rules live in `helpers/_helpers.scss`; its `_index.scss` only forwards that. The module graph uses `@use` / `@forward`: a partial starts with `@use '../config' as *`, which is the hub forwarding `settings`, `variables`, `variables-dark`, `maps`, `mixins` and `utilities`. Cross-module `@extend` rules must stay in `_extends.scss`, which loads last. @@ -149,7 +151,7 @@ pnpm run bundlewatch # size budgets (tabler.css 80 kB, tab ## 9. Checklist -- [ ] Partial in the right directory and `@forward`ed from `_core.scss` or its bundle +- [ ] Partial in the right directory and `@forward`ed from that directory's `_index.scss` barrel (or `_core.scss` / its bundle for a barrel-less path) - [ ] Themeable values as custom properties at the top of the root rule, seeded from `!default` Sass variables - [ ] Custom properties written bare; new foreign names added to `cssVarIgnore` - [ ] Dark mode via `light-dark()` or all three dark selectors, behind `$enable-dark-mode` diff --git a/.changeset/scss-directory-barrels.md b/.changeset/scss-directory-barrels.md new file mode 100644 index 000000000..bfb3967d7 --- /dev/null +++ b/.changeset/scss-directory-barrels.md @@ -0,0 +1,5 @@ +--- +"@tabler/core": patch +--- + +Added per-directory `_index.scss` barrels and routed `_core.scss`, `tabler-marketing` and `tabler-vendors` through them. diff --git a/core/scss/_core.scss b/core/scss/_core.scss index ca30366c8..0410c2e13 100644 --- a/core/scss/_core.scss +++ b/core/scss/_core.scss @@ -1,115 +1,18 @@ @forward 'config'; -// Bootstrap components — managed by Tabler (see core/scss/bootstrap/) -@forward 'bootstrap/root'; -@forward 'bootstrap/reboot'; -@forward 'bootstrap/type'; -@forward 'bootstrap/images'; -@forward 'bootstrap/containers'; -@forward 'bootstrap/grid'; -@forward 'bootstrap/tables'; -@forward 'bootstrap/forms'; -@forward 'bootstrap/buttons'; -@forward 'bootstrap/transitions'; -@forward 'bootstrap/dropdown'; -@forward 'bootstrap/button-group'; -@forward 'bootstrap/nav'; -@forward 'bootstrap/navbar'; -@forward 'bootstrap/card'; -@forward 'bootstrap/pagination'; -@forward 'bootstrap/progress'; -@forward 'bootstrap/list-group'; -@forward 'bootstrap/toasts'; -@forward 'bootstrap/modal'; -@forward 'bootstrap/tooltip'; -@forward 'bootstrap/popover'; -@forward 'bootstrap/carousel'; -@forward 'bootstrap/spinners'; -@forward 'bootstrap/offcanvas'; -@forward 'bootstrap/placeholders'; -@forward 'bootstrap/utilities/api'; +// Bootstrap components — managed by Tabler (see core/scss/bootstrap/). +// `bootstrap/root` (first in the barrel) must precede `props`: `_props.scss` +// re-declares `--border-radius-*` on `:root, :host` and wins by source order. +@forward 'bootstrap'; @forward 'props'; @forward 'fonts/webfonts'; -@forward 'layout/root'; -@forward 'layout/animations'; -@forward 'layout/core'; -@forward 'layout/navbar'; -@forward 'layout/page'; -@forward 'layout/footer'; -@forward 'layout/dark'; -@forward 'layout/accessibility'; +@forward 'layout'; -@forward 'ui/accordion'; -@forward 'ui/alerts'; -@forward 'ui/avatars'; -@forward 'ui/badges'; -@forward 'ui/breadcrumbs'; -@forward 'ui/buttons'; -@forward 'ui/button-group'; -@forward 'ui/calendars'; -@forward 'ui/datepicker'; -@forward 'ui/carousel'; -@forward 'ui/cards'; -@forward 'ui/close'; -@forward 'ui/dropdowns'; -@forward 'ui/datagrid'; -@forward 'ui/empty'; -@forward 'ui/grid'; -@forward 'ui/icons'; -@forward 'ui/images'; -@forward 'ui/forms'; -@forward 'ui/forms/form-icon'; -@forward 'ui/forms/form-colorinput'; -@forward 'ui/forms/form-imagecheck'; -@forward 'ui/forms/form-selectgroup'; -@forward 'ui/forms/form-custom'; -@forward 'ui/forms/form-check'; -@forward 'ui/forms/form-otp'; -@forward 'ui/forms/validation'; -@forward 'ui/forms/strength'; -@forward 'ui/legend'; -@forward 'ui/lists'; -@forward 'ui/loaders'; -@forward 'ui/login'; -@forward 'ui/modals'; -@forward 'ui/nav'; -@forward 'ui/stars'; -@forward 'ui/pagination'; -@forward 'ui/popovers'; -@forward 'ui/progress'; -@forward 'ui/ribbons'; -@forward 'ui/markdown'; -@forward 'ui/placeholder'; -@forward 'ui/segmented'; -@forward 'ui/signal'; -@forward 'ui/steps'; -@forward 'ui/status'; -@forward 'ui/switch-icon'; -@forward 'ui/tables'; -@forward 'ui/tags'; -@forward 'ui/toasts'; -@forward 'ui/toolbar'; -@forward 'ui/tracking'; -@forward 'ui/timeline'; -@forward 'ui/type'; -@forward 'ui/charts'; -@forward 'ui/sparkline'; -@forward 'ui/offcanvas'; -@forward 'ui/chat'; -@forward 'ui/signature'; -@forward 'ui/patterns'; -@forward 'ui/sortable'; +@forward 'ui'; -@forward 'helpers/index'; +@forward 'helpers'; -@forward 'utils/background'; -@forward 'utils/colors'; -@forward 'utils/scroll'; -@forward 'utils/sizing'; -@forward 'utils/opacity'; -@forward 'utils/shadow'; -@forward 'utils/text'; -@forward 'utils/hover'; +@forward 'utils'; diff --git a/core/scss/bootstrap/_index.scss b/core/scss/bootstrap/_index.scss new file mode 100644 index 000000000..36671969e --- /dev/null +++ b/core/scss/bootstrap/_index.scss @@ -0,0 +1,31 @@ +// Barrel for Tabler's managed copies of Bootstrap's own partials. +// Forward-only, in load order. `root` must stay first: `_props.scss` +// re-declares `--border-radius-*` on `:root, :host` after this barrel and +// wins by source order. +@forward 'root'; +@forward 'reboot'; +@forward 'type'; +@forward 'images'; +@forward 'containers'; +@forward 'grid'; +@forward 'tables'; +@forward 'forms'; +@forward 'buttons'; +@forward 'transitions'; +@forward 'dropdown'; +@forward 'button-group'; +@forward 'nav'; +@forward 'navbar'; +@forward 'card'; +@forward 'pagination'; +@forward 'progress'; +@forward 'list-group'; +@forward 'toasts'; +@forward 'modal'; +@forward 'tooltip'; +@forward 'popover'; +@forward 'carousel'; +@forward 'spinners'; +@forward 'offcanvas'; +@forward 'placeholders'; +@forward 'utilities/api'; diff --git a/core/scss/helpers/_helpers.scss b/core/scss/helpers/_helpers.scss new file mode 100644 index 000000000..9331268ac --- /dev/null +++ b/core/scss/helpers/_helpers.scss @@ -0,0 +1,153 @@ +@use 'sass:map'; + +// +// Clearfix +// +@use '../config' as *; + +.clearfix { + @include clearfix(); +} + +// +// Text truncation +// +.text-truncate { + @include text-truncate(); +} + +// +// Vertical rule +// +.vr { + display: inline-block; + align-self: stretch; + width: $vr-border-width; + min-height: 1em; + background-color: currentColor; + opacity: $hr-opacity; +} + +// +// Stretched link +// +.stretched-link { + &::after { + position: absolute; + inset-inline-start: 0; + inset-inline-end: 0; + top: 0; + bottom: 0; + z-index: 1; + content: ''; + } + + // .btn is positioned, which would make the button itself the containing block + &.btn { + position: static; + } +} + +// +// Visually hidden +// +.visually-hidden, +.visually-hidden-focusable:not(:focus):not(:focus-within) { + @include visually-hidden(); +} + +// +// Stacks +// +.hstack { + display: flex; + flex-direction: row; + align-items: center; + align-self: stretch; +} + +.vstack { + display: flex; + flex: 1 1 auto; + flex-direction: column; + align-self: stretch; +} + +// +// Position +// +// Shorthand + +.fixed-top { + position: fixed; + inset-inline-start: 0; + inset-inline-end: 0; + top: 0; + z-index: $zindex-fixed; +} + +.fixed-bottom { + position: fixed; + inset-inline-start: 0; + inset-inline-end: 0; + bottom: 0; + z-index: $zindex-fixed; +} + +// Responsive sticky top and bottom +@each $breakpoint in map.keys($grid-breakpoints) { + @include media-breakpoint-up($breakpoint) { + $infix: breakpoint-infix($breakpoint, $grid-breakpoints); + + .sticky#{$infix}-top { + position: sticky; + top: 0; + z-index: $zindex-sticky; + } + + .sticky#{$infix}-bottom { + position: sticky; + bottom: 0; + z-index: $zindex-sticky; + } + } +} + +// +// Aspect ratio +// +.ratio { + position: relative; + width: 100%; + + &::before { + display: block; + padding-top: var(--aspect-ratio); + content: ''; + } + + > * { + position: absolute; + inset-inline-start: 0; + top: 0; + width: 100%; + height: 100%; + } +} + +@each $key, $ratio in $aspect-ratios { + .ratio-#{$key} { + --aspect-ratio: #{$ratio}; + } +} + +// +// Focus ring +// +.focus-ring { + @include focus-ring-transition(); +} + +.focus-ring:focus-visible { + @include focus-ring($color: var(--focus-ring-color)); +} diff --git a/core/scss/helpers/_index.scss b/core/scss/helpers/_index.scss index 9331268ac..4a6a52370 100644 --- a/core/scss/helpers/_index.scss +++ b/core/scss/helpers/_index.scss @@ -1,153 +1,3 @@ -@use 'sass:map'; - -// -// Clearfix -// -@use '../config' as *; - -.clearfix { - @include clearfix(); -} - -// -// Text truncation -// -.text-truncate { - @include text-truncate(); -} - -// -// Vertical rule -// -.vr { - display: inline-block; - align-self: stretch; - width: $vr-border-width; - min-height: 1em; - background-color: currentColor; - opacity: $hr-opacity; -} - -// -// Stretched link -// -.stretched-link { - &::after { - position: absolute; - inset-inline-start: 0; - inset-inline-end: 0; - top: 0; - bottom: 0; - z-index: 1; - content: ''; - } - - // .btn is positioned, which would make the button itself the containing block - &.btn { - position: static; - } -} - -// -// Visually hidden -// -.visually-hidden, -.visually-hidden-focusable:not(:focus):not(:focus-within) { - @include visually-hidden(); -} - -// -// Stacks -// -.hstack { - display: flex; - flex-direction: row; - align-items: center; - align-self: stretch; -} - -.vstack { - display: flex; - flex: 1 1 auto; - flex-direction: column; - align-self: stretch; -} - -// -// Position -// -// Shorthand - -.fixed-top { - position: fixed; - inset-inline-start: 0; - inset-inline-end: 0; - top: 0; - z-index: $zindex-fixed; -} - -.fixed-bottom { - position: fixed; - inset-inline-start: 0; - inset-inline-end: 0; - bottom: 0; - z-index: $zindex-fixed; -} - -// Responsive sticky top and bottom -@each $breakpoint in map.keys($grid-breakpoints) { - @include media-breakpoint-up($breakpoint) { - $infix: breakpoint-infix($breakpoint, $grid-breakpoints); - - .sticky#{$infix}-top { - position: sticky; - top: 0; - z-index: $zindex-sticky; - } - - .sticky#{$infix}-bottom { - position: sticky; - bottom: 0; - z-index: $zindex-sticky; - } - } -} - -// -// Aspect ratio -// -.ratio { - position: relative; - width: 100%; - - &::before { - display: block; - padding-top: var(--aspect-ratio); - content: ''; - } - - > * { - position: absolute; - inset-inline-start: 0; - top: 0; - width: 100%; - height: 100%; - } -} - -@each $key, $ratio in $aspect-ratios { - .ratio-#{$key} { - --aspect-ratio: #{$ratio}; - } -} - -// -// Focus ring -// -.focus-ring { - @include focus-ring-transition(); -} - -.focus-ring:focus-visible { - @include focus-ring($color: var(--focus-ring-color)); -} +// Barrel for the helper classes. The rules live in `_helpers.scss`; this +// keeps `helpers/` consistent with every other directory's `_index.scss`. +@forward 'helpers'; diff --git a/core/scss/layout/_index.scss b/core/scss/layout/_index.scss new file mode 100644 index 000000000..39c68869d --- /dev/null +++ b/core/scss/layout/_index.scss @@ -0,0 +1,11 @@ +// Barrel for the page-chrome layer. Forward-only, in load order. +// `dark` must stay after `root`: it flips `color-scheme` to dark at equal +// specificity and relies on later source order (see `layout/_dark.scss`). +@forward 'root'; +@forward 'animations'; +@forward 'core'; +@forward 'navbar'; +@forward 'page'; +@forward 'footer'; +@forward 'dark'; +@forward 'accessibility'; diff --git a/core/scss/marketing/_index.scss b/core/scss/marketing/_index.scss new file mode 100644 index 000000000..2a821e0b5 --- /dev/null +++ b/core/scss/marketing/_index.scss @@ -0,0 +1,8 @@ +// Barrel for the marketing bundle. Forward-only, in load order. +@forward 'core'; +@forward 'hero'; +@forward 'browser'; +@forward 'sections'; +@forward 'filters'; +@forward 'pricing'; +@forward 'shape'; diff --git a/core/scss/tabler-marketing.scss b/core/scss/tabler-marketing.scss index 798a6d041..c0582ebde 100644 --- a/core/scss/tabler-marketing.scss +++ b/core/scss/tabler-marketing.scss @@ -1,12 +1,6 @@ @forward 'config'; -@forward 'marketing/core'; -@forward 'marketing/hero'; -@forward 'marketing/browser'; -@forward 'marketing/sections'; -@forward 'marketing/filters'; -@forward 'marketing/pricing'; -@forward 'marketing/shape'; +@forward 'marketing'; // This bundle uses its own utilities map instead of the global one, so the // utilities API is emitted via the parameterized mixin (last, as before). diff --git a/core/scss/tabler-vendors.scss b/core/scss/tabler-vendors.scss index cce656e31..9afd2656d 100644 --- a/core/scss/tabler-vendors.scss +++ b/core/scss/tabler-vendors.scss @@ -1,17 +1,3 @@ @forward 'config'; -@forward 'vendor/nouislider'; -@forward 'vendor/tom-select'; -@forward 'vendor/apexcharts'; -@forward 'vendor/jsvectormap'; -@forward 'vendor/dropzone'; -@forward 'vendor/fslightbox'; -@forward 'vendor/plyr'; -@forward 'vendor/wysiwyg'; -@forward 'vendor/stars-rating'; -@forward 'vendor/coloris'; -@forward 'vendor/typed'; -@forward 'vendor/fullcalendar'; -// deprecated(2.0): Litepicker is replaced by the Datepicker plugin; its styles -// stay for projects that still load it. -@forward 'vendor/litepicker'; +@forward 'vendor'; diff --git a/core/scss/ui/_index.scss b/core/scss/ui/_index.scss new file mode 100644 index 000000000..694f7af1b --- /dev/null +++ b/core/scss/ui/_index.scss @@ -0,0 +1,67 @@ +// Barrel for the component layer. Forward-only, in load order. +// `steps` must stay before `type`: `ui/_type.scss` narrows the shared +// `.steps` selector and depends on being loaded after the component (see +// `ui/_type.scss`). +// `ui/_chips.scss` is intentionally not forwarded — nothing forwards it +// today and adding it would emit new CSS. It is picked up by the component +// parity work (phase 9). +@forward 'accordion'; +@forward 'alerts'; +@forward 'avatars'; +@forward 'badges'; +@forward 'breadcrumbs'; +@forward 'buttons'; +@forward 'button-group'; +@forward 'calendars'; +@forward 'datepicker'; +@forward 'carousel'; +@forward 'cards'; +@forward 'close'; +@forward 'dropdowns'; +@forward 'datagrid'; +@forward 'empty'; +@forward 'grid'; +@forward 'icons'; +@forward 'images'; +@forward 'forms'; +@forward 'forms/form-icon'; +@forward 'forms/form-colorinput'; +@forward 'forms/form-imagecheck'; +@forward 'forms/form-selectgroup'; +@forward 'forms/form-custom'; +@forward 'forms/form-check'; +@forward 'forms/form-otp'; +@forward 'forms/validation'; +@forward 'forms/strength'; +@forward 'legend'; +@forward 'lists'; +@forward 'loaders'; +@forward 'login'; +@forward 'modals'; +@forward 'nav'; +@forward 'stars'; +@forward 'pagination'; +@forward 'popovers'; +@forward 'progress'; +@forward 'ribbons'; +@forward 'markdown'; +@forward 'placeholder'; +@forward 'segmented'; +@forward 'signal'; +@forward 'steps'; +@forward 'status'; +@forward 'switch-icon'; +@forward 'tables'; +@forward 'tags'; +@forward 'toasts'; +@forward 'toolbar'; +@forward 'tracking'; +@forward 'timeline'; +@forward 'type'; +@forward 'charts'; +@forward 'sparkline'; +@forward 'offcanvas'; +@forward 'chat'; +@forward 'signature'; +@forward 'patterns'; +@forward 'sortable'; diff --git a/core/scss/utils/_index.scss b/core/scss/utils/_index.scss new file mode 100644 index 000000000..2ca2d4f48 --- /dev/null +++ b/core/scss/utils/_index.scss @@ -0,0 +1,9 @@ +// Barrel for the utility-class layer. Forward-only, in load order. +@forward 'background'; +@forward 'colors'; +@forward 'scroll'; +@forward 'sizing'; +@forward 'opacity'; +@forward 'shadow'; +@forward 'text'; +@forward 'hover'; diff --git a/core/scss/vendor/_index.scss b/core/scss/vendor/_index.scss new file mode 100644 index 000000000..8dae1a8df --- /dev/null +++ b/core/scss/vendor/_index.scss @@ -0,0 +1,16 @@ +// Barrel for the third-party plugin overrides bundle. Forward-only, in load order. +@forward 'nouislider'; +@forward 'tom-select'; +@forward 'apexcharts'; +@forward 'jsvectormap'; +@forward 'dropzone'; +@forward 'fslightbox'; +@forward 'plyr'; +@forward 'wysiwyg'; +@forward 'stars-rating'; +@forward 'coloris'; +@forward 'typed'; +@forward 'fullcalendar'; +// deprecated(2.0): Litepicker is replaced by the Datepicker plugin; its styles +// stay for projects that still load it. +@forward 'litepicker';