Compare commits
1
Commits
RC6
...
51682a901d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
51682a901d |
Binary file not shown.
|
After Width: | Height: | Size: 27 KiB |
@@ -0,0 +1,305 @@
|
||||
# Noo Design System
|
||||
|
||||
Noo is a Nextcloud client for iOS, Android, macOS and Windows. ("Noo" is a placeholder name.)
|
||||
Its visual language is warm neutrals with one violet accent, flat surfaces, pill-shaped controls, and no gradients.
|
||||
|
||||
**Platform rule:** keep one visual language everywhere. Adapt only the navigation chrome (status bar, top bar, bottom bar, window controls) to each platform. Content components look the same on every platform.
|
||||
|
||||
Reference files in this project:
|
||||
- `Noo Screens.dc.html` has every screen on every platform, in light and dark.
|
||||
- `Noo Design System.dc.html` is the visual component sheet.
|
||||
- `noo-kit.js` holds the tokens (`TH`), the icon set (`SVG`/`ic`), file-type mapping (`KIND`) and mock data.
|
||||
- `Mobile Screen.dc.html` and `Desktop Screen.dc.html` are the reference builds for each screen.
|
||||
|
||||
---
|
||||
|
||||
## 1. Tokens
|
||||
|
||||
### 1.1 Color (semantic). Use these names in code.
|
||||
|
||||
| Token | Role | Light | Dark |
|
||||
|---|---|---|---|
|
||||
| `bg` | App background, desktop sidebar | `#F3EFE6` warm off-white | `#0E0D0B` |
|
||||
| `surface` (`sf`) | Cards, rows, bars, sheets, desktop main pane | `#FFFFFF` | `#25241F` |
|
||||
| `surface-2` (`sf2`) | Inputs, inset panels, secondary buttons | `#F6F5F2` | `#3D3C38` |
|
||||
| `surface-3` (`sf3`) | Progress tracks, toggle off, grabbers | `#EAE8E2` | `#5A5852` |
|
||||
| `line` (`ln`) | Dividers, 1px borders | `#EAE8E2` | `#3D3C38` |
|
||||
| `fg-1` | Primary text | `#0E0D0B` | `#F3EFE6` |
|
||||
| `fg-2` | Secondary text, idle icons | `#5A5852` | `#BDBAB1` |
|
||||
| `fg-3` | Meta text, placeholders, trailing icons | `#7C7A72` | `#9E9B92` |
|
||||
| `accent` (`ac`) | Primary fills (buttons, FAB, toggle on, progress) | `#8D0DE3` | `#8D0DE3` |
|
||||
| `accent-text` (`act`) | Accent text and icons, active nav | `#8D0DE3` | `#CBA5FD` |
|
||||
| `accent-soft` (`acs`) | Selected and active backgrounds, tonal buttons | `#ECDFFF` | `#2F0454` |
|
||||
| `danger` / `danger-soft` | Destructive text / bg | `#A8202A` / `#FDE7E7` | `#F49E9E` / `#560F18` |
|
||||
| `danger-fill` | Swipe-delete background (white text) | `#A8202A` | `#A8202A` |
|
||||
| `success` / `success-soft` | Synced, connected | `#3E7A23` / `#EAF5DF` | `#B7DD9F` / `#1E3F10` |
|
||||
| `warning` / `warning-soft` | Video file type | `#8C5A0E` / `#FBEFD0` | `#F0C26C` / `#4A3208` |
|
||||
| `info` / `info-soft` | Docs, images | `#2940A8` / `#E6ECFE` | `#B6C3FB` / `#1C2B73` |
|
||||
| `scrim` | Behind sheets, drawers, dialogs | `rgba(14,13,11,.45)` | `rgba(0,0,0,.6)` |
|
||||
|
||||
Rules:
|
||||
- Text on `accent` is always `#FFFFFF`. Accent-colored text uses `accent-text`, never `accent` in dark mode.
|
||||
- On-color text always uses the matching pair: `accent-text` on `accent-soft`, `danger` on `danger-soft`, and so on.
|
||||
- Don't use gradients. Don't add new colors. Avatar and photo placeholder fills use the secondary palette: `#8DCDE2 #96B0FD #E5D8BD #EEEDB3 #DA9AC7 #A7D296 #E9A6A7 #85D1BD #CBA5FD`, always with `#0E0D0B` text.
|
||||
|
||||
### 1.2 File-type tiles (`KIND`)
|
||||
| Kind | Background | Icon color | Lucide icon |
|
||||
|---|---|---|---|
|
||||
| folder | accent-soft | accent-text | `folder` |
|
||||
| pdf | danger-soft | danger | `file-text` |
|
||||
| doc / text | info-soft | info | `file-text` |
|
||||
| sheet | success-soft | success | `sheet` |
|
||||
| video | warning-soft | warning | `film` |
|
||||
| image | info-soft | info | `image` |
|
||||
| archive | surface-3 | fg-2 | `file-archive` |
|
||||
|
||||
Tile sizes: 40px/r12 for mobile rows, 30px/r9 for desktop rows, 44px/r12 for the share header, 32px/r10 for activity. The icon is half the tile size (20, 16, 24, 16).
|
||||
|
||||
### 1.3 Typography
|
||||
Fonts (Google Fonts): **Schibsted Grotesk** for headings (weights 500/600) and **Instrument Sans** for UI (weights 400/500/600). Load them with `https://fonts.googleapis.com/css2?family=Instrument+Sans:wght@400;500;600&family=Schibsted+Grotesk:wght@500;600&display=swap`. Don't use italics, all-caps or wide tracking.
|
||||
|
||||
| Style | Font | Size / line-height | Tracking | Use |
|
||||
|---|---|---|---|---|
|
||||
| Large title | Schibsted 600 | 34 / 0.9 | −3% | iOS large title |
|
||||
| Stat | Schibsted 600 | 32 (mobile) · 28 (desktop) / 0.9 | −3% | Offline GB, counters |
|
||||
| Title | Schibsted 500 | 22 / 1 | −2% | Android top bar, desktop toolbar |
|
||||
| Card title | Schibsted 500 | 17–20 / 1 | −2% | Settings cards, sheet sections, account name |
|
||||
| Group heading | Schibsted 500 | 18 / 1 | −2% | Photos month |
|
||||
| Body L | Instrument 400/500 | 16 / 1.2 | 0 | Mobile row title, settings label |
|
||||
| Body | Instrument 400/500 | 14–15 / 1.3 | 0 | Desktop rows, activity text, banners |
|
||||
| Label | Instrument 600 | 13 / 1 | 0 | Section labels (fg-2), chips, table headers (12, fg-3) |
|
||||
| Meta | Instrument 400 | 13 (mobile) · 12–13 (desktop) / 1.2 | 0 | Size · date, subtitles (fg-3) |
|
||||
| Nav label | Instrument 500 / 600 (active) | 12 Android · 10 iOS | 0 | Bottom bars |
|
||||
| Button | Instrument 600 | 14–16 / 1 | 0 | All buttons |
|
||||
| Mono | ui-monospace 400 | 13–14 | 0 | Share URLs, local paths |
|
||||
|
||||
### 1.4 Space, radius, elevation, motion
|
||||
- **Spacing** uses a 4px base: 4, 8, 12, 14, 16, 20, 24, 32. Mobile screen gutter is **12px** (cards) and 16px (bars). Desktop content gutter is **24px**.
|
||||
- **Radius:**
|
||||
- pills (`999px`) for every button, chip, segmented control, toggle, search field and badge
|
||||
- 20px for cards and grouped lists
|
||||
- 18px for grid cards and stat cards
|
||||
- 14px for inputs and inset panels
|
||||
- 12px for desktop sidebar items and selected table rows
|
||||
- 28px for the sheet top and drawer edge
|
||||
- 24px for desktop dialogs
|
||||
- screen corners are 48 on iOS and 36 on Android
|
||||
- **Elevation:** product UI is flat, with no shadows on buttons or cards. The only shadow is `0 24px 48px rgba(30,0,47,.14)`, and only on floating desktop dialogs. Separate things by surface color, not by shadow.
|
||||
- **Motion:** use `cubic-bezier(.7,0,.15,1)` with durations of 180, 280 and 480ms. Nothing bounces. Pressing a button scales it to 0.98.
|
||||
|
||||
### 1.5 Icons
|
||||
Use **Lucide** (pinned to `lucide-static@0.460.0`) at a 1.8 stroke. Sizes are 14, 16, 18, 20, 24 and 32. Icons render in the current text color. Tab icons: Files `folder`, Photos `images`, Favorites `star`, Offline `hard-drive-download`, Shares `share-2`, Recent `clock`, Activity `activity`, Trash `trash-2`, Settings `settings`.
|
||||
|
||||
---
|
||||
|
||||
## 2. Components
|
||||
|
||||
**Button**
|
||||
- Always a pill. Heights: 52 (sheet CTA), 44 (mobile card), 40 (inline in a field), 36 (desktop toolbar), 28–32 (compact).
|
||||
- Variants:
|
||||
- *Primary*: accent fill, white text.
|
||||
- *Tonal*: accent-soft fill, accent-text.
|
||||
- *Secondary*: surface-2 fill, fg-1.
|
||||
- *Danger*: danger-soft fill, danger text.
|
||||
- *Outline*: 1.5px surface-3 border.
|
||||
- An icon goes on the left, with a 6–10px gap.
|
||||
|
||||
**FAB** (Android only)
|
||||
- An extended pill: 56px tall, accent fill, labelled "Upload".
|
||||
- Sits 16px from the right and bottom edges of the content area.
|
||||
- Shows only on Files and Photos.
|
||||
|
||||
**Chip**
|
||||
- A pill, 32–34px tall, 12px horizontal padding, Label 13–14.
|
||||
- Idle: surface fill on mobile, or a 1px line border on desktop.
|
||||
- Selected: accent-soft fill with accent-text.
|
||||
- A trailing `chevron-down` means it opens a menu. A trailing `x` means it's an active filter.
|
||||
|
||||
**Segmented control**
|
||||
- A pill track (surface or surface-2) with 3px padding.
|
||||
- The active segment gets an accent-soft fill with accent-text at weight 600. Idle segments use fg-2 at weight 500.
|
||||
- Use it for the List/Grid toggle (icons only, 36×28), Shares scope, Theme, and default view.
|
||||
|
||||
**Toggle**
|
||||
- 48×28 on mobile, 44×26 on desktop, with a white knob 3px inset.
|
||||
- On: accent track. Off: surface-3 track. It looks the same on every platform.
|
||||
|
||||
**Search field**
|
||||
- A pill (radius 12 on the iOS inline field), 36–38px tall.
|
||||
- Surface fill on bg, or surface-2 fill on surface. Leading search icon and placeholder in fg-3.
|
||||
- Placement:
|
||||
- iOS: below the large title.
|
||||
- Android: an icon in the top bar that expands.
|
||||
- Desktop: 260px wide in the toolbar.
|
||||
|
||||
**Grouped list (card)**
|
||||
- A surface card with radius 20 and 1px gaps showing `line`, which draws the dividers.
|
||||
- An optional group label above it: 13/600 in fg-2, inset 8px.
|
||||
- Each group is 18px from the next.
|
||||
|
||||
**File row**
|
||||
- Mobile: 64px tall.
|
||||
- Left to right: tile 40, then a column with the name (16/500, one line, ellipsis) above a meta line (13, fg-3), then optional trailing icons, then the overflow menu (`ellipsis` on iOS, `ellipsis-vertical` on Android).
|
||||
- The meta line is `[status icon][shared icon] size · modified`.
|
||||
- A favorite shows an accent-text star before the overflow menu.
|
||||
- Trailing icon by screen: star in Favorites, `rotate-ccw` in Trash.
|
||||
- Desktop: a table row 52px tall.
|
||||
- Columns are `minmax(0,1fr) 180px 160px 120px`: Name, two data columns, then status icons and the overflow menu.
|
||||
- The header row is 36px, 12/600 in fg-3, with a sort arrow on the active column.
|
||||
- A selected row gets an accent-soft fill with radius 12.
|
||||
|
||||
**Status icons (14px)**
|
||||
- Synced: `circle-check` in success.
|
||||
- Syncing: `refresh-cw` in accent-text.
|
||||
- Error: `circle-alert` in danger, and the meta text says what to do ("Couldn't sync · Tap to retry").
|
||||
- Shared: `users` in fg-3.
|
||||
|
||||
**Swipe action**
|
||||
- The row slides and uncovers a 96px action block. Delete is white on danger-fill; Favorite is white on accent.
|
||||
- The block has a 20px icon above a 12/600 label.
|
||||
- Swipe actions are set in Settings → Swipe on a file.
|
||||
|
||||
**Grid card**
|
||||
- Surface fill, radius 18. Mobile uses 2 columns with a 10px gap; desktop uses 5 columns with a 16px gap.
|
||||
- The thumbnail area is 104–118px tall, filled with the file-type soft color and a 32px icon. Real thumbnails replace it when they exist.
|
||||
- Below it: the name (14/500) with an overflow menu, then the meta (12).
|
||||
|
||||
**Photo grid**
|
||||
- Square tiles with a 2px gap on mobile (3 columns, edge to edge) and a 4px gap on desktop (8 columns).
|
||||
- Tiles are grouped by month, with the group heading on the left and the count on the right.
|
||||
- Videos get a badge in the bottom-right: a `play` icon and the duration on `rgba(14,13,11,.7)`.
|
||||
|
||||
**Activity item**
|
||||
- Avatar 36 (initials on a secondary-palette color), then a sentence: **Actor** verb **object** tail.
|
||||
- Time in meta style. The file tile (32) goes on the right.
|
||||
|
||||
**Banner / summary card**
|
||||
- A surface card with radius 20 (surface-2 on desktop) and padding of 14–18.
|
||||
- Trash: an info icon, the retention text, and "Empty trash" as a danger text button.
|
||||
- Offline: the stat, a 6px progress bar, the last-sync meta, and a "Sync now" tonal button.
|
||||
|
||||
**Progress bar**
|
||||
- 6px tall pill. Surface-3 track with an accent fill.
|
||||
- Used for storage quota, cache use and the offline limit.
|
||||
|
||||
**Avatar**
|
||||
- A circle with initials, weight 600, at 0.36× the avatar size.
|
||||
- Sizes: 30–32 in bars, 36 in lists, 48 in the drawer, 52–56 on the account card.
|
||||
- The current user gets an accent-soft fill with accent-text.
|
||||
|
||||
**Settings row**
|
||||
- 52px tall, or 60px with a subtitle.
|
||||
- Left to right: an optional 20px icon in fg-2, then the label (16) with an optional subtitle (13, fg-3), then a trailing control.
|
||||
- Trailing control is one of: a toggle, a value in fg-3 with a chevron (desktop uses a 32px dropdown with radius 10), a segmented control, a pill button, or a status badge.
|
||||
- A destructive row uses danger text.
|
||||
|
||||
**Tab order row**
|
||||
- A grip icon (`grip-vertical`, fg-3), the tab icon, the label, then a pin button: a 36px circle (30 on desktop) that is accent-soft with `pin` when pinned, or surface-2 with `pin-off` when not.
|
||||
- Allow at most 5 pinned tabs.
|
||||
|
||||
**Sheet** (mobile)
|
||||
- Surface fill, radius 28 at the top. A 36×5 grabber in surface-3. Padding 20, with 22px between sections.
|
||||
- It sits on a scrim.
|
||||
|
||||
**Dialog** (desktop)
|
||||
- 540px wide, radius 24, padding 24, sitting on a scrim.
|
||||
- Header: file tile, title "Share "<name>"", and a close button (32px circle, surface-2).
|
||||
|
||||
**Drawer** (mobile)
|
||||
- 316px wide, surface fill, radius 28 on the trailing edge, on a scrim.
|
||||
- Top to bottom:
|
||||
- account block with a chevron to switch accounts
|
||||
- storage bar
|
||||
- "More" label, then the unpinned tabs as 52px pill items (icon 24, label 16/500, trailing count)
|
||||
- Settings
|
||||
- an "Edit tabs" link at the bottom, in accent-text
|
||||
|
||||
---
|
||||
|
||||
## 3. Navigation & platform mapping
|
||||
|
||||
**Tabs** (the user sets the order): Files, Photos, Favorites, Offline, Shares, Recent, Activity, Trash. Settings is always separate.
|
||||
|
||||
### Mobile
|
||||
|
||||
Mobile always has **5 pinned tabs in the bottom bar**. The rest go in the drawer, which opens from the top-left menu icon.
|
||||
|
||||
| Element | iOS | Android |
|
||||
|---|---|---|
|
||||
| Status bar | 54px, Dynamic Island | 40px |
|
||||
| Top bar | 44px row: `menu` on the left; `plus` and avatar on the right (all accent-text). Then a 34px large title, then the search field. | 64px: `menu`, 22px title, `search`, avatar |
|
||||
| Bottom bar | Surface fill, 1px top line. Icon 24 above a 10px label. Active: accent-text. Idle: fg-3. 34px home indicator below. | Surface fill, 80px. The active icon sits in a 56×32 accent-soft pill with a 12px label. 20px gesture bar below. |
|
||||
| Upload | `plus` in the nav bar | Extended FAB |
|
||||
| Overflow icon | `ellipsis` | `ellipsis-vertical` |
|
||||
| Settings | Pushed screen with a "‹ Files" back button and a large title. No bottom bar. | Pushed screen with a back arrow and a title. No bottom bar. |
|
||||
| Biometric label | "Lock with Face ID" | "Lock with fingerprint" |
|
||||
|
||||
### Desktop
|
||||
|
||||
Desktop has a 256px sidebar in `bg` and a main pane in `surface`, separated by a 1px line.
|
||||
|
||||
**Sidebar**, top to bottom:
|
||||
- account switcher card
|
||||
- the 5 pinned tabs
|
||||
- a divider
|
||||
- the remaining tabs
|
||||
- a spacer
|
||||
- the storage meter
|
||||
- Settings
|
||||
|
||||
Sidebar items are 38px tall with radius 12, an 18px icon and a 14/500 label. The active item gets an accent-soft fill with accent-text at weight 600. Counts sit on the right: Trash 12, Offline errors, new shares.
|
||||
|
||||
**Toolbar** is 64px tall:
|
||||
- the title (22px Schibsted Grotesk), with a breadcrumb in Files
|
||||
- a spacer
|
||||
- the search field
|
||||
- context actions: List/Grid toggle and Upload in Files, Upload in Photos, Empty trash in Trash, Sync now in Offline
|
||||
|
||||
| Element | macOS | Windows |
|
||||
|---|---|---|
|
||||
| Window | Radius 12 | Radius 8 |
|
||||
| Controls | Traffic lights at the top of the sidebar | 40px title bar with the app mark and name; minimize, maximize and close buttons 46px wide |
|
||||
| Navigation | Back and forward chevrons at the start of the toolbar | Not shown in the toolbar |
|
||||
| Biometric | "Touch ID" | "Windows Hello" |
|
||||
| Local path | `~/Noo/…` | `C:\Users\…\Noo` |
|
||||
| Swipe setting | "Trackpad swipe on a file" | "Touch swipe on a file" |
|
||||
|
||||
---
|
||||
|
||||
## 4. Screen recipes
|
||||
|
||||
- **Files:**
|
||||
- Toolbar: sort chip (`Name ↑`), type filter chip, List/Grid segmented toggle.
|
||||
- Desktop adds Modified and Shared filter chips, an active-filter chip, and an item count.
|
||||
- Content: a list, or a grid when the toggle is set.
|
||||
- **Photos:** type chips (All, Photos, Videos, Camera), then the photo grid grouped by month. The grid view is the only view.
|
||||
- **Favorites:** a file list with a star as the trailing icon.
|
||||
- **Offline:** a summary card (or 4 stat cards on desktop), then a list whose rows show sync status icons and status meta.
|
||||
- **Shares:** a segmented control (With you, By you, Links), then a list. The meta reads "Owner · Permission".
|
||||
- **Recent:** a list grouped into Today, Yesterday and This week. The meta is the action plus the location.
|
||||
- **Activity:** the feed grouped by day. Desktop limits it to 760px wide.
|
||||
- **Trash:** a retention banner, then a list. Mobile rows get a restore icon; desktop rows get a tonal "Restore" pill.
|
||||
- **Settings:** sections in this order:
|
||||
1. Account card
|
||||
2. Accounts (list, then "Add account")
|
||||
3. Security
|
||||
4. File sync
|
||||
5. Files cache
|
||||
6. Appearance
|
||||
7. Tabs
|
||||
8. Swipe on a file
|
||||
|
||||
Mobile uses one column of grouped lists. Desktop uses a 2-column grid of cards with a 1px line and radius 20.
|
||||
- **Share sheet / dialog:** sections in this order:
|
||||
1. Header: file tile, name, size · folder, and close.
|
||||
2. **Share with people:** an input ("Name, email or group"), then the people with access. The owner comes first; the others each have a permission pill ("Can edit ▾").
|
||||
3. **Share link:** a toggle, then the URL field in mono with a primary "Copy link" button, then option chips (permission, expiry, password, allow download).
|
||||
4. **Send file directly:** an outline button, with a caption saying that link settings don't apply.
|
||||
|
||||
---
|
||||
|
||||
## 5. Copy
|
||||
- Use plain, active and short sentences, under 15 words. Say "you".
|
||||
- Name the problem and the fix: "Couldn't sync · Tap to retry", not "An error occurred".
|
||||
- Use sentence case everywhere and no all-caps. Use a middle dot ( · ) to separate meta values.
|
||||
- Don't use emoji in the product UI.
|
||||
@@ -0,0 +1,340 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<script src="./support.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<x-dc>
|
||||
<helmet>
|
||||
<script src="noo-kit.js"></script>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Instrument+Sans:wght@400;500;600&family=Schibsted+Grotesk:wght@500;600&display=swap">
|
||||
<style>
|
||||
body{margin:0}
|
||||
a{color:#8D0DE3;text-decoration:none}
|
||||
a:hover{color:#6E08B3}
|
||||
</style>
|
||||
</helmet>
|
||||
<sc-if value="{{ ready }}" hint-placeholder-val="{{ false }}">
|
||||
<div style="{{ root }}">
|
||||
|
||||
<sc-if value="{{ win }}">
|
||||
<div style="height:40px;flex:none;display:flex;align-items:center;background:var(--bg);color:var(--fg2)">
|
||||
<div style="display:flex;align-items:center;gap:10px;padding:0 16px;flex:1;font:400 12px/1 var(--ft)"><div style="width:16px;height:16px;border-radius:4px;background:var(--ac)"></div>Noo</div>
|
||||
<div style="width:46px;height:40px;display:flex;align-items:center;justify-content:center"><span style="{{ i16.minus }}"></span></div>
|
||||
<div style="width:46px;height:40px;display:flex;align-items:center;justify-content:center"><span style="{{ i14.square }}"></span></div>
|
||||
<div style="width:46px;height:40px;display:flex;align-items:center;justify-content:center"><span style="{{ i16.x }}"></span></div>
|
||||
</div>
|
||||
</sc-if>
|
||||
|
||||
<div style="flex:1;min-height:0;display:flex">
|
||||
<div style="width:256px;flex:none;background:var(--bg);display:flex;flex-direction:column;padding:12px 12px 16px;box-sizing:border-box;gap:2px">
|
||||
<sc-if value="{{ mac }}">
|
||||
<div style="height:32px;display:flex;align-items:center;gap:8px;padding:0 8px 8px"><div style="width:12px;height:12px;border-radius:999px;background:#FF5F57"></div><div style="width:12px;height:12px;border-radius:999px;background:#FEBC2E"></div><div style="width:12px;height:12px;border-radius:999px;background:#28C840"></div></div>
|
||||
</sc-if>
|
||||
<div style="display:flex;align-items:center;gap:10px;padding:8px 10px;border-radius:14px;background:var(--sf);margin-bottom:14px">
|
||||
<div style="width:32px;height:32px;border-radius:999px;background:var(--acs);color:var(--act);display:flex;align-items:center;justify-content:center;font:600 12px/1 var(--ft);flex:none">MR</div>
|
||||
<div style="flex:1;min-width:0;display:flex;flex-direction:column;gap:4px"><div style="font:600 14px/1 var(--ft)">Marina Rocha</div><div style="font:400 12px/1 var(--ft);color:var(--fg3)">cloud.rocha.family</div></div>
|
||||
<span style="{{ chevG }}"></span>
|
||||
</div>
|
||||
<sc-for list="{{ navA }}" as="n" hint-placeholder-count="5">
|
||||
<sc-if value="{{ n.on }}"><div style="height:38px;border-radius:12px;padding:0 12px;display:flex;align-items:center;gap:12px;background:var(--acs);color:var(--act);font:600 14px/1 var(--ft)"><span style="{{ n.ico }}"></span><div style="flex:1">{{ n.label }}</div><div style="font:500 12px/1 var(--ft)">{{ n.count }}</div></div></sc-if>
|
||||
<sc-if value="{{ n.off }}"><div style="height:38px;border-radius:12px;padding:0 12px;display:flex;align-items:center;gap:12px;color:var(--fg1);font:500 14px/1 var(--ft)"><span style="{{ n.icoG }}"></span><div style="flex:1">{{ n.label }}</div><div style="font:500 12px/1 var(--ft);color:var(--fg3)">{{ n.count }}</div></div></sc-if>
|
||||
</sc-for>
|
||||
<div style="height:1px;background:var(--ln);margin:8px 12px"></div>
|
||||
<sc-for list="{{ navB }}" as="n" hint-placeholder-count="3">
|
||||
<sc-if value="{{ n.on }}"><div style="height:38px;border-radius:12px;padding:0 12px;display:flex;align-items:center;gap:12px;background:var(--acs);color:var(--act);font:600 14px/1 var(--ft)"><span style="{{ n.ico }}"></span><div style="flex:1">{{ n.label }}</div><div style="font:500 12px/1 var(--ft)">{{ n.count }}</div></div></sc-if>
|
||||
<sc-if value="{{ n.off }}"><div style="height:38px;border-radius:12px;padding:0 12px;display:flex;align-items:center;gap:12px;color:var(--fg1);font:500 14px/1 var(--ft)"><span style="{{ n.icoG }}"></span><div style="flex:1">{{ n.label }}</div><div style="font:500 12px/1 var(--ft);color:var(--fg3)">{{ n.count }}</div></div></sc-if>
|
||||
</sc-for>
|
||||
<div style="flex:1"></div>
|
||||
<div style="display:flex;flex-direction:column;gap:8px;padding:12px 12px 14px">
|
||||
<div style="display:flex;justify-content:space-between;font:400 12px/1 var(--ft);color:var(--fg2)"><span style="font-weight:500;color:var(--fg1)">Storage</span><span>38.2 of 100 GB</span></div>
|
||||
<div style="height:6px;border-radius:999px;background:var(--sf3);overflow:hidden"><div style="width:38%;height:100%;background:var(--ac)"></div></div>
|
||||
</div>
|
||||
<sc-if value="{{ setOn }}"><div style="height:38px;border-radius:12px;padding:0 12px;display:flex;align-items:center;gap:12px;background:var(--acs);color:var(--act);font:600 14px/1 var(--ft)"><span style="{{ i18.settings }}"></span>Settings</div></sc-if>
|
||||
<sc-if value="{{ setOff }}"><div style="height:38px;border-radius:12px;padding:0 12px;display:flex;align-items:center;gap:12px;color:var(--fg1);font:500 14px/1 var(--ft)"><span style="{{ setIcoG }}"></span>Settings</div></sc-if>
|
||||
</div>
|
||||
|
||||
<div style="flex:1;min-width:0;background:var(--sf);display:flex;flex-direction:column;position:relative;border-left:1px solid var(--ln)">
|
||||
<div style="height:64px;flex:none;display:flex;align-items:center;gap:12px;padding:0 20px 0 24px;border-bottom:1px solid var(--ln)">
|
||||
<sc-if value="{{ mac }}"><div style="display:flex;gap:4px;color:var(--fg3);margin-right:4px"><span style="{{ i20.chevL }}"></span><span style="{{ i20.chevR }}"></span></div></sc-if>
|
||||
<div style="display:flex;align-items:center;gap:8px;font:500 22px/1 var(--fd);letter-spacing:-0.02em">{{ title }}<sc-if value="{{ s.files }}"><span style="{{ chevG }}"></span><span style="font:400 15px/1 var(--ft);letter-spacing:0;color:var(--fg2);white-space:nowrap">All files</span></sc-if></div>
|
||||
<div style="flex:1"></div>
|
||||
<sc-if value="{{ notSettings }}"><div style="width:260px;height:36px;border-radius:999px;background:var(--sf2);display:flex;align-items:center;gap:8px;padding:0 14px;color:var(--fg3);font:400 14px/1 var(--ft)"><span style="{{ i16.search }}"></span>Search in {{ title }}</div></sc-if>
|
||||
<sc-if value="{{ s.files }}">
|
||||
<div style="display:flex;padding:3px;border-radius:999px;background:var(--sf2);gap:2px"><div style="{{ segL }}"><span style="{{ i16.list }}"></span></div><div style="{{ segG }}"><span style="{{ i16.grid }}"></span></div></div>
|
||||
<div style="height:36px;padding:0 16px 0 12px;border-radius:999px;background:var(--ac);color:#FFFFFF;display:flex;align-items:center;gap:8px;font:600 14px/1 var(--ft);white-space:nowrap"><span style="{{ i18.plus }}"></span>Upload</div>
|
||||
</sc-if>
|
||||
<sc-if value="{{ s.photos }}"><div style="height:36px;padding:0 16px 0 12px;border-radius:999px;background:var(--ac);color:#FFFFFF;display:flex;align-items:center;gap:8px;font:600 14px/1 var(--ft);white-space:nowrap"><span style="{{ i18.upload }}"></span>Upload</div></sc-if>
|
||||
<sc-if value="{{ s.trash }}"><div style="height:36px;padding:0 16px;border-radius:999px;background:var(--dgs);color:var(--dg);display:flex;align-items:center;gap:8px;font:600 14px/1 var(--ft);white-space:nowrap"><span style="{{ i16.trash }}"></span>Empty trash</div></sc-if>
|
||||
<sc-if value="{{ s.offline }}"><div style="height:36px;padding:0 16px;border-radius:999px;background:var(--acs);color:var(--act);display:flex;align-items:center;gap:8px;font:600 14px/1 var(--ft);white-space:nowrap"><span style="{{ i16.sync }}"></span>Sync now</div></sc-if>
|
||||
</div>
|
||||
|
||||
<div style="flex:1;min-height:0;overflow:hidden;display:flex;flex-direction:column;padding:0 24px">
|
||||
|
||||
<sc-if value="{{ s.files }}">
|
||||
<div style="flex:none;display:flex;align-items:center;gap:8px;padding:14px 0 10px">
|
||||
<div style="height:32px;padding:0 12px;border-radius:999px;border:1px solid var(--ln);display:flex;align-items:center;gap:6px;font:500 13px/1 var(--ft);white-space:nowrap"><span style="{{ i14.filter }}"></span>All types<span style="{{ i14.chevD }}"></span></div>
|
||||
<div style="height:32px;padding:0 12px;border-radius:999px;border:1px solid var(--ln);display:flex;align-items:center;gap:6px;font:500 13px/1 var(--ft);white-space:nowrap">Modified<span style="{{ i14.chevD }}"></span></div>
|
||||
<div style="height:32px;padding:0 12px;border-radius:999px;border:1px solid var(--ln);display:flex;align-items:center;gap:6px;font:500 13px/1 var(--ft);white-space:nowrap">Shared<span style="{{ i14.chevD }}"></span></div>
|
||||
<div style="height:32px;padding:0 12px;border-radius:999px;background:var(--acs);color:var(--act);display:flex;align-items:center;gap:6px;font:600 13px/1 var(--ft);white-space:nowrap"><span style="{{ i14.offline }}"></span>Available offline<span style="{{ i14.x }}"></span></div>
|
||||
<div style="flex:1"></div>
|
||||
<div style="font:400 13px/1 var(--ft);color:var(--fg3)">10 items · 440 MB</div>
|
||||
</div>
|
||||
</sc-if>
|
||||
<sc-if value="{{ s.trash }}">
|
||||
<div style="flex:none;margin:16px 0 4px;padding:12px 16px;border-radius:14px;background:var(--sf2);display:flex;gap:10px;align-items:center;color:var(--fg2);font:400 14px/1.2 var(--ft)"><span style="{{ i18.info }}"></span>Items here are deleted for good after 30 days.</div>
|
||||
</sc-if>
|
||||
<sc-if value="{{ s.offline }}">
|
||||
<div style="flex:none;display:grid;grid-template-columns:minmax(0,2fr) repeat(3,minmax(0,1fr));gap:12px;padding:18px 0 8px">
|
||||
<div style="padding:16px 18px;border-radius:18px;background:var(--sf2);display:flex;flex-direction:column;gap:10px"><div style="display:flex;justify-content:space-between;align-items:baseline"><div style="font:600 28px/0.9 var(--fd);letter-spacing:-0.03em">2.4 GB</div><div style="font:400 13px/1 var(--ft);color:var(--fg3)">of 5 GB limit</div></div><div style="height:6px;border-radius:999px;background:var(--sf3);overflow:hidden"><div style="width:48%;height:100%;background:var(--ac)"></div></div></div>
|
||||
<div style="padding:16px 18px;border-radius:18px;background:var(--sf2);display:flex;flex-direction:column;gap:8px"><div style="font:600 28px/0.9 var(--fd);letter-spacing:-0.03em">142</div><div style="font:400 13px/1 var(--ft);color:var(--fg2)">Files up to date</div></div>
|
||||
<div style="padding:16px 18px;border-radius:18px;background:var(--sf2);display:flex;flex-direction:column;gap:8px"><div style="font:600 28px/0.9 var(--fd);letter-spacing:-0.03em;color:var(--act)">6</div><div style="font:400 13px/1 var(--ft);color:var(--fg2)">Syncing now</div></div>
|
||||
<div style="padding:16px 18px;border-radius:18px;background:var(--dgs);display:flex;flex-direction:column;gap:8px"><div style="font:600 28px/0.9 var(--fd);letter-spacing:-0.03em;color:var(--dg)">1</div><div style="font:400 13px/1 var(--ft);color:var(--dg)">Needs attention</div></div>
|
||||
</div>
|
||||
</sc-if>
|
||||
<sc-if value="{{ s.shares }}">
|
||||
<div style="flex:none;display:flex;padding:14px 0 8px"><div style="display:flex;padding:3px;border-radius:999px;background:var(--sf2);gap:2px">
|
||||
<div style="height:32px;padding:0 16px;border-radius:999px;background:var(--acs);color:var(--act);display:flex;align-items:center;font:600 13px/1 var(--ft);white-space:nowrap">With you</div>
|
||||
<div style="height:32px;padding:0 16px;display:flex;align-items:center;font:500 13px/1 var(--ft);color:var(--fg2)">By you</div>
|
||||
<div style="height:32px;padding:0 16px;display:flex;align-items:center;font:500 13px/1 var(--ft);color:var(--fg2)">Links</div>
|
||||
</div></div>
|
||||
</sc-if>
|
||||
|
||||
<sc-if value="{{ showTable }}">
|
||||
<sc-for list="{{ groups }}" as="g" hint-placeholder-count="1">
|
||||
<sc-if value="{{ g.hasLabel }}"><div style="padding:18px 12px 6px;font:600 13px/1 var(--ft);color:var(--fg2)">{{ g.label }}</div></sc-if>
|
||||
<div style="display:grid;grid-template-columns:minmax(0,1fr) 180px 160px 120px;align-items:center;height:36px;padding:0 12px;border-bottom:1px solid var(--ln);font:600 12px/1 var(--ft);color:var(--fg3)">
|
||||
<div style="display:flex;align-items:center;gap:4px">{{ c0 }}<sc-if value="{{ sortable }}"><span style="{{ i14.up }}"></span></sc-if></div><div>{{ c1 }}</div><div>{{ c2 }}</div><div></div>
|
||||
</div>
|
||||
<sc-for list="{{ g.rows }}" as="f" hint-placeholder-count="8">
|
||||
<div style="{{ f.rs }}">
|
||||
<div style="display:flex;align-items:center;gap:12px;min-width:0"><div style="{{ f.tile }}"><span style="{{ f.ico }}"></span></div><div style="font:500 14px/1.2 var(--ft);white-space:nowrap;overflow:hidden;text-overflow:ellipsis">{{ f.name }}</div></div>
|
||||
<div style="font:400 13px/1.2 var(--ft);color:var(--fg2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis">{{ f.a }}</div>
|
||||
<div style="display:flex;align-items:center;gap:6px;font:400 13px/1.2 var(--ft);color:var(--fg2);white-space:nowrap;overflow:hidden"><sc-if value="{{ f.bInline }}"><span style="{{ f.badge }}"></span></sc-if>{{ f.b }}</div>
|
||||
<div style="display:flex;align-items:center;justify-content:flex-end;gap:10px;color:var(--fg3)">
|
||||
<sc-if value="{{ f.bIcon }}"><span style="{{ f.badge }}"></span></sc-if>
|
||||
<sc-if value="{{ f.shared }}"><span style="{{ i16.users }}"></span></sc-if>
|
||||
<sc-if value="{{ f.fav }}"><span style="{{ starSm }}"></span></sc-if>
|
||||
<sc-if value="{{ restore }}"><div style="height:28px;padding:0 12px;border-radius:999px;background:var(--acs);color:var(--act);display:flex;align-items:center;gap:6px;font:600 12px/1 var(--ft);white-space:nowrap"><span style="{{ i14.restore }}"></span>Restore</div></sc-if>
|
||||
<span style="{{ i18.moreH }}"></span>
|
||||
</div>
|
||||
</div>
|
||||
</sc-for>
|
||||
</sc-for>
|
||||
</sc-if>
|
||||
|
||||
<sc-if value="{{ showGrid }}">
|
||||
<div style="display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:16px;padding-top:6px">
|
||||
<sc-for list="{{ gridRows }}" as="f" hint-placeholder-count="10">
|
||||
<div style="border:1px solid var(--ln);border-radius:18px;overflow:hidden;display:flex;flex-direction:column;background:var(--sf)">
|
||||
<div style="{{ f.thumb }}"><span style="{{ f.icoL }}"></span></div>
|
||||
<div style="padding:10px 10px 12px 14px;display:flex;flex-direction:column;gap:5px">
|
||||
<div style="display:flex;align-items:center;gap:4px"><div style="flex:1;min-width:0;font:500 14px/1.2 var(--ft);white-space:nowrap;overflow:hidden;text-overflow:ellipsis">{{ f.name }}</div><span style="{{ moreSm }}"></span></div>
|
||||
<div style="display:flex;align-items:center;gap:5px;font:400 12px/1.2 var(--ft);color:var(--fg3)"><sc-if value="{{ f.hasBadge }}"><span style="{{ f.badge }}"></span></sc-if>{{ f.meta }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</sc-for>
|
||||
</div>
|
||||
</sc-if>
|
||||
|
||||
<sc-if value="{{ s.photos }}">
|
||||
<div style="flex:none;display:flex;gap:8px;padding:14px 0 4px">
|
||||
<div style="height:32px;padding:0 14px;border-radius:999px;background:var(--acs);color:var(--act);display:flex;align-items:center;font:600 13px/1 var(--ft);white-space:nowrap">All</div>
|
||||
<div style="height:32px;padding:0 14px;border-radius:999px;border:1px solid var(--ln);display:flex;align-items:center;font:500 13px/1 var(--ft);white-space:nowrap">Photos</div>
|
||||
<div style="height:32px;padding:0 14px;border-radius:999px;border:1px solid var(--ln);display:flex;align-items:center;font:500 13px/1 var(--ft);white-space:nowrap">Videos</div>
|
||||
<div style="height:32px;padding:0 14px;border-radius:999px;border:1px solid var(--ln);display:flex;align-items:center;gap:6px;font:500 13px/1 var(--ft);white-space:nowrap"><span style="{{ i14.camera }}"></span>Camera uploads</div>
|
||||
</div>
|
||||
<sc-for list="{{ photoGroups }}" as="g" hint-placeholder-count="2">
|
||||
<div style="display:flex;justify-content:space-between;align-items:baseline;padding:16px 0 10px"><div style="font:500 18px/1 var(--fd);letter-spacing:-0.02em">{{ g.label }}</div><div style="font:400 13px/1 var(--ft);color:var(--fg3)">{{ g.count }}</div></div>
|
||||
<div style="display:grid;grid-template-columns:repeat(8,minmax(0,1fr));gap:4px">
|
||||
<sc-for list="{{ g.tiles }}" as="t" hint-placeholder-count="16">
|
||||
<div style="{{ t.s }}"><sc-if value="{{ t.vid }}"><div style="position:absolute;right:6px;bottom:6px;height:20px;padding:0 7px 0 5px;border-radius:999px;background:rgba(14,13,11,0.7);color:#FFFFFF;display:flex;align-items:center;gap:3px;font:600 11px/1 var(--ft)"><span style="{{ i14.play }}"></span>{{ t.dur }}</div></sc-if></div>
|
||||
</sc-for>
|
||||
</div>
|
||||
</sc-for>
|
||||
</sc-if>
|
||||
|
||||
<sc-if value="{{ s.activity }}">
|
||||
<div style="max-width:760px;width:100%;display:flex;flex-direction:column">
|
||||
<sc-for list="{{ act }}" as="g" hint-placeholder-count="2">
|
||||
<div style="padding:20px 0 8px;font:600 13px/1 var(--ft);color:var(--fg2)">{{ g.label }}</div>
|
||||
<sc-for list="{{ g.items }}" as="a" hint-placeholder-count="3">
|
||||
<div style="display:flex;gap:14px;padding:14px 0;align-items:center;border-bottom:1px solid var(--ln)">
|
||||
<div style="{{ a.av }}">{{ a.who }}</div>
|
||||
<div style="flex:1;min-width:0;font:400 14px/1.3 var(--ft)"><span style="font-weight:600">{{ a.name }}</span> {{ a.verb }} <span style="font-weight:600">{{ a.obj }}</span> {{ a.tail }}</div>
|
||||
<div style="{{ a.tile }}"><span style="{{ a.ico }}"></span></div>
|
||||
<div style="width:48px;text-align:right;font:400 13px/1 var(--ft);color:var(--fg3)">{{ a.time }}</div>
|
||||
</div>
|
||||
</sc-for>
|
||||
</sc-for>
|
||||
</div>
|
||||
</sc-if>
|
||||
|
||||
<sc-if value="{{ s.settings }}">
|
||||
<div style="display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:16px;padding:20px 0;align-items:start">
|
||||
<div style="display:flex;flex-direction:column;gap:16px">
|
||||
<div style="padding:20px;border-radius:20px;border:1px solid var(--ln);display:flex;flex-direction:column;gap:16px">
|
||||
<div style="display:flex;gap:14px;align-items:center"><div style="width:52px;height:52px;border-radius:999px;background:var(--acs);color:var(--act);display:flex;align-items:center;justify-content:center;font:600 18px/1 var(--ft);flex:none">MR</div><div style="flex:1;display:flex;flex-direction:column;gap:5px"><div style="font:500 20px/1 var(--fd);letter-spacing:-0.02em">Marina Rocha</div><div style="font:400 14px/1 var(--ft);color:var(--fg2)">marina@rocha.family</div></div><div style="height:24px;padding:0 10px;border-radius:999px;background:var(--oks);color:var(--ok);display:flex;align-items:center;font:600 12px/1 var(--ft);white-space:nowrap">Connected</div></div>
|
||||
<div style="display:grid;grid-template-columns:auto minmax(0,1fr);gap:10px 16px;font:400 14px/1.2 var(--ft)"><span style="color:var(--fg3)">Server</span><span>cloud.rocha.family</span><span style="color:var(--fg3)">Version</span><span>Nextcloud 30.0.2</span><span style="color:var(--fg3)">Storage</span><div style="display:flex;align-items:center;gap:10px"><div style="flex:1;height:6px;border-radius:999px;background:var(--sf3);overflow:hidden"><div style="width:38%;height:100%;background:var(--ac)"></div></div><span style="color:var(--fg2)">38.2 of 100 GB</span></div></div>
|
||||
<div style="display:flex;gap:8px"><div style="height:36px;padding:0 16px;border-radius:999px;background:var(--sf2);display:flex;align-items:center;gap:8px;font:600 14px/1 var(--ft);white-space:nowrap"><span style="{{ i14.external }}"></span>Manage on web</div><div style="height:36px;padding:0 16px;border-radius:999px;background:var(--dgs);color:var(--dg);display:flex;align-items:center;gap:8px;font:600 14px/1 var(--ft);white-space:nowrap"><span style="{{ i14.logout }}"></span>Log out</div></div>
|
||||
</div>
|
||||
<div style="padding:8px 20px 12px;border-radius:20px;border:1px solid var(--ln);display:flex;flex-direction:column">
|
||||
<div style="padding:12px 0 8px;font:500 17px/1 var(--fd);letter-spacing:-0.02em">Accounts</div>
|
||||
<div style="display:flex;align-items:center;gap:12px;height:56px;border-bottom:1px solid var(--ln)"><div style="width:32px;height:32px;border-radius:999px;background:var(--acs);color:var(--act);display:flex;align-items:center;justify-content:center;font:600 12px/1 var(--ft)">MR</div><div style="flex:1;display:flex;flex-direction:column;gap:4px"><div style="font:500 14px/1 var(--ft)">Marina Rocha</div><div style="font:400 12px/1 var(--ft);color:var(--fg3)">cloud.rocha.family</div></div><span style="{{ checkA }}"></span></div>
|
||||
<div style="display:flex;align-items:center;gap:12px;height:56px;border-bottom:1px solid var(--ln)"><div style="width:32px;height:32px;border-radius:999px;background:#85D1BD;color:#0E0D0B;display:flex;align-items:center;justify-content:center;font:600 12px/1 var(--ft)">MR</div><div style="flex:1;display:flex;flex-direction:column;gap:4px"><div style="font:500 14px/1 var(--ft)">Marina · Work</div><div style="font:400 12px/1 var(--ft);color:var(--fg3)">files.acme-studio.com</div></div><div style="font:600 13px/1 var(--ft);color:var(--act)">Switch</div></div>
|
||||
<div style="display:flex;align-items:center;gap:12px;height:48px;color:var(--act);font:600 14px/1 var(--ft)"><div style="width:32px;display:flex;justify-content:center"><span style="{{ i18.plus }}"></span></div>Add account</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display:flex;flex-direction:column;gap:16px">
|
||||
<div style="padding:8px 20px 8px;border-radius:20px;border:1px solid var(--ln);display:flex;flex-direction:column">
|
||||
<div style="padding:12px 0 8px;font:500 17px/1 var(--fd);letter-spacing:-0.02em">Security</div>
|
||||
<div style="display:flex;align-items:center;gap:14px;min-height:60px;border-bottom:1px solid var(--ln)"><span style="{{ bioIco }}"></span><div style="flex:1;display:flex;flex-direction:column;gap:4px"><div style="font:400 14px/1.1 var(--ft)">{{ bioLabel }}</div><div style="font:400 12px/1.2 var(--ft);color:var(--fg3)">Needed every time you open Noo</div></div><div style="width:44px;height:26px;border-radius:999px;background:var(--ac);padding:3px;box-sizing:border-box;display:flex;justify-content:flex-end;flex:none"><div style="width:20px;height:20px;border-radius:999px;background:#FFFFFF"></div></div></div>
|
||||
<div style="display:flex;align-items:center;gap:14px;height:52px"><span style="{{ i18.timer }}"></span><div style="flex:1;font:400 14px/1 var(--ft)">Lock after</div><div style="height:32px;padding:0 10px 0 12px;border-radius:10px;border:1px solid var(--ln);display:flex;align-items:center;gap:6px;font:500 13px/1 var(--ft)">5 minutes idle<span style="{{ i14.chevD }}"></span></div></div>
|
||||
</div>
|
||||
<div style="padding:8px 20px 8px;border-radius:20px;border:1px solid var(--ln);display:flex;flex-direction:column">
|
||||
<div style="padding:12px 0 8px;font:500 17px/1 var(--fd);letter-spacing:-0.02em">File sync</div>
|
||||
<div style="display:flex;align-items:center;gap:14px;min-height:60px;border-bottom:1px solid var(--ln)"><span style="{{ i18.folder }}"></span><div style="flex:1;display:flex;flex-direction:column;gap:4px"><div style="font:400 14px/1.1 var(--ft)">Local sync folder</div><div style="font:400 12px/1.2 var(--ft);color:var(--fg3);font-family:ui-monospace,Menlo,monospace">{{ syncPath }}</div></div><div style="height:32px;padding:0 12px;border-radius:999px;background:var(--sf2);display:flex;align-items:center;font:600 13px/1 var(--ft);white-space:nowrap">Change</div></div>
|
||||
<div style="display:flex;align-items:center;gap:14px;height:52px;border-bottom:1px solid var(--ln)"><span style="{{ i18.sync }}"></span><div style="flex:1;font:400 14px/1 var(--ft)">Sync automatically</div><div style="width:44px;height:26px;border-radius:999px;background:var(--ac);padding:3px;box-sizing:border-box;display:flex;justify-content:flex-end;flex:none"><div style="width:20px;height:20px;border-radius:999px;background:#FFFFFF"></div></div></div>
|
||||
<div style="display:flex;align-items:center;gap:14px;height:52px;border-bottom:1px solid var(--ln)"><span style="{{ i18.download }}"></span><div style="flex:1;font:400 14px/1 var(--ft)">Download files on demand</div><div style="width:44px;height:26px;border-radius:999px;background:var(--ac);padding:3px;box-sizing:border-box;display:flex;justify-content:flex-end;flex:none"><div style="width:20px;height:20px;border-radius:999px;background:#FFFFFF"></div></div></div>
|
||||
<div style="display:flex;align-items:center;gap:14px;height:52px"><span style="{{ i18.wifi }}"></span><div style="flex:1;font:400 14px/1 var(--ft)">Pause on metered networks</div><div style="width:44px;height:26px;border-radius:999px;background:var(--sf3);padding:3px;box-sizing:border-box;display:flex;justify-content:flex-start;flex:none"><div style="width:20px;height:20px;border-radius:999px;background:#FFFFFF"></div></div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</sc-if>
|
||||
|
||||
<sc-if value="{{ s.settings2 }}">
|
||||
<div style="display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:16px;padding:20px 0;align-items:start">
|
||||
<div style="display:flex;flex-direction:column;gap:16px">
|
||||
<div style="padding:8px 20px 8px;border-radius:20px;border:1px solid var(--ln);display:flex;flex-direction:column">
|
||||
<div style="padding:12px 0 8px;font:500 17px/1 var(--fd);letter-spacing:-0.02em">Files cache</div>
|
||||
<div style="display:flex;flex-direction:column;gap:10px;padding:10px 0 14px;border-bottom:1px solid var(--ln)"><div style="display:flex;justify-content:space-between;font:400 14px/1 var(--ft)"><span>Cache in use</span><span style="color:var(--fg2)">1.2 of 2 GB</span></div><div style="height:6px;border-radius:999px;background:var(--sf3);overflow:hidden"><div style="width:60%;height:100%;background:var(--ac)"></div></div></div>
|
||||
<div style="display:flex;align-items:center;gap:14px;height:52px;border-bottom:1px solid var(--ln)"><span style="{{ i18.database }}"></span><div style="flex:1;font:400 14px/1 var(--ft)">Cache limit</div><div style="height:32px;padding:0 10px 0 12px;border-radius:10px;border:1px solid var(--ln);display:flex;align-items:center;gap:6px;font:500 13px/1 var(--ft)">2 GB<span style="{{ i14.chevD }}"></span></div></div>
|
||||
<div style="display:flex;align-items:center;gap:14px;height:52px"><span style="{{ i18.trash }}"></span><div style="flex:1;font:400 14px/1 var(--ft)">Clear cached files</div><div style="height:32px;padding:0 14px;border-radius:999px;background:var(--dgs);color:var(--dg);display:flex;align-items:center;font:600 13px/1 var(--ft);white-space:nowrap">Clear cache</div></div>
|
||||
</div>
|
||||
<div style="padding:8px 20px 8px;border-radius:20px;border:1px solid var(--ln);display:flex;flex-direction:column">
|
||||
<div style="padding:12px 0 8px;font:500 17px/1 var(--fd);letter-spacing:-0.02em">Appearance</div>
|
||||
<div style="display:flex;align-items:center;gap:14px;height:56px;border-bottom:1px solid var(--ln)"><span style="{{ i18.palette }}"></span><div style="flex:1;font:400 14px/1 var(--ft)">Theme</div><div style="display:flex;padding:3px;border-radius:999px;background:var(--sf2);gap:2px"><div style="height:28px;padding:0 12px;border-radius:999px;background:var(--acs);color:var(--act);display:flex;align-items:center;font:600 13px/1 var(--ft);white-space:nowrap">System</div><div style="height:28px;padding:0 12px;display:flex;align-items:center;font:500 13px/1 var(--ft);color:var(--fg2)">Light</div><div style="height:28px;padding:0 12px;display:flex;align-items:center;font:500 13px/1 var(--ft);color:var(--fg2)">Dark</div></div></div>
|
||||
<div style="display:flex;align-items:center;gap:14px;height:56px;border-bottom:1px solid var(--ln)"><span style="{{ i18.grid }}"></span><div style="flex:1;font:400 14px/1 var(--ft)">Default file view</div><div style="display:flex;padding:3px;border-radius:999px;background:var(--sf2);gap:2px"><div style="height:28px;padding:0 12px;border-radius:999px;background:var(--acs);color:var(--act);display:flex;align-items:center;gap:6px;font:600 13px/1 var(--ft);white-space:nowrap"><span style="{{ i14.list }}"></span>List</div><div style="height:28px;padding:0 12px;display:flex;align-items:center;gap:6px;font:500 13px/1 var(--ft);color:var(--fg2)"><span style="{{ i14.grid }}"></span>Grid</div></div></div>
|
||||
<div style="display:flex;align-items:center;gap:14px;height:52px"><span style="{{ i18.hidden }}"></span><div style="flex:1;font:400 14px/1 var(--ft)">Show hidden files</div><div style="width:44px;height:26px;border-radius:999px;background:var(--sf3);padding:3px;box-sizing:border-box;display:flex;justify-content:flex-start;flex:none"><div style="width:20px;height:20px;border-radius:999px;background:#FFFFFF"></div></div></div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display:flex;flex-direction:column;gap:16px">
|
||||
<div style="padding:8px 20px 12px;border-radius:20px;border:1px solid var(--ln);display:flex;flex-direction:column">
|
||||
<div style="padding:12px 0 4px;display:flex;justify-content:space-between;align-items:baseline"><div style="font:500 17px/1 var(--fd);letter-spacing:-0.02em">Sidebar tabs</div><div style="font:400 12px/1 var(--ft);color:var(--fg3)">Drag to reorder</div></div>
|
||||
<div style="padding:4px 0 8px;font:400 12px/1.3 var(--ft);color:var(--fg3)">Pinned tabs show at the top of the sidebar, and in the bottom bar on mobile.</div>
|
||||
<sc-for list="{{ tabRows }}" as="t" hint-placeholder-count="8">
|
||||
<div style="display:flex;align-items:center;gap:12px;height:44px;border-bottom:1px solid var(--ln)"><span style="{{ gripS }}"></span><span style="{{ t.ico }}"></span><div style="flex:1;font:400 14px/1 var(--ft)">{{ t.label }}</div><div style="{{ t.pinS }}"><span style="{{ t.pinI }}"></span></div></div>
|
||||
</sc-for>
|
||||
</div>
|
||||
<div style="padding:8px 20px 8px;border-radius:20px;border:1px solid var(--ln);display:flex;flex-direction:column">
|
||||
<div style="padding:12px 0 8px;font:500 17px/1 var(--fd);letter-spacing:-0.02em">{{ swipeTitle }}</div>
|
||||
<div style="display:flex;align-items:center;gap:14px;height:52px;border-bottom:1px solid var(--ln)"><span style="{{ i18.swipe }}"></span><div style="flex:1;font:400 14px/1 var(--ft)">Swipe left</div><div style="height:32px;padding:0 10px 0 12px;border-radius:10px;border:1px solid var(--ln);display:flex;align-items:center;gap:6px;font:500 13px/1 var(--ft);color:var(--dg)"><span style="{{ i14.trash }}"></span>Delete<span style="{{ i14.chevD }}"></span></div></div>
|
||||
<div style="display:flex;align-items:center;gap:14px;height:52px"><span style="{{ i18.swipe }}"></span><div style="flex:1;font:400 14px/1 var(--ft)">Swipe right</div><div style="height:32px;padding:0 10px 0 12px;border-radius:10px;border:1px solid var(--ln);display:flex;align-items:center;gap:6px;font:500 13px/1 var(--ft);color:var(--act)"><span style="{{ i14.star }}"></span>Favorite<span style="{{ i14.chevD }}"></span></div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</sc-if>
|
||||
|
||||
</div>
|
||||
|
||||
<sc-if value="{{ share }}">
|
||||
<div style="position:absolute;inset:0;background:var(--scrim);display:flex;align-items:center;justify-content:center">
|
||||
<div style="width:540px;background:var(--sf);border-radius:24px;padding:24px;box-sizing:border-box;display:flex;flex-direction:column;gap:20px;box-shadow:0 24px 48px rgba(30,0,47,0.14)">
|
||||
<div style="display:flex;gap:12px;align-items:center">
|
||||
<div style="{{ shareTile }}"><span style="{{ i20.doc }}"></span></div>
|
||||
<div style="flex:1;min-width:0;display:flex;flex-direction:column;gap:5px"><div style="font:500 19px/1 var(--fd);letter-spacing:-0.02em">Share “Q3 Planning.pdf”</div><div style="font:400 13px/1 var(--ft);color:var(--fg3)">2.4 MB · Documents</div></div>
|
||||
<div style="width:32px;height:32px;border-radius:999px;background:var(--sf2);display:flex;align-items:center;justify-content:center"><span style="{{ i16.x }}"></span></div>
|
||||
</div>
|
||||
<div style="display:flex;flex-direction:column;gap:12px">
|
||||
<div style="font:500 16px/1 var(--fd);letter-spacing:-0.02em">Share with people</div>
|
||||
<div style="display:flex;gap:8px"><div style="flex:1;height:42px;border-radius:12px;background:var(--sf2);display:flex;align-items:center;gap:10px;padding:0 12px;color:var(--fg3);font:400 14px/1 var(--ft)"><span style="{{ i18.userPlus }}"></span>Name, email or group</div><div style="height:42px;padding:0 10px 0 14px;border-radius:12px;border:1px solid var(--ln);display:flex;align-items:center;gap:6px;font:500 13px/1 var(--ft)">Can edit<span style="{{ i14.chevD }}"></span></div></div>
|
||||
<div style="display:flex;align-items:center;gap:12px;height:44px"><div style="{{ avYou }}">MR</div><div style="flex:1;display:flex;flex-direction:column;gap:4px"><div style="font:500 14px/1 var(--ft)">You</div><div style="font:400 12px/1 var(--ft);color:var(--fg3)">marina@rocha.family</div></div><div style="font:500 13px/1 var(--ft);color:var(--fg3)">Owner</div></div>
|
||||
<div style="display:flex;align-items:center;gap:12px;height:44px"><div style="{{ avAna }}">AS</div><div style="flex:1;display:flex;flex-direction:column;gap:4px"><div style="font:500 14px/1 var(--ft)">Ana Souza</div><div style="font:400 12px/1 var(--ft);color:var(--fg3)">ana@rocha.family</div></div><div style="height:28px;padding:0 8px 0 12px;border-radius:999px;border:1px solid var(--ln);display:flex;align-items:center;gap:4px;font:500 12px/1 var(--ft);white-space:nowrap">Can edit<span style="{{ i14.chevD }}"></span></div></div>
|
||||
<div style="display:flex;align-items:center;gap:12px;height:44px"><div style="width:32px;height:32px;border-radius:999px;background:var(--sf2);color:var(--fg2);display:flex;align-items:center;justify-content:center;flex:none"><span style="{{ i16.users }}"></span></div><div style="flex:1;display:flex;flex-direction:column;gap:4px"><div style="font:500 14px/1 var(--ft)">Design team</div><div style="font:400 12px/1 var(--ft);color:var(--fg3)">Group · 6 people</div></div><div style="height:28px;padding:0 8px 0 12px;border-radius:999px;border:1px solid var(--ln);display:flex;align-items:center;gap:4px;font:500 12px/1 var(--ft);white-space:nowrap">Can view<span style="{{ i14.chevD }}"></span></div></div>
|
||||
</div>
|
||||
<div style="height:1px;background:var(--ln)"></div>
|
||||
<div style="display:flex;flex-direction:column;gap:12px">
|
||||
<div style="display:flex;justify-content:space-between;align-items:center"><div style="display:flex;flex-direction:column;gap:5px"><div style="font:500 16px/1 var(--fd);letter-spacing:-0.02em">Share link</div><div style="font:400 12px/1 var(--ft);color:var(--fg3)">Anyone with the link can view</div></div><div style="width:44px;height:26px;border-radius:999px;background:var(--ac);padding:3px;box-sizing:border-box;display:flex;justify-content:flex-end;flex:none"><div style="width:20px;height:20px;border-radius:999px;background:#FFFFFF"></div></div></div>
|
||||
<div style="border-radius:14px;background:var(--sf2);padding:5px 5px 5px 14px;display:flex;gap:10px;align-items:center;color:var(--fg2)"><span style="{{ i16.link }}"></span><div style="flex:1;min-width:0;font:400 13px/1 ui-monospace,Menlo,monospace;color:var(--fg1);white-space:nowrap;overflow:hidden;text-overflow:ellipsis">https://cloud.rocha.family/s/k7Pq2xW</div><div style="height:34px;padding:0 14px;border-radius:999px;background:var(--ac);color:#FFFFFF;display:flex;align-items:center;gap:6px;font:600 13px/1 var(--ft);white-space:nowrap"><span style="{{ i14.copy }}"></span>Copy link</div></div>
|
||||
<div style="display:flex;gap:8px;flex-wrap:wrap">
|
||||
<div style="height:30px;padding:0 12px;border-radius:999px;border:1px solid var(--ln);display:flex;align-items:center;gap:6px;font:500 12px/1 var(--ft);white-space:nowrap"><span style="{{ i14.eye }}"></span>Can view<span style="{{ i14.chevD }}"></span></div>
|
||||
<div style="height:30px;padding:0 12px;border-radius:999px;background:var(--acs);color:var(--act);display:flex;align-items:center;gap:6px;font:600 12px/1 var(--ft);white-space:nowrap"><span style="{{ i14.calendar }}"></span>Expires Oct 24</div>
|
||||
<div style="height:30px;padding:0 12px;border-radius:999px;border:1px solid var(--ln);display:flex;align-items:center;gap:6px;font:500 12px/1 var(--ft);white-space:nowrap"><span style="{{ i14.lock }}"></span>Add password</div>
|
||||
<div style="height:30px;padding:0 12px;border-radius:999px;border:1px solid var(--ln);display:flex;align-items:center;gap:6px;font:500 12px/1 var(--ft);white-space:nowrap"><span style="{{ i14.download }}"></span>Allow download</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="height:1px;background:var(--ln)"></div>
|
||||
<div style="display:flex;align-items:center;gap:12px">
|
||||
<div style="flex:1;font:400 12px/1.3 var(--ft);color:var(--fg3)">Sends a copy through another app. Link settings don’t apply.</div>
|
||||
<div style="height:38px;padding:0 16px;border-radius:999px;border:1.5px solid var(--sf3);display:flex;align-items:center;gap:8px;font:600 14px/1 var(--ft);white-space:nowrap"><span style="{{ i16.send }}"></span>Send file directly</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</sc-if>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</sc-if>
|
||||
</x-dc>
|
||||
<script type="text/x-dc" data-dc-script data-props="{"$preview":{"width":1280,"height":800},"os":{"editor":"enum","options":["mac","windows"],"default":"mac","tsType":"'mac'|'windows'"},"screen":{"editor":"enum","options":["files","filesGrid","photos","favorites","offline","shares","recent","activity","trash","share","settings","settings2"],"default":"files","tsType":"string"},"theme":{"editor":"enum","options":["light","dark"],"default":"light","tsType":"'light'|'dark'"}}">
|
||||
class Component extends DCLogic {
|
||||
componentDidMount() {
|
||||
if (!window.NK) this._t = setInterval(() => { if (window.NK) { clearInterval(this._t); this.forceUpdate(); } }, 40);
|
||||
}
|
||||
componentWillUnmount() { clearInterval(this._t); }
|
||||
renderVals() {
|
||||
const K = window.NK;
|
||||
if (!K) return { ready: false };
|
||||
const { I, ic, D, row, TH, tile, tiles, avatar } = K;
|
||||
const mac = this.props.os !== 'windows', win = !mac;
|
||||
const sc = this.props.screen || 'files';
|
||||
const theme = this.props.theme === 'dark' ? 'dark' : 'light';
|
||||
const share = sc === 'share', grid = sc === 'filesGrid';
|
||||
const base = (share || grid) ? 'files' : sc;
|
||||
const settings = base.startsWith('settings');
|
||||
const s = {}; ['files','photos','activity','trash','favorites','offline','shares','recent','settings','settings2'].forEach(k => s[k] = base === k);
|
||||
const RS = sel => ({ display: 'grid', gridTemplateColumns: 'minmax(0,1fr) 180px 160px 120px', alignItems: 'center', height: 52, padding: '0 12px', borderBottom: '1px solid var(--ln)', background: sel ? 'var(--acs)' : 'transparent', borderRadius: sel ? 12 : 0 });
|
||||
const mk = (list, fn, o = {}) => list.map((f, i) => { const r = row(f, { tile: 30, r: 9, ico: 16, ...o }); Object.assign(r, fn(f)); r.rs = RS(o.sel === i); return r; });
|
||||
let groups = [], cols = ['Name', 'Size', 'Modified'];
|
||||
const split = f => { const p = (f.meta || '').split(' · '); return { a: p[0], b: p[1] || '' }; };
|
||||
if (base === 'files') groups = [{ rows: mk(D.files, f => ({ a: f.size, b: f.mod, bIcon: !!f.off }), { noSwipe: 1, sel: 3 }) }];
|
||||
if (base === 'favorites') groups = [{ rows: mk(D.favorites, f => ({ a: f.size, b: f.mod, bIcon: !!f.off, fav: true })) }];
|
||||
if (base === 'offline') { cols = ['Name', 'Size', 'Status']; groups = [{ rows: mk(D.offline, f => ({ a: f.size, b: split(f).a, bInline: true })) }]; }
|
||||
if (base === 'shares') { cols = ['Name', 'Shared by', 'Permission']; groups = [{ rows: mk(D.shares, f => ({ a: f.by, b: f.perm })) }]; }
|
||||
if (base === 'recent') { cols = ['Name', 'Activity', 'Location']; groups = D.recent.map(g => ({ label: g.label, rows: mk(g.rows, f => ({ ...split(f), bIcon: !!f.off })) })); }
|
||||
if (base === 'trash') { cols = ['Name', 'Original location', 'Deleted']; groups = [{ rows: mk(D.trash, f => ({ a: f.from, b: f.del })) }]; }
|
||||
groups = groups.map(g => ({ ...g, hasLabel: !!g.label }));
|
||||
const title = settings ? 'Settings' : D.titles[base];
|
||||
const seg = on => ({ width: 34, height: 30, borderRadius: 999, display: 'flex', alignItems: 'center', justifyContent: 'center', background: on ? 'var(--acs)' : 'transparent', color: on ? 'var(--act)' : 'var(--fg3)' });
|
||||
const counts = { trash: '12', offline: '1', shares: '3' };
|
||||
const navItem = ([label, ico, key]) => ({ label, ico: I[18][ico], icoG: ic(ico, 18, 'var(--fg2)'), on: key === base, off: key !== base, count: counts[key] || '' });
|
||||
return {
|
||||
ready: true, mac, win, s, title, groups, c0: cols[0], c1: cols[1], c2: cols[2], share, notSettings: !settings,
|
||||
sortable: base === 'files' || base === 'favorites',
|
||||
restore: base === 'trash',
|
||||
root: { ...TH[theme], width: 1280, height: 800, borderRadius: mac ? 12 : 8, overflow: 'hidden', position: 'relative', display: 'flex', flexDirection: 'column', background: 'var(--bg)', color: 'var(--fg1)', fontFamily: 'var(--ft)', border: '1px solid var(--ln)', boxSizing: 'border-box' },
|
||||
i14: I[14], i16: I[16], i18: I[18], i20: I[20], i24: I[24],
|
||||
showTable: groups.length > 0 && !grid, showGrid: grid,
|
||||
gridRows: D.files.map(f => row(f, { noSwipe: 1, thumbH: 118 })).map(r => ({ ...r, meta: `${r.size} · ${r.mod}` })),
|
||||
segL: seg(!grid), segG: seg(grid),
|
||||
navA: D.pinned.map(navItem), navB: D.menu.map(navItem),
|
||||
setOn: settings, setOff: !settings, setIcoG: ic('settings', 18, 'var(--fg2)'),
|
||||
starSm: ic('star', 16, 'var(--act)'), moreSm: ic('moreH', 16, 'var(--fg3)'),
|
||||
checkA: ic('check', 18, 'var(--act)'), chevG: ic('chevR', 16, 'var(--fg3)'), gripS: ic('grip', 16, 'var(--fg3)'),
|
||||
photoGroups: [{ label: 'September 2026', count: '38 items', tiles: tiles(24, 0, [2, 9, 13, 20]) }, { label: 'August 2026', count: '112 items', tiles: tiles(16, 3, [4, 11]) }],
|
||||
act: D.activity.map(g => ({ label: g.label, items: g.items.map(a => ({ ...a, av: avatar(a.col, 36), tile: tile(a.kind, 30, 9), ico: I[16][K.KIND[a.kind][2]] })) })),
|
||||
tabRows: [...D.pinned.map(([label, ico]) => ({ label, ico: I[18][ico], p: 1 })), ...D.menu.map(([label, ico]) => ({ label, ico: I[18][ico], p: 0 }))].map(t => ({ ...t,
|
||||
pinS: { width: 30, height: 30, borderRadius: 999, display: 'flex', alignItems: 'center', justifyContent: 'center', background: t.p ? 'var(--acs)' : 'var(--sf2)', color: t.p ? 'var(--act)' : 'var(--fg3)' },
|
||||
pinI: I[14][t.p ? 'pin' : 'pinOff'] })),
|
||||
bioLabel: mac ? 'Lock with Touch ID' : 'Lock with Windows Hello', bioIco: I[18][mac ? 'fingerprint' : 'face'],
|
||||
syncPath: mac ? '~/Noo/rocha.family' : 'C:\\Users\\Marina\\Noo',
|
||||
swipeTitle: mac ? 'Trackpad swipe on a file' : 'Touch swipe on a file',
|
||||
shareTile: tile('pdf', 40, 12), avYou: avatar('#CBA5FD', 32), avAna: avatar('#DA9AC7', 32)
|
||||
};
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,433 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<script src="./support.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<x-dc>
|
||||
<helmet>
|
||||
<script src="noo-kit.js"></script>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Instrument+Sans:wght@400;500;600&family=Schibsted+Grotesk:wght@500;600&display=swap">
|
||||
<style>
|
||||
body{margin:0}
|
||||
a{color:#8D0DE3;text-decoration:none}
|
||||
a:hover{color:#6E08B3}
|
||||
</style>
|
||||
</helmet>
|
||||
<sc-if value="{{ ready }}" hint-placeholder-val="{{ false }}">
|
||||
<div style="{{ root }}">
|
||||
|
||||
<sc-if value="{{ ios }}">
|
||||
<div style="height:54px;flex:none;display:flex;align-items:center;justify-content:space-between;padding:0 30px 0 46px;position:relative;font:600 17px/1 var(--ft);color:var(--fg1)">
|
||||
<span>9:41</span>
|
||||
<div style="position:absolute;left:50%;top:11px;width:124px;height:36px;margin-left:-62px;border-radius:20px;background:#000000"></div>
|
||||
<div style="display:flex;gap:6px;align-items:center"><span style="{{ i16.signal }}"></span><span style="{{ i16.wifi }}"></span><span style="{{ i24.battery }}"></span></div>
|
||||
</div>
|
||||
</sc-if>
|
||||
<sc-if value="{{ android }}">
|
||||
<div style="height:40px;flex:none;display:flex;align-items:center;justify-content:space-between;padding:0 24px;font:500 14px/1 var(--ft);color:var(--fg1)">
|
||||
<span>9:41</span>
|
||||
<div style="display:flex;gap:6px;align-items:center"><span style="{{ i16.wifi }}"></span><span style="{{ i16.signal }}"></span><span style="{{ i16.battery }}"></span></div>
|
||||
</div>
|
||||
</sc-if>
|
||||
|
||||
<sc-if value="{{ aBar }}">
|
||||
<div style="height:64px;flex:none;display:flex;align-items:center;gap:4px;padding:0 8px 0 4px;color:var(--fg1)">
|
||||
<div style="width:48px;height:48px;display:flex;align-items:center;justify-content:center"><span style="{{ i24.menu }}"></span></div>
|
||||
<div style="flex:1;font:500 22px/1 var(--fd);letter-spacing:-0.02em">{{ title }}</div>
|
||||
<div style="width:48px;height:48px;display:flex;align-items:center;justify-content:center"><span style="{{ i24.search }}"></span></div>
|
||||
<div style="width:48px;height:48px;display:flex;align-items:center;justify-content:center"><div style="width:32px;height:32px;border-radius:999px;background:var(--acs);color:var(--act);display:flex;align-items:center;justify-content:center;font:600 13px/1 var(--ft)">MR</div></div>
|
||||
</div>
|
||||
</sc-if>
|
||||
<sc-if value="{{ aSet }}">
|
||||
<div style="height:64px;flex:none;display:flex;align-items:center;gap:4px;padding:0 8px 0 4px;color:var(--fg1)">
|
||||
<div style="width:48px;height:48px;display:flex;align-items:center;justify-content:center"><span style="{{ i24.back }}"></span></div>
|
||||
<div style="flex:1;font:500 22px/1 var(--fd);letter-spacing:-0.02em">Settings</div>
|
||||
</div>
|
||||
</sc-if>
|
||||
<sc-if value="{{ iBar }}">
|
||||
<div style="height:44px;flex:none;display:flex;align-items:center;justify-content:space-between;padding:0 16px;color:var(--act)">
|
||||
<span style="{{ i24.menu }}"></span>
|
||||
<div style="display:flex;gap:18px;align-items:center"><span style="{{ i24.plus }}"></span><div style="width:30px;height:30px;border-radius:999px;background:var(--acs);color:var(--act);display:flex;align-items:center;justify-content:center;font:600 12px/1 var(--ft)">MR</div></div>
|
||||
</div>
|
||||
<div style="flex:none;padding:2px 16px 12px;font:600 34px/0.9 var(--fd);letter-spacing:-0.03em;color:var(--fg1)">{{ title }}</div>
|
||||
<div style="flex:none;margin:0 16px 12px;height:38px;border-radius:12px;background:var(--sf);display:flex;align-items:center;gap:8px;padding:0 10px;color:var(--fg3);font:400 16px/1 var(--ft)"><span style="{{ i18.search }}"></span>Search</div>
|
||||
</sc-if>
|
||||
<sc-if value="{{ iSet }}">
|
||||
<div style="height:44px;flex:none;display:flex;align-items:center;gap:2px;padding:0 10px;color:var(--act);font:400 17px/1 var(--ft)"><span style="{{ i24.chevL }}"></span>Files</div>
|
||||
<div style="flex:none;padding:2px 16px 14px;font:600 34px/0.9 var(--fd);letter-spacing:-0.03em;color:var(--fg1)">Settings</div>
|
||||
</sc-if>
|
||||
|
||||
<div style="flex:1;min-height:0;position:relative;overflow:hidden;display:flex;flex-direction:column">
|
||||
|
||||
<sc-if value="{{ s.files }}">
|
||||
<div style="flex:none;display:flex;align-items:center;gap:8px;padding:4px 12px 12px 12px">
|
||||
<div style="height:34px;padding:0 12px;border-radius:999px;background:var(--sf);display:flex;align-items:center;gap:6px;font:500 14px/1 var(--ft);color:var(--fg1);white-space:nowrap"><span style="{{ i16.sort }}"></span>Name<span style="{{ i14.up }}"></span></div>
|
||||
<div style="height:34px;padding:0 12px;border-radius:999px;background:var(--sf);display:flex;align-items:center;gap:6px;font:500 14px/1 var(--ft);color:var(--fg1);white-space:nowrap"><span style="{{ i16.filter }}"></span><span style="white-space:nowrap">All types</span><span style="{{ i14.chevD }}"></span></div>
|
||||
<div style="flex:1"></div>
|
||||
<div style="display:flex;padding:3px;border-radius:999px;background:var(--sf);gap:2px">
|
||||
<div style="{{ segL }}"><span style="{{ i18.list }}"></span></div>
|
||||
<div style="{{ segG }}"><span style="{{ i18.grid }}"></span></div>
|
||||
</div>
|
||||
</div>
|
||||
</sc-if>
|
||||
|
||||
<sc-if value="{{ s.trash }}">
|
||||
<div style="flex:none;margin:0 12px 16px;padding:14px 16px;border-radius:20px;background:var(--sf);display:flex;gap:12px;align-items:center;color:var(--fg2)">
|
||||
<span style="{{ i20.info }}"></span>
|
||||
<div style="flex:1;font:400 14px/1.3 var(--ft);text-wrap:pretty">Items here are deleted for good after 30 days.</div>
|
||||
<div style="font:600 14px/1 var(--ft);color:var(--dg);white-space:nowrap">Empty trash</div>
|
||||
</div>
|
||||
</sc-if>
|
||||
|
||||
<sc-if value="{{ s.offline }}">
|
||||
<div style="flex:none;margin:0 12px 16px;padding:18px;border-radius:20px;background:var(--sf);display:flex;flex-direction:column;gap:14px">
|
||||
<div style="display:flex;justify-content:space-between;align-items:flex-end;gap:12px">
|
||||
<div style="display:flex;flex-direction:column;gap:6px"><div style="font:600 32px/0.9 var(--fd);letter-spacing:-0.03em">2.4 GB</div><div style="font:400 14px/1.2 var(--ft);color:var(--fg2)">of your 5 GB offline limit</div></div>
|
||||
<div style="height:36px;padding:0 14px;border-radius:999px;background:var(--acs);color:var(--act);display:flex;align-items:center;gap:6px;font:600 14px/1 var(--ft);white-space:nowrap"><span style="{{ i16.sync }}"></span>Sync now</div>
|
||||
</div>
|
||||
<div style="height:6px;border-radius:999px;background:var(--sf3);overflow:hidden"><div style="width:48%;height:100%;background:var(--ac)"></div></div>
|
||||
<div style="font:400 13px/1.2 var(--ft);color:var(--fg3)">Last synced 2 minutes ago · 1 file needs attention</div>
|
||||
</div>
|
||||
</sc-if>
|
||||
|
||||
<sc-if value="{{ s.shares }}">
|
||||
<div style="flex:none;margin:0 12px 16px;display:flex;padding:3px;border-radius:999px;background:var(--sf);gap:2px">
|
||||
<div style="flex:1;height:34px;border-radius:999px;background:var(--acs);color:var(--act);display:flex;align-items:center;justify-content:center;font:600 14px/1 var(--ft)">With you</div>
|
||||
<div style="flex:1;height:34px;border-radius:999px;color:var(--fg2);display:flex;align-items:center;justify-content:center;font:500 14px/1 var(--ft)">By you</div>
|
||||
<div style="flex:1;height:34px;border-radius:999px;color:var(--fg2);display:flex;align-items:center;justify-content:center;font:500 14px/1 var(--ft)">Links</div>
|
||||
</div>
|
||||
</sc-if>
|
||||
|
||||
<sc-if value="{{ showList }}">
|
||||
<div style="display:flex;flex-direction:column;gap:18px;padding:0 12px 16px">
|
||||
<sc-for list="{{ groups }}" as="g" hint-placeholder-count="1">
|
||||
<div style="display:flex;flex-direction:column;gap:8px">
|
||||
<sc-if value="{{ g.hasLabel }}"><div style="padding:0 8px;font:600 13px/1 var(--ft);color:var(--fg2)">{{ g.label }}</div></sc-if>
|
||||
<div style="display:flex;flex-direction:column;gap:1px;background:var(--ln);border-radius:20px;overflow:hidden">
|
||||
<sc-for list="{{ g.rows }}" as="f" hint-placeholder-count="6">
|
||||
<div style="position:relative;background:var(--dgf)">
|
||||
<sc-if value="{{ f.swiped }}"><div style="position:absolute;right:0;top:0;bottom:0;width:96px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:5px;color:#FFFFFF;font:600 12px/1 var(--ft)"><span style="{{ i20.trash }}"></span>Delete</div></sc-if>
|
||||
<div style="{{ f.rs }}">
|
||||
<div style="{{ f.tile }}"><span style="{{ f.ico }}"></span></div>
|
||||
<div style="flex:1;min-width:0;display:flex;flex-direction:column;gap:4px">
|
||||
<div style="font:500 16px/1.2 var(--ft);color:var(--fg1);white-space:nowrap;overflow:hidden;text-overflow:ellipsis">{{ f.name }}</div>
|
||||
<div style="display:flex;align-items:center;gap:5px;font:400 13px/1.2 var(--ft);color:var(--fg3);white-space:nowrap;overflow:hidden">
|
||||
<sc-if value="{{ f.hasBadge }}"><span style="{{ f.badge }}"></span></sc-if>
|
||||
<sc-if value="{{ f.shared }}"><span style="{{ i14.users }}"></span></sc-if>
|
||||
<span style="flex:0 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis">{{ f.meta }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<sc-if value="{{ f.fav }}"><span style="{{ starSm }}"></span></sc-if>
|
||||
<div style="width:32px;height:40px;display:flex;align-items:center;justify-content:center"><span style="{{ trail }}"></span></div>
|
||||
</div>
|
||||
</div>
|
||||
</sc-for>
|
||||
</div>
|
||||
</div>
|
||||
</sc-for>
|
||||
</div>
|
||||
</sc-if>
|
||||
|
||||
<sc-if value="{{ showGrid }}">
|
||||
<div style="display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:10px;padding:0 12px 16px">
|
||||
<sc-for list="{{ gridRows }}" as="f" hint-placeholder-count="6">
|
||||
<div style="background:var(--sf);border-radius:18px;overflow:hidden;display:flex;flex-direction:column">
|
||||
<div style="{{ f.thumb }}"><span style="{{ f.icoL }}"></span></div>
|
||||
<div style="padding:10px 8px 12px 12px;display:flex;flex-direction:column;gap:5px">
|
||||
<div style="display:flex;align-items:center;gap:4px"><div style="flex:1;min-width:0;font:500 14px/1.2 var(--ft);white-space:nowrap;overflow:hidden;text-overflow:ellipsis">{{ f.name }}</div><span style="{{ moreSm }}"></span></div>
|
||||
<div style="display:flex;align-items:center;gap:4px;font:400 12px/1.2 var(--ft);color:var(--fg3);white-space:nowrap"><sc-if value="{{ f.hasBadge }}"><span style="{{ f.badge }}"></span></sc-if><sc-if value="{{ f.fav }}"><span style="{{ starXs }}"></span></sc-if>{{ f.size }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</sc-for>
|
||||
</div>
|
||||
</sc-if>
|
||||
|
||||
<sc-if value="{{ s.photos }}">
|
||||
<div style="flex:none;display:flex;gap:8px;padding:4px 12px 4px">
|
||||
<div style="height:34px;padding:0 14px;border-radius:999px;background:var(--acs);color:var(--act);display:flex;align-items:center;font:600 14px/1 var(--ft);white-space:nowrap">All</div>
|
||||
<div style="height:34px;padding:0 14px;border-radius:999px;background:var(--sf);display:flex;align-items:center;font:500 14px/1 var(--ft);white-space:nowrap">Photos</div>
|
||||
<div style="height:34px;padding:0 14px;border-radius:999px;background:var(--sf);display:flex;align-items:center;font:500 14px/1 var(--ft);white-space:nowrap">Videos</div>
|
||||
<div style="height:34px;padding:0 14px;border-radius:999px;background:var(--sf);display:flex;align-items:center;gap:6px;font:500 14px/1 var(--ft);white-space:nowrap"><span style="{{ i16.camera }}"></span>Camera</div>
|
||||
</div>
|
||||
<sc-for list="{{ photoGroups }}" as="g" hint-placeholder-count="2">
|
||||
<div style="display:flex;justify-content:space-between;align-items:baseline;padding:16px 16px 10px"><div style="font:500 18px/1 var(--fd);letter-spacing:-0.02em">{{ g.label }}</div><div style="font:400 13px/1 var(--ft);color:var(--fg3)">{{ g.count }}</div></div>
|
||||
<div style="display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:2px">
|
||||
<sc-for list="{{ g.tiles }}" as="t" hint-placeholder-count="9">
|
||||
<div style="{{ t.s }}"><sc-if value="{{ t.vid }}"><div style="position:absolute;right:6px;bottom:6px;height:20px;padding:0 7px 0 5px;border-radius:999px;background:rgba(14,13,11,0.7);color:#FFFFFF;display:flex;align-items:center;gap:3px;font:600 11px/1 var(--ft)"><span style="{{ i14.play }}"></span>{{ t.dur }}</div></sc-if></div>
|
||||
</sc-for>
|
||||
</div>
|
||||
</sc-for>
|
||||
</sc-if>
|
||||
|
||||
<sc-if value="{{ s.activity }}">
|
||||
<div style="display:flex;flex-direction:column;gap:18px;padding:0 12px 16px">
|
||||
<sc-for list="{{ act }}" as="g" hint-placeholder-count="2">
|
||||
<div style="display:flex;flex-direction:column;gap:8px">
|
||||
<div style="padding:0 8px;font:600 13px/1 var(--ft);color:var(--fg2)">{{ g.label }}</div>
|
||||
<div style="display:flex;flex-direction:column;gap:1px;background:var(--ln);border-radius:20px;overflow:hidden">
|
||||
<sc-for list="{{ g.items }}" as="a" hint-placeholder-count="3">
|
||||
<div style="display:flex;gap:12px;padding:14px;background:var(--sf);align-items:flex-start">
|
||||
<div style="{{ a.av }}">{{ a.who }}</div>
|
||||
<div style="flex:1;min-width:0;display:flex;flex-direction:column;gap:5px">
|
||||
<div style="font:400 15px/1.3 var(--ft);color:var(--fg1);text-wrap:pretty"><span style="font-weight:600">{{ a.name }}</span> {{ a.verb }} <span style="font-weight:600">{{ a.obj }}</span> {{ a.tail }}</div>
|
||||
<div style="font:400 13px/1 var(--ft);color:var(--fg3)">{{ a.time }}</div>
|
||||
</div>
|
||||
<div style="{{ a.tile }}"><span style="{{ a.ico }}"></span></div>
|
||||
</div>
|
||||
</sc-for>
|
||||
</div>
|
||||
</div>
|
||||
</sc-for>
|
||||
</div>
|
||||
</sc-if>
|
||||
|
||||
<sc-if value="{{ s.settings }}">
|
||||
<div style="display:flex;flex-direction:column;gap:20px;padding:0 12px 16px">
|
||||
<div style="padding:18px;border-radius:20px;background:var(--sf);display:flex;flex-direction:column;gap:16px">
|
||||
<div style="display:flex;gap:14px;align-items:center">
|
||||
<div style="width:56px;height:56px;border-radius:999px;background:var(--acs);color:var(--act);display:flex;align-items:center;justify-content:center;font:600 20px/1 var(--ft);flex:none">MR</div>
|
||||
<div style="display:flex;flex-direction:column;gap:5px;flex:1;min-width:0"><div style="font:500 20px/1 var(--fd);letter-spacing:-0.02em">Marina Rocha</div><div style="font:400 14px/1 var(--ft);color:var(--fg2)">marina@rocha.family</div></div>
|
||||
</div>
|
||||
<div style="display:flex;gap:12px;align-items:center;padding:12px 14px;border-radius:14px;background:var(--sf2)">
|
||||
<span style="{{ i18.server }}"></span>
|
||||
<div style="flex:1;min-width:0;display:flex;flex-direction:column;gap:4px"><div style="font:500 15px/1.1 var(--ft)">cloud.rocha.family</div><div style="font:400 13px/1 var(--ft);color:var(--fg3)">Nextcloud 30.0.2</div></div>
|
||||
<div style="height:24px;padding:0 10px;border-radius:999px;background:var(--oks);color:var(--ok);display:flex;align-items:center;font:600 12px/1 var(--ft);white-space:nowrap">Connected</div>
|
||||
</div>
|
||||
<div style="display:flex;flex-direction:column;gap:8px">
|
||||
<div style="display:flex;justify-content:space-between;font:400 14px/1 var(--ft)"><span style="font-weight:500">Storage</span><span style="color:var(--fg2)">38.2 of 100 GB</span></div>
|
||||
<div style="height:6px;border-radius:999px;background:var(--sf3);overflow:hidden"><div style="width:38%;height:100%;background:var(--ac)"></div></div>
|
||||
</div>
|
||||
<div style="display:flex;gap:8px">
|
||||
<div style="flex:1;height:44px;border-radius:999px;background:var(--sf2);display:flex;align-items:center;justify-content:center;gap:8px;font:600 15px/1 var(--ft)"><span style="{{ i16.external }}"></span>Manage on web</div>
|
||||
<div style="flex:1;height:44px;border-radius:999px;background:var(--dgs);color:var(--dg);display:flex;align-items:center;justify-content:center;gap:8px;font:600 15px/1 var(--ft)"><span style="{{ i16.logout }}"></span>Log out</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display:flex;flex-direction:column;gap:8px">
|
||||
<div style="padding:0 8px;font:600 13px/1 var(--ft);color:var(--fg2)">Accounts</div>
|
||||
<div style="display:flex;flex-direction:column;gap:1px;background:var(--ln);border-radius:20px;overflow:hidden">
|
||||
<div style="display:flex;align-items:center;gap:14px;padding:0 16px;height:60px;background:var(--sf)"><div style="width:36px;height:36px;border-radius:999px;background:var(--acs);color:var(--act);display:flex;align-items:center;justify-content:center;font:600 13px/1 var(--ft)">MR</div><div style="flex:1;display:flex;flex-direction:column;gap:4px"><div style="font:500 16px/1 var(--ft)">Marina Rocha</div><div style="font:400 13px/1 var(--ft);color:var(--fg3)">cloud.rocha.family</div></div><span style="{{ checkA }}"></span></div>
|
||||
<div style="display:flex;align-items:center;gap:14px;padding:0 16px;height:60px;background:var(--sf)"><div style="width:36px;height:36px;border-radius:999px;background:#85D1BD;color:#0E0D0B;display:flex;align-items:center;justify-content:center;font:600 13px/1 var(--ft)">MR</div><div style="flex:1;display:flex;flex-direction:column;gap:4px"><div style="font:500 16px/1 var(--ft)">Marina · Work</div><div style="font:400 13px/1 var(--ft);color:var(--fg3)">files.acme-studio.com</div></div></div>
|
||||
<div style="display:flex;align-items:center;gap:14px;padding:0 16px;height:52px;background:var(--sf);color:var(--act);font:600 15px/1 var(--ft)"><div style="width:36px;display:flex;justify-content:center"><span style="{{ i20.plus }}"></span></div>Add account</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display:flex;flex-direction:column;gap:8px">
|
||||
<div style="padding:0 8px;font:600 13px/1 var(--ft);color:var(--fg2)">Security</div>
|
||||
<div style="display:flex;flex-direction:column;gap:1px;background:var(--ln);border-radius:20px;overflow:hidden">
|
||||
<div style="display:flex;align-items:center;gap:14px;padding:12px 16px;min-height:60px;box-sizing:border-box;background:var(--sf)"><span style="{{ bioIco }}"></span><div style="flex:1;display:flex;flex-direction:column;gap:4px"><div style="font:400 16px/1.1 var(--ft)">{{ bioLabel }}</div><div style="font:400 13px/1.2 var(--ft);color:var(--fg3)">Needed every time you open the app</div></div><div style="width:48px;height:28px;border-radius:999px;background:var(--ac);padding:3px;box-sizing:border-box;display:flex;justify-content:flex-end;flex:none"><div style="width:22px;height:22px;border-radius:999px;background:#FFFFFF"></div></div></div>
|
||||
<div style="display:flex;align-items:center;gap:14px;padding:0 16px;height:52px;background:var(--sf)"><span style="{{ i20.timer }}"></span><div style="flex:1;font:400 16px/1 var(--ft)">Lock after</div><div style="display:flex;align-items:center;gap:4px;font:400 15px/1 var(--ft);color:var(--fg3)">1 minute<span style="{{ i18.chevR }}"></span></div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</sc-if>
|
||||
|
||||
<sc-if value="{{ s.settings2 }}">
|
||||
<div style="display:flex;flex-direction:column;gap:20px;padding:0 12px 16px">
|
||||
<div style="display:flex;flex-direction:column;gap:8px">
|
||||
<div style="padding:0 8px;font:600 13px/1 var(--ft);color:var(--fg2)">File sync</div>
|
||||
<div style="display:flex;flex-direction:column;gap:1px;background:var(--ln);border-radius:20px;overflow:hidden">
|
||||
<div style="display:flex;align-items:center;gap:14px;padding:12px 16px;min-height:60px;box-sizing:border-box;background:var(--sf)"><span style="{{ i20.camera }}"></span><div style="flex:1;display:flex;flex-direction:column;gap:4px"><div style="font:400 16px/1.1 var(--ft)">Auto-upload photos</div><div style="font:400 13px/1.2 var(--ft);color:var(--fg3)">To /Photos/Camera</div></div><div style="width:48px;height:28px;border-radius:999px;background:var(--ac);padding:3px;box-sizing:border-box;display:flex;justify-content:flex-end;flex:none"><div style="width:22px;height:22px;border-radius:999px;background:#FFFFFF"></div></div></div>
|
||||
<div style="display:flex;align-items:center;gap:14px;padding:0 16px;height:52px;background:var(--sf)"><span style="{{ i20.wifi }}"></span><div style="flex:1;font:400 16px/1 var(--ft)">Wi-Fi only</div><div style="width:48px;height:28px;border-radius:999px;background:var(--ac);padding:3px;box-sizing:border-box;display:flex;justify-content:flex-end;flex:none"><div style="width:22px;height:22px;border-radius:999px;background:#FFFFFF"></div></div></div>
|
||||
<div style="display:flex;align-items:center;gap:14px;padding:0 16px;height:52px;background:var(--sf)"><span style="{{ i20.charging }}"></span><div style="flex:1;font:400 16px/1 var(--ft)">Only while charging</div><div style="width:48px;height:28px;border-radius:999px;background:var(--sf3);padding:3px;box-sizing:border-box;display:flex;justify-content:flex-start;flex:none"><div style="width:22px;height:22px;border-radius:999px;background:#FFFFFF"></div></div></div>
|
||||
<div style="display:flex;align-items:center;gap:14px;padding:0 16px;height:52px;background:var(--sf)"><span style="{{ i20.sync }}"></span><div style="flex:1;font:400 16px/1 var(--ft)">Refresh offline files</div><div style="display:flex;align-items:center;gap:4px;font:400 15px/1 var(--ft);color:var(--fg3)">Every 15 min<span style="{{ i18.chevR }}"></span></div></div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display:flex;flex-direction:column;gap:8px">
|
||||
<div style="padding:0 8px;font:600 13px/1 var(--ft);color:var(--fg2)">Files cache</div>
|
||||
<div style="display:flex;flex-direction:column;gap:1px;background:var(--ln);border-radius:20px;overflow:hidden">
|
||||
<div style="display:flex;flex-direction:column;gap:10px;padding:14px 16px;background:var(--sf)"><div style="display:flex;justify-content:space-between;font:400 16px/1 var(--ft)"><span>Cache in use</span><span style="color:var(--fg3);font-size:15px">1.2 of 2 GB</span></div><div style="height:6px;border-radius:999px;background:var(--sf3);overflow:hidden"><div style="width:60%;height:100%;background:var(--ac)"></div></div></div>
|
||||
<div style="display:flex;align-items:center;gap:14px;padding:0 16px;height:52px;background:var(--sf)"><span style="{{ i20.database }}"></span><div style="flex:1;font:400 16px/1 var(--ft)">Cache limit</div><div style="display:flex;align-items:center;gap:4px;font:400 15px/1 var(--ft);color:var(--fg3)">2 GB<span style="{{ i18.chevR }}"></span></div></div>
|
||||
<div style="display:flex;align-items:center;gap:14px;padding:0 16px;height:52px;background:var(--sf);color:var(--dg)"><span style="{{ i20.trash }}"></span><div style="flex:1;font:500 16px/1 var(--ft)">Clear cache</div></div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display:flex;flex-direction:column;gap:8px">
|
||||
<div style="padding:0 8px;font:600 13px/1 var(--ft);color:var(--fg2)">Appearance</div>
|
||||
<div style="display:flex;flex-direction:column;gap:1px;background:var(--ln);border-radius:20px;overflow:hidden">
|
||||
<div style="display:flex;align-items:center;gap:12px;padding:0 12px 0 16px;height:56px;background:var(--sf)"><div style="flex:1;font:400 16px/1 var(--ft)">Theme</div><div style="display:flex;padding:3px;border-radius:999px;background:var(--sf2);gap:2px"><div style="height:30px;padding:0 12px;border-radius:999px;background:var(--acs);color:var(--act);display:flex;align-items:center;font:600 13px/1 var(--ft);white-space:nowrap">System</div><div style="height:30px;padding:0 12px;display:flex;align-items:center;font:500 13px/1 var(--ft);color:var(--fg2)">Light</div><div style="height:30px;padding:0 12px;display:flex;align-items:center;font:500 13px/1 var(--ft);color:var(--fg2)">Dark</div></div></div>
|
||||
<div style="display:flex;align-items:center;gap:12px;padding:0 12px 0 16px;height:56px;background:var(--sf)"><div style="flex:1;font:400 16px/1 var(--ft)">Default view</div><div style="display:flex;padding:3px;border-radius:999px;background:var(--sf2);gap:2px"><div style="height:30px;padding:0 12px;border-radius:999px;background:var(--acs);color:var(--act);display:flex;align-items:center;gap:6px;font:600 13px/1 var(--ft);white-space:nowrap"><span style="{{ i14.list }}"></span>List</div><div style="height:30px;padding:0 12px;display:flex;align-items:center;gap:6px;font:500 13px/1 var(--ft);color:var(--fg2)"><span style="{{ i14.grid }}"></span>Grid</div></div></div>
|
||||
<div style="display:flex;align-items:center;gap:14px;padding:0 16px;height:52px;background:var(--sf)"><div style="flex:1;font:400 16px/1 var(--ft)">Show hidden files</div><div style="width:48px;height:28px;border-radius:999px;background:var(--sf3);padding:3px;box-sizing:border-box;display:flex;justify-content:flex-start;flex:none"><div style="width:22px;height:22px;border-radius:999px;background:#FFFFFF"></div></div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</sc-if>
|
||||
|
||||
<sc-if value="{{ s.settings3 }}">
|
||||
<div style="display:flex;flex-direction:column;gap:20px;padding:0 12px 16px">
|
||||
<div style="display:flex;flex-direction:column;gap:8px">
|
||||
<div style="padding:0 8px;display:flex;justify-content:space-between;font:600 13px/1 var(--ft);color:var(--fg2)"><span>Tabs</span><span style="font-weight:500;color:var(--fg3)">5 of 5 pinned</span></div>
|
||||
<div style="display:flex;flex-direction:column;gap:1px;background:var(--ln);border-radius:20px;overflow:hidden">
|
||||
<sc-for list="{{ tabRows }}" as="t" hint-placeholder-count="8">
|
||||
<div style="display:flex;align-items:center;gap:12px;padding:0 10px 0 10px;height:52px;background:var(--sf)">
|
||||
<span style="{{ gripS }}"></span>
|
||||
<span style="{{ t.ico }}"></span>
|
||||
<div style="flex:1;font:400 16px/1 var(--ft)">{{ t.label }}</div>
|
||||
<div style="{{ t.pinS }}"><span style="{{ t.pinI }}"></span></div>
|
||||
</div>
|
||||
</sc-for>
|
||||
</div>
|
||||
<div style="padding:0 8px;font:400 13px/1.3 var(--ft);color:var(--fg3);text-wrap:pretty">Pinned tabs sit in the bottom bar. The rest live in the menu. Drag to reorder.</div>
|
||||
</div>
|
||||
<div style="display:flex;flex-direction:column;gap:8px">
|
||||
<div style="padding:0 8px;font:600 13px/1 var(--ft);color:var(--fg2)">Swipe on a file</div>
|
||||
<div style="display:flex;flex-direction:column;gap:1px;background:var(--ln);border-radius:20px;overflow:hidden">
|
||||
<div style="display:flex;align-items:center;gap:14px;padding:0 16px;height:52px;background:var(--sf)"><span style="{{ i20.swipe }}"></span><div style="flex:1;font:400 16px/1 var(--ft)">Swipe left</div><div style="height:28px;padding:0 10px;border-radius:999px;background:var(--dgs);color:var(--dg);display:flex;align-items:center;gap:5px;font:600 13px/1 var(--ft);white-space:nowrap"><span style="{{ i14.trash }}"></span>Delete</div><span style="{{ chevG }}"></span></div>
|
||||
<div style="display:flex;align-items:center;gap:14px;padding:0 16px;height:52px;background:var(--sf)"><span style="{{ i20.swipe }}"></span><div style="flex:1;font:400 16px/1 var(--ft)">Swipe right</div><div style="height:28px;padding:0 10px;border-radius:999px;background:var(--acs);color:var(--act);display:flex;align-items:center;gap:5px;font:600 13px/1 var(--ft);white-space:nowrap"><span style="{{ i14.star }}"></span>Favorite</div><span style="{{ chevG }}"></span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</sc-if>
|
||||
|
||||
<sc-if value="{{ fab }}">
|
||||
<div style="position:absolute;right:16px;bottom:16px;height:56px;padding:0 20px 0 16px;border-radius:999px;background:var(--ac);color:#FFFFFF;display:flex;align-items:center;gap:10px;font:600 16px/1 var(--ft)"><span style="{{ i24.plus }}"></span>Upload</div>
|
||||
</sc-if>
|
||||
</div>
|
||||
|
||||
<sc-if value="{{ aNav }}">
|
||||
<div style="flex:none;background:var(--sf);display:flex;flex-direction:column">
|
||||
<div style="display:flex;height:80px;align-items:center">
|
||||
<sc-for list="{{ nav }}" as="n" hint-placeholder-count="5">
|
||||
<div style="flex:1;display:flex;flex-direction:column;align-items:center;gap:4px">
|
||||
<sc-if value="{{ n.on }}"><div style="width:56px;height:32px;border-radius:999px;background:var(--acs);color:var(--act);display:flex;align-items:center;justify-content:center"><span style="{{ n.ico }}"></span></div><div style="font:600 12px/1 var(--ft);color:var(--fg1)">{{ n.label }}</div></sc-if>
|
||||
<sc-if value="{{ n.off }}"><div style="width:56px;height:32px;color:var(--fg2);display:flex;align-items:center;justify-content:center"><span style="{{ n.ico }}"></span></div><div style="font:500 12px/1 var(--ft);color:var(--fg2)">{{ n.label }}</div></sc-if>
|
||||
</div>
|
||||
</sc-for>
|
||||
</div>
|
||||
<div style="height:20px;display:flex;align-items:center;justify-content:center"><div style="width:108px;height:4px;border-radius:999px;background:var(--fg3)"></div></div>
|
||||
</div>
|
||||
</sc-if>
|
||||
<sc-if value="{{ iNav }}">
|
||||
<div style="flex:none;background:var(--sf);border-top:1px solid var(--ln);display:flex;flex-direction:column">
|
||||
<div style="display:flex;padding-top:8px;height:50px;box-sizing:border-box">
|
||||
<sc-for list="{{ nav }}" as="n" hint-placeholder-count="5">
|
||||
<sc-if value="{{ n.on }}"><div style="flex:1;display:flex;flex-direction:column;align-items:center;gap:4px;color:var(--act);font:600 10px/1 var(--ft)"><span style="{{ n.ico }}"></span>{{ n.label }}</div></sc-if>
|
||||
<sc-if value="{{ n.off }}"><div style="flex:1;display:flex;flex-direction:column;align-items:center;gap:4px;color:var(--fg3);font:500 10px/1 var(--ft)"><span style="{{ n.ico }}"></span>{{ n.label }}</div></sc-if>
|
||||
</sc-for>
|
||||
</div>
|
||||
<div style="height:34px;display:flex;align-items:flex-end;justify-content:center;padding-bottom:8px;box-sizing:border-box"><div style="width:134px;height:5px;border-radius:999px;background:var(--fg1)"></div></div>
|
||||
</div>
|
||||
</sc-if>
|
||||
<sc-if value="{{ aGesture }}"><div style="height:24px;flex:none;display:flex;align-items:center;justify-content:center"><div style="width:108px;height:4px;border-radius:999px;background:var(--fg3)"></div></div></sc-if>
|
||||
<sc-if value="{{ iGesture }}"><div style="height:34px;flex:none;display:flex;align-items:flex-end;justify-content:center;padding-bottom:8px;box-sizing:border-box"><div style="width:134px;height:5px;border-radius:999px;background:var(--fg1)"></div></div></sc-if>
|
||||
|
||||
<sc-if value="{{ drawer }}">
|
||||
<div style="position:absolute;inset:0;background:var(--scrim)"></div>
|
||||
<div style="position:absolute;left:0;top:0;bottom:0;width:316px;background:var(--sf);border-radius:0 28px 28px 0;display:flex;flex-direction:column;padding:64px 12px 28px;box-sizing:border-box;gap:4px">
|
||||
<div style="display:flex;gap:12px;align-items:center;padding:0 12px 14px">
|
||||
<div style="width:48px;height:48px;border-radius:999px;background:var(--acs);color:var(--act);display:flex;align-items:center;justify-content:center;font:600 17px/1 var(--ft);flex:none">MR</div>
|
||||
<div style="flex:1;min-width:0;display:flex;flex-direction:column;gap:5px"><div style="font:500 18px/1 var(--fd);letter-spacing:-0.02em">Marina Rocha</div><div style="font:400 13px/1 var(--ft);color:var(--fg3)">cloud.rocha.family</div></div>
|
||||
<div style="width:36px;height:36px;border-radius:999px;background:var(--sf2);display:flex;align-items:center;justify-content:center"><span style="{{ i18.chevD }}"></span></div>
|
||||
</div>
|
||||
<div style="display:flex;flex-direction:column;gap:8px;padding:0 12px 16px">
|
||||
<div style="height:6px;border-radius:999px;background:var(--sf3);overflow:hidden"><div style="width:38%;height:100%;background:var(--ac)"></div></div>
|
||||
<div style="font:400 13px/1 var(--ft);color:var(--fg3)">38.2 GB of 100 GB used</div>
|
||||
</div>
|
||||
<div style="height:1px;background:var(--ln);margin:0 12px 8px"></div>
|
||||
<div style="padding:8px 16px;font:600 13px/1 var(--ft);color:var(--fg2)">More</div>
|
||||
<sc-for list="{{ menuRows }}" as="m" hint-placeholder-count="3">
|
||||
<div style="height:52px;border-radius:999px;padding:0 16px;display:flex;align-items:center;gap:14px;font:500 16px/1 var(--ft)"><span style="{{ m.ico }}"></span><div style="flex:1">{{ m.label }}</div><div style="font:500 14px/1 var(--ft);color:var(--fg3)">{{ m.count }}</div></div>
|
||||
</sc-for>
|
||||
<div style="height:1px;background:var(--ln);margin:8px 12px"></div>
|
||||
<div style="height:52px;border-radius:999px;padding:0 16px;display:flex;align-items:center;gap:14px;font:500 16px/1 var(--ft)"><span style="{{ i24.settings }}"></span>Settings</div>
|
||||
<div style="flex:1"></div>
|
||||
<div style="padding:0 16px;display:flex;align-items:center;gap:8px;font:600 14px/1 var(--ft);color:var(--act)"><span style="{{ i16.pencil }}"></span>Edit tabs</div>
|
||||
</div>
|
||||
</sc-if>
|
||||
|
||||
<sc-if value="{{ share }}">
|
||||
<div style="position:absolute;inset:0;background:var(--scrim)"></div>
|
||||
<div style="position:absolute;left:0;right:0;bottom:0;background:var(--sf);border-radius:28px 28px 0 0;padding:10px 20px 40px;display:flex;flex-direction:column;gap:22px">
|
||||
<div style="align-self:center;width:36px;height:5px;border-radius:999px;background:var(--sf3)"></div>
|
||||
<div style="display:flex;gap:12px;align-items:center">
|
||||
<div style="{{ shareTile }}"><span style="{{ i24.doc }}"></span></div>
|
||||
<div style="flex:1;min-width:0;display:flex;flex-direction:column;gap:5px"><div style="font:500 19px/1 var(--fd);letter-spacing:-0.02em">Q3 Planning.pdf</div><div style="font:400 13px/1 var(--ft);color:var(--fg3)">2.4 MB · Documents</div></div>
|
||||
<div style="width:36px;height:36px;border-radius:999px;background:var(--sf2);display:flex;align-items:center;justify-content:center"><span style="{{ i18.x }}"></span></div>
|
||||
</div>
|
||||
<div style="display:flex;flex-direction:column;gap:12px">
|
||||
<div style="font:500 17px/1 var(--fd);letter-spacing:-0.02em">Share with people</div>
|
||||
<div style="height:48px;border-radius:14px;background:var(--sf2);display:flex;align-items:center;gap:10px;padding:0 14px;color:var(--fg3);font:400 15px/1 var(--ft)"><span style="{{ i20.userPlus }}"></span>Name, email or group</div>
|
||||
<div style="display:flex;flex-direction:column;gap:14px;padding-top:4px">
|
||||
<div style="display:flex;align-items:center;gap:12px"><div style="{{ avYou }}">MR</div><div style="flex:1;display:flex;flex-direction:column;gap:4px"><div style="font:500 15px/1 var(--ft)">You</div><div style="font:400 13px/1 var(--ft);color:var(--fg3)">marina@rocha.family</div></div><div style="font:500 13px/1 var(--ft);color:var(--fg3);padding-right:4px">Owner</div></div>
|
||||
<div style="display:flex;align-items:center;gap:12px"><div style="{{ avAna }}">AS</div><div style="flex:1;display:flex;flex-direction:column;gap:4px"><div style="font:500 15px/1 var(--ft)">Ana Souza</div><div style="font:400 13px/1 var(--ft);color:var(--fg3)">ana@rocha.family</div></div><div style="height:30px;padding:0 8px 0 12px;border-radius:999px;border:1px solid var(--ln);display:flex;align-items:center;gap:4px;font:500 13px/1 var(--ft);white-space:nowrap">Can edit<span style="{{ i14.chevD }}"></span></div></div>
|
||||
<div style="display:flex;align-items:center;gap:12px"><div style="width:36px;height:36px;border-radius:999px;background:var(--sf2);color:var(--fg2);display:flex;align-items:center;justify-content:center;flex:none"><span style="{{ i18.users }}"></span></div><div style="flex:1;display:flex;flex-direction:column;gap:4px"><div style="font:500 15px/1 var(--ft)">Design team</div><div style="font:400 13px/1 var(--ft);color:var(--fg3)">Group · 6 people</div></div><div style="height:30px;padding:0 8px 0 12px;border-radius:999px;border:1px solid var(--ln);display:flex;align-items:center;gap:4px;font:500 13px/1 var(--ft);white-space:nowrap">Can view<span style="{{ i14.chevD }}"></span></div></div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="height:1px;background:var(--ln)"></div>
|
||||
<div style="display:flex;flex-direction:column;gap:12px">
|
||||
<div style="display:flex;justify-content:space-between;align-items:center"><div style="display:flex;flex-direction:column;gap:5px"><div style="font:500 17px/1 var(--fd);letter-spacing:-0.02em">Share link</div><div style="font:400 13px/1 var(--ft);color:var(--fg3)">Anyone with the link can view</div></div><div style="width:48px;height:28px;border-radius:999px;background:var(--ac);padding:3px;box-sizing:border-box;display:flex;justify-content:flex-end;flex:none"><div style="width:22px;height:22px;border-radius:999px;background:#FFFFFF"></div></div></div>
|
||||
<div style="border-radius:16px;background:var(--sf2);padding:6px 6px 6px 14px;display:flex;gap:10px;align-items:center;color:var(--fg2)"><span style="{{ i18.link }}"></span><div style="flex:1;min-width:0;font:400 14px/1 ui-monospace,Menlo,monospace;color:var(--fg1);white-space:nowrap;overflow:hidden;text-overflow:ellipsis">cloud.rocha.family/s/k7Pq2xW</div><div style="height:40px;padding:0 16px;border-radius:999px;background:var(--ac);color:#FFFFFF;display:flex;align-items:center;gap:6px;font:600 14px/1 var(--ft);white-space:nowrap"><span style="{{ i16.copy }}"></span>Copy link</div></div>
|
||||
<div style="display:flex;gap:8px;flex-wrap:wrap">
|
||||
<div style="height:32px;padding:0 12px;border-radius:999px;border:1px solid var(--ln);display:flex;align-items:center;gap:6px;font:500 13px/1 var(--ft);white-space:nowrap"><span style="{{ i14.eye }}"></span>Can view<span style="{{ i14.chevD }}"></span></div>
|
||||
<div style="height:32px;padding:0 12px;border-radius:999px;background:var(--acs);color:var(--act);display:flex;align-items:center;gap:6px;font:600 13px/1 var(--ft);white-space:nowrap"><span style="{{ i14.calendar }}"></span>Expires Oct 24</div>
|
||||
<div style="height:32px;padding:0 12px;border-radius:999px;border:1px solid var(--ln);display:flex;align-items:center;gap:6px;font:500 13px/1 var(--ft);white-space:nowrap"><span style="{{ i14.lock }}"></span>Add password</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display:flex;flex-direction:column;gap:10px">
|
||||
<div style="height:52px;border-radius:999px;border:1.5px solid var(--sf3);display:flex;align-items:center;justify-content:center;gap:10px;font:600 16px/1 var(--ft)"><span style="{{ i20.send }}"></span>Send file directly</div>
|
||||
<div style="font:400 13px/1.3 var(--ft);color:var(--fg3);text-align:center">Sends a copy through another app. Link settings don’t apply.</div>
|
||||
</div>
|
||||
</div>
|
||||
</sc-if>
|
||||
|
||||
</div>
|
||||
</sc-if>
|
||||
</x-dc>
|
||||
<script type="text/x-dc" data-dc-script data-props="{"$preview":{"width":390,"height":844},"platform":{"editor":"enum","options":["ios","android"],"default":"ios","tsType":"'ios'|'android'"},"screen":{"editor":"enum","options":["files","filesGrid","photos","favorites","offline","shares","recent","activity","trash","drawer","share","settings","settings2","settings3"],"default":"files","tsType":"string"},"theme":{"editor":"enum","options":["light","dark"],"default":"light","tsType":"'light'|'dark'"}}">
|
||||
class Component extends DCLogic {
|
||||
componentDidMount() {
|
||||
if (!window.NK) this._t = setInterval(() => { if (window.NK) { clearInterval(this._t); this.forceUpdate(); } }, 40);
|
||||
}
|
||||
componentWillUnmount() { clearInterval(this._t); }
|
||||
renderVals() {
|
||||
const K = window.NK;
|
||||
if (!K) return { ready: false };
|
||||
const { I, ic, D, row, TH, tile, tiles, avatar } = K;
|
||||
const ios = this.props.platform !== 'android', android = !ios;
|
||||
const sc = this.props.screen || 'files';
|
||||
const theme = this.props.theme === 'dark' ? 'dark' : 'light';
|
||||
const drawer = sc === 'drawer', share = sc === 'share';
|
||||
const grid = sc === 'filesGrid';
|
||||
const base = (drawer || share || grid) ? 'files' : sc;
|
||||
const settings = base.startsWith('settings');
|
||||
const s = {}; ['files','photos','activity','trash','favorites','offline','shares','recent','settings','settings2','settings3'].forEach(k => s[k] = base === k);
|
||||
const ROW = { display: 'flex', alignItems: 'center', gap: 14, padding: '0 6px 0 14px', height: 64, background: 'var(--sf)', position: 'relative' };
|
||||
const mk = (list, o = {}) => list.map(f => { const r = row(f, o); r.rs = { ...ROW, transform: r.swiped ? 'translateX(-96px)' : 'none' }; return r; });
|
||||
const noSwipe = drawer || share;
|
||||
let groups = [], trail = ic(ios ? 'moreH' : 'moreV', 20, 'var(--fg3)');
|
||||
if (base === 'files') groups = [{ rows: mk(D.files, { noSwipe }) }];
|
||||
if (base === 'favorites') { groups = [{ rows: mk(D.favorites, { noFav: 1 }) }]; trail = ic('star', 20, 'var(--act)'); }
|
||||
if (base === 'offline') groups = [{ rows: mk(D.offline) }];
|
||||
if (base === 'shares') groups = [{ rows: mk(D.shares) }];
|
||||
if (base === 'recent') groups = D.recent.map(g => ({ label: g.label, rows: mk(g.rows) }));
|
||||
if (base === 'trash') { groups = [{ rows: mk(D.trash) }]; trail = ic('restore', 20, 'var(--act)'); }
|
||||
groups = groups.map(g => ({ ...g, hasLabel: !!g.label }));
|
||||
const title = settings ? 'Settings' : D.titles[base];
|
||||
const seg = on => ({ width: 36, height: 28, borderRadius: 999, display: 'flex', alignItems: 'center', justifyContent: 'center', background: on ? 'var(--acs)' : 'transparent', color: on ? 'var(--act)' : 'var(--fg3)' });
|
||||
return {
|
||||
ready: true, ios, android, s, title, groups, trail, drawer, share,
|
||||
root: { ...TH[theme], width: 390, height: 844, borderRadius: ios ? 48 : 36, overflow: 'hidden', position: 'relative', display: 'flex', flexDirection: 'column', background: 'var(--bg)', color: 'var(--fg1)', fontFamily: 'var(--ft)' },
|
||||
i14: I[14], i16: I[16], i18: I[18], i20: I[20], i24: I[24],
|
||||
aBar: android && !settings, aSet: android && settings, iBar: ios && !settings, iSet: ios && settings,
|
||||
aNav: android && !settings, iNav: ios && !settings, aGesture: android && settings, iGesture: ios && settings,
|
||||
showList: groups.length > 0 && !grid, showGrid: grid,
|
||||
gridRows: D.files.slice(0, 8).map(f => row(f, { noSwipe: 1 })),
|
||||
segL: seg(!grid), segG: seg(grid),
|
||||
fab: android && (base === 'files' || base === 'photos'),
|
||||
starSm: ic('star', 16, 'var(--act)'), starXs: ic('star', 12, 'var(--act)'), moreSm: ic(ios ? 'moreH' : 'moreV', 16, 'var(--fg3)'),
|
||||
checkA: ic('check', 20, 'var(--act)'), chevG: ic('chevR', 18, 'var(--fg3)'), gripS: ic('grip', 18, 'var(--fg3)'),
|
||||
photoGroups: [{ label: 'September 2026', count: '38 items', tiles: tiles(18, 0, [2, 9, 13]) }, { label: 'August 2026', count: '112 items', tiles: tiles(9, 3, [4]) }],
|
||||
act: D.activity.map(g => ({ label: g.label, items: g.items.map(a => ({ ...a, av: avatar(a.col, 36), tile: tile(a.kind, 32, 10), ico: I[16][K.KIND[a.kind][2]] })) })),
|
||||
nav: D.pinned.map(([label, ico, key]) => ({ label, ico: I[24][ico], on: key === base, off: key !== base })),
|
||||
menuRows: D.menu.map(([label, ico, key, count]) => ({ label, ico: I[24][ico], count })),
|
||||
tabRows: [...D.pinned.map(([label, ico]) => ({ label, ico: I[20][ico], p: 1 })), ...D.menu.map(([label, ico]) => ({ label, ico: I[20][ico], p: 0 }))].map(t => ({ ...t,
|
||||
pinS: { width: 36, height: 36, borderRadius: 999, display: 'flex', alignItems: 'center', justifyContent: 'center', background: t.p ? 'var(--acs)' : 'var(--sf2)', color: t.p ? 'var(--act)' : 'var(--fg3)' },
|
||||
pinI: I[16][t.p ? 'pin' : 'pinOff'] })),
|
||||
bioLabel: ios ? 'Lock with Face ID' : 'Lock with fingerprint', bioIco: I[20][ios ? 'face' : 'fingerprint'],
|
||||
shareTile: tile('pdf', 44, 12), avYou: { ...avatar('#CBA5FD', 36) }, avAna: avatar('#DA9AC7', 36)
|
||||
};
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,202 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<script src="./support.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<x-dc>
|
||||
<helmet>
|
||||
<script src="noo-kit.js"></script>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Instrument+Sans:wght@400;500;600&family=Schibsted+Grotesk:wght@500;600&display=swap">
|
||||
<style>
|
||||
body{margin:0;background:#F3EFE6}
|
||||
a{color:#8D0DE3;text-decoration:none}
|
||||
a:hover{color:#6E08B3}
|
||||
</style>
|
||||
</helmet>
|
||||
<div style="max-width:1440px;margin:0 auto;padding:64px 40px 96px;display:flex;flex-direction:column;gap:48px;font-family:'Instrument Sans',system-ui,sans-serif;color:#0E0D0B">
|
||||
<div style="display:flex;flex-direction:column;gap:16px">
|
||||
<div style="font:600 64px/0.9 'Schibsted Grotesk',system-ui,sans-serif;letter-spacing:-0.03em">Noo design system</div>
|
||||
<div style="font:400 18px/1.35 'Instrument Sans',system-ui,sans-serif;color:#5A5852;max-width:760px;text-wrap:pretty">Every component is shown in light and dark. The full rules for code are in <a href="DESIGN_SYSTEM.md">DESIGN_SYSTEM.md</a>. You can see every screen in <a href="Noo Screens.dc.html">Noo Screens</a>.</div>
|
||||
</div>
|
||||
|
||||
<sc-if value="{{ ready }}" hint-placeholder-val="{{ false }}">
|
||||
<div style="display:flex;flex-direction:column;gap:14px">
|
||||
<div style="font:500 28px/1 'Schibsted Grotesk',system-ui,sans-serif;letter-spacing:-0.02em">Type</div>
|
||||
<div style="background:#FFFFFF;border-radius:20px;padding:8px 24px">
|
||||
<sc-for list="{{ type }}" as="t" hint-placeholder-count="9">
|
||||
<div style="display:grid;grid-template-columns:200px minmax(0,1fr);gap:24px;align-items:center;padding:16px 0;border-bottom:1px solid #EAE8E2">
|
||||
<div style="font:400 13px/1.3 ui-monospace,Menlo,monospace;color:#7C7A72">{{ t.spec }}</div>
|
||||
<div style="{{ t.s }}">{{ t.sample }}</div>
|
||||
</div>
|
||||
</sc-for>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,600px),1fr));gap:24px">
|
||||
<sc-for list="{{ themes }}" as="th" hint-placeholder-count="2">
|
||||
<div style="{{ th.vars }}">
|
||||
<div style="display:flex;flex-direction:column;gap:28px;padding:28px;border-radius:28px;background:var(--bg);color:var(--fg1);font-family:var(--ft)">
|
||||
<div style="font:600 32px/0.9 var(--fd);letter-spacing:-0.03em">{{ th.label }}</div>
|
||||
|
||||
<div style="display:flex;flex-direction:column;gap:12px">
|
||||
<div style="font:600 13px/1 var(--ft);color:var(--fg2)">Color</div>
|
||||
<div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(120px,1fr));gap:8px">
|
||||
<sc-for list="{{ th.swatches }}" as="c" hint-placeholder-count="16">
|
||||
<div style="display:flex;flex-direction:column;gap:6px;padding:6px;border-radius:14px;background:var(--sf)">
|
||||
<div style="{{ c.s }}"></div>
|
||||
<div style="padding:0 4px 4px;display:flex;flex-direction:column;gap:3px"><div style="font:600 12px/1 var(--ft)">{{ c.name }}</div><div style="font:400 11px/1 ui-monospace,Menlo,monospace;color:var(--fg3)">{{ c.hex }}</div></div>
|
||||
</div>
|
||||
</sc-for>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="display:flex;flex-direction:column;gap:12px">
|
||||
<div style="font:600 13px/1 var(--ft);color:var(--fg2)">File-type tiles</div>
|
||||
<div style="display:flex;gap:14px;flex-wrap:wrap">
|
||||
<sc-for list="{{ kinds }}" as="k" hint-placeholder-count="7">
|
||||
<div style="display:flex;flex-direction:column;align-items:center;gap:6px"><div style="{{ k.tile }}"><span style="{{ k.ico }}"></span></div><div style="font:500 12px/1 var(--ft);color:var(--fg2)">{{ k.name }}</div></div>
|
||||
</sc-for>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="display:flex;flex-direction:column;gap:12px">
|
||||
<div style="font:600 13px/1 var(--ft);color:var(--fg2)">Buttons</div>
|
||||
<div style="display:flex;gap:10px;flex-wrap:wrap;align-items:center">
|
||||
<div style="height:44px;padding:0 20px 0 16px;border-radius:999px;background:var(--ac);color:#FFFFFF;display:flex;align-items:center;gap:8px;font:600 15px/1 var(--ft);white-space:nowrap"><span style="{{ i18.plus }}"></span>Primary</div>
|
||||
<div style="height:44px;padding:0 20px;border-radius:999px;background:var(--acs);color:var(--act);display:flex;align-items:center;gap:8px;font:600 15px/1 var(--ft);white-space:nowrap"><span style="{{ i16.sync }}"></span>Tonal</div>
|
||||
<div style="height:44px;padding:0 20px;border-radius:999px;background:var(--sf2);display:flex;align-items:center;font:600 15px/1 var(--ft);white-space:nowrap">Secondary</div>
|
||||
<div style="height:44px;padding:0 20px;border-radius:999px;background:var(--dgs);color:var(--dg);display:flex;align-items:center;gap:8px;font:600 15px/1 var(--ft);white-space:nowrap"><span style="{{ i16.logout }}"></span>Danger</div>
|
||||
<div style="height:44px;padding:0 20px;border-radius:999px;border:1.5px solid var(--sf3);display:flex;align-items:center;gap:8px;font:600 15px/1 var(--ft);white-space:nowrap"><span style="{{ i16.send }}"></span>Outline</div>
|
||||
<div style="height:56px;padding:0 20px 0 16px;border-radius:999px;background:var(--ac);color:#FFFFFF;display:flex;align-items:center;gap:10px;font:600 16px/1 var(--ft);white-space:nowrap"><span style="{{ i24.plus }}"></span>FAB · Android</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="display:flex;flex-direction:column;gap:12px">
|
||||
<div style="font:600 13px/1 var(--ft);color:var(--fg2)">Chips, segmented, toggles, search</div>
|
||||
<div style="display:flex;gap:10px;flex-wrap:wrap;align-items:center">
|
||||
<div style="height:34px;padding:0 12px;border-radius:999px;background:var(--sf);display:flex;align-items:center;gap:6px;font:500 14px/1 var(--ft);white-space:nowrap"><span style="{{ i16.sort }}"></span>Name<span style="{{ i14.up }}"></span></div>
|
||||
<div style="height:34px;padding:0 12px;border-radius:999px;border:1px solid var(--ln);display:flex;align-items:center;gap:6px;font:500 14px/1 var(--ft);white-space:nowrap">Modified<span style="{{ i14.chevD }}"></span></div>
|
||||
<div style="height:34px;padding:0 12px;border-radius:999px;background:var(--acs);color:var(--act);display:flex;align-items:center;gap:6px;font:600 14px/1 var(--ft);white-space:nowrap">Available offline<span style="{{ i14.x }}"></span></div>
|
||||
<div style="display:flex;padding:3px;border-radius:999px;background:var(--sf);gap:2px"><div style="width:36px;height:28px;border-radius:999px;background:var(--acs);color:var(--act);display:flex;align-items:center;justify-content:center"><span style="{{ i18.list }}"></span></div><div style="width:36px;height:28px;color:var(--fg3);display:flex;align-items:center;justify-content:center"><span style="{{ i18.grid }}"></span></div></div>
|
||||
<div style="display:flex;padding:3px;border-radius:999px;background:var(--sf);gap:2px"><div style="height:30px;padding:0 14px;border-radius:999px;background:var(--acs);color:var(--act);display:flex;align-items:center;font:600 13px/1 var(--ft)">With you</div><div style="height:30px;padding:0 14px;display:flex;align-items:center;font:500 13px/1 var(--ft);color:var(--fg2)">By you</div><div style="height:30px;padding:0 14px;display:flex;align-items:center;font:500 13px/1 var(--ft);color:var(--fg2)">Links</div></div>
|
||||
<div style="width:48px;height:28px;border-radius:999px;background:var(--ac);padding:3px;box-sizing:border-box;display:flex;justify-content:flex-end"><div style="width:22px;height:22px;border-radius:999px;background:#FFFFFF"></div></div>
|
||||
<div style="width:48px;height:28px;border-radius:999px;background:var(--sf3);padding:3px;box-sizing:border-box;display:flex;justify-content:flex-start"><div style="width:22px;height:22px;border-radius:999px;background:#FFFFFF"></div></div>
|
||||
</div>
|
||||
<div style="height:38px;border-radius:12px;background:var(--sf);display:flex;align-items:center;gap:8px;padding:0 12px;color:var(--fg3);font:400 16px/1 var(--ft)"><span style="{{ i18.search }}"></span>Search</div>
|
||||
</div>
|
||||
|
||||
<div style="display:flex;flex-direction:column;gap:12px">
|
||||
<div style="font:600 13px/1 var(--ft);color:var(--fg2)">Grouped list · file rows · swipe</div>
|
||||
<div style="display:flex;flex-direction:column;gap:1px;background:var(--ln);border-radius:20px;overflow:hidden">
|
||||
<sc-for list="{{ rows }}" as="f" hint-placeholder-count="4">
|
||||
<div style="position:relative;background:var(--dgf)">
|
||||
<sc-if value="{{ f.swiped }}"><div style="position:absolute;right:0;top:0;bottom:0;width:96px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:5px;color:#FFFFFF;font:600 12px/1 var(--ft)"><span style="{{ i20.trash }}"></span>Delete</div></sc-if>
|
||||
<div style="{{ f.rs }}">
|
||||
<div style="{{ f.tile }}"><span style="{{ f.ico }}"></span></div>
|
||||
<div style="flex:1;min-width:0;display:flex;flex-direction:column;gap:4px">
|
||||
<div style="font:500 16px/1.2 var(--ft);white-space:nowrap;overflow:hidden;text-overflow:ellipsis">{{ f.name }}</div>
|
||||
<div style="display:flex;align-items:center;gap:5px;font:400 13px/1.2 var(--ft);color:var(--fg3);white-space:nowrap"><sc-if value="{{ f.hasBadge }}"><span style="{{ f.badge }}"></span></sc-if><sc-if value="{{ f.shared }}"><span style="{{ i14.users }}"></span></sc-if>{{ f.meta }}</div>
|
||||
</div>
|
||||
<sc-if value="{{ f.fav }}"><span style="{{ starSm }}"></span></sc-if>
|
||||
<div style="width:32px;display:flex;justify-content:center"><span style="{{ moreT }}"></span></div>
|
||||
</div>
|
||||
</div>
|
||||
</sc-for>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="display:flex;flex-direction:column;gap:12px">
|
||||
<div style="font:600 13px/1 var(--ft);color:var(--fg2)">Settings rows · progress · badges · avatars</div>
|
||||
<div style="display:flex;flex-direction:column;gap:1px;background:var(--ln);border-radius:20px;overflow:hidden">
|
||||
<div style="display:flex;align-items:center;gap:14px;padding:12px 16px;min-height:60px;box-sizing:border-box;background:var(--sf)"><span style="{{ i20.fingerprint }}"></span><div style="flex:1;display:flex;flex-direction:column;gap:4px"><div style="font:400 16px/1.1 var(--ft)">Toggle row</div><div style="font:400 13px/1.2 var(--ft);color:var(--fg3)">With a subtitle</div></div><div style="width:48px;height:28px;border-radius:999px;background:var(--ac);padding:3px;box-sizing:border-box;display:flex;justify-content:flex-end;flex:none"><div style="width:22px;height:22px;border-radius:999px;background:#FFFFFF"></div></div></div>
|
||||
<div style="display:flex;align-items:center;gap:14px;padding:0 16px;height:52px;background:var(--sf)"><span style="{{ i20.timer }}"></span><div style="flex:1;font:400 16px/1 var(--ft)">Value row</div><div style="display:flex;align-items:center;gap:4px;font:400 15px/1 var(--ft);color:var(--fg3)">1 minute<span style="{{ i18.chevR }}"></span></div></div>
|
||||
<div style="display:flex;flex-direction:column;gap:10px;padding:14px 16px;background:var(--sf)"><div style="display:flex;justify-content:space-between;font:400 16px/1 var(--ft)"><span>Progress row</span><span style="color:var(--fg3);font-size:15px">1.2 of 2 GB</span></div><div style="height:6px;border-radius:999px;background:var(--sf3);overflow:hidden"><div style="width:60%;height:100%;background:var(--ac)"></div></div></div>
|
||||
<div style="display:flex;align-items:center;gap:14px;padding:0 16px;height:52px;background:var(--sf);color:var(--dg)"><span style="{{ i20.trash }}"></span><div style="flex:1;font:500 16px/1 var(--ft)">Destructive row</div></div>
|
||||
</div>
|
||||
<div style="display:flex;gap:10px;align-items:center;flex-wrap:wrap">
|
||||
<div style="height:24px;padding:0 10px;border-radius:999px;background:var(--oks);color:var(--ok);display:flex;align-items:center;font:600 12px/1 var(--ft)">Connected</div>
|
||||
<div style="height:24px;padding:0 10px;border-radius:999px;background:var(--dgs);color:var(--dg);display:flex;align-items:center;font:600 12px/1 var(--ft)">Couldn’t sync</div>
|
||||
<div style="display:flex;align-items:center;gap:5px;font:400 13px/1 var(--ft);color:var(--fg3)"><span style="{{ bOk }}"></span>Synced</div>
|
||||
<div style="display:flex;align-items:center;gap:5px;font:400 13px/1 var(--ft);color:var(--fg3)"><span style="{{ bSync }}"></span>Syncing</div>
|
||||
<div style="display:flex;align-items:center;gap:5px;font:400 13px/1 var(--ft);color:var(--fg3)"><span style="{{ bErr }}"></span>Error</div>
|
||||
<div style="flex:1"></div>
|
||||
<div style="width:36px;height:36px;border-radius:999px;background:var(--acs);color:var(--act);display:flex;align-items:center;justify-content:center;font:600 13px/1 var(--ft)">MR</div>
|
||||
<div style="{{ avA }}">AS</div>
|
||||
<div style="{{ avB }}">LP</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="display:flex;flex-direction:column;gap:12px">
|
||||
<div style="font:600 13px/1 var(--ft);color:var(--fg2)">Navigation · iOS tab bar / Android navigation bar / desktop sidebar</div>
|
||||
<div style="display:flex;background:var(--sf);border-radius:20px;padding:10px 0">
|
||||
<sc-for list="{{ nav }}" as="n" hint-placeholder-count="5">
|
||||
<sc-if value="{{ n.on }}"><div style="flex:1;display:flex;flex-direction:column;align-items:center;gap:4px;color:var(--act);font:600 10px/1 var(--ft)"><span style="{{ n.ico }}"></span>{{ n.label }}</div></sc-if>
|
||||
<sc-if value="{{ n.off }}"><div style="flex:1;display:flex;flex-direction:column;align-items:center;gap:4px;color:var(--fg3);font:500 10px/1 var(--ft)"><span style="{{ n.ico }}"></span>{{ n.label }}</div></sc-if>
|
||||
</sc-for>
|
||||
</div>
|
||||
<div style="display:flex;background:var(--sf);border-radius:20px;padding:14px 0">
|
||||
<sc-for list="{{ nav }}" as="n" hint-placeholder-count="5">
|
||||
<div style="flex:1;display:flex;flex-direction:column;align-items:center;gap:4px">
|
||||
<sc-if value="{{ n.on }}"><div style="width:56px;height:32px;border-radius:999px;background:var(--acs);color:var(--act);display:flex;align-items:center;justify-content:center"><span style="{{ n.ico }}"></span></div><div style="font:600 12px/1 var(--ft)">{{ n.label }}</div></sc-if>
|
||||
<sc-if value="{{ n.off }}"><div style="width:56px;height:32px;color:var(--fg2);display:flex;align-items:center;justify-content:center"><span style="{{ n.ico }}"></span></div><div style="font:500 12px/1 var(--ft);color:var(--fg2)">{{ n.label }}</div></sc-if>
|
||||
</div>
|
||||
</sc-for>
|
||||
</div>
|
||||
<div style="display:flex;gap:4px;flex-wrap:wrap">
|
||||
<div style="height:38px;border-radius:12px;padding:0 12px;display:flex;align-items:center;gap:12px;background:var(--acs);color:var(--act);font:600 14px/1 var(--ft);width:220px;box-sizing:border-box"><span style="{{ i18.folder }}"></span>Files</div>
|
||||
<div style="height:38px;border-radius:12px;padding:0 12px;display:flex;align-items:center;gap:12px;font:500 14px/1 var(--ft);width:220px;box-sizing:border-box"><span style="{{ i18.trash }}"></span><div style="flex:1">Trash</div><div style="font:500 12px/1 var(--ft);color:var(--fg3)">12</div></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</sc-for>
|
||||
</div>
|
||||
</sc-if>
|
||||
</div>
|
||||
</x-dc>
|
||||
<script type="text/x-dc" data-dc-script>
|
||||
class Component extends DCLogic {
|
||||
componentDidMount() {
|
||||
if (!window.NK) this._t = setInterval(() => { if (window.NK) { clearInterval(this._t); this.forceUpdate(); } }, 40);
|
||||
}
|
||||
componentWillUnmount() { clearInterval(this._t); }
|
||||
renderVals() {
|
||||
const K = window.NK;
|
||||
if (!K) return { ready: false };
|
||||
const { I, ic, D, row, TH, tile, avatar } = K;
|
||||
const FD = "'Schibsted Grotesk',system-ui,sans-serif", FT = "'Instrument Sans',system-ui,sans-serif";
|
||||
const t = (spec, sample, s) => ({ spec, sample, s: { ...s, color: '#0E0D0B' } });
|
||||
const names = [['bg','--bg'],['surface','--sf'],['surface-2','--sf2'],['surface-3','--sf3'],['line','--ln'],['fg-1','--fg1'],['fg-2','--fg2'],['fg-3','--fg3'],['accent','--ac'],['accent-text','--act'],['accent-soft','--acs'],['danger','--dg'],['danger-soft','--dgs'],['success','--ok'],['success-soft','--oks'],['warning','--wn'],['warning-soft','--wns'],['info','--in'],['info-soft','--ins']];
|
||||
const ROW = { display: 'flex', alignItems: 'center', gap: 14, padding: '0 6px 0 14px', height: 64, background: 'var(--sf)', position: 'relative' };
|
||||
const demo = [D.files[2], D.files[3], D.offline[2], D.offline[4], { ...D.files[4] }].map(f => { const r = row(f); r.rs = { ...ROW, transform: r.swiped ? 'translateX(-96px)' : 'none' }; return r; });
|
||||
return {
|
||||
ready: true,
|
||||
i14: I[14], i16: I[16], i18: I[18], i20: I[20], i24: I[24],
|
||||
type: [
|
||||
t('Display 600 · 34/0.9 · −3%', 'Large title', { font: `600 34px/0.9 ${FD}`, letterSpacing: '-0.03em' }),
|
||||
t('Display 600 · 32/0.9 · −3%', '2.4 GB', { font: `600 32px/0.9 ${FD}`, letterSpacing: '-0.03em' }),
|
||||
t('Display 500 · 22/1 · −2%', 'Top bar title', { font: `500 22px/1 ${FD}`, letterSpacing: '-0.02em' }),
|
||||
t('Display 500 · 18/1 · −2%', 'Card title · September 2026', { font: `500 18px/1 ${FD}`, letterSpacing: '-0.02em' }),
|
||||
t('Text 500 · 16/1.2', 'Q3 Planning.pdf', { font: `500 16px/1.2 ${FT}` }),
|
||||
t('Text 400 · 15/1.3', 'Ana Souza shared Q3 Planning.pdf with you', { font: `400 15px/1.3 ${FT}` }),
|
||||
t('Text 600 · 13/1', 'Section label', { font: `600 13px/1 ${FT}` }),
|
||||
t('Text 400 · 13/1.2 · fg-3', '2.4 MB · Yesterday', { font: `400 13px/1.2 ${FT}`, opacity: 0.62 }),
|
||||
t('Mono 400 · 14', 'cloud.rocha.family/s/k7Pq2xW', { font: '400 14px/1 ui-monospace,Menlo,monospace' })
|
||||
],
|
||||
themes: ['light', 'dark'].map(id => ({ label: id === 'light' ? 'Light' : 'Dark', vars: TH[id],
|
||||
swatches: names.map(([name, v]) => ({ name, hex: TH[id][v], s: { height: 44, borderRadius: 10, background: `var(${v})`, boxShadow: 'inset 0 0 0 1px var(--ln)' } })) })),
|
||||
kinds: Object.keys(K.KIND).map(k => ({ name: k, tile: tile(k, 40, 12), ico: I[20][K.KIND[k][2]] })),
|
||||
rows: demo, starSm: ic('star', 16, 'var(--act)'), moreT: ic('moreH', 20, 'var(--fg3)'),
|
||||
bOk: ic('ok', 14, 'var(--ok)'), bSync: ic('sync', 14, 'var(--act)'), bErr: ic('alert', 14, 'var(--dg)'),
|
||||
avA: avatar('#DA9AC7', 36), avB: avatar('#8DCDE2', 36),
|
||||
nav: D.pinned.map(([label, ico], i) => ({ label, ico: I[24][ico], on: i === 0, off: i !== 0 }))
|
||||
};
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,93 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<script src="./support.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<x-dc>
|
||||
<helmet>
|
||||
<meta name="design_doc_mode" content="canvas">
|
||||
<script src="noo-kit.js"></script>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Instrument+Sans:wght@400;500;600&family=Schibsted+Grotesk:wght@500;600&display=swap">
|
||||
<style>
|
||||
body{margin:0;background:#EAE8E2}
|
||||
a{color:#8D0DE3;text-decoration:none}
|
||||
a:hover{color:#6E08B3}
|
||||
</style>
|
||||
</helmet>
|
||||
<div style="padding:96px;display:flex;flex-direction:column;gap:120px;font-family:'Instrument Sans',system-ui,sans-serif;color:#0E0D0B;width:max-content">
|
||||
<div style="display:flex;flex-direction:column;gap:20px;max-width:1100px">
|
||||
<div style="font:600 96px/0.9 'Schibsted Grotesk',system-ui,sans-serif;letter-spacing:-0.03em">Noo</div>
|
||||
<div style="font:400 28px/1.3 'Instrument Sans',system-ui,sans-serif;color:#5A5852;text-wrap:pretty">A Nextcloud client for iOS, Android, macOS and Windows. One brand language, navigation adapted per platform. Light and dark shown for every screen.</div>
|
||||
<div style="display:flex;gap:12px;font:600 20px/1 'Instrument Sans',system-ui,sans-serif"><a href="Noo Design System.dc.html" style="height:52px;padding:0 24px;border-radius:999px;background:#8D0DE3;color:#FFFFFF;display:flex;align-items:center;white-space:nowrap">Open the design system</a><a href="DESIGN_SYSTEM.md" style="height:52px;padding:0 24px;border-radius:999px;background:#FFFFFF;display:flex;align-items:center;white-space:nowrap">DESIGN_SYSTEM.md</a></div>
|
||||
</div>
|
||||
|
||||
<sc-for list="{{ mobile }}" as="p" hint-placeholder-count="2">
|
||||
<section style="display:flex;flex-direction:column;gap:40px">
|
||||
<div style="display:flex;align-items:baseline;gap:24px;border-bottom:2px solid #0E0D0B;padding-bottom:20px"><div style="font:600 72px/0.9 'Schibsted Grotesk',system-ui,sans-serif;letter-spacing:-0.03em">{{ p.name }}</div><div style="font:400 24px/1.2 'Instrument Sans',system-ui,sans-serif;color:#5A5852;white-space:nowrap">{{ p.note }}</div></div>
|
||||
<div style="display:flex;gap:120px">
|
||||
<sc-for list="{{ p.themes }}" as="t" hint-placeholder-count="2">
|
||||
<div style="display:flex;flex-direction:column;gap:32px">
|
||||
<div style="font:500 36px/1 'Schibsted Grotesk',system-ui,sans-serif;letter-spacing:-0.02em">{{ t.label }}</div>
|
||||
<div style="display:grid;grid-template-columns:repeat(7,390px);gap:72px 48px">
|
||||
<sc-for list="{{ screensM }}" as="sc" hint-placeholder-count="14">
|
||||
<div style="display:flex;flex-direction:column;gap:14px">
|
||||
<div style="display:flex;gap:10px;align-items:baseline;font:500 18px/1 'Instrument Sans',system-ui,sans-serif"><span style="color:#7C7A72">{{ sc.n }}</span><span style="white-space:nowrap">{{ sc.label }}</span></div>
|
||||
<div style="width:390px;height:844px;border-radius:48px;box-shadow:0 0 0 1px rgba(14,13,11,0.08),0 24px 48px rgba(30,0,47,0.10)">
|
||||
<dc-import name="Mobile Screen" platform="{{ p.id }}" screen="{{ sc.id }}" theme="{{ t.id }}" hint-size="390px,844px"></dc-import>
|
||||
</div>
|
||||
</div>
|
||||
</sc-for>
|
||||
</div>
|
||||
</div>
|
||||
</sc-for>
|
||||
</div>
|
||||
</section>
|
||||
</sc-for>
|
||||
|
||||
<sc-for list="{{ desktop }}" as="p" hint-placeholder-count="2">
|
||||
<section style="display:flex;flex-direction:column;gap:40px">
|
||||
<div style="display:flex;align-items:baseline;gap:24px;border-bottom:2px solid #0E0D0B;padding-bottom:20px"><div style="font:600 72px/0.9 'Schibsted Grotesk',system-ui,sans-serif;letter-spacing:-0.03em">{{ p.name }}</div><div style="font:400 24px/1.2 'Instrument Sans',system-ui,sans-serif;color:#5A5852;white-space:nowrap">{{ p.note }}</div></div>
|
||||
<div style="display:flex;gap:160px">
|
||||
<sc-for list="{{ p.themes }}" as="t" hint-placeholder-count="2">
|
||||
<div style="display:flex;flex-direction:column;gap:32px">
|
||||
<div style="font:500 36px/1 'Schibsted Grotesk',system-ui,sans-serif;letter-spacing:-0.02em">{{ t.label }}</div>
|
||||
<div style="display:grid;grid-template-columns:repeat(3,1280px);gap:72px 64px">
|
||||
<sc-for list="{{ screensD }}" as="sc" hint-placeholder-count="12">
|
||||
<div style="display:flex;flex-direction:column;gap:14px">
|
||||
<div style="display:flex;gap:10px;align-items:baseline;font:500 20px/1 'Instrument Sans',system-ui,sans-serif"><span style="color:#7C7A72">{{ sc.n }}</span><span style="white-space:nowrap">{{ sc.label }}</span></div>
|
||||
<div style="width:1280px;height:800px;border-radius:12px;box-shadow:0 24px 48px rgba(30,0,47,0.12)">
|
||||
<dc-import name="Desktop Screen" os="{{ p.id }}" screen="{{ sc.id }}" theme="{{ t.id }}" hint-size="1280px,800px"></dc-import>
|
||||
</div>
|
||||
</div>
|
||||
</sc-for>
|
||||
</div>
|
||||
</div>
|
||||
</sc-for>
|
||||
</div>
|
||||
</section>
|
||||
</sc-for>
|
||||
</div>
|
||||
</x-dc>
|
||||
<script type="text/x-dc" data-dc-script data-props="{"platforms":{"editor":"enum","options":["all","ios","android","mac","windows"],"default":"all","tsType":"string"},"themes":{"editor":"enum","options":["both","light","dark"],"default":"both","tsType":"string"}}">
|
||||
class Component extends DCLogic {
|
||||
renderVals() {
|
||||
const pf = this.props.platforms || 'all';
|
||||
const th = this.props.themes || 'both';
|
||||
const themes = [{ id: 'light', label: 'Light' }, { id: 'dark', label: 'Dark' }].filter(t => th === 'both' || th === t.id);
|
||||
const M = [['files','Files · list'],['filesGrid','Files · grid'],['photos','Photos'],['favorites','Favorites'],['offline','Offline'],['shares','Shares'],['recent','Recent'],['activity','Activity'],['trash','Trash'],['drawer','Menu (unpinned tabs)'],['share','Share sheet'],['settings','Settings · account & security'],['settings2','Settings · sync, cache, appearance'],['settings3','Settings · tabs & swipe']];
|
||||
const Dk = [['files','Files · list'],['filesGrid','Files · grid'],['photos','Photos'],['favorites','Favorites'],['offline','Offline'],['shares','Shares'],['recent','Recent'],['activity','Activity'],['trash','Trash'],['share','Share dialog'],['settings','Settings · account, security, sync'],['settings2','Settings · cache, appearance, tabs, swipe']];
|
||||
const num = a => a.map(([id, label], i) => ({ id, label, n: String(i + 1).padStart(2, '0') }));
|
||||
const keep = id => pf === 'all' || pf === id;
|
||||
return {
|
||||
screensM: num(M), screensD: num(Dk),
|
||||
mobile: [{ id: 'ios', name: 'iOS', note: 'Large titles, tab bar, “+” upload in the nav bar.', themes }, { id: 'android', name: 'Android', note: 'Top app bar, navigation bar with pill indicator, Upload FAB.', themes }].filter(p => keep(p.id)),
|
||||
desktop: [{ id: 'mac', name: 'macOS', note: 'Traffic lights in the sidebar, back/forward in the toolbar.', themes }, { id: 'windows', name: 'Windows', note: 'Title bar with caption buttons, same sidebar and toolbar.', themes }].filter(p => keep(p.id))
|
||||
};
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,13 @@
|
||||
# Styling
|
||||
|
||||
**Migration in progress:** this file documents the current (pre-rework)
|
||||
Material 3 theme. The target look is
|
||||
[`design-system/DESIGN_SYSTEM.md`](design-system/DESIGN_SYSTEM.md) — warm
|
||||
neutrals, one violet accent, pill controls, Schibsted Grotesk/Instrument
|
||||
Sans, no gradients/shadows. Update this file to describe the new system as
|
||||
each area gets reworked, rather than leaving stale Material 3 guidance next
|
||||
to a design system that's already superseded it.
|
||||
|
||||
## Theme
|
||||
|
||||
All theming goes through [`AppTheme`](../../lib/theme/app_theme.dart)
|
||||
@@ -127,4 +135,8 @@ widgets. Key points:
|
||||
ColorFilter.mode(colorScheme.onSurface, BlendMode.srcIn), ...)` so it
|
||||
reads correctly in both light and dark mode. Never the full-color
|
||||
`app_icon.png`/adaptive-icon assets for in-app UI — those are for the
|
||||
launcher icon only (`flutter_launcher_icons` in `pubspec.yaml`).
|
||||
launcher icon only. The launcher icon is maintained by hand from an
|
||||
IconKitchen export (`mipmap-*` in `android/app/src/main/res`); there is no
|
||||
generator step. `assets/icon/app_icon_monochrome.png` is deliberately a
|
||||
tightly-cropped glyph (unlike the launcher's safe-zone-padded monochrome
|
||||
layer), so it renders at a sensible size at 72-80px.
|
||||
|
||||
@@ -15,6 +15,11 @@ relevant file(s) before working in that area rather than loading all of them:
|
||||
conventions, fonts, reusable chrome widgets
|
||||
- [`standards.md`](.claude/context/standards.md) — code style, comment
|
||||
conventions, linting, testing
|
||||
- [`design-system/DESIGN_SYSTEM.md`](.claude/context/design-system/DESIGN_SYSTEM.md)
|
||||
— the target visual/component spec (tokens, components, platform
|
||||
mapping, screen recipes) for the in-progress UI rework; the sibling
|
||||
`.dc.html`/`noo-kit.js` files it references are the visual/token
|
||||
reference builds, not something to read directly
|
||||
|
||||
## Common commands
|
||||
|
||||
|
||||
Reference in New Issue
Block a user