@truenas/ui-components 0.1.2 → 0.1.4

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@truenas/ui-components",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "publishConfig": {
5
5
  "registry": "https://registry.npmjs.org",
6
6
  "access": "public"
@@ -437,79 +437,7 @@ textarea.tn-input-directive {
437
437
  }
438
438
 
439
439
  /* ================================
440
- Let's apply these variables to
441
- the preview and story book docs elements
442
- ================================ */
443
-
444
- html, body, #storybook-docs > .sbdocs-wrapper {
445
- font-family: var(--tn-font-family-body);
446
- color: var(--tn-fg2) !important;
447
- background-color: var(--tn-bg1) !important;
448
- }
449
-
450
- h1, h2, h3,h4,
451
- .sbdocs-title h1, .sbdocs-title h2, .sbdocs-title h3,.sbdocs-title h4 {
452
- font-family: var(--tn-font-family-header);
453
- color: var(--tn-fg1) !important;
454
- }
455
-
456
- p, li, td {
457
- color: var(--tn-fg2) !important;
458
- }
459
-
460
- .docs-story,
461
- .sb-bar,
462
- .sbdocs-wrapper td,
463
- .sbdocs-preview {
464
- background-color: var(--tn-bg2) !important;
465
- color: var(--tn-fg2) !important;
466
- }
467
-
468
- thead, th {
469
- background-color: var(--tn-topbar);
470
- color: var(--tn-topbar-txt) !important;
471
- }
472
-
473
- /* Form field styles */
474
- input:not([role="switch"]),
475
- .sbdocs-wrapper select,
476
- .sbdocs-wrapper textarea {
477
- background-color: var(--tn-bg1) !important;
478
- color: var(--tn-fg2) !important;
479
- }
480
-
481
- .docblock-code-toggle {
482
- background-color: var(--tn-btn-default-bg) !important;
483
- color: var(--tn-btn-default-txt) !important;
484
- }
485
-
486
- .docblock-argstable-body span {
487
- color: var(--tn-fg1);
488
- background-color: unset;
489
- border: unset;
490
- }
491
-
492
- .docs-story > div {
493
- background-color: unset;
494
- }
495
-
496
- .docblock-source > div {
497
- background: #000000 !important;
498
- color: #dedede;
499
- border: unset;
500
- }
501
-
502
- .docblock-source button {
503
- background: var(--tn-bg2) !important;
504
- color: var(--tn-fg2);
505
- }
506
-
507
- .docblock-source {
508
- border: solid 1px var(--tn-alt-bg2) !important;
509
- }
510
-
511
- /* ================================
512
- IX Dialog Styles
440
+ TN Dialog Styles
513
441
  ================================ */
514
442
 
515
443
  /* Dialog panel - the main dialog container */
@@ -1,8 +1,9 @@
1
1
  import * as _angular_core from '@angular/core';
2
- import { AfterViewInit, ElementRef, OnDestroy, TemplateRef, AfterContentInit, ChangeDetectorRef, PipeTransform, OnInit, ViewContainerRef, AfterViewChecked } from '@angular/core';
2
+ import { AfterViewInit, ElementRef, OnDestroy, TemplateRef, AfterContentInit, Provider, ChangeDetectorRef, PipeTransform, OnInit, ViewContainerRef, AfterViewChecked } from '@angular/core';
3
3
  import { ComponentHarness, BaseHarnessFilters, HarnessPredicate } from '@angular/cdk/testing';
4
4
  import { SafeHtml, SafeResourceUrl, DomSanitizer } from '@angular/platform-browser';
5
5
  import { ControlValueAccessor, NgControl } from '@angular/forms';
6
+ import { jest } from '@jest/globals';
6
7
  import { DataSource } from '@angular/cdk/collections';
7
8
  import * as i1 from '@angular/cdk/tree';
8
9
  import { CdkTree, FlatTreeControl, CdkTreeNode, CdkNestedTreeNode } from '@angular/cdk/tree';
@@ -27,8 +28,27 @@ declare class DiskIconComponent {
27
28
  }
28
29
 
29
30
  type TnBannerType = 'info' | 'warning' | 'error' | 'success';
31
+ /**
32
+ * Directive to mark an element as a banner action.
33
+ * Apply this to any element that should appear in the banner's action area.
34
+ *
35
+ * @example
36
+ * ```html
37
+ * <tn-banner heading="Error">
38
+ * <button tnBannerAction>Fix Now</button>
39
+ * </tn-banner>
40
+ * ```
41
+ */
42
+ declare class TnBannerActionDirective {
43
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<TnBannerActionDirective, never>;
44
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<TnBannerActionDirective, "[tnBannerAction]", never, {}, {}, never, never, true, never>;
45
+ }
30
46
  declare class TnBannerComponent {
31
47
  private iconRegistry;
48
+ /** Query for projected action content */
49
+ private actionContent;
50
+ /** Signal indicating whether action content has been projected */
51
+ protected hasAction: _angular_core.Signal<boolean>;
32
52
  heading: _angular_core.InputSignal<string>;
33
53
  message: _angular_core.InputSignal<string | undefined>;
34
54
  type: _angular_core.InputSignal<TnBannerType>;
@@ -53,7 +73,7 @@ declare class TnBannerComponent {
53
73
  */
54
74
  classes: _angular_core.Signal<string[]>;
55
75
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<TnBannerComponent, never>;
56
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<TnBannerComponent, "tn-banner", never, { "heading": { "alias": "heading"; "required": true; "isSignal": true; }; "message": { "alias": "message"; "required": false; "isSignal": true; }; "type": { "alias": "type"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
76
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<TnBannerComponent, "tn-banner", never, { "heading": { "alias": "heading"; "required": true; "isSignal": true; }; "message": { "alias": "message"; "required": false; "isSignal": true; }; "type": { "alias": "type"; "required": false; "isSignal": true; }; }, {}, ["actionContent"], ["[tnBannerAction]"], true, never>;
57
77
  }
58
78
 
59
79
  /**
@@ -138,6 +158,93 @@ declare class TnButtonComponent {
138
158
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<TnButtonComponent, "tn-button", never, { "primary": { "alias": "primary"; "required": false; "isSignal": true; }; "color": { "alias": "color"; "required": false; "isSignal": true; }; "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "backgroundColor": { "alias": "backgroundColor"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; }, { "onClick": "onClick"; }, never, never, true, never>;
139
159
  }
140
160
 
161
+ /**
162
+ * Harness for interacting with tn-button in tests.
163
+ * Provides methods for querying button state and simulating user interactions.
164
+ *
165
+ * @example
166
+ * ```typescript
167
+ * // Find and click a button
168
+ * const saveBtn = await loader.getHarness(TnButtonHarness.with({ label: 'Save' }));
169
+ * await saveBtn.click();
170
+ *
171
+ * // Check if button is disabled
172
+ * const submitBtn = await loader.getHarness(TnButtonHarness.with({ label: 'Submit' }));
173
+ * expect(await submitBtn.isDisabled()).toBe(false);
174
+ *
175
+ * // Find button by regex
176
+ * const cancelBtn = await loader.getHarness(TnButtonHarness.with({ label: /Cancel/i }));
177
+ * ```
178
+ */
179
+ declare class TnButtonHarness extends ComponentHarness {
180
+ /**
181
+ * The selector for the host element of a `TnButtonComponent` instance.
182
+ */
183
+ static hostSelector: string;
184
+ private _button;
185
+ /**
186
+ * Gets a `HarnessPredicate` that can be used to search for a button
187
+ * with specific attributes.
188
+ *
189
+ * @param options Options for filtering which button instances are considered a match.
190
+ * @returns A `HarnessPredicate` configured with the given options.
191
+ *
192
+ * @example
193
+ * ```typescript
194
+ * // Find button by exact label
195
+ * const button = await loader.getHarness(TnButtonHarness.with({ label: 'Save' }));
196
+ *
197
+ * // Find button with regex pattern
198
+ * const button = await loader.getHarness(TnButtonHarness.with({ label: /Delete/i }));
199
+ * ```
200
+ */
201
+ static with(options?: ButtonHarnessFilters): HarnessPredicate<TnButtonHarness>;
202
+ /**
203
+ * Gets the button's label text.
204
+ *
205
+ * @returns Promise resolving to the button's text content.
206
+ *
207
+ * @example
208
+ * ```typescript
209
+ * const button = await loader.getHarness(TnButtonHarness);
210
+ * const label = await button.getLabel();
211
+ * expect(label).toBe('Submit');
212
+ * ```
213
+ */
214
+ getLabel(): Promise<string>;
215
+ /**
216
+ * Checks whether the button is disabled.
217
+ *
218
+ * @returns Promise resolving to true if the button is disabled.
219
+ *
220
+ * @example
221
+ * ```typescript
222
+ * const button = await loader.getHarness(TnButtonHarness.with({ label: 'Submit' }));
223
+ * expect(await button.isDisabled()).toBe(false);
224
+ * ```
225
+ */
226
+ isDisabled(): Promise<boolean>;
227
+ /**
228
+ * Clicks the button.
229
+ *
230
+ * @returns Promise that resolves when the click action is complete.
231
+ *
232
+ * @example
233
+ * ```typescript
234
+ * const button = await loader.getHarness(TnButtonHarness.with({ label: 'Save' }));
235
+ * await button.click();
236
+ * ```
237
+ */
238
+ click(): Promise<void>;
239
+ }
240
+ /**
241
+ * A set of criteria that can be used to filter a list of `TnButtonHarness` instances.
242
+ */
243
+ interface ButtonHarnessFilters extends BaseHarnessFilters {
244
+ /** Filters by button label text. Supports string or regex matching. */
245
+ label?: string | RegExp;
246
+ }
247
+
141
248
  type IconSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
142
249
  type IconSource = 'svg' | 'css' | 'unicode' | 'text' | 'sprite';
143
250
  type IconLibraryType = 'material' | 'mdi' | 'custom' | 'lucide';
@@ -1041,6 +1148,97 @@ declare function tnIconMarker(iconName: string, library?: 'mdi' | 'material' | '
1041
1148
  */
1042
1149
  declare function libIconMarker(iconName: `tn-${string}`): string;
1043
1150
 
1151
+ /**
1152
+ * Mock type for TnSpriteLoaderService
1153
+ */
1154
+ interface MockSpriteLoader {
1155
+ ensureSpriteLoaded: jest.Mock;
1156
+ getIconUrl: jest.Mock;
1157
+ getSafeIconUrl: jest.Mock;
1158
+ isSpriteLoaded: jest.Mock;
1159
+ getSpriteConfig: jest.Mock;
1160
+ }
1161
+ /**
1162
+ * Mock type for TnIconRegistryService
1163
+ */
1164
+ interface MockIconRegistry {
1165
+ resolveIcon: jest.Mock;
1166
+ getSpriteLoader: jest.Mock;
1167
+ registerIcon: jest.Mock;
1168
+ registerIcons: jest.Mock;
1169
+ registerLibrary: jest.Mock;
1170
+ }
1171
+ /**
1172
+ * Options for customizing icon testing mocks
1173
+ */
1174
+ interface IconTestingMockOverrides {
1175
+ spriteLoader?: Partial<MockSpriteLoader>;
1176
+ iconRegistry?: Partial<MockIconRegistry>;
1177
+ }
1178
+ /**
1179
+ * Testing utilities for TnIcon components.
1180
+ *
1181
+ * Provides framework-specific mock implementations of icon services to simplify testing
1182
+ * components that use TnIconComponent.
1183
+ *
1184
+ * @example
1185
+ * ```typescript
1186
+ * // Simple usage - "it just works"
1187
+ * await TestBed.configureTestingModule({
1188
+ * imports: [MyComponent],
1189
+ * providers: [
1190
+ * TnIconTesting.jest.providers()
1191
+ * ]
1192
+ * }).compileComponents();
1193
+ * ```
1194
+ *
1195
+ * @example
1196
+ * ```typescript
1197
+ * // Advanced usage - customize mocks
1198
+ * await TestBed.configureTestingModule({
1199
+ * imports: [MyComponent],
1200
+ * providers: [
1201
+ * TnIconTesting.jest.providers({
1202
+ * iconRegistry: {
1203
+ * resolveIcon: jest.fn(() => ({
1204
+ * source: 'sprite',
1205
+ * spriteUrl: '#custom-icon'
1206
+ * }))
1207
+ * }
1208
+ * })
1209
+ * ]
1210
+ * }).compileComponents();
1211
+ * ```
1212
+ */
1213
+ declare const TnIconTesting: {
1214
+ /**
1215
+ * Jest-specific testing utilities.
1216
+ */
1217
+ readonly jest: {
1218
+ /**
1219
+ * Returns Angular providers with mocked icon services.
1220
+ * Creates fresh mock instances on each call to prevent test pollution.
1221
+ *
1222
+ * @param overrides Optional partial mock implementations to customize behavior
1223
+ * @returns Array of providers for TestBed
1224
+ *
1225
+ * @example
1226
+ * ```typescript
1227
+ * // Default mocks
1228
+ * TnIconTesting.jest.providers()
1229
+ *
1230
+ * // Custom sprite loader behavior
1231
+ * TnIconTesting.jest.providers({
1232
+ * spriteLoader: {
1233
+ * getIconUrl: jest.fn(() => '#custom-icon')
1234
+ * }
1235
+ * })
1236
+ * ```
1237
+ */
1238
+ readonly providers: (overrides?: IconTestingMockOverrides) => Provider[];
1239
+ };
1240
+ };
1241
+
1044
1242
  /**
1045
1243
  * Lucide Icons Integration Helper
1046
1244
  *
@@ -2683,5 +2881,5 @@ declare const TN_THEME_DEFINITIONS: readonly TnThemeDefinition[];
2683
2881
  */
2684
2882
  declare const THEME_MAP: Map<TnTheme, TnThemeDefinition>;
2685
2883
 
2686
- export { CommonShortcuts, DEFAULT_THEME, DiskIconComponent, DiskType, FileSizePipe, InputType, LinuxModifierKeys, LinuxShortcuts, ModifierKeys, QuickShortcuts, ShortcutBuilder, StripMntPrefixPipe, THEME_MAP, THEME_STORAGE_KEY, TN_THEME_DEFINITIONS, TnBannerComponent, TnBannerHarness, TnBrandedSpinnerComponent, TnButtonComponent, TnButtonToggleComponent, TnButtonToggleGroupComponent, TnCalendarComponent, TnCalendarHeaderComponent, TnCardComponent, TnCellDefDirective, TnCheckboxComponent, TnChipComponent, TnConfirmDialogComponent, TnDateInputComponent, TnDateRangeInputComponent, TnDialog, TnDialogShellComponent, TnDividerComponent, TnDividerDirective, TnExpansionPanelComponent, TnFilePickerComponent, TnFilePickerPopupComponent, TnFormFieldComponent, TnHeaderCellDefDirective, TnIconButtonComponent, TnIconComponent, TnIconHarness, TnIconRegistryService, TnInputComponent, TnInputDirective, TnKeyboardShortcutComponent, TnKeyboardShortcutService, TnListAvatarDirective, TnListComponent, TnListIconDirective, TnListItemComponent, TnListItemLineDirective, TnListItemPrimaryDirective, TnListItemSecondaryDirective, TnListItemTitleDirective, TnListItemTrailingDirective, TnListOptionComponent, TnListSubheaderComponent, TnMenuComponent, TnMenuTriggerDirective, TnMonthViewComponent, TnMultiYearViewComponent, TnNestedTreeNodeComponent, TnParticleProgressBarComponent, TnProgressBarComponent, TnRadioComponent, TnSelectComponent, TnSelectionListComponent, TnSlideToggleComponent, TnSliderComponent, TnSliderThumbDirective, TnSliderWithLabelDirective, TnSpinnerComponent, TnSpriteLoaderService, TnStepComponent, TnStepperComponent, TnTabComponent, TnTabPanelComponent, TnTableColumnDirective, TnTableComponent, TnTabsComponent, TnTheme, TnThemeService, TnTimeInputComponent, TnTooltipComponent, TnTooltipDirective, TnTreeComponent, TnTreeFlatDataSource, TnTreeFlattener, TnTreeNodeComponent, TnTreeNodeOutletDirective, TruncatePathPipe, WindowsModifierKeys, WindowsShortcuts, createLucideLibrary, createShortcut, defaultSpriteBasePath, defaultSpriteConfigPath, libIconMarker, registerLucideIcons, setupLucideIntegration, tnIconMarker };
2687
- export type { BannerHarnessFilters, CalendarCell, ChipColor, CreateFolderEvent, DateRange, FilePickerCallbacks, FilePickerError, FilePickerMode, FileSystemItem, IconHarnessFilters, IconLibrary, IconLibraryType, IconResult, IconSize, IconSource, KeyCombination, LabelType, LucideIconOptions, PathSegment, PlatformType, ProgressBarMode, ResolvedIcon, ShortcutHandler, SlideToggleColor, SpinnerMode, SpriteConfig, TabChangeEvent, TnBannerType, TnButtonToggleType, TnCardAction, TnCardControl, TnCardFooterLink, TnCardHeaderStatus, TnConfirmDialogData, TnDialogDefaults, TnDialogOpenTarget, TnFlatTreeNode, TnMenuItem, TnSelectOption, TnSelectOptionGroup, TnSelectionChange, TnTableDataSource, TnThemeDefinition, TooltipPosition, YearCell };
2884
+ export { CommonShortcuts, DEFAULT_THEME, DiskIconComponent, DiskType, FileSizePipe, InputType, LinuxModifierKeys, LinuxShortcuts, ModifierKeys, QuickShortcuts, ShortcutBuilder, StripMntPrefixPipe, THEME_MAP, THEME_STORAGE_KEY, TN_THEME_DEFINITIONS, TnBannerActionDirective, TnBannerComponent, TnBannerHarness, TnBrandedSpinnerComponent, TnButtonComponent, TnButtonHarness, TnButtonToggleComponent, TnButtonToggleGroupComponent, TnCalendarComponent, TnCalendarHeaderComponent, TnCardComponent, TnCellDefDirective, TnCheckboxComponent, TnChipComponent, TnConfirmDialogComponent, TnDateInputComponent, TnDateRangeInputComponent, TnDialog, TnDialogShellComponent, TnDividerComponent, TnDividerDirective, TnExpansionPanelComponent, TnFilePickerComponent, TnFilePickerPopupComponent, TnFormFieldComponent, TnHeaderCellDefDirective, TnIconButtonComponent, TnIconComponent, TnIconHarness, TnIconRegistryService, TnIconTesting, TnInputComponent, TnInputDirective, TnKeyboardShortcutComponent, TnKeyboardShortcutService, TnListAvatarDirective, TnListComponent, TnListIconDirective, TnListItemComponent, TnListItemLineDirective, TnListItemPrimaryDirective, TnListItemSecondaryDirective, TnListItemTitleDirective, TnListItemTrailingDirective, TnListOptionComponent, TnListSubheaderComponent, TnMenuComponent, TnMenuTriggerDirective, TnMonthViewComponent, TnMultiYearViewComponent, TnNestedTreeNodeComponent, TnParticleProgressBarComponent, TnProgressBarComponent, TnRadioComponent, TnSelectComponent, TnSelectionListComponent, TnSlideToggleComponent, TnSliderComponent, TnSliderThumbDirective, TnSliderWithLabelDirective, TnSpinnerComponent, TnSpriteLoaderService, TnStepComponent, TnStepperComponent, TnTabComponent, TnTabPanelComponent, TnTableColumnDirective, TnTableComponent, TnTabsComponent, TnTheme, TnThemeService, TnTimeInputComponent, TnTooltipComponent, TnTooltipDirective, TnTreeComponent, TnTreeFlatDataSource, TnTreeFlattener, TnTreeNodeComponent, TnTreeNodeOutletDirective, TruncatePathPipe, WindowsModifierKeys, WindowsShortcuts, createLucideLibrary, createShortcut, defaultSpriteBasePath, defaultSpriteConfigPath, libIconMarker, registerLucideIcons, setupLucideIntegration, tnIconMarker };
2885
+ export type { BannerHarnessFilters, ButtonHarnessFilters, CalendarCell, ChipColor, CreateFolderEvent, DateRange, FilePickerCallbacks, FilePickerError, FilePickerMode, FileSystemItem, IconHarnessFilters, IconLibrary, IconLibraryType, IconResult, IconSize, IconSource, IconTestingMockOverrides, KeyCombination, LabelType, LucideIconOptions, MockIconRegistry, MockSpriteLoader, PathSegment, PlatformType, ProgressBarMode, ResolvedIcon, ShortcutHandler, SlideToggleColor, SpinnerMode, SpriteConfig, TabChangeEvent, TnBannerType, TnButtonToggleType, TnCardAction, TnCardControl, TnCardFooterLink, TnCardHeaderStatus, TnConfirmDialogData, TnDialogDefaults, TnDialogOpenTarget, TnFlatTreeNode, TnMenuItem, TnSelectOption, TnSelectOptionGroup, TnSelectionChange, TnTableDataSource, TnThemeDefinition, TooltipPosition, YearCell };
@@ -1,150 +0,0 @@
1
- /* TN Dialog Global Styles for CDK Dialog */
2
-
3
- /* CDK Dialog Container Styles */
4
- .cdk-dialog-container {
5
- display: flex;
6
- flex-direction: column;
7
- align-items: center;
8
- justify-content: center;
9
- min-height: 100vh;
10
- padding: 20px;
11
- box-sizing: border-box;
12
- }
13
-
14
- /* Dialog Panel - this is the actual dialog box */
15
- .cdk-dialog-panel,
16
- .tn-dialog-panel {
17
- position: relative;
18
- display: flex;
19
- flex-direction: column;
20
- border-radius: 8px;
21
- box-sizing: border-box;
22
- overflow: hidden;
23
- outline: 0;
24
- width: 100%;
25
- max-width: 80vw;
26
- max-height: 80vh;
27
- background: var(--tn-bg1, #ffffff);
28
- color: var(--tn-fg1, #000000);
29
- box-shadow: 0 11px 15px -7px rgba(0, 0, 0, 0.2),
30
- 0 24px 38px 3px rgba(0, 0, 0, 0.14),
31
- 0 9px 46px 8px rgba(0, 0, 0, 0.12);
32
- }
33
-
34
- /* Dialog backdrop */
35
- .cdk-dialog-backdrop {
36
- background: rgba(0, 0, 0, 0.5);
37
- }
38
-
39
- /* Dialog content structure styling */
40
- .cdk-dialog-panel > * {
41
- display: flex;
42
- flex-direction: column;
43
- height: 100%;
44
- width: 100%;
45
- box-sizing: border-box;
46
- }
47
-
48
- /* Dialog title should be at the very top */
49
- .tn-dialog-title {
50
- box-sizing: border-box;
51
- display: block;
52
- flex-shrink: 0; /* Don't allow shrinking */
53
- width: 100%; /* Full width */
54
- padding: 24px 48px 20px 24px; /* Top, right (for close button), bottom, left */
55
- margin: 0;
56
- font-size: 1.25rem;
57
- font-weight: 600;
58
- line-height: 1.5;
59
- }
60
-
61
- /* Reset margins for any heading elements inside the title */
62
- .tn-dialog-title h1,
63
- .tn-dialog-title h2,
64
- .tn-dialog-title h3,
65
- .tn-dialog-title h4,
66
- .tn-dialog-title h5,
67
- .tn-dialog-title h6 {
68
- margin: 0;
69
- font-size: inherit;
70
- font-weight: inherit;
71
- line-height: inherit;
72
- }
73
-
74
- /* Dialog content should expand to fill available space between title and actions */
75
- .tn-dialog-content {
76
- flex-grow: 1;
77
- overflow: auto;
78
- box-sizing: border-box;
79
- min-height: 0; /* Allow flexbox to shrink */
80
- }
81
-
82
- /* Dialog actions styling */
83
- .tn-dialog-actions {
84
- box-sizing: border-box;
85
- display: flex !important;
86
- flex-shrink: 0; /* Don't allow shrinking - always visible */
87
- align-items: center !important;
88
- justify-content: flex-end !important;
89
- width: 100%; /* Full width */
90
- padding: 8px 24px 24px 24px !important; /* Top, right, bottom, left */
91
- margin: 0 !important;
92
- gap: 12px !important;
93
- border-top: 1px solid var(--tn-lines, #e5e7eb) !important;
94
- }
95
-
96
- /* Close button styling */
97
- .tn-dialog-close-btn {
98
- position: absolute;
99
- top: 16px;
100
- right: 16px;
101
- display: flex;
102
- align-items: center;
103
- justify-content: center;
104
- width: 32px;
105
- height: 32px;
106
- padding: 0;
107
- background: none;
108
- border: none;
109
- border-radius: 4px;
110
- color: var(--tn-fg2, #6c757d);
111
- cursor: pointer;
112
- font-size: 24px;
113
- line-height: 1;
114
- transition: all 0.2s ease-in-out;
115
- z-index: 10;
116
- }
117
-
118
- .tn-dialog-close-btn:hover {
119
- background: var(--tn-alt-bg1, #f8f9fa);
120
- color: var(--tn-fg1, #000000);
121
- }
122
-
123
- .tn-dialog-close-btn:focus {
124
- outline: 2px solid var(--tn-primary, #007bff);
125
- outline-offset: 2px;
126
- }
127
-
128
- .tn-dialog-close-btn:active {
129
- transform: scale(0.95);
130
- }
131
-
132
- .tn-dialog-close-btn span {
133
- font-weight: normal;
134
- }
135
-
136
- /* High contrast mode support */
137
- @media (prefers-contrast: high) {
138
- .cdk-dialog-panel,
139
- .tn-dialog-panel {
140
- border: 1px solid var(--tn-fg1, #000);
141
- }
142
- }
143
-
144
- /* Reduced motion support */
145
- @media (prefers-reduced-motion: reduce) {
146
- .cdk-dialog-panel,
147
- .tn-dialog-panel {
148
- /* Animations will be disabled by the animation trigger */
149
- }
150
- }