@joinskips/brand 5.0.0-develop.117 → 5.0.0-develop.119
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -0
- package/chat/components/Welcome.d.ts +3 -0
- package/chat/components/Welcome.js +30 -4
- package/manifest.json +4 -0
- package/package.json +4 -4
- package/tokens/skips-tailwind-theme.css +106 -0
package/README.md
CHANGED
|
@@ -13,4 +13,11 @@ import tokens from '@joinskips/brand/tokens/skips-design-tokens.json' with { typ
|
|
|
13
13
|
@import '@joinskips/brand/fonts/onest/onest.css';
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
+
A Tailwind 4 app imports the tokens as its theme. The colours sit under `@variant light` and `@variant dark`, the way
|
|
17
|
+
Uniwind reads them.
|
|
18
|
+
|
|
19
|
+
```css
|
|
20
|
+
@import '@joinskips/brand/tokens/skips-tailwind-theme.css';
|
|
21
|
+
```
|
|
22
|
+
|
|
16
23
|
`manifest.json` lists every file with its hash and size. Onest's licence is `fonts/onest/OFL.txt`.
|
|
@@ -62,6 +62,9 @@ export declare function CodeStep({ words, length, noMatch, ranOut, resendAfterMs
|
|
|
62
62
|
onResend: () => void;
|
|
63
63
|
onChangeEmail: () => void;
|
|
64
64
|
}): import("react").JSX.Element;
|
|
65
|
+
export declare const DOT_REST_OPACITY = 0.35;
|
|
66
|
+
export declare const DOT_RISE = 3;
|
|
67
|
+
export declare const DOT_STILL_OPACITY = 0.6;
|
|
65
68
|
/** Skip writing a reply: three dots rising in turn in Skip's bubble beside Skip's mark, announced as a status. */
|
|
66
69
|
export declare function SkipTyping({ label, skipMark }: {
|
|
67
70
|
label: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useRef, useState } from 'react';
|
|
3
|
-
import { ActivityIndicator, Animated, Image, Pressable, Text, TextInput, View } from 'react-native';
|
|
3
|
+
import { AccessibilityInfo, ActivityIndicator, Animated, Image, Pressable, Text, TextInput, View } from 'react-native';
|
|
4
4
|
import { DOT_CYCLE_MS } from "../skipTyping.js";
|
|
5
5
|
import { codeDigits, completesCode, EMAIL_MAX_LENGTH, givenEmail, givenName, NAME_MAX_LENGTH, RESEND_AFTER_MS, resendClock, } from "../welcome.js";
|
|
6
6
|
import { useColor } from "./parts.js";
|
|
@@ -74,17 +74,38 @@ export function CodeStep({ words, length, noMatch, ranOut, resendAfterMs = RESEN
|
|
|
74
74
|
setCode(digits);
|
|
75
75
|
if (completesCode(digits, code, length))
|
|
76
76
|
onSubmit(digits);
|
|
77
|
-
}, accessibilityLabel: words.codeLabel, "aria-invalid": error !== null, inputMode: "numeric", autoComplete: "one-time-code", textContentType: "oneTimeCode", caretHidden: true, className: "absolute inset-0 rounded-control text-transparent" })] }), error ? (_jsx(Text, { role: "alert", className: "text-center font-ui text-sm text-error-ink", children: error })) : null, _jsxs(View, { className: "flex-row flex-wrap items-center justify-center gap-2", children: [_jsx(Pill, { label: words.changeEmail, look: "flat", onPress: onChangeEmail }), _jsx(NewCode, { waitMs: resendAfterMs, words: words, onResend: onResend }), _jsx(Pill, { label: words.codeSubmit, onPress: () => {
|
|
77
|
+
}, accessibilityLabel: words.codeLabel, "aria-invalid": error !== null, inputMode: "numeric", autoComplete: "one-time-code", textContentType: "oneTimeCode", caretHidden: true, className: "absolute inset-0 rounded-control text-transparent" })] }), error ? (_jsx(Text, { role: "alert", className: "text-center font-ui text-sm text-error-ink", children: error })) : null, _jsxs(View, { className: "flex-row flex-wrap items-center justify-center gap-2", children: [_jsx(Pill, { label: words.changeEmail, look: "flat", onPress: onChangeEmail }), _jsx(NewCode, { waitMs: resendAfterMs, words: words, onResend: onResend }), _jsx(Pill, { label: words.codeSubmit, disabled: code.length < length, onPress: () => {
|
|
78
78
|
onSubmit(code);
|
|
79
79
|
} })] })] }));
|
|
80
80
|
}
|
|
81
81
|
const DOTS = [0, 1, 2];
|
|
82
82
|
const DOT_SIZE = 6;
|
|
83
|
+
// A dot at rest is faint, rises this far at the top of its turn, and holds at the still strength for a visitor who
|
|
84
|
+
// asks for less motion.
|
|
85
|
+
export const DOT_REST_OPACITY = 0.35;
|
|
86
|
+
export const DOT_RISE = 3;
|
|
87
|
+
export const DOT_STILL_OPACITY = 0.6;
|
|
88
|
+
// Null until the device has answered, so the dots never start before a visitor who wants them still is known.
|
|
89
|
+
function useReducedMotion() {
|
|
90
|
+
const [reduced, setReduced] = useState(null);
|
|
91
|
+
useEffect(() => {
|
|
92
|
+
void AccessibilityInfo.isReduceMotionEnabled().then(setReduced);
|
|
93
|
+
const change = AccessibilityInfo.addEventListener('reduceMotionChanged', setReduced);
|
|
94
|
+
return () => {
|
|
95
|
+
change.remove();
|
|
96
|
+
};
|
|
97
|
+
}, []);
|
|
98
|
+
return reduced;
|
|
99
|
+
}
|
|
83
100
|
/** Skip writing a reply: three dots rising in turn in Skip's bubble beside Skip's mark, announced as a status. */
|
|
84
101
|
export function SkipTyping({ label, skipMark }) {
|
|
85
102
|
const dotColor = useColor('ink-secondary');
|
|
103
|
+
const reduced = useReducedMotion();
|
|
104
|
+
const still = reduced === true;
|
|
86
105
|
const rise = useRef(DOTS.map(() => new Animated.Value(0))).current;
|
|
87
106
|
useEffect(() => {
|
|
107
|
+
if (reduced !== false)
|
|
108
|
+
return undefined;
|
|
88
109
|
const step = DOT_CYCLE_MS / (2 * DOTS.length);
|
|
89
110
|
const loop = Animated.loop(Animated.stagger(step, rise.map((value) => Animated.sequence([
|
|
90
111
|
Animated.timing(value, { toValue: 1, duration: step, useNativeDriver: true }),
|
|
@@ -94,12 +115,17 @@ export function SkipTyping({ label, skipMark }) {
|
|
|
94
115
|
return () => {
|
|
95
116
|
loop.stop();
|
|
96
117
|
};
|
|
97
|
-
}, [rise]);
|
|
118
|
+
}, [rise, reduced]);
|
|
98
119
|
return (_jsxs(View, { className: "mt-3 flex-row items-end gap-2", children: [_jsx(Image, { source: skipMark, "aria-hidden": true, style: { width: 32, height: 32 }, className: "rounded-control" }), _jsx(View, { role: "status", accessibilityLabel: label, className: "flex-row items-center gap-1 rounded-[20px] rounded-bl-[7px] border border-line-subtle bg-surface px-4 py-4", children: rise.map((value, dot) => (_jsx(Animated.View, { style: {
|
|
99
120
|
width: DOT_SIZE,
|
|
100
121
|
height: DOT_SIZE,
|
|
101
122
|
borderRadius: DOT_SIZE / 2,
|
|
102
123
|
backgroundColor: dotColor,
|
|
103
|
-
|
|
124
|
+
...(still
|
|
125
|
+
? { opacity: DOT_STILL_OPACITY }
|
|
126
|
+
: {
|
|
127
|
+
opacity: value.interpolate({ inputRange: [0, 1], outputRange: [DOT_REST_OPACITY, 1] }),
|
|
128
|
+
transform: [{ translateY: value.interpolate({ inputRange: [0, 1], outputRange: [0, -DOT_RISE] }) }],
|
|
129
|
+
}),
|
|
104
130
|
} }, DOTS[dot]))) })] }));
|
|
105
131
|
}
|
package/manifest.json
CHANGED
|
@@ -484,6 +484,10 @@
|
|
|
484
484
|
"tokens/skips-design-tokens.json": {
|
|
485
485
|
"sha256": "bd0deecdedbad1a5ab28d0ec3231095d2b4691390a7d42257d259f3197f181ef",
|
|
486
486
|
"bytes": 3205
|
|
487
|
+
},
|
|
488
|
+
"tokens/skips-tailwind-theme.css": {
|
|
489
|
+
"sha256": "00fef53e4e6c3bde68e93a2e5f0ba28edcf17e6da5df6823c7601461462364af",
|
|
490
|
+
"bytes": 3240
|
|
487
491
|
}
|
|
488
492
|
}
|
|
489
493
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@joinskips/brand",
|
|
3
|
-
"version": "5.0.0-develop.
|
|
3
|
+
"version": "5.0.0-develop.119",
|
|
4
4
|
"description": "Skips design tokens, Onest, logos, favicons, interface icons, member pictures and app icons.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"homepage": "https://brand.joinskips.com",
|
|
@@ -20,10 +20,10 @@
|
|
|
20
20
|
"validator": "^13.15.35"
|
|
21
21
|
},
|
|
22
22
|
"peerDependencies": {
|
|
23
|
-
"react": "^19.
|
|
23
|
+
"react": "^19.0.0",
|
|
24
24
|
"react-native": ">=0.81.0",
|
|
25
|
-
"react-native-web": "~0.21.
|
|
26
|
-
"tailwindcss": "^4.
|
|
25
|
+
"react-native-web": "~0.21.0",
|
|
26
|
+
"tailwindcss": "^4.0.0",
|
|
27
27
|
"uniwind": "1.13.2"
|
|
28
28
|
},
|
|
29
29
|
"peerDependenciesMeta": {
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/* Written by scripts/derive.py from skips-design-tokens.json; do not edit by hand. */
|
|
2
|
+
@theme {
|
|
3
|
+
--font-ui: 'Onest Variable', Onest, system-ui, -apple-system, 'Segoe UI', Arial, sans-serif;
|
|
4
|
+
--text-xs: 12px;
|
|
5
|
+
--text-xs--line-height: 1.5;
|
|
6
|
+
--text-sm: 13px;
|
|
7
|
+
--text-sm--line-height: 1.5;
|
|
8
|
+
--text-base: 15px;
|
|
9
|
+
--text-base--line-height: 1.6;
|
|
10
|
+
--text-md: 16px;
|
|
11
|
+
--text-md--line-height: 1.6;
|
|
12
|
+
--text-lg: 18px;
|
|
13
|
+
--text-lg--line-height: 1.55;
|
|
14
|
+
--text-xl: 22px;
|
|
15
|
+
--text-xl--line-height: 1.4;
|
|
16
|
+
--text-2xl: 28px;
|
|
17
|
+
--text-2xl--line-height: 1.2;
|
|
18
|
+
--text-3xl: 36px;
|
|
19
|
+
--text-3xl--line-height: 1.1;
|
|
20
|
+
--text-4xl: 40px;
|
|
21
|
+
--text-4xl--line-height: 1.05;
|
|
22
|
+
--text-5xl: 54px;
|
|
23
|
+
--text-5xl--line-height: 1.03;
|
|
24
|
+
--text-6xl: 72px;
|
|
25
|
+
--text-6xl--line-height: 1.02;
|
|
26
|
+
--font-weight-light: 300;
|
|
27
|
+
--font-weight-regular: 400;
|
|
28
|
+
--font-weight-medium: 500;
|
|
29
|
+
--font-weight-semibold: 600;
|
|
30
|
+
--font-weight-bold: 700;
|
|
31
|
+
--font-weight-heavy: 800;
|
|
32
|
+
--radius-control: 8px;
|
|
33
|
+
--radius-card: 12px;
|
|
34
|
+
--radius-overlay: 16px;
|
|
35
|
+
--radius-pill: 9999px;
|
|
36
|
+
--shadow-card: 0 1px 2px rgba(33, 38, 41, 0.04);
|
|
37
|
+
--shadow-lift: 0 4px 12px rgba(33, 38, 41, 0.06);
|
|
38
|
+
--shadow-lift-hover: 0 8px 28px rgba(33, 38, 41, 0.14);
|
|
39
|
+
--shadow-menu: 0 8px 24px rgba(33, 38, 41, 0.12);
|
|
40
|
+
--shadow-modal: 0 24px 64px rgba(33, 38, 41, 0.18);
|
|
41
|
+
--ease-standard: cubic-bezier(0.2, 0, 0, 1);
|
|
42
|
+
--ease-pulse: cubic-bezier(0.4, 0, 0.6, 1);
|
|
43
|
+
--container-content: 1200px;
|
|
44
|
+
--container-reading: 720px;
|
|
45
|
+
--spacing-control: 48px;
|
|
46
|
+
--spacing-control-compact: 44px;
|
|
47
|
+
--spacing-header-short: 60px;
|
|
48
|
+
--spacing-header-tall: 76px;
|
|
49
|
+
--spacing-gutter-phone: 16px;
|
|
50
|
+
--spacing-gutter-tablet: 24px;
|
|
51
|
+
--spacing-gutter-desktop: 32px;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
@layer theme {
|
|
55
|
+
:root {
|
|
56
|
+
@variant light {
|
|
57
|
+
--color-page: #f8f5f2;
|
|
58
|
+
--color-surface: #ffffff;
|
|
59
|
+
--color-muted: #f5f6f7;
|
|
60
|
+
--color-paper: #f7f5f0;
|
|
61
|
+
--color-ink: #212629;
|
|
62
|
+
--color-ink-secondary: #5b5b57;
|
|
63
|
+
--color-ink-placeholder: #64645f;
|
|
64
|
+
--color-line-subtle: #d9d9d6;
|
|
65
|
+
--color-line-control: #85857f;
|
|
66
|
+
--color-accent: #f7ad00;
|
|
67
|
+
--color-accent-ink: #212629;
|
|
68
|
+
--color-action: #242e2b;
|
|
69
|
+
--color-action-hover: #314039;
|
|
70
|
+
--color-action-pressed: #1a231f;
|
|
71
|
+
--color-action-ink: #ffffff;
|
|
72
|
+
--color-error: #fff1f0;
|
|
73
|
+
--color-error-ink: #b42318;
|
|
74
|
+
--color-warning: #fff5d6;
|
|
75
|
+
--color-warning-ink: #854d0e;
|
|
76
|
+
--color-success: #dcf3e3;
|
|
77
|
+
--color-success-ink: #166534;
|
|
78
|
+
--color-focus: #212629;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
@variant dark {
|
|
82
|
+
--color-page: #0f1110;
|
|
83
|
+
--color-surface: #181a19;
|
|
84
|
+
--color-muted: #1f2221;
|
|
85
|
+
--color-paper: #1b1b18;
|
|
86
|
+
--color-ink: #f5f6f4;
|
|
87
|
+
--color-ink-secondary: #b4b4ae;
|
|
88
|
+
--color-ink-placeholder: #8d8d87;
|
|
89
|
+
--color-line-subtle: #2c2e2d;
|
|
90
|
+
--color-line-control: #5a5c59;
|
|
91
|
+
--color-accent: #f7ad00;
|
|
92
|
+
--color-accent-ink: #212629;
|
|
93
|
+
--color-action: #3a4a44;
|
|
94
|
+
--color-action-hover: #46574f;
|
|
95
|
+
--color-action-pressed: #2f3c37;
|
|
96
|
+
--color-action-ink: #ffffff;
|
|
97
|
+
--color-error: #3a1b19;
|
|
98
|
+
--color-error-ink: #ff8a80;
|
|
99
|
+
--color-warning: #3a2e10;
|
|
100
|
+
--color-warning-ink: #f5c451;
|
|
101
|
+
--color-success: #12301f;
|
|
102
|
+
--color-success-ink: #7ddc9c;
|
|
103
|
+
--color-focus: #f5f6f4;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|