Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BaseBadge Component #16

Closed
wants to merge 10 commits into from
Closed
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
41 changes: 41 additions & 0 deletions components/src/base-badge/base-badge.story.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<script setup lang="ts">
import { reactive } from 'vue';
import BaseBadge from './base-badge.vue';

const state = reactive({
size: 'medium',
label: 'Badge',
color: 'primary',
caps: false,
border: false,
});
</script>

<template>
<Story title="Base / Badge">
<template #controls>
<HstSelect
v-model="state.size"
title="Size"
:options="{
small: 'Small',
medium: 'Medium',
large: 'Large',
}"
/>
<HstSelect
v-model="state.color"
title="Color"
:options="{
primary: 'Primary',
gray: 'Gray',
}"
/>
<HstText v-model="state.label" title="Icon" />
<HstCheckbox v-model="state.caps" title="Caps" />
<HstCheckbox v-model="state.border" title="Border" />
</template>

<BaseBadge :size="state.size" :color="state.color" :label="state.label" :caps="state.caps" :border="state.border" />
</Story>
</template>
146 changes: 146 additions & 0 deletions components/src/base-badge/base-badge.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
<script setup lang="ts">
import { computed } from 'vue';

export interface BaseBadgeProps {
/**
* Size of the badge. Controls both font size and icon size.
* @values small, medium, large
*/
size?: 'small' | 'medium' | 'large';

/**
* Color of the badge.
* @values primary, white, danger
*/
color?: 'primary' | 'gray';

/**
* Whether the badge should be displayed in all caps.
*/
caps?: boolean;

/**
* Whether the badge should have a border.
*/
border?: boolean;

/**
* Label of the badge.
*/
label?: string;

/**
* URL to navigate to when the badge is clicked.
*/
href?: string;

/**
* Target of the link.
* @values _blank, _self, _parent, _top
*/
target?: '_blank' | '_self' | '_parent' | '_top';

/**
* Aria label for the badge if using as a link.
*/
ariaLabel?: string;
}

const props = withDefaults(defineProps<BaseBadgeProps>(), {
size: 'medium',
color: 'primary',
});

const as = computed(() => {
if (props.href) {
// router-link is not displaying correctly in Histoire
return 'a';
Comment on lines +56 to +57
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But this should be a router-link? In that case, lets fix the problem in Histoire rather than in the website codebase itself 👍🏻

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you give me some guidance on how you would you fix the problem in Histoire?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like the problem wasn't histoire in the first place! You were trying to set an href on a router-link, but router-link uses to instead of href for local pages 👍🏻 For this badge, be aware that you need to use <a> for links to pages outside of the website, and <router-link> for pages within

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh - it was me 😆
Too used to using NuxtLink instead of router-link.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's the source for it
https://github.com/nuxt/nuxt/blob/main/packages/nuxt/src/app/components/nuxt-link.ts
It has some niceties built-in like prefetching and handling external links.

Is there an easy way to just use it inside of a Nuxt project vs a Vue project (docs)?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there an easy way to just use it inside of a Nuxt project vs a Vue project (docs)?

No idea, though I have my doubts it'll just work outside of the Nuxt context (as it's so dependent on the router and some other magic). It does raise the question though: should we rework the docs to Nuxt as well?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean adding Nuxt to context of Histoire?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does raise the question though: should we rework the docs to Nuxt as well?

I think so. Eventually...

I like VitePress and it's super easy to get started with but there are lots of little specific quirks that I've struggled to sort out.
But Nuxt has it's own quirks too.

To me it makes sense that it's all unified though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean adding Nuxt to context of Histoire?

No not really. I was just meaning if there was an easy way to say in this components package ..

hey if this is a nuxt project use nuxt-link if not use router-link

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No not really. I was just meaning if there was an easy way to say in this components package ..

hey if this is a nuxt project use nuxt-link if not use router-link

For later: Something like this sounds like a good idea in order to be able to unify the components. For Nuxt we could maybe inject nuxt-link in the module setup file.

} else {
return 'span';
}
});

const badgeProps = computed(() => {
if (props.href) {
return {
href: props.href,
target: props.target,
...(props.ariaLabel && { 'aria-label': props.ariaLabel }),
};
} else {
return {};
}
});
</script>

<template>
<component
:is="as"
:class="[
'badge-base',
`badge-${props.color}`,
`badge-${props.size}`,
{
caps: props.caps,
border: props.border,
},
]"
v-bind="badgeProps"
>
<slot>{{ label }}</slot>
</component>
</template>

<style scoped>
/* Base */
.badge-base {
display: inline-flex;
align-items: center;
text-decoration: none;
border-top-right-radius: 9999px;
border-bottom-right-radius: 9999px;
border-top-left-radius: 9999px;
border-bottom-left-radius: 9999px;
font-weight: 600;
font-family: var(--family-display);
}

/* Colors */
.badge-primary {
background-color: var(--purple-50);
color: var(--purple-600);
border-color: var(--purple-300);
}

.badge-gray {
background-color: var(--gray-50);
color: var(--gray-600);
border-color: var(--gray-300);
}

/* Sizes */
.badge-small {
font-size: var(--text-xs);
padding: 2px 8px;
}

.badge-medium {
font-size: var(--text-sm);
padding: 4px 12px;
}

.badge-large {
font-size: var(--text-md);
padding: 6px 16px;
}

/* Props */
.border {
border-width: 1px;
border-style: solid;
}

.caps {
text-transform: uppercase;
}
</style>
3 changes: 2 additions & 1 deletion components/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { default as BaseIcon } from './base-icon/base-icon.vue';
export { default as BaseBadge } from './base-badge/base-badge.vue';
export { default as BaseDivider } from './base-button/base-divider.vue';
export { default as BaseIcon } from './base-icon/base-icon.vue';
11 changes: 11 additions & 0 deletions components/src/theme/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,17 @@
--primary: var(--purple-400);
--secondary: var(--pink-200);

--gray-50: #f9fafb;
--gray-100: #f4f5f7;
--gray-200: #e5e7eb;
--gray-300: #d2d6dc;
--gray-400: #9fa6b2;
--gray-500: #6b7280;
--gray-600: #4b5563;
--gray-700: #374151;
--gray-800: #252f3f;
--gray-900: #161e2e;

--purple-50: #ede5ff;
--purple-100: #d0c0fd;
--purple-200: #af95fd;
Expand Down