Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
202 changes: 101 additions & 101 deletions locale/da/texts.po

Large diffs are not rendered by default.

205 changes: 104 additions & 101 deletions locale/pt-br/texts.po

Large diffs are not rendered by default.

196 changes: 98 additions & 98 deletions locale/ru-ru/texts.po

Large diffs are not rendered by default.

204 changes: 102 additions & 102 deletions locale/texts.pot

Large diffs are not rendered by default.

43 changes: 43 additions & 0 deletions src/components/Radio/RadioButton.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* Copyright (c) Hathor Labs and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

import React from 'react';
import { View, StyleSheet } from 'react-native';
import { COLORS } from '../../styles/themes';

/**
* A single radio circle: outer ring plus an inner dot when selected.
*
* @param {Object} props
* @param {boolean} props.selected - If true, the radio is selected.
* @param {boolean} [props.disabled] - If true, the radio is disabled.
*/
export default function RadioButton({ selected, disabled = false }) {
const selectedColor = disabled ? COLORS.borderColorDark : COLORS.primary;
const borderColor = selected ? selectedColor : COLORS.borderColorDark;
return (
<View style={[styles.outer, { borderColor }]}>
{selected && <View style={[styles.inner, { backgroundColor: selectedColor }]} />}
</View>
);
}

const styles = StyleSheet.create({
outer: {
width: 24,
height: 24,
borderRadius: 12,
borderWidth: 2,
justifyContent: 'center',
alignItems: 'center',
},
inner: {
width: 12,
height: 12,
borderRadius: 6,
},
});
63 changes: 63 additions & 0 deletions src/components/Radio/RadioGroup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/**
* Copyright (c) Hathor Labs and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

import React from 'react';
import { View, StyleSheet } from 'react-native';
import { COLORS } from '../../styles/themes';
import RadioOption from './RadioOption';

/**
* A bordered card grouping radio options, separated by dividers. Controlled:
* the caller owns the selected `value` and receives it back via `onChange`.
*
* @param {Object} props
* @param {string|number} props.value - The currently selected option value.
* @param {Function} props.onChange - Called with an option's `value` on press.
* @param {Array<{
* value: string|number, title: string, description?: string, hint?: string,
* badge?: string, disabled?: boolean
* }>} props.options
*/
export default function RadioGroup({ value, onChange, options }) {
return (
<View accessibilityRole='radiogroup' style={styles.card}>
{options.map((option, index) => (
<React.Fragment key={String(option.value)}>
{index > 0 && <View style={styles.divider} />}
<RadioOption
selected={value === option.value}
onPress={() => {
// Deliberately redundant with the touchable's `disabled`: keeps
// the guard in JS rather than RN's touch-responder layer.
if (!option.disabled) onChange(option.value);
}}
disabled={option.disabled}
title={option.title}
badge={option.badge}
description={option.description}
hint={option.hint}
/>
</React.Fragment>
))}
</View>
);
}

const styles = StyleSheet.create({
card: {
borderWidth: 1,
borderColor: COLORS.borderColor,
borderRadius: 16,
paddingHorizontal: 16,
paddingVertical: 24,
},
divider: {
height: 1,
backgroundColor: COLORS.borderColor,
marginVertical: 24,
},
});
114 changes: 114 additions & 0 deletions src/components/Radio/RadioOption.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/**
* Copyright (c) Hathor Labs and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

import React from 'react';
import {
View,
Text,
StyleSheet,
TouchableOpacity,
} from 'react-native';
import { COLORS } from '../../styles/themes';
import RadioButton from './RadioButton';

/**
* A selectable row: a radio circle beside a title (with an optional badge),
* an optional description, and an optional muted italic hint.
*
* @param {Object} props
* @param {boolean} props.selected - If true, the option is selected.
* @param {Function} props.onPress
* @param {boolean} [props.disabled] - If true, the option is disabled.
* @param {string} props.title
* @param {string} [props.badge] - Pill text shown at the right of the title row.
* @param {string} [props.description]
* @param {string} [props.hint] - Muted italic line below the description.
*/
export default function RadioOption({
selected,
onPress,
disabled = false,
title,
badge,
description,
hint,
}) {
return (
<TouchableOpacity
Comment thread
tuliomir marked this conversation as resolved.
accessibilityRole='radio'
accessibilityState={{ checked: selected, disabled }}
activeOpacity={disabled ? 1 : 0.7}
onPress={onPress}
disabled={disabled}
style={styles.option}
>
<RadioButton selected={selected} disabled={disabled} />
{/* Fade the block, not each element, so the text keeps its hierarchy. */}
<View style={[styles.textWrapper, disabled && styles.textWrapperDisabled]}>
<View style={styles.titleRow}>
<Text style={styles.title}>{title}</Text>
{badge != null && (
<View style={styles.badge}>
<Text style={styles.badgeText}>{badge}</Text>
</View>
)}
</View>
{description != null && (
<Text style={styles.description}>{description}</Text>
)}
{hint != null && <Text style={styles.hint}>{hint}</Text>}
</View>
</TouchableOpacity>
);
}

const styles = StyleSheet.create({
option: {
flexDirection: 'row',
alignItems: 'flex-start',
},
textWrapper: {
flex: 1,
marginLeft: 16,
},
textWrapperDisabled: {
opacity: 0.5,
},
titleRow: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
},
title: {
fontSize: 16,
fontWeight: '600',
color: COLORS.black,
},
badge: {
backgroundColor: COLORS.lowContrastDetail,
borderRadius: 12,
paddingHorizontal: 10,
paddingVertical: 2,
},
badgeText: {
fontSize: 12,
color: COLORS.darkContrastDetail,
},
description: {
marginTop: 4,
fontSize: 12,
lineHeight: 20,
color: COLORS.midContrastDetail,
},
hint: {
marginTop: 4,
fontSize: 12,
lineHeight: 20,
fontStyle: 'italic',
color: COLORS.darkContrastDetail,
},
});
8 changes: 8 additions & 0 deletions src/components/Radio/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/**
* Copyright (c) Hathor Labs and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

export { default as RadioGroup } from './RadioGroup';
Loading
Loading