mirror of
https://github.com/johannesjo/super-productivity.git
synced 2026-07-18 08:56:41 +00:00
The base body{} block was re-declaring --transition-duration-s (180ms)
and --transition-duration-l (400ms), shadowing the :root defaults
(150ms/375ms) for every element in the app regardless of theme
(body.isDarkTheme did not re-override them). That made the recent
token sweep silently drift some callers from 150ms to 180ms (+20%)
instead of the intended 1:1 swap, and left the light/dark experience
identical despite looking theme-specific.
Remove the three overrides — durations are now consistently the :root
defaults in both themes. Visible effect: task hover/select, done-toggle
SVG, and onboarding animations run about 30ms faster.
Update styling-guide.md to drop the obsolete "light theme overrides"
note and keep the bucket-rounding guidance.
179 lines
8.7 KiB
Markdown
179 lines
8.7 KiB
Markdown
# Styling Guide
|
||
|
||
## Rules
|
||
|
||
- **All visual styling must use CSS variables** from `src/styles/_css-variables.scss` — never hardcode colors, spacing, shadows, transitions, or z-index.
|
||
- **Positioning/layout is fine as plain CSS** — flexbox, grid, display, position, dimensions.
|
||
- **Check `src/app/ui/` first** before creating new styled elements — 40+ reusable components exist.
|
||
- **Component SCSS should be minimal** — shared styles belong in `src/styles/components/` or as a mixin.
|
||
- **Material overlay components** (menus, dialogs, tooltips) render outside component scope — style them in `src/styles/components/` and add a comment in the component pointing there.
|
||
|
||
## Anti-Patterns
|
||
|
||
| Avoid | Do Instead |
|
||
| ------------------------------------ | ------------------------------------------------------------------------- |
|
||
| Hardcoded colors (`#fff`, `red`) | CSS variables (`--text-color`, `--card-bg`, `--color-danger`) |
|
||
| Hardcoded spacing (`16px`, `1rem`) | Spacing variables (`--s2`, `--s`, `--s-half`) |
|
||
| Hardcoded shadows | Elevation variables (`--whiteframe-shadow-*dp`, `--md-sys-level*`) |
|
||
| Hardcoded transitions/durations | Transition variables (`--transition-standard`, `--transition-duration-*`) |
|
||
| Custom z-index values | Z-index variables (`--z-main-header`, `--z-backdrop`, etc.) |
|
||
| New styled elements without checking | Check `src/app/ui/` for existing reusable components first |
|
||
|
||
## Key Files
|
||
|
||
| File | Purpose |
|
||
| -------------------------------- | ------------------------------------------------------------- |
|
||
| `src/styles/_css-variables.scss` | All CSS custom properties (design tokens) |
|
||
| `src/styles/themes.scss` | Material theme setup + utility classes |
|
||
| `src/styles/page.scss` | Global page/body styles |
|
||
| `src/styles/util.scss` | Utility classes |
|
||
| `src/styles/components/` | Global component styles (Material overrides, shared patterns) |
|
||
| `src/styles/mixins/` | Reusable SCSS mixins |
|
||
| `src/app/ui/` | 40+ reusable Angular UI components |
|
||
|
||
## Spacing Variables (8px Grid)
|
||
|
||
| Variable | Value | Variable | Value |
|
||
| ------------- | ----- | -------- | ----- |
|
||
| `--s-quarter` | 2px | `--s4` | 32px |
|
||
| `--s-half` | 4px | `--s5` | 40px |
|
||
| `--s` | 8px | `--s6` | 48px |
|
||
| `--s2` | 16px | `--s7` | 56px |
|
||
| `--s3` | 24px | `--s8` | 64px |
|
||
|
||
```scss
|
||
// ✅ Good
|
||
padding: var(--s2) var(--s3);
|
||
gap: var(--s-half);
|
||
|
||
// ❌ Bad
|
||
padding: 16px 24px;
|
||
gap: 4px;
|
||
```
|
||
|
||
## Color Variables
|
||
|
||
| Use case | Variables |
|
||
| ------------------ | -------------------------------------------------------------------------------------------------- |
|
||
| Text | `--text-color`, `--text-color-muted`, `--text-color-most-intense` |
|
||
| Backgrounds | `--bg`, `--card-bg`, `--task-c-bg`, `--sub-task-c-bg` |
|
||
| Semantic | `--color-success` (#4caf50), `--color-warning` (#ff9800), `--color-danger` (#f44336) |
|
||
| Material palette | `--palette-primary-500`, `--palette-accent-500`, `--palette-warn-500` (100–900) |
|
||
| Overlays | `--c-dark-10` through `--c-dark-90`, `--c-light-05` through `--c-light-90` |
|
||
| Alpha coefficients | `--border-alpha` (0.12), `--overlay-alpha` (0.1), `--muted-alpha` (0.6), `--separator-alpha` (0.3) |
|
||
|
||
### Theme-Specific Values
|
||
|
||
Light theme sets: `--bg: #f8f8f7`, `--card-bg: #ffffff`, `--text-color: rgb(44, 44, 44)`
|
||
Dark theme sets: `--bg: #131314`, `--card-bg: var(--dark3)`, `--text-color: rgb(230, 230, 230)`
|
||
|
||
Dark elevation colors: `--dark0` (rgb(0,0,0)) through `--dark24` (rgb(56,56,56))
|
||
|
||
### Theme-Specific Overrides in Components
|
||
|
||
```scss
|
||
@include darkTheme() {
|
||
/* dark-only styles */
|
||
}
|
||
@include lightTheme() {
|
||
/* light-only styles */
|
||
}
|
||
```
|
||
|
||
Mixins are in `src/styles/mixins/_theming.scss`.
|
||
|
||
## Shadows & Elevation
|
||
|
||
- `--whiteframe-shadow-1dp` through `--whiteframe-shadow-24dp` — classic Material shadows
|
||
- `--md-sys-level1` through `--md-sys-level5` — Material Design 3 style
|
||
|
||
## Transitions & Animations
|
||
|
||
| Type | Variables |
|
||
| ---------- | ------------------------------------------------------------------------------------------------------------------ |
|
||
| Shorthands | `--transition-fast`, `--transition-standard`, `--transition-enter`, `--transition-leave` |
|
||
| Durations | `--transition-duration-xs` (90ms), `-s` (150ms), `-m` (225ms), `-l` (375ms) |
|
||
| Additional | `--transition-duration-enter` (225ms), `--transition-duration-leave` (195ms), `--page-transition-duration` (225ms) |
|
||
| Timing | `--ani-standard-timing`, `--ani-enter-timing`, `--ani-leave-timing`, `--ani-sharp-timing` |
|
||
|
||
When migrating hardcoded durations, pick the nearest bucket — up to ~15% drift is acceptable for UI transitions.
|
||
|
||
## Focus Ring
|
||
|
||
Keyboard-accessibility tokens for custom interactive elements. Material components keep their own focus treatment; use these for non-Material buttons, cards, and custom controls.
|
||
|
||
| Variable | Value |
|
||
| --------------------- | ---------------------------- |
|
||
| `--focus-ring-width` | 2px |
|
||
| `--focus-ring-offset` | 2px |
|
||
| `--focus-ring-color` | `var(--palette-primary-500)` |
|
||
|
||
Quickest adoption — add the `.focus-ring` utility class from `util.scss`, which applies an `outline` on `:focus-visible` only (so it doesn't fire on mouse clicks).
|
||
|
||
```scss
|
||
// opt-in per-element
|
||
.my-button:focus-visible {
|
||
outline: var(--focus-ring-width) solid var(--focus-ring-color);
|
||
outline-offset: var(--focus-ring-offset);
|
||
}
|
||
```
|
||
|
||
## Z-Index Layers
|
||
|
||
| Variable | Value | Purpose |
|
||
| ----------------------- | ----- | ------------------------ |
|
||
| `--z-check-done` | 11 | Task done checkbox |
|
||
| `--z-main-header` | 12 | Main header |
|
||
| `--z-task-title-focus` | 32 | Focused task title |
|
||
| `--z-mobile-bottom-nav` | 50 | Mobile bottom navigation |
|
||
| `--z-side-nav` | 60 | Side navigation |
|
||
| `--z-backdrop` | 222 | Backdrop overlay |
|
||
| `--z-add-task-bar` | 999 | Add task bar |
|
||
| `--z-search-bar` | 999 | Search bar |
|
||
| `--z-tour` | 1001 | Tour overlay |
|
||
|
||
## Layout Variables
|
||
|
||
| Variable | Value | Notes |
|
||
| ----------------------- | ----- | ------------------ |
|
||
| `--component-max-width` | 800px | 900–1000px on iPad |
|
||
| `--side-nav-width` | 200px | |
|
||
| `--side-nav-width-l` | 400px | |
|
||
| `--bar-height-large` | 56px | |
|
||
| `--bar-height` | 48px | |
|
||
| `--bar-height-small` | 40px | |
|
||
|
||
## Responsive Breakpoints
|
||
|
||
Available as CSS vars (`--layout-xxxs` through `--layout-xl`) and as SCSS mixins in `src/styles/mixins/_media-queries.scss`:
|
||
|
||
| Breakpoint | Value |
|
||
| ---------- | ------ |
|
||
| `xxxs` | 398px |
|
||
| `xxs` | 450px |
|
||
| `xs` | 600px |
|
||
| `s` | 800px |
|
||
| `m` | 1000px |
|
||
| `l` | 1200px |
|
||
| `xl` | 2000px |
|
||
|
||
## Utility Classes
|
||
|
||
Defined in `src/styles/util.scss` and `src/styles/themes.scss`:
|
||
|
||
- Layout: `.center-wrapper`, `.mw` (max-width container)
|
||
- Responsive: `.hide-xs`, `.hide-xxs`, `.hide-gt-sm`
|
||
- Input: `.show-only-on-touch-primary`, `.show-only-on-mouse-primary`
|
||
- Theme: `.show-dark-only`, `.show-light-only`
|
||
- Color: `.bg-primary`, `.bgc-accent`, `.color-primary`, `.bg-success`, `.bg-warning`, `.bg-danger`
|
||
- Effects: `.milk-glass` (backdrop blur)
|
||
|
||
## Global Component Styles
|
||
|
||
Located in `src/styles/components/`, these are needed for elements that render outside component scope:
|
||
|
||
- `_overwrite-material.scss` — Material component customizations
|
||
- `_customizer-menu.scss`, `backdrop.scss`, `bottom-panel.scss`
|
||
- `markdown.scss`, `mentions.scss`, `table.scss`
|
||
- `fab-wrapper.scss`, `wrap-buttons.scss`, `multi-btn-wrapper.scss`
|
||
- `planner-shared.scss`, `formly-rows.scss`, `scrollbars.scss`
|