Scan complete · 83ms · 210 code files

Design System Diagnosis

telekom/scale · scanned 2026-09-01
Health score
49/100
web components (Stencil)TypeScriptplain CSScustom design system (--telekom-*)monorepoalso present: --scl-*
Summary
69 off-scale spacing values where a dozen would do. 1 typeface declared 14 different ways. 6 colour pairs are nearly identical (#1b1b1b next to #191919), copy-paste, not decisions.
Written by Claude from this scan · 2026-09-01 · not part of the measurement

What the numbers mean

Scale is architecturally sound, and this scan can now say so with the components read: 95 Stencil web components, generated React, Vue and Angular wrappers, and a real composition core where scale-dropdown-select-item, scale-combobox and scale-button do the heavy lifting. The findings below are not quality problems. They are the residue of a token migration that was started and never closed out.

The headline is still the token migration. One font, TeleNeo, is declared 14 different ways across the component source, and the token traffic tells the same story in numbers: roughly 2,000 references answer to the current --telekom-* namespace while around 100 still call --scl-*, whose definitions sit in the in-repo @telekom/scale-design-tokens package that is itself marked deprecated in favour of the separate @telekom/design-tokens. The source of truth moved; about a tenth of the calls have not followed it yet. The 69 off-scale spacing values and the 6 near-identical colour pairs are the same unfinished move wearing different clothes.

Where the specificity fights are. The 27 !important declarations cluster instead of spreading: data-grid carries 8, then tag with 4, switch and tab-header with 3 each. The composite components are where the cascade is being argued with, and those are also the components consumers can least work around.

Three names are defined twice. TelekomNavItem, Logo and Shell each have two implementations. In a system whose whole promise is one canonical answer per question, an agent asked for the nav item has a coin to flip. Small list, cheap fix, outsized signal.

Two colour findings worth separating. #cb0068, the pressed state of Telekom magenta, appears hardcoded rather than derived from the brand token, and it is the one colour the licence specifically ring-fences: the clearest commercial argument for a real token boundary. Separately, the near-identical dark pair #1b1b1b next to #191919 is copy-paste, not a decision.

What is genuinely working. 302 colours sounds alarming and is not: the palette is token-led, greys are disciplined at 24, and there are zero arbitrary bracket values and zero unimported components in the design-system scope. The web component core with generated framework wrappers remains the right call for an organisation with this many product estates.

One gap that grows monthly. No CLAUDE.md, no AGENTS.md. For a design system whose entire job is telling people which component is canonical, every agent-written UI change is currently a guess. The rules file this scan can generate would name the canonical components, the --telekom-* namespace and the duplicates to avoid, in one page.

Where to start

Three tweaks · 49 → 78

01
Unwind the 27 !important declarations
+11
Each one is a selector losing an argument with another selector; data-grid.css alone carries 8. Fix the specificity at the source and they stop being necessary.
paste it into your agent ·
02
Collapse the 6 near-identical colours
+11
#1b1b1b and #191919 are the same colour to any eye, and they are used 8 times between them. Nobody chose to have both. Pick the one that is already a token, point the other at it, and the pair stops multiplying.
paste it into your agent ·
03
Crown the canonical <TelekomNavItem>
+6
3 component names have competing implementations. Start with <TelekomNavItem>: packages/components/src/components/telekom/telekom-nav-item/telekom-nav-item.tsx vs packages/components/src/components/telekom/telekom-nav-flyout/telekom-nav-flyout.tsx. Decide which one is canonical, re-export it from one home, and rename or fold in the other.
paste it into your agent ·

You sat through the roast

so you get a present.

Agent trap. <TelekomNavItem> alone has 2 implementations. An agent asked for one cannot tell which is canonical, so it picks at random or writes another, and every wrong pick becomes the example the next agent copies. This is the finding that multiplies itself.
Agent trap. -1px appears 22 times. An agent looking for how this repo does spacing reads repetition as intent, so it will write occurrence 23. The most copied pattern here is the one you least want copied.
Agent trap. This palette holds 6 pairs of colours a screen can barely tell apart. An agent asked for the brand grey cannot see the difference either, so it copies whichever twin is nearest, and when unsure it invents a third between them. Twins breed triplets.
302
distinct colours
Ideal Design System~24
Avg Design System130
Reputable systems24
24
shades of grey
Ideal Design System~13
Avg Design System17
Reputable systems5
69
off-scale spacing values
Ideal Design System~12
Avg Design System34 · messier than 79%
Reputable systems6
3
duplicated components
Ideal Design System0
Avg Design System20 · cleaner than 71%
Reputable systems12
7
inline style blocks
Ideal Design System0
Avg Design System49 · cleaner than 76%
Reputable systems12
6
near-identical colour pairs
Ideal Design System0
Avg Design System13
Reputable systems1
27
!important declarations
Ideal Design System0
Avg Design System7 · messier than 71%
Reputable systems3
0
components never imported
Ideal Design System0 =
Avg Design System14
Reputable systems0 =
library: internal use only, downstream consumers invisible
0
arbitrary bracket values
Ideal Design System~20
Avg Design System70 · cleaner than 71%
Reputable systems0 =

Package by package

1 package with enough UI to judge · the repo score above is the whole thing blended, and 6 packages were too small or too backend to score

packagescoreworst findingsize
packages/components 60 27 !important declarations 162 files

A repo scores below its own packages by arithmetic, not by accident: distinct values add up across packages, so the whole always carries more than any part. Read the package scores for where each team stands, and the repo score for what your agent sees when it looks at everything at once.

What your AI agent sees today

No CLAUDE.md, no AGENTS.md, no .cursorrules. Every time your AI builds UI here, it guesses, from everything below. This is why its output looks almost-but-not-quite right.

Palette
302colours

A healthy product palette is up to ~24 colours: one brand hue with a few tints, one accent, up to 13 greys, and status colours.

297 tokens5 strays
Colour usage
Sized by how often each is used
token stray
+242
Grey ramp · sorted dark → light · how many can you tell apart?
6 nearly identical pairs · copy-paste, not decisions
#1b1b1b ×4 #191919 ×4#eeeeee ×2 #f2f2f2 ×2#eeeeee ×2 #e9ecf6 ×2#eeeeee ×2 #ecf3e7 ×2#eeeeee ×2 #ededed ×1#eeeeee ×2 #f4f4f4 ×1

69 off-scale spacing values

a disciplined repo keeps these around a dozen · on-scale Tailwind steps (·) shown for context · off-scale in coral

-1px
22
0px
21
12px
16
8px
14
1px
14
2em
11
-2px
9
4px
9
1rem
8
-10px
8
48px
8
-4px
7
6px
7
5px
7
10px
7
1.5em
7
17px
6
1em
6

Typography & shape

1
typefaces
Ideal Design System~3
Avg Design System3 · cleaner than 71%
Reputable systems1 =
52
font sizes
Ideal Design System~10
Avg Design System20 · messier than 94%
Reputable systems6
48
border radii
Ideal Design System~10
Avg Design System13 · messier than 97%
Reputable systems2
34
shadow styles
Ideal Design System~6
Avg Design System2 · messier than 94%
Reputable systems1
the type scale, at its real sizes · how many of these are the same decision?
1rem ×2 Almost but not quite
16px ×1 Almost but not quite
12px ×1 Almost but not quite
0.75rem ×1 Almost but not quite
the corners, drawn · 48 radii in one interface
50% ×7
20% ×3
2px ×2
100% ×1
1rem ×1
3px ×1
0 0 3px 3px ×1

1 typeface, declared 14 different ways

every distinct declaration is a chance for the next one to be wrong

'TeleNeoWeb'×24
'TeleNeoWeb', sans-serif×2
var(--scl-font-variant-body-family, TeleNeoWeb, sans-serif)×1
var( --scl-font-variant-body-short-family, TeleNeoWeb, sans-serif )×1
var( --scl-font-variant-body-large-family, TeleNeoWeb, sans-serif )×1
var(--scl-font-variant-smaller-family, TeleNeoWeb, sans-serif)×1
var(--scl-font-variant-label-family, TeleNeoWeb, sans-serif)×1
var(--scl-font-variant-caption-family, TeleNeoWeb, sans-serif)×1

Where it hurts most

the 5 files carrying the most off-system styling

Duplicated components

an agent asking which one is canonical gets several plausible answers. Paths open in VS Code

footer family · 6 variants
<TelekomFooter>
packages/components/src/components/telekom/telekom-footer/telekom-footer.tsx
used 1×
<TelekomFooterContent>
packages/components/src/components/telekom/telekom-footer/telekom-footer-content.tsx
used 1×
<AppFooter>
packages/components/src/components/telekom/app-footer/app-footer.tsx
<TelekomFooterDataBackCompat>
packages/components/src/components/telekom/telekom-footer-data-back-compat/telekom-footer-data-back-compat.tsx
<TelekomFooterExtendedNavigation>
packages/components/src/components/telekom/telekom-footer-extended-navigation/telekom-footer-extended-navigation.tsx
<TelekomFooterExtendedNavigationColumn>
packages/components/src/components/telekom/telekom-footer-extended-navigation/telekom-footer-extended-navigation-column.tsx
button family · 5 variants
<Button>
packages/components/src/components/button/button.tsx
used 10×
<RadioButton>
packages/components/src/components/radio-button/radio-button.tsx
used 1×
<RadioButtonGroup>
packages/components/src/components/radio-button-group/radio-button-group.tsx
<SegmentedButton>
packages/components/src/components/segmented-button/segmented-button.tsx
<ToggleButton>
packages/components/src/components/toggle-button/toggle-button.tsx
toast family · 5 variants
<Toast>
packages/components/src/components/toast/toast.tsx
used 1×
<Notification>
packages/components/src/components/notification/notification.tsx
<NotificationBanner>
packages/components/src/components/notification-banner/notification-banner.tsx
<NotificationMessage>
packages/components/src/components/notification-message/notification-message.tsx
<NotificationToast>
packages/components/src/components/notification-toast/notification-toast.tsx
list family · 4 variants
<MenuFlyoutList>
packages/components/src/components/menu-flyout-list/menu-flyout-list.tsx
used 6×
<TelekomNavList>
packages/components/src/components/telekom/telekom-nav-list/telekom-nav-list.tsx
used 6×
<List>
packages/components/src/components/list/list.tsx
used 1×
<ListItem>
packages/components/src/components/list-item/list-item.tsx
used 1×
header family · 4 variants
<TabHeader>
packages/components/src/components/tab-header/tab-header.tsx
used 2×
<Header>
packages/components/src/components/telekom/app-header/app-header.tsx
used 1×
<TelekomHeader>
packages/components/src/components/telekom/telekom-header/telekom-header.tsx
used 1×
<TelekomHeaderDataBackCompat>
packages/components/src/components/telekom/telekom-header-data-back-compat/telekom-header-data-back-compat.tsx
select family · 2 variants
<DropdownSelectItem>
packages/components/src/components/dropdown-select-item/dropdown-select-item.tsx
used 21×
<DropdownSelect>
packages/components/src/components/dropdown-select/dropdown-select.tsx
used 5×

The composition map

95 components defined · tile area is internal use: how the system builds from itself, downstream consumers invisible from here · the real system, drawn to scale

<DropdownSelectItem> · used 21× · packages/components/src/components/dropdown-select-item/dropdown-select-item.tsx DropdownSelectItem 21× <Combobox> · used 15× · packages/components/src/components/combobox/combobox.tsx Combobox 15× <Tag> · used 11× · packages/components/src/components/tag/tag.tsx Tag 11× <TelekomNavItem> · used 11× · packages/components/src/components/telekom/telekom-nav-item/telekom-nav-item.tsx TelekomNavItem 11× <Button> · used 10× · packages/components/src/components/button/button.tsx Button 10× <Link> · used 10× · packages/components/src/components/link/link.tsx Link 10× <HelperText> · used 9× · packages/components/src/components/helper-text/helper-text.tsx HelperText <AppNavigationUserMenu> · used 8× · packages/components/src/components/telekom/app-navigation-user-menu/app-navigation-user-menu.tsx AppNavigationUserMenu <Checkbox> · used 8× · packages/components/src/components/checkbox/checkbox.tsx Checkbox <Breadcrumb> · used 6× · packages/components/src/components/breadcrumb/breadcrumb.tsx Breadcrumb <Icon> · used 6× · packages/components/src/components/icon/icon.tsx Icon <Logo> · used 6× · packages/components/src/components/telekom/logo/logo.tsx Logo <MenuFlyoutList> · used 6× · packages/components/src/components/menu-flyout-list/menu-flyout-list.tsx MenuFlyoutList <TelekomNavList> · used 6× · packages/components/src/components/telekom/telekom-nav-list/telekom-nav-list.tsx TelekomNavList <Badge> · used 5× · packages/components/src/components/badge/badge.tsx Badge <DropdownSelect> · used 5× · packages/components/src/components/dropdown-select/dropdown-select.tsx DropdownSelect <MenuFlyoutItem> · used 5× · packages/components/src/components/menu-flyout-item/menu-flyout-item.tsx MenuFlyoutItem <MenuFlyout> · used 4× · packages/components/src/components/menu-flyout/menu-flyout.tsx MenuFlyout <NavIcon> · used 4× · packages/components/src/components/telekom/nav-icon/nav-icon.tsx NavIcon <TelekomNavItem> · used 4× · packages/components/src/components/telekom/telekom-nav-flyout/telekom-nav-flyout.tsx TelekomNavIt… <ProgressBar> · used 3× · packages/components/src/components/progress-bar/progress-bar.tsx ProgressBar <SidebarNav> · used 3× · packages/components/src/components/sidebar-nav/sidebar-nav.tsx SidebarNav <TelekomMobileFlyoutCanvas> · used 3× · packages/components/src/components/telekom/telekom-mobile-flyout-canvas/telekom-mobile-flyout-canvas.tsx TelekomMobileFly… <TelekomMobileMenuItem> · used 3× · packages/components/src/components/telekom/telekom-mobile-menu-item/telekom-mobile-menu-item.tsx TelekomMobileMen…

9 more adopted components below the top 24, not drawn.

30 components are imported exactly once: <Accordion>, <Carousel>, <ChartStackCard>, <Collapsible>, <Divider>, <Dropdown> and 24 more. Quiet corners, not yet a system.

componentuseddefined inprops
<DropdownSelectItem> 21× packages/components/src/components/dropdown-select-item/dropdown-select-item.tsx none
<Combobox> 15× packages/components/src/components/combobox/combobox.tsx none
<Tag> 11× packages/components/src/components/tag/tag.tsx none
<TelekomNavItem> 11× packages/components/src/components/telekom/telekom-nav-item/telekom-nav-item.tsx none
<Button> 10× packages/components/src/components/button/button.tsx none
<Link> 10× packages/components/src/components/link/link.tsx none
<HelperText> packages/components/src/components/helper-text/helper-text.tsx none
<AppNavigationUserMenu> packages/components/src/components/telekom/app-navigation-user-menu/app-navigation-user-menu.tsx none
<Checkbox> packages/components/src/components/checkbox/checkbox.tsx none
<Breadcrumb> packages/components/src/components/breadcrumb/breadcrumb.tsx none