Skip to content

Add type, icon and use_container_width properties to buttons #286

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

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
116 changes: 87 additions & 29 deletions streamlit_authenticator/views/authentication_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,10 @@ def forgot_username(self, location: Literal['main', 'sidebar'] = 'main',
fields: Optional[Dict[str, str]] = None, captcha: bool = False,
send_email: bool = False, two_factor_auth: bool = False,
clear_on_submit: bool = False, key: str = 'Forgot username',
callback: Optional[Callable]=None) -> Tuple[Optional[str], Optional[str]]:
type: Literal['primary', 'secondary', 'tertiary'] = 'secondary',
icon: Optional[str] = None, use_container_width: bool = False,
callback: Optional[Callable] = None
) -> Tuple[Optional[str], Optional[str]]:
"""
Renders a forgot username widget.

Expand All @@ -181,6 +184,12 @@ def forgot_username(self, location: Literal['main', 'sidebar'] = 'main',
If True, clears input fields after form submission.
key : str, default='Forgot username'
Unique key for the widget to prevent duplicate WidgetID errors.
type : {'primary', 'secondary', 'terciary'}, default='secondary'
Specifies the button type.
icon : str, optional
Optional emoji or icon to display next to the button label.
use_container_width : bool, default=False
Whether to expand the button's width to fill its parent container.
callback : Callable, optional
Function to be executed after form submission.

Expand Down Expand Up @@ -212,7 +221,8 @@ def forgot_username(self, location: Literal['main', 'sidebar'] = 'main',
forgot_username_form.image(Helpers.generate_captcha('forgot_username_captcha',
self.secret_key))
if forgot_username_form.form_submit_button('Submit' if 'Submit' not in fields
else fields['Submit']):
else fields['Submit'], type=type, icon=icon,
use_container_width=use_container_width):
result = self.authentication_controller.forgot_username(email, callback,
captcha, entered_captcha)
if not two_factor_auth:
Expand All @@ -228,14 +238,15 @@ def forgot_username(self, location: Literal['main', 'sidebar'] = 'main',
del st.session_state['2FA_check_forgot_username']
return result
return None, email
def experimental_guest_login(self, button_name: str='Guest login',
def experimental_guest_login(self, button_name: str = 'Guest login',
location: Literal['main', 'sidebar'] = 'main',
provider: Literal['google', 'microsoft'] = 'google',
oauth2: Optional[Dict[str, Any]] = None,
max_concurrent_users: Optional[int]=None,
single_session: bool=False, roles: Optional[List[str]]=None,
use_container_width: bool=False,
callback: Optional[Callable]=None) -> None:
max_concurrent_users: Optional[int] = None,
single_session: bool = False, roles: Optional[List[str]] = None,
use_container_width: bool = False,
callback: Optional[Callable] = None
) -> None:
"""
Renders a guest login button.

Expand Down Expand Up @@ -272,14 +283,14 @@ def experimental_guest_login(self, button_name: str='Guest login',
if not st.session_state.get('authentication_status'):
auth_endpoint = \
self.authentication_controller.guest_login(cookie_controller=\
self.cookie_controller,
provider=provider,
oauth2=oauth2,
max_concurrent_users=\
max_concurrent_users,
single_session=single_session,
roles=roles,
callback=callback)
self.cookie_controller,
provider=provider,
oauth2=oauth2,
max_concurrent_users=\
max_concurrent_users,
single_session=single_session,
roles=roles,
callback=callback)
if location == 'main' and auth_endpoint:
st.link_button(button_name, url=auth_endpoint,
use_container_width=use_container_width)
Expand All @@ -289,7 +300,9 @@ def experimental_guest_login(self, button_name: str='Guest login',
def login(self, location: Literal['main', 'sidebar', 'unrendered'] = 'main',
max_concurrent_users: Optional[int] = None, max_login_attempts: Optional[int] = None,
fields: Optional[Dict[str, str]] = None, captcha: bool = False,
single_session: bool=False, clear_on_submit: bool = False, key: str = 'Login',
single_session: bool = False, clear_on_submit: bool = False, key: str = 'Login',
type: Literal['primary', 'secondary', 'tertiary'] = 'secondary',
icon: Optional[str] = None, use_container_width: bool = False,
callback: Optional[Callable] = None
) -> Optional[Tuple[Optional[str], Optional[bool], Optional[str]]]:
"""
Expand All @@ -313,6 +326,12 @@ def login(self, location: Literal['main', 'sidebar', 'unrendered'] = 'main',
If True, clears input fields after form submission.
key : str, default='Login'
Unique key for the widget to prevent duplicate WidgetID errors.
type : {'primary', 'secondary', 'terciary'}, default='secondary'
Specifies the button type.
icon : str, optional
Optional emoji or icon to display next to the button label.
use_container_width : bool, default=False
Whether to expand the button's width to fill its parent container.
callback : Callable, optional
Function to execute when the form is submitted.

Expand Down Expand Up @@ -359,7 +378,8 @@ def login(self, location: Literal['main', 'sidebar', 'unrendered'] = 'main',
autocomplete='off')
login_form.image(Helpers.generate_captcha('login_captcha', self.secret_key))
if login_form.form_submit_button('Login' if 'Login' not in fields
else fields['Login']):
else fields['Login'], type=type, icon=icon,
use_container_width=use_container_width):
if self.authentication_controller.login(username, password,
max_concurrent_users,
max_login_attempts,
Expand All @@ -371,8 +391,10 @@ def login(self, location: Literal['main', 'sidebar', 'unrendered'] = 'main',
st.rerun()
def logout(self, button_name: str = 'Logout',
location: Literal['main', 'sidebar', 'unrendered'] = 'main',
key: str = 'Logout', use_container_width: bool = False,
callback: Optional[Callable] = None) -> None:
key: str = 'Logout', type: Literal['primary', 'secondary', 'tertiary'] = 'secondary',
icon: Optional[str] = None, use_container_width: bool = False,
callback: Optional[Callable] = None
) -> None:
"""
Renders a logout button.

Expand All @@ -384,6 +406,10 @@ def logout(self, button_name: str = 'Logout',
Location where the logout button is rendered.
key : str, default='Logout'
Unique key for the widget, useful in multi-page applications.
type : {'primary', 'secondary', 'terciary'}, default='secondary'
Specifies the button type.
icon : str, optional
Optional emoji or icon to display next to the button label.
use_container_width : bool, default=False
If True, the button width matches the container.
callback : Callable, optional
Expand All @@ -394,11 +420,13 @@ def logout(self, button_name: str = 'Logout',
if location not in ['main', 'sidebar', 'unrendered']:
raise ValueError("Location must be one of 'main' or 'sidebar' or 'unrendered'")
if location == 'main':
if st.button(button_name, key=key, use_container_width=use_container_width):
if st.button(button_name, key=key, type=type, icon=icon,
use_container_width=use_container_width):
self.authentication_controller.logout(callback)
self.cookie_controller.delete_cookie()
elif location == 'sidebar':
if st.sidebar.button(button_name, key=key, use_container_width=use_container_width):
if st.sidebar.button(button_name, key=key, type=type, icon=icon,
use_container_width=use_container_width):
self.authentication_controller.logout(callback)
self.cookie_controller.delete_cookie()
elif location == 'unrendered':
Expand All @@ -411,7 +439,10 @@ def register_user(self, location: Literal['main', 'sidebar'] = 'main',
captcha: bool = True, roles: Optional[List[str]] = None,
merge_username_email: bool = False, password_hint: bool = True,
two_factor_auth: bool = False, clear_on_submit: bool = False,
key: str = 'Register user', callback: Optional[Callable] = None
key: str = 'Register user',
type: Literal['primary', 'secondary', 'tertiary'] = 'secondary',
icon: Optional[str] = None, use_container_width: bool = False,
callback: Optional[Callable] = None
) -> Tuple[Optional[str], Optional[str], Optional[str]]:
"""
Renders a register new user widget.
Expand Down Expand Up @@ -440,6 +471,12 @@ def register_user(self, location: Literal['main', 'sidebar'] = 'main',
If True, clears input fields after form submission.
key : str, default='Register user'
Unique key for the widget to prevent duplicate WidgetID errors.
type : {'primary', 'secondary', 'terciary'}, default='secondary'
Specifies the button type.
icon : str, optional
Optional emoji or icon to display next to the button label.
use_container_width : bool, default=False
Whether to expand the button's width to fill its parent container.
callback : Callable, optional
Function to execute when the form is submitted.

Expand Down Expand Up @@ -504,7 +541,8 @@ def register_user(self, location: Literal['main', 'sidebar'] = 'main',
register_user_form.image(Helpers.generate_captcha('register_user_captcha',
self.secret_key))
if register_user_form.form_submit_button('Register' if 'Register' not in fields
else fields['Register']):
else fields['Register'], type=type, icon=icon,
use_container_width=use_container_width):
if two_factor_auth:
self.__two_factor_auth(new_email, widget='register', fields=fields)
else:
Expand All @@ -526,7 +564,10 @@ def register_user(self, location: Literal['main', 'sidebar'] = 'main',
return None, None, None
def reset_password(self, username: str, location: Literal['main', 'sidebar'] = 'main',
fields: Optional[Dict[str, str]] = None, clear_on_submit: bool = False,
key: str = 'Reset password', callback: Optional[Callable] = None
key: str = 'Reset password',
type: Literal['primary', 'secondary', 'tertiary'] = 'secondary',
icon: Optional[str] = None, use_container_width: bool = False,
callback: Optional[Callable] = None
) -> Optional[bool]:
"""
Renders a password reset widget.
Expand All @@ -543,6 +584,12 @@ def reset_password(self, username: str, location: Literal['main', 'sidebar'] = '
If True, clears input fields after form submission.
key : str, default='Reset password'
Unique key for the widget to prevent duplicate WidgetID errors.
type : {'primary', 'secondary', 'terciary'}, default='secondary'
Specifies the button type.
icon : str, optional
Optional emoji or icon to display next to the button label.
use_container_width : bool, default=False
Whether to expand the button's width to fill its parent container.
callback : Callable, optional
Function to execute when the form is submitted.

Expand Down Expand Up @@ -584,9 +631,10 @@ def reset_password(self, username: str, location: Literal['main', 'sidebar'] = '
type='password',
autocomplete='off').strip()
if reset_password_form.form_submit_button('Reset' if 'Reset' not in fields
else fields['Reset']):
else fields['Reset'], icon=icon, type=type,
use_container_width=use_container_width):
if self.authentication_controller.reset_password(username, password, new_password,
new_password_repeat, callback):
new_password_repeat, callback):
return True
return None
def __two_factor_auth(self, email: str, content: Optional[Dict[str, Any]] = None,
Expand Down Expand Up @@ -622,7 +670,10 @@ def two_factor_auth_form():
def update_user_details(self, username: str, location: Literal['main', 'sidebar'] = 'main',
fields: Optional[Dict[str, str]] = None,
clear_on_submit: bool = False, key: str = 'Update user details',
callback: Optional[Callable] = None) -> bool:
type: Literal['primary', 'secondary', 'tertiary'] = 'secondary',
icon: Optional[str] = None, use_container_width: bool = False,
callback: Optional[Callable] = None
) -> bool:
"""
Renders an update user details widget.

Expand All @@ -638,6 +689,12 @@ def update_user_details(self, username: str, location: Literal['main', 'sidebar'
If True, clears input fields after form submission.
key : str, default='Update user details'
Unique key for the widget to prevent duplicate WidgetID errors.
type : {'primary', 'secondary', 'terciary'}, default='secondary'
Specifies the button type.
icon : str, optional
Optional emoji or icon to display next to the button label.
use_container_width : bool, default=False
Whether to expand the button's width to fill its parent container.
callback : Callable, optional
Function to execute when the form is submitted.

Expand All @@ -664,7 +721,7 @@ def update_user_details(self, username: str, location: Literal['main', 'sidebar'
update_user_details_form_fields = ['First name' if 'First name' not in fields else \
fields['First name'],
'Last name' if 'Last name' not in fields else \
fields['Last name'],
fields['Last name'],
'Email' if 'Email' not in fields else fields['Email']]
field = update_user_details_form.selectbox('Field' if 'Field' not in fields
else fields['Field'],
Expand All @@ -679,7 +736,8 @@ def update_user_details(self, username: str, location: Literal['main', 'sidebar'
elif update_user_details_form_fields.index(field) == 2:
field = 'email'
if update_user_details_form.form_submit_button('Update' if 'Update' not in fields
else fields['Update']):
else fields['Update'], icon=icon, type=type,
use_container_width=use_container_width):
if self.authentication_controller.update_user_details(username, field, new_value,
callback):
# self.cookie_controller.set_cookie()
Expand Down