@ids-group-ltd/ids-design-system 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@ids-group-ltd/ids-design-system",
3
+ "version": "0.1.0",
4
+ "description": "IDS Group Angular design system: components, tokens, themes",
5
+ "license": "UNLICENSED",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://bitbucket.org/itband/ids-design-system.git"
9
+ },
10
+ "keywords": [
11
+ "angular",
12
+ "design-system",
13
+ "components",
14
+ "ui",
15
+ "ids-group"
16
+ ],
17
+ "publishConfig": {
18
+ "access": "public"
19
+ },
20
+ "exports": {
21
+ "./styles/*": "./styles/*",
22
+ "./themes/*": "./themes/*",
23
+ "./package.json": {
24
+ "default": "./package.json"
25
+ },
26
+ ".": {
27
+ "types": "./types/ids-group-ltd-ids-design-system.d.ts",
28
+ "default": "./fesm2022/ids-group-ltd-ids-design-system.mjs"
29
+ }
30
+ },
31
+ "peerDependencies": {
32
+ "@angular/cdk": "^21.2.0",
33
+ "@angular/common": "^21.2.0",
34
+ "@angular/core": "^21.2.0",
35
+ "@angular/forms": "^21.2.0",
36
+ "@angular/platform-browser": "^21.2.0",
37
+ "@angular/router": "^21.2.0"
38
+ },
39
+ "dependencies": {
40
+ "tslib": "^2.3.0"
41
+ },
42
+ "sideEffects": false,
43
+ "module": "fesm2022/ids-group-ltd-ids-design-system.mjs",
44
+ "typings": "types/ids-group-ltd-ids-design-system.d.ts",
45
+ "type": "module"
46
+ }
@@ -0,0 +1,117 @@
1
+ // Dropdown panel styles — GLOBAL because the panel is portaled via CDK
2
+ // Overlay outside the host component's DOM tree, so emulated encapsulation
3
+ // (and any `:host ::ng-deep` selectors) cannot reach it. The component sets
4
+ // `panelClass: 'ds-dropdown-panel'` on the overlay config; this partial
5
+ // declares the matching rules so the portaled panel renders styled.
6
+
7
+ .ds-dropdown-panel {
8
+ .dropdown-panel {
9
+ // Fill the cdk-overlay-pane width (set from trigger.getBoundingClientRect()
10
+ // in dropdown.component.ts). Without `width: 100%` the panel is a flex
11
+ // child of the pane and shrinks to its own option content width.
12
+ width: 100%;
13
+ background: var(--surface-overlay);
14
+ border: var(--border-width-default) solid var(--border-default);
15
+ border-radius: var(--radius-md);
16
+ box-shadow: var(--shadow-popover);
17
+ padding: var(--space-1);
18
+ max-height: 320px;
19
+ overflow-y: auto;
20
+ z-index: var(--layer-popover);
21
+ }
22
+
23
+ .dropdown-list {
24
+ list-style: none;
25
+ margin: 0;
26
+ padding: 0;
27
+ display: flex;
28
+ flex-direction: column;
29
+ gap: 2px;
30
+ }
31
+
32
+ .optgroup {
33
+ list-style: none;
34
+ display: flex;
35
+ flex-direction: column;
36
+ gap: 2px;
37
+ }
38
+
39
+ .optgroup-label {
40
+ display: block;
41
+ padding: var(--space-2) var(--space-3) var(--space-1);
42
+ font: var(--font-weight-semibold) var(--font-size-xs)/var(--line-height-flat) var(--font-sans);
43
+ color: var(--text-tertiary);
44
+ text-transform: uppercase;
45
+ letter-spacing: var(--letter-spacing-wide);
46
+
47
+ // First group sits flush against the panel padding — no extra top space.
48
+ &.is-first {
49
+ padding-top: var(--space-1);
50
+ }
51
+ }
52
+
53
+ .optgroup-list {
54
+ list-style: none;
55
+ margin: 0;
56
+ padding: 0;
57
+ display: flex;
58
+ flex-direction: column;
59
+ gap: 2px;
60
+ }
61
+
62
+ .option {
63
+ display: flex;
64
+ align-items: center;
65
+ gap: var(--space-2);
66
+ width: 100%;
67
+ padding: var(--space-2) var(--space-2-5);
68
+ border: 0;
69
+ background: transparent;
70
+ font: var(--font-weight-medium) var(--font-size-s)/var(--line-height-flat) var(--font-sans);
71
+ color: var(--text-primary);
72
+ cursor: pointer;
73
+ border-radius: var(--radius-sm);
74
+ text-align: left;
75
+
76
+ .option-icon {
77
+ color: var(--icon-default);
78
+ flex: 0 0 auto;
79
+ }
80
+
81
+ .option-label {
82
+ flex: 1;
83
+ min-width: 0;
84
+ overflow: hidden;
85
+ text-overflow: ellipsis;
86
+ white-space: nowrap;
87
+ }
88
+
89
+ .option-check {
90
+ color: var(--primary);
91
+ flex: 0 0 auto;
92
+ }
93
+
94
+ &:hover:not(.is-disabled),
95
+ &.is-active:not(.is-disabled) {
96
+ background: var(--surface-secondary);
97
+ }
98
+
99
+ &:focus-visible {
100
+ outline: none;
101
+ box-shadow: var(--focus-ring);
102
+ }
103
+
104
+ &.is-selected {
105
+ background: var(--primary-subtle);
106
+ color: var(--primary-strong);
107
+
108
+ .option-icon { color: var(--primary-strong); }
109
+ }
110
+
111
+ &.is-disabled {
112
+ color: var(--text-disabled);
113
+ cursor: not-allowed;
114
+ opacity: var(--opacity-muted);
115
+ }
116
+ }
117
+ }
@@ -0,0 +1,59 @@
1
+ // Self-hosted DS default fonts (latin subset). Consumers override --font-sans / --font-mono to swap.
2
+
3
+ @font-face {
4
+ font-family: 'Mulish';
5
+ font-style: normal;
6
+ font-weight: 400;
7
+ font-display: swap;
8
+ src: url('./fonts/mulish-latin-400-normal.woff2') format('woff2');
9
+ }
10
+ @font-face {
11
+ font-family: 'Mulish';
12
+ font-style: normal;
13
+ font-weight: 500;
14
+ font-display: swap;
15
+ src: url('./fonts/mulish-latin-500-normal.woff2') format('woff2');
16
+ }
17
+ @font-face {
18
+ font-family: 'Mulish';
19
+ font-style: normal;
20
+ font-weight: 600;
21
+ font-display: swap;
22
+ src: url('./fonts/mulish-latin-600-normal.woff2') format('woff2');
23
+ }
24
+ @font-face {
25
+ font-family: 'Mulish';
26
+ font-style: normal;
27
+ font-weight: 700;
28
+ font-display: swap;
29
+ src: url('./fonts/mulish-latin-700-normal.woff2') format('woff2');
30
+ }
31
+ @font-face {
32
+ font-family: 'Mulish';
33
+ font-style: normal;
34
+ font-weight: 800;
35
+ font-display: swap;
36
+ src: url('./fonts/mulish-latin-800-normal.woff2') format('woff2');
37
+ }
38
+
39
+ @font-face {
40
+ font-family: 'JetBrains Mono';
41
+ font-style: normal;
42
+ font-weight: 400;
43
+ font-display: swap;
44
+ src: url('./fonts/jetbrains-mono-latin-400-normal.woff2') format('woff2');
45
+ }
46
+ @font-face {
47
+ font-family: 'JetBrains Mono';
48
+ font-style: normal;
49
+ font-weight: 500;
50
+ font-display: swap;
51
+ src: url('./fonts/jetbrains-mono-latin-500-normal.woff2') format('woff2');
52
+ }
53
+ @font-face {
54
+ font-family: 'JetBrains Mono';
55
+ font-style: normal;
56
+ font-weight: 600;
57
+ font-display: swap;
58
+ src: url('./fonts/jetbrains-mono-latin-600-normal.woff2') format('woff2');
59
+ }
@@ -0,0 +1,9 @@
1
+ // Icon-base sizing — `.icon` class is used inside components to size <ds-icon> svg elements.
2
+ // The actual <svg> is rendered by IconComponent; this class sets default size.
3
+ .icon {
4
+ --_icon-size: var(--ds-icon-size, var(--icon-md));
5
+
6
+ width: var(--_icon-size);
7
+ height: var(--_icon-size);
8
+ flex-shrink: 0;
9
+ }
@@ -0,0 +1,14 @@
1
+ // Layout utility classes — grid helpers from patterns.css §Grid helpers.
2
+ // (Divider lives in _divider.scss — single canonical source.)
3
+
4
+ .grid-2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-4); }
5
+ .grid-3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-4); }
6
+ .grid-4 { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-4); }
7
+
8
+ @media (max-width: 1100px) {
9
+ .grid-4 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
10
+ }
11
+
12
+ @media (max-width: 820px) {
13
+ .grid-3, .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
14
+ }
@@ -0,0 +1,77 @@
1
+ /* Global .link helper — pure CSS class (no Angular wrapper) so consumers
2
+ can apply it to inline anchors inside <p> text without disrupting line
3
+ flow. Modifiers: .quiet, .inline, .standalone, .xs, .sm, .lg. */
4
+
5
+ .link {
6
+ /* Public --ds-link-* are read with fallbacks, never declared — consumer
7
+ overrides inherit in. Hover/active derive from the resolved color. */
8
+ --_link-color: var(--ds-link-color, var(--text-link));
9
+ --_link-color-hover: var(--ds-link-color-hover, color-mix(in srgb, var(--_link-color) 80%, black));
10
+ --_link-color-active: var(--ds-link-color-active, color-mix(in srgb, var(--_link-color) 65%, black));
11
+
12
+ color: var(--_link-color);
13
+ text-decoration: underline;
14
+ text-decoration-color: var(--_link-color);
15
+ text-underline-offset: 2px;
16
+ text-decoration-thickness: 1px;
17
+ font-weight: var(--font-weight-medium);
18
+ cursor: pointer;
19
+ transition: color var(--duration-fast) var(--ease-standard), text-decoration-color var(--duration-fast) var(--ease-standard);
20
+
21
+ &:hover {
22
+ color: var(--_link-color-hover);
23
+ text-decoration-color: var(--_link-color-hover);
24
+ }
25
+
26
+ &:active {
27
+ color: var(--_link-color-active);
28
+ text-decoration-color: var(--_link-color-active);
29
+ }
30
+
31
+ &:focus-visible {
32
+ outline: none;
33
+ box-shadow: var(--focus-ring);
34
+ border-radius: var(--radius-sm);
35
+ text-decoration-color: var(--_link-color);
36
+ }
37
+
38
+ &[aria-disabled="true"] {
39
+ color: var(--text-disabled);
40
+ text-decoration-color: var(--text-disabled);
41
+ pointer-events: none;
42
+ cursor: default;
43
+ }
44
+
45
+ .icon {
46
+ color: currentColor;
47
+ flex-shrink: 0;
48
+ }
49
+
50
+ &.quiet {
51
+ color: var(--text-secondary);
52
+ /* Pull the underline down to match the muted text — the base rule sets
53
+ text-decoration-color to the link color, which would leave a bright
54
+ underline under grey text at rest. */
55
+ text-decoration-color: var(--text-secondary);
56
+ font-weight: var(--font-weight-medium);
57
+
58
+ &:hover {
59
+ color: var(--text-primary);
60
+ text-decoration-color: var(--text-primary);
61
+ }
62
+ }
63
+
64
+ &.inline {
65
+ font-weight: inherit;
66
+ font-size: inherit;
67
+ line-height: inherit;
68
+ }
69
+
70
+ &.standalone {
71
+ font-weight: var(--font-weight-bold);
72
+ }
73
+
74
+ &.xs { font-size: var(--font-size-xs); }
75
+ &.sm { font-size: var(--font-size-s); }
76
+ &.lg { font-size: var(--font-size-l); }
77
+ }
@@ -0,0 +1,68 @@
1
+ // Page grid — four-tier responsive layout grid.
2
+ //
3
+ // One column-count per breakpoint (4 / 8 / 12 / 12), gutters and margins
4
+ // scale with the viewport, content caps at --col-cap-content on the widest
5
+ // tier and stays fluid below. Sub-regions inherit the page grid — never
6
+ // invent a local grid. Sidenav lives OUTSIDE this grid (reserve its rail
7
+ // first, start `.page-grid` in the remaining width).
8
+ //
9
+ // Tier | Range | Cols | Gutter | Margin | Cap
10
+ // ------------ | -------------- | ---- | ------------- | ------------- | ----------------
11
+ // Mobile | <= 640px | 4 | --space-3 (12px) | --space-4 (16px) | fluid
12
+ // Tablet | 641-1024px | 8 | --space-4 (16px) | --space-6 (24px) | fluid
13
+ // Desktop | 1025-1440px | 12 | --space-5 (20px) | --space-8 (32px) | fluid
14
+ // Desktop wide | >= 1441px | 12 | --space-6 (24px) | --space-10 (40px) | --col-cap-content (1280px)
15
+ //
16
+ // Snap to columns, not pixels: 8+4 / 6+6 / 9+3 are canonical splits;
17
+ // 7+5 is forbidden. Prose blocks cap at --col-cap-text (720px) regardless
18
+ // of grid width.
19
+
20
+ .page-grid {
21
+ display: grid;
22
+ gap: var(--page-gutter);
23
+ padding: 0 var(--page-margin);
24
+ max-width: var(--col-cap-content);
25
+ margin: 0 auto;
26
+
27
+ // Mobile (default, <= 640px) — 4 columns
28
+ --page-gutter: var(--page-gutter-mobile);
29
+ --page-margin: var(--page-margin-mobile);
30
+ grid-template-columns: repeat(4, minmax(0, 1fr));
31
+
32
+ // Tablet (641-1024px) — 8 columns
33
+ @media (min-width: 641px) {
34
+ --page-gutter: var(--page-gutter-tablet);
35
+ --page-margin: var(--page-margin-tablet);
36
+ grid-template-columns: repeat(8, minmax(0, 1fr));
37
+ }
38
+
39
+ // Desktop (1025-1440px) — 12 columns, fluid width
40
+ @media (min-width: 1025px) {
41
+ --page-gutter: var(--page-gutter-desktop);
42
+ --page-margin: var(--page-margin-desktop);
43
+ grid-template-columns: repeat(12, minmax(0, 1fr));
44
+ }
45
+
46
+ // Desktop wide (>= 1441px) — 12 columns, container capped at --col-cap-content
47
+ @media (min-width: 1441px) {
48
+ --page-gutter: var(--page-gutter-wide);
49
+ --page-margin: var(--page-margin-wide);
50
+ }
51
+ }
52
+
53
+ // Column-span helpers. The 12-col base covers every tier — at narrower tiers
54
+ // (8 / 4 cols) a span larger than the active column-count wraps to its own
55
+ // row, which is the intended fallback. Snap to canonical splits (8+4 / 6+6 /
56
+ // 9+3 / 4+4+4) rather than ad-hoc widths.
57
+ .col-span-1 { grid-column: span 1; }
58
+ .col-span-2 { grid-column: span 2; }
59
+ .col-span-3 { grid-column: span 3; }
60
+ .col-span-4 { grid-column: span 4; }
61
+ .col-span-5 { grid-column: span 5; }
62
+ .col-span-6 { grid-column: span 6; }
63
+ .col-span-7 { grid-column: span 7; }
64
+ .col-span-8 { grid-column: span 8; }
65
+ .col-span-9 { grid-column: span 9; }
66
+ .col-span-10 { grid-column: span 10; }
67
+ .col-span-11 { grid-column: span 11; }
68
+ .col-span-12 { grid-column: span 12; }
@@ -0,0 +1,17 @@
1
+ // Reset — ported from CLAUDE_DESIGN_DS/tokens.css §Base.
2
+
3
+ *, *::before, *::after { box-sizing: border-box; }
4
+ html, body {
5
+ margin: 0;
6
+ font-family: var(--font-sans);
7
+ color: var(--text-primary);
8
+ background: var(--surface-canvas);
9
+ -webkit-font-smoothing: antialiased;
10
+ text-rendering: optimizeLegibility;
11
+ }
12
+ button, input, select, textarea { font-family: inherit; }
13
+
14
+ /* Zero the browser's default heading margins (~0.83em) — they otherwise leak
15
+ into consumers and mangle spacing. Headings get their size from .t-* utils;
16
+ spacing is owned by the surrounding layout (gap / margin), not the element. */
17
+ h1, h2, h3, h4, h5, h6 { margin: 0; }
@@ -0,0 +1,17 @@
1
+ // Scrollbar — ported verbatim from CLAUDE_DESIGN_DS/components-extras.css §Global scrollbar.
2
+ // Brand-tinted neutral thumb applied globally.
3
+
4
+ html { scrollbar-width: thin; scrollbar-color: var(--scrollbar-thumb) transparent; }
5
+ *::-webkit-scrollbar { width: var(--scrollbar-w); height: var(--scrollbar-w); }
6
+ *::-webkit-scrollbar-track { background: transparent; }
7
+ *::-webkit-scrollbar-thumb {
8
+ background: var(--scrollbar-thumb);
9
+ border-radius: var(--radius-pill);
10
+ border: var(--space-0-5) solid transparent;
11
+ background-clip: padding-box;
12
+ }
13
+ *::-webkit-scrollbar-thumb:hover { background: var(--scrollbar-thumb-hover); background-clip: padding-box; }
14
+ *::-webkit-scrollbar-thumb:active { background: var(--scrollbar-thumb-active); background-clip: padding-box; }
15
+
16
+ // Global text-selection — sourced from components-extras.css line 910.
17
+ ::selection { background: var(--select-bg, color-mix(in srgb, var(--primary) 22%, transparent)); color: var(--text-primary); }
@@ -0,0 +1,32 @@
1
+ // Global skeleton shimmer driver.
2
+ //
3
+ // All <ds-skeleton> instances on the page reveal the same moving slice by
4
+ // reading a shared, viewport-anchored offset (--skeleton-shimmer-x). The
5
+ // offset is animated ONCE on :root so every skeleton stays in lock-step with
6
+ // every other — no per-element animation timers drifting against each other.
7
+ //
8
+ // @property registration is required so the browser can interpolate the
9
+ // custom property continuously instead of treating it as a discrete switch
10
+ // at 0%/100%. Chrome 85+, Edge 85+, Firefox 128+, Safari 16.4+.
11
+
12
+ @property --skeleton-shimmer-x {
13
+ syntax: '<length>';
14
+ inherits: true;
15
+ initial-value: 100vw;
16
+ }
17
+
18
+ :root {
19
+ animation: ds-skeleton-shimmer-loop var(--duration-loop-slow, 1400ms) linear infinite;
20
+ }
21
+
22
+ @keyframes ds-skeleton-shimmer-loop {
23
+ 0% { --skeleton-shimmer-x: 100vw; }
24
+ 100% { --skeleton-shimmer-x: -100vw; }
25
+ }
26
+
27
+ // Honour the user's reduced-motion preference — no shimmer travel.
28
+ @media (prefers-reduced-motion: reduce) {
29
+ :root {
30
+ animation: none;
31
+ }
32
+ }
@@ -0,0 +1,6 @@
1
+ // Toast overlay panel — GLOBAL (portaled via CDK Overlay, outside component DOM).
2
+ // ToastService sets panelClass: 'ds-toast-panel'. CDK overlays stack by DOM
3
+ // insertion order, so lift the toast wrapper above modals/drawers explicitly.
4
+ .cdk-global-overlay-wrapper:has(> .ds-toast-panel) {
5
+ z-index: var(--layer-toast);
6
+ }
@@ -0,0 +1,71 @@
1
+ /* ============================================================
2
+ Boilerplate — Chart / dataviz tokens
3
+ ------------------------------------------------------------
4
+ Categorical: 8 hues, ordered by perceptual distance not
5
+ ramp position. First six are AA against both light and
6
+ dark surface-default; the last two are reserved for
7
+ "rest" / "other" buckets where contrast is less critical.
8
+
9
+ Sequential: single-hue ramp (blue) for ordinal data —
10
+ "low → high" magnitudes.
11
+
12
+ Divergent: red ↔ neutral ↔ green for signed data —
13
+ "bad ← zero → good". Used for Excess / Shortage matrix.
14
+ ============================================================ */
15
+
16
+ :root {
17
+ /* CATEGORICAL (8) ----------------------------------------- */
18
+ --chart-cat-1: hsl(229, 100%, 59%); /* blue (primary) */
19
+ --chart-cat-2: hsl(165, 72%, 38%); /* teal */
20
+ --chart-cat-3: hsl( 24, 95%, 55%); /* orange */
21
+ --chart-cat-4: hsl(330, 82%, 55%); /* magenta */
22
+ --chart-cat-5: hsl(45, 95%, 50%); /* amber */
23
+ --chart-cat-6: hsl(190, 85%, 45%); /* cyan */
24
+ --chart-cat-7: hsl(280, 60%, 60%); /* lavender */
25
+ --chart-cat-8: hsl(130, 45%, 50%); /* moss */
26
+
27
+ /* SEQUENTIAL — single-hue, light → dark */
28
+ --chart-seq-1: var(--blue-100);
29
+ --chart-seq-2: var(--blue-200);
30
+ --chart-seq-3: var(--blue-300);
31
+ --chart-seq-4: var(--blue-500);
32
+ --chart-seq-5: var(--blue-700);
33
+ --chart-seq-6: var(--blue-900);
34
+
35
+ /* DIVERGENT — red ← neutral → green
36
+ Values taken verbatim from the source design prototype
37
+ (CLAUDE_DESIGN_DS/patterns.css) so the Excess/Shortage matrix
38
+ matches the reference one-for-one. Explicit HSL keeps the ramp
39
+ independent of palette retunes — re-skinning brand/red/green
40
+ should not shift the dataviz colour story. */
41
+ --chart-div--3: hsl(0 70% 40%); /* large negative (worst) */
42
+ --chart-div--2: hsl(0 60% 58%);
43
+ --chart-div--1: hsl(0 50% 80%);
44
+ --chart-div-0: hsl(225 8% 92%); /* zero */
45
+ --chart-div-1: hsl(140 35% 80%);
46
+ --chart-div-2: hsl(140 45% 55%);
47
+ --chart-div-3: hsl(140 55% 35%); /* large positive (best) */
48
+
49
+ /* AXIS / GRID / LEGEND */
50
+ --chart-axis-line: var(--neutral-300);
51
+ --chart-axis-label: var(--text-tertiary);
52
+ --chart-axis-title: var(--text-secondary);
53
+ --chart-grid-line: var(--neutral-150);
54
+ --chart-grid-line-strong: var(--neutral-200);
55
+ --chart-tick-size: 4px;
56
+ --chart-axis-fs: var(--font-size-2xs);
57
+
58
+ /* HIGHLIGHT / HOVER */
59
+ --chart-hover-bg: hsla(225, 39%, 7%, .04);
60
+ --chart-cursor-line: var(--neutral-400);
61
+ --chart-tooltip-bg: var(--neutral-900);
62
+ --chart-tooltip-fg: var(--neutral-0);
63
+ --chart-tooltip-border: var(--neutral-700);
64
+
65
+ /* DIMENSIONS */
66
+ --chart-bar-gap: 4px;
67
+ --chart-line-w: 2px;
68
+ --chart-line-w-bold: 3px;
69
+ --chart-dot-r: 4px;
70
+ --chart-dot-r-active: 6px;
71
+ }