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
6 changes: 5 additions & 1 deletion src/components/BccFormLabel/BccFormLabel.css
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
@layer components {
/* Label */
.bcc-form-label, .bcc-input-label {
@apply flex gap-2 justify-between items-end text-label-small text-primary;
}

/* Size */
.bcc-form-label-lg {
@apply text-label-base;
}

/* Optional */
.bcc-form-label-optional, .bcc-input-optional-label {
@apply text-caption font-normal text-tertiary truncate;
Expand Down
18 changes: 18 additions & 0 deletions src/components/BccFormLabel/BccFormLabel.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ export default {
for: {
description: "The normal HTML `for` attribute for the label",
},
size: {
options: ["base", "lg"],
control: { type: "radio" },
},
},
} as Meta<typeof BccFormLabel>;

Expand All @@ -35,6 +39,7 @@ const Template: StoryFn<typeof BccFormLabel> = (args) => ({
export const Example = Template.bind({});
Example.args = {
slotDefault: "Example label",
size: "base",
for: "",
showOptionalLabel: false,
optionalLabel: "Optional",
Expand All @@ -55,6 +60,19 @@ export const OptionalLabel: StoryFn<typeof BccFormLabel> = () => ({
`,
});

/**
* Set the `size` prop to control the size of the label
*/
export const Size: StoryFn<typeof BccFormLabel> = () => ({
components: { BccFormLabel },
template: `
<div class="flex flex-col space-y-4">
<BccFormLabel>base label</BccFormLabel>
<BccFormLabel size="lg">lg label</BccFormLabel>
</div>
`,
});

/**
* Use this label standalone with for example a radio group
*/
Expand Down
4 changes: 3 additions & 1 deletion src/components/BccFormLabel/BccFormLabel.vue
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
<script setup lang="ts">
type Props = {
size?: "base" | "lg";
for?: string;
showOptionalLabel?: boolean;
optionalLabel?: string;
};

const props = withDefaults(defineProps<Props>(), {
size: "base",
showOptionalLabel: false,
optionalLabel: "Optional",
});
</script>

<template>
<label class="bcc-form-label" :for="props.for">
<label class="bcc-form-label" :class="{ 'bcc-form-label-lg': size === 'lg' }" :for="props.for">
<span><slot /></span>
<span v-if="showOptionalLabel" class="bcc-form-label-optional">{{ optionalLabel }}</span>
</label>
Expand Down
15 changes: 15 additions & 0 deletions src/components/BccFormMessage/BccFormMessage.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
@layer components {
.bcc-form-message, .bcc-input-message {
@apply text-caption;
/* default state */
@apply text-secondary;
}

/* State */
.bcc-form-message-error, .bcc-input-message-error {
@apply text-danger;
}
.bcc-form-message-success, .bcc-input-message-success {
@apply text-success;
}
}
15 changes: 15 additions & 0 deletions src/components/BccFormMessage/BccFormMessage.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { describe, it, expect } from "vitest";

import { mount } from "@vue/test-utils";
import BccFormMessage from "./BccFormMessage.vue";

describe("BccFormMessage", () => {
it("renders a text from the default slot", () => {
const wrapper = mount(BccFormMessage, {
slots: { default: "Test message" },
});

expect(wrapper.text()).toBe("Test message");
expect(wrapper.html()).toMatchSnapshot();
});
});
77 changes: 77 additions & 0 deletions src/components/BccFormMessage/BccFormMessage.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import BccFormMessage from "./BccFormMessage.vue";

import type { Meta, StoryFn } from "@storybook/vue3";

/**
* A companion component used with for example the input to show a validation message
*/
export default {
title: "Forms/BccFormMessage",
component: BccFormMessage,
argTypes: {
state: {
description: "Style of the message",
options: ["default", "error", "success"],
control: { type: "radio" },
},
},
} as Meta<typeof BccFormMessage>;

/**
* Pass content to the default slot to render a message
*/
const Template: StoryFn<typeof BccFormMessage> = (args) => ({
components: { BccFormMessage },
setup() {
return { args };
},
template: `
<BccFormMessage v-bind="args">
<span v-if="args.slotDefault">
{{ args.slotDefault }}
</span>
<span v-else>
<strong>Well done!</strong> This username is valid
</span>
</BccFormMessage>
`,
});

export const Example = Template.bind({});
Example.args = {
slotDefault: "",
state: "success",
};
Example.parameters = {
docs: {
source: {
language: "html",
code: `
<BccFormMessage state="success">
<strong>Well done!</strong> This username is valid
</BccFormMessage>
`,
},
},
};

/**
* Set the `state` prop to control how the input is rendered. Set the `disabled` prop to disable the input
*/
export const State: StoryFn<typeof BccFormMessage> = () => ({
components: { BccFormMessage },
template: `
<div class="inline-flex flex-col space-y-4">
<BccFormMessage>
<strong>Example message</strong> to show with an input
</BccFormMessage>
<BccFormMessage state="error">
<strong>Example message</strong> to show with an input
</BccFormMessage>
<BccFormMessage state="success">
<strong>Example message</strong> to show with an input
</BccFormMessage>

</div>
`,
});
22 changes: 22 additions & 0 deletions src/components/BccFormMessage/BccFormMessage.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<script setup lang="ts">
type Props = {
state?: "default" | "error" | "success";
};

withDefaults(defineProps<Props>(), {
state: "default",
});
</script>

<template>
<span
class="bcc-form-message"
:class="{
'bcc-form-message-default': state === 'default',
'bcc-form-message-error': state === 'error',
'bcc-form-message-success': state === 'success',
}"
>
<slot />
</span>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`BccFormMessage > renders a text from the default slot 1`] = `"<span class=\\"bcc-form-message bcc-form-message-default\\">Test message</span>"`;
14 changes: 0 additions & 14 deletions src/components/BccInput/BccInput.css
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,6 @@
@apply border-success focus:outline-success;
}

/* Message */
.bcc-input-message {
@apply text-body-small;
}
.bcc-input-message-default {
@apply text-secondary;
}
.bcc-input-message-error {
@apply text-danger;
}
.bcc-input-message-success {
@apply text-success;
}

/* Icon */
.bcc-input-icon {
@apply h-4 w-4 text-secondary;
Expand Down
12 changes: 6 additions & 6 deletions src/components/BccInput/BccInput.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,12 @@ export const Size: StoryFn<typeof BccInput> = () => ({
},
template: `
<div class="inline-flex flex-col space-y-4">
<BccInput size="sm" value="sm" placeholder="Example placeholder" />
<BccInput size="sm" value="sm" placeholder="Example placeholder" :icon="SearchIcon" disabled />
<BccInput value="base" placeholder="Example placeholder" />
<BccInput value="base" placeholder="Example placeholder" :icon="SearchIcon" disabled />
<BccInput size="lg" value="lg" placeholder="Example placeholder" />
<BccInput size="lg" value="lg" placeholder="Example placeholder" :icon="SearchIcon" disabled />
<BccInput label="label for sm input" size="sm" value="sm" placeholder="Example placeholder" />
<BccInput label="label for sm input" size="sm" value="sm" placeholder="Example placeholder" :icon="SearchIcon" disabled />
<BccInput label="label for base input" value="base" placeholder="Example placeholder" />
<BccInput label="label for base input" value="base" placeholder="Example placeholder" :icon="SearchIcon" disabled />
<BccInput label="label for lg input" size="lg" value="lg" placeholder="Example placeholder" />
<BccInput label="label for lg input" size="lg" value="lg" placeholder="Example placeholder" :icon="SearchIcon" disabled />
</div>
`,
});
Expand Down
16 changes: 5 additions & 11 deletions src/components/BccInput/BccInput.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { useAttrsWithoutStyles } from "@/composables/attrsWithoutStyles";
import { useId } from "@/hooks/use-id";
import { CloseIcon } from "@bcc-code/icons-vue";
import BccFormLabel from "@/components/BccFormLabel/BccFormLabel.vue";
import BccFormMessage from "@/components/BccFormMessage/BccFormMessage.vue";

type Props = {
modelValue?: string;
Expand Down Expand Up @@ -53,8 +54,9 @@ function clear() {
<template>
<div class="bcc-input-container" :class="$attrs['class']" :style="$attrs['style'] as StyleValue">
<BccFormLabel
:for="id"
v-if="label || showOptionalLabel"
:for="id"
:size="size === 'lg' ? 'lg' : undefined"
:showOptionalLabel="showOptionalLabel"
:optionalLabel="optionalLabel"
>
Expand Down Expand Up @@ -103,16 +105,8 @@ function clear() {
/>
</div>
</div>
<span
v-if="$slots.default"
class="bcc-input-message"
:class="{
'bcc-input-message-default': state === 'default',
'bcc-input-message-error': state === 'error',
'bcc-input-message-success': state === 'success',
}"
>
<BccFormMessage v-if="$slots.default" :state="state">
<slot />
</span>
</BccFormMessage>
</div>
</template>
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ exports[`BccInput > renders a text from the default slot 1`] = `
<div class=\\"bcc-input-wrapper\\">
<!--v-if--><input id=\\"bcc-input-2\\" class=\\"bcc-input\\">
<!--v-if-->
</div><span class=\\"bcc-input-message bcc-input-message-default\\">Test message</span>
</div><span class=\\"bcc-form-message bcc-form-message-default\\">Test message</span>
</div>"
`;

Expand Down
6 changes: 3 additions & 3 deletions src/components/BccSelect/BccSelect.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,15 +128,15 @@ export const Size: StoryFn<typeof BccSelect> = () => ({
components: { BccSelect },
template: `
<div class="flex flex-col space-y-4">
<BccSelect size="sm" class="w-1/4" value="default">
<BccSelect label="label for sm select" size="sm" class="w-1/4" value="default">
<option value="default">sm select</option>
<option value="two">Option 2</option>
</BccSelect>
<BccSelect size="base" class="w-1/4" value="default">
<BccSelect label="label for base select" size="base" class="w-1/4" value="default">
<option value="default">base select</option>
<option value="two">Option 2</option>
</BccSelect>
<BccSelect size="lg" class="w-1/4" value="default">
<BccSelect label="label for lg select" size="lg" class="w-1/4" value="default">
<option value="default">lg select</option>
<option value="two">Option 2</option>
</BccSelect>
Expand Down
16 changes: 5 additions & 11 deletions src/components/BccSelect/BccSelect.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { computed, type StyleValue } from "vue";
import { useAttrsWithoutStyles } from "@/composables/attrsWithoutStyles";
import { useId } from "@/hooks/use-id";
import BccFormLabel from "@/components/BccFormLabel/BccFormLabel.vue";
import BccFormMessage from "@/components/BccFormMessage/BccFormMessage.vue";

type Props = {
modelValue?: string;
Expand Down Expand Up @@ -42,8 +43,9 @@ const { attrsWithoutStyles } = useAttrsWithoutStyles();
<template>
<div class="bcc-input-container" :class="$attrs['class']" :style="$attrs['style'] as StyleValue">
<BccFormLabel
:for="id"
v-if="label || showOptionalLabel"
:for="id"
:size="size === 'lg' ? 'lg' : undefined"
:showOptionalLabel="showOptionalLabel"
:optionalLabel="optionalLabel"
>
Expand All @@ -67,16 +69,8 @@ const { attrsWithoutStyles } = useAttrsWithoutStyles();
<slot />
</select>

<span
v-if="$slots.message"
class="bcc-input-message"
:class="{
'bcc-input-message-default': state === 'default',
'bcc-input-message-error': state === 'error',
'bcc-input-message-success': state === 'success',
}"
>
<BccFormMessage v-if="$slots.message" :state="state">
<slot name="message" />
</span>
</BccFormMessage>
</div>
</template>
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ exports[`BccSelect > renders a text from the default and message slots 1`] = `
"<div class=\\"bcc-input-container\\">
<!--v-if--><select class=\\"bcc-select\\" id=\\"bcc-input-2\\">
<option value=\\"brunstad\\">Brunstad</option>
</select><span class=\\"bcc-input-message bcc-input-message-default\\">Test message</span>
</select><span class=\\"bcc-form-message bcc-form-message-default\\">Test message</span>
</div>"
`;

Expand Down
1 change: 1 addition & 0 deletions src/css/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@
@import "../components/BccAlert/BccAlert.css";
@import "../components/BccSelect/BccSelect.css";
@import "../components/BccFormLabel/BccFormLabel.css";
@import "../components/BccFormMessage/BccFormMessage.css";
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ export { default as BccRadio } from "./components/BccRadio/BccRadio.vue";
export { default as BccAlert } from "./components/BccAlert/BccAlert.vue";
export { default as BccSelect } from "./components/BccSelect/BccSelect.vue";
export { default as BccFormLabel } from "./components/BccFormLabel/BccFormLabel.vue";
export { default as BccFormMessage } from "./components/BccFormMessage/BccFormMessage.vue";