@vibeuncle/gpgb-ui 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/DESIGN.md +3 -1
- package/DESIGN_SYSTEM.md +12 -2
- package/README.md +1 -1
- package/package.json +1 -1
- package/src/components/Layout.tsx +8 -3
- package/src/components/SiteHeader.tsx +1 -1
- package/styles/components.css +14 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
Versions follow semver while 0.x: **minor** = new components or token changes that may shift appearance, **patch** = fixes. Apps pin with `^0.x.0`.
|
|
4
4
|
|
|
5
|
+
## 0.3.0
|
|
6
|
+
- **Page width standard:** the 72rem (1152px) frame of draw.gpgb.app, now with responsive gutters (16px, 24px from 640px) so desktop content is 1104px. `ds-container-wide` (80rem), `ds-measure` (42rem reading column inside the frame), `ds-split` / `<SplitLayout>` (content + 22rem side panel), `ds-grid-cards` (auto-fill card grid). `<PageShell wide>`.
|
|
7
|
+
- Docs: Tailwind's `rounded-sm/md/lg/xl` and `shadow-sm/md/lg` follow the system scale (they are defined in `@theme`), and the page-width rules.
|
|
8
|
+
|
|
9
|
+
## 0.2.1
|
|
10
|
+
- Release pipeline only: publishes through npm trusted publishing (no token). No code or appearance changes.
|
|
11
|
+
|
|
5
12
|
## 0.2.0 — first public release
|
|
6
13
|
- Tokens: paper/ink/accent palette with dark mode, `accent-text`, `border-strong`, `focus`, `on-accent`/`on-danger`; radii, shadows, motion tokens.
|
|
7
14
|
- `ds-*` CSS components and a React package: buttons, forms, cards, badges, tabs, modal, confirm dialog, sheet, menu, popover, tooltip, toast, stamp, skeleton.
|
package/DESIGN.md
CHANGED
|
@@ -187,7 +187,9 @@ Rule: no raw hex in app code; no Tailwind red/gray/orange.
|
|
|
187
187
|
|
|
188
188
|
## Layout
|
|
189
189
|
|
|
190
|
-
-
|
|
190
|
+
- **Page frame:** 72rem (1152px) centered, as draw.gpgb.app; gutters 16px, then 24px from 640px (1104px of content on desktop). The header and the content share it. Editors and big tables use the 80rem wide frame. Never a narrower frame: narrow content is a 42rem column (`ds-measure`) inside it; sign-in, invite and not-found are a 400px centered card.
|
|
191
|
+
- **Using the width:** content plus a 22rem side panel (`ds-split`, from 1024px, sticky; stacks on smaller screens), responsive card grids (`ds-grid-cards`, columns of at least 18rem), or a 240px left navigation column for editors and admin.
|
|
192
|
+
- 4px spacing base. Card padding 16 to 24px; field gap 16px; button icon gap 8px.
|
|
191
193
|
- Mobile-first; `sm` (640px) is the phone/tablet switch. On touch (`pointer: coarse`) inputs are 16px (no iOS zoom) and buttons are 44px tall; switches get a 44px hit area; tabs 40px.
|
|
192
194
|
- Sections separate with generous vertical space (40px) and a hairline; groups inside stay tight.
|
|
193
195
|
|
package/DESIGN_SYSTEM.md
CHANGED
|
@@ -89,7 +89,7 @@ Rules: one flourish per view; everything else is quiet feedback that answers an
|
|
|
89
89
|
## Navigation
|
|
90
90
|
| Piece | React | Notes |
|
|
91
91
|
|---|---|---|
|
|
92
|
-
| Header | `<SiteHeader logoSrc title nav actions menuButton containerClassName homeLabel>` | Graphic logo left; `nav` shows from `md`; `menuButton` shows below `md`. Includes a skip link to `#main` (give your `<main>` that id). `containerClassName` sets the content width (default 72rem `ds-container
|
|
92
|
+
| Header | `<SiteHeader logoSrc title nav actions menuButton containerClassName homeLabel>` | Graphic logo left; `nav` shows from `md`; `menuButton` shows below `md`. Includes a skip link to `#main` (give your `<main>` that id). `containerClassName` sets the content width (default the 72rem `ds-container` frame; pass `ds-container ds-container-wide` on wide pages; don't narrow it). Put short always-visible links in `actions` instead of `nav`. |
|
|
93
93
|
| Nav links | `<NavLinks items>` / `ds-nav-link` | Pill links; current = accent-soft wash + `aria-current="page"`. |
|
|
94
94
|
| Phone nav | `<MenuButton>` + `<NavDrawer items open onOpenChange>` | Left drawer (`Sheet side="left"`). Closes on link click, Esc, scrim. |
|
|
95
95
|
| Account | `<UserMenu>` / `<SignInButton>` | Avatar + menu: settings, extras, sign out. Signed out: outline 登录 button. |
|
|
@@ -105,8 +105,18 @@ Pick by job: **Menu** = list of actions; **Popover** = a little extra content or
|
|
|
105
105
|
- Modal, ConfirmDialog and Sheet trap focus, close on Esc, lock scroll and restore focus to the opener. Footer order: outline cancel, then the primary or danger action, whose label names the action ("删除海报", not "确定").
|
|
106
106
|
- Positioning is simple (below the trigger, start or end aligned); there is no collision flipping yet. Keep triggers away from the bottom edge, or use a Sheet on phones.
|
|
107
107
|
|
|
108
|
+
## Page width
|
|
109
|
+
One width across all 大道大商 apps: the **72rem frame** (1152px, centered), as on draw.gpgb.app. Gutters are 16px, then 24px from 640px, so desktop content is **1104px** wide. The header and the page content share the frame.
|
|
110
|
+
- **Standard:** `ds-container` (72rem). Galleries, dashboards, chat, lists, forms-with-context.
|
|
111
|
+
- **Wide:** `ds-container ds-container-wide` (80rem). Editors and big tables only. Pass the same to `SiteHeader`'s `containerClassName`.
|
|
112
|
+
- **Never narrow the frame.** Narrow content is a column *inside* it: `ds-measure` (42rem) for reading text or a single form. Sign-in, invite and not-found pages are a `CenteredPage` card (400px).
|
|
113
|
+
- **Use the width:** `ds-split` / `<SplitLayout aside>` puts content on the left and a 22rem side panel (share link, QR, info, actions) on the right from 1024px, stacking below on smaller screens; `ds-grid-cards` is a responsive card grid (columns of at least 18rem); `<SidebarLayout>` is a left navigation column (240px) for editors, settings and admin.
|
|
114
|
+
- **Phones:** everything is one column with 16px gutters; the frame only matters from tablet up.
|
|
115
|
+
|
|
116
|
+
Tailwind note: `rounded-sm/md/lg/xl` (6/8/12/16px) and `shadow-sm/md/lg` are the system scale (they are defined in `@theme`), so they differ slightly from Tailwind's defaults in every app that imports the package. Use them rather than arbitrary radii.
|
|
117
|
+
|
|
108
118
|
## Page layouts
|
|
109
|
-
`<PageShell header footer>` (header,
|
|
119
|
+
`<PageShell header footer wide>` (header, frame, footer: lists, galleries, dashboards) · `<CenteredPage>` (one 400px card: sign-in, invite, not-found) · `<SplitLayout aside>` (content + right side panel) · `<SidebarLayout aside>` (left navigation column: editors, settings, admin; on phones move it into a bottom Sheet) · `<PageTitle title description actions breadcrumbs>` (serif title, primary action first on phones).
|
|
110
120
|
|
|
111
121
|
## Content & voice
|
|
112
122
|
Warm, plain, respectful: a helpful neighbour at the community centre. Chinese (简体) first, English beside or beneath. Say what happened and what to do next; never blame the person.
|
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@ Then follow "Using it in an app" in [DESIGN_SYSTEM.md](./DESIGN_SYSTEM.md) (CSS
|
|
|
17
17
|
1. Change tokens/components; update the style guide and docs in the same commit; add a `CHANGELOG.md` entry.
|
|
18
18
|
2. `npm run check` (typecheck + browser tests; also runs in CI).
|
|
19
19
|
3. `npm version minor` (or `patch`), then `git push --follow-tags`.
|
|
20
|
-
4. The tag triggers `.github/workflows/release.yml`, which publishes to npm
|
|
20
|
+
4. The tag triggers `.github/workflows/release.yml`, which publishes to npm through trusted publishing (OIDC: npm trusts this repo and workflow, so there is no token to manage).
|
|
21
21
|
5. Apps pick it up via Renovate/Dependabot PRs (or `npm update @vibeuncle/gpgb-ui`).
|
|
22
22
|
|
|
23
23
|
Licence: proprietary (`UNLICENSED`): published for 大道大商 / VibeUncle apps, no reuse grant.
|
package/package.json
CHANGED
|
@@ -6,12 +6,12 @@ import { t } from '../copy'
|
|
|
6
6
|
import type { Lang } from '../copy'
|
|
7
7
|
import { useLink } from '../link'
|
|
8
8
|
|
|
9
|
-
/** Standard page: header, main, footer
|
|
10
|
-
export function PageShell({ header, children, footer }: { header?: ReactNode; children: ReactNode; footer?: ReactNode }) {
|
|
9
|
+
/** Standard page: header, main, footer, all on the 72rem frame (`wide` = 80rem for editors and big tables). */
|
|
10
|
+
export function PageShell({ header, children, footer, wide }: { header?: ReactNode; children: ReactNode; footer?: ReactNode; wide?: boolean }) {
|
|
11
11
|
return (
|
|
12
12
|
<div className="ds-page">
|
|
13
13
|
{header}
|
|
14
|
-
<main id="main" className=
|
|
14
|
+
<main id="main" className={cn('ds-container py-10', wide && 'ds-container-wide')}>{children}</main>
|
|
15
15
|
{footer}
|
|
16
16
|
</div>
|
|
17
17
|
)
|
|
@@ -38,6 +38,11 @@ export function PageTitle({ title, description, actions, breadcrumbs }: { title:
|
|
|
38
38
|
)
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
/** Content + side panel (share link, QR, info, actions). Panel is on the right from 1024px (sticky) and stacks below the content on smaller screens. */
|
|
42
|
+
export function SplitLayout({ aside, children }: { aside: ReactNode; children: ReactNode }) {
|
|
43
|
+
return <div className="ds-split"><div className="min-w-0">{children}</div><aside>{aside}</aside></div>
|
|
44
|
+
}
|
|
45
|
+
|
|
41
46
|
/** Sidebar + content (editor, settings, admin). Sidebar is sticky from `lg`; on phones put its content in a Sheet instead. */
|
|
42
47
|
export function SidebarLayout({ aside, children, wide }: { aside: ReactNode; children: ReactNode; wide?: boolean }) {
|
|
43
48
|
return <div className={cn('ds-shell', wide && 'ds-shell-wide')}><aside>{aside}</aside><div className="min-w-0">{children}</div></div>
|
|
@@ -7,7 +7,7 @@ import { useLink } from '../link'
|
|
|
7
7
|
* Phones: pass `menuButton` (see MenuButton + NavDrawer) and hide `nav` below `md` (NavLinks className="hidden md:flex"). */
|
|
8
8
|
export function SiteHeader({ logoSrc, logoAlt = '大道大商', title, nav, actions, menuButton, href = '/', containerClassName = 'ds-container', homeLabel }: {
|
|
9
9
|
logoSrc: string; logoAlt?: string; title?: string; nav?: ReactNode; actions?: ReactNode; menuButton?: ReactNode; href?: string
|
|
10
|
-
/** Width/gutter of the header content. Default `ds-container` (72rem).
|
|
10
|
+
/** Width/gutter of the header content. Default `ds-container` (the 72rem frame). Keep it equal to the page's frame: pass 'ds-container ds-container-wide' on wide pages. Don't narrow it; put narrow content in a column inside the frame. */
|
|
11
11
|
containerClassName?: string
|
|
12
12
|
/** aria-label for the logo link when there is no title (e.g. "接龙 首页"). */
|
|
13
13
|
homeLabel?: string
|
package/styles/components.css
CHANGED
|
@@ -288,7 +288,20 @@
|
|
|
288
288
|
.ds-header { border-bottom: 1px solid var(--color-border-soft); }
|
|
289
289
|
/* Hairline between the 大道大商 mark and the app name, so the graphic logo and the app title don't read as one phrase. */
|
|
290
290
|
.ds-brand-divider { width: 1px; height: 20px; flex-shrink: 0; background: var(--color-border-strong); opacity: 0.55; }
|
|
291
|
-
|
|
291
|
+
/* Page width: the 72rem frame (1152px, = draw.gpgb.app), gutters 16px then 24px from 640px, so 1104px of content on desktop.
|
|
292
|
+
Header and page content share it. Never use a narrower frame: put narrow content in a column INSIDE it (ds-measure). */
|
|
293
|
+
.ds-container { margin-inline: auto; width: 100%; max-width: 72rem; padding-inline: 16px; }
|
|
294
|
+
@media (min-width: 640px) { .ds-container { padding-inline: 24px; } }
|
|
295
|
+
.ds-container-wide { max-width: 80rem; } /* editors, big tables: add to ds-container */
|
|
296
|
+
.ds-measure { max-width: 42rem; } /* reading text / single-column form inside the frame */
|
|
297
|
+
/* Content + side panel. From 1024px the panel sits to the right (22rem, sticky); below that it stacks under the content. */
|
|
298
|
+
.ds-split { display: grid; gap: 24px; }
|
|
299
|
+
@media (min-width: 1024px) {
|
|
300
|
+
.ds-split { grid-template-columns: minmax(0, 1fr) 22rem; gap: 32px; }
|
|
301
|
+
.ds-split > aside { position: sticky; top: 24px; align-self: start; }
|
|
302
|
+
}
|
|
303
|
+
/* Responsive card grid: as many columns as fit at >=18rem. */
|
|
304
|
+
.ds-grid-cards { display: grid; gap: 16px; grid-template-columns: repeat(auto-fill, minmax(min(100%, 18rem), 1fr)); }
|
|
292
305
|
/* Underline draws in from the left on hover. */
|
|
293
306
|
.ds-link {
|
|
294
307
|
color: var(--color-ink-soft); text-decoration: none; background: linear-gradient(currentColor, currentColor) 0 100% / 0 1px no-repeat;
|