@apliteni/apliteni-ui 0.85.0 → 0.86.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/package.json +2 -2
- package/react/README.md +33 -0
- package/react/dist/index.d.ts +14 -1
- package/react/dist/index.js +42 -0
- package/src/components/index.js +6 -14
- package/src/components/topbar.js +2 -1
- package/src/index.d.ts +6 -1
- package/src/index.js +1 -0
- package/src/logic/accents.js +35 -0
- package/src/styles/segmented.css +20 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@apliteni/apliteni-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.86.0",
|
|
4
4
|
"workspaces": [
|
|
5
5
|
"react"
|
|
6
6
|
],
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"build-storybook": "storybook build -o storybook-static",
|
|
57
57
|
"build": "npm run build --workspace react",
|
|
58
58
|
"prepare": "npm run build",
|
|
59
|
-
"test": "for d in src stories site scripts; do [ -d \"$d\" ] || { echo \"npm test: no such directory: $d\" >&2; exit 1; }; done; node --test 'src/**/*.test.js' 'stories/**/*.test.js' 'site/**/*.test.js' 'scripts/**/*.test.js'",
|
|
59
|
+
"test": "for d in src stories site scripts; do [ -d \"$d\" ] || { echo \"npm test: no such directory: $d\" >&2; exit 1; }; done; node --test --test-reporter=spec --test-reporter-destination=stdout --test-reporter=./scripts/slow-tests.mjs --test-reporter-destination=stdout 'src/**/*.test.js' 'stories/**/*.test.js' 'site/**/*.test.js' 'scripts/**/*.test.js'",
|
|
60
60
|
"tokens:sync": "node scripts/sync-brand-tokens.mjs",
|
|
61
61
|
"tokens:check": "node scripts/sync-brand-tokens.mjs --check",
|
|
62
62
|
"tokens:drift": "node scripts/brand-drift.mjs"
|
package/react/README.md
CHANGED
|
@@ -786,3 +786,36 @@ use it to stay the same whenever they run. `locale` names the months and weekday
|
|
|
786
786
|
the trigger's trailing edge. Without `ariaLabel` the trigger's own text is its accessible
|
|
787
787
|
name, so a control reading "17 September 2026" is heard as that rather than as its
|
|
788
788
|
placeholder. The popover stays mounted while closed, and is `inert` while it is.
|
|
789
|
+
|
|
790
|
+
## AccentPicker
|
|
791
|
+
|
|
792
|
+
`AccentPicker` is a controlled group of the kit’s four accent swatches. Pass `value`
|
|
793
|
+
and `onChange`; optionally pass `options` to choose a subset or its order. Values are
|
|
794
|
+
`default`, `phoenix`, `ocean`, and `emerald` (`Accent`). Import the kit CSS.
|
|
795
|
+
|
|
796
|
+
```tsx
|
|
797
|
+
<AccentPicker value={accent} onChange={setAccent} />
|
|
798
|
+
```
|
|
799
|
+
|
|
800
|
+
Each button has an accessible name and a pressed state. Tab visits each choice;
|
|
801
|
+
Enter and Space request a change without submitting a surrounding form. The host
|
|
802
|
+
owns setting `data-accent` on the page and persisting the choice. The component does
|
|
803
|
+
neither. A value outside `options` leaves every button unpressed; an empty list
|
|
804
|
+
renders an empty group. Supply unique options.
|
|
805
|
+
|
|
806
|
+
The group accepts native div attributes, an additional `className`, and a forwarded
|
|
807
|
+
ref. Its default accessible name is “Accent”; override it with `aria-label` or
|
|
808
|
+
`aria-labelledby` when multiple pickers need distinct names.
|
|
809
|
+
|
|
810
|
+
It emits no `data-accent-pick` on its buttons, so a page that calls
|
|
811
|
+
`wireTopbar(document)` — which a half-migrated page must, to wire its vanilla
|
|
812
|
+
`footer({ switcher: accentPicker() })` — cannot adopt a picker React owns, apply the
|
|
813
|
+
accent and persist it behind your `onChange`. This is the same decision `Dropdown`,
|
|
814
|
+
`Drawer` and `ThemeToggle` make with their own wiring hooks.
|
|
815
|
+
|
|
816
|
+
The selected swatch is marked by a tick inside the circle, in the kit's ink for a
|
|
817
|
+
saturated fill. Focus is the kit ring (`--ring`) and it is the only accent edge the
|
|
818
|
+
control ever draws: selection and focus are one signal each, and only focus is an
|
|
819
|
+
accent. Accent names and swatch paints come from the kit's `ACCENTS` and
|
|
820
|
+
`accentSwatchStyle`, which the vanilla factory also reads, so the two pickers cannot
|
|
821
|
+
drift.
|
package/react/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { InputHTMLAttributes, ReactNode, ButtonHTMLAttributes, RefAttributes, ReactElement, AnchorHTMLAttributes, HTMLAttributes, RefObject, MouseEvent, ElementType, ComponentPropsWithoutRef, SelectHTMLAttributes, TextareaHTMLAttributes, SVGAttributes } from 'react';
|
|
3
|
+
import { ACCENTS } from '@apliteni/apliteni-ui';
|
|
3
4
|
|
|
4
5
|
declare function Icon({ name }: {
|
|
5
6
|
name: string;
|
|
@@ -931,7 +932,19 @@ declare const SidebarNav: react.ForwardRefExoticComponent<Omit<Omit<react.Detail
|
|
|
931
932
|
renderLink?: (item: SidebarNavItem, props: ComponentPropsWithoutRef<"a">) => ReactNode;
|
|
932
933
|
} & react.RefAttributes<HTMLElement>>;
|
|
933
934
|
|
|
935
|
+
type Accent = (typeof ACCENTS)[number];
|
|
936
|
+
type AccentPickerProps = Omit<HTMLAttributes<HTMLDivElement>, 'onChange' | 'children'> & {
|
|
937
|
+
value: Accent;
|
|
938
|
+
onChange: (value: Accent) => void;
|
|
939
|
+
options?: readonly Accent[];
|
|
940
|
+
};
|
|
941
|
+
declare const AccentPicker: react.ForwardRefExoticComponent<Omit<HTMLAttributes<HTMLDivElement>, "children" | "onChange"> & {
|
|
942
|
+
value: Accent;
|
|
943
|
+
onChange: (value: Accent) => void;
|
|
944
|
+
options?: readonly Accent[];
|
|
945
|
+
} & react.RefAttributes<HTMLDivElement>>;
|
|
946
|
+
|
|
934
947
|
declare const PAGE_SIZES: readonly number[];
|
|
935
948
|
declare const DEFAULT_PAGE_SIZE: number;
|
|
936
949
|
|
|
937
|
-
export { AppShell, type AppShellProps, type AppShellSection, BackLink, type BackLinkOwnProps, type BackLinkProps, Badge, BusyRegion, type BusyRegionProps, Button, type ButtonLinkProps, type ButtonProps, Callout, type CalloutProps, type CalloutVariant, Card, Checkbox, type CheckboxProps, type Column, type CommandGroup, type CommandItem, CommandPalette, type CommandPaletteProps, Confirm, type ConfirmProps, DEFAULT_PAGE_SIZE, DataTable, type DataTableProps, DatePicker, type DatePickerMode, type DatePickerPreset, type DatePickerProps, type DatePickerRange, DeltaValue, type DeltaValueProps, Denied, type DeniedProps, Drawer, type DrawerProps, DrawerSection, type DrawerSectionProps, Dropdown, type DropdownBadge, type DropdownEntry, type DropdownItem, type DropdownProps, type DropdownRowProps, type DropdownSearch, type DropdownSection, type DropdownSeparator, EmptyState, type EmptyStateProps, type EmptyStateVariant, Field, type FieldControlProps, type FieldProps, FileDrop, type FileDropFile, type FileDropProps, type FileDropStatus, FileField, type FileFieldProps, type Filter, FilterBar, type FilterBarProps, Icon, KeyValueList, type KeyValueListProps, type KeyValueRow, Modal, type ModalProps, type NativeButtonProps, NumericValue, type NumericValueProps, PAGE_SIZES, Pagination, type PaginationProps, Pill, type PillProps, RowIdentity, type RowIdentityProps, SearchField, type SearchFieldProps, type SegmentOption, Segmented, type SegmentedProps, SelectField, type SelectFieldProps, SidebarNav, type SidebarNavBadge, type SidebarNavItem, type SidebarNavLeaf, type SidebarNavProps, type SidebarNavSection, Skeleton, type SkeletonProps, SkeletonTable, type SkeletonTableProps, Snippet, type SnippetProps, StatBand, type StatBandProps, type StatDelta, type StatFigure, type StatTone, type StatVariant, StatusDot, type StatusDotProps, Success, SuccessCheck, type SuccessCheckProps, type SuccessCountdown, SuccessPanel, type SuccessPanelProps, type SuccessProps, Switch, type SwitchProps, THEME_INIT_SCRIPT, type TabItem, type TableSort, Tabs, type TabsProps, TextArea, type TextAreaProps, TextField, type TextFieldProps, ThemeToggle, type ThemeToggleProps, Timeline, type TimelineEvent, type TimelineEventKind, type TimelineProps, Toast, type ToastNotice, type ToastProps, Tooltip, type TooltipProps, sortTableRows, useToast };
|
|
950
|
+
export { type Accent, AccentPicker, type AccentPickerProps, AppShell, type AppShellProps, type AppShellSection, BackLink, type BackLinkOwnProps, type BackLinkProps, Badge, BusyRegion, type BusyRegionProps, Button, type ButtonLinkProps, type ButtonProps, Callout, type CalloutProps, type CalloutVariant, Card, Checkbox, type CheckboxProps, type Column, type CommandGroup, type CommandItem, CommandPalette, type CommandPaletteProps, Confirm, type ConfirmProps, DEFAULT_PAGE_SIZE, DataTable, type DataTableProps, DatePicker, type DatePickerMode, type DatePickerPreset, type DatePickerProps, type DatePickerRange, DeltaValue, type DeltaValueProps, Denied, type DeniedProps, Drawer, type DrawerProps, DrawerSection, type DrawerSectionProps, Dropdown, type DropdownBadge, type DropdownEntry, type DropdownItem, type DropdownProps, type DropdownRowProps, type DropdownSearch, type DropdownSection, type DropdownSeparator, EmptyState, type EmptyStateProps, type EmptyStateVariant, Field, type FieldControlProps, type FieldProps, FileDrop, type FileDropFile, type FileDropProps, type FileDropStatus, FileField, type FileFieldProps, type Filter, FilterBar, type FilterBarProps, Icon, KeyValueList, type KeyValueListProps, type KeyValueRow, Modal, type ModalProps, type NativeButtonProps, NumericValue, type NumericValueProps, PAGE_SIZES, Pagination, type PaginationProps, Pill, type PillProps, RowIdentity, type RowIdentityProps, SearchField, type SearchFieldProps, type SegmentOption, Segmented, type SegmentedProps, SelectField, type SelectFieldProps, SidebarNav, type SidebarNavBadge, type SidebarNavItem, type SidebarNavLeaf, type SidebarNavProps, type SidebarNavSection, Skeleton, type SkeletonProps, SkeletonTable, type SkeletonTableProps, Snippet, type SnippetProps, StatBand, type StatBandProps, type StatDelta, type StatFigure, type StatTone, type StatVariant, StatusDot, type StatusDotProps, Success, SuccessCheck, type SuccessCheckProps, type SuccessCountdown, SuccessPanel, type SuccessPanelProps, type SuccessProps, Switch, type SwitchProps, THEME_INIT_SCRIPT, type TabItem, type TableSort, Tabs, type TabsProps, TextArea, type TextAreaProps, TextField, type TextFieldProps, ThemeToggle, type ThemeToggleProps, Timeline, type TimelineEvent, type TimelineEventKind, type TimelineProps, Toast, type ToastNotice, type ToastProps, Tooltip, type TooltipProps, sortTableRows, useToast };
|
package/react/dist/index.js
CHANGED
|
@@ -3646,10 +3646,52 @@ var Success = forwardRef9(function Success2({
|
|
|
3646
3646
|
);
|
|
3647
3647
|
});
|
|
3648
3648
|
|
|
3649
|
+
// src/AccentPicker.tsx
|
|
3650
|
+
import { forwardRef as forwardRef10 } from "react";
|
|
3651
|
+
import { ACCENTS, accentSwatchStyle } from "@apliteni/apliteni-ui";
|
|
3652
|
+
import { jsx as jsx38 } from "react/jsx-runtime";
|
|
3653
|
+
var AccentPicker = forwardRef10(function AccentPicker2({
|
|
3654
|
+
value,
|
|
3655
|
+
onChange,
|
|
3656
|
+
options = ACCENTS,
|
|
3657
|
+
className,
|
|
3658
|
+
"aria-label": label = "Accent",
|
|
3659
|
+
...rest
|
|
3660
|
+
}, ref) {
|
|
3661
|
+
return /* @__PURE__ */ jsx38(
|
|
3662
|
+
"div",
|
|
3663
|
+
{
|
|
3664
|
+
...rest,
|
|
3665
|
+
ref,
|
|
3666
|
+
className: ["ui-accent-picker", className].filter(Boolean).join(" "),
|
|
3667
|
+
"data-accent-group": "",
|
|
3668
|
+
role: "group",
|
|
3669
|
+
"aria-label": label,
|
|
3670
|
+
children: options.map((accent) => {
|
|
3671
|
+
const title = accent.charAt(0).toUpperCase() + accent.slice(1);
|
|
3672
|
+
return /* @__PURE__ */ jsx38(
|
|
3673
|
+
"button",
|
|
3674
|
+
{
|
|
3675
|
+
type: "button",
|
|
3676
|
+
className: accent === value ? "is-active" : void 0,
|
|
3677
|
+
style: accentSwatchStyle(accent),
|
|
3678
|
+
"aria-pressed": accent === value,
|
|
3679
|
+
"aria-label": `${title} accent`,
|
|
3680
|
+
title,
|
|
3681
|
+
onClick: () => onChange(accent)
|
|
3682
|
+
},
|
|
3683
|
+
accent
|
|
3684
|
+
);
|
|
3685
|
+
})
|
|
3686
|
+
}
|
|
3687
|
+
);
|
|
3688
|
+
});
|
|
3689
|
+
|
|
3649
3690
|
// src/index.ts
|
|
3650
3691
|
var PAGE_SIZES = KIT_PAGE_SIZES;
|
|
3651
3692
|
var DEFAULT_PAGE_SIZE3 = KIT_DEFAULT_PAGE_SIZE;
|
|
3652
3693
|
export {
|
|
3694
|
+
AccentPicker,
|
|
3653
3695
|
AppShell,
|
|
3654
3696
|
BackLink,
|
|
3655
3697
|
Badge,
|
package/src/components/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { calloutIcons } from '../logic/callout.js';
|
|
2
|
+
import { ACCENTS, accentSwatchStyle } from '../logic/accents.js';
|
|
2
3
|
export { calloutIcons } from '../logic/callout.js';
|
|
3
4
|
// apliteni-ui component factories — each returns an HTML string, matching the
|
|
4
5
|
// viz/ server-render idiom so the portal can adopt them with no framework.
|
|
@@ -99,25 +100,16 @@ export function segmented({ options = [], active = 0, size, block, name = 'seg',
|
|
|
99
100
|
}
|
|
100
101
|
|
|
101
102
|
// ---- Accent picker -------------------------------------------------------
|
|
102
|
-
//
|
|
103
|
-
//
|
|
104
|
-
// land on --purple-light; Nebula's is its own --accent since #157, so it walks
|
|
105
|
-
// on to --purple-mid. site/chrome.mjs and site/index.html hand-keep the same
|
|
106
|
-
// four strings and must change with these. Held by stories/accent-swatch.test.js,
|
|
107
|
-
// which derives both sides rather than restating them. See issue #190.
|
|
108
|
-
const ACCENT_SWATCH = {
|
|
109
|
-
default: 'linear-gradient(135deg,#bd8cff,#b479ff)',
|
|
110
|
-
phoenix: 'linear-gradient(135deg,#ff8a5c,#ff6a3d)',
|
|
111
|
-
ocean: 'linear-gradient(135deg,#5ab0ff,#3b9dff)',
|
|
112
|
-
emerald: 'linear-gradient(135deg,#3ad9a0,#16c98a)',
|
|
113
|
-
};
|
|
103
|
+
// The accent list and every swatch's paints live in ../logic/accents.js, which
|
|
104
|
+
// the React picker reads too, so neither copy can drift from the other.
|
|
114
105
|
// Swatches have no text and no glyph at all — the aria-label is the whole
|
|
115
106
|
// accessible name, and aria-pressed carries which one is on.
|
|
116
|
-
export function accentPicker({ active = 'default', options =
|
|
107
|
+
export function accentPicker({ active = 'default', options = ACCENTS } = {}) {
|
|
117
108
|
const title = (o) => o.charAt(0).toUpperCase() + o.slice(1);
|
|
109
|
+
const style = (o) => Object.entries(accentSwatchStyle(o)).map(([k, v]) => `${k}:${v}`).join(';');
|
|
118
110
|
return `<div class="ui-accent-picker" data-accent-group role="group" aria-label="Accent">${options.map((o) =>
|
|
119
111
|
`<button type="button" data-accent-pick="${esc(o)}"${o === active ? ' class="is-active"' : ''}`
|
|
120
|
-
+ ` style="
|
|
112
|
+
+ ` style="${style(o)}" aria-pressed="${o === active ? 'true' : 'false'}"`
|
|
121
113
|
+ ` aria-label="${esc(title(o))} accent" title="${esc(title(o))}"></button>`).join('')}</div>`;
|
|
122
114
|
}
|
|
123
115
|
|
package/src/components/topbar.js
CHANGED
|
@@ -119,7 +119,8 @@ export function applyTheme(t, root = document.documentElement) {
|
|
|
119
119
|
}
|
|
120
120
|
|
|
121
121
|
const ACCENT_KEY = 'apliteni-strategy-accent';
|
|
122
|
-
|
|
122
|
+
// One list for the pickers, this wiring and the React component.
|
|
123
|
+
export { ACCENTS } from '../logic/accents.js';
|
|
123
124
|
|
|
124
125
|
export function applyAccent(name, root = document.documentElement) {
|
|
125
126
|
if (!name || name === 'default') root.removeAttribute('data-accent');
|
package/src/index.d.ts
CHANGED
|
@@ -53,6 +53,10 @@ export declare function illo(name: string): string;
|
|
|
53
53
|
export * from './motion.js';
|
|
54
54
|
export declare const illoNames: string[];
|
|
55
55
|
|
|
56
|
+
// The custom properties one accent swatch button carries. ACCENTS is declared
|
|
57
|
+
// with the topbar wiring that re-exports it.
|
|
58
|
+
export declare function accentSwatchStyle(accent: string): Record<string, string>;
|
|
59
|
+
|
|
56
60
|
// Vanilla factories accept their existing option bags and return HTML.
|
|
57
61
|
export declare function accentPicker(opts?: Record<string, unknown>): string;
|
|
58
62
|
export declare function accountMenu(opts?: Record<string, unknown>): string;
|
|
@@ -96,7 +100,8 @@ export declare function themeName(theme: string): string;
|
|
|
96
100
|
export declare function themeToggle(theme?: string): string;
|
|
97
101
|
export declare function versionSwitcher(versions?: { label: string; meta?: string; badge?: string }[], activeIdx?: number): string;
|
|
98
102
|
|
|
99
|
-
|
|
103
|
+
// A tuple, so React can derive its Accent union from it.
|
|
104
|
+
export declare const ACCENTS: readonly ['default', 'phoenix', 'ocean', 'emerald'];
|
|
100
105
|
export declare const ACCOUNT_NAV: { id: string; icon: string; label: string }[];
|
|
101
106
|
export declare const RAIL_COOKIE: 'apliteni-ui-rail';
|
|
102
107
|
export declare const STAT_TONES: string[];
|
package/src/index.js
CHANGED
|
@@ -34,3 +34,4 @@ export { filterChipText, filterChipName, filterChipUnset } from './logic/filter-
|
|
|
34
34
|
export { PAGE_SIZES, DEFAULT_PAGE_SIZE } from './logic/pagination.js';
|
|
35
35
|
export { calloutIcons } from './logic/callout.js';
|
|
36
36
|
export { formatNumericValue, formatDeltaValue } from './logic/table-values.js';
|
|
37
|
+
export { accentSwatchStyle } from './logic/accents.js';
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// The accents the kit ships, and the paints one accent swatch needs.
|
|
2
|
+
//
|
|
3
|
+
// Every copy of the picker reads this module, so there is one list and one set of
|
|
4
|
+
// paints rather than a copy per renderer. src/components/index.js and
|
|
5
|
+
// react/src/AccentPicker.tsx call accentSwatchStyle(); site/chrome.mjs and
|
|
6
|
+
// site/index.html still hand-keep the same four gradients. Held by
|
|
7
|
+
// stories/accent-swatch.test.js, which derives both sides out of src/tokens/.
|
|
8
|
+
// why: docs/specification.md#react-accent-picker. See issues #190 and #429.
|
|
9
|
+
export const ACCENTS = ['default', 'phoenix', 'ocean', 'emerald'];
|
|
10
|
+
|
|
11
|
+
// Per accent, the gradient's two stops — each the value src/tokens/ declares for
|
|
12
|
+
// that accent. The swatch gate reads the tokens and this table apart and
|
|
13
|
+
// compares them.
|
|
14
|
+
const PAINTS = {
|
|
15
|
+
default: { from: '#bd8cff', to: '#b479ff' },
|
|
16
|
+
phoenix: { from: '#ff8a5c', to: '#ff6a3d' },
|
|
17
|
+
ocean: { from: '#5ab0ff', to: '#3b9dff' },
|
|
18
|
+
emerald: { from: '#3ad9a0', to: '#16c98a' },
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* The custom properties one swatch button carries, as property → value.
|
|
23
|
+
*
|
|
24
|
+
* An accent with no entry here gets `--swatch: transparent`, which is what it
|
|
25
|
+
* had before this module existed: the strip shows an empty circle you can still
|
|
26
|
+
* press, and the swatch gate reports it by name. Selected, that circle wears the
|
|
27
|
+
* same near-black tick, which is ink for a fill rather than for the surface
|
|
28
|
+
* showing through it — a cost that belongs to the missing paints, not the mark.
|
|
29
|
+
* Painting the circle as some other accent would be worse.
|
|
30
|
+
*/
|
|
31
|
+
export function accentSwatchStyle(accent) {
|
|
32
|
+
const paint = PAINTS[accent];
|
|
33
|
+
if (!paint) return { '--swatch': 'transparent' };
|
|
34
|
+
return { '--swatch': `linear-gradient(135deg,${paint.from},${paint.to})` };
|
|
35
|
+
}
|
package/src/styles/segmented.css
CHANGED
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
.ui-seg--block { display: flex; align-self: stretch; justify-self: stretch; }
|
|
55
55
|
.ui-seg--block button { flex: 1; }
|
|
56
56
|
|
|
57
|
-
/* Accent picker — round colour swatches,
|
|
57
|
+
/* Accent picker — round colour swatches, the selected one ticked */
|
|
58
58
|
.ui-accent-picker { display: inline-flex; gap: 10px; align-items: center; }
|
|
59
59
|
.ui-accent-picker button {
|
|
60
60
|
width: 26px;
|
|
@@ -63,13 +63,30 @@
|
|
|
63
63
|
border: 0;
|
|
64
64
|
padding: 0;
|
|
65
65
|
cursor: pointer;
|
|
66
|
+
position: relative;
|
|
66
67
|
background: var(--swatch, var(--accent));
|
|
67
68
|
box-shadow: 0 0 0 2px var(--surface), 0 0 0 2px var(--surface);
|
|
68
69
|
transition: transform var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
|
|
69
70
|
}
|
|
70
71
|
.ui-accent-picker button:hover { transform: scale(1.08); }
|
|
71
|
-
|
|
72
|
-
|
|
72
|
+
/* Selected is a tick inside the circle, not a second ring around it: one element
|
|
73
|
+
* carries one accent signal, and on a focusable control that signal is the kit's
|
|
74
|
+
* focus ring. The mark is the one .ui-check draws for a checked box, at the same
|
|
75
|
+
* 2px stroke, in --signal-contrast — the circle wears the accent's dark ramp in
|
|
76
|
+
* both themes, so its ink is the one for a fill, not the --accent-contrast that
|
|
77
|
+
* pairs with --accent-strong. Held by stories/accent-mark.test.js.
|
|
78
|
+
* why: docs/specification.md#react-accent-picker */
|
|
79
|
+
.ui-accent-picker button.is-active::after {
|
|
80
|
+
content: "";
|
|
81
|
+
position: absolute;
|
|
82
|
+
left: 50%;
|
|
83
|
+
/* Lifted 2px: turning the box leaves the drawn corner below its middle. */
|
|
84
|
+
top: calc(50% - 2px);
|
|
85
|
+
width: 6px;
|
|
86
|
+
height: 11px;
|
|
87
|
+
border: solid var(--signal-contrast);
|
|
88
|
+
border-width: 0 2px 2px 0;
|
|
89
|
+
transform: translate(-50%, -50%) rotate(45deg); /* motion: still — the turn is the tick's shape, not travel, and the mark lands with the press that asked for it. Nothing else on the swatch changes with selection, so there is no paint for it to arrive with. */
|
|
73
90
|
}
|
|
74
91
|
.ui-accent-picker button:focus-visible { outline: 2px solid transparent; box-shadow: var(--ring); }
|
|
75
92
|
|