Updated indicators (#16190)

This commit is contained in:
ludwiczakpawel 2022-01-20 06:25:10 +01:00 committed by GitHub
parent 4f1a5b5a39
commit 43c188eafb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
28 changed files with 243 additions and 215 deletions

View file

@ -105,7 +105,7 @@ function buildTagsHTML(tag) {
var antifollow = '';
if (tag.points < 0) {
antifollow =
'<span class="crayons-indicator crayons-indicator--critical crayons-indicator--outlined" title="This tag has negative follow weight">Anti-follow</span>';
'<span class="c-indicator c-indicator--danger" title="This tag has negative follow weight">Anti-follow</span>';
}
return `<div class="crayons-card p-4 m:p-6 flex flex-col single-article" id="follows-${tag.id}" style="border: 1px solid ${tag.color}; box-shadow: 3px 3px 0 ${tag.color}">

View file

@ -24,7 +24,7 @@
height: var(--header-height);
}
.crayons-indicator {
.c-indicator {
position: absolute;
top: calc(var(--su-1) * -1);
right: 0;

View file

@ -1,60 +1,39 @@
@import '../config/import';
// indicator() - Generates styles for Indicators
//
// Indicators have bunch of styles combines with bunch of states. To make
// it easier to generate all these classes, we created a help which should
// do the job.
//
// @param {object} $this Cached variable with parent element
// @param {string} $name Value for border-radius
// @param {color} $color-1 Main color.
@mixin indicator($this, $name, $color-1, $color-2) {
&#{'--' + $name} {
background-color: $color-1;
border-color: $color-1;
color: $color-2;
&#{$this + '--outlined'} {
background-color: transparent;
color: $color-1;
border-color: $color-1;
}
}
}
// Basic styling
.crayons-indicator {
font-family: var(--ff-monospace);
font-size: var(--fs-xs);
.c-indicator {
--bg: var(--badge-bg);
--color: var(--badge-color);
padding: var(--su-1);
background-color: var(--indicator-default-bg);
border: 1px solid var(--indicator-default-bg);
color: var(--indicator-default-color);
text-align: center;
line-height: 1;
font-size: var(--fs-s);
border-radius: var(--radius);
display: inline-block;
background: var(--bg);
color: var(--color);
min-width: var(--su-2);
&--outlined {
background-color: transparent;
border-color: var(--indicator-default-bg);
color: var(--indicator-default-color);
&--success {
--bg: var(--badge-success-bg);
--color: var(--badge-success-color);
}
@include indicator(
&,
accent,
var(--indicator-accent-bg),
var(--indicator-accent-color)
);
@include indicator(
&,
critical,
var(--indicator-critical-bg),
var(--indicator-critical-color)
);
&--warning {
--bg: var(--badge-warning-bg);
--color: var(--badge-warning-color);
}
&--danger {
--bg: var(--badge-danger-bg);
--color: var(--badge-danger-color);
}
&--info {
--bg: var(--badge-info-bg);
--color: var(--badge-info-color);
}
&--relaxed {
padding: var(--su-2);
}
&:empty {
display: none;

View file

@ -88,7 +88,7 @@
font-size: var(--fs-xl);
}
.crayons-indicator {
.c-indicator {
margin-left: auto;
&:empty {

View file

@ -307,6 +307,30 @@ of particular colors in components and views.
--cta-branded-border: var(--accent-brand);
--cta-branded-border-hover: var(--accent-brand-darker);
/***********************************************
** Badges **************************************
***********************************************/
/* Badges: Default */
--badge-bg: var(--base-30);
--badge-color: var(--base-80);
/* Badges: Success */
--badge-success-bg: var(--accent-success);
--badge-success-color: rgb(0,0,0);
/* Badges: Warning */
--badge-warning-bg: var(--accent-warning);
--badge-warning-color: rgb(0,0,0);
/* Badges: Danger */
--badge-danger-bg: var(--accent-danger);
--badge-danger-color: rgb(255,255,255);
/* Badges: Info */
--badge-info-bg: var(--accent-brand);
--badge-info-color: rgb(255,255,255);
/***********************************************
** Utilities ***********************************
***********************************************/

View file

@ -34,7 +34,7 @@
justify-content: space-between;
font-weight: var(--fw-medium);
.crayons-indicator {
.c-indicator {
margin-left: 5px;
}
button {

View file

@ -256,6 +256,18 @@
--cta-branded-border: var(--accent-brand);
--cta-branded-border-hover: var(--accent-brand-lighter);
/***********************************************
** Badges **************************************
***********************************************/
/* Badges: Danger */
--badge-danger-bg: var(--accent-danger-darker);
--badge-danger-color: rgb(255,255,255);
/* Badges: Info */
--badge-info-bg: var(--accent-brand-darker);
--badge-info-color: rgb(255,255,255);
/***********************************************
** Utilities ***********************************
***********************************************/

View file

@ -272,7 +272,7 @@ module ApplicationHelper
if method.to_sym.in?(Settings::Mandatory.keys)
required = tag.span(I18n.t("helpers.application_helper.required"),
class: "crayons-indicator crayons-indicator--critical")
class: "c-indicator c-indicator--danger")
content = safe_join([content, required])
end

View file

@ -1,106 +0,0 @@
import { h } from 'preact';
import notes from './indicators.mdx';
export default {
title: 'Components/Indicators',
parameters: {
docs: {
page: notes,
},
},
};
export const Default = () => <span className="crayons-indicator">Label</span>;
Default.story = { name: 'default (grey)' };
export const GreyOutlined = () => (
<span className="crayons-indicator crayons-indicator--outlined">
Outlined
</span>
);
GreyOutlined.story = {
name: 'grey outlined',
};
export const GreyWithNumber = () => (
<span className="crayons-indicator">1</span>
);
GreyWithNumber.story = {
name: 'grey with number',
};
export const Accent = () => (
<span className="crayons-indicator crayons-indicator--accent">Label</span>
);
Accent.story = {
name: 'accent',
};
export const AccentOutlined = () => (
<span className="crayons-indicator crayons-indicator--outlined crayons-indicator--accent">
Outlined
</span>
);
AccentOutlined.story = { name: 'accent outlined' };
export const AccentWithNumber = () => (
<span className="crayons-indicator crayons-indicator--accent">1</span>
);
AccentWithNumber.story = {
name: 'accent with number',
};
export const Critical = () => (
<span className="crayons-indicator crayons-indicator--critical">Label</span>
);
Critical.story = {
name: 'critical',
};
export const CriticalOutline = () => (
<span className="crayons-indicator crayons-indicator--outlined crayons-indicator--critical">
Outlined
</span>
);
CriticalOutline.story = {
name: 'critical outline',
};
export const CriticalWithNumber = () => (
<span className="crayons-indicator crayons-indicator--critical">1</span>
);
CriticalWithNumber.story = {
name: 'critical with number',
};
export const Inverted = () => (
<span className="crayons-indicator crayons-indicator--inverted">Label</span>
);
Inverted.story = { name: 'inverted' };
export const InvertedOutlined = () => (
<span className="crayons-indicator crayons-indicator--outlined crayons-indicator--inverted">
Outlined
</span>
);
InvertedOutlined.story = {
name: 'inverted outlined',
};
export const InvertedWithNumber = () => (
<span className="crayons-indicator crayons-indicator--inverted">1</span>
);
InvertedWithNumber.story = {
name: 'inverted with number',
};

View file

@ -1,23 +0,0 @@
## Indicators
Indicators are meant to be used to inform user about, for example, unread
notifications. They supposed to steal user&apos;s attention and make him notice
or click specific element.
We should keep in mind to never show too many indicators at the same time. Use
your best judgment. There are two types of indicators:
- Rectangle with label (text or number)
- Bullet - just a circle without any text on it.
And there arere four styles to pick from:
- Default (grey) - nothing really crucial, basic information about something.
- Accent (blueish) - something we want user to be aware of but it&apos;s also
not crucial information
- Critical (red) - something super important, don&apos;t overuse it!!
- Inverted (dark grey) - alternative to the default one, especially when we need
to show two default indicators next to each other.

View file

@ -0,0 +1,31 @@
import { h } from 'preact';
import PropTypes from 'prop-types';
import classNames from 'classnames/bind';
export const Indicator = ({
children,
variant = 'default',
extraPadding,
className,
...otherProps
}) => {
const classes = classNames('c-indicator', {
[`c-indicator--${variant}`]: variant && variant !== 'default',
'p-2': extraPadding,
[className]: className,
});
return (
<span className={classes} {...otherProps}>
{children}
</span>
);
};
Indicator.displayName = 'Indicator';
Indicator.propTypes = {
variant: PropTypes.oneOf(['default', 'info', 'success', 'warning', 'danger']),
className: PropTypes.string,
extraPadding: PropTypes.bool,
};

View file

@ -0,0 +1,39 @@
# Indicators
Indicators are meant to be used to inform user about, for example, unread
notifications. They supposed to steal user&apos;s attention and make them notice
or click specific element.
We should keep in mind to never show too many indicators at the same time. Use
your best judgment here.
## Variants
There's a bunch of variants (styles) to pick from:
- Default - grey.
- Info - blue-ish.
- Success - green.
- Warninig - yellow.
- Danger - red.
Even though they are named specifically, they don't really come with any function in mind - main difference is basically a color.
## Padding
By default, Indicator has very tight padding around label - `4px`. It's ok for short labels - like a number.
But for longer labels it may look better with some extra spacing. And there comes `extraPadding` prop which will increase the padding to `8px`.
Keep in mind, Indicators can inherit any classes like every other element which means you can (if you have to) increase that padding manually
with, for example, `p-*` utility classes.
## Design
<mark>
Comparing designs with what's in the Storybook you may notice differences in colors.
This is due to the fact that Figma already reflects new colors palette which is not yet reflected in the codebase
(it's currently being reviewed in a separate PR).
</mark>
<br /><br />
<iframe style="border: 1px solid rgba(0, 0, 0, 0.1);" width="100%" height="450" src="https://www.figma.com/embed?embed_host=share&url=https%3A%2F%2Fwww.figma.com%2Ffile%2FgHpwugeu9jFGW4d9u3ReuR%2FCrayons%3Fnode-id%3D391%253A234" allowfullscreen></iframe>

View file

@ -0,0 +1,75 @@
import { h } from 'preact';
import { Indicator } from '../';
import IndicatorsDoc from './Indicators.mdx';
export default {
component: Indicator,
title: 'Components/Indicators',
parameters: {
docs: {
page: IndicatorsDoc,
},
},
argTypes: {
variant: {
control: {
type: 'select',
options: {
default: undefined,
info: 'info',
success: 'success',
warning: 'warning',
danger: 'danger',
},
},
description:
'There are bunch of available variants (styles) to pick from. The primary difference is color but each color should be used for different purpose. Read Docs for more info.',
table: {
defaultValue: { summary: 'default' },
},
},
extraPadding: {
description:
'Indicators are "tight" by default which means they have very little padding. This will gently increase the padding so it looks more loose.',
table: {
defaultValue: { summary: false },
},
},
},
};
export const Default = (args) => <Indicator {...args} />;
Default.args = {
children: 'Hello world',
};
export const VariantInfo = (args) => <Indicator {...args} />;
VariantInfo.args = {
...Default.args,
variant: 'info',
};
export const VariantSuccess = (args) => <Indicator {...args} />;
VariantSuccess.args = {
...Default.args,
variant: 'success',
};
export const VariantWarning = (args) => <Indicator {...args} />;
VariantWarning.args = {
...Default.args,
variant: 'warning',
};
export const VariantDanger = (args) => <Indicator {...args} />;
VariantDanger.args = {
...Default.args,
variant: 'danger',
};
export const ExtraPadding = (args) => <Indicator {...args} />;
ExtraPadding.args = {
...Default.args,
extraPadding: true,
children: 'Hello world',
};

View file

@ -0,0 +1 @@
export * from './Indicator';

View file

@ -12,11 +12,7 @@ export class SingleRepo extends Component {
forkLabel = () => {
const { fork } = this.props;
if (fork) {
return (
<span className="crayons-indicator crayons-indicator--accent">
fork
</span>
);
return <span className="c-indicator c-indicator--warning">fork</span>;
}
return null;
};

View file

@ -15,7 +15,7 @@
<div class="crayons-icon crayons-icon--default">
<%= link[:icon].html_safe %>
</div>
<%= link[:name] %><span id="reading-list-count" class="crayons-indicator"></span>
<%= link[:name] %><span id="reading-list-count" class="c-indicator"></span>
</a>
</div>
@ -45,7 +45,7 @@
<div class="crayons-icon crayons-icon--default">
<%= link[:icon].html_safe %>
</div>
<%= link[:name] %><span id="reading-list-count" class="crayons-indicator"></span>
<%= link[:name] %><span id="reading-list-count" class="c-indicator"></span>
</a>
</div>

View file

@ -40,7 +40,7 @@
<%= link_to admin_users_gdpr_delete_requests_path, class: "nav-link #{'active' if params[:controller] == 'admin/users/gdpr_delete_requests'}" do %>
GDPR Delete Requests
<% if Users::GdprDeleteRequest.any? %>
&nbsp;<span class="crayons-indicator crayons-indicator--critical"><%= Users::GdprDeleteRequest.count %></span>
&nbsp;<span class="c-indicator c-indicator--danger"><%= Users::GdprDeleteRequest.count %></span>
<% end %>
<% end %>
</li>

View file

@ -5,7 +5,7 @@
<% if plucked_article[2] > 0 %>
<%= t("views.comments.count", count: plucked_article[2]) %>
<% else %>
<span class="crayons-indicator crayons-indicator--accent"><%= t("views.comments.empty") %></span>
<span class="c-indicator c-indicator--warning"><%= t("views.comments.empty") %></span>
<% end %>
</div>
<% end %>

View file

@ -5,7 +5,7 @@
href="<%= dashboard_path %>"
<%= params[:action] == "show" && (params[:which] == "organization" || params[:which].blank?) ? ' aria-current="page"'.html_safe : "" %>>
<%= t("views.dashboard.actions.posts") %>
<span class="crayons-indicator"><%= @user.articles_count %></span>
<span class="c-indicator"><%= @user.articles_count %></span>
</a>
</li>
@ -14,7 +14,7 @@
href="<%= user_series_path(current_user.username) %>"
<%= params[:action] == "series" && (params[:which] == "organization" || params[:which].blank?) ? ' aria-current="page"'.html_safe : "" %>>
<%= t("views.dashboard.actions.series") %>
<span class="crayons-indicator"><%= @collections_count %></span>
<span class="c-indicator"><%= @collections_count %></span>
</a>
</li>
@ -23,7 +23,7 @@
href="/dashboard/user_followers"
<%= params[:action] == "followers" ? ' aria-current="page"'.html_safe : "" %>>
<%= t("views.dashboard.actions.followers") %>
<span class="crayons-indicator"><%= @user.followers_count %></span>
<span class="c-indicator"><%= @user.followers_count %></span>
</a>
</li>
@ -32,7 +32,7 @@
href="<%= dashboard_following_tags_path %>"
<%= params[:action] == "following_tags" ? ' aria-current="page"'.html_safe : "" %>>
<%= t("views.dashboard.actions.following_tags") %>
<span class="crayons-indicator"><%= @user.following_tags_count %></span>
<span class="c-indicator"><%= @user.following_tags_count %></span>
</a>
</li>
@ -41,7 +41,7 @@
href="<%= dashboard_following_users_path %>"
<%= params[:action] == "following_users" ? ' aria-current="page"'.html_safe : "" %>>
<%= t("views.dashboard.actions.following_users") %>
<span class="crayons-indicator"><%= @user.following_users_count %></span>
<span class="c-indicator"><%= @user.following_users_count %></span>
</a>
</li>
@ -50,7 +50,7 @@
href="<%= dashboard_following_organizations_path %>"
<%= params[:action] == "following_organizations" ? ' aria-current="page"'.html_safe : "" %>>
<%= t("views.dashboard.actions.following_orgs") %>
<span class="crayons-indicator"><%= @user.following_organizations_count %></span>
<span class="c-indicator"><%= @user.following_organizations_count %></span>
</a>
</li>
@ -59,7 +59,7 @@
href="<%= dashboard_following_podcasts_path %>"
<%= params[:action] == "following_podcasts" ? ' aria-current="page"'.html_safe : "" %>>
<%= t("views.dashboard.actions.following_pods") %>
<span class="crayons-indicator"><%= @user.following_podcasts_count %></span>
<span class="c-indicator"><%= @user.following_podcasts_count %></span>
</a>
</li>

View file

@ -2,7 +2,7 @@
<div class="dashboard-story__title">
<h3 class="flex items-center">
<% if article.archived %>
<span class="crayons-indicator crayons-indicator--critical mr-2 fw-normal whitespace-nowrap"><%= t("views.dashboard.article.archived") %></span>
<span class="c-indicator c-indicator--danger mr-2 fw-normal whitespace-nowrap"><%= t("views.dashboard.article.archived") %></span>
<% end %>
<a href="<%= article.current_state_path %>" class="inline-flex items-center">
<% if article.organization_id %>
@ -30,7 +30,7 @@
<div class="fs-s color-base-60">
<% if !article.published? %>
<a href="<%= article.path %>/edit" class="crayons-indicator crayons-indicator--accent"><%= t("views.dashboard.article.draft") %></a>
<a href="<%= article.path %>/edit" class="c-indicator c-indicator--warning"><%= t("views.dashboard.article.draft") %></a>
<% else %>
<div class="flex flex-nowrap whitespace-nowrap" data-analytics-pageviews data-article-id="<%= article.id %>">
<span class="flex items-center p-1" title="<%= t("views.dashboard.article.reactions.title") %>">

View file

@ -17,18 +17,18 @@
<div class="crayons-notice crayons-notice--info p-4 mx-3 s:mx-0 mb-3" aria-live="polite">
<%= t("views.dashboard.following_tags.adjust") %>
<span class="crayons-indicator crayons-indicator--outlined crayons-indicator--accent ml-3"><%= t("views.dashboard.following_tags.default") %></span>
<span class="c-indicator c-indicator--warning ml-3"><%= t("views.dashboard.following_tags.default") %></span>
</div>
<div id="following-wrapper" class="grid gap-3 m:gap-4 s:grid-cols-2 l:grid-cols-3 px-3 m:px-0">
<% negative_follow_shown_once = false %>
<% @followed_tags.each do |follow| %>
<% tag = follow.followable %>
<% if tag %>
<div class="crayons-card branded-2 p-4 m:p-6 m:pt-4 flex flex-col single-article break-word content-center <% if follow.explicit_points < 0 %>opacity-75<% end %>" style="border-top-color: <%= tag.bg_color_hex %>;" id="follows-<%= follow.id %>">
<div class="crayons-card branded-2 p-4 m:p-6 m:pt-4 flex flex-col single-article break-word content-center" style="border-top-color: <%= tag.bg_color_hex %>;" id="follows-<%= follow.id %>">
<h3 class="s:mb-1 -ml-1 p-0 fw-medium">
<%= render_tag_link(tag.name) %>
<% if follow.explicit_points < 0 %>
<span class="crayons-indicator crayons-indicator--critical crayons-indicator--outlined" title="<%= t("views.dashboard.following_tags.anti.title") %>"><%= t("views.dashboard.following_tags.anti.text") %></span>
<span class="c-indicator c-indicator--danger" title="<%= t("views.dashboard.following_tags.anti.title") %>"><%= t("views.dashboard.following_tags.anti.text") %></span>
<% end %>
</h3>
@ -39,7 +39,7 @@
<%= fields(follow) do |f| %>
<%= f.hidden_field(:id, name: "follows[][id]", form: "follows_update_form", id: "follow_id_#{follow.followable}") %>
<%= f.number_field(:explicit_points, step: :any, required: true, class: "crayons-textfield flex-1 fs-s", name: "follows[][explicit_points]", form: "follows_update_form", "aria-label": t("views.dashboard.following_tags.number.aria_label", name: follow.followable),
id: "explicit_points_#{follow.followable}") %>
id: "explicit_points_#{follow.followable}") %>
<% end %>
</div>
<% end %>

View file

@ -6,7 +6,7 @@
</span>
<%= t("views.main.nav_name.#{link.name}", default: link.name) %>
<% if link.url.include?("readinglist") %>
<span id="reading-list-count" class="crayons-indicator ml-2 self-center"></span>
<span id="reading-list-count" class="c-indicator ml-2 self-center"></span>
<% end %>
</a>
</li>

View file

@ -40,7 +40,7 @@
<a href="<%= notifications_path %>" id="notifications-link" class="c-link c-link--icon-alone c-link--block mx-1" aria-label="<%= t("views.main.header.notifications.aria_label") %>">
<%= crayons_icon_tag(:bell, title: t("views.main.header.notifications.icon")) %>
<span class="crayons-indicator crayons-indicator--critical hidden" id="notifications-number"></span>
<span class="c-indicator c-indicator--danger hidden" id="notifications-number"></span>
</a>
<div class="crayons-header__menu mx-1" id="crayons-header__menu">

View file

@ -19,7 +19,7 @@
<% @current_user_tags.each do |tag| %>
<a href="<%= "#{URL.url}/mod/#{tag}" %>" class="crayons-link crayons-link--block <%= "crayons-link--current" if tag == @tag&.name %>" data-tag-name="<%= tag %>">
#<%= tag %>
<span id="<%= tag %>-indicator" class="crayons-indicator"></span>
<span id="<%= tag %>-indicator" class="c-indicator"></span>
</a>
<% end %>
<% end %>
@ -42,7 +42,7 @@
<li>
<a data-text="#<%= tag %>" href="<%= "#{mod_path}/#{tag}" %>" class="crayons-tabs__item <%= "crayons-tabs__item--current" if tag == @tag&.name %>" data-tag-name="<%= tag %>" aria-current="<%= "page" if tag == @tag&.name %>">
#<%= tag %>
<span id="<%= tag %>-indicator" class="crayons-indicator"></span>
<span id="<%= tag %>-indicator" class="c-indicator"></span>
</a>
</li>
<% end %>

View file

@ -6,7 +6,7 @@
<header>
<h2 class="crayons-subtitle-1 flex items-center">
<%= t("views.settings.extensions.web") %>
<span class="ml-2 crayons-indicator crayons-indicator--accent"><%= t("core.beta") %></span>
<span class="ml-2 c-indicator c-indicator--warning"><%= t("core.beta") %></span>
</h2>
<p class="color-base-70">
<%= t("views.settings.extensions.micro") %><a href="https://dev.to/hacksultan/web-monetization-like-i-m-5-1418"><%= t("views.settings.extensions.learn") %></a>

View file

@ -15,7 +15,7 @@
<% end %>
<p class="fs-s color-base-60 flex items-center">
<% if repo.fork %>
<span class="crayons-indicator mr-3"><%= t("views.users.github.fork") %></span>
<span class="c-indicator mr-3"><%= t("views.users.github.fork") %></span>
<% end %>
<% if repo.language %>

View file

@ -10,11 +10,11 @@
<p class="fw-medium flex-1">
<a href="<%= org_membership.user.path %>"><%= org_membership.user.name %></a>
<% if org_membership.user == @user %>
<span class="crayons-indicator"><%= t("views.settings.org.admin.you") %></span>
<span class="c-indicator"><%= t("views.settings.org.admin.you") %></span>
<% end %>
<% if org_membership.type_of_user == "admin" %>
<span class="crayons-indicator crayons-indicator--critical"><%= t("views.settings.org.admin.admin") %></span>
<span class="c-indicator c-indicator--danger"><%= t("views.settings.org.admin.admin") %></span>
<% end %>
</p>

View file

@ -22,7 +22,7 @@ RSpec.describe "/admin/users/gdpr_delete_requests", type: :request do
it "displays the number of existing requests" do
get admin_users_gdpr_delete_requests_path
expect(response.body).to include("<span class=\"crayons-indicator crayons-indicator--critical\">1</span>")
expect(response.body).to include("<span class=\"c-indicator c-indicator--danger\">1</span>")
end
it "destroys the gdpr delete request on confirmation" do
@ -41,7 +41,7 @@ RSpec.describe "/admin/users/gdpr_delete_requests", type: :request do
context "without gdpr request" do
it "doesn't display the number of existing requests" do
get admin_users_gdpr_delete_requests_path
expect(response.body).not_to include("<span class=\"crayons-indicator crayons-indicator--critical\">0</span>")
expect(response.body).not_to include("<span class=\"c-indicator c-indicator--danger\">0</span>")
end
end
end