@hearthsound/design 0.0.0-stage → 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/LICENSE +21 -0
- package/README.md +132 -2
- package/THIRD-PARTY.md +46 -0
- package/css/base.css +245 -0
- package/css/components/admin.css +257 -0
- package/css/components/banner.css +140 -0
- package/css/components/button.css +309 -0
- package/css/components/card.css +339 -0
- package/css/components/check.css +202 -0
- package/css/components/dialog.css +85 -0
- package/css/components/field.css +296 -0
- package/css/components/list.css +260 -0
- package/css/components/menu.css +282 -0
- package/css/components/page-header.css +230 -0
- package/css/components/pill.css +101 -0
- package/css/components/player.css +524 -0
- package/css/components/progress.css +173 -0
- package/css/components/section.css +86 -0
- package/css/components/segmented.css +64 -0
- package/css/components/shell.css +281 -0
- package/css/components/sidebar.css +170 -0
- package/css/components/slider.css +92 -0
- package/css/components/status-page.css +48 -0
- package/css/components/stepper.css +130 -0
- package/css/components/toast.css +88 -0
- package/css/components/tooltip.css +29 -0
- package/css/components/track.css +336 -0
- package/css/components/upload.css +70 -0
- package/css/index.css +35 -0
- package/css/tokens.css +375 -0
- package/dist/icons.d.ts +56 -0
- package/dist/icons.js +56 -0
- package/dist/icons.svg +55 -0
- package/fonts/OFL-BricolageGrotesque.txt +93 -0
- package/fonts/OFL-Geist.txt +92 -0
- package/fonts/bricolage-var.woff2 +0 -0
- package/fonts/geist-mono.woff2 +0 -0
- package/fonts/geist-var.woff2 +0 -0
- package/icons/LICENSE +10 -0
- package/icons/adwaita-account.svg +1 -0
- package/icons/adwaita-acquire.svg +1 -0
- package/icons/adwaita-add.svg +1 -0
- package/icons/adwaita-album.svg +1 -0
- package/icons/adwaita-artist.svg +1 -0
- package/icons/adwaita-back.svg +1 -0
- package/icons/adwaita-check.svg +1 -0
- package/icons/adwaita-close.svg +1 -0
- package/icons/adwaita-collapse.svg +1 -0
- package/icons/adwaita-dark-mode.svg +1 -0
- package/icons/adwaita-delete.svg +1 -0
- package/icons/adwaita-drag.svg +1 -0
- package/icons/adwaita-edit.svg +1 -0
- package/icons/adwaita-error.svg +1 -0
- package/icons/adwaita-expand.svg +1 -0
- package/icons/adwaita-folder.svg +1 -0
- package/icons/adwaita-forward.svg +1 -0
- package/icons/adwaita-home.svg +1 -0
- package/icons/adwaita-layers.svg +1 -0
- package/icons/adwaita-like.svg +1 -0
- package/icons/adwaita-lock.svg +1 -0
- package/icons/adwaita-menu.svg +1 -0
- package/icons/adwaita-more.svg +1 -0
- package/icons/adwaita-mute.svg +1 -0
- package/icons/adwaita-next.svg +1 -0
- package/icons/adwaita-pause.svg +1 -0
- package/icons/adwaita-play.svg +1 -0
- package/icons/adwaita-playlist.svg +1 -0
- package/icons/adwaita-plugin.svg +1 -0
- package/icons/adwaita-previous.svg +1 -0
- package/icons/adwaita-queue.svg +1 -0
- package/icons/adwaita-rating-outline.svg +1 -0
- package/icons/adwaita-rating.svg +1 -0
- package/icons/adwaita-refresh.svg +1 -0
- package/icons/adwaita-remote.svg +1 -0
- package/icons/adwaita-remove.svg +1 -0
- package/icons/adwaita-repeat.svg +1 -0
- package/icons/adwaita-reveal.svg +1 -0
- package/icons/adwaita-search.svg +1 -0
- package/icons/adwaita-settings.svg +1 -0
- package/icons/adwaita-shuffle.svg +1 -0
- package/icons/adwaita-sign-out.svg +1 -0
- package/icons/adwaita-song.svg +1 -0
- package/icons/adwaita-sort.svg +1 -0
- package/icons/adwaita-storage.svg +1 -0
- package/icons/adwaita-users.svg +1 -0
- package/icons/adwaita-volume.svg +1 -0
- package/icons/adwaita-warning.svg +1 -0
- package/icons/custom-dislike-outline.svg +1 -0
- package/icons/custom-dislike.svg +1 -0
- package/icons/custom-like-outline.svg +1 -0
- package/icons/custom-unknown.svg +1 -0
- package/icons/custom-upload.svg +1 -0
- package/identity/icons/app-icon-dark-16.png +0 -0
- package/identity/icons/app-icon-dark-180.png +0 -0
- package/identity/icons/app-icon-dark-192.png +0 -0
- package/identity/icons/app-icon-dark-32.png +0 -0
- package/identity/icons/app-icon-dark-512.png +0 -0
- package/identity/icons/app-icon-dark.svg +1 -0
- package/identity/icons/app-icon-light-16.png +0 -0
- package/identity/icons/app-icon-light-180.png +0 -0
- package/identity/icons/app-icon-light-192.png +0 -0
- package/identity/icons/app-icon-light-32.png +0 -0
- package/identity/icons/app-icon-light-512.png +0 -0
- package/identity/icons/app-icon-light.svg +1 -0
- package/identity/icons/favicon.svg +1 -0
- package/identity/mark/mark-dark.svg +1 -0
- package/identity/mark/mark-light.svg +1 -0
- package/identity/mark/mark-symbolic.svg +1 -0
- package/package.json +35 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Hearthsound contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,133 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @hearthsound/design
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The design language of Hearthsound: tokens, fonts, icons and component styles. It ships
|
|
4
|
+
plain CSS, so it works in any framework and needs no build step of its own.
|
|
5
|
+
|
|
6
|
+
## Install
|
|
7
|
+
|
|
8
|
+
```sh
|
|
9
|
+
npm install @hearthsound/design
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Import the stylesheet once per application:
|
|
13
|
+
|
|
14
|
+
```js
|
|
15
|
+
import '@hearthsound/design/index.css';
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
`index.css` pulls in `css/tokens.css`, `css/base.css` and every component stylesheet, in
|
|
19
|
+
that order. Individual files can be imported instead, for example
|
|
20
|
+
`@hearthsound/design/css/tokens.css`.
|
|
21
|
+
|
|
22
|
+
## Schemes: System, Light and Dark
|
|
23
|
+
|
|
24
|
+
The light scheme is the default. Dark follows the operating system unless the page
|
|
25
|
+
chooses otherwise. The choice is a `data-scheme` attribute, which may sit on `<html>` or
|
|
26
|
+
on any subtree:
|
|
27
|
+
|
|
28
|
+
| Attribute | Result |
|
|
29
|
+
|---|---|
|
|
30
|
+
| none | System: dark under `prefers-color-scheme: dark`, light otherwise |
|
|
31
|
+
| `data-scheme="light"` | Light, even on a dark system |
|
|
32
|
+
| `data-scheme="dark"` | Dark, even on a light system |
|
|
33
|
+
|
|
34
|
+
```html
|
|
35
|
+
<!-- System -->
|
|
36
|
+
<html>
|
|
37
|
+
<!-- Force light -->
|
|
38
|
+
<html data-scheme="light">
|
|
39
|
+
<!-- Force dark -->
|
|
40
|
+
<html data-scheme="dark">
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
There is one fixed brand accent; there is no accent attribute.
|
|
44
|
+
|
|
45
|
+
## Class naming
|
|
46
|
+
|
|
47
|
+
Components use BEM-like `hs-` classes:
|
|
48
|
+
|
|
49
|
+
- block: `hs-<component>` (for example `hs-button`, `hs-dialog`);
|
|
50
|
+
- element: `hs-<component>__<part>` (for example `hs-dialog__title`);
|
|
51
|
+
- modifier: `hs-<component>--<modifier>` (for example `hs-button--suggested`);
|
|
52
|
+
- utilities: the type scale (`hs-display`, `hs-title-1` to `hs-title-4`, `hs-heading`,
|
|
53
|
+
`hs-body`, `hs-caption`), `hs-link`, `hs-visually-hidden` and `hs-icon`.
|
|
54
|
+
|
|
55
|
+
State is expressed with real pseudo-classes and ARIA attributes, never helper classes:
|
|
56
|
+
`:hover`, `:focus-visible`, `:disabled`, `[aria-disabled="true"]`, `[aria-pressed="true"]`,
|
|
57
|
+
`[aria-selected="true"]`, `[aria-current]`, `[aria-busy="true"]`, `[aria-invalid="true"]`
|
|
58
|
+
and `[aria-expanded="true"]`. Focus is the approved tint-and-lift treatment shown on
|
|
59
|
+
`:focus-visible` only.
|
|
60
|
+
|
|
61
|
+
Style with the shipped tokens, not raw values:
|
|
62
|
+
|
|
63
|
+
```css
|
|
64
|
+
.my-shell {
|
|
65
|
+
background: var(--hs-view-bg);
|
|
66
|
+
color: var(--hs-fg);
|
|
67
|
+
padding: var(--hs-space-5);
|
|
68
|
+
border-radius: var(--hs-radius-card);
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Tokens cover colour, type, spacing, density, radii, elevation, focus, motion and artwork.
|
|
73
|
+
`css/tokens.css` is the complete list; the light values are the `:root` base and dark
|
|
74
|
+
values apply through the media query and the `data-scheme` attribute.
|
|
75
|
+
|
|
76
|
+
## Fonts
|
|
77
|
+
|
|
78
|
+
Three OFL faces ship in `fonts/` and are declared in `css/base.css`:
|
|
79
|
+
`Geist` (body, `--hs-font-body`), `Bricolage Grotesque` (display, `--hs-font-display`) and
|
|
80
|
+
`Geist Mono` (machine text, `--hs-font-mono`, ligatures off). The font files are loaded
|
|
81
|
+
relative to the stylesheet, so no path configuration is needed.
|
|
82
|
+
|
|
83
|
+
## Icons
|
|
84
|
+
|
|
85
|
+
The approved icon set ships as individual SVGs in `icons/` and as a generated sprite in
|
|
86
|
+
`dist/icons.svg`. Each source name in the manifest maps to a file name and symbol id by
|
|
87
|
+
replacing `/` with `-`:
|
|
88
|
+
|
|
89
|
+
- manifest `adwaita/play` -> `icons/adwaita-play.svg` -> symbol `#adwaita-play`;
|
|
90
|
+
- manifest `custom/upload` -> `icons/custom-upload.svg` -> symbol `#custom-upload`.
|
|
91
|
+
|
|
92
|
+
Use the sprite with the `hs-icon` base class:
|
|
93
|
+
|
|
94
|
+
```js
|
|
95
|
+
import sprite from '@hearthsound/design/icons.svg?url';
|
|
96
|
+
import { iconNames } from '@hearthsound/design/icons'; // string[]
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
```html
|
|
100
|
+
<svg class="hs-icon" aria-hidden="true">
|
|
101
|
+
<use href="/path/to/icons.svg#adwaita-play"></use>
|
|
102
|
+
</svg>
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
`hs-icon` is 16 px by default and inherits `currentColor`; set `--hs-icon-size` to resize
|
|
106
|
+
it. `@hearthsound/design/icons` exports `iconNames` and, in TypeScript, the `IconName`
|
|
107
|
+
union type. Give a labelled icon `role="img"` and an accessible name; otherwise mark it
|
|
108
|
+
`aria-hidden="true"`.
|
|
109
|
+
|
|
110
|
+
## Identity
|
|
111
|
+
|
|
112
|
+
The approved identity files ship unchanged:
|
|
113
|
+
|
|
114
|
+
- `identity/mark/mark-light.svg`, `mark-dark.svg`: the full-colour mark for each scheme.
|
|
115
|
+
- `identity/mark/mark-symbolic.svg`: the one-colour mark in `currentColor`.
|
|
116
|
+
- `identity/icons/app-icon-light.svg`, `app-icon-dark.svg`: 128 px masters.
|
|
117
|
+
- `identity/icons/app-icon-{light,dark}-{16,32,180,192,512}.png`: exported sizes.
|
|
118
|
+
- `identity/icons/favicon.svg`: one file that switches with `prefers-color-scheme`.
|
|
119
|
+
|
|
120
|
+
Use the full-colour mark only on its own scheme, keep a quarter of the mark's height as
|
|
121
|
+
clear space, and never rebuild a one-colour mark from the full-colour file: use
|
|
122
|
+
`mark-symbolic.svg`. Licence details are in `THIRD-PARTY.md`.
|
|
123
|
+
|
|
124
|
+
## Development
|
|
125
|
+
|
|
126
|
+
```sh
|
|
127
|
+
npm run build # writes dist/icons.svg, dist/icons.js and dist/icons.d.ts
|
|
128
|
+
npm run check # build, then verify tokens, imports, ASCII, fonts and icon refs
|
|
129
|
+
npm run specimen # build, then write the unpublished specimen/index.html
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
`specimen/index.html` shows every component in every state, light and dark side by side.
|
|
133
|
+
It is a development reference and is not published.
|
package/THIRD-PARTY.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Third-party notices
|
|
2
|
+
|
|
3
|
+
The package itself is MIT licensed; see `LICENSE`.
|
|
4
|
+
|
|
5
|
+
## Fonts
|
|
6
|
+
|
|
7
|
+
### Geist and Geist Mono
|
|
8
|
+
|
|
9
|
+
Copyright (c) 2023 Vercel, in collaboration with basement.studio.
|
|
10
|
+
|
|
11
|
+
Licensed under the SIL Open Font License, Version 1.1. The full licence text ships as
|
|
12
|
+
`fonts/OFL-Geist.txt`.
|
|
13
|
+
|
|
14
|
+
Files: `fonts/geist-var.woff2`, `fonts/geist-mono.woff2`.
|
|
15
|
+
|
|
16
|
+
### Bricolage Grotesque
|
|
17
|
+
|
|
18
|
+
Copyright 2022 The Bricolage Grotesque Project Authors
|
|
19
|
+
(https://github.com/ateliertriay/bricolage).
|
|
20
|
+
|
|
21
|
+
Licensed under the SIL Open Font License, Version 1.1. The full licence text ships as
|
|
22
|
+
`fonts/OFL-BricolageGrotesque.txt`.
|
|
23
|
+
|
|
24
|
+
File: `fonts/bricolage-var.woff2`.
|
|
25
|
+
|
|
26
|
+
## Icons
|
|
27
|
+
|
|
28
|
+
### Adwaita symbolic icons
|
|
29
|
+
|
|
30
|
+
Copyright the GNOME Project. The icons are licensed under the terms of either the GNU
|
|
31
|
+
LGPL v3 or the Creative Commons Attribution-Share Alike 3.0 United States License. The
|
|
32
|
+
full notice ships as `icons/LICENSE`. When attributing the artwork, "GNOME Project" is
|
|
33
|
+
enough; see http://www.gnome.org.
|
|
34
|
+
|
|
35
|
+
Files: every `icons/adwaita-*.svg`.
|
|
36
|
+
|
|
37
|
+
### Custom icons derived from Adwaita
|
|
38
|
+
|
|
39
|
+
`icons/custom-like-outline.svg`, `icons/custom-dislike-outline.svg`,
|
|
40
|
+
`icons/custom-dislike.svg`, `icons/custom-upload.svg` and `icons/custom-unknown.svg` are
|
|
41
|
+
drawn from Adwaita shapes and carry the same licence and attribution as the Adwaita set.
|
|
42
|
+
|
|
43
|
+
## Identity
|
|
44
|
+
|
|
45
|
+
The Hearthsound mark, app icons and favicon are original work of the Hearthsound
|
|
46
|
+
contributors and are covered by the package's MIT licence.
|
package/css/base.css
ADDED
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @hearthsound/design - base
|
|
3
|
+
*
|
|
4
|
+
* Fonts, reset, body typography, the type-scale classes (foundations.md 2.2),
|
|
5
|
+
* the focus indicator carrier, the icon base class and reduced motion.
|
|
6
|
+
* Component looks live in css/components/; this file only owns the page frame.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/* f01, f01b, f02, B09 - the three approved faces, shipped in fonts/. */
|
|
10
|
+
@font-face {
|
|
11
|
+
font-family: 'Geist';
|
|
12
|
+
src: url('../fonts/geist-var.woff2') format('woff2');
|
|
13
|
+
font-weight: 100 900;
|
|
14
|
+
font-style: normal;
|
|
15
|
+
font-display: swap;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
@font-face {
|
|
19
|
+
font-family: 'Bricolage Grotesque';
|
|
20
|
+
src: url('../fonts/bricolage-var.woff2') format('woff2');
|
|
21
|
+
font-weight: 200 800;
|
|
22
|
+
font-style: normal;
|
|
23
|
+
font-display: swap;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
@font-face {
|
|
27
|
+
font-family: 'Geist Mono';
|
|
28
|
+
src: url('../fonts/geist-mono.woff2') format('woff2');
|
|
29
|
+
font-weight: 100 900;
|
|
30
|
+
font-style: normal;
|
|
31
|
+
font-display: swap;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/* ------------------------------------------------------------------ */
|
|
35
|
+
/* Reset */
|
|
36
|
+
/* ------------------------------------------------------------------ */
|
|
37
|
+
|
|
38
|
+
*,
|
|
39
|
+
*::before,
|
|
40
|
+
*::after {
|
|
41
|
+
box-sizing: border-box;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
html {
|
|
45
|
+
-webkit-text-size-adjust: 100%;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
body {
|
|
49
|
+
margin: 0;
|
|
50
|
+
background: var(--hs-view-bg);
|
|
51
|
+
color: var(--hs-fg);
|
|
52
|
+
font-family: var(--hs-font-body);
|
|
53
|
+
font-size: var(--hs-type-body-size);
|
|
54
|
+
font-weight: var(--hs-type-body-weight);
|
|
55
|
+
line-height: var(--hs-type-body-lh);
|
|
56
|
+
letter-spacing: var(--hs-type-body-track);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
button,
|
|
60
|
+
input,
|
|
61
|
+
select,
|
|
62
|
+
textarea {
|
|
63
|
+
font: inherit;
|
|
64
|
+
color: inherit;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/* f02 - the mono face is shown with ligatures off. */
|
|
68
|
+
code,
|
|
69
|
+
kbd,
|
|
70
|
+
pre,
|
|
71
|
+
samp {
|
|
72
|
+
font-family: var(--hs-font-mono);
|
|
73
|
+
font-variant-ligatures: none;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/* ------------------------------------------------------------------ */
|
|
77
|
+
/* Type scale (f03, l07) */
|
|
78
|
+
/* ------------------------------------------------------------------ */
|
|
79
|
+
|
|
80
|
+
.hs-display {
|
|
81
|
+
font-family: var(--hs-font-display);
|
|
82
|
+
font-size: var(--hs-type-display-size);
|
|
83
|
+
font-weight: var(--hs-type-display-weight);
|
|
84
|
+
line-height: var(--hs-type-display-lh);
|
|
85
|
+
letter-spacing: var(--hs-type-display-track);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.hs-title-1 {
|
|
89
|
+
font-family: var(--hs-font-display);
|
|
90
|
+
font-size: var(--hs-type-title-1-size);
|
|
91
|
+
font-weight: var(--hs-type-title-1-weight);
|
|
92
|
+
line-height: var(--hs-type-title-1-lh);
|
|
93
|
+
letter-spacing: var(--hs-type-title-1-track);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.hs-title-2 {
|
|
97
|
+
font-family: var(--hs-font-display);
|
|
98
|
+
font-size: var(--hs-type-title-2-size);
|
|
99
|
+
font-weight: var(--hs-type-title-2-weight);
|
|
100
|
+
line-height: var(--hs-type-title-2-lh);
|
|
101
|
+
letter-spacing: var(--hs-type-title-2-track);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.hs-title-3 {
|
|
105
|
+
font-family: var(--hs-font-display);
|
|
106
|
+
font-size: var(--hs-type-title-3-size);
|
|
107
|
+
font-weight: var(--hs-type-title-3-weight);
|
|
108
|
+
line-height: var(--hs-type-title-3-lh);
|
|
109
|
+
letter-spacing: var(--hs-type-title-3-track);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.hs-title-4 {
|
|
113
|
+
font-family: var(--hs-font-display);
|
|
114
|
+
font-size: var(--hs-type-title-4-size);
|
|
115
|
+
font-weight: var(--hs-type-title-4-weight);
|
|
116
|
+
line-height: var(--hs-type-title-4-lh);
|
|
117
|
+
letter-spacing: var(--hs-type-title-4-track);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.hs-heading {
|
|
121
|
+
font-family: var(--hs-font-display);
|
|
122
|
+
font-size: var(--hs-type-heading-size);
|
|
123
|
+
font-weight: var(--hs-type-heading-weight);
|
|
124
|
+
line-height: var(--hs-type-heading-lh);
|
|
125
|
+
letter-spacing: var(--hs-type-heading-track);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.hs-body {
|
|
129
|
+
font-family: var(--hs-font-body);
|
|
130
|
+
font-size: var(--hs-type-body-size);
|
|
131
|
+
font-weight: var(--hs-type-body-weight);
|
|
132
|
+
line-height: var(--hs-type-body-lh);
|
|
133
|
+
letter-spacing: var(--hs-type-body-track);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.hs-caption {
|
|
137
|
+
font-family: var(--hs-font-body);
|
|
138
|
+
font-size: var(--hs-type-caption-size);
|
|
139
|
+
font-weight: var(--hs-type-caption-weight);
|
|
140
|
+
line-height: var(--hs-type-caption-lh);
|
|
141
|
+
letter-spacing: var(--hs-type-caption-track);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/* ------------------------------------------------------------------ */
|
|
145
|
+
/* Links (f06-r4) */
|
|
146
|
+
/* ------------------------------------------------------------------ */
|
|
147
|
+
|
|
148
|
+
a.link,
|
|
149
|
+
.hs-link {
|
|
150
|
+
color: var(--hs-accent-text);
|
|
151
|
+
font-weight: 500;
|
|
152
|
+
text-decoration-line: underline;
|
|
153
|
+
text-decoration-color: var(--hs-accent-bg);
|
|
154
|
+
text-decoration-thickness: 1px;
|
|
155
|
+
text-underline-offset: 2px;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/* f06-r4 - light raises the underline to 3 px at a 3 px offset. */
|
|
159
|
+
@media (prefers-color-scheme: light) {
|
|
160
|
+
:root:not([data-scheme='dark']) :where(a.link, .hs-link) {
|
|
161
|
+
text-decoration-thickness: 3px;
|
|
162
|
+
text-underline-offset: 3px;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
[data-scheme='light'] a.link,
|
|
167
|
+
[data-scheme='light'] .hs-link {
|
|
168
|
+
text-decoration-thickness: 3px;
|
|
169
|
+
text-underline-offset: 3px;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
[data-scheme='dark'] a.link,
|
|
173
|
+
[data-scheme='dark'] .hs-link {
|
|
174
|
+
text-decoration-thickness: 1px;
|
|
175
|
+
text-underline-offset: 2px;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/* f13-r3 - links take a tint background on keyboard focus. */
|
|
179
|
+
a.link:focus-visible,
|
|
180
|
+
.hs-link:focus-visible {
|
|
181
|
+
outline: none;
|
|
182
|
+
background: var(--hs-accent-tint);
|
|
183
|
+
color: var(--hs-accent-text);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/* ------------------------------------------------------------------ */
|
|
187
|
+
/* Focus */
|
|
188
|
+
/* ------------------------------------------------------------------ */
|
|
189
|
+
|
|
190
|
+
/*
|
|
191
|
+
* f13-r3, k01b, k03f: focus is the tint-and-lift treatment, never a ring,
|
|
192
|
+
* outline, underline, bar or dot. Each component owns its exact focus rule;
|
|
193
|
+
* this reset removes the user-agent ring so no component has to repeat it.
|
|
194
|
+
* Text-type fields keep --hs-control-tone and show focus through the caret
|
|
195
|
+
* (k03f); filled buttons deepen their fill (k01b).
|
|
196
|
+
*/
|
|
197
|
+
:focus-visible {
|
|
198
|
+
outline: none;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/* ------------------------------------------------------------------ */
|
|
202
|
+
/* Utilities */
|
|
203
|
+
/* ------------------------------------------------------------------ */
|
|
204
|
+
|
|
205
|
+
.hs-visually-hidden {
|
|
206
|
+
position: absolute;
|
|
207
|
+
width: 1px;
|
|
208
|
+
height: 1px;
|
|
209
|
+
margin: -1px;
|
|
210
|
+
padding: 0;
|
|
211
|
+
overflow: hidden;
|
|
212
|
+
clip: rect(0 0 0 0);
|
|
213
|
+
clip-path: inset(50%);
|
|
214
|
+
white-space: nowrap;
|
|
215
|
+
border: 0;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/*
|
|
219
|
+
* f12 A - every icon is an inline SVG using the shipped sprite. Size it with
|
|
220
|
+
* --hs-icon-size (16 px default); colour is inherited through currentColor.
|
|
221
|
+
*/
|
|
222
|
+
.hs-icon {
|
|
223
|
+
--hs-icon-size: 16px;
|
|
224
|
+
display: inline-block;
|
|
225
|
+
flex: none;
|
|
226
|
+
width: var(--hs-icon-size);
|
|
227
|
+
height: var(--hs-icon-size);
|
|
228
|
+
fill: currentColor;
|
|
229
|
+
vertical-align: middle;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/* ------------------------------------------------------------------ */
|
|
233
|
+
/* Reduced motion (f14b-r1) */
|
|
234
|
+
/* ------------------------------------------------------------------ */
|
|
235
|
+
|
|
236
|
+
/*
|
|
237
|
+
* The duration tokens are overridden to 0ms in tokens.css. Scrolling is
|
|
238
|
+
* immediate as well. Components set their own animation fallbacks (the
|
|
239
|
+
* spinner is the recorded k09-rm exception).
|
|
240
|
+
*/
|
|
241
|
+
@media (prefers-reduced-motion: reduce) {
|
|
242
|
+
:root {
|
|
243
|
+
scroll-behavior: auto;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Admin area composition (l10, p05, p24-r3, p26, p26b).
|
|
3
|
+
* The admin pages reuse the k28 row groups (list.css) and the k13 cards (card.css);
|
|
4
|
+
* this file adds only the admin-specific pieces: the Overview grid, the instance-dialog
|
|
5
|
+
* import-root rows, the plugin permission list, the storage bar with its legend, and
|
|
6
|
+
* the acquisition row spacing.
|
|
7
|
+
*
|
|
8
|
+
* plugin-approval-interim: the Install confirmation (340 px dialog with the permission
|
|
9
|
+
* list, Cancel and a suggested Install) and the File-tab permission list are built but
|
|
10
|
+
* stay switched off until the core reports permissions for uninstalled plugins. Until
|
|
11
|
+
* then no permission list shows before install. No CSS state is added for the switch.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/* ------------------------------------------------------------------ */
|
|
15
|
+
/* l10 B - Overview: a card grid; the cards themselves are card.css */
|
|
16
|
+
/* ------------------------------------------------------------------ */
|
|
17
|
+
|
|
18
|
+
.hs-admin-overview {
|
|
19
|
+
display: grid;
|
|
20
|
+
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
|
|
21
|
+
gap: 16px;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@media (max-width: 720px) {
|
|
25
|
+
.hs-admin-overview {
|
|
26
|
+
grid-template-columns: 1fr;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/* ------------------------------------------------------------------ */
|
|
31
|
+
/* p05 - instance dialog import-root rows */
|
|
32
|
+
/* ------------------------------------------------------------------ */
|
|
33
|
+
|
|
34
|
+
/* A grey group inside the Files section of the 640 px instance dialog. */
|
|
35
|
+
.hs-import-roots {
|
|
36
|
+
display: flex;
|
|
37
|
+
flex-direction: column;
|
|
38
|
+
border-radius: var(--hs-radius-card);
|
|
39
|
+
overflow: hidden;
|
|
40
|
+
background: var(--hs-group-bg);
|
|
41
|
+
box-shadow: var(--hs-group-shadow);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.hs-import-root {
|
|
45
|
+
display: flex;
|
|
46
|
+
align-items: center;
|
|
47
|
+
gap: 8px;
|
|
48
|
+
padding: 8px 10px;
|
|
49
|
+
box-sizing: border-box;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.hs-import-roots .hs-import-root + .hs-import-root {
|
|
53
|
+
box-shadow: inset 0 1px 0 var(--hs-separator);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.hs-import-roots > .hs-setting-row {
|
|
57
|
+
box-shadow: inset 0 1px 0 var(--hs-separator);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.hs-import-root__id {
|
|
61
|
+
flex: none;
|
|
62
|
+
width: 110px;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.hs-import-root__path {
|
|
66
|
+
flex: 1;
|
|
67
|
+
min-width: 0;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.hs-import-root__path .hs-field__value {
|
|
71
|
+
font: 12.5px var(--hs-font-mono);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.hs-import-root__mode {
|
|
75
|
+
flex: none;
|
|
76
|
+
width: 96px;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.hs-import-roots__hint {
|
|
80
|
+
margin: 6px 0 0;
|
|
81
|
+
color: var(--hs-fg-muted);
|
|
82
|
+
font-size: 12.5px;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/* Phones: the path takes the full first line; Id and Mode share the second. */
|
|
86
|
+
@media (max-width: 720px) {
|
|
87
|
+
.hs-import-root {
|
|
88
|
+
flex-wrap: wrap;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.hs-import-root__path {
|
|
92
|
+
flex-basis: 100%;
|
|
93
|
+
order: -1;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.hs-import-root__id,
|
|
97
|
+
.hs-import-root__mode {
|
|
98
|
+
width: calc(50% - 4px);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/* ------------------------------------------------------------------ */
|
|
103
|
+
/* p24-r3 - plugin permission list */
|
|
104
|
+
/* ------------------------------------------------------------------ */
|
|
105
|
+
|
|
106
|
+
.hs-permission-list {
|
|
107
|
+
display: flex;
|
|
108
|
+
flex-direction: column;
|
|
109
|
+
gap: 6px;
|
|
110
|
+
margin-top: 6px;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.hs-permission-row {
|
|
114
|
+
display: flex;
|
|
115
|
+
align-items: center;
|
|
116
|
+
gap: 10px;
|
|
117
|
+
font-size: 13px;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.hs-permission-row__scope {
|
|
121
|
+
flex: none;
|
|
122
|
+
min-width: 64px;
|
|
123
|
+
font: 12px var(--hs-font-mono);
|
|
124
|
+
color: var(--hs-fg);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.hs-permission-row__detail {
|
|
128
|
+
flex: 1;
|
|
129
|
+
min-width: 0;
|
|
130
|
+
color: var(--hs-fg-muted);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.hs-permission-row .hs-pill {
|
|
134
|
+
flex: none;
|
|
135
|
+
margin-left: auto;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
@media (max-width: 720px) {
|
|
139
|
+
.hs-permission-row {
|
|
140
|
+
flex-wrap: wrap;
|
|
141
|
+
row-gap: 2px;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.hs-permission-row__detail {
|
|
145
|
+
flex-basis: 100%;
|
|
146
|
+
order: 3;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/* ------------------------------------------------------------------ */
|
|
151
|
+
/* p26 - storage usage bar and legend */
|
|
152
|
+
/* ------------------------------------------------------------------ */
|
|
153
|
+
|
|
154
|
+
.hs-storage-usage {
|
|
155
|
+
display: flex;
|
|
156
|
+
flex-direction: column;
|
|
157
|
+
gap: 14px;
|
|
158
|
+
max-width: 760px;
|
|
159
|
+
padding: 18px;
|
|
160
|
+
border-radius: var(--hs-radius-card);
|
|
161
|
+
background: var(--hs-group-bg);
|
|
162
|
+
box-shadow: var(--hs-group-shadow);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.hs-storage-bar {
|
|
166
|
+
display: flex;
|
|
167
|
+
height: 14px;
|
|
168
|
+
border-radius: var(--hs-radius-full);
|
|
169
|
+
overflow: hidden;
|
|
170
|
+
background: color-mix(in srgb, var(--hs-fg) 12%, transparent);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.hs-storage-bar > i {
|
|
174
|
+
display: block;
|
|
175
|
+
height: 100%;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
.hs-storage-legend {
|
|
179
|
+
display: grid;
|
|
180
|
+
grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
|
|
181
|
+
gap: 12px;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
.hs-storage-legend__item {
|
|
185
|
+
display: flex;
|
|
186
|
+
align-items: flex-start;
|
|
187
|
+
gap: 8px;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.hs-storage-legend__swatch {
|
|
191
|
+
flex: none;
|
|
192
|
+
width: 12px;
|
|
193
|
+
height: 12px;
|
|
194
|
+
margin-top: 3px;
|
|
195
|
+
border-radius: 3px;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
.hs-storage-legend__text {
|
|
199
|
+
display: flex;
|
|
200
|
+
flex-direction: column;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
.hs-storage-pinned {
|
|
204
|
+
margin: 0;
|
|
205
|
+
color: var(--hs-fg-muted);
|
|
206
|
+
font-size: 13px;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/* p26: Library acid, Cache acid at 55% over the view, Folders muted, the rest free. */
|
|
210
|
+
.hs-storage-bar__library,
|
|
211
|
+
.hs-storage-legend__swatch--library {
|
|
212
|
+
background: var(--hs-accent-bg);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
.hs-storage-bar__cache,
|
|
216
|
+
.hs-storage-legend__swatch--cache {
|
|
217
|
+
background: color-mix(in srgb, var(--hs-accent-bg) 55%, var(--hs-view-bg));
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
.hs-storage-bar__folders,
|
|
221
|
+
.hs-storage-legend__swatch--folders {
|
|
222
|
+
background: var(--hs-fg-muted);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
.hs-storage-bar__free,
|
|
226
|
+
.hs-storage-legend__swatch--free {
|
|
227
|
+
background: color-mix(in srgb, var(--hs-fg) 12%, transparent);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/* ------------------------------------------------------------------ */
|
|
231
|
+
/* p26b - acquisition rows */
|
|
232
|
+
/* ------------------------------------------------------------------ */
|
|
233
|
+
|
|
234
|
+
.hs-setting-row--acquisition {
|
|
235
|
+
align-items: flex-start;
|
|
236
|
+
padding-top: 12px;
|
|
237
|
+
padding-bottom: 12px;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
.hs-setting-row--acquisition .hs-setting-row__text {
|
|
241
|
+
gap: 3px;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
.hs-setting-row--acquisition .hs-setting-row__subtitle {
|
|
245
|
+
font-size: 13px;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
.hs-setting-row--acquisition .hs-pill {
|
|
249
|
+
flex: none;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/* Phones: the summary wraps and the menu stays a flat icon button. */
|
|
253
|
+
@media (max-width: 720px) {
|
|
254
|
+
.hs-setting-row--acquisition .hs-setting-row__subtitle {
|
|
255
|
+
white-space: normal;
|
|
256
|
+
}
|
|
257
|
+
}
|