Skip to content

Commit

Permalink
feat: adds revealable-input component (#46)
Browse files Browse the repository at this point in the history
  • Loading branch information
lukicenturi authored Jul 12, 2023
1 parent 288285f commit 0a05ff6
Show file tree
Hide file tree
Showing 7 changed files with 161 additions and 7 deletions.
24 changes: 24 additions & 0 deletions example/src/views/HomeView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
RuiFooterStepper,
RuiIcon,
RuiProgress,
RuiRevealableTextField,
RuiStepper,
RuiTextField,
StepperState,
Expand Down Expand Up @@ -940,6 +941,15 @@ const progress = ref([
variant: 'indeterminate',
},
]);
const revealableTextFields = ref([
{ value: '', color: 'primary', variant: 'outlined' },
{ value: '', color: 'secondary', variant: 'outlined' },
{ value: '', color: 'error', variant: 'outlined' },
{ value: '', color: 'warning', variant: 'outlined' },
{ value: '', color: 'info', variant: 'outlined' },
{ value: '', color: 'success', variant: 'outlined' },
]);
</script>

<template>
Expand Down Expand Up @@ -1037,6 +1047,20 @@ const progress = ref([
/>
</div>
</div>

<div :class="css.section">
<h2 class="text-h4 mb-6" data-cy="text-fields">Revealable Text Fields</h2>
<div class="grid gap-4 grid-rows-2 grid-cols-3">
<rui-revealable-text-field
v-for="(field, i) in revealableTextFields"
:key="i"
v-model="field.value"
v-bind="field"
label="Password"
placeholder="Placeholder"
/>
</div>
</div>
</template>

<style lang="scss" module>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { type ComponentMountingOptions, mount } from '@vue/test-utils';
import { describe, expect, it } from 'vitest';
import RevealableTextField from '@/components/forms/revealable-text-field/RevealableTextField.vue';

const createWrapper = (
options?: ComponentMountingOptions<typeof RevealableTextField>
) =>
mount(RevealableTextField, { ...options, global: { stubs: ['rui-icon'] } });

describe('Forms/RevealableTextField', () => {
it('renders properly', () => {
const label = 'Password';
const wrapper = createWrapper({
props: {
label,
},
});
expect(wrapper.find('label').text()).toContain(label);
});

it('toggle the type', async () => {
const wrapper = createWrapper();

expect(wrapper.find('input').attributes().type).toBe('password');
expect(wrapper.find('rui-icon-stub').attributes().name).toBe(
'eye-off-line'
);

await wrapper.find('button').trigger('click');
expect(wrapper.find('input').attributes().type).toBe('text');
expect(wrapper.find('rui-icon-stub').attributes().name).toBe('eye-line');

await wrapper.find('button').trigger('click');
expect(wrapper.find('input').attributes().type).toBe('password');
expect(wrapper.find('rui-icon-stub').attributes().name).toBe(
'eye-off-line'
);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { type Meta, type StoryFn } from '@storybook/vue3';
import { contextColors } from '@/consts/colors';
import RevealableTextField from './RevealableTextField.vue';

const render: StoryFn<typeof RevealableTextField> = (_, { argTypes }) => ({
components: { RevealableTextField },
props: Object.keys(argTypes),
template: `<RevealableTextField v-bind="$props" />`,
});

const meta: Meta<typeof RevealableTextField> = {
title: 'Components/Forms/RevealableTextField',
component: RevealableTextField,
tags: ['autodocs'],
render,
argTypes: {
modelValue: { control: 'text' },
label: { control: 'text' },
placeholder: { control: 'text' },
hint: { control: 'text' },
appendIcon: { control: 'text' },
prependIcon: { control: 'text' },
errorMessages: { control: 'text' },
hideDetails: { control: 'boolean' },
dense: { control: 'boolean' },
variant: {
control: 'select',
options: ['default', 'filled', 'outlined'],
table: { category: 'State' },
},
disabled: { control: 'boolean', table: { category: 'State' } },
color: { control: 'select', options: contextColors },
},
parameters: {
docs: {
controls: { exclude: ['default'] },
},
},
};

export const Default = {
args: {
label: 'Password',
placeholder: 'Placeholder',
variant: 'outlined',
},
};

export default meta;
36 changes: 36 additions & 0 deletions src/components/forms/revealable-text-field/RevealableTextField.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<script setup lang="ts">
import { default as RuiTextField } from '@/components/forms/text-field/TextField.vue';
import { default as RuiButton } from '@/components/buttons/Button.vue';
import { default as RuiIcon } from '@/components/icons/Icon.vue';
const hidden: Ref<boolean> = ref(true);
const attrs = useAttrs();
const slots = useSlots();
</script>

<template>
<rui-text-field v-bind="attrs" :type="hidden ? 'password' : 'text'">
<template v-if="slots.prepend" #prepend>
<slot name="prepend" />
</template>
<template #append>
<div class="flex items-center">
<rui-button
variant="text"
icon
class="-mr-1 !p-2"
@click="hidden = !hidden"
>
<rui-icon
class="text-black/[.54] dark:text-white/[.56]"
size="20"
:name="hidden ? 'eye-off-line' : 'eye-line'"
/>
</rui-button>

<slot name="append" />
</div>
</template>
</rui-text-field>
</template>
2 changes: 1 addition & 1 deletion src/components/icons/Icon.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { type ContextColorsType } from '@/consts/colors';
const props = withDefaults(
defineProps<{
name: string;
size?: number;
size?: number | string;
color?: ContextColorsType;
}>(),
{
Expand Down
16 changes: 10 additions & 6 deletions src/composables/icons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,24 @@ import {
RiCheckboxFill,
RiCheckboxIndeterminateFill,
RiErrorWarningFill,
RiEyeLine,
RiEyeOffLine,
RiInformationFill,
} from '@/all-icons';

export const useIcons = createGlobalState(() => {
const requiredIcons: GeneratedIcon[] = [
RiCheckboxFill,
RiAlertFill,
RiArrowLeftSLine,
RiCheckLine,
RiCheckboxBlankCircleFill,
RiCheckboxBlankLine,
RiCheckboxCircleFill,
RiCheckboxFill,
RiCheckboxIndeterminateFill,
RiCheckboxBlankLine,
RiCheckboxBlankCircleFill,
RiCheckLine,
RiErrorWarningFill,
RiAlertFill,
RiArrowLeftSLine,
RiEyeLine,
RiEyeOffLine,
RiInformationFill,
];

Expand Down
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { default as RuiStepper } from '@/components/steppers/Stepper.vue';
import { default as RuiTextField } from '@/components/forms/text-field/TextField.vue';
import { default as RuiFooterStepper } from '@/components/steppers/FooterStepper.vue';
import { default as RuiProgress } from '@/components/progress/Progress.vue';
import { default as RuiRevealableTextField } from '@/components/forms/revealable-text-field/RevealableTextField.vue';
import { useRotkiTheme } from '@/composables/theme';
import { StepperState } from '@/types/stepper';
import type { InitThemeOptions } from '@/types/theme';
Expand All @@ -30,6 +31,7 @@ export {
RuiTextField,
RuiFooterStepper,
RuiProgress,
RuiRevealableTextField,
useRotkiTheme,
};

Expand Down

0 comments on commit 0a05ff6

Please sign in to comment.