العناصر
ColorPicker
يحمل منتقي اللون لونًا واحدًا، وتعرضه الأجزاء الموجودة بداخله وتغيّره: ColorArea للتشبع والسطوع، وColorSlider لأي قناة من RGB أو HSL أو HSB أو OKLCH وللألفا، وColorField تأخذ اللون كنص أو قناة واحدة كرقم، وColorSwatch للألوان المعدّة مسبقًا، وColorEyeDropper يلتقط لونًا من أي مكان على الشاشة. ينسّق التطبيق الأجزاء بعناصره الخاصة فيما بينها (صف لكل قناة مع حرفها، والفضاء الذي يُختار بـTabs، والمنتقي داخل Popover)، ويتولى تنسيق كلٍّ منها: ترسم الأجزاء ألوان القنوات، أما كل حجم ونصف قطر وحدّ وظل فيعود إلى التطبيق.
import { mount, signal, Text, View } from "nsh";
import { type ColorChannel, ColorArea, ColorEyeDropper, ColorField, ColorPicker, ColorSlider, type ColorSpace, ColorSwatch } from "nsh/base";
import { desktop, field, Icon, Log, Segmented, Split, ui } from "./palette";
// `ColorPicker` holds the color; its parts, laid out and styled here, read
// and change it: the saturation and brightness area, the hue and alpha
// sliders, a row per channel of the space picked (its slider and its
// number), the color typed in any CSS form, the browser's eyedropper where
// it has one, and a palette of swatches.
const thumb = "rounded-full border-2 border-white";
const thumbStyle = { boxShadow: "0 0 0 1px rgba(0,0,0,0.25), 0 1px 3px rgba(0,0,0,0.3)" };
const spaces = ["rgb", "hsl", "hsb", "oklch"] as const;
const channels: Record<ColorSpace, [ColorChannel, string][]> = {
rgb: [["red", "R"], ["green", "G"], ["blue", "B"]],
hsl: [["hue", "H"], ["saturation", "S"], ["lightness", "L"]],
hsb: [["hue", "H"], ["saturation", "S"], ["brightness", "B"]],
oklch: [["lightness", "L"], ["chroma", "C"], ["hue", "H"]],
};
const palette = ["#ef4444", "#f97316", "#eab308", "#22c55e", "#06b6d4", "#3b82f6", "#8b5cf6", "#ec4899", "#0f172a80"];
/** A track `h` points high, half a thumb free at each end for the thumb. */
const track = (h: number) => ({
class: `h-[${h + 8}px] justify-center px-[${(h + 6) / 2}px]`,
trackClass: `h-[${h}px] rounded-full`,
thumbClass: `w-[${h + 6}px] h-[${h + 6}px] ${thumb}`,
thumbStyle,
fillThumb: true,
});
function App() {
const color = signal("#3b82f6ff");
const text = signal("#3b82f6");
const space = signal<ColorSpace>("oklch");
const events = signal<string[]>([]);
return (
<View style={{ flex: 1, backgroundColor: ui().page, padding: 20, paddingTop: 24, gap: 14 }}>
<Text style={{ fontSize: 22, fontWeight: "700", color: ui().text }}>color picker</Text>
<Text style={{ color: ui().muted }}>
{desktop ? "Drag the area or a slider, type a color, or pick a swatch" : "Drag the area or a slider, or tap a swatch"}
</Text>
<Split
gap={14}
inspector={
<Log title="onChangeEnd({ value, formatted })" lines={events()} minHeight={92} />
}
>
<View style={{ ...ui().card, borderRadius: 16, padding: 16 }}>
<ColorPicker
value={color()}
onChange={({ value, formatted }) => {
color.set(value);
text.set(formatted);
}}
onChangeEnd={({ formatted }) => events.set([formatted, ...events()].slice(0, 5))}
style={{ gap: 12 }}
>
<ColorArea
accessibilityLabel="Saturation and brightness"
style={{ height: desktop ? 160 : 140 }}
panelClass="rounded-lg"
thumbClass={`w-[18px] h-[18px] ${thumb}`}
thumbStyle={thumbStyle}
fillThumb
/>
<View style={{ flexDirection: "row", alignItems: "center", gap: 12 }}>
<ColorSwatch accessibilityLabel="Current color" style={{ width: 36, height: 36, borderRadius: 18 }} checkerboardColor="#d4d4d8" />
<View style={{ flex: 1, gap: 8 }}>
<ColorSlider colorSpace="hsb" channel="hue" accessibilityLabel="Hue" {...track(12)} />
<ColorSlider channel="alpha" accessibilityLabel="Alpha" checkerboardColor="#d4d4d8" {...track(12)} />
</View>
</View>
<Text style={{ fontSize: 13, color: ui().muted, fontVariant: ["tabular-nums"] }}>{text()}</Text>
<Segmented options={spaces} value={space()} onChange={(next) => space.set(next)} />
{() =>
channels[space()].map(([channel, letter]) => (
<View style={{ flexDirection: "row", alignItems: "center", gap: 10 }}>
<Text style={{ width: 14, fontSize: 13, color: ui().muted }}>{letter}</Text>
<ColorSlider colorSpace={space()} channel={channel} accessibilityLabel={`${space()} ${channel}`} style={{ flex: 1 }} {...track(10)} />
<ColorField
colorSpace={space()}
channel={channel}
accessibilityLabel={`${space()} ${channel} value`}
{...field({ style: { width: 64, textAlign: "right" } })}
/>
</View>
))
}
<View style={{ flexDirection: "row", alignItems: "center", gap: 8 }}>
<ColorField
accessibilityLabel="Color"
placeholder="#rrggbb, rgb(), hsl(), oklch() or a name"
{...field({ style: { flex: 1 } })}
/>
<ColorEyeDropper
accessibilityLabel="Pick a color from the screen"
class="disabled:hidden w-9 h-9 items-center justify-center rounded-md border border-border active:opacity-70"
>
<Icon name="pipette" size={16} tint={ui().text} />
</ColorEyeDropper>
</View>
<View style={{ flexDirection: "row", flexWrap: "wrap", gap: 8 }}>
{palette.map((c) => (
<ColorSwatch
color={c}
style={{ width: 24, height: 24, borderRadius: 6 }}
selectedStyle={{ borderWidth: 2, borderColor: ui().text }}
checkerboardColor="#d4d4d8"
checkerboardSize={6}
/>
))}
</View>
</ColorPicker>
</View>
</Split>
</View>
);
}
mount(App);use nsh_base::{
ColorChannel, ColorPickerEvent, ColorSpace, color_area, color_field, color_picker,
color_slider, color_swatch, theme,
};
use nsh_core::prelude::*;
fn primary(color: Signal<Hsla>) -> impl IntoElement {
// A channel of OKLCH: its letter, its slider, its number.
let channel = move |channel: ColorChannel, letter: &'static str| {
view()
.flex_row()
.items_center()
.gap_2()
.child(text(letter).w(px(14.0)).text_sm().text_color(move || theme().muted_foreground))
.child(
color_slider()
.color_space(ColorSpace::Oklch)
.channel(channel)
.accessibility_label(letter)
.flex_1()
.h(px(18.0))
.justify_center()
.px(px(8.0))
.track_style(|s| s.h(px(10.0)).rounded_full())
.thumb_style(|s| s.size(px(16.0)).rounded_full().border_2().border_color(white()))
.fill_thumb(true),
)
.child(
color_field()
.color_space(ColorSpace::Oklch)
.channel(channel)
.accessibility_label(letter)
.w(px(64.0))
.h(px(28.0))
.px_2()
.rounded_md()
.border_1()
.border_color(move || theme().border)
.text_sm(),
)
};
color_picker()
.value(move || Some(color.get()))
.on_change(move |e: &ColorPickerEvent| {
if let ColorPickerEvent::Change(value, _) = e {
color.set(*value);
}
})
.gap_3()
.child(
color_area()
.accessibility_label("Saturation and brightness")
.h(px(160.0))
.panel_style(|s| s.rounded_lg())
.thumb_style(|s| s.size(px(18.0)).rounded_full().border_2().border_color(white()))
.fill_thumb(true),
)
.child(channel(ColorChannel::Lightness, "L"))
.child(channel(ColorChannel::Chroma, "C"))
.child(channel(ColorChannel::Hue, "H"))
.child(color_swatch().size(px(28.0)).rounded_md())
}import { mount, signal, Text, View } from "nsh";
import { type ColorChannel, ColorArea, ColorField, ColorPicker, ColorSlider, ColorSwatch } from "nsh/base";
const thumb = "rounded-full border-2 border-white";
function Channel(props: { channel: ColorChannel; letter: string }) {
return (
<View class="flex-row items-center gap-2">
<Text class="w-[14px] text-sm text-muted-foreground">{props.letter}</Text>
<ColorSlider
colorSpace="oklch"
channel={props.channel}
accessibilityLabel={props.letter}
class="flex-1 h-[18px] justify-center px-2"
trackClass="h-[10px] rounded-full"
thumbClass={`size-4 ${thumb}`}
fillThumb
/>
<ColorField
colorSpace="oklch"
channel={props.channel}
accessibilityLabel={props.letter}
class="w-16 h-7 px-2 rounded-md border border-border text-sm text-right"
/>
</View>
);
}
function App() {
const primary = signal("oklch(54.6% 0.215 262.9)");
return (
<ColorPicker value={primary()} format="oklch" onChange={({ formatted }) => primary.set(formatted)} class="gap-3">
<ColorArea accessibilityLabel="Saturation and brightness" class="h-40" panelClass="rounded-lg" thumbClass={`size-[18px] ${thumb}`} fillThumb />
<Channel channel="lightness" letter="L" />
<Channel channel="chroma" letter="C" />
<Channel channel="hue" letter="H" />
<View class="flex-row items-center gap-2">
<ColorSwatch class="size-7 rounded-md" />
<Text class="font-mono text-sm">{`--primary: ${primary()}`}</Text>
</View>
</ColorPicker>
);
}
mount(App);ColorPicker وColorArea وColorSlider وColorField وColorSwatch وColorEyeDropper تأتي من nsh/base، وهي حزمة nsh-base في Rust. في Rust، تُنشئها الدالة color_picker() ودوال أجزائها باستخدام دالة ضبط لكل خاصية (.channel(..)، .thumb_style(..))، ودالة مستمع لكل حدث (.on_change(..))، ودوال التنسيق المُنمَّطة؛ واللون هو Hsla، والفضاءات والقنوات والصيغ هي ColorSpace وColorChannel وColorFormat.
#القيمة
اللون هو لون CSS: hex (#3b82f6، #3b82f680 مع ألفاه)، أو rgb() أو hsl() أو hsb() أو oklch() أو اسم CSS؛ وفي Rust هو Hsla. يملكه التطبيق باستخدام value ويضبط القيمة التي يبلّغ عنها onChange، كما في كل عنصر تحكم في nsh/base؛ أو يترك اللون للمنتقي باستخدام defaultValue ومع ذلك يسمع التغييرات.
- يبلّغ
onChange({ value, formatted })عن كل لون يطلبه المستخدم: عند كل خطوة من سحب على المنطقة أو شريط التمرير، ولكل ضغطة مفتاح، ولرقم حقل أثناء كتابته، وعند الضغط على عيّنة.valueهو اللون، وformattedهو اللون نفسه مكتوبًا بالصيغة التي يحددهاformat("hex"،"rgb"،"hsl"،"hsb"أو"oklch")، جاهزًا للحفظ أو للضبط كـ token. - يبلّغ
onChangeEnd({ value, formatted })عن اللون الذي انتهى عنده التغيير، مرة واحدة: عند رفع المؤشر، وبعد كل مفتاح، وعند مغادرة حقل أو إرساله، وعند الضغط على عيّنة. - يحتفظ المنتقي باللون في كل فضاء كما ضبطه المستخدم. يحتفظ الرمادي بصبغته وتشبعه، فيبقى شريط الصبغة حيث تركه المستخدم؛ واللون المحرَّر في OKLCH يحتفظ بإضاءته وكرومته وصبغته كما كُتبت، حتى فيما يتجاوز ما يعرضه sRGB (اللون المبلَّغ عنه هو الأقرب إلى ما يعرضه sRGB، و
formattedفي"oklch"يحتفظ بالقنوات). - أي
valueيضبطه التطبيق ولم يبلّغ عنه المنتقي يستبدل اللون في كل الفضاءات.
#الفضاءات والقنوات
colorSpace | القنوات (channel) | المدى |
|---|---|---|
"rgb" | "red"، "green"، "blue" | من 0 إلى 255 |
"hsl" | "hue"، "saturation"، "lightness" | الصبغة من 0 إلى 360، والبقية من 0 إلى 100 |
"hsb" | "hue"، "saturation"، "brightness" | الصبغة من 0 إلى 360، والبقية من 0 إلى 100 |
"oklch" | "lightness"، "chroma"، "hue" | الإضاءة من 0 إلى 100 (بخطوة 0.1)، والكروما من 0 إلى 0.4 (بخطوة 0.001)، والصبغة من 0 إلى 360 (بخطوة 0.1) |
| أي فضاء | "alpha" | من 0 إلى 100 |
يرسم مسار الشريط ألوان قناته مع تثبيت القنوات الأخرى، فيُظهر إلى أين تقود كل قيمة. أما القناة التي لا يملكها الفضاء فتُستبدل بأولى قنوات الفضاء (ويُصدر تحذير بذلك).
#الخصائص
#ColorPicker
| الخاصية | Rust | النوع | الافتراضي | الوصف |
|---|---|---|---|---|
value | .value(..) | string | لا شيء | اللون (متحكَّم به). يضبط التطبيق القيمة التي يبلّغ عنها onChange. |
defaultValue | .default_value(..) | string | "#000000" | اللون الأولي ما دام value غير مضبوط؛ ويحتفظ المنتقي حينئذٍ بلونه الخاص. |
format | .format(..) | "hex" | "rgb" | "hsl" | "hsb" | "oklch" | "hex" | الكيفية التي يكتب بها formatted اللون. |
disabled | .disabled(..) | boolean | false | لا تغييرات من أي جزء؛ وتُطبَّق فئات disabled: على المنتقي وأجزائه. |
children | .child(..) | JSX.Element | لا شيء | الأجزاء وعناصر التطبيق التي بينها. |
class، style | دوال التنسيق | string، StyleProp<ViewStyle> | لا شيء | المنتقي نفسه: العمود (أو الصف) المحيط بأجزائه. |
#ColorArea
| الخاصية | Rust | النوع | الافتراضي | الوصف |
|---|---|---|---|---|
panelClass، panelStyle | .panel_style(|s| ..) | string، StyleProp<ViewStyle> | لا شيء | اللوحة التي تملأ المنطقة: ألوان الصبغة، والتشبع من اليسار إلى اليمين (ومن اليمين إلى اليسار في التخطيط من اليمين إلى اليسار)، والسطوع من الأسفل إلى الأعلى، مقصوصة عند زواياها. |
thumbClass، thumbStyle | .thumb_style(|s| ..) | string، StyleProp<ViewStyle> | لا شيء | المقبض، متمركز على اللون. |
fillThumb | .fill_thumb(..) | boolean | false | خلفية المقبض هي اللون. |
disabled | .disabled(..) | boolean | false | لا تغييرات بالمؤشر أو لوحة المفاتيح أو قارئ الشاشة. |
accessibilityLabel | .accessibility_label(..) | string | لا شيء | ما تنطق به قارئات الشاشة للمقبض. |
class، style | دوال التنسيق | string، StyleProp<ViewStyle> | لا شيء | المنطقة: حجمها من اختيار التطبيق. |
#ColorSlider
| الخاصية | Rust | النوع | الافتراضي | الوصف |
|---|---|---|---|---|
colorSpace | .color_space(..) | "rgb" | "hsl" | "hsb" | "oklch" | "hsb" | فضاء القناة. |
channel | .channel(..) | ColorChannel | "hue" | القناة التي يغيّرها: إحدى قنوات الفضاء، أو "alpha". |
axis | .axis(..) | "horizontal" | "vertical" | "horizontal" | اتجاه المسار: أصغر قيمة عند البداية (اليسار، واليمين في التخطيط من اليمين إلى اليسار)، أو عند الأسفل. تُقرأ عند إنشاء الشريط. |
trackClass، trackStyle | .track_style(|s| ..) | string، StyleProp<ViewStyle> | لا شيء | المسار: ألوان القناة على امتداده، مقصوصة عند زواياها؛ ويوضع المقبض عليه. |
thumbClass، thumbStyle | .thumb_style(|s| ..) | string، StyleProp<ViewStyle> | لا شيء | المقبض، متمركز على القيمة. |
fillThumb | .fill_thumb(..) | boolean | false | خلفية المقبض هي اللون (مع ألفاه في شريط الألفا). |
checkerboardColor | .checkerboard_color(..) | string | لا شيء | لون رقعة شطرنج تحت المسار، تظهر من خلال ألوان شريط الألفا. |
checkerboardSize | .checkerboard_size(..) | number | 4 | ضلع مربعات رقعة الشطرنج. |
disabled | .disabled(..) | boolean | false | لا تغييرات بالمؤشر أو لوحة المفاتيح أو قارئ الشاشة. |
accessibilityLabel | .accessibility_label(..) | string | لا شيء | ما تنطق به قارئات الشاشة للمقبض. |
class، style | دوال التنسيق | string، StyleProp<ViewStyle> | لا شيء | الشريط: النطاق المحيط بالمسار الذي يستقبل الضغطات والسحب. |
#ColorField
| الخاصية | Rust | النوع | الافتراضي | الوصف |
|---|---|---|---|---|
channel | .channel(..) | ColorChannel | لا شيء | القناة التي يأخذها كرقم. وبدونها يأخذ الحقل اللون كاملًا كنص. |
colorSpace | .color_space(..) | ColorSpace | "hsb" | فضاء channel. |
format | .format(..) | ColorFormat | "hex" | الكيفية التي يكتب بها الحقل اللون كاملًا. ويقرأ أي صيغة CSS. |
placeholder | .placeholder(..) | string | لا شيء | يظهر ما دام الحقل فارغًا. |
disabled | .disabled(..) | boolean | false | لا كتابة. |
accessibilityLabel | .accessibility_label(..) | string | لا شيء | ما تنطق به قارئات الشاشة للحقل. |
class، style | دوال التنسيق | string، StyleProp<TextStyle> | لا شيء | الحقل، وهو مُدخل نصي. |
يغيّر حقل القناة اللون أثناء كتابة الرقم، مع تقييده بمدى القناة؛ أما حقل اللون كاملًا فيغيّره عند مغادرة الحقل أو إرساله، إذا كان النص يُقرأ كلونًا. ومغادرة الحقل تعيد كتابة قيمته بصيغته.
#ColorSwatch
| الخاصية | Rust | النوع | الافتراضي | الوصف |
|---|---|---|---|---|
color | .color(..) | string | لا شيء | اللون الذي تعرضه؛ والضغط عليها يختاره في المنتقي المحيط بها. وبدونه تعرض لون المنتقي نفسه: معاينة. |
selectedStyle | .selected_style(..) | StyleProp<ViewStyle> | لا شيء | التنسيق حين تكون بلون المنتقي، على هيئة فئات selected:. |
checkerboardColor | .checkerboard_color(..) | string | لا شيء | رقعة شطرنج تحت اللون الشفاف. |
checkerboardSize | .checkerboard_size(..) | number | 4 | ضلع مربعاتها. |
disabled | .disabled(..) | boolean | false | لا ضغطات. |
accessibilityLabel | .accessibility_label(..) | string | اللون بصيغة hex | ما تنطق به قارئات الشاشة. |
children | .child(..) | JSX.Element | لا شيء | محتوى فوق اللون: علامة صح على العيّنة المحددة (group-selected:). |
class، style | دوال التنسيق | string، StyleProp<ViewStyle> | لا شيء | العيّنة: حجمها وشكلها وحدّها؛ وتقصّ زواياها اللون. |
#ColorEyeDropper
| الخاصية | Rust | النوع | الافتراضي | الوصف |
|---|---|---|---|---|
disabled | .disabled(..) | boolean | false | لا ضغطات. ويكون معطّلًا أيضًا حيث لا تتوفر قطّارة ألوان في المنصة. |
accessibilityLabel | .accessibility_label(..) | string | لا شيء | ما تنطق به قارئات الشاشة. |
children | .child(..) | JSX.Element | لا شيء | محتواه: أيقونة التطبيق أو تسميته. |
class، style | دوال التنسيق | string، StyleProp<ViewStyle> | لا شيء | الزر. |
يعرض الضغط قطّارة الألوان الخاصة بالنظام: أداة أخذ العينات اللونية في AppKit على macOS، وEyeDropper في المتصفح على الويب (Chrome وEdge). يصبح اللون المختار لون المنتقي (onChange، ثم onChangeEnd)؛ ولا يختار Escape أي لون. وحيث لا تتوفر قطّارة في المنصة يكون الزر معطّلًا، ويخفيه disabled:hidden هناك.
#الأحداث
| الحدث | على | Rust | الحمولة | المتى |
|---|---|---|---|---|
onChange | ColorPicker | .on_change(|e: &ColorPickerEvent| ..) | ({ value: string, formatted: string }) | غيّر المستخدم اللون. |
onChangeEnd | ColorPicker | .on_change_end(|e: &ColorPickerEvent| ..) | ({ value: string, formatted: string }) | انتهى التغيير. مرة واحدة لكل تغيير. |
onPress | ColorSwatch | .on_press(|color: &Hsla| ..) | ({ color: string }) | ضُغطت العيّنة؛ ويعمل أيضًا منفردًا، كرقاقة في لوحة ألوان. |
onPick | ColorEyeDropper | .on_pick(|color: &Hsla| ..) | ({ color: string }) | اختار المستخدم لونًا من الشاشة؛ ويعمل أيضًا منفردًا. |
في Rust، يحمل ColorPickerEvent::Change(Hsla, SharedString) وColorPickerEvent::ChangeEnd(Hsla, SharedString) اللون ونصّه بصيغة formatted.
#الأجزاء
| الجزء | بداخل | يُنسَّق بـ |
|---|---|---|
ColorArea | المنتقي | class، style |
| لوحة المنطقة | المنطقة، تملؤها | panelClass، panelStyle |
| مقبض المنطقة | المنطقة، متمركز على اللون | thumbClass، thumbStyle |
ColorSlider | المنتقي | class، style |
| مسار الشريط | الشريط | trackClass، trackStyle |
| مقبض الشريط | الشريط، متمركز على القيمة على المسار | thumbClass، thumbStyle |
ColorField | المنتقي | class، style |
ColorSwatch | المنتقي، أو منفردة | class، style، selectedStyle |
ColorEyeDropper | المنتقي، أو منفردة | class، style |
يتمركز مقبض الشريط على طرفي المسار عند طرفي القناة. وحشوة على الشريط بمقدار نصف عرض المقبض (h-6 justify-center px-2.5 حول مسار h-3) تُبقي المقبض كاملًا داخل الشريط، حيث يستقبل الضغطات عند الطرفين. أما الحالات التي تعرضها الأجزاء فهي: active: للمقبض أثناء سحبه وfocus: عند وجود تركيز لوحة المفاتيح عليه، وselected: للعيّنة، وdisabled: لكل جزء.
#لوحة المفاتيح
على macOS والويب يكون كل مقبض نقطة توقف لتركيز لوحة المفاتيح (Tab):
| المفتاح | على الشريط | على المنطقة |
|---|---|---|
| السهم الأيمن، السهم الأعلى | خطوة واحدة للأعلى | الأيمن: تشبع أكثر؛ الأعلى: سطوع أكثر |
| السهم الأيسر، السهم الأسفل | خطوة واحدة للأسفل | الأيسر: تشبع أقل؛ الأسفل: سطوع أقل |
| Shift مع سهم | عشر خطوات | عشر خطوات |
| Page Up، Page Down | عشر خطوات | عشر خطوات من السطوع |
| Home، End | طرفا القناة |
في التخطيط من اليمين إلى اليسار يمتد الشريط الأفقي والمنطقة من اليمين، وتكون أصغر قيمة (أقل تشبع) عند الطرف الأيمن: السهم الأيسر خطوة للأعلى والسهم الأيمن خطوة للأسفل، والضغط أو السحب يختار القيمة تحت المؤشر كما هي مرسومة. أما الشريط العمودي فيُبقي السهم الأيمن والسهم الأعلى خطوةً للأعلى؛ ويُبقي السهمان الأعلى والأسفل على المنطقة السطوع.
تستجيب العيّنة لـ Space وReturn. يبلّغ كل مفتاح عن onChange ثم onChangeEnd؛ وتتكرر الأسهم أثناء الإبقاء عليها مضغوطة.
#إمكانية الوصول
- مقبض المنطقة ومقبض كل شريط عنصران قابلان للضبط (
"adjustable"، وهو slider في المتصفح) مع تسميتهما وقيمتهما ومداهما؛ وتؤدي أوامر الزيادة والنقصان في قارئات الشاشة إلى تحريكهما خطوة خطوة. - كل حقل هو حقل نصي مع تسميته؛ وكل عيّنة زر، محددة ما دامت لون المنتقي، وتُسمّى بلونها بصيغة hex ما لم يسمّها
accessibilityLabel. أما قطّارة الألوان فهي زر بتسمية من التطبيق. - أثناء التعطيل، تذكر قارئات الشاشة أن الأجزاء معتّمة، ولا تقبل أي إجراءات.
راجع إمكانية الوصول للاطلاع على التسميات والأدوار والإجراءات بوجه عام.
#ملاحظات المنصات
- ترسم كل منصة ما ينسّقه التطبيق؛ وألوان المسارات واللوحة هي تدرجات ترسمها المنصة. تُتابَع الضغطات والسحب في النواة، للفأرة أو القلم أو الإصبع، ويقتصر التمرير في عرض التمرير المحيط بالمنتقي على السحب الذي يبدأ في مكان آخر.
- يلتقط
ColorEyeDropperاللون بأداة أخذ العينات اللونية في AppKit على macOS وبـEyeDropperفي المتصفح على الويب؛ ويصل اللون بصيغة sRGB.