@ojiepermana/angular 21.1.11 → 21.1.13
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/README.md +13 -0
- package/brand/etos/README.md +142 -122
- package/etos/styles/color.css +52 -0
- package/etos/styles/layout.css +0 -165
- package/fesm2022/ojiepermana-angular-brand-etos.mjs +398 -234
- package/fesm2022/ojiepermana-angular-brand-etos.mjs.map +1 -1
- package/fesm2022/ojiepermana-angular-chart.mjs +72 -72
- package/fesm2022/ojiepermana-angular-chart.mjs.map +1 -1
- package/fesm2022/ojiepermana-angular-component.mjs +306 -296
- package/fesm2022/ojiepermana-angular-component.mjs.map +1 -1
- package/fesm2022/ojiepermana-angular-layout.mjs +75 -56
- package/fesm2022/ojiepermana-angular-layout.mjs.map +1 -1
- package/fesm2022/ojiepermana-angular-navigation.mjs +279 -258
- package/fesm2022/ojiepermana-angular-navigation.mjs.map +1 -1
- package/fesm2022/ojiepermana-angular-theme.mjs +3 -3
- package/fesm2022/ojiepermana-angular-theme.mjs.map +1 -1
- package/package.json +1 -1
- package/theme/styles/themes/taildwind.css +3 -0
- package/types/ojiepermana-angular-brand-etos.d.ts +30 -53
- package/types/ojiepermana-angular-component.d.ts +2 -1
- package/types/ojiepermana-angular-layout.d.ts +18 -11
- package/types/ojiepermana-angular-navigation.d.ts +28 -15
package/README.md
CHANGED
|
@@ -33,6 +33,19 @@ If you install the package with `npm install`, `bun add`, `pnpm add`, or `yarn
|
|
|
33
33
|
add` directly, peer dependency installation falls back to the package
|
|
34
34
|
manager's own behavior.
|
|
35
35
|
|
|
36
|
+
## Navigation primitives
|
|
37
|
+
|
|
38
|
+
`@ojiepermana/angular/navigation` exports the shared sidebar and topbar building blocks used by the demo shells. The vertical navigation selector is now `sidebar` and the projected sidebar slots use `sidebar-header` and `sidebar-footer`.
|
|
39
|
+
|
|
40
|
+
```html
|
|
41
|
+
<sidebar [ariaLabel]="'Primary'" [appearance]="'default'">
|
|
42
|
+
<div sidebar-header>Brand</div>
|
|
43
|
+
<div sidebar-footer>Footer actions</div>
|
|
44
|
+
</sidebar>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Register items through `NavigationService.registerItems(...)`, or pass them directly with the `items` input when composing a local navigation tree.
|
|
48
|
+
|
|
36
49
|
## SDK generator in a consumer workspace
|
|
37
50
|
|
|
38
51
|
After `@ojiepermana/angular` is installed, a consumer workspace can scaffold an
|
package/brand/etos/README.md
CHANGED
|
@@ -2,12 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
Etos implementation lives under `projects/angular/brand/etos`. Published consumers should use `@ojiepermana/angular/etos`.
|
|
4
4
|
|
|
5
|
+
This package is the Etos-specific layer on top of the shared Angular libraries. It owns the Etos brand defaults, shell composition, brand stylesheet, and Etos-only UI such as the profile/theme switcher.
|
|
6
|
+
|
|
5
7
|
Use this folder for Etos-specific implementation:
|
|
6
8
|
|
|
7
|
-
- `core/` contains
|
|
9
|
+
- `core/` contains brand defaults and provider composition.
|
|
10
|
+
- `component/` contains Etos-owned UI such as `EtosThemeSwitcherComponent`.
|
|
11
|
+
- `shells/` contains `EtosLayoutComponent` and the Etos empty, horizontal, and vertical shells.
|
|
8
12
|
- `themes/` contains Etos color, style, layout, and component-facing CSS.
|
|
9
|
-
- `
|
|
10
|
-
- `navigation/`, `components/`, `assets/`, and `docs/` can be added when Etos needs brand-specific behavior beyond shared primitives.
|
|
13
|
+
- `navigation/`, `assets/`, and `docs/` can be added when Etos needs brand-specific behavior beyond shared primitives.
|
|
11
14
|
|
|
12
15
|
Shared services, types, and primitives stay in the generic libraries:
|
|
13
16
|
|
|
@@ -15,96 +18,87 @@ Shared services, types, and primitives stay in the generic libraries:
|
|
|
15
18
|
- `@ojiepermana/angular/layout`
|
|
16
19
|
- `@ojiepermana/angular/navigation`
|
|
17
20
|
|
|
18
|
-
##
|
|
21
|
+
## Public entrypoint
|
|
19
22
|
|
|
20
23
|
Published consumers should import Etos through the short public entrypoint:
|
|
21
24
|
|
|
22
25
|
```ts
|
|
23
26
|
import {
|
|
24
|
-
|
|
25
|
-
EtosHorizontalLayoutComponent,
|
|
27
|
+
EtosLayoutComponent,
|
|
26
28
|
EtosThemeSwitcherComponent,
|
|
27
|
-
EtosVerticalLayoutComponent,
|
|
28
29
|
provideEtosBrand,
|
|
30
|
+
provideEtosLayout,
|
|
31
|
+
provideEtosTheme,
|
|
32
|
+
type EtosBrandOptions,
|
|
33
|
+
type EtosThemeSwitcherQuickAction,
|
|
34
|
+
type EtosThemeSwitcherUserInfo,
|
|
29
35
|
} from '@ojiepermana/angular/etos';
|
|
30
|
-
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
`@ojiepermana/angular/etos` currently exports:
|
|
39
|
+
|
|
40
|
+
- `provideEtosBrand()` to apply the Etos theme and layout defaults together and optionally register navigation items.
|
|
41
|
+
- `provideEtosTheme()` to install only the Etos theme wrapper over the shared theme provider.
|
|
42
|
+
- `provideEtosLayout()` to install only the Etos layout wrapper over the shared layout provider.
|
|
43
|
+
- `EtosLayoutComponent` to render the Etos shell from the current layout mode.
|
|
44
|
+
- `EtosThemeSwitcherComponent` and related types for the profile/preferences UI.
|
|
45
|
+
|
|
46
|
+
## Provider setup
|
|
47
|
+
|
|
48
|
+
Etos ships with these defaults:
|
|
49
|
+
|
|
50
|
+
- Theme defaults to brand `etos` with light mode.
|
|
51
|
+
- Layout defaults to `vertical` mode with `container` width.
|
|
52
|
+
|
|
53
|
+
Recommended provider configuration:
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
import { ApplicationConfig, provideBrowserGlobalErrorListeners } from '@angular/core';
|
|
57
|
+
import { provideRouter } from '@angular/router';
|
|
58
|
+
import { type EtosBrandOptions, provideEtosBrand } from '@ojiepermana/angular/etos';
|
|
59
|
+
|
|
60
|
+
import { AppNavigation } from './app.navigation';
|
|
61
|
+
import { routes } from './app.routes';
|
|
31
62
|
|
|
32
63
|
export const etosBrandConfig = {
|
|
33
64
|
theme: {
|
|
34
65
|
mode: 'light',
|
|
35
|
-
style: 'default',
|
|
36
66
|
},
|
|
37
67
|
layout: {
|
|
38
68
|
mode: 'vertical',
|
|
39
|
-
width: 'fixed',
|
|
40
69
|
},
|
|
70
|
+
navigation: AppNavigation,
|
|
41
71
|
} satisfies EtosBrandOptions;
|
|
42
72
|
|
|
43
|
-
export const appConfig = {
|
|
44
|
-
providers: [provideEtosBrand(etosBrandConfig)],
|
|
73
|
+
export const appConfig: ApplicationConfig = {
|
|
74
|
+
providers: [provideBrowserGlobalErrorListeners(), provideRouter(routes), provideEtosBrand(etosBrandConfig)],
|
|
45
75
|
};
|
|
46
76
|
```
|
|
47
77
|
|
|
48
|
-
`provideEtosBrand()`
|
|
78
|
+
`provideEtosBrand()` accepts these Etos-specific options:
|
|
79
|
+
|
|
80
|
+
- `theme` merges into the shared Material theme config while keeping the Etos brand tokens.
|
|
81
|
+
- `layout` merges into the shared Material layout config while keeping the Etos layout defaults.
|
|
82
|
+
- `navigation` registers navigation items during application startup.
|
|
83
|
+
- `navigationId` targets a non-default navigation registry id when needed.
|
|
84
|
+
- `materialDefaults` defaults to `true`; set it to `false` to skip `withMaterialDefaults()`.
|
|
85
|
+
|
|
86
|
+
Use the granular providers when the consumer only needs one part of the Etos stack:
|
|
49
87
|
|
|
50
88
|
```ts
|
|
51
|
-
@
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
<div ui-layout-profile>
|
|
58
|
-
<etos-theme-switcher
|
|
59
|
-
[userInfo]="profileInfo"
|
|
60
|
-
[quickActions]="horizontalQuickActions"
|
|
61
|
-
[notificationShortcut]="horizontalNotificationShortcut" />
|
|
62
|
-
</div>
|
|
63
|
-
</etos-horizontal-layout>
|
|
64
|
-
}
|
|
65
|
-
@default {
|
|
66
|
-
<etos-vertical-layout>
|
|
67
|
-
<div ui-sidebar-footer class="flex items-center gap-3">
|
|
68
|
-
<etos-theme-switcher [userInfo]="profileInfo" [quickActions]="verticalQuickActions" popoverAlign="start" />
|
|
69
|
-
|
|
70
|
-
<div class="flex flex-col gap-px">
|
|
71
|
-
<span>Ojie Permana</span>
|
|
72
|
-
<span>Etos design system navigator</span>
|
|
73
|
-
</div>
|
|
74
|
-
</div>
|
|
75
|
-
</etos-vertical-layout>
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
`,
|
|
79
|
-
})
|
|
80
|
-
export class Pages {
|
|
81
|
-
protected readonly layoutMode = inject(LayoutService).mode;
|
|
82
|
-
protected readonly profileInfo = {
|
|
83
|
-
name: 'Ojie Permana',
|
|
84
|
-
subtitle: 'Etos design system navigator',
|
|
85
|
-
avatarSrc: '/avatar-ojie.svg',
|
|
86
|
-
avatarAlt: 'Portrait of Ojie Permana',
|
|
87
|
-
};
|
|
88
|
-
protected readonly horizontalQuickActions = [
|
|
89
|
-
{ value: 'sign-out', label: 'Logout', icon: 'logout', tone: 'destructive' },
|
|
90
|
-
];
|
|
91
|
-
protected readonly verticalQuickActions = [
|
|
92
|
-
{ value: 'notifications', label: 'Notifications', icon: 'notifications' },
|
|
93
|
-
{ value: 'sign-out', label: 'Logout', icon: 'logout', tone: 'destructive' },
|
|
94
|
-
];
|
|
95
|
-
protected readonly horizontalNotificationShortcut = {
|
|
96
|
-
value: 'notifications',
|
|
97
|
-
icon: 'notifications',
|
|
98
|
-
ariaLabel: 'Open notifications for Ojie Permana',
|
|
99
|
-
};
|
|
100
|
-
}
|
|
89
|
+
import { ApplicationConfig } from '@angular/core';
|
|
90
|
+
import { provideEtosLayout, provideEtosTheme } from '@ojiepermana/angular/etos';
|
|
91
|
+
|
|
92
|
+
export const appConfig: ApplicationConfig = {
|
|
93
|
+
providers: [provideEtosTheme(), provideEtosLayout({ mode: 'horizontal', width: 'wide' })],
|
|
94
|
+
};
|
|
101
95
|
```
|
|
102
96
|
|
|
103
97
|
## Using the brand theme
|
|
104
98
|
|
|
105
99
|
The Etos brand theme has two parts:
|
|
106
100
|
|
|
107
|
-
- TypeScript setup through
|
|
101
|
+
- TypeScript setup through one of the Etos providers.
|
|
108
102
|
- CSS setup through the Etos stylesheet so the `theme-brand="etos"` tokens are available at runtime.
|
|
109
103
|
|
|
110
104
|
App CSS should import the Etos package stylesheet before Tailwind:
|
|
@@ -115,68 +109,100 @@ App CSS should import the Etos package stylesheet before Tailwind:
|
|
|
115
109
|
@import '@ojiepermana/angular/theme/tailwind/theme.css';
|
|
116
110
|
```
|
|
117
111
|
|
|
118
|
-
|
|
112
|
+
## Using the layout shell
|
|
113
|
+
|
|
114
|
+
`EtosLayoutComponent` is the exported shell component for Etos. It resolves `empty`, `horizontal`, or `vertical` from its `mode` input or from `LayoutService` when the input is omitted.
|
|
115
|
+
|
|
116
|
+
This is the same composition pattern used by the Etos demo:
|
|
119
117
|
|
|
120
118
|
```ts
|
|
121
|
-
import {
|
|
119
|
+
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
|
120
|
+
import { RouterLink } from '@angular/router';
|
|
121
|
+
import {
|
|
122
|
+
EtosLayoutComponent,
|
|
123
|
+
type EtosThemeSwitcherQuickAction,
|
|
124
|
+
EtosThemeSwitcherComponent,
|
|
125
|
+
type EtosThemeSwitcherUserInfo,
|
|
126
|
+
} from '@ojiepermana/angular/etos';
|
|
122
127
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
128
|
+
@Component({
|
|
129
|
+
selector: 'app-pages',
|
|
130
|
+
imports: [RouterLink, EtosLayoutComponent, EtosThemeSwitcherComponent],
|
|
131
|
+
template: `
|
|
132
|
+
<ng-template #layoutBrand>
|
|
133
|
+
<a routerLink="/" class="flex min-w-0 items-center gap-3 px-2 py-1.5 transition-colors">
|
|
134
|
+
<span class="text-sm font-semibold leading-none tracking-tight">Ojiepermana UI</span>
|
|
135
|
+
</a>
|
|
136
|
+
</ng-template>
|
|
137
|
+
|
|
138
|
+
<ng-template #layoutPanel>
|
|
139
|
+
<div class="flex h-full w-full min-w-0 items-center justify-start gap-3 px-2 py-0">
|
|
140
|
+
<etos-theme-switcher [userInfo]="profileInfo" [quickActions]="quickActions" />
|
|
141
|
+
|
|
142
|
+
<div class="min-w-0 flex flex-col gap-px">
|
|
143
|
+
<span class="truncate text-sm font-semibold leading-none text-foreground">{{ profileName }}</span>
|
|
144
|
+
<span class="truncate text-xs leading-none text-muted-foreground">{{ profileTitle }}</span>
|
|
145
|
+
</div>
|
|
146
|
+
</div>
|
|
147
|
+
</ng-template>
|
|
148
|
+
|
|
149
|
+
<etos-layout [layoutBrandTemplate]="layoutBrand" [layoutProfileTemplate]="layoutPanel" />
|
|
150
|
+
`,
|
|
151
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
152
|
+
})
|
|
153
|
+
export class Pages {
|
|
154
|
+
protected readonly profileName = 'Ojie Permana';
|
|
155
|
+
protected readonly profileTitle = 'Etos design system navigator';
|
|
156
|
+
protected readonly profileInfo = {
|
|
157
|
+
name: this.profileName,
|
|
158
|
+
subtitle: this.profileTitle,
|
|
159
|
+
avatarSrc: '/avatar-ojie.svg',
|
|
160
|
+
avatarAlt: 'Portrait of Ojie Permana',
|
|
161
|
+
} satisfies EtosThemeSwitcherUserInfo;
|
|
133
162
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
}
|
|
163
|
+
protected readonly quickActions = [
|
|
164
|
+
{ value: 'notifications', label: 'Notifications', icon: 'notifications' },
|
|
165
|
+
{ value: 'sign-out', label: 'Logout', icon: 'logout', tone: 'destructive' },
|
|
166
|
+
] satisfies readonly EtosThemeSwitcherQuickAction[];
|
|
167
|
+
}
|
|
137
168
|
```
|
|
138
169
|
|
|
139
|
-
|
|
170
|
+
Layout inputs:
|
|
140
171
|
|
|
141
|
-
|
|
172
|
+
- `mode`: optional explicit override for the active layout mode.
|
|
173
|
+
- `layoutBrandTemplate`: used in the horizontal brand area and as the default vertical sidebar header.
|
|
174
|
+
- `layoutProfileTemplate`: used in the horizontal profile area and as the default vertical sidebar footer.
|
|
175
|
+
- `sidebarHeaderTemplate`: optional vertical-only override for the sidebar header.
|
|
176
|
+
- `sidebarFooterTemplate`: optional vertical-only override for the sidebar footer.
|
|
142
177
|
|
|
143
|
-
|
|
178
|
+
That fallback behavior means a single `layoutBrandTemplate` and `layoutProfileTemplate` pair is enough for most consumers, while vertical layouts can still diverge when needed.
|
|
144
179
|
|
|
145
|
-
|
|
180
|
+
## Using the theme switcher
|
|
146
181
|
|
|
147
|
-
|
|
148
|
-
- `quickActions`: required array of action items rendered in the popup footer.
|
|
149
|
-
- `notificationShortcut`: object input for the standalone notification trigger shown beside the avatar in horizontal mode.
|
|
150
|
-
- `popoverAlign` and `popoverSide`: override the popover anchor position.
|
|
151
|
-
- `showNotificationShortcut`: legacy boolean shortcut for rendering the default notification button. Prefer `notificationShortcut` when the data should come from the parent.
|
|
182
|
+
`EtosThemeSwitcherComponent` is exported from `@ojiepermana/angular/etos` and is intended to live inside the Etos shell profile area or any consumer-owned profile trigger.
|
|
152
183
|
|
|
153
|
-
|
|
184
|
+
Common inputs and output:
|
|
154
185
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
```
|
|
186
|
+
- `quickActions`: required array rendered in the popup footer. Pass `[]` if you only want the built-in theme and layout controls.
|
|
187
|
+
- `userInfo`: object input for `name`, `subtitle`, `avatarSrc`, and `avatarAlt`.
|
|
188
|
+
- `userName`, `userSubtitle`, `avatarSrc`, and `avatarAlt`: fallback inputs when `userInfo` is not supplied.
|
|
189
|
+
- `notificationShortcut`: configures the standalone notification trigger shown beside the avatar.
|
|
190
|
+
- `showNotificationShortcut`: legacy boolean shortcut for rendering the default notification button.
|
|
191
|
+
- `popoverSide`, `popoverAlign`, and `popoverSideOffset`: explicit popover placement overrides.
|
|
192
|
+
- `actionSelected`: emits the selected quick action or notification shortcut value.
|
|
163
193
|
|
|
164
|
-
|
|
194
|
+
The popup always exposes theme scheme, layout mode, and layout width controls. The quick action area is fully consumer-driven:
|
|
195
|
+
|
|
196
|
+
- Provide the action values and labels you need in `quickActions`.
|
|
197
|
+
- Handle actions such as logout in the app consumer through `(actionSelected)`.
|
|
198
|
+
- When `notificationShortcut.value` matches one of the `quickActions` values, the matching popup item is removed to avoid duplication.
|
|
165
199
|
|
|
166
|
-
|
|
200
|
+
Popover defaults now follow the active layout automatically:
|
|
167
201
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
<etos-theme-switcher [userInfo]="profileInfo" [quickActions]="verticalQuickActions" popoverAlign="start" />
|
|
171
|
-
|
|
172
|
-
<div class="min-w-0 flex flex-col gap-px">
|
|
173
|
-
<span class="truncate text-sm font-semibold leading-none text-foreground">Ojie Permana</span>
|
|
174
|
-
<span class="truncate text-xs leading-none text-muted-foreground">Etos design system navigator</span>
|
|
175
|
-
</div>
|
|
176
|
-
</div>
|
|
177
|
-
```
|
|
202
|
+
- Vertical layout defaults to `side="top"` and `align="start"`.
|
|
203
|
+
- Horizontal and empty layouts default to `side="bottom"` and `align="end"`.
|
|
178
204
|
|
|
179
|
-
|
|
205
|
+
Only pass `popoverSide`, `popoverAlign`, or `popoverSideOffset` when you need to override those defaults.
|
|
180
206
|
|
|
181
207
|
Input shape examples:
|
|
182
208
|
|
|
@@ -188,30 +214,24 @@ profileInfo = {
|
|
|
188
214
|
avatarAlt: 'Portrait of Ojie Permana',
|
|
189
215
|
};
|
|
190
216
|
|
|
191
|
-
|
|
217
|
+
notificationShortcut = {
|
|
192
218
|
value: 'notifications',
|
|
193
219
|
icon: 'notifications',
|
|
194
220
|
ariaLabel: 'Open notifications for Ojie Permana',
|
|
195
221
|
};
|
|
196
222
|
|
|
197
|
-
|
|
223
|
+
quickActions = [
|
|
198
224
|
{ value: 'notifications', label: 'Notifications', icon: 'notifications' },
|
|
199
225
|
{ value: 'sign-out', label: 'Logout', icon: 'logout', tone: 'destructive' },
|
|
200
226
|
];
|
|
201
227
|
```
|
|
202
228
|
|
|
203
|
-
The popup always exposes theme scheme, layout mode, and layout width controls. The quick action area is fully consumer-driven:
|
|
204
|
-
|
|
205
|
-
- Provide the action values and labels you need in `quickActions`.
|
|
206
|
-
- Handle actions such as logout in the app consumer through `(actionSelected)`.
|
|
207
|
-
- When `notificationShortcut.value` matches one of the `quickActions` values, the matching popup item is removed to avoid duplication.
|
|
208
|
-
|
|
209
229
|
Example consumer-owned action handling:
|
|
210
230
|
|
|
211
231
|
```html
|
|
212
232
|
<etos-theme-switcher
|
|
213
233
|
[userInfo]="profileInfo"
|
|
214
|
-
[quickActions]="
|
|
234
|
+
[quickActions]="quickActions"
|
|
215
235
|
(actionSelected)="onThemeSwitcherAction($event)" />
|
|
216
236
|
```
|
|
217
237
|
|
|
@@ -225,10 +245,10 @@ onThemeSwitcherAction(action: string): void {
|
|
|
225
245
|
|
|
226
246
|
## Workspace usage in this repository
|
|
227
247
|
|
|
228
|
-
The Etos demo under `projects/demo/etos` already uses the short TypeScript entrypoint:
|
|
248
|
+
The Etos demo under `projects/demo/etos` already uses the short TypeScript entrypoint for provider setup and shell composition:
|
|
229
249
|
|
|
230
|
-
- `src/app/app.config.ts` imports `provideEtosBrand`
|
|
231
|
-
- `src/pages/pages.ts` imports `
|
|
250
|
+
- `src/app/app.config.ts` imports `provideEtosBrand` and passes `navigation: AppNavigation`.
|
|
251
|
+
- `src/pages/pages.ts` imports `EtosLayoutComponent` and `EtosThemeSwitcherComponent` and wires `layoutBrandTemplate` plus `layoutProfileTemplate`.
|
|
232
252
|
|
|
233
253
|
For CSS, the workspace demo currently imports the Etos source stylesheet directly:
|
|
234
254
|
|
package/etos/styles/color.css
CHANGED
|
@@ -3,6 +3,27 @@
|
|
|
3
3
|
*/
|
|
4
4
|
@layer tokens {
|
|
5
5
|
[theme-brand='etos'] {
|
|
6
|
+
--brand: 0 0% 64%;
|
|
7
|
+
--brand-border-alpha: 0.7;
|
|
8
|
+
--brand-background-alpha: 0.7;
|
|
9
|
+
|
|
10
|
+
--background: 210 38% 98%;
|
|
11
|
+
--surface: 0 0% 89.8%;
|
|
12
|
+
--surface-foreground: 211 56% 12%;
|
|
13
|
+
--foreground: 211 56% 12%;
|
|
14
|
+
|
|
15
|
+
--card: 0 0% 100%;
|
|
16
|
+
--card-foreground: 211 56% 12%;
|
|
17
|
+
|
|
18
|
+
--popover: 0 0% 100%;
|
|
19
|
+
--popover-foreground: 211 56% 12%;
|
|
20
|
+
|
|
21
|
+
--muted: 211 34% 94%;
|
|
22
|
+
--muted-foreground: 211 24% 38%;
|
|
23
|
+
|
|
24
|
+
--border: 211 28% 82%;
|
|
25
|
+
--input: 211 28% 82%;
|
|
26
|
+
|
|
6
27
|
--primary: 211 95% 29%;
|
|
7
28
|
--primary-foreground: 0 0% 100%;
|
|
8
29
|
--accent: 211 95% 96%;
|
|
@@ -13,9 +34,40 @@
|
|
|
13
34
|
}
|
|
14
35
|
|
|
15
36
|
[data-mode='dark'][theme-brand='etos'] {
|
|
37
|
+
--brand: 0 0% 64%;
|
|
38
|
+
--brand-border-alpha: 0.45;
|
|
39
|
+
--brand-background-alpha: 0.55;
|
|
40
|
+
|
|
41
|
+
--background: 211 38% 9%;
|
|
42
|
+
--surface: 211 22% 18%;
|
|
43
|
+
--surface-foreground: 210 40% 96%;
|
|
44
|
+
--foreground: 210 40% 96%;
|
|
45
|
+
|
|
46
|
+
--card: 211 34% 11%;
|
|
47
|
+
--card-foreground: 210 40% 96%;
|
|
48
|
+
|
|
49
|
+
--popover: 211 34% 11%;
|
|
50
|
+
--popover-foreground: 210 40% 96%;
|
|
51
|
+
|
|
52
|
+
--muted: 211 22% 18%;
|
|
53
|
+
--muted-foreground: 211 18% 70%;
|
|
54
|
+
|
|
55
|
+
--border: 211 24% 24%;
|
|
56
|
+
--input: 211 24% 24%;
|
|
57
|
+
|
|
16
58
|
--accent: 211 58% 18%;
|
|
17
59
|
--accent-foreground: 211 90% 84%;
|
|
18
60
|
--secondary: 211 24% 18%;
|
|
19
61
|
--secondary-foreground: 211 82% 84%;
|
|
20
62
|
}
|
|
21
63
|
}
|
|
64
|
+
|
|
65
|
+
@layer utilities {
|
|
66
|
+
.border-brand {
|
|
67
|
+
border-color: hsl(var(--brand, var(--border)) / var(--brand-border-alpha, 0.7));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.bg-brand {
|
|
71
|
+
background-color: hsl(var(--brand, var(--border)) / var(--brand-background-alpha, 0.7));
|
|
72
|
+
}
|
|
73
|
+
}
|
package/etos/styles/layout.css
CHANGED
|
@@ -19,168 +19,3 @@
|
|
|
19
19
|
--etos-layout-frame-shadow: 0 0 0 1px hsl(var(--border));
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
|
-
|
|
23
|
-
@layer components {
|
|
24
|
-
.etos-layout-host {
|
|
25
|
-
display: block;
|
|
26
|
-
height: 100dvh;
|
|
27
|
-
width: 100%;
|
|
28
|
-
overflow: hidden;
|
|
29
|
-
background: hsl(var(--background));
|
|
30
|
-
color: hsl(var(--foreground));
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
.etos-layout-host--fixed {
|
|
34
|
-
box-sizing: border-box;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
.etos-layout-frame {
|
|
38
|
-
display: flex;
|
|
39
|
-
height: 100%;
|
|
40
|
-
width: 100%;
|
|
41
|
-
overflow: hidden;
|
|
42
|
-
background: hsl(var(--background));
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
.etos-layout-frame--horizontal {
|
|
46
|
-
flex-direction: column;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
.etos-layout-main {
|
|
50
|
-
min-width: 0;
|
|
51
|
-
flex: 1 1 0%;
|
|
52
|
-
overflow: auto;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
.etos-layout-main--fixed {
|
|
56
|
-
width: 100%;
|
|
57
|
-
max-width: var(--etos-layout-main-max-width);
|
|
58
|
-
margin-inline: auto;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
.etos-layout-topbar {
|
|
62
|
-
width: 100%;
|
|
63
|
-
flex-shrink: 0;
|
|
64
|
-
border-bottom: var(--border-width) solid hsl(var(--border));
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
.etos-layout-topbar-slot {
|
|
68
|
-
display: flex;
|
|
69
|
-
min-width: 0;
|
|
70
|
-
align-items: center;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
.etos-layout-topbar-slot--end {
|
|
74
|
-
justify-content: flex-end;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
.etos-layout-empty-host {
|
|
78
|
-
display: flex;
|
|
79
|
-
min-height: 100dvh;
|
|
80
|
-
width: 100%;
|
|
81
|
-
align-items: center;
|
|
82
|
-
justify-content: center;
|
|
83
|
-
padding: var(--etos-layout-empty-padding);
|
|
84
|
-
background: hsl(var(--background));
|
|
85
|
-
color: hsl(var(--foreground));
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
.etos-layout-empty-main {
|
|
89
|
-
width: 100%;
|
|
90
|
-
max-width: var(--etos-layout-empty-max-width);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
.etos-brand-link,
|
|
94
|
-
.etos-profile-trigger {
|
|
95
|
-
display: inline-flex;
|
|
96
|
-
align-items: center;
|
|
97
|
-
gap: 0.75rem;
|
|
98
|
-
min-height: 2.5rem;
|
|
99
|
-
padding: 0.375rem 0.5rem;
|
|
100
|
-
color: hsl(var(--foreground));
|
|
101
|
-
text-decoration: none;
|
|
102
|
-
transition:
|
|
103
|
-
color 160ms ease,
|
|
104
|
-
background-color 160ms ease;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
.etos-brand-link:focus-visible,
|
|
108
|
-
.etos-profile-trigger:focus-visible {
|
|
109
|
-
outline: 2px solid hsl(var(--ring));
|
|
110
|
-
outline-offset: 2px;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
.etos-brand-mark,
|
|
114
|
-
.etos-profile-mark {
|
|
115
|
-
display: inline-flex;
|
|
116
|
-
height: var(--etos-layout-brand-mark-size);
|
|
117
|
-
width: var(--etos-layout-brand-mark-size);
|
|
118
|
-
align-items: center;
|
|
119
|
-
justify-content: center;
|
|
120
|
-
border-radius: var(--radius-md);
|
|
121
|
-
background: hsl(var(--primary));
|
|
122
|
-
color: hsl(var(--primary-foreground));
|
|
123
|
-
font-size: 0.7rem;
|
|
124
|
-
font-weight: 700;
|
|
125
|
-
letter-spacing: 0.18em;
|
|
126
|
-
line-height: 1;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
.etos-profile-mark {
|
|
130
|
-
border-radius: 999px;
|
|
131
|
-
letter-spacing: 0;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
.etos-brand-copy {
|
|
135
|
-
display: none;
|
|
136
|
-
min-width: 0;
|
|
137
|
-
flex-direction: column;
|
|
138
|
-
gap: 0.125rem;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
.etos-brand-name {
|
|
142
|
-
font-size: var(--text-sm);
|
|
143
|
-
font-weight: 700;
|
|
144
|
-
line-height: 1;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
.etos-brand-subtitle,
|
|
148
|
-
.etos-profile-name {
|
|
149
|
-
font-size: var(--text-xs);
|
|
150
|
-
line-height: 1;
|
|
151
|
-
color: hsl(var(--muted-foreground));
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
.etos-profile-name {
|
|
155
|
-
display: none;
|
|
156
|
-
font-weight: 600;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
@media (min-width: 40rem) {
|
|
160
|
-
.etos-brand-copy,
|
|
161
|
-
.etos-profile-name {
|
|
162
|
-
display: flex;
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
@media (min-width: 64rem) {
|
|
167
|
-
.etos-layout-host--fixed {
|
|
168
|
-
padding: var(--etos-layout-shell-padding);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
.etos-layout-frame--vertical-fixed {
|
|
172
|
-
max-width: var(--etos-layout-vertical-shell-max-width);
|
|
173
|
-
margin-inline: auto;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
.etos-layout-frame--fixed {
|
|
177
|
-
border: var(--border-width) solid hsl(var(--border));
|
|
178
|
-
border-radius: var(--etos-layout-frame-radius);
|
|
179
|
-
box-shadow: var(--etos-layout-frame-shadow);
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
.etos-layout-main--vertical-fixed {
|
|
183
|
-
margin-inline: 0;
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
}
|